123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- #ifndef VOLUMETRIC_FOG_2_RAYMARCH
- #define VOLUMETRIC_FOG_2_RAYMARCH
- sampler2D _MainTex;
- sampler3D _DetailTex;
- float jitter;
- float _NoiseScale;
- half4 _Color;
- float3 _SunDir;
- half _DeepObscurance;
- half _LightDiffusionIntensity, _LightDiffusionPower;
- float3 _WindDirection, _DetailWindDirection;
- half4 _LightColor;
- half _Density;
- half3 _ShadowData;
- #define SHADOW_INTENSITY _ShadowData.x
- #define SHADOW_CANCELLATION _ShadowData.y
- #define SHADOW_MAX_DISTANCE _ShadowData.z
- float3 _MaxDistanceData;
- #define FOG_MAX_LENGTH _MaxDistanceData.x
- #define FOG_MAX_LENGTH_FALLOFF_PRECOMPUTED _MaxDistanceData.y
- #define FOG_MAX_LENGTH_FALLOFF _MaxDistanceData.z
- float4 _BoundsBorder;
- #define BORDER_SIZE_SPHERE _BoundsBorder.x
- #define BORDER_START_SPHERE _BoundsBorder.y
- #define BORDER_SIZE_BOX _BoundsBorder.xz
- #define BORDER_START_BOX _BoundsBorder.yw
- float3 _BoundsData;
- #define BOUNDS_VERTICAL_OFFSET _BoundsData.x
- #define BOUNDS_BOTTOM _BoundsData.y
- #define BOUNDS_SIZE_Y _BoundsData.z
- half4 _DetailData; // x = strength, y = offset, z = scale, w = importance
- half4 _DetailColor;
- #define DETAIL_STRENGTH _DetailData.x
- #define DETAIL_OFFSET _DetailData.y
- #define DETAIL_SCALE _DetailData.z
- #define USE_BASE_NOISE _DetailData.w
- float4 _RayMarchSettings;
-
- #define FOG_STEPPING _RayMarchSettings.x
- #define DITHERING _RayMarchSettings.y
- #define JITTERING _RayMarchSettings.z
- #define MIN_STEPPING _RayMarchSettings.w
- float loop_t;
- #include "PointLights.cginc"
- #include "FogVoids.cginc"
- #include "FogOfWar.cginc"
- #include "FogDistance.cginc"
- #include "Surface.cginc"
- TEXTURE2D(_BlueNoise);
- SAMPLER(sampler_BlueNoise_PointRepeat);
- float4 _BlueNoise_TexelSize;
- float3 _VFRTSize;
- float2 uvScreen;
- void SetJitter(float4 scrPos) {
- float2 screenSize = lerp(_ScreenParams.xy, _VFRTSize.xy, _VFRTSize.z);
- uvScreen = scrPos.xy / scrPos.w;
- float2 uv = uvScreen * screenSize;
- #if defined(FOG_BLUE_NOISE)
- float2 noiseUV = uv * _BlueNoise_TexelSize.xy;
- jitter = SAMPLE_TEXTURE2D(_BlueNoise, sampler_BlueNoise_PointRepeat, noiseUV).r;
- #else
- //Jitter = frac(dot(float2(2.4084507, 3.2535211), (scrPos.xy / scrPos.w) * _ScreenParams.xy));
- const float3 magic = float3( 0.06711056, 0.00583715, 52.9829189 );
- jitter = frac( magic.z * frac( dot( uv, magic.xy ) ) );
- #endif
- }
- inline float3 ProjectOnPlane(float3 v, float3 planeNormal) {
- float sqrMag = dot(planeNormal, planeNormal);
- float dt = dot(v, planeNormal);
- return v - planeNormal * dt / sqrMag;
- }
- inline float3 GetRayStart(float3 wpos) {
- float3 cameraPosition = GetCameraPositionWS();
- #if defined(ORTHO_SUPPORT)
- float3 cameraForward = UNITY_MATRIX_V[2].xyz;
- float3 rayStart = ProjectOnPlane(wpos - cameraPosition, cameraForward) + cameraPosition;
- return lerp(cameraPosition, rayStart, unity_OrthoParams.w);
- #else
- return cameraPosition;
- #endif
- }
- inline half Brightness(half3 color) {
- return max(color.r, max(color.g, color.b));
- }
- half4 SampleDensity(float3 wpos) {
- wpos.y -= BOUNDS_VERTICAL_OFFSET;
- float3 boundsCenter = _BoundsCenter;
- float3 boundsExtents = _BoundsExtents;
- SurfaceApply(boundsCenter, boundsExtents);
- #if VF2_DETAIL_NOISE
- #if !defined(USE_WORLD_SPACE_NOISE)
- wpos.xyz -= boundsCenter;
- #endif
- half detail = tex3Dlod(_DetailTex, float4(wpos * DETAIL_SCALE - _DetailWindDirection, 0)).a;
- half4 density = _DetailColor;
- if (USE_BASE_NOISE) {
- #if defined(USE_WORLD_SPACE_NOISE)
- wpos.y -= boundsCenter.y;
- #endif
- wpos.y /= boundsExtents.y;
- density = tex2Dlod(_MainTex, float4(wpos.xz * _NoiseScale - _WindDirection.xz, 0, 0));
- density.a -= abs(wpos.y);
- }
- density.a += (detail + DETAIL_OFFSET) * DETAIL_STRENGTH;
- #else
- #if defined(USE_WORLD_SPACE_NOISE) || VF2_CONSTANT_DENSITY
- wpos.y -= boundsCenter.y;
- #else
- wpos.xyz -= boundsCenter;
- #endif
- wpos.y /= boundsExtents.y;
- #if VF2_CONSTANT_DENSITY
- half4 density = half4(_DetailColor.rgb, 1.0);
- #else
- half4 density = tex2Dlod(_MainTex, float4(wpos.xz * _NoiseScale - _WindDirection.xz, 0, 0));
- #endif
- density.a -= abs(wpos.y);
- #endif
- return density;
- }
- #define dot2(x) dot(x,x)
- void AddFog(float3 rayStart, float3 wpos, float rs, half4 baseColor, inout half4 sum) {
- half4 density = SampleDensity(wpos);
- float3 rotatedWPos = wpos;
- #if defined(FOG_ROTATION)
- rotatedWPos = Rotate(rotatedWPos);
- #endif
- #if VF2_VOIDS
- density.a -= ApplyFogVoids(rotatedWPos);
- #endif
- #if defined(FOG_BORDER)
- #if VF2_SHAPE_SPHERE
- float3 delta = wpos - _BoundsCenter;
- float distSqr = dot2(delta);
- float border = 1.0 - saturate( (distSqr - BORDER_START_SPHERE) / BORDER_SIZE_SPHERE );
- density.a *= border * border;
- #else
- float2 dist2 = abs(wpos.xz - _BoundsCenter.xz);
- float2 border2 = saturate( (dist2 - BORDER_START_BOX) / BORDER_SIZE_BOX );
- float border = 1.0 - max(border2.x, border2.y);
- density.a *= border * border;
- #endif
- #endif
- if (density.a > 0) {
- half4 fgCol = baseColor * half4((1.0 - density.a * _DeepObscurance).xxx, density.a);
- #if VF2_RECEIVE_SHADOWS
- if (dot2(wpos - _WorldSpaceCameraPos) < SHADOW_MAX_DISTANCE) {
- half shadowAtten = GetLightAttenuation(rotatedWPos);
- fgCol.rgb *= lerp(1.0, shadowAtten, SHADOW_INTENSITY);
- #if defined(FOG_SHADOW_CANCELLATION)
- fgCol.a *= lerp(1.0, shadowAtten, SHADOW_CANCELLATION);
- #endif
- }
- #endif
- #if VF2_NATIVE_LIGHTS
- #if USE_FORWARD_PLUS && !defined(FOG_FORWARD_PLUS_IGNORE_CLUSTERING)
- // additional directional lights
- #if defined(FOG_FORWARD_PLUS_ADDITIONAL_DIRECTIONAL_LIGHTS)
- for (uint lightIndex = 0; lightIndex < URP_FP_DIRECTIONAL_LIGHTS_COUNT; lightIndex++) {
- Light light = GetAdditionalLight(lightIndex, rotatedWPos, 1.0.xxxx);
- fgCol.rgb += light.color * (light.distanceAttenuation * light.shadowAttenuation);
- }
- #endif
- // clustered lights
- {
- uint lightIndex;
- ClusterIterator _urp_internal_clusterIterator = ClusterInit(uvScreen, rotatedWPos, 0);
- [loop] while (ClusterNext(_urp_internal_clusterIterator, lightIndex)) {
- lightIndex += URP_FP_DIRECTIONAL_LIGHTS_COUNT;
- Light light = GetAdditionalLight(lightIndex, rotatedWPos, 1.0.xxxx);
- fgCol.rgb += light.color * (light.distanceAttenuation * light.shadowAttenuation);
- }
- }
- #else
- #if USE_FORWARD_PLUS
- uint additionalLightCount = min(URP_FP_PROBES_BEGIN, 8); // more than 8 lights is too slow for raymarching
- #else
- uint additionalLightCount = GetAdditionalLightsCount();
- #endif
- for (uint i = 0; i < additionalLightCount; ++i) {
- #if UNITY_VERSION >= 202030
- Light light = GetAdditionalLight(i, rotatedWPos, 1.0.xxxx);
- #else
- Light light = GetAdditionalLight(i, rotatedWPos);
- #endif
- fgCol.rgb += light.color * (light.distanceAttenuation * light.shadowAttenuation);
- }
- #endif
- #endif
- #if VF2_LIGHT_COOKIE
- half3 cookieColor = SampleMainLightCookie(wpos);
- fgCol.rgb *= cookieColor;
- #if defined(V2F_LIGHT_COOKIE_CANCELLATION)
- fgCol.a *= Brightness(cookieColor);
- #endif
- #endif
- #if VF2_DEPTH_GRADIENT
- fgCol *= ApplyDepthGradient(rayStart, wpos);
- #endif
- #if VF2_HEIGHT_GRADIENT
- fgCol *= ApplyHeightGradient(wpos);
- #endif
- fgCol.rgb *= density.rgb * fgCol.aaa;
- #if VF2_FOW
- fgCol *= ApplyFogOfWar(rotatedWPos);
- #endif
- #if VF2_DISTANCE
- fgCol *= ApplyFogDistance(rayStart, wpos);
- #endif
- fgCol *= min(1.0, _Density * rs);
- sum += fgCol * (1.0 - sum.a);
- }
- }
- half GetDiffusionIntensity(float3 viewDir) {
- return pow(max(dot(viewDir, _SunDir.xyz), 0), _LightDiffusionPower) * _LightDiffusionIntensity;
- }
- half3 GetDiffusionColor(float3 viewDir) {
- half diffusion = 1.0 + GetDiffusionIntensity(viewDir);
- half3 diffusionColor = _LightColor.rgb * diffusion;
- return diffusionColor;
- }
- half4 GetFogColor(float3 rayStart, float3 viewDir, float t0, float t1) {
- t0 = min(t0 + jitter * JITTERING, t1);
- float len = t1 - t0;
- float rs = MIN_STEPPING + max(log(len), 0) / FOG_STEPPING; // stepping ratio with atten detail with distance
- half4 sum = half4(0,0,0,0);
- half3 diffusionColor = GetDiffusionColor(viewDir);
- half4 lightColor = half4(diffusionColor, 1.0);
- float3 wpos = rayStart + viewDir * t0;
- float3 endPos = rayStart + viewDir * t1;
- SurfaceComputeEndPoints(wpos, endPos);
- rs = max(rs, 1.0 / MAX_ITERATIONS);
- viewDir *= rs;
- float energyStep = rs;
- rs /= len + 0.001;
-
- float t = 0;
- // Use this Unroll macro to support WebGL. Increase 50 value if needed.
- #if defined(WEBGL_COMPATIBILITY_MODE)
- UNITY_UNROLLX(50)
- #elif VF2_LIGHT_COOKIE
- UNITY_LOOP
- #endif
- while (t < 1.0) {
- loop_t = t;
- AddFog(rayStart, wpos, energyStep, lightColor, sum);
- if (sum.a > 0.99) {
- sum.a = 1.0;
- return sum;
- }
- t += rs;
- wpos += viewDir;
- }
- AddFog(rayStart, endPos, len * (rs - (t-1.0)), lightColor, sum);
- return sum;
- }
- #endif // VOLUMETRIC_FOG_2_RAYMARCH
|