SSR_GBuf_Pass.hlsl 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. #ifndef SSR_GBUF_PASS
  2. #define SSR_GBUF_PASS
  3. // Copyright 2021 Kronnect - All Rights Reserved.
  4. TEXTURE2D(_NoiseTex);
  5. float4 _NoiseTex_TexelSize;
  6. float4 _MaterialData;
  7. #define SMOOTHNESS _MaterialData.x
  8. #define FRESNEL _MaterialData.y
  9. #define FUZZYNESS _MaterialData.z
  10. #define DECAY _MaterialData.w
  11. float4 _SSRSettings;
  12. #define THICKNESS _SSRSettings.x
  13. #define SAMPLES _SSRSettings.y
  14. #define BINARY_SEARCH_ITERATIONS _SSRSettings.z
  15. #define MAX_RAY_LENGTH _SSRSettings.w
  16. #if SSR_THICKNESS_FINE
  17. float _SSRSettings5;
  18. #define THICKNESS_FINE _SSRSettings5
  19. #else
  20. #define THICKNESS_FINE THICKNESS
  21. #endif
  22. float4 _SSRSettings2;
  23. #define JITTER _SSRSettings2.x
  24. #define CONTACT_HARDENING _SSRSettings2.y
  25. float4 _SSRSettings3;
  26. #define INPUT_SIZE _SSRSettings3.xy
  27. #define GOLDEN_RATIO_ACUM _SSRSettings3.z
  28. #define DEPTH_BIAS _SSRSettings3.w
  29. float4x4 _WorldToViewDir;
  30. TEXTURE2D_X(_GBuffer2);
  31. struct AttributesFS {
  32. float4 positionHCS : POSITION;
  33. float4 uv : TEXCOORD0;
  34. UNITY_VERTEX_INPUT_INSTANCE_ID
  35. };
  36. struct VaryingsSSR {
  37. float4 positionCS : SV_POSITION;
  38. float4 uv : TEXCOORD0;
  39. UNITY_VERTEX_OUTPUT_STEREO
  40. };
  41. VaryingsSSR VertSSR(AttributesFS input) {
  42. VaryingsSSR output;
  43. UNITY_SETUP_INSTANCE_ID(input);
  44. UNITY_TRANSFER_INSTANCE_ID(input, output);
  45. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  46. output.positionCS = float4(input.positionHCS.xyz, 1.0);
  47. #if UNITY_UV_STARTS_AT_TOP
  48. output.positionCS.y *= -1;
  49. #endif
  50. output.uv = input.uv;
  51. float4 projPos = output.positionCS * 0.5;
  52. projPos.xy = projPos.xy + projPos.w;
  53. output.uv.zw = projPos.xy;
  54. return output;
  55. }
  56. inline float GetLinearDepth(float2 uv) {
  57. float rawDepth = SAMPLE_TEXTURE2D_X_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, SSRStereoTransformScreenSpaceTex(uv), 0).r;
  58. return LinearEyeDepth(rawDepth, _ZBufferParams);
  59. }
  60. float4 SSR_Pass(float2 uv, float3 normalVS, float3 rayStart, float smoothness) {
  61. float3 viewDirVS = normalize(rayStart);
  62. float3 rayDir = reflect( viewDirVS, normalVS );
  63. // if ray is toward the camera, early exit (optional)
  64. //if (rayDir.z < 0) return 0.0.xxxx;
  65. float rayLength = MAX_RAY_LENGTH;
  66. float3 rayEnd = rayStart + rayDir * rayLength;
  67. if (rayEnd.z < _ProjectionParams.y) {
  68. rayLength = (rayStart.z - _ProjectionParams.y) / rayDir.z;
  69. }
  70. rayEnd = rayStart + rayDir * rayLength;
  71. float4 sposStart = mul(unity_CameraProjection, float4(rayStart, 1.0));
  72. float4 sposEnd = mul(unity_CameraProjection, float4(rayEnd, 1.0));
  73. float k0 = rcp(sposStart.w);
  74. float q0 = rayStart.z * k0;
  75. float k1 = rcp(sposEnd.w);
  76. float q1 = rayEnd.z * k1;
  77. float4 p = float4(uv, q0, k0);
  78. // length in pixels
  79. float2 uv1 = (sposEnd.xy * rcp(rayEnd.z) + 1.0) * 0.5;
  80. float2 duv = uv1 - uv;
  81. float2 duvPixel = abs(duv * INPUT_SIZE);
  82. float pixelDistance = max(duvPixel.x, duvPixel.y);
  83. pixelDistance = max(1, pixelDistance);
  84. int sampleCount = (int)SAMPLES;
  85. float scale = max(1, SAMPLES * rcp(pixelDistance));
  86. sampleCount = (int)(sampleCount * rcp(scale));
  87. float4 pincr = float4(duv, q1-q0, k1-k0) * rcp(sampleCount);
  88. #if SSR_JITTER
  89. float jitter = SAMPLE_TEXTURE2D(_NoiseTex, sampler_PointRepeat, uv * INPUT_SIZE * _NoiseTex_TexelSize.xy + GOLDEN_RATIO_ACUM).r;
  90. pincr *= 1.0 + jitter * JITTER;
  91. p += pincr * (jitter * JITTER);
  92. #endif
  93. float collision = 0;
  94. float dist = 0;
  95. float zdist = 0;
  96. UNITY_LOOP
  97. for (int k = 0; k < sampleCount; k++) {
  98. p += pincr;
  99. if (any(floor(p.xy)!=0)) return 0.0.xxxx; // exit if out of screen space
  100. float sceneDepth = GetLinearDepth(p.xy);
  101. float pz = p.z / p.w;
  102. float depthDiff = pz - sceneDepth;
  103. if (depthDiff > 0 && depthDiff < THICKNESS) {
  104. float4 origPincr = pincr;
  105. p -= pincr;
  106. float reduction = 1.0;
  107. UNITY_LOOP
  108. for (int j = 0; j < BINARY_SEARCH_ITERATIONS; j++) {
  109. reduction *= 0.5;
  110. p += pincr * reduction;
  111. sceneDepth = GetLinearDepth(p.xy);
  112. pz = p.z / p.w;
  113. depthDiff = sceneDepth - pz;
  114. pincr = sign(depthDiff) * origPincr;
  115. }
  116. #if SSR_THICKNESS_FINE
  117. if (abs(depthDiff) < THICKNESS_FINE)
  118. #endif
  119. {
  120. float hitAccuracy = 1.0 - abs(depthDiff) / THICKNESS_FINE;
  121. zdist = (pz - rayStart.z) / (rayEnd.z - rayStart.z);
  122. float rayFade = 1.0 - saturate(zdist);
  123. collision = hitAccuracy * rayFade;
  124. break;
  125. }
  126. pincr = origPincr;
  127. p += pincr;
  128. }
  129. }
  130. if (collision > 0) {
  131. // intersection found
  132. float reflectionIntensity = smoothness * pow(collision, DECAY);
  133. // compute fresnel
  134. float fresnel = 1.0 - FRESNEL * abs(dot(normalVS, viewDirVS));
  135. float reflectionAmount = reflectionIntensity * fresnel;
  136. // compute blur amount
  137. float wdist = rayLength * zdist;
  138. float blurAmount = max(0, wdist - CONTACT_HARDENING) * FUZZYNESS * (1 - smoothness);
  139. // return hit pixel
  140. return float4(p.xy, blurAmount + 0.001, reflectionAmount);
  141. }
  142. return float4(0,0,0,0);
  143. }
  144. float4 FragSSR (VaryingsSSR input) : SV_Target {
  145. UNITY_SETUP_INSTANCE_ID(input);
  146. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  147. float depth = SAMPLE_TEXTURE2D_X(_CameraDepthTexture, sampler_PointClamp, input.uv.xy).r;
  148. #if UNITY_REVERSED_Z
  149. depth = 1.0 - depth;
  150. #endif
  151. if (depth >= 1.0) return float4(0,0,0,0);
  152. depth = 2.0 * depth - 1.0;
  153. float2 zw = SSRStereoTransformScreenSpaceTex(input.uv.zw);
  154. float3 positionVS = ComputeViewSpacePosition(zw, depth, unity_CameraInvProjection);
  155. float4 normals = SAMPLE_TEXTURE2D_X(_GBuffer2, sampler_PointClamp, SSRStereoTransformScreenSpaceTex(input.uv.xy));
  156. #if defined(_GBUFFER_NORMALS_OCT)
  157. half2 remappedOctNormalWS = Unpack888ToFloat2(normals.xyz); // values between [ 0, 1]
  158. half2 octNormalWS = remappedOctNormalWS.xy * 2.0h - 1.0h; // values between [-1, +1]
  159. float3 normalWS = UnpackNormalOctQuadEncode(octNormalWS);
  160. #else
  161. float3 normalWS = normals.xyz;
  162. #endif
  163. float3 normalVS = mul((float3x3)_WorldToViewDir, normalWS);
  164. normalVS.z *= -1.0;
  165. float smoothness = normals.w;
  166. float4 reflection = SSR_Pass(input.uv.xy, normalVS, positionVS, smoothness);
  167. return reflection;
  168. }
  169. #endif // SSR_GBUF_PASS