Raymarch2D.cginc 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. #ifndef VOLUMETRIC_FOG_2_RAYMARCH
  2. #define VOLUMETRIC_FOG_2_RAYMARCH
  3. sampler2D _MainTex;
  4. sampler3D _DetailTex;
  5. float jitter;
  6. float _NoiseScale;
  7. half4 _Color;
  8. float3 _SunDir;
  9. half _DeepObscurance;
  10. half _LightDiffusionIntensity, _LightDiffusionPower;
  11. float3 _WindDirection, _DetailWindDirection;
  12. half4 _LightColor;
  13. half _Density;
  14. half3 _ShadowData;
  15. #define SHADOW_INTENSITY _ShadowData.x
  16. #define SHADOW_CANCELLATION _ShadowData.y
  17. #define SHADOW_MAX_DISTANCE _ShadowData.z
  18. float3 _MaxDistanceData;
  19. #define FOG_MAX_LENGTH _MaxDistanceData.x
  20. #define FOG_MAX_LENGTH_FALLOFF_PRECOMPUTED _MaxDistanceData.y
  21. #define FOG_MAX_LENGTH_FALLOFF _MaxDistanceData.z
  22. float4 _BoundsBorder;
  23. #define BORDER_SIZE_SPHERE _BoundsBorder.x
  24. #define BORDER_START_SPHERE _BoundsBorder.y
  25. #define BORDER_SIZE_BOX _BoundsBorder.xz
  26. #define BORDER_START_BOX _BoundsBorder.yw
  27. float3 _BoundsData;
  28. #define BOUNDS_VERTICAL_OFFSET _BoundsData.x
  29. #define BOUNDS_BOTTOM _BoundsData.y
  30. #define BOUNDS_SIZE_Y _BoundsData.z
  31. half4 _DetailData; // x = strength, y = offset, z = scale, w = importance
  32. half4 _DetailColor;
  33. #define DETAIL_STRENGTH _DetailData.x
  34. #define DETAIL_OFFSET _DetailData.y
  35. #define DETAIL_SCALE _DetailData.z
  36. #define USE_BASE_NOISE _DetailData.w
  37. float4 _RayMarchSettings;
  38. #define FOG_STEPPING _RayMarchSettings.x
  39. #define DITHERING _RayMarchSettings.y
  40. #define JITTERING _RayMarchSettings.z
  41. #define MIN_STEPPING _RayMarchSettings.w
  42. float loop_t;
  43. #include "PointLights.cginc"
  44. #include "FogVoids.cginc"
  45. #include "FogOfWar.cginc"
  46. #include "FogDistance.cginc"
  47. #include "Surface.cginc"
  48. TEXTURE2D(_BlueNoise);
  49. SAMPLER(sampler_BlueNoise_PointRepeat);
  50. float4 _BlueNoise_TexelSize;
  51. float3 _VFRTSize;
  52. float2 uvScreen;
  53. void SetJitter(float4 scrPos) {
  54. float2 screenSize = lerp(_ScreenParams.xy, _VFRTSize.xy, _VFRTSize.z);
  55. uvScreen = scrPos.xy / scrPos.w;
  56. float2 uv = uvScreen * screenSize;
  57. #if defined(FOG_BLUE_NOISE)
  58. float2 noiseUV = uv * _BlueNoise_TexelSize.xy;
  59. jitter = SAMPLE_TEXTURE2D(_BlueNoise, sampler_BlueNoise_PointRepeat, noiseUV).r;
  60. #else
  61. //Jitter = frac(dot(float2(2.4084507, 3.2535211), (scrPos.xy / scrPos.w) * _ScreenParams.xy));
  62. const float3 magic = float3( 0.06711056, 0.00583715, 52.9829189 );
  63. jitter = frac( magic.z * frac( dot( uv, magic.xy ) ) );
  64. #endif
  65. }
  66. inline float3 ProjectOnPlane(float3 v, float3 planeNormal) {
  67. float sqrMag = dot(planeNormal, planeNormal);
  68. float dt = dot(v, planeNormal);
  69. return v - planeNormal * dt / sqrMag;
  70. }
  71. inline float3 GetRayStart(float3 wpos) {
  72. float3 cameraPosition = GetCameraPositionWS();
  73. #if defined(ORTHO_SUPPORT)
  74. float3 cameraForward = UNITY_MATRIX_V[2].xyz;
  75. float3 rayStart = ProjectOnPlane(wpos - cameraPosition, cameraForward) + cameraPosition;
  76. return lerp(cameraPosition, rayStart, unity_OrthoParams.w);
  77. #else
  78. return cameraPosition;
  79. #endif
  80. }
  81. inline half Brightness(half3 color) {
  82. return max(color.r, max(color.g, color.b));
  83. }
  84. half4 SampleDensity(float3 wpos) {
  85. wpos.y -= BOUNDS_VERTICAL_OFFSET;
  86. float3 boundsCenter = _BoundsCenter;
  87. float3 boundsExtents = _BoundsExtents;
  88. SurfaceApply(boundsCenter, boundsExtents);
  89. #if VF2_DETAIL_NOISE
  90. #if !defined(USE_WORLD_SPACE_NOISE)
  91. wpos.xyz -= boundsCenter;
  92. #endif
  93. half detail = tex3Dlod(_DetailTex, float4(wpos * DETAIL_SCALE - _DetailWindDirection, 0)).a;
  94. half4 density = _DetailColor;
  95. if (USE_BASE_NOISE) {
  96. #if defined(USE_WORLD_SPACE_NOISE)
  97. wpos.y -= boundsCenter.y;
  98. #endif
  99. wpos.y /= boundsExtents.y;
  100. density = tex2Dlod(_MainTex, float4(wpos.xz * _NoiseScale - _WindDirection.xz, 0, 0));
  101. density.a -= abs(wpos.y);
  102. }
  103. density.a += (detail + DETAIL_OFFSET) * DETAIL_STRENGTH;
  104. #else
  105. #if defined(USE_WORLD_SPACE_NOISE) || VF2_CONSTANT_DENSITY
  106. wpos.y -= boundsCenter.y;
  107. #else
  108. wpos.xyz -= boundsCenter;
  109. #endif
  110. wpos.y /= boundsExtents.y;
  111. #if VF2_CONSTANT_DENSITY
  112. half4 density = half4(_DetailColor.rgb, 1.0);
  113. #else
  114. half4 density = tex2Dlod(_MainTex, float4(wpos.xz * _NoiseScale - _WindDirection.xz, 0, 0));
  115. #endif
  116. density.a -= abs(wpos.y);
  117. #endif
  118. return density;
  119. }
  120. #define dot2(x) dot(x,x)
  121. void AddFog(float3 rayStart, float3 wpos, float rs, half4 baseColor, inout half4 sum) {
  122. half4 density = SampleDensity(wpos);
  123. float3 rotatedWPos = wpos;
  124. #if defined(FOG_ROTATION)
  125. rotatedWPos = Rotate(rotatedWPos);
  126. #endif
  127. #if VF2_VOIDS
  128. density.a -= ApplyFogVoids(rotatedWPos);
  129. #endif
  130. #if defined(FOG_BORDER)
  131. #if VF2_SHAPE_SPHERE
  132. float3 delta = wpos - _BoundsCenter;
  133. float distSqr = dot2(delta);
  134. float border = 1.0 - saturate( (distSqr - BORDER_START_SPHERE) / BORDER_SIZE_SPHERE );
  135. density.a *= border * border;
  136. #else
  137. float2 dist2 = abs(wpos.xz - _BoundsCenter.xz);
  138. float2 border2 = saturate( (dist2 - BORDER_START_BOX) / BORDER_SIZE_BOX );
  139. float border = 1.0 - max(border2.x, border2.y);
  140. density.a *= border * border;
  141. #endif
  142. #endif
  143. if (density.a > 0) {
  144. half4 fgCol = baseColor * half4((1.0 - density.a * _DeepObscurance).xxx, density.a);
  145. #if VF2_RECEIVE_SHADOWS
  146. if (dot2(wpos - _WorldSpaceCameraPos) < SHADOW_MAX_DISTANCE) {
  147. half shadowAtten = GetLightAttenuation(rotatedWPos);
  148. fgCol.rgb *= lerp(1.0, shadowAtten, SHADOW_INTENSITY);
  149. #if defined(FOG_SHADOW_CANCELLATION)
  150. fgCol.a *= lerp(1.0, shadowAtten, SHADOW_CANCELLATION);
  151. #endif
  152. }
  153. #endif
  154. #if VF2_NATIVE_LIGHTS
  155. #if USE_FORWARD_PLUS && !defined(FOG_FORWARD_PLUS_IGNORE_CLUSTERING)
  156. // additional directional lights
  157. #if defined(FOG_FORWARD_PLUS_ADDITIONAL_DIRECTIONAL_LIGHTS)
  158. for (uint lightIndex = 0; lightIndex < URP_FP_DIRECTIONAL_LIGHTS_COUNT; lightIndex++) {
  159. Light light = GetAdditionalLight(lightIndex, rotatedWPos, 1.0.xxxx);
  160. fgCol.rgb += light.color * (light.distanceAttenuation * light.shadowAttenuation);
  161. }
  162. #endif
  163. // clustered lights
  164. {
  165. uint lightIndex;
  166. ClusterIterator _urp_internal_clusterIterator = ClusterInit(uvScreen, rotatedWPos, 0);
  167. [loop] while (ClusterNext(_urp_internal_clusterIterator, lightIndex)) {
  168. lightIndex += URP_FP_DIRECTIONAL_LIGHTS_COUNT;
  169. Light light = GetAdditionalLight(lightIndex, rotatedWPos, 1.0.xxxx);
  170. fgCol.rgb += light.color * (light.distanceAttenuation * light.shadowAttenuation);
  171. }
  172. }
  173. #else
  174. #if USE_FORWARD_PLUS
  175. uint additionalLightCount = min(URP_FP_PROBES_BEGIN, 8); // more than 8 lights is too slow for raymarching
  176. #else
  177. uint additionalLightCount = GetAdditionalLightsCount();
  178. #endif
  179. for (uint i = 0; i < additionalLightCount; ++i) {
  180. #if UNITY_VERSION >= 202030
  181. Light light = GetAdditionalLight(i, rotatedWPos, 1.0.xxxx);
  182. #else
  183. Light light = GetAdditionalLight(i, rotatedWPos);
  184. #endif
  185. fgCol.rgb += light.color * (light.distanceAttenuation * light.shadowAttenuation);
  186. }
  187. #endif
  188. #endif
  189. #if VF2_LIGHT_COOKIE
  190. half3 cookieColor = SampleMainLightCookie(wpos);
  191. fgCol.rgb *= cookieColor;
  192. #if defined(V2F_LIGHT_COOKIE_CANCELLATION)
  193. fgCol.a *= Brightness(cookieColor);
  194. #endif
  195. #endif
  196. #if VF2_DEPTH_GRADIENT
  197. fgCol *= ApplyDepthGradient(rayStart, wpos);
  198. #endif
  199. #if VF2_HEIGHT_GRADIENT
  200. fgCol *= ApplyHeightGradient(wpos);
  201. #endif
  202. fgCol.rgb *= density.rgb * fgCol.aaa;
  203. #if VF2_FOW
  204. fgCol *= ApplyFogOfWar(rotatedWPos);
  205. #endif
  206. #if VF2_DISTANCE
  207. fgCol *= ApplyFogDistance(rayStart, wpos);
  208. #endif
  209. fgCol *= min(1.0, _Density * rs);
  210. sum += fgCol * (1.0 - sum.a);
  211. }
  212. }
  213. half GetDiffusionIntensity(float3 viewDir) {
  214. return pow(max(dot(viewDir, _SunDir.xyz), 0), _LightDiffusionPower) * _LightDiffusionIntensity;
  215. }
  216. half3 GetDiffusionColor(float3 viewDir) {
  217. half diffusion = 1.0 + GetDiffusionIntensity(viewDir);
  218. half3 diffusionColor = _LightColor.rgb * diffusion;
  219. return diffusionColor;
  220. }
  221. half4 GetFogColor(float3 rayStart, float3 viewDir, float t0, float t1) {
  222. t0 = min(t0 + jitter * JITTERING, t1);
  223. float len = t1 - t0;
  224. float rs = MIN_STEPPING + max(log(len), 0) / FOG_STEPPING; // stepping ratio with atten detail with distance
  225. half4 sum = half4(0,0,0,0);
  226. half3 diffusionColor = GetDiffusionColor(viewDir);
  227. half4 lightColor = half4(diffusionColor, 1.0);
  228. float3 wpos = rayStart + viewDir * t0;
  229. float3 endPos = rayStart + viewDir * t1;
  230. SurfaceComputeEndPoints(wpos, endPos);
  231. rs = max(rs, 1.0 / MAX_ITERATIONS);
  232. viewDir *= rs;
  233. float energyStep = rs;
  234. rs /= len + 0.001;
  235. float t = 0;
  236. // Use this Unroll macro to support WebGL. Increase 50 value if needed.
  237. #if defined(WEBGL_COMPATIBILITY_MODE)
  238. UNITY_UNROLLX(50)
  239. #elif VF2_LIGHT_COOKIE
  240. UNITY_LOOP
  241. #endif
  242. while (t < 1.0) {
  243. loop_t = t;
  244. AddFog(rayStart, wpos, energyStep, lightColor, sum);
  245. if (sum.a > 0.99) {
  246. sum.a = 1.0;
  247. return sum;
  248. }
  249. t += rs;
  250. wpos += viewDir;
  251. }
  252. AddFog(rayStart, endPos, len * (rs - (t-1.0)), lightColor, sum);
  253. return sum;
  254. }
  255. #endif // VOLUMETRIC_FOG_2_RAYMARCH