一、丢弃片段
有些图片并不需要半透明,只需要根据纹理颜色值,显示一部分(alpha值为1.0),或者不显示一部分(alpha值为0.0),没有中间情况。我们需要丢弃(Discard)显示纹理中透明部分的片段,不将这些片段存储到颜色缓冲中。
要想加载有alpha值的纹理,我们需要在纹理生成过程中告诉OpenGL,我们的纹理现在使用alpha通道了:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
然后,在片段着色器中检测一个片段的alpha值是否低于某个阈值,如果是的话,则 discard 丢弃这个片段,就好像它不存在一样:
void main()
{
vec4 texColor=texture(material.texture_diffuse1,TexCoords);
if(texColor.a < 0.1) discard;
FragColor = texColor;
}
接着,为避免出现半透明的有色边框,还要将纹理的环绕方式设置为GL_CLAMP_TO_EDGE:
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
效果如下:
二、混合
虽然直接丢弃片段很好,但它不能让我们渲染半透明的图像。我们要么渲染一个片段,要么完全丢弃它。要想渲染有多个透明度级别的图像,我们需要启用混合(Blending):
glEnable(GL_BLEND);
开启混合后,我们还需要告诉OpenGL它该如何混合:
片段着色器运行完成并且所有的测试都通过以后,混合方程才能自由执行片段的颜色输出,当前它在颜色缓冲中(前面片段的颜色在当前片段之前储存)。源和目标颜色会自动被OpenGL设置,而源和目标因子可以让我们自由设置:
void glBlendFunc(GLenum sfactor, GLenum dfactor)
常用参数选项如下:
颜色常数向量C¯constant可以用 glBlendColor
函数分开来设置!
为从两个方块获得混合结果,我们打算把源颜色的 alpha 给源因子,1−alpha 给目标因子。调整到glBlendFunc
之后就像这样:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
由于我们开启了混合,就不需要丢弃片段了,所以我们把片段着色器设置为原来的那个版本:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D texture1;
void main()
{
color = texture(texture1, TexCoords);
}
要让混合在多物体上有效,我们必须先绘制最远的物体,最后绘制最近的物体。普通的无混合物体仍然可以使用深度缓冲正常绘制,所以不必给它们排序。
当无透明度物体和透明物体一起绘制的时候,通常要遵循以下原则:先绘制所有不透明物体。 为所有透明物体排序, 按顺序绘制透明物体。
demo下载:点击跳转
效果如下:
觉得有帮助的话,打赏一下呗。。