GLSL预乘Alpha合成导致圆角矩形阴影异常问题解决
带投影阴影的圆角矩形Shader预乘Alpha合成问题
我编写了一个带投影阴影的圆角矩形Shader(网上现有示例无法完全满足需求),使用SDF公式变体绘制圆角矩形,用smoothstep实现阴影模糊,采用SDF抗锯齿公式。
单独显示抗锯齿矩形正常,但在预乘Alpha目标(Vulkan交换链图像,开启VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR)上将矩形与阴影混合时,矩形角落像素直接透显至背景,阴影完全不显示,看起来像是矩形彻底遮挡了阴影。
我判断问题出在对Alpha合成公式的误解(参考维基百科Alpha合成相关内容),但无法自行修正。
问题截图


初始GLSL片段Shader代码
#version 450 layout(location=0) out vec4 outColor; float sdfRoundedRectangle(vec2 p, vec2 b, float r) { vec2 q = abs(p) - b + r; return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r; } vec2 extent = vec2(600.0, 400.0); float cornerRadius = 10.0; float blurRadius = 20.0; vec3 fragColor = vec3(0.2, 0.5, 0.5); vec3 shadowPaint = vec3(0.0); void main() { vec2 center = extent.xy / 2.0; vec2 size = (extent.xy / 2.0) - blurRadius; float boxDistance = sdfRoundedRectangle(gl_FragCoord.xy - center, size, cornerRadius); float boxAlpha = clamp(0.5 - boxDistance, 0.0, 1.0); float shadowAlpha = 1.0 - smoothstep(-blurRadius, blurRadius, boxDistance); float outAlpha = boxAlpha + (shadowAlpha * (1.0 - boxAlpha)); vec3 outRgb = ((fragColor * boxAlpha) + (shadowPaint * shadowAlpha * (1.0 - boxAlpha))) / outAlpha; outColor = vec4(outRgb * outAlpha, outAlpha); }
更新1
直接将矩形与阴影的Alpha值相加(而非阴影Alpha乘以矩形Alpha的补值),视觉效果更自然,但不确定是否正确,附红色阴影截图:


修改代码行:
float outAlpha = clamp(boxAlpha + shadowAlpha, 0.0, 1.0);
更新2:问题已解决
发现维基百科页面下方有不除以输出Alpha的公式变体,此前错误使用了适用于Straight Alpha的公式。最终解决方案代码如下:
/* ... */ float boxAlpha = clamp(0.5 - boxDistance, 0.0, 1.0); float shadowAlpha = 1.0 - smoothstep(-blurRadius, blurRadius, boxDistance); vec3 boxColor = fragColor * boxAlpha; vec3 shadowColor = shadowPaint * shadowAlpha; float outAlpha = boxAlpha + (shadowAlpha * (1.0 - boxAlpha)); vec3 outRgb = boxColor + (shadowColor * (1.0 - boxAlpha)); outColor = vec4(outRgb * outAlpha, outAlpha); }
解决后效果截图:

内容的提问来源于stack exchange,提问作者Chase Patterson
相关产品推荐
相关产品推荐

