Files
Fishing2/Assets/Plugins/Azure[Sky] Dynamic Skybox/Core/Shaders/FogScatteringComputation.shader
2026-01-25 11:25:49 +08:00

193 lines
9.0 KiB
Plaintext

Shader "Azure[Sky] Dynamic Skybox/Fog Scattering Computation"
{
SubShader
{
// No culling or depth
Cull Off ZWrite Off ZTest Always
Pass
{
HLSLPROGRAM
#pragma vertex vertex_program
#pragma fragment fragment_program
#pragma target 3.0
#include "UnityCG.cginc"
// Constants
#define PI 3.1415926535f
#define Pi316 0.0596831f
#define Pi14 0.07957747f
// Textures
uniform sampler2D _CameraDepthTexture;
uniform float4 _CameraDepthTexture_TexelSize;
// Directions
uniform float3 _Azure_SunDirection;
uniform float3 _Azure_MoonDirection;
uniform float4x4 _Azure_SunMatrix;
uniform float4x4 _Azure_MoonMatrix;
uniform float4x4 _Azure_UpDirectionMatrix;
uniform float4x4 _Azure_FrustumCornersMatrix;
// Scattering
uniform float _Azure_MieDistance;
uniform float _Azure_Kr;
uniform float _Azure_Km;
uniform float3 _Azure_Rayleigh;
uniform float3 _Azure_Mie;
uniform float3 _Azure_MieG;
uniform float _Azure_Scattering;
uniform float _Azure_SkyLuminance;
uniform float _Azure_Exposure;
uniform float4 _Azure_RayleighColor;
uniform float4 _Azure_MieColor;
// Fog paramters
uniform float _Azure_GlobalFogDistance;
uniform float _Azure_GlobalFogSmooth;
uniform float _Azure_GlobalFogDensity;
uniform float _Azure_HeightFogDistance;
uniform float _Azure_HeightFogSmooth;
uniform float _Azure_HeightFogDensity;
uniform float _Azure_HeightFogStartAltitude;
uniform float _Azure_HeightFogEndAltitude;
uniform float _Azure_FogBluishIntensity;
uniform float _Azure_HeightFogScatterMultiplier;
// Attributes transfered from the mesh data to the vertex program
struct Attributes
{
float4 vertex : POSITION;
float4 texcoord : TEXCOORD0;
};
// Attributes transfered from the vertex program to the fragment program
struct Varyings
{
float4 Position : SV_POSITION;
float2 DepthUV : TEXCOORD0;
float4 InterpolatedRay : TEXCOORD1;
};
// Vertex shader program
Varyings vertex_program (Attributes v)
{
Varyings Output = (Varyings)0;
v.vertex.z = 0.1f;
Output.Position = UnityObjectToClipPos(v.vertex);
Output.DepthUV = v.texcoord.xy;
//#if UNITY_UV_STARTS_AT_TOP
//if (_CameraDepthTexture_TexelSize.y < 0.0f)
//{
// Output.DepthUV.y = 1.0f - Output.DepthUV.y; // Not sure this one is required!
//}
//#endif
// Based on Unity5.6 GlobalFog
int index = v.texcoord.x + (2.0f * Output.DepthUV.y);
Output.InterpolatedRay = _Azure_FrustumCornersMatrix[index];
Output.InterpolatedRay.xyz = mul((float3x3)_Azure_UpDirectionMatrix, Output.InterpolatedRay.xyz);
Output.InterpolatedRay.w = index;
return Output;
}
// Fragment shader program
float4 fragment_program (Varyings Input) : SV_Target
{
// Reconstruct world space position and direction towards this screen pixel
float depth = Linear01Depth(UNITY_SAMPLE_DEPTH(tex2D(_CameraDepthTexture, Input.DepthUV)));
float mieDepth = saturate(lerp(depth * (_ProjectionParams.z / 10000.0f), depth * (_ProjectionParams.z / 1000.0f), _Azure_MieDistance));
// Global fog
float globalFog = smoothstep(-_Azure_GlobalFogSmooth, 1.25f, length(depth * Input.InterpolatedRay.xyz) / _Azure_GlobalFogDistance) * _Azure_GlobalFogDensity;
// Height fog
float heightFogDistance = smoothstep(-_Azure_HeightFogSmooth, 1.25f, length(depth * Input.InterpolatedRay.xyz) / _Azure_HeightFogDistance);
float3 worldSpaceDirection = mul((float3x3)_Azure_UpDirectionMatrix, _WorldSpaceCameraPos) + depth * Input.InterpolatedRay.xyz;
float heightFog = saturate((worldSpaceDirection.y - _Azure_HeightFogStartAltitude) / (_Azure_HeightFogEndAltitude + _Azure_HeightFogStartAltitude));
heightFog = 1.0f - heightFog;
heightFog *= heightFog;
heightFog *= heightFogDistance;
heightFog *= _Azure_HeightFogDensity;
// Total fog
float totalFog = saturate(globalFog + heightFog);
// Directions
float3 worldPos = _WorldSpaceCameraPos + depth * Input.InterpolatedRay.xyz;
float3 viewDir = normalize(worldPos - _WorldSpaceCameraPos);
float sunCosTheta = dot(viewDir, _Azure_SunDirection);
float moonCosTheta = dot(viewDir, _Azure_MoonDirection);
float skyCosTheta = dot(viewDir, float3(0.0f, -1.0f, 0.0f));
float r = length(float3(0.0f, 50.0f, 0.0f));
float sunRise = saturate(dot(float3(0.0f, 500.0f, 0.0f), _Azure_SunDirection) / r);
float moonRise = saturate(dot(float3(0.0f, 500.0f, 0.0f), _Azure_MoonDirection) / r);
float sunDot = saturate(dot(float3(0.0f, 1.0f, 0.0f), _Azure_SunDirection));
float moonDot = saturate(dot(float3(0.0f, 1.0f, 0.0f), _Azure_MoonDirection));
// Optical depth
//float zenith1 = acos(saturate(dot(float3(-0.47f, 1.0f, -0.47f), depth))); // Better for sunset
float zenith1 = acos(saturate(dot(float3(0.0f, 1.0f, 0.0f), viewDir) * mieDepth)); // Better for sunset
float zenith2 = acos(saturate(max(0.0f, viewDir.y) + (1.0f - depth) * _Azure_FogBluishIntensity)); // Better for noon
float zenith = lerp(zenith1, zenith2, saturate(lerp(moonDot, sunDot, sunRise)));
float z = cos(zenith) + 0.15f * pow(93.885f - ((zenith * 180.0f) / PI), -1.253f);
float SR = _Azure_Kr / z;
float SM = _Azure_Km / z;
// Extinction
float3 fex = exp(-(_Azure_Rayleigh * SR + _Azure_Mie * SM));
// Default sky - When there is no sun or moon in the sky!
float3 Esun = 1.0f - fex;
float rayPhase = 2.0f + 0.5f * pow(skyCosTheta, 2.0f);
float3 BrTheta = Pi316 * _Azure_Rayleigh * rayPhase * _Azure_RayleighColor.rgb;
float3 BrmTheta = BrTheta / (_Azure_Rayleigh + _Azure_Mie);
float3 defaultDayLight = BrmTheta * Esun * _Azure_Scattering * _Azure_SkyLuminance * (1.0f - fex);
defaultDayLight *= 1.0f - sunRise;
defaultDayLight *= 1.0f - moonRise;
// Sun inScattering
Esun = lerp(fex, (1.0f - fex), sunDot);
rayPhase = 2.0f + 0.5f * pow(sunCosTheta, 2.0f);
float miePhase = _Azure_MieG.x / pow(_Azure_MieG.y - _Azure_MieG.z * sunCosTheta, 1.5f);
BrTheta = Pi316 * _Azure_Rayleigh * rayPhase * _Azure_RayleighColor.rgb;
float3 BmTheta = Pi14 * _Azure_Mie * miePhase * _Azure_MieColor.rgb * mieDepth;
BrmTheta = (BrTheta + BmTheta) / (_Azure_Rayleigh + _Azure_Mie);
float3 sunInScatter = BrmTheta * Esun * _Azure_Scattering * (1.0f - fex);
sunInScatter *= sunRise;
// Moon inScattering
Esun = 1.0f - fex;
rayPhase = 2.0f + 0.5f * pow(moonCosTheta, 2.0f);
miePhase = _Azure_MieG.x / pow(_Azure_MieG.y - _Azure_MieG.z * moonCosTheta, 1.5f);
BrTheta = Pi316 * _Azure_Rayleigh * rayPhase * _Azure_RayleighColor.rgb;
BmTheta = Pi14 * _Azure_Mie * miePhase * _Azure_MieColor.rgb * mieDepth;
BrmTheta = (BrTheta + BmTheta) / (_Azure_Rayleigh + _Azure_Mie);
float3 moonInScatter = BrmTheta * Esun * _Azure_Scattering * 0.1f * (1.0f - fex);
moonInScatter *= moonRise;
moonInScatter *= 1.0f - sunRise;
// Output
float3 OutputColor = defaultDayLight + sunInScatter + moonInScatter;
OutputColor += heightFog * _Azure_HeightFogScatterMultiplier;
// Tonemapping
OutputColor = saturate(1.0f - exp(-_Azure_Exposure * OutputColor));
// Color correction
#ifndef UNITY_COLORSPACE_GAMMA
OutputColor = pow(OutputColor, 2.2f);
#endif
return float4(OutputColor.rgb, totalFog);
}
ENDHLSL
}
}
}