Shader "NLD_URP/NLD_Scene_FogSheet" { Properties { [Header(Base Settings)] _MainTex ("Fog Texture", 2D) = "white" {} _Color("Tint Color", Color) = (0.8, 0.9, 1.0, 0.5) _AlphaMultiplier("Alpha Multiplier", Range(0, 5)) = 1.0 [Header(Animation)] _ScrollSpeed("Scroll Speed (XY)", Vector) = (0.1, 0.05, 0, 0) _NoiseScale("Noise Scale", Float) = 1.0 [Header(Soft Particles)] [Toggle(_SOFTPARTICLES_ON)] _SoftParticles("Soft Particles Enabled", Float) = 0.0 _SoftParticleFade("Soft Particle Intensity", Range(0.01, 10)) = 1.0 [Header(Vertical Gradient)] [Toggle(_INVERT_VERTICAL_GRADIENT)] _InvertVerticalGradient("Invert Vertical Gradient", Float) = 0.0 _GradientBottomStart("Gradient Bottom Start (Invisible)", Range(0, 1)) = 0.0 _GradientBottom("Gradient Bottom End (Opaque)", Range(0, 1)) = 0.2 _GradientTop("Gradient Top Start (Opaque)", Range(0, 1)) = 0.8 _GradientTopEnd("Gradient Top End (Invisible)", Range(0, 1)) = 1.0 _GradientPower("Gradient Power", Float) = 1.0 } SubShader { Tags { "RenderType" = "Transparent" "RenderPipeline" = "UniversalPipeline" "Queue" = "Transparent" "IgnoreProjector" = "True" } Pass { Name "ForwardLit" Tags { "LightMode" = "UniversalForward" } Blend SrcAlpha OneMinusSrcAlpha ZWrite Off Cull Off HLSLPROGRAM #pragma vertex vert #pragma fragment frag #pragma shader_feature_local _INVERT_VERTICAL_GRADIENT #pragma shader_feature_local _SOFTPARTICLES_ON #pragma multi_compile_fog #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl" #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl" struct Attributes { float4 positionOS : POSITION; float2 uv : TEXCOORD0; half4 color : COLOR; // Use half for color UNITY_VERTEX_INPUT_INSTANCE_ID }; struct Varyings { float4 positionCS : SV_POSITION; half4 color : TEXCOORD0; // Color low precision ok half fogFactor : TEXCOORD1; // xy: Original UV (for gradient), zw: Scrolled UV (for texture) float4 uvAndScroll : TEXCOORD2; #if defined(_SOFTPARTICLES_ON) float4 screenPos : TEXCOORD3; #endif UNITY_VERTEX_OUTPUT_STEREO }; CBUFFER_START(UnityPerMaterial) float4 _MainTex_ST; half4 _Color; float4 _ScrollSpeed; // Time is high precision half _SoftParticleFade; float _NoiseScale; half _AlphaMultiplier; half _GradientTop; half _GradientTopEnd; half _GradientBottom; half _GradientBottomStart; // Power removed for optimization (linear or smoothstep is enough) CBUFFER_END TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex); Varyings vert(Attributes input) { Varyings output = (Varyings)0; UNITY_SETUP_INSTANCE_ID(input); UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output); float3 positionWS = TransformObjectToWorld(input.positionOS.xyz); output.positionCS = TransformWorldToHClip(positionWS); #if defined(_SOFTPARTICLES_ON) output.screenPos = ComputeScreenPos(output.positionCS); #endif float2 rawUV = TRANSFORM_TEX(input.uv, _MainTex); output.uvAndScroll.xy = rawUV; // Calculate Scrolling in Vertex Shader to save ALUs in Pixel Shader output.uvAndScroll.zw = rawUV * _NoiseScale + _Time.y * _ScrollSpeed.xy; output.color = input.color; output.fogFactor = ComputeFogFactor(output.positionCS.z); return output; } half4 frag(Varyings input) : SV_Target { half4 texColor = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.uvAndScroll.zw); half v = input.uvAndScroll.y; #if defined(_INVERT_VERTICAL_GRADIENT) v = 1.0h - v; #endif half bottomDenom = _GradientBottom - _GradientBottomStart; half topDenom = _GradientTopEnd - _GradientTop; // Calculate Bottom Fade (0 -> 1) half fadeBottom = saturate((v - _GradientBottomStart) / (bottomDenom + 0.0001h)); // Calculate Top Fade (1 -> 0) half fadeTop = saturate((_GradientTopEnd - v) / (topDenom + 0.0001h)); half alphaFactor = fadeBottom * fadeTop * _AlphaMultiplier; #if defined(_SOFTPARTICLES_ON) // Soft Particles Logic - Cross Platform Compatible // Normalize screen position for depth sampling float2 screenUV = input.screenPos.xy / input.screenPos.w; // Sample scene depth float rawDepth = SampleSceneDepth(screenUV); // Convert to linear eye depth - handles both reversed Z (DX/Vulkan) and standard Z (OpenGL ES) float sceneDepth = LinearEyeDepth(rawDepth, _ZBufferParams); // Particle depth is already in linear eye space (clip space w component) float partDepth = input.screenPos.w; // Calculate soft fade half softFade = saturate((sceneDepth - partDepth) * _SoftParticleFade); alphaFactor *= softFade; #endif half4 finalColor = texColor * _Color * input.color; finalColor.a *= alphaFactor; // Apply Fog finalColor.rgb = MixFog(finalColor.rgb, input.fogFactor); return finalColor; } ENDHLSL } } FallBack "Hidden/Universal Render Pipeline/FallbackError" }