123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- Shader "Hidden/VolumetricsURP"
- {
- Properties
- {
- //_MainTex ("Texture", any) = "white" {}
- }
- SubShader
- {
- // No culling or depth
- Cull Off ZWrite Off ZTest Always
- Pass
- {
- HLSLPROGRAM
- #pragma vertex vert
- #pragma fragment frag
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
- #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
-
- float4x4 _LeftWorldFromView;
- float4x4 _RightWorldFromView;
- float4x4 _LeftViewFromScreen;
- float4x4 _RightViewFromScreen;
- sampler2D _DitherTexture;
- //UNITY_DECLARE_SCREENSPACE_TEXTURE(_CloudsTex);
- TEXTURE2D_X_FLOAT(_CameraDepthTexture);
- SAMPLER(sampler_CameraDepthTexture);
- uniform sampler3D _NoiseTexture;
-
- uniform int _Steps;
- uniform float3 _CameraPosition;
- uniform float4 _VolumetricLight;
- uniform float4 _HeightFog;
- uniform float4 _HeightParams;
- uniform float4 _NoiseData;
- uniform float3 _WindDirection;
- uniform float4 _MieG;
- uniform float _MaxRayLength;
- uniform float4 _AmbientColor;
- uniform float3 _DirLightDir;
- uniform float4 _Randomness;
- struct PointLight
- {
- float3 pos;
- float range;
- float3 color;
- float padding;
- };
- StructuredBuffer<PointLight> _PointLights;
- float _PointLightsCount;
- struct SpotLight
- {
- float3 pos;
- float range;
- float3 color;
- float3 lightDirection;
- float lightCosHalfAngle;
- //float2 angularFalloffParameters;
- //float2 distanceFalloffParameters;
- float padding;
- };
- StructuredBuffer<SpotLight> _SpotLights;
- float _SpotLightsCount;
- struct v2f
- {
- float2 uv : TEXCOORD0;
- float4 position : SV_POSITION;
- UNITY_VERTEX_INPUT_INSTANCE_ID
- UNITY_VERTEX_OUTPUT_STEREO
- };
-
- struct appdata
- {
- float4 vertex : POSITION;
- float2 texcoord : TEXCOORD0;
- UNITY_VERTEX_INPUT_INSTANCE_ID
- };
- v2f vert (appdata v)
- {
- v2f o = (v2f)0;
- UNITY_SETUP_INSTANCE_ID(v);
- //UNITY_TRANSFER_INSTANCE_ID(v, o);
- UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
- //VertexPositionInputs vertexInput = GetVertexPositionInputs(v.vertex.xyz);
- o.position = float4(v.vertex.xyz,1);
- #if UNITY_UV_STARTS_AT_TOP
- o.position.y *= -1;
- #endif
- //o.position = v.vertex * float4(2,2,1,1) + float4(-1,-1,0,0);
- o.uv = v.texcoord;
- return o;
- }
- float anisotropy(float costheta)
- {
- float g = _MieG;
- float gsq = g*g;
- float denom = 1 + gsq - 2.0 * g * costheta;
- denom = denom * denom * denom;
- denom = sqrt(max(0, denom));
- return (1 - gsq) / denom;
- }
-
- float anisotropyPointSpot(float costheta)
- {
- float g = 0.8;
- float gsq = g*g;
- float denom = 1 + gsq - 2.0 * g * costheta;
- denom = denom * denom * denom;
- denom = sqrt(max(0, denom));
- return (1 - gsq) / denom;
- }
- float Attenuation(float distNorm)
- {
- return 1.0 / (1.0 + 25.0 * distNorm);
- }
- float DirectionalLight(float3 wpos)
- {
- float atten = 1.0f;
- half cascadeIndex = ComputeCascadeIndex(wpos);
- bool inside = dot(cascadeIndex, 1) < 4;
- float4 coords = mul(_MainLightWorldToShadow[cascadeIndex], float4(wpos, 1.0));
-
- ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
- half4 shadowParams = GetMainLightShadowParams();
- float shadows = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), coords, shadowSamplingData, shadowParams, false).r;
-
- atten = inside ? shadows : 1.0f;
- if(shadows > 0.0f)
- atten = 1.0f;
- return atten;
- }
- float3 PointLights(float3 pos)
- {
- float3 color = 0;
- for (int i = 0; i < _PointLightsCount; i++)
- {
- float3 posToLight = _PointLights[i].pos - pos;
- float distNorm = dot(posToLight, posToLight) * _PointLights[i].range;
- float att = Attenuation(distNorm);
- //#if ANISOTROPY
- float3 cameraToPos = normalize(pos - _WorldSpaceCameraPos.xyz);
- float costheta = dot(cameraToPos, normalize(posToLight));
- att *= anisotropyPointSpot(costheta);
- //#endif
- color += _PointLights[i].color * att;
- }
- return color;
- }
- float3 SpotLights(float3 pos)
- {
- float3 color = 0;
- for (int i = 0; i < _SpotLightsCount; i++)
- {
- float3 posToLight = _SpotLights[i].pos - pos;
- float distNorm = dot(posToLight, posToLight) * _SpotLights[i].range;
- float att = Attenuation(distNorm);
- half3 lightVector = normalize(pos - _SpotLights[i].pos);
- half cosAngle = dot(_SpotLights[i].lightDirection.xyz, lightVector);
- half angleAttenuation = 1;
- angleAttenuation = smoothstep(_SpotLights[i].lightCosHalfAngle, lerp(1, _SpotLights[i].lightCosHalfAngle, 0.8f), cosAngle);
- angleAttenuation = pow(angleAttenuation, 2.0f);
- att *= angleAttenuation;
-
- #if ANISOTROPY
- float3 cameraToPos = normalize(pos - _CameraPos.xyz);
- float costheta = dot(cameraToPos, normalize(posToLight));
- att *= anisotropyPointSpot(costheta);
- #endif
- color += _SpotLights[i].color * att;
- }
- return color;
- }
- //-----------------------------------------------------------------------------------------
- // GetDensity
- //-----------------------------------------------------------------------------------------
- float GetDensity(float3 wpos, inout float density, float depth, float3 rayDir)
- {
- density = 1.0f;
-
- // #ifdef NOISE
- // float4 noise = tex3D(_NoiseTexture, frac(wpos * _NoiseData.x + float3(_Time.y * _WindDirection.x, 0, _Time.y * _WindDirection.y)));
- // float noiseFbm = (noise.g * 0.625) + (noise.b * 0.25) + (noise.a * 0.125);
- // noiseFbm = saturate(noiseFbm - _NoiseData.y);
- // density *= saturate(noiseFbm);
- // #endif
- return density;
- }
-
- float2 squareUV(float2 uv)
- {
- float width = _ScreenParams.x;
- float height =_ScreenParams.y;
- float scale = 1000;
- float x = uv.x * width;
- float y = uv.y * height;
- return float2 (x/scale, y/scale);
- }
- float4 RayMarch(float2 uv,float2 screenPos, float3 rayStart, float3 rayDir, float rayLength, float linearDepth)
- {
- float2 interleavedPos = (fmod(floor(screenPos.xy), 8.0));
- #if UNITY_SINGLE_PASS_STEREO
- float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
- interleavedPos = (interleavedPos - scaleOffset.zw) / scaleOffset.xy;
- #endif
- float offset = tex2D(_DitherTexture, interleavedPos / 8.0 + float2(0.5 / 8.0, 0.5 / 8.0)).w;
- //float offset = tex2D(_DitherTexture, squareUV(uv + _Randomness.xy)).x;
-
- int stepCount = _Steps;
- float stepSize = rayLength / stepCount;
- float3 step = rayDir * stepSize;
- float3 currentPositionDithered = rayStart + step * offset;
- float3 currentPosition = rayStart + step;
- float4 color = float4(0.0,0.0,0.0,0);
- float cosAngle;
- float extinction = 0;
- float transmitance = 0;
- float ambient = 0;
- cosAngle = dot(_DirLightDir.xyz, -rayDir);
- float ani = anisotropy(cosAngle);
- float4 lightsColor;
-
- [loop]
- for (int i = 0; i < stepCount; ++i)
- {
- float density = GetDensity(currentPosition, density, linearDepth, rayDir);
- float atten = DirectionalLight(currentPositionDithered);
-
- //Cloud Shadows
- //float cloudShadows = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_CloudsTex,uv).b;
- //atten *= (1-cloudShadows);
- float scattering = _VolumetricLight.x * density;
- extinction += _VolumetricLight.y * density;
- transmitance += atten * scattering * exp(-extinction);
-
- lightsColor.rgb += PointLights(currentPositionDithered) * density;
- lightsColor.rgb += SpotLights(currentPositionDithered) * density;
-
- currentPosition += step;
- currentPositionDithered += step;
- }
- color.a = transmitance * ani;
- color.rgb += lightsColor.rgb;
- color = max(0, color);
-
- return color;
- }
-
- float4 frag (v2f i) : SV_Target
- {
- UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
- float2 uv = i.uv.xy;
- float depth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_CameraDepthTexture, UnityStereoTransformScreenSpaceTex(uv)).r;
- float linearDepth = Linear01Depth(depth,_ZBufferParams);
-
- float4x4 proj, eyeToWorld;
- if (unity_StereoEyeIndex == 0)
- {
- proj = _LeftViewFromScreen;
- eyeToWorld = _LeftWorldFromView;
- }
- else
- {
- proj = _RightViewFromScreen;
- eyeToWorld = _RightWorldFromView;
- }
- //bit of matrix math to take the screen space coord (u,v,depth) and transform to world space
- float2 uvClip = i.uv * 2.0 - 1.0;
- float clipDepth = depth; // Fix for OpenGl Core thanks to Lars Bertram
- clipDepth = (UNITY_NEAR_CLIP_VALUE < 0) ? clipDepth * 2 - 1 : clipDepth;
- float4 clipPos = float4(uvClip, clipDepth, 1.0);
- float4 viewPos = mul(proj, clipPos); // inverse projection by clip position
- viewPos /= viewPos.w; // perspective division
- float3 wpos = mul(eyeToWorld, viewPos).xyz;
-
- float3 rayStart = _WorldSpaceCameraPos;
- float3 rayDir = wpos - _WorldSpaceCameraPos;
- //rayDir *= linearDepth;
- float rayLength = length(rayDir);
- rayDir /= rayLength;
- rayLength = min(rayLength, _MaxRayLength);
- float4 color = RayMarch(uv, i.position.xy, rayStart, rayDir, rayLength, linearDepth);
- return color;
- }
- ENDHLSL
- }
- }
- }
|