ssss-blur.effect 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
  2. CCEffect %{
  3. techniques:
  4. - passes:
  5. - vert: blur-vs
  6. frag: copy-fs
  7. pass: copy-pass
  8. depthTest: false
  9. depthWrite: false
  10. - vert: blur-vs
  11. frag: ssssBlurX-fs
  12. pass: ssss-blurX
  13. depthStencilState:
  14. depthTest: false
  15. depthWrite: false
  16. stencilTestFront: true
  17. stencilFuncFront: equal
  18. stencilRef: 0x78 # [0~255],use 120
  19. - vert: blur-vs
  20. frag: ssssBlurY-fs
  21. pass: ssss-blurY
  22. depthStencilState:
  23. depthTest: false
  24. depthWrite: false
  25. stencilTestFront: true
  26. stencilFuncFront: equal
  27. stencilRef: 0x78 # [0~255],use 120
  28. }%
  29. CCProgram blur-vs %{
  30. #include <./post-process/chunks/vs>
  31. }%
  32. CCProgram copy-fs %{
  33. precision highp float;
  34. #include <builtin/uniforms/cc-global>
  35. #include <common/data/packing>
  36. #pragma rate depthRaw pass
  37. uniform sampler2D depthRaw;
  38. in vec2 v_uv;
  39. layout(location = 0) out vec4 fragColor;
  40. void main() {
  41. float depth = texture(depthRaw, v_uv).r;
  42. fragColor = packDepthToRGBA(depth);
  43. }
  44. }%
  45. CCProgram ssssBlur %{
  46. precision highp float;
  47. #include <common/common-define>
  48. #include <common/math/number>
  49. #include <common/data/packing>
  50. #include <common/color/gamma>
  51. #include <common/math/coordinates>
  52. #pragma define NUMKERNEL 25
  53. #pragma define RANGE (NUMKERNEL > 20 ? 3.0 : 2.0)
  54. uniform blurUBO {
  55. highp vec4 blurInfo; // x: ssssFov; y: ssssWidth; z: boundingBox; w: scale;
  56. highp vec4 kernel[NUMKERNEL];
  57. };
  58. #pragma rate colorTex pass
  59. uniform sampler2D colorTex;
  60. #pragma rate depthTex pass
  61. uniform sampler2D depthTex;
  62. // force clamped sample
  63. vec2 fixUV(vec2 uv)
  64. {
  65. return saturate(uv);
  66. }
  67. /**
  68. * @param texcoord The usual quad texture coordinates.
  69. * @param dir Direction of the blur:
  70. * - First pass: float2(1.0, 0.0)
  71. * - Second pass: float2(0.0, 1.0)
  72. */
  73. vec4 blur(vec2 texcoord, vec2 dir) {
  74. float ssssFov = blurInfo.x;
  75. // This parameter specifies the global level of subsurface scattering
  76. // or, in other words, the width of the filter. It's specified in
  77. // world space units.
  78. float ssssWidth = blurInfo.y;
  79. float boundingBox = blurInfo.z;
  80. float depthUnitScale = boundingBox * blurInfo.w;
  81. // Fetch color of current pixel:
  82. // Use Sample_Point_Clamp
  83. vec4 colorM = texture(colorTex, texcoord);
  84. #if !CC_USE_HDR
  85. colorM = vec4(LinearToSRGB(colorM.rgb), colorM.a);
  86. #endif
  87. // valid range is 0 - 0.9, same as skin output alpha
  88. // msaa do not support ranged intensity, fallback to boolean
  89. float threshold = 0.9, rangeScale = 1.0 / 0.9;
  90. // #if MSAA_ENABLE
  91. // threshold = 0.0;
  92. // rangeScale = 1.0;
  93. // #endif
  94. float SSSS_STRENGTH_SOURCE = colorM.a > threshold ? 0.0 : colorM.a * rangeScale;
  95. #define SSSS_STRENGTH_SOURCE_INLOOP (color.a > threshold ? 0.0 : color.a * rangeScale)
  96. // Fetch linear depth of current pixel:
  97. // Use Sample_Point_Clamp
  98. float depthHS = unpackRGBAToDepth(texture(depthTex, texcoord)) * 2.0 - 1.0; // -1.0 ~ +1.0
  99. float depthM = -GetCameraDepthRH(depthHS, cc_matProj);
  100. // Calculate the ssssWidth scale (1.0 for a unit plane sitting on the projection window):
  101. float distanceToProjectionWindow = 1.0 / tan(0.5 * ssssFov);
  102. float scale = distanceToProjectionWindow / depthM * depthUnitScale;
  103. // Calculate the final step to fetch the surrounding pixels:
  104. vec2 finalStep = vec2(ssssWidth) * vec2(scale) * dir;
  105. // Modulate it using the alpha channel.
  106. finalStep *= vec2(SSSS_STRENGTH_SOURCE);
  107. // Divide by 3 as the kernels range from -3 to 3.
  108. finalStep *= vec2(1.0 / RANGE);
  109. // Accumulate the center sample:
  110. vec4 colorBlurred = colorM;
  111. colorBlurred.rgb *= kernel[0].rgb;
  112. // Accumulate the other samples:
  113. for (int i = 1; i < NUMKERNEL; i++) {
  114. // Fetch color and depth for current sample:
  115. vec2 offset = texcoord + vec2(kernel[i].a) * finalStep;
  116. // Use Sample_Point_Clamp
  117. vec4 color = texture(colorTex, fixUV(offset));
  118. #if !CC_USE_HDR
  119. color = vec4(LinearToSRGB(color.rgb), color.a);
  120. #endif
  121. // caution for NaN
  122. //if (isnan(dot(color, color)) || isinf(dot(color, color))) continue;
  123. // If the difference in depth is huge, we lerp color back to "colorM":
  124. float depthHS = unpackRGBAToDepth(texture(depthTex, fixUV(offset))) * 2.0 - 1.0;
  125. float depth = -GetCameraDepthRH(depthHS, cc_matProj);
  126. float s = saturate(100.0 / depthUnitScale * distanceToProjectionWindow * ssssWidth * abs(depthM - depth));
  127. color.rgb = mix(color.rgb, colorM.rgb, s);
  128. colorBlurred.rgb += kernel[i].rgb * mix(colorM.rgb, color.rgb, SSSS_STRENGTH_SOURCE_INLOOP);
  129. }
  130. #if !CC_USE_HDR
  131. colorBlurred = vec4(SRGBToLinear(colorBlurred.rgb), colorBlurred.a);
  132. #endif
  133. return colorBlurred;
  134. }
  135. }%
  136. CCProgram ssssBlurX-fs %{
  137. precision highp float;
  138. #include <builtin/uniforms/cc-global>
  139. #include <ssssBlur>
  140. in vec2 v_uv;
  141. layout(location = 0) out vec4 fragColor;
  142. void main() {
  143. fragColor = blur(v_uv, vec2(1.0, 0.0));
  144. }
  145. }%
  146. CCProgram ssssBlurY-fs %{
  147. precision highp float;
  148. #include <builtin/uniforms/cc-global>
  149. #include <ssssBlur>
  150. in vec2 v_uv;
  151. layout(location = 0) out vec4 fragColor;
  152. void main() {
  153. fragColor = vec4(blur(v_uv, vec2(0.0, 1.0)).rgb, 1.0);
  154. }
  155. }%