零基础学习OpenGL(五)--混合

        OpenGL中,混合用来实现物体透明度。透明就是说一个物体的颜色是物体本身的颜色和它背后其它物体的颜色的不同强度结合。一个物体的透明度是通过它颜色的aplha值来决定的。

        想加载有alpha值的纹理时,要在纹理生成过程中告诉OpenGL,我们的纹理现在使用alpha通道了:

        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);

        保证你在片段着色器中获取了纹理的全部4个颜色分量,而不仅仅是RGB分量:

        // FragColor = vec4(vec3(texture(texture1, TexCoords)), 1.0);

        FragColor = texture(texture1, TexCoords);

                                                                                              丢弃

         OpenGL默认是不知道怎么处理alpha值的,更不知道什么时候应该丢弃片段。我们需要自己手动来弄。GLSL给了discard命令,一旦被调用,它就会保证片段不会被进一步处理,所以就不会进入颜色缓冲。有了这个指令,我们就能够在片段着色器中检测一个片段的alpha值是否低于某个阈值,如果是的话,则丢弃这个片段,就好像它不存在一样。

           vec4 texColor = texture(texture1, TexCoords);

           if(texColor.a < 0.1)

                  discard;

           FragColor = texColor;

                                                                                                    混合

           启用GL_BLEND来启用混合:    glEnable(GL_BLEND);

           混合方式如下:

            混合时机:片段着色器完成,所有测试都通过后。

             比如两个正方形,如果希望是绿色的正方形在红色正方形之上,源为绿色,目标为红色,如果设置源因子为0.6,目标因子为1 - 0.6 = 0.4,

            

       最终的颜色将会被储存到颜色缓冲中,替代之前的颜色。

       OpenGL使用一个函数设置因子:glBlendFunc。

        glBlendFunc(GLenum sfactor, GLenum dfactor)函数接受两个参数,来设置源和目标因子。OpenGL为我们定义了很多个选项,我们将在下面列出大部分最常用的选项。

      上面例子中使用的就是:glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

       glBlendEquation(GLenum mode)允许我们设置运算符的正负,比如结果等于源+目标或者源-目标等。

       每当OpenGL渲染了一个片段时,它都会将当前片段的颜色和当前颜色缓冲中的片段颜色根据alpha值来进行混合。有个问题:深度测试和混合一起使用的话会产生一些麻烦。当写入深度缓冲时,深度缓冲不会检查片段是否是透明的,所以透明的部分会和其它值一样写入到深度缓冲中。结果就是不论透明度都会进行深度测试。即使透明的部分应该显示背后的窗户,深度测试仍然丢弃了它们。eg:

       要想让混合在多个物体上工作,我们需要最先绘制最远的物体,最后绘制最近的物体。普通不需要混合的物体仍然可以使用深度缓冲正常绘制,所以它们不需要排序。但我们仍要保证它们在绘制(排序的)透明物体之前已经绘制完毕了。当绘制一个有不透明和透明物体的场景的时候,大体的原则如下:

        1.先绘制所有不透明物体;2.对所有透明物体排序;3.按顺序绘制所有透明的物体。(排序透明物体的一种方法是,从观察者视角获取物体的距离。通过计算摄像机位置向量和物体的位置向量之间的距离所获得。)

参考自https://learnopengl-cn.github.io

猜你喜欢

转载自blog.csdn.net/jfy307596479/article/details/84634172
今日推荐