FogInclude.cginc 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  1. #include "SkyInclude.cginc"
  2. //UNITY_DECLARE_SCREENSPACE_TEXTURE(_EnviroVolumetricFogTex);
  3. #if defined(UNITY_STEREO_INSTANCING_ENABLED) || defined(UNITY_STEREO_MULTIVIEW_ENABLED)
  4. UNITY_DECLARE_TEX2DARRAY(_EnviroVolumetricFogTex);
  5. #else
  6. sampler2D _EnviroVolumetricFogTex;
  7. #endif
  8. float4 _EnviroVolumetricFogTex_TexelSize;
  9. float4 _Screen_TexelSize;
  10. uniform float4 _EnviroFogParameters; //x = rayorigin1, y = falloff1, z = density1, w = height1
  11. uniform float4 _EnviroFogParameters2; //x = rayorigin2, y = falloff2, z = density2, w = height2
  12. uniform float4 _EnviroFogParameters3; //x = maxDensity, y = startDistance, z = , w = sky blend
  13. uniform float4 _EnviroFogColor; //Fog color
  14. uniform float4 _EnviroDirLightColor;
  15. #if defined(SHADER_API_D3D11) || defined(SHADER_API_METAL) || defined(SHADER_API_VULKAN)
  16. struct EllipsZones
  17. {
  18. float3 pos;
  19. float radius;
  20. float3 axis;
  21. float stretch;
  22. float density;
  23. float feather;
  24. float padding1;
  25. float padding2;
  26. };
  27. StructuredBuffer<EllipsZones> _EllipsZones;
  28. float _EllipsZonesCount;
  29. #endif
  30. int ihash(int n)
  31. {
  32. n = (n<<13)^n;
  33. return (n*(n*n*15731+789221)+1376312589) & 2147483647;
  34. }
  35. float frand(int n)
  36. {
  37. return ihash(n) / 2147483647.0;
  38. }
  39. float2 cellNoise(int2 p)
  40. {
  41. int i = p.y*256 + p.x;
  42. return float2(frand(i), frand(i + 57)) - 0.5;//*2.0-1.0;
  43. }
  44. float Pow2(float x)
  45. {
  46. return x * x;
  47. }
  48. // Calculate the line integral of the ray from the camera to the receiver position through the fog density function
  49. // The exponential fog density function is d = GlobalDensity * exp(-HeightFalloff * y)
  50. float CalculateLineIntegralShared(float FogHeightFalloff, float RayDirectionY, float RayOriginTerms)
  51. {
  52. float Falloff = max(-127.0f, FogHeightFalloff * RayDirectionY); // if it's lower than -127.0, then exp2() goes crazy in OpenGL's GLSL.
  53. float LineIntegral = (1.0f - exp2(-Falloff)) / Falloff;
  54. float LineIntegralTaylor = log(2.0) - (0.5 * Pow2(log(2.0))) * Falloff; // Taylor expansion around 0
  55. return RayOriginTerms * (abs(Falloff) > 0.01f ? LineIntegral : LineIntegralTaylor);
  56. }
  57. #if defined(SHADER_API_D3D11) || defined(SHADER_API_METAL) || defined(SHADER_API_VULKAN)
  58. void FogZones(float3 pos, inout float density)
  59. {
  60. for (int i = 0; i < _EllipsZonesCount; i++)
  61. {
  62. float3 dir = _EllipsZones[i].pos - pos;
  63. float3 axis = _EllipsZones[i].axis;
  64. float3 dirAlongAxis = dot(dir, axis) * axis;
  65. //float scrollNoise = ScrollNoise(dir, _EllipsZones[i].noiseSpeed, _EllipsZones[i].noiseScale, axis, _EllipsZones[i].noiseAmount);
  66. dir = dir + dirAlongAxis * _EllipsZones[i].stretch;
  67. float distsq = dot(dir, dir);
  68. float radius = _EllipsZones[i].radius;
  69. float feather = _EllipsZones[i].feather;
  70. // float feather = 0.3;
  71. feather = (1.0 - smoothstep (radius * feather, radius, distsq));
  72. float contribution = feather * _EllipsZones[i].density;
  73. density = density + contribution;
  74. }
  75. }
  76. #endif
  77. half4 GetExponentialHeightFog(float3 wPos, float linearDepth)
  78. {
  79. const half MinFogOpacity = _EnviroFogParameters3.x;
  80. //Receiver
  81. float3 CameraToReceiver = wPos - _WorldSpaceCameraPos.xyz;
  82. float3 viewDirection = CameraToReceiver;
  83. float viewLength = length(viewDirection);
  84. viewDirection /= viewLength;
  85. float CameraToReceiverLengthSqr = dot(CameraToReceiver, CameraToReceiver);
  86. float CameraToReceiverLengthInv = rsqrt(CameraToReceiverLengthSqr);
  87. float CameraToReceiverLength = CameraToReceiverLengthSqr * CameraToReceiverLengthInv;
  88. half3 CameraToReceiverNormalized = CameraToReceiver * CameraToReceiverLengthInv;
  89. float RayOriginTerms = _EnviroFogParameters.x;
  90. float RayOriginTermsSecond = _EnviroFogParameters2.x;
  91. float RayLength = CameraToReceiverLength;
  92. float RayDirectionY = CameraToReceiver.y;
  93. // Factor in StartDistance
  94. float ExcludeDistance = _EnviroFogParameters3.y;
  95. if (ExcludeDistance > 0)
  96. {
  97. float ExcludeIntersectionTime = ExcludeDistance * CameraToReceiverLengthInv;
  98. float CameraToExclusionIntersectionY = ExcludeIntersectionTime * CameraToReceiver.y;
  99. float ExclusionIntersectionY = _WorldSpaceCameraPos.y + CameraToExclusionIntersectionY;
  100. float ExclusionIntersectionToReceiverY = CameraToReceiver.y - CameraToExclusionIntersectionY;
  101. RayLength = (1.0f - ExcludeIntersectionTime) * CameraToReceiverLength;
  102. RayDirectionY = ExclusionIntersectionToReceiverY;
  103. float Exponent = max(-127.0f, _EnviroFogParameters.y * (ExclusionIntersectionY - _EnviroFogParameters.w));
  104. RayOriginTerms = _EnviroFogParameters.z * exp2(-Exponent);
  105. float ExponentSecond = max(-127.0f, _EnviroFogParameters2.y * (ExclusionIntersectionY - _EnviroFogParameters2.w));
  106. RayOriginTermsSecond = _EnviroFogParameters2.z * exp2(-ExponentSecond);
  107. }
  108. // Calculate fog amount of both layers
  109. float fogAmount = (CalculateLineIntegralShared(_EnviroFogParameters.y, RayDirectionY, RayOriginTerms) + CalculateLineIntegralShared(_EnviroFogParameters2.y, RayDirectionY, RayOriginTermsSecond))* RayLength;
  110. //Fog Zones
  111. #if defined(SHADER_API_D3D11) || defined(SHADER_API_METAL) || defined(SHADER_API_VULKAN)
  112. FogZones(wPos,fogAmount);
  113. #endif
  114. // Calculate the amount of light that made it through the fog using the transmission equation
  115. float fogfactor = max(saturate(exp2(-fogAmount)), MinFogOpacity);
  116. // Color
  117. float4 sky = GetSkyColor(viewDirection,0.005f);
  118. float3 inscatterColor = lerp(_EnviroFogColor.rgb,sky.rgb,_EnviroFogParameters3.w);
  119. float3 fogColor = inscatterColor * (1 - fogfactor);
  120. return float4(fogColor, fogfactor);
  121. }
  122. float3 ApplyVolumetricLights(float4 fogColor, float3 sceneColor, float2 uv)
  123. {
  124. float4 volumeLightsSample = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_EnviroVolumetricFogTex, uv);
  125. //uvs += cellNoise(uvs.xy * _Screen_TexelSize.zw) * _VolumeScatter_TexelSize.xy * 0.8;
  126. float3 volumeLightsDirectional = volumeLightsSample.a * _EnviroDirLightColor.rgb;
  127. float3 volumeLights = volumeLightsSample.rgb;
  128. return (sceneColor.rgb * fogColor.a + fogColor.rgb * max(volumeLightsDirectional,0.75)) + volumeLights;
  129. }
  130. float3 ApplyFogAndVolumetricLights(float3 sceneColor, float2 uv, float3 wPos, float linearDepth)
  131. {
  132. float4 fog = GetExponentialHeightFog(wPos,linearDepth);
  133. return ApplyVolumetricLights(fog,sceneColor,uv);
  134. }