详细请阅读:https://learnopengl-cn.github.io/04%20Advanced%20OpenGL/03%20Blending/
混合
用于混合多种颜色,适用于不透明的场景;
如果是全透明时可以在shader中使用discard字段,显式表示不进行后面的处理;
glEnable(GL_BLEND); // 开启混合测试
glBlendFunc(GLenum sfactor, GLenum dfactor); // 设置源因子和目标因子
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); // 分别设置RGB分量和Alpha的源因子和目标因子
glBlendEquation(GLenum mode); // 设置源颜色 与 目标颜色之间的算术运算
源颜色指源自纹理的颜色向量,目标颜色指存储在颜色缓冲中的颜色向量。
需要特别注意混合与深度测试之间的关系。因为深度测试不关心透明度,如果先绘制了近处的透明物体,那么深度缓冲会被更新为一个比较小的值,此后如果再绘制透明物体后的物体时,将不能通过深度测试,导致透明物体后的物体不显示。对于使用了混合的场景,我们应该使用下面的步骤:
- 先绘制所有不透明的物体。
- 对所有透明的物体排序。
- 按顺序绘制所有透明的物体。
或者在绘制透明物体时关闭深度测试,
- 建议使用glDepthMask(GL_FALSE),防止更新深度缓冲。
- 使用glEnable(GL_DEPTH_TEST)时仍然可以写入深度缓冲,所以不推荐。
面剔除
在顶点着色器之后,光栅化阶段,会执行面剔除。因为我们需要先确定图元与相机的位置与角度关系,才能确定正反面。
默认情况下,正面为顶点逆时针顺序,朝向我们的面,但是我们可以自定义正面。
glFrontFace(GL_CW); // 将顺时针的面定义为正向面,默认 GL_CCW
我们开启面剔除,并指定剔除正面或者背面或者两者。
glEnable(GL_CULL_FACE);
glCullFace(GL_FRONT);
想象一下,你再绘制立方体的六个面时,你需要保证六个面的正面都是朝外,这么当我们从一个方向看向立方体时,光线穿过近面然后再穿过远面,近面的正向面向你,而因为光线是从立方体内穿过远面,远面是反面对着你。
其实当你看向一个立方体时,你最多只能同时看到3个面,而那些你看不到的面都是反面。那么我们就可以通过面剔除去掉那些不需要渲染的面,避免片元着色器做无用功。但是近面是透明物体时,这时就不能剔除反面了。