SSR_Surface_Pass.hlsl 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #ifndef SSR_SURF_FX
  2. #define SSR_SURF_FX
  3. // Copyright 2021 Kronnect - All Rights Reserved.
  4. TEXTURE2D(_NoiseTex);
  5. TEXTURE2D(_BumpMap);
  6. TEXTURE2D(_SmoothnessMap);
  7. float4 _BumpMap_ST;
  8. float4 _NoiseTex_TexelSize;
  9. float4 _MaterialData;
  10. #define SMOOTHNESS _MaterialData.x
  11. #define FRESNEL _MaterialData.y
  12. #define FUZZYNESS _MaterialData.z
  13. #define DECAY _MaterialData.w
  14. float4 _SSRSettings;
  15. #define THICKNESS _SSRSettings.x
  16. #define SAMPLES _SSRSettings.y
  17. #define BINARY_SEARCH_ITERATIONS _SSRSettings.z
  18. #define MAX_RAY_LENGTH _SSRSettings.w
  19. #if SSR_THICKNESS_FINE
  20. float _SSRSettings5;
  21. #define THICKNESS_FINE _SSRSettings5
  22. #else
  23. #define THICKNESS_FINE THICKNESS
  24. #endif
  25. float4 _SSRSettings2;
  26. #define JITTER _SSRSettings2.x
  27. #define CONTACT_HARDENING _SSRSettings2.y
  28. float4 _SSRSettings3;
  29. #define INPUT_SIZE _SSRSettings3.xy
  30. #define GOLDEN_RATIO_ACUM _SSRSettings3.z
  31. #define DEPTH_BIAS _SSRSettings3.w
  32. struct AttributesSurf {
  33. float4 positionOS : POSITION;
  34. float2 texcoord : TEXCOORD0;
  35. float3 normalOS : NORMAL;
  36. float4 tangentOS : TANGENT;
  37. UNITY_VERTEX_INPUT_INSTANCE_ID
  38. };
  39. struct VaryingsSSRSurf {
  40. float4 positionCS : SV_POSITION;
  41. float2 uv : TEXCOORD0;
  42. float4 scrPos : TEXCOORD1;
  43. float3 positionVS : TEXCOORD2;
  44. #if SSR_NORMALMAP
  45. float4 normal : TEXCOORD3; // xyz: normal, w: viewDir.x
  46. float4 tangent : TEXCOORD4; // xyz: tangent, w: viewDir.y
  47. float4 bitangent : TEXCOORD5; // xyz: bitangent, w: viewDir.z
  48. #else
  49. float3 normal : TEXCOORD3;
  50. #endif
  51. UNITY_VERTEX_INPUT_INSTANCE_ID
  52. UNITY_VERTEX_OUTPUT_STEREO
  53. };
  54. VaryingsSSRSurf VertSSRSurf(AttributesSurf input) {
  55. VaryingsSSRSurf output = (VaryingsSSRSurf)0;
  56. UNITY_SETUP_INSTANCE_ID(input);
  57. UNITY_TRANSFER_INSTANCE_ID(input, output);
  58. UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(output);
  59. VertexPositionInputs positions = GetVertexPositionInputs(input.positionOS.xyz);
  60. VertexNormalInputs normalInput = GetVertexNormalInputs(input.normalOS, input.tangentOS);
  61. output.positionCS = positions.positionCS;
  62. output.positionVS = positions.positionVS * float3(1,1,-1);
  63. output.scrPos = ComputeScreenPos(positions.positionCS);
  64. output.uv = TRANSFORM_TEX(input.texcoord, _BumpMap);
  65. #if SSR_NORMALMAP
  66. half3 viewDirWS = GetCameraPositionWS() - positions.positionWS;
  67. output.normal = half4(normalInput.normalWS, viewDirWS.x);
  68. output.tangent = half4(normalInput.tangentWS, viewDirWS.y);
  69. output.bitangent = half4(normalInput.bitangentWS, viewDirWS.z);
  70. #else
  71. output.normal = TransformWorldToViewDir(normalInput.normalWS) * float3(1,1,-1);
  72. #endif
  73. #if UNITY_REVERSED_Z
  74. output.positionCS.z += 0.001;
  75. #else
  76. output.positionCS.z -= 0.001;
  77. #endif
  78. return output;
  79. }
  80. inline float GetLinearDepth(float2 uv) {
  81. float rawDepth = SAMPLE_TEXTURE2D_X_LOD(_CameraDepthTexture, sampler_CameraDepthTexture, SSRStereoTransformScreenSpaceTex(uv), 0).r;
  82. return LinearEyeDepth(rawDepth, _ZBufferParams);
  83. }
  84. float4 SSR_Pass(float2 uv, float3 normalVS, float3 rayStart, float smoothness) {
  85. float3 viewDirVS = normalize(rayStart);
  86. float3 rayDir = reflect( viewDirVS, normalVS );
  87. // if ray is toward the camera, early exit (optional)
  88. //if (rayDir.z < 0) return 0.0.xxxx;
  89. float rayLength = MAX_RAY_LENGTH;
  90. float3 rayEnd = rayStart + rayDir * rayLength;
  91. if (rayEnd.z < _ProjectionParams.y) {
  92. rayLength = (rayStart.z - _ProjectionParams.y) / rayDir.z;
  93. }
  94. rayEnd = rayStart + rayDir * rayLength;
  95. float4 sposStart = mul(unity_CameraProjection, float4(rayStart, 1.0));
  96. float4 sposEnd = mul(unity_CameraProjection, float4(rayEnd, 1.0));
  97. float k0 = rcp(sposStart.w);
  98. float q0 = rayStart.z * k0;
  99. float k1 = rcp(sposEnd.w);
  100. float q1 = rayEnd.z * k1;
  101. float4 p = float4(uv, q0, k0);
  102. // depth clip check
  103. float sceneDepth = GetLinearDepth(p.xy);
  104. float pz = p.z / p.w;
  105. if (sceneDepth < pz - DEPTH_BIAS) return 0;
  106. // length in pixels
  107. float2 uv1 = (sposEnd.xy * rcp(rayEnd.z) + 1.0) * 0.5;
  108. float2 duv = uv1 - uv;
  109. float2 duvPixel = abs(duv * INPUT_SIZE);
  110. float pixelDistance = max(duvPixel.x, duvPixel.y);
  111. pixelDistance = max(1, pixelDistance);
  112. int sampleCount = (int)SAMPLES;
  113. float scale = max(1, SAMPLES * rcp(pixelDistance));
  114. sampleCount = (int)(sampleCount * rcp(scale));
  115. float4 pincr = float4(duv, q1-q0, k1-k0) * rcp(sampleCount);
  116. #if SSR_JITTER
  117. float jitter = SAMPLE_TEXTURE2D(_NoiseTex, sampler_PointRepeat, uv * INPUT_SIZE * _NoiseTex_TexelSize.xy + GOLDEN_RATIO_ACUM).r;
  118. //pincr *= 1.0 + jitter * JITTER;
  119. p += pincr * (jitter * JITTER);
  120. #endif
  121. float collision = 0;
  122. float dist = 0;
  123. float zdist = 0;
  124. UNITY_LOOP
  125. for (int k = 0; k < sampleCount; k++) {
  126. p += pincr;
  127. if (any(floor(p.xy)!=0)) return 0.0.xxxx; // exit if out of screen space
  128. sceneDepth = GetLinearDepth(p.xy);
  129. pz = p.z / p.w;
  130. float depthDiff = pz - sceneDepth;
  131. if (depthDiff > 0 && depthDiff < THICKNESS) {
  132. float4 origPincr = pincr;
  133. p -= pincr;
  134. float reduction = 1.0;
  135. UNITY_LOOP
  136. for (int j = 0; j < BINARY_SEARCH_ITERATIONS; j++) {
  137. reduction *= 0.5;
  138. p += pincr * reduction;
  139. sceneDepth = GetLinearDepth(p.xy);
  140. pz = p.z / p.w;
  141. depthDiff = sceneDepth - pz;
  142. pincr = sign(depthDiff) * origPincr;
  143. }
  144. #if SSR_THICKNESS_FINE
  145. if (abs(depthDiff) < THICKNESS_FINE)
  146. {
  147. #endif
  148. float hitAccuracy = 1.0 - abs(depthDiff) / THICKNESS_FINE;
  149. zdist = (pz - rayStart.z) / (rayEnd.z - rayStart.z);
  150. float rayFade = 1.0 - saturate(zdist);
  151. collision = hitAccuracy * rayFade;
  152. break;
  153. #if SSR_THICKNESS_FINE
  154. }
  155. pincr = origPincr;
  156. p += pincr;
  157. #endif
  158. }
  159. }
  160. if (collision > 0) {
  161. // intersection found
  162. float reflectionIntensity = smoothness * pow(collision, DECAY);
  163. // compute fresnel
  164. float fresnel = 1.0 - FRESNEL * abs(dot(normalVS, viewDirVS));
  165. float reflectionAmount = reflectionIntensity * fresnel;
  166. // compute blur amount
  167. float wdist = rayLength * zdist;
  168. float blurAmount = max(0, wdist - CONTACT_HARDENING) * FUZZYNESS * (1 - smoothness);
  169. // return hit pixel
  170. return float4(p.xy, blurAmount + 0.001, reflectionAmount);
  171. }
  172. return float4(0,0,0,0);
  173. }
  174. float4 FragSSRSurf (VaryingsSSRSurf input) : SV_Target {
  175. UNITY_SETUP_INSTANCE_ID(input);
  176. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  177. input.scrPos.xy /= input.scrPos.w;
  178. //input.scrPos = SSRStereoTransformScreenSpaceTex(input.scrPos);
  179. #if SSR_NORMALMAP
  180. float4 packedNormal = SAMPLE_TEXTURE2D(_BumpMap, sampler_PointRepeat, input.uv);
  181. float3 normalTS = UnpackNormal(packedNormal);
  182. half3 viewDirWS = half3(input.normal.w, input.tangent.w, input.bitangent.w);
  183. float3 normalWS = TransformTangentToWorld(normalTS, half3x3(input.tangent.xyz, input.bitangent.xyz, input.normal.xyz));
  184. float3 normalVS = TransformWorldToViewDir(normalWS);
  185. normalVS.z *= -1;
  186. #else
  187. float3 normalVS = input.normal;
  188. #endif
  189. #if SSR_SMOOTHNESSMAP
  190. float smoothness = SMOOTHNESS * SAMPLE_TEXTURE2D(_SmoothnessMap, sampler_PointRepeat, input.uv).a;
  191. #else
  192. float smoothness = SMOOTHNESS;
  193. #endif
  194. float4 reflection = SSR_Pass(input.scrPos.xy, normalVS, input.positionVS, smoothness);
  195. return reflection;
  196. }
  197. #endif // SSR_SURF_FX