| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- // Copyright (c) 2017-2020 Xiamen Yaji Software Co., Ltd.
- CCEffect %{
- techniques:
- - passes:
- - vert: blur-vs
- frag: copy-fs
- pass: copy-pass
- depthTest: false
- depthWrite: false
- - vert: blur-vs
- frag: ssssBlurX-fs
- pass: ssss-blurX
- depthStencilState:
- depthTest: false
- depthWrite: false
- stencilTestFront: true
- stencilFuncFront: equal
- stencilRef: 0x78 # [0~255],use 120
- - vert: blur-vs
- frag: ssssBlurY-fs
- pass: ssss-blurY
- depthStencilState:
- depthTest: false
- depthWrite: false
- stencilTestFront: true
- stencilFuncFront: equal
- stencilRef: 0x78 # [0~255],use 120
- }%
- CCProgram blur-vs %{
- #include <./post-process/chunks/vs>
- }%
- CCProgram copy-fs %{
- precision highp float;
- #include <builtin/uniforms/cc-global>
- #include <common/data/packing>
- #pragma rate depthRaw pass
- uniform sampler2D depthRaw;
- in vec2 v_uv;
- layout(location = 0) out vec4 fragColor;
- void main() {
- float depth = texture(depthRaw, v_uv).r;
- fragColor = packDepthToRGBA(depth);
- }
- }%
- CCProgram ssssBlur %{
- precision highp float;
- #include <common/common-define>
- #include <common/math/number>
- #include <common/data/packing>
- #include <common/color/gamma>
- #include <common/math/coordinates>
- #pragma define NUMKERNEL 25
- #pragma define RANGE (NUMKERNEL > 20 ? 3.0 : 2.0)
- uniform blurUBO {
- highp vec4 blurInfo; // x: ssssFov; y: ssssWidth; z: boundingBox; w: scale;
- highp vec4 kernel[NUMKERNEL];
- };
- #pragma rate colorTex pass
- uniform sampler2D colorTex;
- #pragma rate depthTex pass
- uniform sampler2D depthTex;
- // force clamped sample
- vec2 fixUV(vec2 uv)
- {
- return saturate(uv);
- }
- /**
- * @param texcoord The usual quad texture coordinates.
- * @param dir Direction of the blur:
- * - First pass: float2(1.0, 0.0)
- * - Second pass: float2(0.0, 1.0)
- */
- vec4 blur(vec2 texcoord, vec2 dir) {
- float ssssFov = blurInfo.x;
- // This parameter specifies the global level of subsurface scattering
- // or, in other words, the width of the filter. It's specified in
- // world space units.
- float ssssWidth = blurInfo.y;
- float boundingBox = blurInfo.z;
- float depthUnitScale = boundingBox * blurInfo.w;
- // Fetch color of current pixel:
- // Use Sample_Point_Clamp
- vec4 colorM = texture(colorTex, texcoord);
- #if !CC_USE_HDR
- colorM = vec4(LinearToSRGB(colorM.rgb), colorM.a);
- #endif
- // valid range is 0 - 0.9, same as skin output alpha
- // msaa do not support ranged intensity, fallback to boolean
- float threshold = 0.9, rangeScale = 1.0 / 0.9;
- // #if MSAA_ENABLE
- // threshold = 0.0;
- // rangeScale = 1.0;
- // #endif
- float SSSS_STRENGTH_SOURCE = colorM.a > threshold ? 0.0 : colorM.a * rangeScale;
- #define SSSS_STRENGTH_SOURCE_INLOOP (color.a > threshold ? 0.0 : color.a * rangeScale)
- // Fetch linear depth of current pixel:
- // Use Sample_Point_Clamp
- float depthHS = unpackRGBAToDepth(texture(depthTex, texcoord)) * 2.0 - 1.0; // -1.0 ~ +1.0
- float depthM = -GetCameraDepthRH(depthHS, cc_matProj);
- // Calculate the ssssWidth scale (1.0 for a unit plane sitting on the projection window):
- float distanceToProjectionWindow = 1.0 / tan(0.5 * ssssFov);
- float scale = distanceToProjectionWindow / depthM * depthUnitScale;
- // Calculate the final step to fetch the surrounding pixels:
- vec2 finalStep = vec2(ssssWidth) * vec2(scale) * dir;
- // Modulate it using the alpha channel.
- finalStep *= vec2(SSSS_STRENGTH_SOURCE);
- // Divide by 3 as the kernels range from -3 to 3.
- finalStep *= vec2(1.0 / RANGE);
- // Accumulate the center sample:
- vec4 colorBlurred = colorM;
- colorBlurred.rgb *= kernel[0].rgb;
- // Accumulate the other samples:
- for (int i = 1; i < NUMKERNEL; i++) {
- // Fetch color and depth for current sample:
- vec2 offset = texcoord + vec2(kernel[i].a) * finalStep;
- // Use Sample_Point_Clamp
- vec4 color = texture(colorTex, fixUV(offset));
- #if !CC_USE_HDR
- color = vec4(LinearToSRGB(color.rgb), color.a);
- #endif
- // caution for NaN
- //if (isnan(dot(color, color)) || isinf(dot(color, color))) continue;
- // If the difference in depth is huge, we lerp color back to "colorM":
- float depthHS = unpackRGBAToDepth(texture(depthTex, fixUV(offset))) * 2.0 - 1.0;
- float depth = -GetCameraDepthRH(depthHS, cc_matProj);
- float s = saturate(100.0 / depthUnitScale * distanceToProjectionWindow * ssssWidth * abs(depthM - depth));
- color.rgb = mix(color.rgb, colorM.rgb, s);
- colorBlurred.rgb += kernel[i].rgb * mix(colorM.rgb, color.rgb, SSSS_STRENGTH_SOURCE_INLOOP);
- }
- #if !CC_USE_HDR
- colorBlurred = vec4(SRGBToLinear(colorBlurred.rgb), colorBlurred.a);
- #endif
- return colorBlurred;
- }
- }%
- CCProgram ssssBlurX-fs %{
- precision highp float;
- #include <builtin/uniforms/cc-global>
- #include <ssssBlur>
- in vec2 v_uv;
- layout(location = 0) out vec4 fragColor;
- void main() {
- fragColor = blur(v_uv, vec2(1.0, 0.0));
- }
- }%
- CCProgram ssssBlurY-fs %{
- precision highp float;
- #include <builtin/uniforms/cc-global>
- #include <ssssBlur>
- in vec2 v_uv;
- layout(location = 0) out vec4 fragColor;
- void main() {
- fragColor = vec4(blur(v_uv, vec2(0.0, 1.0)).rgb, 1.0);
- }
- }%
|