VisualizeSDF.shader 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. Shader "Hidden/ZibraEffects/Liquid/VisualizeSDF"
  2. {
  3. SubShader
  4. {
  5. Pass
  6. {
  7. Cull Off
  8. ZWrite Off
  9. ZTest Always
  10. HLSLPROGRAM
  11. #pragma multi_compile_local __ HDRP
  12. #pragma instancing_options procedural:setup
  13. #pragma vertex VSMain
  14. #pragma fragment PSMain
  15. #pragma target 3.5
  16. #include "UnityCG.cginc"
  17. #include "UnityStandardBRDF.cginc"
  18. #include "UnityImageBasedLighting.cginc"
  19. #define MAX_VIEWING_DISTANCE 1e8
  20. #ifdef HDRP
  21. float3 LightDirection;
  22. #endif
  23. struct VSIn
  24. {
  25. uint vertexID : SV_VertexID;
  26. };
  27. struct VSOut
  28. {
  29. float4 position : POSITION;
  30. float3 raydir : TEXCOORD1;
  31. float2 uv : TEXCOORD0;
  32. };
  33. struct PSOut
  34. {
  35. float4 color : COLOR;
  36. };
  37. float4x4 EyeRayCameraCoeficients;
  38. float2 TextureScale;
  39. sampler2D SDFRender;
  40. // built-in Unity sampler name - do not change
  41. sampler2D _CameraDepthTexture;
  42. float2 GetFlippedUV(float2 uv)
  43. {
  44. if (_ProjectionParams.x > 0)
  45. return float2(uv.x, 1 - uv.y);
  46. return uv;
  47. }
  48. // See Raytracing Gems 1 chapter 20.3.2.1
  49. float3 GetCameraRay(float2 uv)
  50. {
  51. float2 c = float2(2.0f * uv.x - 1.0f, -2.0f * uv.y + 1.0f);
  52. float3 r = EyeRayCameraCoeficients[0].xyz;
  53. float3 u = EyeRayCameraCoeficients[1].xyz;
  54. float3 v = EyeRayCameraCoeficients[2].xyz;
  55. float3 direction = c.x * r + c.y * u + v;
  56. return normalize(direction);
  57. }
  58. VSOut VSMain(VSIn input)
  59. {
  60. VSOut output;
  61. float2 vertexBuffer[4] = {
  62. float2(0.0f, 0.0f),
  63. float2(0.0f, 1.0f),
  64. float2(1.0f, 0.0f),
  65. float2(1.0f, 1.0f),
  66. };
  67. uint indexBuffer[6] = { 0, 1, 2, 2, 1, 3 };
  68. uint indexID = indexBuffer[input.vertexID];
  69. float2 uv = vertexBuffer[indexID];
  70. float2 flippedUV = GetFlippedUV(uv);
  71. output.position = float4(2 * flippedUV.x - 1, 1 - 2 * flippedUV.y, 0.5, 1.0);
  72. output.uv = flippedUV;
  73. output.raydir = GetCameraRay(uv);
  74. return output;
  75. }
  76. float PositionToDepth(float3 pos)
  77. {
  78. float4 clipPos = mul(UNITY_MATRIX_VP, float4(pos, 1));
  79. return (1.0 / clipPos.w - _ZBufferParams.w) / _ZBufferParams.z; //inverse of linearEyeDepth
  80. }
  81. float4 RenderSDFSurface(float3 cameraPos, float3 cameraRay, float2 uv)
  82. {
  83. float4 sdfout = tex2D(SDFRender, GetFlippedUV(uv * TextureScale));
  84. float3 sdfPos = cameraPos + cameraRay * sdfout.w;
  85. float sdfDepth = PositionToDepth(sdfPos);
  86. if (sdfout.w < MAX_VIEWING_DISTANCE)
  87. {
  88. // lighting vectors:
  89. float3 worldView = -cameraRay;
  90. #ifdef HDRP
  91. float3 lightDirWorld = LightDirection;
  92. #else
  93. float3 lightDirWorld = normalize(_WorldSpaceLightPos0.xyz);
  94. #endif
  95. float3 normal = sdfout.xyz;
  96. half3 h = normalize(lightDirWorld + worldView);
  97. float nh = BlinnTerm(normal, h);
  98. float nl = DotClamped(normal, lightDirWorld);
  99. float nv = dot(normal, worldView);
  100. float rough = 0.55;
  101. half V = SmithBeckmannVisibilityTerm(nl, nv, rough);
  102. half D = NDFBlinnPhongNormalizedTerm(nh, RoughnessToSpecPower(rough));
  103. float spec = (V * D) * (UNITY_PI / 4);
  104. spec = max(0, spec * nl);
  105. return float4(spec + (normal*0.5 + 0.5)*(dot(lightDirWorld, normal)*0.5 + 0.5), sdfDepth);
  106. }
  107. return 0.0;
  108. }
  109. float4 MinIntersection(float4 a, float4 b)
  110. {
  111. return (a.w > b.w) ? a : b;
  112. }
  113. PSOut PSMain(VSOut input)
  114. {
  115. PSOut output;
  116. float sceneDepth = tex2D(_CameraDepthTexture, input.uv).x;
  117. #if !defined(UNITY_REVERSED_Z)
  118. sceneDepth = 1.0 - sceneDepth;
  119. #endif
  120. float3 cameraPos = _WorldSpaceCameraPos;
  121. float3 cameraRay = normalize(input.raydir);
  122. float4 intersection = RenderSDFSurface(cameraPos, cameraRay, input.uv);
  123. if (intersection.w == 0.0)
  124. {
  125. //didn't hit anything
  126. discard;
  127. }
  128. // Move visualization tiny bit closer to the camera
  129. // To reduce Z fighting
  130. const float depthOffset = 0.0001f;
  131. if (intersection.w + depthOffset < sceneDepth)
  132. {
  133. discard;
  134. }
  135. output.color = float4(intersection.rgb, 1.0);
  136. return output;
  137. }
  138. ENDHLSL
  139. }
  140. }
  141. }