You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

929 lines
31 KiB

  1. /**
  2. \author Michael Mara and Morgan McGuire, Casual Effects. 2015.
  3. */
  4. Shader "Hidden/Post FX/Screen Space Reflection"
  5. {
  6. Properties
  7. {
  8. _MainTex ("Base (RGB)", 2D) = "white" {}
  9. }
  10. CGINCLUDE
  11. #pragma target 3.0
  12. #include "UnityCG.cginc"
  13. #include "UnityPBSLighting.cginc"
  14. #include "UnityStandardBRDF.cginc"
  15. #include "UnityStandardUtils.cginc"
  16. #include "Common.cginc"
  17. #include "ScreenSpaceRaytrace.cginc"
  18. float4 _ProjInfo;
  19. float4x4 _WorldToCameraMatrix;
  20. float4x4 _CameraToWorldMatrix;
  21. float4x4 _ProjectToPixelMatrix;
  22. float2 _ScreenSize;
  23. float2 _ReflectionBufferSize;
  24. float2 _InvScreenSize;
  25. float3 _CameraClipInfo;
  26. sampler2D _CameraGBufferTexture0;
  27. sampler2D _CameraGBufferTexture1;
  28. sampler2D _CameraGBufferTexture2;
  29. sampler2D _CameraGBufferTexture3;
  30. sampler2D _CameraReflectionsTexture;
  31. float _CurrentMipLevel;
  32. float _RayStepSize;
  33. float _MaxRayTraceDistance;
  34. float _LayerThickness;
  35. float _FresnelFade;
  36. float _FresnelFadePower;
  37. float _ReflectionBlur;
  38. int _HalfResolution;
  39. int _TreatBackfaceHitAsMiss;
  40. int _AllowBackwardsRays;
  41. // RG: SS Hitpoint of ray
  42. // B: distance ray travelled, used for mip-selection in the final resolve
  43. // A: confidence value
  44. sampler2D _HitPointTexture;
  45. sampler2D _FinalReflectionTexture;
  46. // RGB: camera-space normal (encoded in [0-1])
  47. // A: Roughness
  48. sampler2D _NormalAndRoughnessTexture;
  49. int _EnableRefine;
  50. int _AdditiveReflection;
  51. float _ScreenEdgeFading;
  52. int _MaxSteps;
  53. int _BilateralUpsampling;
  54. float _MaxRoughness;
  55. float _RoughnessFalloffRange;
  56. float _SSRMultiplier;
  57. float _FadeDistance;
  58. int _TraceBehindObjects;
  59. int _UseEdgeDetector;
  60. int _HighlightSuppression;
  61. /** The height in pixels of a 1m object if viewed from 1m away. */
  62. float _PixelsPerMeterAtOneMeter;
  63. // For temporal filtering:
  64. float4x4 _CurrentCameraToPreviousCamera;
  65. sampler2D _PreviousReflectionTexture;
  66. sampler2D _PreviousCSZBuffer;
  67. float _TemporalAlpha;
  68. int _UseTemporalConfidence;
  69. struct v2f
  70. {
  71. float4 pos : SV_POSITION;
  72. float2 uv : TEXCOORD0;
  73. float2 uv2 : TEXCOORD1;
  74. };
  75. v2f vert( appdata_img v )
  76. {
  77. v2f o;
  78. o.pos = UnityObjectToClipPos(v.vertex);
  79. o.uv = v.texcoord.xy;
  80. o.uv2 = v.texcoord.xy;
  81. #if UNITY_UV_STARTS_AT_TOP
  82. if (_MainTex_TexelSize.y < 0)
  83. o.uv2.y = 1.0 - o.uv2.y;
  84. #endif
  85. return o;
  86. }
  87. float2 mipToSize(int mip)
  88. {
  89. return floor(_ReflectionBufferSize * exp2(-mip));
  90. }
  91. float3 ReconstructCSPosition(float2 S, float z)
  92. {
  93. float linEyeZ = -LinearEyeDepth(z);
  94. return float3((((S.xy * _MainTex_TexelSize.zw)) * _ProjInfo.xy + _ProjInfo.zw) * linEyeZ, linEyeZ);
  95. }
  96. /** Read the camera-space position of the point at screen-space pixel ssP */
  97. float3 GetPosition(float2 ssP)
  98. {
  99. float3 P;
  100. P.z = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, ssP.xy);
  101. // Offset to pixel center
  102. P = ReconstructCSPosition(float2(ssP) /*+ float2(0.5, 0.5)*/, P.z);
  103. return P;
  104. }
  105. float applyEdgeFade(float2 tsP, float fadeStrength)
  106. {
  107. float maxFade = 0.1;
  108. float2 itsP = float2(1.0, 1.0) - tsP;
  109. float dist = min(min(itsP.x, itsP.y), min(tsP.x, tsP.x));
  110. float fade = dist / (maxFade*fadeStrength + 0.001);
  111. fade = max(min(fade, 1.0), 0.0);
  112. fade = pow(fade, 0.2);
  113. return fade;
  114. }
  115. float3 csMirrorVector(float3 csPosition, float3 csN)
  116. {
  117. float3 csE = -normalize(csPosition.xyz);
  118. float cos_o = dot(csN, csE);
  119. float3 c_mi = normalize((csN * (2.0 * cos_o)) - csE);
  120. return c_mi;
  121. }
  122. float4 fragRaytrace(v2f i, int stepRate)
  123. {
  124. float2 ssP = i.uv2.xy;
  125. float3 csPosition = GetPosition(ssP);
  126. float smoothness = tex2D(_CameraGBufferTexture1, ssP).a;
  127. if (csPosition.z < -100.0 || smoothness == 0.0)
  128. {
  129. return float4(0.0,0.0,0.0,0.0);
  130. }
  131. float3 wsNormal = tex2D(_CameraGBufferTexture2, ssP).rgb * 2.0 - 1.0;
  132. int2 ssC = int2(ssP * _ScreenSize);
  133. float3 csN = mul((float3x3)(_WorldToCameraMatrix), wsNormal);
  134. float3 csRayDirection = csMirrorVector(csPosition, csN);
  135. if (_AllowBackwardsRays == 0 && csRayDirection.z > 0.0)
  136. {
  137. return float4(0.0, 0.0, 0.0, 0.0);
  138. }
  139. float maxRayTraceDistance = _MaxRayTraceDistance;
  140. float jitterFraction = 0.0f;
  141. float layerThickness = _LayerThickness;
  142. int maxSteps = _MaxSteps;
  143. // Bump the ray more in world space as it gets farther away (and so each pixel covers more WS distance)
  144. float rayBump = max(-0.01*csPosition.z, 0.001);
  145. float2 hitPixel;
  146. float3 csHitPoint;
  147. float stepCount;
  148. bool wasHit = castDenseScreenSpaceRay
  149. (csPosition + (csN) * rayBump,
  150. csRayDirection,
  151. _ProjectToPixelMatrix,
  152. _ScreenSize,
  153. _CameraClipInfo,
  154. jitterFraction,
  155. maxSteps,
  156. layerThickness,
  157. maxRayTraceDistance,
  158. hitPixel,
  159. stepRate,
  160. _TraceBehindObjects == 1,
  161. csHitPoint,
  162. stepCount);
  163. float2 tsPResult = hitPixel / _ScreenSize;
  164. float rayDist = dot(csHitPoint - csPosition, csRayDirection);
  165. float confidence = 0.0;
  166. if (wasHit)
  167. {
  168. confidence = Pow2(1.0 - max(2.0*float(stepCount) / float(maxSteps) - 1.0, 0.0));
  169. confidence *= clamp(((_MaxRayTraceDistance - rayDist) / _FadeDistance), 0.0, 1.0);
  170. // Fake fresnel fade
  171. float3 csE = -normalize(csPosition.xyz);
  172. confidence *= max(0.0, lerp(pow(abs(dot(csRayDirection, -csE)), _FresnelFadePower), 1, 1.0 - _FresnelFade));
  173. if (_TreatBackfaceHitAsMiss > 0)
  174. {
  175. float3 wsHitNormal = tex2Dlod(_CameraGBufferTexture2, float4(tsPResult, 0, 0)).rgb * 2.0 - 1.0;
  176. float3 wsRayDirection = mul(_CameraToWorldMatrix, float4(csRayDirection, 0)).xyz;
  177. if (dot(wsHitNormal, wsRayDirection) > 0)
  178. {
  179. confidence = 0.0;
  180. }
  181. }
  182. }
  183. // Fade out reflections that hit near edge of screen, to prevent abrupt appearance/disappearance when object go off screen
  184. // Fade out reflections that hit near edge of screen,
  185. // to prevent abrupt appearance/disappearance when object go off screen
  186. float vignette = applyEdgeFade(tsPResult, _ScreenEdgeFading);
  187. confidence *= vignette;
  188. confidence *= vignette;
  189. return float4(tsPResult, rayDist, confidence);
  190. }
  191. float4 fragComposite(v2f i) : SV_Target
  192. {
  193. // Pixel being shaded
  194. float2 tsP = i.uv2.xy;
  195. // View space point being shaded
  196. float3 C = GetPosition(tsP);
  197. // Final image before this pass
  198. float4 gbuffer3 = tex2D(_MainTex, i.uv);
  199. float4 specEmission = float4(0.0,0.0,0.0,0.0);
  200. float3 specColor = tex2D(_CameraGBufferTexture1, tsP).rgb;
  201. float roughness = tex2D(_CameraGBufferTexture1, tsP).a;
  202. float4 reflectionTexel = tex2D(_FinalReflectionTexture, tsP);
  203. float4 gbuffer0 = tex2D(_CameraGBufferTexture0, tsP);
  204. // Let core Unity functions do the dirty work of applying the BRDF
  205. float3 baseColor = gbuffer0.rgb;
  206. float occlusion = gbuffer0.a;
  207. float oneMinusReflectivity;
  208. baseColor = EnergyConservationBetweenDiffuseAndSpecular(baseColor, specColor, oneMinusReflectivity);
  209. float3 wsNormal = tex2D(_CameraGBufferTexture2, tsP).rgb * 2.0 - 1.0;
  210. float3 csEyeVec = normalize(C);
  211. float3 eyeVec = mul(_CameraToWorldMatrix, float4(csEyeVec, 0)).xyz;
  212. float3 worldPos = mul(_CameraToWorldMatrix, float4(C, 1)).xyz;
  213. float cos_o = dot(wsNormal, eyeVec);
  214. float3 w_mi = -normalize((wsNormal * (2.0 * cos_o)) - eyeVec);
  215. float3 incomingRadiance = reflectionTexel.rgb;
  216. UnityLight light;
  217. light.color = 0;
  218. light.dir = 0;
  219. #if UNITY_VERSION < 550
  220. light.ndotl = 0;
  221. #endif
  222. UnityIndirect ind;
  223. ind.diffuse = 0;
  224. ind.specular = incomingRadiance;
  225. float3 ssrResult = UNITY_BRDF_PBS (0, specColor, oneMinusReflectivity, roughness, wsNormal, -eyeVec, light, ind).rgb * _SSRMultiplier;
  226. float confidence = reflectionTexel.a;
  227. specEmission.rgb = tex2D(_CameraReflectionsTexture, tsP).rgb;
  228. float3 finalGlossyTerm;
  229. // Subtract out Unity's glossy result: (we're just applying the delta)
  230. if (_AdditiveReflection == 0)
  231. {
  232. gbuffer3 -= specEmission;
  233. // We may have blown out our dynamic range by adding then subtracting the reflection probes.
  234. // As a half-measure to fix this, simply clamp to zero
  235. gbuffer3 = max(gbuffer3, 0);
  236. finalGlossyTerm = lerp(specEmission.rgb, ssrResult, saturate(confidence));
  237. }
  238. else
  239. {
  240. finalGlossyTerm = ssrResult*saturate(confidence);
  241. }
  242. finalGlossyTerm *= occlusion;
  243. // Additively blend the glossy GI result with the output buffer
  244. return gbuffer3 + float4(finalGlossyTerm, 0);
  245. }
  246. float roughnessWeight(float midpointRoughness, float tapRoughness)
  247. {
  248. return (1.0 - sqrt(sqrt(abs(midpointRoughness-tapRoughness))));
  249. }
  250. float normalWeight(float3 midpointNormal, float3 tapNormal)
  251. {
  252. return clamp(dot(midpointNormal, tapNormal), 0, 1);
  253. }
  254. float highlightDecompression(float x)
  255. {
  256. return x / (1.0 - x);
  257. }
  258. float3 highlightDecompression(float3 x)
  259. {
  260. return float3(
  261. highlightDecompression(x.x),
  262. highlightDecompression(x.y),
  263. highlightDecompression(x.z)
  264. );
  265. }
  266. float highlightCompression(float x)
  267. {
  268. return x / (1.0 + x);
  269. }
  270. float3 highlightCompression(float3 x)
  271. {
  272. return float3(
  273. highlightCompression(x.x),
  274. highlightCompression(x.y),
  275. highlightCompression(x.z)
  276. );
  277. }
  278. float4 _Axis;
  279. float4 fragGBlur(v2f i) : SV_Target
  280. {
  281. int radius = 4;
  282. // Pixel being shaded
  283. float2 tsP = i.uv2.xy;
  284. float weightSum = 0.0;
  285. float gaussWeights[5] = { 0.225, 0.150, 0.110, 0.075, 0.0525 };//{0.225, 0.150, 0.110, 0.075, 0.0525};
  286. float4 resultSum = float4(0.0, 0.0, 0.0, 0.0);
  287. float4 unweightedResultSum = float4(0.0, 0.0, 0.0, 0.0);
  288. float4 nAndRough = tex2D(_NormalAndRoughnessTexture, tsP);
  289. float midpointRoughness = nAndRough.a;
  290. float3 midpointNormal = nAndRough.rgb * 2 - 1;
  291. for (int i = -radius; i <= radius; ++i)
  292. {
  293. float4 temp;
  294. float tapRoughness;
  295. float3 tapNormal;
  296. float2 tsTap = tsP + (_Axis.xy * _MainTex_TexelSize.xy * float2(i,i)*2.0);
  297. temp = tex2D(_MainTex, tsTap);
  298. float weight = temp.a * gaussWeights[abs(i)];
  299. // Bilateral filtering
  300. // if (_ImproveCorners)
  301. // {
  302. nAndRough = tex2D(_NormalAndRoughnessTexture, tsTap);
  303. tapRoughness = nAndRough.a;
  304. tapNormal = nAndRough.rgb * 2 - 1;
  305. weight *= normalWeight(midpointNormal, tapNormal);
  306. // }
  307. weightSum += weight;
  308. if (_HighlightSuppression)
  309. {
  310. temp.rgb = highlightCompression(temp.rgb);
  311. }
  312. unweightedResultSum += temp;
  313. resultSum += temp*weight;
  314. }
  315. if (weightSum > 0.01)
  316. {
  317. float invWeightSum = (1.0/weightSum);
  318. // Adding the sqrt seems to decrease temporal flickering at the expense
  319. // of having larger "halos" of fallback on rough surfaces
  320. // Subject to change with testing. Sqrt around only half the expression is *intentional*.
  321. float confidence = min(resultSum.a * sqrt(max(invWeightSum, 2.0)), 1.0);
  322. float3 finalColor = resultSum.rgb * invWeightSum;
  323. if (_HighlightSuppression)
  324. {
  325. finalColor = highlightDecompression(finalColor);
  326. }
  327. return float4(finalColor, confidence);
  328. }
  329. else
  330. {
  331. float3 finalColor = unweightedResultSum.rgb / (2 * radius + 1);
  332. if (_HighlightSuppression)
  333. {
  334. finalColor = highlightDecompression(finalColor);
  335. }
  336. return float4(finalColor, 0.0);
  337. }
  338. }
  339. sampler2D _ReflectionTexture0;
  340. sampler2D _ReflectionTexture1;
  341. sampler2D _ReflectionTexture2;
  342. sampler2D _ReflectionTexture3;
  343. sampler2D _ReflectionTexture4;
  344. // Simulate mip maps, since we don't have NPOT mip-chains
  345. float4 getReflectionValue(float2 tsP, int mip)
  346. {
  347. float4 coord = float4(tsP,0,0);
  348. if (mip == 0)
  349. {
  350. return tex2Dlod(_ReflectionTexture0, coord);
  351. }
  352. else if (mip == 1)
  353. {
  354. return tex2Dlod(_ReflectionTexture1, coord);
  355. }
  356. else if (mip == 2)
  357. {
  358. return tex2Dlod(_ReflectionTexture2, coord);
  359. }
  360. else if (mip == 3)
  361. {
  362. return tex2Dlod(_ReflectionTexture3, coord);
  363. }
  364. else
  365. {
  366. return tex2Dlod(_ReflectionTexture4, coord);
  367. }
  368. }
  369. sampler2D _EdgeTexture0;
  370. sampler2D _EdgeTexture1;
  371. sampler2D _EdgeTexture2;
  372. sampler2D _EdgeTexture3;
  373. sampler2D _EdgeTexture4;
  374. // Simulate mip maps, since we don't have NPOT mip-chains
  375. float4 getEdgeValue(float2 tsP, int mip)
  376. {
  377. float4 coord = float4(tsP + float2(1.0/(2 * mipToSize(mip))),0,0);
  378. if (mip == 0)
  379. {
  380. return tex2Dlod(_EdgeTexture0, coord);
  381. }
  382. else if (mip == 1)
  383. {
  384. return tex2Dlod(_EdgeTexture1, coord);
  385. }
  386. else if (mip == 2)
  387. {
  388. return tex2Dlod(_EdgeTexture2, coord);
  389. }
  390. else if (mip == 3)
  391. {
  392. return tex2Dlod(_EdgeTexture3, coord);
  393. }
  394. else
  395. {
  396. return tex2Dlod(_EdgeTexture4, coord);
  397. }
  398. }
  399. float2 centerPixel(float2 inputP)
  400. {
  401. return floor(inputP - float2(0.5,0.5)) + float2(0.5,0.5);
  402. }
  403. float2 snapToTexelCenter(float2 inputP, float2 texSize, float2 texSizeInv)
  404. {
  405. return centerPixel(inputP * texSize) * texSizeInv;
  406. }
  407. float4 bilateralUpsampleReflection(float2 tsP, int mip)
  408. {
  409. float2 smallTexSize = mipToSize(mip);
  410. float2 smallPixelPos = tsP * smallTexSize;
  411. float2 smallPixelPosi = centerPixel(smallPixelPos);
  412. float2 smallTexSizeInv = 1.0 / smallTexSize;
  413. float2 p0 = smallPixelPosi * smallTexSizeInv;
  414. float2 p3 = (smallPixelPosi + float2(1.0, 1.0)) * smallTexSizeInv;
  415. float2 p1 = float2(p3.x, p0.y);
  416. float2 p2 = float2(p0.x, p3.y);
  417. float4 V0 = getReflectionValue(p0.xy, mip);
  418. float4 V1 = getReflectionValue(p1.xy, mip);
  419. float4 V2 = getReflectionValue(p2.xy, mip);
  420. float4 V3 = getReflectionValue(p3.xy, mip);
  421. // Bilateral weights:
  422. // Bilinear interpolation (filter distance)
  423. float2 smallPixelPosf = smallPixelPos - smallPixelPosi;
  424. float a0 = (1.0 - smallPixelPosf.x) * (1.0 - smallPixelPosf.y);
  425. float a1 = smallPixelPosf.x * (1.0 - smallPixelPosf.y);
  426. float a2 = (1.0 - smallPixelPosf.x) * smallPixelPosf.y;
  427. float a3 = smallPixelPosf.x * smallPixelPosf.y;
  428. float2 fullTexSize = _ReflectionBufferSize;
  429. float2 fullTexSizeInv = 1.0 / fullTexSize;
  430. float4 hiP0 = float4(snapToTexelCenter(p0, fullTexSize, fullTexSizeInv), 0,0);
  431. float4 hiP3 = float4(snapToTexelCenter(p3, fullTexSize, fullTexSizeInv), 0,0);
  432. float4 hiP1 = float4(snapToTexelCenter(p1, fullTexSize, fullTexSizeInv), 0,0);
  433. float4 hiP2 = float4(snapToTexelCenter(p2, fullTexSize, fullTexSizeInv), 0,0);
  434. float4 tempCenter = tex2Dlod(_NormalAndRoughnessTexture, float4(tsP, 0, 0));
  435. float3 n = tempCenter.xyz * 2 - 1;
  436. float4 temp0 = tex2Dlod(_NormalAndRoughnessTexture, hiP0);
  437. float4 temp1 = tex2Dlod(_NormalAndRoughnessTexture, hiP1);
  438. float4 temp2 = tex2Dlod(_NormalAndRoughnessTexture, hiP2);
  439. float4 temp3 = tex2Dlod(_NormalAndRoughnessTexture, hiP3);
  440. float3 n0 = temp0.xyz * 2 - 1;
  441. float3 n1 = temp1.xyz * 2 - 1;
  442. float3 n2 = temp2.xyz * 2 - 1;
  443. float3 n3 = temp3.xyz * 2 - 1;
  444. a0 *= normalWeight(n, n0);
  445. a1 *= normalWeight(n, n1);
  446. a2 *= normalWeight(n, n2);
  447. a3 *= normalWeight(n, n3);
  448. float r = tempCenter.a;
  449. float r0 = temp0.a;
  450. float r1 = temp1.a;
  451. float r2 = temp2.a;
  452. float r3 = temp3.a;
  453. a0 *= roughnessWeight(r, r0);
  454. a1 *= roughnessWeight(r, r1);
  455. a2 *= roughnessWeight(r, r2);
  456. a3 *= roughnessWeight(r, r3);
  457. // Slightly offset from zero
  458. a0 = max(a0, 0.001);
  459. a1 = max(a1, 0.001);
  460. a2 = max(a2, 0.001);
  461. a3 = max(a3, 0.001);
  462. // Nearest neighbor
  463. // a0 = a1 = a2 = a3 = 1.0;
  464. // Normalize the blending weights (weights were chosen so that
  465. // the denominator can never be zero)
  466. float norm = 1.0 / (a0 + a1 + a2 + a3);
  467. // Blend
  468. float4 value = (V0 * a0 + V1 * a1 + V2 * a2 + V3 * a3) * norm;
  469. //return V0;
  470. return value;
  471. }
  472. /** Explicit bilinear fetches; must be used if the reflection buffer is bound using point sampling */
  473. float4 bilinearUpsampleReflection(float2 tsP, int mip)
  474. {
  475. float2 smallTexSize = mipToSize(mip);
  476. float2 smallPixelPos = tsP * smallTexSize;
  477. float2 smallPixelPosi = centerPixel(smallPixelPos);
  478. float2 smallTexSizeInv = 1.0 / smallTexSize;
  479. float2 p0 = smallPixelPosi * smallTexSizeInv;
  480. float2 p3 = (smallPixelPosi + float2(1.0, 1.0)) * smallTexSizeInv;
  481. float2 p1 = float2(p3.x, p0.y);
  482. float2 p2 = float2(p0.x, p3.y);
  483. float4 V0 = getReflectionValue(p0.xy, mip);
  484. float4 V1 = getReflectionValue(p1.xy, mip);
  485. float4 V2 = getReflectionValue(p2.xy, mip);
  486. float4 V3 = getReflectionValue(p3.xy, mip);
  487. float a0 = 1.0;
  488. float a1 = 1.0;
  489. float a2 = 1.0;
  490. float a3 = 1.0;
  491. // Bilateral weights:
  492. // Bilinear interpolation (filter distance)
  493. float2 smallPixelPosf = smallPixelPos - smallPixelPosi;
  494. a0 = (1.0 - smallPixelPosf.x) * (1.0 - smallPixelPosf.y);
  495. a1 = smallPixelPosf.x * (1.0 - smallPixelPosf.y);
  496. a2 = (1.0 - smallPixelPosf.x) * smallPixelPosf.y;
  497. a3 = smallPixelPosf.x * smallPixelPosf.y;
  498. // Blend
  499. float4 value = (V0 * a0 + V1 * a1 + V2 * a2 + V3 * a3);
  500. return value;
  501. }
  502. // Unity's roughness is GGX roughness squared
  503. float roughnessToBlinnPhongExponent(float roughness)
  504. {
  505. float r2 = roughness*roughness;
  506. return 2.0f / r2*r2 - 2.0f;
  507. }
  508. float glossyLobeSlope(float roughness)
  509. {
  510. return pow(roughness, 4.0/3.0);
  511. }
  512. // Empirically based on our filter:
  513. // Mip | Pixels
  514. // --------------
  515. // 0 | 1 no filter, so single pixel
  516. // 1 | 17 2r + 1 filter applied once, grabbing from pixels r away in either direction (r=8, four samples times stride of 2)
  517. // 2 | 50 2r + 1 filter applied on double size pixels, and each of those pixels had reached another r out to the side 2(2r + 1) + m_1
  518. // 3 | 118 4(2r + 1) + m_2
  519. // 4 | 254 8(2r + 1) + m_3
  520. //
  521. // Approximated by pixels = 16*2^mip-15
  522. // rearranging we get mip = log_2((pixels + 15) / 16)
  523. //
  524. float filterFootprintInPixelsToMip(float footprint)
  525. {
  526. return log2((footprint + 15) / 16);
  527. }
  528. float3 ansiGradient(float t)
  529. {
  530. //return float3(t, t, t);
  531. return fmod(floor(t * float3(8.0, 4.0, 2.0)), 2.0);
  532. }
  533. float4 fragCompositeSSR(v2f i) : SV_Target
  534. {
  535. // Pixel being shaded
  536. float2 tsP = i.uv2.xy;
  537. float roughness = 1.0-tex2D(_CameraGBufferTexture1, tsP).a;
  538. float rayDistance = tex2D(_HitPointTexture, tsP).z;
  539. // Get the camera space position of the reflection hit
  540. float3 csPosition = GetPosition(tsP);
  541. float3 wsNormal = tex2D(_CameraGBufferTexture2, tsP).rgb * 2.0 - 1.0;
  542. float3 csN = mul((float3x3)(_WorldToCameraMatrix), wsNormal);
  543. float3 c_mi = csMirrorVector(csPosition, csN);
  544. float3 csHitpoint = c_mi * rayDistance + csPosition;
  545. float gatherFootprintInMeters = glossyLobeSlope(roughness) * rayDistance;
  546. // We could add a term that incorporates the normal
  547. // This approximation assumes reflections happen at a glancing angle
  548. float filterFootprintInPixels = gatherFootprintInMeters * _PixelsPerMeterAtOneMeter / csHitpoint.z;
  549. if (_HalfResolution == 1)
  550. {
  551. filterFootprintInPixels *= 0.5;
  552. }
  553. float mip = filterFootprintInPixelsToMip(filterFootprintInPixels);
  554. float nonPhysicalMip = pow(roughness, 3.0 / 4.0) * UNITY_SPECCUBE_LOD_STEPS;
  555. if (_HalfResolution == 1)
  556. {
  557. nonPhysicalMip = nonPhysicalMip * 0.7;
  558. }
  559. mip = max(0, min(4, mip));
  560. float4 result = 0.;
  561. {
  562. int mipMin = int(mip);
  563. int mipMax = min(mipMin + 1, 4);
  564. float mipLerp = mip-mipMin;
  565. if (_BilateralUpsampling == 1)
  566. {
  567. result = lerp(bilateralUpsampleReflection(tsP, mipMin), bilateralUpsampleReflection(tsP, mipMax), mipLerp);
  568. }
  569. else
  570. {
  571. float4 minResult = getReflectionValue(tsP, mipMin);
  572. float4 maxResult = getReflectionValue(tsP, mipMax);
  573. result = lerp(minResult, maxResult, mipLerp);
  574. result.a = min(minResult.a, maxResult.a);
  575. }
  576. }
  577. result.a = min(result.a, 1.0);
  578. float vignette = applyEdgeFade(tsP, _ScreenEdgeFading);
  579. result.a *= vignette;
  580. // THIS MIGHT BE SLIGHTLY WRONG, TRY STEP()
  581. float alphaModifier = 1.0 - clamp(roughness * .3, 0., 1.);
  582. result.a *= alphaModifier;
  583. return result;
  584. }
  585. int _LastMip;
  586. float4 fragMin(v2f i) : SV_Target
  587. {
  588. float2 tsP = i.uv2.xy;
  589. float2 lastTexSize = mipToSize(_LastMip);
  590. float2 lastTexSizeInv = 1.0 / lastTexSize;
  591. float2 p00 = snapToTexelCenter(tsP, lastTexSize, lastTexSizeInv);
  592. float2 p11 = p00 + lastTexSizeInv;
  593. return min(
  594. min(tex2D(_MainTex, p00), tex2D(_MainTex, p11)),
  595. min(tex2D(_MainTex, float2(p00.x, p11.y)), tex2D(_MainTex, float2(p11.x, p00.y)))
  596. );
  597. }
  598. float4 fragResolveHitPoints(v2f i) : SV_Target
  599. {
  600. float2 tsP = i.uv2.xy;
  601. float4 temp = tex2D(_HitPointTexture, tsP);
  602. float2 hitPoint = temp.xy;
  603. float confidence = temp.w;
  604. float3 colorResult = confidence > 0.0 ? tex2D(_MainTex, hitPoint).rgb : tex2D(_CameraReflectionsTexture, tsP).rgb;
  605. if (any(isnan(colorResult)))
  606. colorResult = float3(0.0, 0.0, 0.0);
  607. // As of 11/29/2015, on Unity 5.3 on a Windows 8.1 computer with a NVIDIA GeForce 980,
  608. // with driver 347.62, the above check does not actually work to get rid of NaNs!
  609. // So we add this "redundant" check.
  610. if (!all(isfinite(colorResult)))
  611. colorResult = float3(0.0, 0.0, 0.0);
  612. return float4(colorResult, confidence);
  613. }
  614. float4 fragBilatKeyPack(v2f i) : SV_Target
  615. {
  616. float2 tsP = i.uv2.xy;
  617. float3 csN = tex2D(_CameraGBufferTexture2, tsP).xyz;
  618. float roughness = tex2D(_CameraGBufferTexture1, tsP).a;
  619. return float4(csN, roughness);
  620. }
  621. float4 fragDepthToCSZ(v2f i) : SV_Target
  622. {
  623. float depth = SAMPLE_DEPTH_TEXTURE(_CameraDepthTexture, i.uv2.xy);
  624. return float4(-LinearEyeDepth(depth), 0.0, 0.0, 0.0);
  625. }
  626. static const int NUM_POISSON_TAPS = 12;
  627. // Same as used in CameraMotionBlur.shader
  628. static const float2 poissonSamples[NUM_POISSON_TAPS] =
  629. {
  630. float2(-0.326212,-0.40581),
  631. float2(-0.840144,-0.07358),
  632. float2(-0.695914,0.457137),
  633. float2(-0.203345,0.620716),
  634. float2(0.96234,-0.194983),
  635. float2(0.473434,-0.480026),
  636. float2(0.519456,0.767022),
  637. float2(0.185461,-0.893124),
  638. float2(0.507431,0.064425),
  639. float2(0.89642,0.412458),
  640. float2(-0.32194,-0.932615),
  641. float2(-0.791559,-0.59771)
  642. };
  643. float4 fragFilterSharpReflections(v2f i) : SV_Target
  644. {
  645. // Could improve perf by not computing blur when we won't be sampling the highest level anyways
  646. float2 tsP = i.uv2.xy;
  647. float4 sum = 0.0;
  648. float sampleRadius = _MainTex_TexelSize.xy * _ReflectionBlur;
  649. for (int i = 0; i < NUM_POISSON_TAPS; i++)
  650. {
  651. float2 p = tsP + poissonSamples[i] * sampleRadius;
  652. float4 tap = tex2D(_MainTex, p);
  653. if (_HighlightSuppression)
  654. {
  655. tap.rgb = highlightCompression(tap.rgb);
  656. }
  657. sum += tap;
  658. }
  659. float4 result = sum / float(NUM_POISSON_TAPS);
  660. if (_HighlightSuppression)
  661. {
  662. result.rgb = highlightDecompression(result.rgb);
  663. }
  664. return result;
  665. }
  666. ENDCG
  667. SubShader
  668. {
  669. ZTest Always Cull Off ZWrite Off
  670. // 0: Raytrace
  671. Pass
  672. {
  673. CGPROGRAM
  674. #pragma exclude_renderers gles xbox360 ps3
  675. #pragma vertex vert
  676. #pragma fragment fragRaytrace1
  677. float4 fragRaytrace1(v2f i) : SV_Target
  678. {
  679. return fragRaytrace(i, _RayStepSize);
  680. }
  681. ENDCG
  682. }
  683. // 1: Composite
  684. Pass
  685. {
  686. CGPROGRAM
  687. #pragma exclude_renderers gles xbox360 ps3
  688. #pragma vertex vert
  689. #pragma fragment fragComposite
  690. ENDCG
  691. }
  692. // 2: GBlur
  693. Pass
  694. {
  695. CGPROGRAM
  696. #pragma exclude_renderers gles xbox360 ps3
  697. #pragma vertex vert
  698. #pragma fragment fragGBlur
  699. ENDCG
  700. }
  701. // 3: CompositeSSR
  702. Pass
  703. {
  704. CGPROGRAM
  705. #pragma exclude_renderers gles xbox360 ps3
  706. #pragma vertex vert
  707. #pragma fragment fragCompositeSSR
  708. ENDCG
  709. }
  710. // 4: Min mip generation
  711. Pass
  712. {
  713. CGPROGRAM
  714. #pragma exclude_renderers gles xbox360 ps3
  715. #pragma vertex vert
  716. #pragma fragment fragMin
  717. ENDCG
  718. }
  719. // 5: Hit point texture to reflection buffer
  720. Pass
  721. {
  722. CGPROGRAM
  723. #pragma exclude_renderers gles xbox360 ps3
  724. #pragma vertex vert
  725. #pragma fragment fragResolveHitPoints
  726. ENDCG
  727. }
  728. // 6: Pack Bilateral Filter Keys in single buffer
  729. Pass
  730. {
  731. CGPROGRAM
  732. #pragma exclude_renderers gles xbox360 ps3
  733. #pragma vertex vert
  734. #pragma fragment fragBilatKeyPack
  735. ENDCG
  736. }
  737. // 7: Blit depth information as camera space Z
  738. Pass
  739. {
  740. CGPROGRAM
  741. #pragma exclude_renderers gles xbox360 ps3
  742. #pragma vertex vert
  743. #pragma fragment fragDepthToCSZ
  744. ENDCG
  745. }
  746. // 8: Filter the highest quality reflection buffer
  747. Pass
  748. {
  749. CGPROGRAM
  750. #pragma exclude_renderers gles xbox360 ps3
  751. #pragma vertex vert
  752. #pragma fragment fragFilterSharpReflections
  753. ENDCG
  754. }
  755. }
  756. Fallback "Diffuse"
  757. }