DepthOfField34.shader 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
  2. Shader "Hidden/Dof/DepthOfField34" {
  3. Properties {
  4. _MainTex ("Base", 2D) = "" {}
  5. _TapLowBackground ("TapLowBackground", 2D) = "" {}
  6. _TapLowForeground ("TapLowForeground", 2D) = "" {}
  7. _TapMedium ("TapMedium", 2D) = "" {}
  8. }
  9. CGINCLUDE
  10. #include "UnityCG.cginc"
  11. struct v2f {
  12. half4 pos : SV_POSITION;
  13. half2 uv1 : TEXCOORD0;
  14. };
  15. struct v2fDofApply {
  16. half4 pos : SV_POSITION;
  17. half2 uv : TEXCOORD0;
  18. };
  19. struct v2fRadius {
  20. half4 pos : SV_POSITION;
  21. half2 uv : TEXCOORD0;
  22. half4 uv1[4] : TEXCOORD1;
  23. };
  24. struct v2fDown {
  25. half4 pos : SV_POSITION;
  26. half2 uv0 : TEXCOORD0;
  27. half2 uv[2] : TEXCOORD1;
  28. };
  29. sampler2D _MainTex;
  30. sampler2D_float _CameraDepthTexture;
  31. sampler2D _TapLowBackground;
  32. sampler2D _TapLowForeground;
  33. sampler2D _TapMedium;
  34. half4 _CurveParams;
  35. half _ForegroundBlurExtrude;
  36. uniform half3 _Threshhold;
  37. uniform float4 _MainTex_TexelSize;
  38. uniform float2 _InvRenderTargetSize;
  39. v2f vert( appdata_img v ) {
  40. v2f o;
  41. o.pos = UnityObjectToClipPos (v.vertex);
  42. o.uv1.xy = v.texcoord.xy;
  43. return o;
  44. }
  45. v2fRadius vertWithRadius( appdata_img v ) {
  46. v2fRadius o;
  47. o.pos = UnityObjectToClipPos(v.vertex);
  48. o.uv.xy = v.texcoord.xy;
  49. const half2 blurOffsets[4] = {
  50. half2(-0.5, +1.5),
  51. half2(+0.5, -1.5),
  52. half2(+1.5, +0.5),
  53. half2(-1.5, -0.5)
  54. };
  55. o.uv1[0].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[0];
  56. o.uv1[1].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[1];
  57. o.uv1[2].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[2];
  58. o.uv1[3].xy = v.texcoord.xy + 5.0 * _MainTex_TexelSize.xy * blurOffsets[3];
  59. o.uv1[0].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[0];
  60. o.uv1[1].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[1];
  61. o.uv1[2].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[2];
  62. o.uv1[3].zw = v.texcoord.xy + 3.0 * _MainTex_TexelSize.xy * blurOffsets[3];
  63. return o;
  64. }
  65. v2fDofApply vertDofApply( appdata_img v ) {
  66. v2fDofApply o;
  67. o.pos = UnityObjectToClipPos(v.vertex);
  68. o.uv.xy = v.texcoord.xy;
  69. return o;
  70. }
  71. v2fDown vertDownsampleWithCocConserve(appdata_img v) {
  72. v2fDown o;
  73. o.pos = UnityObjectToClipPos(v.vertex);
  74. o.uv0.xy = v.texcoord.xy;
  75. o.uv[0].xy = v.texcoord.xy + half2(-1.0,-1.0) * _InvRenderTargetSize;
  76. o.uv[1].xy = v.texcoord.xy + half2(1.0,-1.0) * _InvRenderTargetSize;
  77. return o;
  78. }
  79. half4 BokehPrereqs (sampler2D tex, half4 uv1[4], half4 center, half considerCoc) {
  80. // @NOTE 1:
  81. // we are checking for 3 things in order to create a bokeh.
  82. // goal is to get the highest bang for the buck.
  83. // 1.) contrast/frequency should be very high (otherwise bokeh mostly unvisible)
  84. // 2.) luminance should be high
  85. // 3.) no occluder nearby (stored in alpha channel)
  86. // @NOTE 2: about the alpha channel in littleBlur:
  87. // the alpha channel stores an heuristic on how likely it is
  88. // that there is no bokeh occluder nearby.
  89. // if we didn't' check for that, we'd get very noise bokeh
  90. // popping because of the sudden contrast changes
  91. half4 sampleA = tex2D(tex, uv1[0].zw);
  92. half4 sampleB = tex2D(tex, uv1[1].zw);
  93. half4 sampleC = tex2D(tex, uv1[2].zw);
  94. half4 sampleD = tex2D(tex, uv1[3].zw);
  95. half4 littleBlur = 0.125 * (sampleA + sampleB + sampleC + sampleD);
  96. sampleA = tex2D(tex, uv1[0].xy);
  97. sampleB = tex2D(tex, uv1[1].xy);
  98. sampleC = tex2D(tex, uv1[2].xy);
  99. sampleD = tex2D(tex, uv1[3].xy);
  100. littleBlur += 0.125 * (sampleA + sampleB + sampleC + sampleD);
  101. littleBlur = lerp (littleBlur, center, saturate(100.0 * considerCoc * abs(littleBlur.a - center.a)));
  102. return littleBlur;
  103. }
  104. half4 fragDownsampleWithCocConserve(v2fDown i) : SV_Target {
  105. half2 rowOfs[4];
  106. rowOfs[0] = half2(0.0, 0.0);
  107. rowOfs[1] = half2(0.0, _InvRenderTargetSize.y);
  108. rowOfs[2] = half2(0.0, _InvRenderTargetSize.y) * 2.0;
  109. rowOfs[3] = half2(0.0, _InvRenderTargetSize.y) * 3.0;
  110. half4 color = tex2D(_MainTex, i.uv0.xy);
  111. half4 sampleA = tex2D(_MainTex, i.uv[0].xy + rowOfs[0]);
  112. half4 sampleB = tex2D(_MainTex, i.uv[1].xy + rowOfs[0]);
  113. half4 sampleC = tex2D(_MainTex, i.uv[0].xy + rowOfs[2]);
  114. half4 sampleD = tex2D(_MainTex, i.uv[1].xy + rowOfs[2]);
  115. color += sampleA + sampleB + sampleC + sampleD;
  116. color *= 0.2;
  117. // @NOTE we are doing max on the alpha channel for 2 reasons:
  118. // 1) foreground blur likes a slightly bigger radius
  119. // 2) otherwise we get an ugly outline between high blur- and medium blur-areas
  120. // drawback: we get a little bit of color bleeding
  121. color.a = max(max(sampleA.a, sampleB.a), max(sampleC.a, sampleD.a));
  122. return color;
  123. }
  124. half4 fragDofApplyBg (v2fDofApply i) : SV_Target {
  125. half4 tapHigh = tex2D (_MainTex, i.uv.xy);
  126. #if UNITY_UV_STARTS_AT_TOP
  127. if (_MainTex_TexelSize.y < 0)
  128. i.uv.xy = i.uv.xy * half2(1,-1)+half2(0,1);
  129. #endif
  130. half4 tapLow = tex2D (_TapLowBackground, i.uv.xy); // already mixed with medium blur
  131. tapHigh = lerp (tapHigh, tapLow, tapHigh.a);
  132. return tapHigh;
  133. }
  134. half4 fragDofApplyBgDebug (v2fDofApply i) : SV_Target {
  135. half4 tapHigh = tex2D (_MainTex, i.uv.xy);
  136. half4 tapLow = tex2D (_TapLowBackground, i.uv.xy);
  137. half4 tapMedium = tex2D (_TapMedium, i.uv.xy);
  138. tapMedium.rgb = (tapMedium.rgb + half3 (1, 1, 0)) * 0.5;
  139. tapLow.rgb = (tapLow.rgb + half3 (0, 1, 0)) * 0.5;
  140. tapLow = lerp (tapMedium, tapLow, saturate (tapLow.a * tapLow.a));
  141. tapLow = tapLow * 0.5 + tex2D (_TapLowBackground, i.uv.xy) * 0.5;
  142. return lerp (tapHigh, tapLow, tapHigh.a);
  143. }
  144. half4 fragDofApplyFg (v2fDofApply i) : SV_Target {
  145. half4 fgBlur = tex2D(_TapLowForeground, i.uv.xy);
  146. #if UNITY_UV_STARTS_AT_TOP
  147. if (_MainTex_TexelSize.y < 0)
  148. i.uv.xy = i.uv.xy * half2(1,-1)+half2(0,1);
  149. #endif
  150. half4 fgColor = tex2D(_MainTex,i.uv.xy);
  151. //fgBlur.a = saturate(fgBlur.a*_ForegroundBlurWeight+saturate(fgColor.a-fgBlur.a));
  152. //fgBlur.a = max (fgColor.a, (2.0 * fgBlur.a - fgColor.a)) * _ForegroundBlurExtrude;
  153. fgBlur.a = max(fgColor.a, fgBlur.a * _ForegroundBlurExtrude); //max (fgColor.a, (2.0*fgBlur.a-fgColor.a)) * _ForegroundBlurExtrude;
  154. return lerp (fgColor, fgBlur, saturate(fgBlur.a));
  155. }
  156. half4 fragDofApplyFgDebug (v2fDofApply i) : SV_Target {
  157. half4 fgBlur = tex2D(_TapLowForeground, i.uv.xy);
  158. half4 fgColor = tex2D(_MainTex,i.uv.xy);
  159. fgBlur.a = max(fgColor.a, fgBlur.a * _ForegroundBlurExtrude); //max (fgColor.a, (2.0*fgBlur.a-fgColor.a)) * _ForegroundBlurExtrude;
  160. half4 tapMedium = half4 (1, 1, 0, fgBlur.a);
  161. tapMedium.rgb = 0.5 * (tapMedium.rgb + fgColor.rgb);
  162. fgBlur.rgb = 0.5 * (fgBlur.rgb + half3(0,1,0));
  163. fgBlur.rgb = lerp (tapMedium.rgb, fgBlur.rgb, saturate (fgBlur.a * fgBlur.a));
  164. return lerp ( fgColor, fgBlur, saturate(fgBlur.a));
  165. }
  166. half4 fragCocBg (v2f i) : SV_Target {
  167. float d = SAMPLE_DEPTH_TEXTURE (_CameraDepthTexture, i.uv1.xy);
  168. d = Linear01Depth (d);
  169. half coc = 0.0;
  170. half focalDistance01 = _CurveParams.w + _CurveParams.z;
  171. if (d > focalDistance01)
  172. coc = (d - focalDistance01);
  173. coc = saturate (coc * _CurveParams.y);
  174. return coc;
  175. }
  176. half4 fragCocFg (v2f i) : SV_Target {
  177. half4 color = tex2D (_MainTex, i.uv1.xy);
  178. color.a = 0.0;
  179. #if UNITY_UV_STARTS_AT_TOP
  180. if (_MainTex_TexelSize.y < 0)
  181. i.uv1.xy = i.uv1.xy * half2(1,-1)+half2(0,1);
  182. #endif
  183. float d = SAMPLE_DEPTH_TEXTURE (_CameraDepthTexture, i.uv1.xy);
  184. d = Linear01Depth (d);
  185. half focalDistance01 = (_CurveParams.w - _CurveParams.z);
  186. if (d < focalDistance01)
  187. color.a = (focalDistance01 - d);
  188. color.a = saturate (color.a * _CurveParams.x);
  189. return color;
  190. }
  191. // not being used atm
  192. half4 fragMask (v2f i) : SV_Target {
  193. return half4(0,0,0,0);
  194. }
  195. // used for simple one one blend
  196. half4 fragAddBokeh (v2f i) : SV_Target {
  197. half4 from = tex2D( _MainTex, i.uv1.xy );
  198. return from;
  199. }
  200. half4 fragAddFgBokeh (v2f i) : SV_Target {
  201. half4 from = tex2D( _MainTex, i.uv1.xy );
  202. return from;
  203. }
  204. half4 fragDarkenForBokeh(v2fRadius i) : SV_Target {
  205. half4 fromOriginal = tex2D(_MainTex, i.uv.xy);
  206. half4 lowRez = BokehPrereqs (_MainTex, i.uv1, fromOriginal, _Threshhold.z);
  207. half4 outColor = half4(0,0,0, fromOriginal.a);
  208. half modulate = fromOriginal.a;
  209. // this code imitates the if-then-else conditions below
  210. half2 conditionCheck = half2( dot(abs(fromOriginal.rgb-lowRez.rgb), half3(0.3,0.5,0.2)), Luminance(fromOriginal.rgb));
  211. conditionCheck *= fromOriginal.a;
  212. conditionCheck = saturate(_Threshhold.xy - conditionCheck);
  213. outColor = lerp (outColor, fromOriginal, saturate (dot(conditionCheck, half2(1000.0,1000.0))));
  214. /*
  215. if ( abs(dot(fromOriginal.rgb - lowRez.rgb, half3 (0.3,0.5,0.2))) * modulate < _Threshhold.x)
  216. outColor = fromOriginal; // no darkening
  217. if (Luminance(fromOriginal.rgb) * modulate < _Threshhold.y)
  218. outColor = fromOriginal; // no darkening
  219. if (lowRez.a < _Threshhold.z) // need to make foreground not cast false bokeh's
  220. outColor = fromOriginal; // no darkenin
  221. */
  222. return outColor;
  223. }
  224. half4 fragExtractAndAddToBokeh (v2fRadius i) : SV_Target {
  225. half4 from = tex2D(_MainTex, i.uv.xy);
  226. half4 lowRez = BokehPrereqs(_MainTex, i.uv1, from, _Threshhold.z);
  227. half4 outColor = from;
  228. // this code imitates the if-then-else conditions below
  229. half2 conditionCheck = half2( dot(abs(from.rgb-lowRez.rgb), half3(0.3,0.5,0.2)), Luminance(from.rgb));
  230. conditionCheck *= from.a;
  231. conditionCheck = saturate(_Threshhold.xy - conditionCheck);
  232. outColor = lerp (outColor, half4(0,0,0,0), saturate (dot(conditionCheck, half2(1000.0,1000.0))));
  233. /*
  234. if ( abs(dot(from.rgb - lowRez.rgb, half3 (0.3,0.5,0.2))) * modulate < _Threshhold.x)
  235. outColor = half4(0,0,0,0); // don't add
  236. if (Luminance(from.rgb) * modulate < _Threshhold.y)
  237. outColor = half4(0,0,0,0); // don't add
  238. if (lowRez.a < _Threshhold.z) // need to make foreground not cast false bokeh's
  239. outColor = half4(0,0,0,0); // don't add
  240. */
  241. return outColor;
  242. }
  243. ENDCG
  244. Subshader {
  245. // pass 0
  246. Pass {
  247. ZTest Always Cull Off ZWrite Off
  248. CGPROGRAM
  249. #pragma vertex vertDofApply
  250. #pragma fragment fragDofApplyBg
  251. ENDCG
  252. }
  253. // pass 1
  254. Pass {
  255. ZTest Always Cull Off ZWrite Off
  256. ColorMask RGB
  257. CGPROGRAM
  258. #pragma vertex vertDofApply
  259. #pragma fragment fragDofApplyFgDebug
  260. ENDCG
  261. }
  262. // pass 2
  263. Pass {
  264. ZTest Always Cull Off ZWrite Off
  265. ColorMask RGB
  266. CGPROGRAM
  267. #pragma vertex vertDofApply
  268. #pragma fragment fragDofApplyBgDebug
  269. ENDCG
  270. }
  271. // pass 3
  272. Pass {
  273. ZTest Always Cull Off ZWrite Off
  274. ColorMask A
  275. CGPROGRAM
  276. #pragma vertex vert
  277. #pragma fragment fragCocBg
  278. ENDCG
  279. }
  280. // pass 4
  281. Pass {
  282. ZTest Always Cull Off ZWrite Off
  283. ColorMask RGB
  284. //Blend One One
  285. CGPROGRAM
  286. #pragma vertex vertDofApply
  287. #pragma fragment fragDofApplyFg
  288. ENDCG
  289. }
  290. // pass 5
  291. Pass {
  292. ZTest Always Cull Off ZWrite Off
  293. ColorMask ARGB
  294. CGPROGRAM
  295. #pragma vertex vert
  296. #pragma fragment fragCocFg
  297. ENDCG
  298. }
  299. // pass 6
  300. Pass {
  301. ZTest Always Cull Off ZWrite Off
  302. CGPROGRAM
  303. #pragma vertex vertDownsampleWithCocConserve
  304. #pragma fragment fragDownsampleWithCocConserve
  305. ENDCG
  306. }
  307. // pass 7
  308. // not being used atm
  309. Pass {
  310. ZTest Always Cull Off ZWrite Off
  311. ColorMask RGBA
  312. CGPROGRAM
  313. #pragma vertex vert
  314. #pragma fragment fragMask
  315. ENDCG
  316. }
  317. // pass 8
  318. Pass {
  319. ZTest Always Cull Off ZWrite Off
  320. Blend SrcAlpha OneMinusSrcAlpha
  321. ColorMask RGB
  322. CGPROGRAM
  323. #pragma vertex vert
  324. #pragma fragment fragAddBokeh
  325. ENDCG
  326. }
  327. // pass 9
  328. Pass {
  329. ZTest Always Cull Off ZWrite Off
  330. Blend One One
  331. ColorMask RGB
  332. CGPROGRAM
  333. #pragma vertex vertWithRadius
  334. #pragma fragment fragExtractAndAddToBokeh
  335. ENDCG
  336. }
  337. // pass 10
  338. Pass {
  339. ZTest Always Cull Off ZWrite Off
  340. CGPROGRAM
  341. #pragma vertex vertWithRadius
  342. #pragma fragment fragDarkenForBokeh
  343. ENDCG
  344. }
  345. // pass 11
  346. Pass {
  347. ZTest Always Cull Off ZWrite Off
  348. CGPROGRAM
  349. #pragma vertex vertWithRadius
  350. #pragma fragment fragExtractAndAddToBokeh
  351. ENDCG
  352. }
  353. }
  354. Fallback off
  355. }