347 lines
11 KiB
HLSL
347 lines
11 KiB
HLSL
uniform float4 _SunDir;
|
|
uniform float4 _MoonDir;
|
|
|
|
uniform float4 _SunColor;
|
|
|
|
uniform half4 _FrontColor0;
|
|
uniform half4 _FrontColor1;
|
|
uniform half4 _FrontColor2;
|
|
uniform half4 _FrontColor3;
|
|
uniform half4 _FrontColor4;
|
|
uniform half4 _FrontColor5;
|
|
uniform half4 _FrontColor6;
|
|
|
|
uniform half4 _BackColor0;
|
|
uniform half4 _BackColor1;
|
|
uniform half4 _BackColor2;
|
|
uniform half4 _BackColor3;
|
|
uniform half4 _BackColor4;
|
|
uniform half4 _BackColor5;
|
|
uniform half4 _BackColor6;
|
|
|
|
uniform float4 _SkyColorTint;
|
|
|
|
uniform float _frontBackDistribution0;
|
|
uniform float _frontBackDistribution1;
|
|
uniform float _frontBackDistribution2;
|
|
uniform float _frontBackDistribution3;
|
|
uniform float _frontBackDistribution4;
|
|
|
|
uniform float _Intensity;
|
|
uniform float _SkyColorExponent;
|
|
uniform float _MieScatteringIntensity;
|
|
|
|
|
|
float Mie(float costh, float g)
|
|
{
|
|
g = min(g, 0.9381);
|
|
float k = 1.55 * g - 0.55 * g * g * g;
|
|
|
|
float kcosth = k * costh;
|
|
|
|
return (1 - k * k) / ((4 * 3.14159265f) * (1 - kcosth) * (1 - kcosth));
|
|
}
|
|
|
|
float RemapEnviro(float org_val, float org_min, float org_max, float new_min, float new_max)
|
|
{
|
|
return new_min + saturate(((org_val - org_min) / (org_max - org_min))*(new_max - new_min));
|
|
}
|
|
|
|
|
|
//Cirrus Clouds
|
|
uniform sampler2D _CirrusCloudMap;
|
|
uniform float _CirrusCloudAlpha;
|
|
uniform float _CirrusCloudCoverage;
|
|
uniform float _CirrusCloudAltitude;
|
|
uniform float4 _CirrusCloudColor;
|
|
uniform float _CirrusCloudColorPower;
|
|
uniform float2 _CirrusCloudAnimation;
|
|
|
|
float4 CirrusClouds(float3 uvs)
|
|
{
|
|
uvs = normalize(uvs);
|
|
|
|
float4 uv1;
|
|
float4 uv2;
|
|
|
|
uv1.xy = (uvs.xz * 0.2) + _CirrusCloudAnimation;
|
|
uv2.xy = (uvs.xz * 0.6) + _CirrusCloudAnimation;
|
|
|
|
float4 clouds1 = tex2D(_CirrusCloudMap, uv1.xy);
|
|
float4 clouds2 = tex2D(_CirrusCloudMap, uv2.xy);
|
|
|
|
float color1 = pow(clouds1.g + clouds2.g, 0.1);
|
|
float color2 = pow(clouds2.b * clouds1.r, 0.2);
|
|
|
|
float4 finalClouds = lerp(clouds1, clouds2, color1 * color2);
|
|
float cloudExtinction = pow(uvs.y , 2);
|
|
|
|
finalClouds.a *= _CirrusCloudAlpha;
|
|
finalClouds.a *= cloudExtinction;
|
|
|
|
if (uvs.y < 0)
|
|
finalClouds.a = 0;
|
|
|
|
finalClouds.rgb = finalClouds.a * pow(_CirrusCloudColor.rgb,max(_CirrusCloudColorPower,0.0001));
|
|
finalClouds.rgb = pow(finalClouds.rgb,1 - _CirrusCloudCoverage);
|
|
|
|
return finalClouds;
|
|
}
|
|
|
|
|
|
//2D Clouds
|
|
uniform sampler2D _FlatCloudsBaseTexture;
|
|
uniform sampler2D _FlatCloudsDetailTexture;
|
|
uniform float4 _FlatCloudsAnimation;
|
|
uniform float3 _FlatCloudsLightDirection;
|
|
uniform float3 _FlatCloudsLightColor;
|
|
uniform float3 _FlatCloudsAmbientColor;
|
|
uniform float4 _FlatCloudsLightingParams; // x = LightIntensity, y = AmbientIntensity, z = Absorbtion, w = HgPhase
|
|
uniform float4 _FlatCloudsParams; // x = Coverage, y = Density, z = Altitude, w = shadowSteps
|
|
uniform float4 _FlatCloudsTiling; // x = Base, y = Detail
|
|
|
|
|
|
float HenryGreenstein(float cosTheta, float g)
|
|
{
|
|
float k = 3.0 / (8.0 * 3.1415926f) * (1.0 - g * g) / (2.0 + g * g);
|
|
return k * (1.0 + cosTheta * cosTheta) / pow(abs(1.0 + g * g - 2.0 * g * cosTheta), 1.5);
|
|
}
|
|
|
|
|
|
float CalculateCloudDensity(float2 posBase, float2 posDetail,float3 worldPos, float coverage)
|
|
{
|
|
float4 baseNoise = tex2D(_FlatCloudsBaseTexture, posBase);
|
|
float low_freq_fBm = (baseNoise.g * 0.625) + (baseNoise.b * 0.25) + (baseNoise.a * 0.125);
|
|
float base_cloud = RemapEnviro(baseNoise.r, -(1.0 - low_freq_fBm), 1.0, 0.0, 1.0) * coverage;
|
|
|
|
float4 detailNoise = tex2D(_FlatCloudsDetailTexture, posDetail * 2);
|
|
float high_freq_fBm = (detailNoise.r * 0.625) + (detailNoise.g * 0.25) + (detailNoise.b * 0.125);
|
|
float density = RemapEnviro(base_cloud, 1-high_freq_fBm * 0.5, 1.0, 0.0, 1.0);
|
|
|
|
density *= pow(high_freq_fBm, 0.4);
|
|
density *= _FlatCloudsParams.y;
|
|
|
|
|
|
return density;
|
|
}
|
|
float SampleShadowUV(float2 baseUV, float2 detailUV)
|
|
{
|
|
// Direction in UV space, scaled by some small factor
|
|
// Direction in UV space
|
|
float2 dirUV = normalize(_FlatCloudsLightDirection.xz);
|
|
|
|
// Total shadow length in UV space (constant)
|
|
float totalShadowLength = 0.01;
|
|
|
|
// Per-step offset so total distance remains the same
|
|
float2 stepUV = dirUV * (totalShadowLength / _FlatCloudsParams.w);
|
|
|
|
float shadow = 1.0;
|
|
float stepFactor = _FlatCloudsLightingParams.z * 1 / _FlatCloudsParams.w;
|
|
|
|
for (int i = 1; i <= _FlatCloudsParams.w; i++)
|
|
{
|
|
float2 uvOffsetBase = baseUV - stepUV * i;
|
|
float2 uvOffsetDetail = detailUV - stepUV * i * (_FlatCloudsTiling.y/_FlatCloudsTiling.x);
|
|
|
|
float d = CalculateCloudDensity(uvOffsetBase, uvOffsetDetail, float3(0,0,0), _FlatCloudsParams.x);
|
|
shadow *= exp(-d * stepFactor);
|
|
}
|
|
|
|
return saturate(shadow);
|
|
}
|
|
|
|
float4 Clouds2D (float3 uvs, float3 worldPos)
|
|
{
|
|
half4 col = 0;
|
|
uvs = normalize(uvs);
|
|
|
|
float4 uv1;
|
|
uv1.xy = (uvs.xz * _FlatCloudsTiling.x) + _FlatCloudsAnimation.xy;
|
|
uv1.zw = (uvs.xz * _FlatCloudsTiling.y) + _FlatCloudsAnimation.zw;
|
|
|
|
float cloudExtinction = pow(uvs.y, 2);
|
|
float density = CalculateCloudDensity(uv1.xy, uv1.zw, uvs, _FlatCloudsParams.x);
|
|
|
|
// --- Shadows ---
|
|
float shadowTerm = SampleShadowUV(uv1.xy, uv1.zw);
|
|
//float absorbtion = exp2(-1 * (density * _FlatCloudsLightingParams.z));
|
|
float shadows = shadowTerm;
|
|
|
|
float3 viewDir = normalize(worldPos - _WorldSpaceCameraPos);
|
|
float inscatterAngle = dot(normalize(_FlatCloudsLightDirection), -viewDir);
|
|
float hg = HenryGreenstein(inscatterAngle, _FlatCloudsLightingParams.w) * 2 * shadows;
|
|
|
|
// apply shadow to the direct light only
|
|
float lighting = density * (shadows + hg) * shadowTerm;
|
|
|
|
float3 lightColor = pow(_FlatCloudsLightColor, 2) * _FlatCloudsLightingParams.x;
|
|
col.rgb = lightColor * lighting;
|
|
col.rgb += _FlatCloudsAmbientColor * _FlatCloudsLightingParams.y;
|
|
|
|
|
|
col.a = saturate(density * cloudExtinction);
|
|
|
|
if (uvs.y < 0)
|
|
col.a = 0;
|
|
|
|
|
|
return col;
|
|
}
|
|
|
|
float4 GetSkyColorSimple (float3 viewDir, float mieSize, float depth = 1.0)
|
|
{
|
|
float cosTheta = smoothstep(-0.25,1.15,saturate(dot(-_SunDir.xyz, viewDir)));
|
|
half y = -viewDir.y / 0.02;
|
|
|
|
float3 frontBack1 = lerp(_FrontColor1.rgb,_BackColor1.rgb,cosTheta);
|
|
float3 frontBack2 = lerp(_FrontColor2.rgb,_BackColor2.rgb,cosTheta);
|
|
float3 frontBack5 = lerp(_FrontColor5.rgb,_BackColor5.rgb,cosTheta);
|
|
|
|
float heightS1 = RemapEnviro(viewDir.y,-0.75,_frontBackDistribution0,0,1);
|
|
float heightS2 = RemapEnviro(viewDir.y,_frontBackDistribution0,_frontBackDistribution1,0,1);
|
|
float heightS5 = RemapEnviro(viewDir.y,_frontBackDistribution1,1,0,1);
|
|
|
|
float3 sky1 = lerp(float3(0,0,0),frontBack1.rgb,heightS1);
|
|
float3 sky2 = lerp(sky1.rgb,frontBack2.rgb,heightS2);
|
|
float3 sky5 = lerp(sky2.rgb,frontBack5.rgb,heightS5);
|
|
|
|
float3 skyColor = sky5 * _Intensity;
|
|
|
|
float eyeCos = dot(_SunDir.xyz, viewDir);
|
|
float eyeCos2 = eyeCos * eyeCos;
|
|
float fade = saturate(dot(_SunDir.xyz, viewDir));
|
|
|
|
float mie = Mie(eyeCos, 0.7) * _MieScatteringIntensity * fade * depth;
|
|
skyColor.rgb += (mie * skyColor) * _SunColor.rgb;
|
|
|
|
return float4(skyColor * _SkyColorTint.rgb,1);
|
|
}
|
|
|
|
float4 GetSkyColor (float3 viewDir, float mieSize, float depth = 1.0)
|
|
{
|
|
float cosTheta = smoothstep(-0.25,1.15,saturate(dot(-_SunDir.xyz, viewDir)));
|
|
half y = -viewDir.y / 0.02;
|
|
|
|
float3 frontBack0 = lerp(_FrontColor0.rgb,_BackColor0.rgb,cosTheta);
|
|
float3 frontBack1 = lerp(_FrontColor1.rgb,_BackColor1.rgb,cosTheta);
|
|
float3 frontBack2 = lerp(_FrontColor2.rgb,_BackColor2.rgb,cosTheta);
|
|
float3 frontBack3 = lerp(_FrontColor3.rgb,_BackColor3.rgb,cosTheta);
|
|
float3 frontBack4 = lerp(_FrontColor4.rgb,_BackColor4.rgb,cosTheta);
|
|
float3 frontBack5 = lerp(_FrontColor5.rgb,_BackColor5.rgb,cosTheta);
|
|
|
|
float heightS1 = RemapEnviro(viewDir.y,-0.75,_frontBackDistribution0,0,1);
|
|
float heightS2 = RemapEnviro(viewDir.y,_frontBackDistribution0,_frontBackDistribution1,0,1);
|
|
float heightS3 = RemapEnviro(viewDir.y,_frontBackDistribution1,_frontBackDistribution2,0,1);
|
|
float heightS4 = RemapEnviro(viewDir.y,_frontBackDistribution2,_frontBackDistribution3,0,1);
|
|
float heightS5 = RemapEnviro(viewDir.y,_frontBackDistribution3,1,0,1);
|
|
|
|
float3 sky1 = lerp(frontBack0.rgb,frontBack1.rgb,heightS1);
|
|
float3 sky2 = lerp(sky1.rgb,frontBack2.rgb,heightS2);
|
|
float3 sky3 = lerp(sky2.rgb,frontBack3.rgb,heightS3);
|
|
float3 sky4 = lerp(sky3.rgb,frontBack4.rgb,heightS4);
|
|
float3 sky5 = lerp(sky4.rgb,frontBack5.rgb,heightS5);
|
|
|
|
float3 skyColor = sky5 * _Intensity;
|
|
|
|
float eyeCos = dot(_SunDir.xyz, viewDir);
|
|
float eyeCos2 = eyeCos * eyeCos;
|
|
float fade = saturate(dot(_SunDir.xyz, viewDir));
|
|
|
|
float mie = Mie(eyeCos, 0.7) * _MieScatteringIntensity * fade * depth;
|
|
|
|
skyColor.rgb += (mie * skyColor) * _SunColor.rgb;
|
|
|
|
return float4(skyColor * _SkyColorTint.rgb,1);
|
|
}
|
|
|
|
|
|
///Aurora
|
|
sampler2D _Aurora_Layer_1;
|
|
sampler2D _Aurora_Layer_2;
|
|
sampler2D _Aurora_Colorshift;
|
|
|
|
float4 _AuroraColor;
|
|
float _AuroraIntensity;
|
|
float _AuroraBrightness;
|
|
float _AuroraContrast;
|
|
float _AuroraHeight;
|
|
float _AuroraScale;
|
|
float _AuroraSpeed;
|
|
float _AuroraSteps;
|
|
|
|
float4 _Aurora_Tiling_Layer1;
|
|
float4 _Aurora_Tiling_Layer2;
|
|
float4 _Aurora_Tiling_ColorShift;
|
|
|
|
float randomNoise(float3 co)
|
|
{
|
|
return frac(sin(dot(co.xyz ,float3(17.2486,32.76149, 368.71564))) * 32168.47512);
|
|
}
|
|
|
|
float4 SampleAurora(float3 uv)
|
|
{
|
|
|
|
float2 uv_1 = uv.xy * _Aurora_Tiling_Layer1.xy + (_Aurora_Tiling_Layer1.zw * _AuroraSpeed * _Time.y);
|
|
|
|
float4 aurora = tex2Dlod(_Aurora_Layer_1, float4(uv_1.xy,0,0));
|
|
|
|
float2 uv_2 = uv_1 * _Aurora_Tiling_Layer2.xy + (_Aurora_Tiling_Layer2.zw * _AuroraSpeed * _Time.y);
|
|
float4 aurora2 = tex2Dlod(_Aurora_Layer_2, float4(uv_2.xy,0,0));
|
|
aurora += (aurora2 - 0.5) * 0.5;
|
|
|
|
aurora.w = aurora.w * 0.8 + 0.05;
|
|
|
|
float3 uv_3 = float3(uv.xy * _Aurora_Tiling_ColorShift.xy + (_Aurora_Tiling_ColorShift.zw * _AuroraSpeed * _Time.y), 0.0);
|
|
float4 cloudColor = tex2Dlod(_Aurora_Colorshift, float4(uv_3.xy,0,0));
|
|
|
|
float contrastMask = 1.0 - saturate(aurora.a);
|
|
contrastMask = pow(contrastMask, _AuroraContrast);
|
|
aurora.rgb *= lerp(float3(0,0,0), _AuroraColor.rgb * cloudColor.rgb * _AuroraBrightness, contrastMask);
|
|
|
|
float cloudSub = 1.0 - uv.z;
|
|
aurora.a = aurora.a - cloudSub * cloudSub;
|
|
aurora.a = saturate(aurora.a * _AuroraIntensity);
|
|
aurora.rgb *= aurora.a;
|
|
|
|
return aurora;
|
|
}
|
|
|
|
float4 Aurora (float3 wpos)
|
|
{
|
|
if (_AuroraIntensity < 0.05)
|
|
return float4(0,0,0,0);
|
|
|
|
float3 viewDir = normalize(wpos);
|
|
|
|
float viewFalloff = 1.0 - saturate(dot(viewDir, float3(0,1,0)));
|
|
|
|
if (viewDir.y < 0 || viewDir.y > 1)
|
|
return half4(0, 0, 0, 0);
|
|
|
|
float3 traceDir = normalize(viewDir + float3(0, viewFalloff * 0.2 ,0));
|
|
|
|
float3 worldPos = _WorldSpaceCameraPos + traceDir * ((_AuroraHeight - _WorldSpaceCameraPos.y) / max(traceDir.y, 0.01));
|
|
float3 uv = float3(worldPos.xz * 0.01 * _AuroraScale, 0);
|
|
|
|
half3 uvStep = half3(traceDir.xz * -1.0 * (1.0 / traceDir.y), 1.0) * (1.0 / _AuroraSteps);
|
|
uv += uvStep * randomNoise(wpos + _SinTime.w);
|
|
|
|
half4 finalColor = half4(0,0,0,0);
|
|
|
|
[loop]
|
|
for (int iCount = 0; iCount < _AuroraSteps; iCount++)
|
|
{
|
|
if (finalColor.a > 1)
|
|
break;
|
|
|
|
uv += uvStep;
|
|
finalColor += SampleAurora(uv) * (1.0 - finalColor.a);
|
|
}
|
|
|
|
finalColor *= viewDir.y;
|
|
|
|
return finalColor;
|
|
}
|
|
|