暫無描述
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.

BokehDepthOfField.shader 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. Shader "Hidden/Universal Render Pipeline/BokehDepthOfField"
  2. {
  3. HLSLINCLUDE
  4. #pragma multi_compile_local_fragment _ _USE_FAST_SRGB_LINEAR_CONVERSION
  5. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"
  6. #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Color.hlsl"
  7. #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/DeclareDepthTexture.hlsl"
  8. #include "Packages/com.unity.render-pipelines.universal/Shaders/PostProcessing/Common.hlsl"
  9. // Do not change this without changing PostProcessPass.PrepareBokehKernel()
  10. #define SAMPLE_COUNT 42
  11. // Toggle this to reduce flickering - note that it will reduce overall bokeh energy and add
  12. // a small cost to the pre-filtering pass
  13. #define COC_LUMA_WEIGHTING 0
  14. TEXTURE2D_X(_DofTexture);
  15. TEXTURE2D_X(_FullCoCTexture);
  16. half4 _SourceSize;
  17. half4 _DownSampleScaleFactor;
  18. half4 _CoCParams;
  19. half4 _BokehKernel[SAMPLE_COUNT];
  20. half4 _BokehConstants;
  21. #define FocusDist _CoCParams.x
  22. #define MaxCoC _CoCParams.y
  23. #define MaxRadius _CoCParams.z
  24. #define RcpAspect _CoCParams.w
  25. half FragCoC(Varyings input) : SV_Target
  26. {
  27. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  28. float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord);
  29. float depth = LOAD_TEXTURE2D_X(_CameraDepthTexture, _SourceSize.xy * uv).x;
  30. float linearEyeDepth = LinearEyeDepth(depth, _ZBufferParams);
  31. half coc = (1.0 - FocusDist / linearEyeDepth) * MaxCoC;
  32. half nearCoC = clamp(coc, -1.0, 0.0);
  33. half farCoC = saturate(coc);
  34. return saturate((farCoC + nearCoC + 1.0) * 0.5);
  35. }
  36. half4 FragPrefilter(Varyings input) : SV_Target
  37. {
  38. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  39. float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord);
  40. #if SHADER_TARGET >= 45 && defined(PLATFORM_SUPPORT_GATHER)
  41. // Sample source colors
  42. half4 cr = GATHER_RED_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
  43. half4 cg = GATHER_GREEN_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
  44. half4 cb = GATHER_BLUE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
  45. half3 c0 = half3(cr.x, cg.x, cb.x);
  46. half3 c1 = half3(cr.y, cg.y, cb.y);
  47. half3 c2 = half3(cr.z, cg.z, cb.z);
  48. half3 c3 = half3(cr.w, cg.w, cb.w);
  49. // Sample CoCs
  50. half4 cocs = GATHER_TEXTURE2D_X(_FullCoCTexture, sampler_LinearClamp, uv) * 2.0 - 1.0;
  51. half coc0 = cocs.x;
  52. half coc1 = cocs.y;
  53. half coc2 = cocs.z;
  54. half coc3 = cocs.w;
  55. #else
  56. float3 duv = _SourceSize.zwz * float3(0.5, 0.5, -0.5);
  57. float2 uv0 = uv - duv.xy;
  58. float2 uv1 = uv - duv.zy;
  59. float2 uv2 = uv + duv.zy;
  60. float2 uv3 = uv + duv.xy;
  61. // Sample source colors
  62. half3 c0 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv0).xyz;
  63. half3 c1 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv1).xyz;
  64. half3 c2 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv2).xyz;
  65. half3 c3 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv3).xyz;
  66. // Sample CoCs
  67. half coc0 = SAMPLE_TEXTURE2D_X(_FullCoCTexture, sampler_LinearClamp, uv0).x * 2.0 - 1.0;
  68. half coc1 = SAMPLE_TEXTURE2D_X(_FullCoCTexture, sampler_LinearClamp, uv1).x * 2.0 - 1.0;
  69. half coc2 = SAMPLE_TEXTURE2D_X(_FullCoCTexture, sampler_LinearClamp, uv2).x * 2.0 - 1.0;
  70. half coc3 = SAMPLE_TEXTURE2D_X(_FullCoCTexture, sampler_LinearClamp, uv3).x * 2.0 - 1.0;
  71. #endif
  72. #if COC_LUMA_WEIGHTING
  73. // Apply CoC and luma weights to reduce bleeding and flickering
  74. half w0 = abs(coc0) / (Max3(c0.x, c0.y, c0.z) + 1.0);
  75. half w1 = abs(coc1) / (Max3(c1.x, c1.y, c1.z) + 1.0);
  76. half w2 = abs(coc2) / (Max3(c2.x, c2.y, c2.z) + 1.0);
  77. half w3 = abs(coc3) / (Max3(c3.x, c3.y, c3.z) + 1.0);
  78. // Weighted average of the color samples
  79. half3 avg = c0 * w0 + c1 * w1 + c2 * w2 + c3 * w3;
  80. avg /= max(w0 + w1 + w2 + w3, 1e-5);
  81. #else
  82. half3 avg = (c0 + c1 + c2 + c3) / 4.0;
  83. #endif
  84. // Select the largest CoC value
  85. half cocMin = min(coc0, Min3(coc1, coc2, coc3));
  86. half cocMax = max(coc0, Max3(coc1, coc2, coc3));
  87. half coc = (-cocMin > cocMax ? cocMin : cocMax) * MaxRadius;
  88. // Premultiply CoC
  89. avg *= smoothstep(0, _SourceSize.w * 2.0, abs(coc));
  90. #if defined(UNITY_COLORSPACE_GAMMA)
  91. avg = GetSRGBToLinear(avg);
  92. #endif
  93. return half4(avg, coc);
  94. }
  95. void Accumulate(half4 samp0, float2 uv, half4 disp, inout half4 farAcc, inout half4 nearAcc)
  96. {
  97. half4 samp = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampAndScaleUVForBilinear(uv + disp.wy, _BlitTexture_TexelSize.xy));
  98. // Compare CoC of the current sample and the center sample and select smaller one
  99. half farCoC = max(min(samp0.a, samp.a), 0.0);
  100. // Compare the CoC to the sample distance & add a small margin to smooth out
  101. half farWeight = saturate((farCoC - disp.z + _BokehConstants.y) / _BokehConstants.y);
  102. half nearWeight = saturate((-samp.a - disp.z + _BokehConstants.y) / _BokehConstants.y);
  103. // Cut influence from focused areas because they're darkened by CoC premultiplying. This is only
  104. // needed for near field
  105. nearWeight *= step(_BokehConstants.x, -samp.a);
  106. // Accumulation
  107. farAcc += half4(samp.rgb, 1.0h) * farWeight;
  108. nearAcc += half4(samp.rgb, 1.0h) * nearWeight;
  109. }
  110. half4 FragBlur(Varyings input) : SV_Target
  111. {
  112. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  113. float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord);
  114. half4 samp0 = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, uv);
  115. half4 farAcc = 0.0; // Background: far field bokeh
  116. half4 nearAcc = 0.0; // Foreground: near field bokeh
  117. // Center sample isn't in the kernel array, accumulate it separately
  118. Accumulate(samp0, uv, 0.0, farAcc, nearAcc);
  119. UNITY_LOOP
  120. for (int si = 0; si < SAMPLE_COUNT; si++)
  121. {
  122. Accumulate(samp0, uv, _BokehKernel[si], farAcc, nearAcc);
  123. }
  124. // Get the weighted average
  125. farAcc.rgb /= farAcc.a + (farAcc.a == 0.0); // Zero-div guard
  126. nearAcc.rgb /= nearAcc.a + (nearAcc.a == 0.0);
  127. // Normalize the total of the weights for the near field
  128. nearAcc.a *= PI / (SAMPLE_COUNT + 1);
  129. // Alpha premultiplying (total near field accumulation weight)
  130. half alpha = saturate(nearAcc.a);
  131. half3 rgb = lerp(farAcc.rgb, nearAcc.rgb, alpha);
  132. return half4(rgb, alpha);
  133. }
  134. half4 FragPostBlur(Varyings input) : SV_Target
  135. {
  136. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  137. float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord);
  138. // 9-tap tent filter with 4 bilinear samples
  139. float4 duv = _SourceSize.zwzw * _DownSampleScaleFactor.zwzw * float4(0.5, 0.5, -0.5, 0);
  140. half4 acc;
  141. acc = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(uv - duv.xy, _BlitTexture_TexelSize.xy));
  142. acc += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(uv - duv.zy, _BlitTexture_TexelSize.xy));
  143. acc += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(uv + duv.zy, _BlitTexture_TexelSize.xy));
  144. acc += SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(uv + duv.xy, _BlitTexture_TexelSize.xy));
  145. return acc * 0.25;
  146. }
  147. half4 FragComposite(Varyings input) : SV_Target
  148. {
  149. UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(input);
  150. float2 uv = UnityStereoTransformScreenSpaceTex(input.texcoord);
  151. float dofDownSample = 2.0f;
  152. half4 dof = SAMPLE_TEXTURE2D_X(_DofTexture, sampler_LinearClamp, ClampUVForBilinear(uv, _BlitTexture_TexelSize.xy * dofDownSample));
  153. half coc = SAMPLE_TEXTURE2D_X(_FullCoCTexture, sampler_LinearClamp, ClampUVForBilinear(uv, _BlitTexture_TexelSize.xy)).r;
  154. coc = (coc - 0.5) * 2.0 * MaxRadius;
  155. // Convert CoC to far field alpha value
  156. float ffa = smoothstep(_SourceSize.w * 2.0, _SourceSize.w * 4.0, coc);
  157. half4 color = SAMPLE_TEXTURE2D_X(_BlitTexture, sampler_LinearClamp, ClampUVForBilinear(uv, _BlitTexture_TexelSize.xy));
  158. #if defined(UNITY_COLORSPACE_GAMMA)
  159. color = GetSRGBToLinear(color);
  160. #endif
  161. half alpha = Max3(dof.r, dof.g, dof.b);
  162. half4 outColor = lerp(color, half4(dof.rgb, alpha), ffa + dof.a - ffa * dof.a);
  163. #if _ENABLE_ALPHA_OUTPUT
  164. // Preserve the original value of the pixels with zero alpha
  165. outColor.rgb = color.a > 0 ? outColor.rgb : color.rgb;
  166. // The BokehDoF does not process source content alpha as it uses the alpha channel to pack CoC and near/far field weights.
  167. // The outColor.a is an approximate mixed alpha between the sharp and the blurred (near+far) dof layers.
  168. // It is not the actual blurred alpha of the source content.
  169. // Keep the original alpha mask.
  170. outColor.a = color.a;
  171. #endif
  172. #if defined(UNITY_COLORSPACE_GAMMA)
  173. outColor = GetLinearToSRGB(outColor);
  174. #endif
  175. return outColor;
  176. }
  177. ENDHLSL
  178. SubShader
  179. {
  180. Tags { "RenderPipeline" = "UniversalPipeline" }
  181. LOD 100
  182. ZTest Always ZWrite Off Cull Off
  183. Pass
  184. {
  185. Name "Bokeh Depth Of Field CoC"
  186. HLSLPROGRAM
  187. #pragma vertex Vert
  188. #pragma fragment FragCoC
  189. #pragma target 4.5
  190. ENDHLSL
  191. }
  192. Pass
  193. {
  194. Name "Bokeh Depth Of Field Prefilter"
  195. HLSLPROGRAM
  196. #pragma vertex Vert
  197. #pragma fragment FragPrefilter
  198. #pragma target 4.5
  199. ENDHLSL
  200. }
  201. Pass
  202. {
  203. Name "Bokeh Depth Of Field Blur"
  204. HLSLPROGRAM
  205. #pragma vertex Vert
  206. #pragma fragment FragBlur
  207. #pragma target 4.5
  208. ENDHLSL
  209. }
  210. Pass
  211. {
  212. Name "Bokeh Depth Of Field Post Blur"
  213. HLSLPROGRAM
  214. #pragma vertex Vert
  215. #pragma fragment FragPostBlur
  216. #pragma target 4.5
  217. ENDHLSL
  218. }
  219. Pass
  220. {
  221. Name "Bokeh Depth Of Field Composite"
  222. HLSLPROGRAM
  223. #pragma vertex Vert
  224. #pragma fragment FragComposite
  225. #pragma target 4.5
  226. #pragma multi_compile_fragment _ _ENABLE_ALPHA_OUTPUT
  227. ENDHLSL
  228. }
  229. }
  230. // SM3.5 fallbacks - needed because of the use of Gather
  231. SubShader
  232. {
  233. Tags { "RenderPipeline" = "UniversalPipeline" }
  234. LOD 100
  235. ZTest Always ZWrite Off Cull Off
  236. Pass
  237. {
  238. Name "Bokeh Depth Of Field CoC"
  239. HLSLPROGRAM
  240. #pragma vertex Vert
  241. #pragma fragment FragCoC
  242. #pragma target 3.5
  243. ENDHLSL
  244. }
  245. Pass
  246. {
  247. Name "Bokeh Depth Of Field Prefilter"
  248. HLSLPROGRAM
  249. #pragma vertex Vert
  250. #pragma fragment FragPrefilter
  251. #pragma target 3.5
  252. ENDHLSL
  253. }
  254. Pass
  255. {
  256. Name "Bokeh Depth Of Field Blur"
  257. HLSLPROGRAM
  258. #pragma vertex Vert
  259. #pragma fragment FragBlur
  260. #pragma target 3.5
  261. ENDHLSL
  262. }
  263. Pass
  264. {
  265. Name "Bokeh Depth Of Field Post Blur"
  266. HLSLPROGRAM
  267. #pragma vertex Vert
  268. #pragma fragment FragPostBlur
  269. #pragma target 3.5
  270. ENDHLSL
  271. }
  272. Pass
  273. {
  274. Name "Bokeh Depth Of Field Composite"
  275. HLSLPROGRAM
  276. #pragma vertex Vert
  277. #pragma fragment FragComposite
  278. #pragma target 3.5
  279. #pragma multi_compile_fragment _ _ENABLE_ALPHA_OUTPUT
  280. ENDHLSL
  281. }
  282. }
  283. }