Is there something unusual about how the alpha component is handled in a pixel shader? I have a WPF application for which my artist is giving me grayscale images to use as backgrounds, and the application colorizes those images according to the current state. So I wrote a pixel shader (using the WPF Pixel Shader Effects Library infrastructure) to use as an effect on an Image element. The shader takes a color as a parameter, which it converts to HSL so it can manipulate brightness. Then for each grey pixel, it computes a color whose brightness is interpolated between the color parameter and white in proportion to the brightness of the source pixel.
关于如何在像素着色器中处理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;
}
This works just fine on the pixels where alpha = 1. But where alpha = 0, the resultant pixels come out white, rather than having the window's background show through. So I made a tiny change:
这对于alpha = 1的像素效果很好。但是在alpha = 0的情况下,结果像素变为白色,而不是让窗口的背景显示出来。所以我做了一个微小的改变:
float4 main(float2 uv : TEXCOORD) : COLOR
{
float4 src = tex2D(implicitInputSampler, uv);
if (src.a == 0)
return src;
...
and now the transparent parts really are transparent. Why? Why didn't the dst.a = src.a
statement in the first version accomplish that? Unfortunately, even this is only a partial fix, because it looks to me like the pixels with 0 < alpha < 1 are coming out white.
而现在透明的部分确实是透明的。为什么?为什么第一个版本中的dst.a = src.a语句没有实现呢?不幸的是,即使这只是一个部分修复,因为它看起来像0
Does anyone know what I'm not understanding about alpha?
有谁知道我不了解alpha?
3 个解决方案
#1
21
After some more web searching, I discovered the piece I was missing.
经过一些网络搜索,我发现了我失踪的那篇文章。
According to an article on MSDN: "WPF uses pre-multiplied alpha everywhere internally for a number of performance reasons, so that's also the way we interpret the color values in the custom pixel shader."
根据MSDN上的一篇文章:“由于许多性能原因,WPF在内部到处使用预乘的alpha,因此这也是我们解释自定义像素着色器中颜色值的方式。”
So the fix turns out to be to throw in a multiplication by alpha:
所以修复结果是抛出乘以alpha:
float4 main(float2 uv : TEXCOORD) : COLOR
{
...
dst.rgb *= src.a;
return dst;
}
And now my output looks as I expect it to.
现在我的输出看起来像我期望的那样。
#2
-1
0 < alpha < 1 are coming out white
0
What ranges are you expecting here?
你在这里期待什么范围?
All values are going to be in the range 0.0 and 1.0... pixel shaders do not work in discrete 256 colour ranges, they are floating point where 1.0 is the maximum intensity.
所有值都将在0.0和1.0范围内...像素着色器在离散的256色范围内不起作用,它们是浮点,其中1.0是最大强度。
If your calculations end up setting r/g/b values to >1.0 you are going to get white...
如果你的计算结果将r / g / b值设置为> 1.0,你就会变白......
http://www.facewound.com/tutorials/shader1/
http://www.facewound.com/tutorials/shader1/
#3
-1
Dude I am working on a XNA game, and I had to use a grayscale pixel shader and I got the same problem you are facing. I donno if you are familiar with XNA environment or not, but I solved the problem by changing the SpriteBatch drawing SpriteBlendMode from SpriteBlendMode.None to SpriteBlendMode.AlphaBlend, I hope this can help you knowing the reason.
老兄,我正在研究XNA游戏,我不得不使用灰度像素着色器,我遇到了你面临的同样问题。我不知道你是否熟悉XNA环境,但我通过将SpriteBatch SpriteBlendMode从SpriteBlendMode.None更改为SpriteBlendMode.AlphaBlend解决了这个问题,我希望这可以帮助你了解原因。
regards,
问候,
#1
21
After some more web searching, I discovered the piece I was missing.
经过一些网络搜索,我发现了我失踪的那篇文章。
According to an article on MSDN: "WPF uses pre-multiplied alpha everywhere internally for a number of performance reasons, so that's also the way we interpret the color values in the custom pixel shader."
根据MSDN上的一篇文章:“由于许多性能原因,WPF在内部到处使用预乘的alpha,因此这也是我们解释自定义像素着色器中颜色值的方式。”
So the fix turns out to be to throw in a multiplication by alpha:
所以修复结果是抛出乘以alpha:
float4 main(float2 uv : TEXCOORD) : COLOR
{
...
dst.rgb *= src.a;
return dst;
}
And now my output looks as I expect it to.
现在我的输出看起来像我期望的那样。
#2
-1
0 < alpha < 1 are coming out white
0
What ranges are you expecting here?
你在这里期待什么范围?
All values are going to be in the range 0.0 and 1.0... pixel shaders do not work in discrete 256 colour ranges, they are floating point where 1.0 is the maximum intensity.
所有值都将在0.0和1.0范围内...像素着色器在离散的256色范围内不起作用,它们是浮点,其中1.0是最大强度。
If your calculations end up setting r/g/b values to >1.0 you are going to get white...
如果你的计算结果将r / g / b值设置为> 1.0,你就会变白......
http://www.facewound.com/tutorials/shader1/
http://www.facewound.com/tutorials/shader1/
#3
-1
Dude I am working on a XNA game, and I had to use a grayscale pixel shader and I got the same problem you are facing. I donno if you are familiar with XNA environment or not, but I solved the problem by changing the SpriteBatch drawing SpriteBlendMode from SpriteBlendMode.None to SpriteBlendMode.AlphaBlend, I hope this can help you knowing the reason.
老兄,我正在研究XNA游戏,我不得不使用灰度像素着色器,我遇到了你面临的同样问题。我不知道你是否熟悉XNA环境,但我通过将SpriteBatch SpriteBlendMode从SpriteBlendMode.None更改为SpriteBlendMode.AlphaBlend解决了这个问题,我希望这可以帮助你了解原因。
regards,
问候,