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



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

首先,看看这个关于PNG透明度和预乘法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。这就是为什么我觉得这种方法很灵活。

最新更新