OpenGL学习笔记——Blending

发表于2018-03-03
评论0 3.3k浏览
混合可以实现物体透明度。

实现透明度由两种方式:
  1. 是抛弃(discard)一部分片段,这种情况下,不存在半透明的片段。
  2. 才是真正意义上的混合。将当前片段,和目标片段,按照一定的公式,进行加权计算。

1、
<span style="font-size:14px;">#version 330 core  
out vec4 FragColor;  
in vec2 TexCoords;  
uniform sampler2D texture1;  
void main()  
{               
    vec4 texColor = texture(texture1, TexCoords);  
    if(texColor.a < 0.1)  
        discard;  
    FragColor = texColor;  
}</span> 

丢弃片段的比较暴力了,直接判断alpha<某个常亮的片段,丢弃掉,不过这个if会产生逻辑分支,所以效率也就那样吧……
环绕纹理设置成:GL_CLAMP_TO_EDGE 可以略微提高视觉效果。

2、混合
激活混合用:glEnable(GL_BLEND);

那一大丢丢的参数,其实最常用的也就只有:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
也就是源alpha 和 1-源alpha
这里glBlendFunc是混合操作设置函数。
glBlendFuncSeparate更为鬼畜一些,他可以为颜色和Alpha分别设置操作函数。

这两个都是设置源和目标,如何处理rgb和alpha值的。

glBlendEquation可以用来设置混合运算符。其实最常用的也就是GL_FUNC_ADD

这个函式,是设置用哪个公式去处理这些alpha和RGB值的。

混合的原理:
前提是你已经在混合之前画过一些东西(哪怕只天空盒也OK),不然混合个毛线?
混合的时候,将要绘制的东西是Source,已经画完的东西是Target。
混合的时候,你的Shader里面几乎不用改什么东西,片段会按照混合公式和数值规则,自己去和已经绘制好的片段进行混合。Unity则是在用ShaderLab的语法去设置这些函式的。

之前遇到过的一个问题的解释:
几个月以前,我曾经遇到过一个问题,在我用WorldCreatorPro制作地图的时候,在没有使用SpeedTree而使用切片LOD的时候,也就是离的比较远的时候,树会变成半透明切片。这时候半透明区域会将后面的地形隐藏掉。

现在时候很容易解释这个问题了。借用LearnOpenGL作者的图:
看篮圈的部分:
如果先绘制前面的图,由于Z-Buffer是不理会Alpha的,所以,这里的透明像素也会被写进ZBuffer。
当绘制后面的物体时(无论它是不是透明,只要他比前面物体远)Z-测试会失败,然后对应像素就被丢弃了。

结论:Z-Buffer和Blending一起用的时候,必须先画远处物件再画近处的,才能保证不出错。
那么之前用的树木,即便可以排序,每帧将几千棵树每帧排一次序,然后在渲染,也是非常恐怖的开销,所以索性直接换成SpeedTree好了,直接用模型LOD,也不是用贴图LOD,虽然它确实很省。

方法:如何正确使用Blending。
  1. 先绘制所有不透明的物体。
  2. 对所有透明的物体排序。
  3. 按顺序(由远到进)绘制所有透明的物体。具体来讲,可以按距离插入排序,先画远处,后画近处。

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引