SKYPRO_Renderer.hlsl 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. float2 rayBoxDst(float3 boundsMin, float3 boundsMax, float3 rayOrigin, float3 invRaydir)
  2. {
  3. float3 t0 = (boundsMin - rayOrigin) * invRaydir;
  4. float3 t1 = (boundsMax - rayOrigin) * invRaydir;
  5. float3 tmin = min(t0, t1);
  6. float3 tmax = max(t0, t1);
  7. float dstA = max(max(tmin.x, tmin.y), tmin.z);
  8. float dstB = min(tmax.x, min(tmax.y, tmax.z));
  9. float dstToBox = max(0, dstA);
  10. float dstInsideBox = max(0, dstB - dstToBox);
  11. return float2(dstToBox, dstInsideBox);
  12. }
  13. float3 GetRay_float(float2 screenPos)
  14. {
  15. float3 viewVector = mul(unity_CameraInvProjection, float4(screenPos * 2 - 1, 0, -1));
  16. float3 viewDir = mul(unity_CameraToWorld, float4(viewVector, 0));
  17. float viewLength = length(viewDir);
  18. float3 ray = viewDir / viewLength;
  19. return ray;
  20. }
  21. float3 GetShadows(float3 rayPos)
  22. {
  23. float ShadowAttenuation;
  24. float DistanceAttenuation;
  25. #ifdef SHADERGRAPH_PREVIEW
  26. ShadowAttenuation = 0.4;
  27. DistanceAttenuation = 0.4;
  28. #else
  29. #if SHADOWS_SCREEN
  30. half4 clipPos = TransformWorldToHClip(rayPos);
  31. half4 shadowCoord = ComputeScreenPos(clipPos);
  32. #else
  33. half4 shadowCoord = TransformWorldToShadowCoord(rayPos);
  34. #endif
  35. Light mainLight = GetMainLight(shadowCoord);
  36. DistanceAttenuation = mainLight.distanceAttenuation;
  37. ShadowAttenuation = mainLight.shadowAttenuation;
  38. #endif
  39. return ShadowAttenuation * DistanceAttenuation;
  40. }
  41. float3 GetLightDir_float()
  42. {
  43. float3 Direction;
  44. #ifdef SHADERGRAPH_PREVIEW
  45. Direction = float3(-0.5, 0.5, -0.5);
  46. #else
  47. Light mainLight = GetMainLight(float4(0, 0, 0, 0));
  48. Direction = mainLight.direction;
  49. #endif
  50. return Direction;
  51. }
  52. float random(float2 uv)
  53. {
  54. float rnd = frac(sin(dot(uv.xy, float2(12.9898, 78.233))) * 43758.5453123);
  55. return rnd;
  56. }
  57. float cellular(float2 uv, float columns, float rows)
  58. {
  59. float2 index_uv = floor(float2(uv.x * columns, uv.y * rows));
  60. float2 fract_uv = frac(float2(uv.x * columns, uv.y * rows));
  61. float minimum_dist = 1.0;
  62. [unroll]
  63. for (int y = -1; y <= 1; y++)
  64. {
  65. for (int x = -1; x <= 1; x++)
  66. {
  67. float2 neighbor = float2(float(x), float(y));
  68. float2 _point = random(index_uv + neighbor);
  69. float2 diff = neighbor + _point - fract_uv;
  70. float dist = length(diff);
  71. minimum_dist = min(minimum_dist, dist);
  72. }
  73. }
  74. return minimum_dist;
  75. }
  76. float SampleDensity_float(float density, float3 rayPos, SamplerState _sampler, texture2D noiseTexture, float tiling, float offset, float thicknessMin, float thicknessMax, float3 pos, float3 bounds)
  77. {
  78. if (thicknessMin > 0)
  79. {
  80. offset /= 10;
  81. float2 noiseUV = rayPos.xz;
  82. float _noise = SAMPLE_TEXTURE2D_LOD(noiseTexture, _sampler, (noiseUV + (offset * 200)) / (tiling * 25), 0).x;
  83. float noise = 0;
  84. noise += cellular(noiseUV / tiling / 0.7, 5, 5) / 2;
  85. noise += cellular(noiseUV / tiling / 2, 5, 5);
  86. noise /= 1.5;
  87. noise += _noise * 4;
  88. noise /= 5;
  89. float distToEdge = abs(rayPos.y - pos.y) / bounds.y;
  90. float minEdge = thicknessMin * (1 - distToEdge);
  91. return clamp(density * smoothstep(noise, minEdge + thicknessMax, minEdge), 0, 1);
  92. }
  93. else
  94. {
  95. return density;
  96. }
  97. }
  98. float map01_float(float value)
  99. {
  100. value += 1;
  101. value = 1 / value;
  102. value = 1 - value;
  103. value = pow(value, 5);
  104. return value;
  105. }
  106. float DensityLighting_float(float3 rayPos, float lightingSteps, bool directionalLighting, float density, SamplerState _sampler, texture2D noiseTexture, float tiling, float offset, float thicknessMin, float thicknessMax, float3 pos, float3 bounds, bool useSphereMask, float sphereMaskRadius, float3 sphereMaskPos, float farPlane)
  107. {
  108. float3 posBL = pos - bounds / 2;
  109. float3 posTR = pos + bounds / 2;
  110. float lighting;
  111. float3 cumulativeRayPos = rayPos;
  112. float cumulativeDensity = 0;
  113. lighting = 1;
  114. float3 dirToLight = GetLightDir_float();
  115. float lightDist = rayBoxDst(posBL, posTR, rayPos, 1 / dirToLight).y;
  116. for (int i = 0; i < lightingSteps; i++)
  117. {
  118. float _stepSize = lightDist / lightingSteps;
  119. cumulativeRayPos += dirToLight * _stepSize;
  120. if ((useSphereMask && distance(cumulativeRayPos, sphereMaskPos) < sphereMaskRadius) || !useSphereMask)
  121. {
  122. float pointDensity = SampleDensity_float(density, cumulativeRayPos, _sampler, noiseTexture, tiling, offset, thicknessMin, thicknessMax, pos, bounds);
  123. cumulativeDensity += pointDensity * _stepSize;
  124. lighting *= 1 - exp(-cumulativeDensity);
  125. }
  126. }
  127. return lighting;
  128. }
  129. float SunHighlight(float3 rayDir)
  130. {
  131. float fade = dot(GetLightDir_float(), float3(0, -1, 0));
  132. fade = max(fade, 0);
  133. fade = pow(1 - fade, 50);
  134. float phase = dot(GetLightDir_float(), rayDir);
  135. phase += 1;
  136. phase /= 2;
  137. phase = pow(phase, 25) * 25;
  138. return (phase * fade) + 1;
  139. }
  140. void RenderVolume_float(float3 pos, float3 bounds, float3 sphereMaskPos, float sphereMaskRadius, bool useSphereMask, float3 worldPos, float2 screenPos, float depth, float density, float densityStrength, float steps, float stepSize, float lightingSteps, bool directionalLighting, SamplerState _sampler, texture2D noiseTexture, float tiling, float offset, float thicknessMin, float thicknessMax, float farPlane, out float volumeDensity, out float3 lighting, out float distInBox, out float distToBox, out float distToLight, out float linearDepth, out float3 rayPos)
  141. {
  142. float3 posBL = pos - bounds / 2;
  143. float3 posTR = pos + bounds / 2;
  144. float3 viewVector = mul(unity_CameraInvProjection, float4(screenPos * 2 - 1, 0, -1));
  145. float3 viewDir = mul(unity_CameraToWorld, float4(viewVector, 0));
  146. float viewLength = length(viewDir);
  147. float3 ray = GetRay_float(screenPos);
  148. float2 boxDist = rayBoxDst(posBL, posTR, _WorldSpaceCameraPos, 1 / ray);
  149. distToBox = boxDist.x;
  150. distInBox = boxDist.y;
  151. float3 entryPoint = _WorldSpaceCameraPos + ray * distToBox;
  152. rayPos = entryPoint + ray * viewLength;
  153. linearDepth = depth * length(viewDir);
  154. //Density
  155. float shadowMap = 0;
  156. float distTravelled = 0;
  157. float cumulativeDensity = 0;
  158. float3 cumulativeRayPos = rayPos;
  159. float transmittance = 1;
  160. for (int j = 0; j < steps && distTravelled < distInBox && distTravelled + distToBox < linearDepth; j++)
  161. {
  162. cumulativeRayPos += ray * stepSize;
  163. distTravelled += stepSize;
  164. if ((useSphereMask && distance(cumulativeRayPos, sphereMaskPos) < sphereMaskRadius) || !useSphereMask)
  165. {
  166. float pointDensity = SampleDensity_float(density, cumulativeRayPos, _sampler, noiseTexture, tiling, offset, thicknessMin, thicknessMax, pos, bounds);
  167. float cumDens = pointDensity * stepSize;
  168. cumulativeDensity += cumDens * densityStrength;
  169. if (lightingSteps > 0)
  170. {
  171. float lightingAtPoint = DensityLighting_float(cumulativeRayPos, lightingSteps, directionalLighting, density, _sampler, noiseTexture, tiling, offset, thicknessMin, thicknessMax, pos, bounds, useSphereMask, sphereMaskRadius, sphereMaskPos, farPlane);
  172. #ifdef MAIN_LIGHT_CALCULATE_SHADOWS
  173. float shadows = (1 - GetShadows(cumulativeRayPos));
  174. #else
  175. float shadows = 0;
  176. #endif
  177. shadowMap += shadows;
  178. float ambient = exp(-cumDens);
  179. transmittance *= exp(-cumDens * pow(exp(-ambient), 3));
  180. if (transmittance < 0.01 || exp(exp(-ambient)) < 0.1)
  181. {
  182. break;
  183. }
  184. lighting += lightingAtPoint * transmittance * pow(exp(-ambient), 2);
  185. }
  186. else
  187. {
  188. lighting += 1;
  189. }
  190. }
  191. }
  192. cumulativeDensity = map01_float(cumulativeDensity);
  193. lighting = exp(-lighting) * SunHighlight(ray);
  194. lighting = clamp(lighting, 0, 5);
  195. #ifdef SHADERGRAPH_PREVIEW
  196. distToLight = 1000;
  197. #else
  198. distToLight = length(_MainLightPosition + _WorldSpaceCameraPos - rayPos);
  199. #endif
  200. #ifdef MAIN_LIGHT_CALCULATE_SHADOWS
  201. lighting += ((1 - clamp(shadowMap, 0, 1)) - 0.3);
  202. #endif
  203. volumeDensity = cumulativeDensity;
  204. if (distToBox > linearDepth)
  205. {
  206. distInBox = 0;
  207. volumeDensity = 0;
  208. lighting = 0;
  209. }
  210. if (distInBox + distToBox > linearDepth)
  211. {
  212. distInBox = linearDepth - distToBox;
  213. }
  214. }