为什么在纹理表面的透明区域和不透明区域之间存在暗边/晕圈(在opengl es 2.0片段着色器中)

时间:2011-10-20 19:52:21

标签: ios png transparency glsl opengl-es-2.0

我正在使用PNG纹理图像来控制Opengl es 2.0着色器(在iOS上)中片段的不透明度。我所追求的结果是在我的场景中灰色背景上的浅灰色文本(片段着色器应用于场景中的三角形条)。问题是我的文本周围有黑边 - 它们看起来像是文物。我正在使用PNG透明度来获取alpha信息 - 但我对其他方法持开放态度。发生了什么事,我怎么能正确地做到这一点?

1 个答案:

答案 0 :(得分:1)

首先,看看这个关于PNG transparency and premultiplied alpha.的答案。长话短说,PNG图像中不透明度低于100%的像素正在被预乘,因此它们实际上变得更暗,因为它们变得更透明。因此,边缘周围的黑色瑕疵。

即使没有PNG和预乘透明度,如果您在应用透明度之前忘记设置片段着色器的颜色,仍可能会遇到问题。

此问题的解决方案(您希望文本为浅灰色,纹理贴图中的所有内容都不是透明的文本)将创建纹理贴图,其中文本为白色,背景为黑色

此纹理贴图将控制片段的alpha。片段的RGB值将设置为浅灰色。

例如:

// color used for text
lowp vec4 textColor = vec4(.82,.82,.82,1.0);

gl_FragColor = textColor;

// greyscale texture passed in as uniform
lowp vec4 alphaMap = texture2D(u_alpha_texture,v_texture);

// set the alpha using the texture  
gl_FragColor.w = alphaMap.x;

如果您的颜色纹理不同,这种方法需要两个单独的纹理贴图图像(一个用于颜色,一个用于alpha)。显然,这与处理具有alpha透明度烘焙的一个PNG相比效率较低。然而,根据我的经验,这是一个很好的权衡(预乘像素可以反直觉处理,而其他加载PNG透明度而没有预乘的方法会增加复杂性。)

这种方法的优点是,您可以独立于纹理贴图图像来改变文本的颜色。例如,如果您想要红色文本,可以将textColor值更改为:

lowp vec4 textColor = vec4(1.0,0.0,0.0,1.0);

您甚至可以随着时间的推移改变颜色等,所有这些都与alpha无关。这就是为什么我发现这种方法是灵活的。