Shader "World Political Map/Unlit Earth Scenic Scatter City Lights" { Properties { _MainTex ("Base (RGB)", 2D) = "white" {} [Normal] _NormalMap ("Normal Map", 2D) = "bump" {} _BumpAmount ("Bump Amount", Range(0, 1)) = 0.5 _SpecularPower("Specular Power", Float) = 32.0 _SpecularIntensity("Specular Intensity", Float) = 2.0 _CloudMap ("Cloud Map", 2D) = "black" {} _CloudSpeed ("Cloud Speed", Range(-1, 1)) = -0.04 _CloudAlpha ("Cloud Alpha", Range(0, 1)) = 1 _CloudShadowStrength ("Cloud Shadow Strength", Range(0, 1)) = 0.2 _CloudElevation ("Cloud Elevation", Range(0.001, 0.1)) = 0.003 _CityLights ("City Lights (RGB)", 2D) = "black" {} _CityLightsBrightness("City Lights Brightness", Float) = 1 _Brightness("Brightness", Range(1,3)) = 1.25 _Contrast("Contrast", Range(0,2)) = 1.1 _AmbientLight("Ambient Light", Range(0,1)) = 0.1 _SunLightDirection("Sun Light Direction", Vector) = (0,0,1) _SpecularPower("Specular Power", Float) = 1 _SpecularIntensity("Specular Intensity", Float) = 0 _AtmosphereAlpha("Atmosphere Alpha", Float) = 1.0 [HideInInspector] _fOuterRadius ("Outer Radius", Float) = 1.25 [HideInInspector] fOuterRadius2 ("Outer Radius Squared", Float) = 1.5625 [HideInInspector] fInnerRadius ("Inner Radius", Float) = 1 [HideInInspector] fInnerRadius2 ("Inner Radius Squared", Float) = 1 [HideInInspector] fKrESun ("", Float) = 1.0 [HideInInspector] fKmESun ("", Float) = 1.0 [HideInInspector] fKr4PI ("", Float) = 1.0 [HideInInspector] fKm4PI ("", Float) = 1.0 [HideInInspector] fScale ("", Float) = 1.0 [HideInInspector] fScaleDepth ("", Float) = 1.0 [HideInInspector] fScaleOverScaleDepth ("", Float) = 1.0 [HideInInspector] fHdrExposure ("", Float) = 1.0 } SubShader { Tags { "Queue"="Geometry-20" "RenderType"="Opaque" } ZWrite Off Pass { CGPROGRAM #include "UnityCG.cginc" #pragma target 3.0 #pragma vertex vert #pragma fragment frag #pragma multi_compile __ WPM_SPECULAR_ENABLED #pragma multi_compile __ WPM_BUMPMAP_ENABLED #pragma multi_compile __ WPM_CLOUDSHADOWS_ENABLED sampler2D _MainTex; sampler2D _NormalMap; sampler2D _CloudMap; sampler2D _CityLights; uniform float3 _SunLightDirection; // The direction vector to the light source uniform float3 v3InvWavelength; // 1 / pow(wavelength, 4) for the red, green, and blue channels uniform float fOuterRadius; // The outer (atmosphere) radius uniform float fOuterRadius2; // fOuterRadius^2 uniform float fInnerRadius; // The inner (planetary) radius uniform float fInnerRadius2; // fInnerRadius^2 uniform float fKrESun; // Kr * ESun uniform float fKmESun; // Km * ESun uniform float fKr4PI; // Kr * 4 * PI uniform float fKm4PI; // Km * 4 * PI uniform float fScale; // 1 / (fOuterRadius - fInnerRadius) uniform float fScaleDepth; // The scale depth (i.e. the altitude at which the atmosphere's average density is found) uniform float fScaleOverScaleDepth; // fScale / fScaleDepth uniform float fHdrExposure; // HDR exposure uniform float _BumpAmount; // Normal/Bump effect amount (0..1) uniform float _CloudSpeed; uniform float _CloudAlpha; uniform float _CloudShadowStrength; uniform float _CloudElevation; uniform float _Brightness; uniform float _Contrast; uniform float _AmbientLight; uniform float _SpecularPower; uniform float _SpecularIntensity; uniform float _AtmosphereAlpha; uniform float _CityLightsBrightness; struct v2f { float4 pos : SV_POSITION; float2 uv : TEXCOORD0; float3 c0 : COLOR0; float3 c1 : COLOR1; float3 viewDir: TEXCOORD1; float3 normal: NORMAL; #if WPM_BUMPMAP_ENABLED float3 tspace0 : TEXCOORD2; // tangent.x, bitangent.x, normal.x float3 tspace1 : TEXCOORD3; // tangent.y, bitangent.y, normal.y float3 tspace2 : TEXCOORD4; // tangent.z, bitangent.z, normal.z #endif UNITY_VERTEX_INPUT_INSTANCE_ID UNITY_VERTEX_OUTPUT_STEREO }; float scale(float fCos) { float x = 1.0 - fCos; return fScaleDepth * exp(-0.00287 + x*(0.459 + x*(3.83 + x*(-6.80 + x*5.25)))); } v2f vert (appdata_tan v) { float3 center = float3(unity_ObjectToWorld[0][3], unity_ObjectToWorld[1][3], unity_ObjectToWorld[2][3]); float3 v3CameraPos = _WorldSpaceCameraPos - center; // The camera's current position float fCameraHeight = length(v3CameraPos); // The camera's current height float fCameraHeight2 = fCameraHeight*fCameraHeight; // fCameraHeight^2 // Get the ray from the camera to the vertex and its length (which is the far point of the ray passing through the atmosphere) float3 v3Pos = mul(unity_ObjectToWorld, v.vertex).xyz - center; float3 v3Ray = v3Pos - v3CameraPos; float fFar = length(v3Ray); v3Ray /= fFar; // Calculate the closest intersection of the ray with the outer atmosphere (which is the near point of the ray passing through the atmosphere) float B = 2.0 * dot(v3CameraPos, v3Ray); float C = fCameraHeight2 - fOuterRadius2; float fDet = max(0.0, B*B - 4.0 * C); float fNear = 0.5 * (-B - sqrt(fDet)); // Calculate the ray's starting position, then calculate its scattering offset float3 v3Start = v3CameraPos + v3Ray * fNear; fFar -= fNear; float fDepth = exp((fInnerRadius - fOuterRadius) / fScaleDepth); float fCameraAngle = dot(-v3Ray, v3Pos) / length(v3Pos); float v3PosLength = length(v3Pos); float fLightAngle = dot(_SunLightDirection, v3Pos) / v3PosLength; float fCameraScale = scale(fCameraAngle); float fLightScale = scale(fLightAngle); float fCameraOffset = fDepth*fCameraScale; float fTemp = (fLightScale + fCameraScale); const float fSamples = 2.0; // Initialize the scattering loop variables float fSampleLength = fFar / fSamples; float fScaledLength = fSampleLength * fScale; float3 v3SampleRay = v3Ray * fSampleLength; float3 v3SamplePoint = v3Start + v3SampleRay * 0.5; // Now loop through the sample rays float3 v3FrontColor = float3(0.0, 0.0, 0.0); float3 v3Attenuate; for(int i=0; i