在WPF像素着色器效果中处理Alpha通道

van*_*lle 9 wpf alphablending pixel pixel-shader

关于如何在像素着色器中处理alpha分量有什么不寻常之处吗?我有一个WPF应用程序,我的艺术家为我提供灰度图像作为背景,应用程序根据当前状态着色这些图像.所以我写了一个像素着色器(使用WPF像素着色器效果库基础结构)来用作Image元素的效果.着色器将颜色作为参数,将其转换为HSL,以便操作亮度.然后,对于每个灰色像素,它计算亮度在颜色参数和白色之间插入的颜色与源像素的亮度成比例.

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 src = tex2D(implicitInputSampler, uv);

    // ...Do messy computation involving src brightness and color parameter...

    float4 dst;
    dst.r = ...
    dst.g = ...
    dst.b = ...
    dst.a = src.a;
    return dst;
}
Run Code Online (Sandbox Code Playgroud)

这对于alpha = 1的像素效果很好.但是在alpha = 0的情况下,结果像素变白,而不是让窗口的背景显示出来.所以我做了一个微小的改变:

float4 main(float2 uv : TEXCOORD) : COLOR
{
    float4 src = tex2D(implicitInputSampler, uv);
    if (src.a == 0) 
        return src;
    ...
Run Code Online (Sandbox Code Playgroud)

而现在透明的部分确实是透明的.为什么?为什么dst.a = src.a第一个版本的声明没有实现呢?不幸的是,即使这只是一个部分修复,因为它看起来像0 <alpha <1的像素是白色的.

有谁知道我不了解alpha?

van*_*lle 24

经过一些网络搜索,我发现了我失踪的那篇文章.

根据MSDN的一篇文章:"由于许多性能原因,WPF在内部到处使用预乘的alpha,所以这也是我们解释自定义像素着色器中颜色值的方式."

所以修复结果是抛出乘以alpha:

float4 main(float2 uv : TEXCOORD) : COLOR
{
    ...
    dst.rgb *= src.a;
    return dst;
}
Run Code Online (Sandbox Code Playgroud)

现在我的输出看起来像我期望的那样.