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

209 lines
9.5 KiB
Plaintext

Shader "Azure[Sky] Dynamic Skybox/Fog Scattering Renderer"
{
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 "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
#include "Packages/com.unity.render-pipelines.core/ShaderLibrary/DynamicScaling.hlsl"
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
// Constants
//#define PI 3.1415926535f
#define Pi316 0.0596831f
#define Pi14 0.07957747f
// Textures
#ifdef USE_FULL_PRECISION_BLIT_TEXTURE
TEXTURE2D_X_FLOAT(_BlitTexture);
#else
TEXTURE2D_X(_BlitTexture);
#endif
uniform float4 _BlitScaleBias;
// 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
{
uint vertexID : SV_VertexID;
float4 vertex : POSITION;
};
// Attributes transfered from the vertex program to the fragment program
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 texcoord : TEXCOORD0;
float2 positionHCS : TEXCOORD1;
};
// Vertex shader program
Varyings vertex_program(Attributes v)
{
Varyings Output = (Varyings)0;
float2 uv = GetFullScreenTriangleTexCoord(v.vertexID);
Output.positionCS = GetFullScreenTriangleVertexPosition(v.vertexID);
Output.positionHCS = TransformObjectToHClip(v.vertex.xyz).xy;
Output.texcoord = DYNAMIC_SCALING_APPLY_SCALEBIAS(uv);
return Output;
}
inline float Linear01DepthCustom(float z) {
return 1.0 / (_ZBufferParams.x * z + _ZBufferParams.y);
}
// Fragment shader program
float4 fragment_program(Varyings Input) : SV_Target
{
// Original scene
float3 screen = SAMPLE_TEXTURE2D(_BlitTexture, sampler_LinearClamp, Input.texcoord).rgb;
// Depth calculation
float2 UV = Input.positionCS.xy / _ScaledScreenParams.xy;
#if UNITY_REVERSED_Z
real depth = SampleSceneDepth(UV);
#else
// Adjust z to match NDC for OpenGL
real depth = lerp(UNITY_NEAR_CLIP_VALUE, 1, SampleSceneDepth(UV));
#endif
if (depth == 1.0f) return float4(screen, 1.0f);
// Reconstruct world space position and direction towards this screen pixel
float3 worldPos = ComputeWorldSpacePosition(UV, depth, UNITY_MATRIX_I_VP);
float dist = distance(_WorldSpaceCameraPos, worldPos);
float linearDepth = Linear01DepthCustom(depth);
float mieDepth = saturate(lerp(linearDepth * (_ProjectionParams.z / 10000.0f), linearDepth * (_ProjectionParams.z / 1000.0f), _Azure_MieDistance));
float globalFog = smoothstep(-_Azure_GlobalFogSmooth, 1.25f, dist / _Azure_GlobalFogDistance) * _Azure_GlobalFogDensity;
float heightFogDistance = smoothstep(-_Azure_HeightFogSmooth, 1.25f, dist / _Azure_HeightFogDistance);
float3 worldSpaceDirection = mul((float3x3)_Azure_UpDirectionMatrix, worldPos.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 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 - linearDepth) * _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 fogData = defaultDayLight + sunInScatter + moonInScatter;
fogData += heightFog * _Azure_HeightFogScatterMultiplier;
// Tonemapping
fogData = saturate(1.0f - exp(-_Azure_Exposure * fogData));
// Color correction
#ifndef UNITY_COLORSPACE_GAMMA
fogData = pow(fogData, 2.2f);
#endif
// Output color
float4 outputColor = lerp(float4(screen, 1.0f), float4(fogData.rgb, 1.0f), totalFog);
return outputColor;
}
ENDHLSL
}
}
}