EnviroVolumetrics.shader 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. Shader "Hidden/Volumetrics"
  2. {
  3. Properties
  4. {
  5. _MainTex ("Texture", any) = "white" {}
  6. }
  7. SubShader
  8. {
  9. // No culling or depth
  10. Cull Off ZWrite Off ZTest Always
  11. Pass
  12. {
  13. CGPROGRAM
  14. #pragma vertex vert
  15. #pragma fragment frag
  16. #include "UnityCG.cginc"
  17. //#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
  18. //#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
  19. float4x4 _LeftWorldFromView;
  20. float4x4 _RightWorldFromView;
  21. float4x4 _LeftViewFromScreen;
  22. float4x4 _RightViewFromScreen;
  23. sampler2D _DitherTexture;
  24. UNITY_DECLARE_SHADOWMAP(_CascadeShadowMapTexture);
  25. //UNITY_DECLARE_SCREENSPACE_TEXTURE(_CloudsTex);
  26. UNITY_DECLARE_DEPTH_TEXTURE(_CameraDepthTexture);
  27. uniform sampler3D _NoiseTexture;
  28. uniform int _Steps;
  29. uniform float3 _CameraPosition;
  30. uniform float4 _VolumetricLight;
  31. uniform float4 _HeightFog;
  32. uniform float4 _HeightParams;
  33. uniform float4 _NoiseData;
  34. uniform float3 _WindDirection;
  35. uniform float4 _MieG;
  36. uniform float _MaxRayLength;
  37. uniform float4 _AmbientColor;
  38. uniform float3 _DirLightDir;
  39. //uniform float4 _DirLightColor;
  40. uniform float4 _Randomness;
  41. struct PointLight
  42. {
  43. float3 pos;
  44. float range;
  45. float3 color;
  46. float padding;
  47. };
  48. StructuredBuffer<PointLight> _PointLights;
  49. float _PointLightsCount;
  50. struct SpotLight
  51. {
  52. float3 pos;
  53. float range;
  54. float3 color;
  55. float3 lightDirection;
  56. float lightCosHalfAngle;
  57. //float2 angularFalloffParameters;
  58. //float2 distanceFalloffParameters;
  59. float padding;
  60. };
  61. StructuredBuffer<SpotLight> _SpotLights;
  62. float _SpotLightsCount;
  63. struct v2f
  64. {
  65. float2 uv : TEXCOORD0;
  66. float4 position : SV_POSITION;
  67. UNITY_VERTEX_OUTPUT_STEREO
  68. };
  69. v2f vert (appdata_img v)
  70. {
  71. v2f o;
  72. UNITY_SETUP_INSTANCE_ID(v);
  73. UNITY_INITIALIZE_OUTPUT(v2f, o);
  74. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
  75. o.position = UnityObjectToClipPos(v.vertex);
  76. //o.position = v.vertex * float4(2,2,1,1) + float4(-1,-1,0,0);
  77. o.uv = v.texcoord;
  78. return o;
  79. }
  80. float4 GetCascadeWeights_SplitSpheres(float3 wpos)
  81. {
  82. float3 fromCenter0 = wpos - unity_ShadowSplitSpheres[0].xyz;
  83. float3 fromCenter1 = wpos - unity_ShadowSplitSpheres[1].xyz;
  84. float3 fromCenter2 = wpos - unity_ShadowSplitSpheres[2].xyz;
  85. float3 fromCenter3 = wpos - unity_ShadowSplitSpheres[3].xyz;
  86. float4 distances2 = float4(dot(fromCenter0,fromCenter0), dot(fromCenter1,fromCenter1), dot(fromCenter2,fromCenter2), dot(fromCenter3,fromCenter3));
  87. float4 weights = float4(distances2 >= unity_ShadowSplitSqRadii);
  88. return weights;
  89. }
  90. float4 GetCascadeShadowCoord(float4 pos, float4 cascadeWeights)
  91. {
  92. return mul(unity_WorldToShadow[(int)dot(cascadeWeights, float4(1,1,1,1))], pos);
  93. }
  94. float anisotropy(float costheta)
  95. {
  96. float g = _MieG;
  97. float gsq = g*g;
  98. float denom = 1 + gsq - 2.0 * g * costheta;
  99. denom = denom * denom * denom;
  100. denom = sqrt(max(0, denom));
  101. return (1 - gsq) / denom;
  102. }
  103. float anisotropyPointSpot(float costheta)
  104. {
  105. float g = 0.8;
  106. float gsq = g*g;
  107. float denom = 1 + gsq - 2.0 * g * costheta;
  108. denom = denom * denom * denom;
  109. denom = sqrt(max(0, denom));
  110. return (1 - gsq) / denom;
  111. }
  112. float Attenuation(float distNorm)
  113. {
  114. return 1.0 / (1.0 + 25.0 * distNorm);
  115. }
  116. float DirectionalLight(float3 wpos)
  117. {
  118. float atten = 1.0f;
  119. float4 cascadeWeights = GetCascadeWeights_SplitSpheres(wpos);
  120. bool inside = dot(cascadeWeights, float4(1, 1, 1, 1)) < 4;
  121. float4 samplePos = GetCascadeShadowCoord(float4(wpos, 1), cascadeWeights);
  122. float shadows = UNITY_SAMPLE_SHADOW(_CascadeShadowMapTexture, samplePos.xyz).r;
  123. atten = inside ? shadows : 1.0f;
  124. if(shadows > 0.0f)
  125. atten = 1.0f;
  126. return atten;
  127. }
  128. float3 PointLights(float3 pos)
  129. {
  130. float3 color = 0;
  131. for (int i = 0; i < _PointLightsCount; i++)
  132. {
  133. float3 posToLight = _PointLights[i].pos - pos;
  134. float distNorm = dot(posToLight, posToLight) * _PointLights[i].range;
  135. float att = Attenuation(distNorm);
  136. //#if ANISOTROPY
  137. float3 cameraToPos = normalize(pos - _WorldSpaceCameraPos.xyz);
  138. float costheta = dot(cameraToPos, normalize(posToLight));
  139. att *= anisotropyPointSpot(costheta);
  140. //#endif
  141. color += _PointLights[i].color * att;
  142. }
  143. return color;
  144. }
  145. float3 SpotLights(float3 pos)
  146. {
  147. float3 color = 0;
  148. for (int i = 0; i < _SpotLightsCount; i++)
  149. {
  150. float3 posToLight = _SpotLights[i].pos - pos;
  151. float distNorm = dot(posToLight, posToLight) * _SpotLights[i].range;
  152. float att = Attenuation(distNorm);
  153. half3 lightVector = normalize(pos - _SpotLights[i].pos);
  154. half cosAngle = dot(_SpotLights[i].lightDirection.xyz, lightVector);
  155. half angleAttenuation = 1;
  156. angleAttenuation = smoothstep(_SpotLights[i].lightCosHalfAngle, lerp(1, _SpotLights[i].lightCosHalfAngle, 0.8f), cosAngle);
  157. angleAttenuation = pow(angleAttenuation, 2.0f);
  158. att *= angleAttenuation;
  159. #if ANISOTROPY
  160. float3 cameraToPos = normalize(pos - _CameraPos.xyz);
  161. float costheta = dot(cameraToPos, normalize(posToLight));
  162. att *= anisotropyPointSpot(costheta);
  163. #endif
  164. color += _SpotLights[i].color * att;
  165. }
  166. return color;
  167. }
  168. //-----------------------------------------------------------------------------------------
  169. // GetDensity
  170. //-----------------------------------------------------------------------------------------
  171. float GetDensity(float3 wpos, inout float density, float depth, float3 rayDir)
  172. {
  173. density = 1.0f;
  174. // #ifdef NOISE
  175. // float4 noise = tex3D(_NoiseTexture, frac(wpos * _NoiseData.x + float3(_Time.y * _WindDirection.x, 0, _Time.y * _WindDirection.y)));
  176. // float noiseFbm = (noise.g * 0.625) + (noise.b * 0.25) + (noise.a * 0.125);
  177. // noiseFbm = saturate(noiseFbm - _NoiseData.y);
  178. // density *= saturate(noiseFbm);
  179. // #endif
  180. return density;
  181. }
  182. float2 squareUV(float2 uv)
  183. {
  184. float width = _ScreenParams.x;
  185. float height =_ScreenParams.y;
  186. float scale = 1000;
  187. float x = uv.x * width;
  188. float y = uv.y * height;
  189. return float2 (x/scale, y/scale);
  190. }
  191. float4 RayMarch(float2 uv,float2 screenPos, float3 rayStart, float3 rayDir, float rayLength, float linearDepth)
  192. {
  193. float2 interleavedPos = (fmod(floor(screenPos.xy), 8.0));
  194. #if UNITY_SINGLE_PASS_STEREO
  195. float4 scaleOffset = unity_StereoScaleOffset[unity_StereoEyeIndex];
  196. interleavedPos = (interleavedPos - scaleOffset.zw) / scaleOffset.xy;
  197. #endif
  198. float offset = tex2D(_DitherTexture, interleavedPos / 8.0 + float2(0.5 / 8.0, 0.5 / 8.0)).w;
  199. //float offset = tex2D(_DitherTexture, squareUV(uv + _Randomness.xy)).x;
  200. int stepCount = _Steps;
  201. float stepSize = rayLength / stepCount;
  202. float3 step = rayDir * stepSize;
  203. float3 currentPositionDithered = rayStart + step * offset;
  204. float3 currentPosition = rayStart + step;
  205. float4 color = float4(0.0,0.0,0.0,0);
  206. float cosAngle;
  207. float extinction = 0;
  208. float transmitance = 0;
  209. float ambient = 0;
  210. cosAngle = dot(_DirLightDir.xyz, -rayDir);
  211. float ani = anisotropy(cosAngle);
  212. float4 lightsColor;
  213. [loop]
  214. for (int i = 0; i < stepCount; i++)
  215. {
  216. float density = GetDensity(currentPosition, density, linearDepth, rayDir);
  217. float atten = DirectionalLight(currentPositionDithered);
  218. //Cloud Shadows
  219. //float cloudShadows = UNITY_SAMPLE_SCREENSPACE_TEXTURE(_CloudsTex,uv).b;
  220. //atten *= (1-cloudShadows);
  221. float scattering = _VolumetricLight.x * density;
  222. extinction += _VolumetricLight.y * density;
  223. transmitance += atten * scattering * exp(-extinction);
  224. lightsColor.rgb += PointLights(currentPositionDithered) * density;
  225. lightsColor.rgb += SpotLights(currentPositionDithered) * density;
  226. currentPosition += step;
  227. currentPositionDithered += step;
  228. }
  229. //color.rgb = _DirLightColor.rgb * transmitance * ani;
  230. color.a = transmitance * ani;
  231. color.rgb += lightsColor.rgb;
  232. color = max(0, color);
  233. return color;
  234. }
  235. float4 frag (v2f i) : SV_Target
  236. {
  237. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);
  238. float2 uv = i.uv.xy;
  239. float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, uv);
  240. float linearDepth = Linear01Depth(depth);
  241. float4x4 proj, eyeToWorld;
  242. if (unity_StereoEyeIndex == 0)
  243. {
  244. proj = _LeftViewFromScreen;
  245. eyeToWorld = _LeftWorldFromView;
  246. }
  247. else
  248. {
  249. proj = _RightViewFromScreen;
  250. eyeToWorld = _RightWorldFromView;
  251. }
  252. //bit of matrix math to take the screen space coord (u,v,depth) and transform to world space
  253. float2 uvClip = i.uv * 2.0 - 1.0;
  254. float clipDepth = depth; // Fix for OpenGl Core thanks to Lars Bertram
  255. clipDepth = (UNITY_NEAR_CLIP_VALUE < 0) ? clipDepth * 2 - 1 : clipDepth;
  256. float4 clipPos = float4(uvClip, clipDepth, 1.0);
  257. float4 viewPos = mul(proj, clipPos); // inverse projection by clip position
  258. viewPos /= viewPos.w; // perspective division
  259. float3 wpos = mul(eyeToWorld, viewPos).xyz;
  260. float3 rayStart = _WorldSpaceCameraPos;
  261. float3 rayDir = wpos - _WorldSpaceCameraPos;
  262. //rayDir *= linearDepth;
  263. float rayLength = length(rayDir);
  264. rayDir /= rayLength;
  265. rayLength = min(rayLength, _MaxRayLength);
  266. float4 color = RayMarch(uv, i.position.xy, rayStart, rayDir, rayLength, linearDepth);
  267. return color;
  268. }
  269. ENDCG
  270. }
  271. }
  272. }