Learn OpenGL 笔记5.3 Blending

OpenGL 中的混合通常被称为在对象内实现透明度的技术。

基础知识:

1.Discarding fragments(丢弃片段)

当将植被添加到场景中时,我们不想看到草的方形图像,而只想显示实际的草并看穿图像的其余部分。

Learn OpenGL 笔记5.3 Blending_第1张图片

#version 330 core
out vec4 FragColor;

in vec2 TexCoords;

uniform sampler2D texture1;

void main()
{             
    vec4 texColor = texture(texture1, TexCoords);
    //颜色中的透明度小于0.1直接丢弃这个fragment
    if(texColor.a < 0.1)
        discard;
    FragColor = texColor;
}

 为了防止上面边缘的透明部分,因为repeat显示底下的部分,对最底下进行插值,变成半透明了,需要加上这一行:

glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);	
glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);   

Learn OpenGL 笔记5.3 Blending_第2张图片

 2.Blending(混合)

开启混合:

glEnable(GL_BLEND); 

Learn OpenGL 笔记5.3 Blending_第3张图片

C-source:源颜色向量,这是fragment本应显示的片段

C-destination:目的颜色,这是当前的color buffer中存储的颜色

F-source: 源 factor value(因子),源透明度值

F-destination: color buffer中存储的透明度值

总结:本身颜色*透明度 + 缓存中的颜色*透明度

假设:自身透明度0.6,而buffer中的颜色透明度为1:

Learn OpenGL 笔记5.3 Blending_第4张图片

 Learn OpenGL 笔记5.3 Blending_第5张图片

 glBlendFunc(GLenum sfactor, GLenum dfactor) 混合函数

两个参数来设置源和目标因子的选项。

glBlendFunc()设置alpha,取源透明度a,并取1-a为目标透明度

glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  

 其他参数设置:

Learn OpenGL 笔记5.3 Blending_第6张图片

 也可以分开配置RGB和alpha(glBlendFunc函数是直接一起配置了):

glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);

glBlendEquation(GLenum mode)  OpenGL 允许我们在等式的源和目标部分之间使用其他运算符,加减乘除最大值之类的。

3.Rendering semi-transparent textures(渲染半透明贴图)

 必须按顺序渲染,不然会出现这种情况,前面的正方形先渲染(边角也没做discard丢弃处理)

结果渲染后面的fragment的时候,depth检测到被覆盖,直接不渲染了。 

Learn OpenGL 笔记5.3 Blending_第7张图片

 遵守顺序:

  1. Draw all opaque objects first. (不透明先渲染)
  2. Sort all the transparent objects. (对所有透明的东西进行排序)
  3. Draw all the transparent objects in sorted order. (对透明的东西按排序进行渲染)

透明物体-排序算法: 对物品(窗户)距离camera进行排序

    // transparent window locations
    // --------------------------------
    vector windows
    {
        glm::vec3(-1.5f, 0.0f, -0.48f),
        glm::vec3( 1.5f, 0.0f, 0.51f),
        glm::vec3( 0.0f, 0.0f, 0.7f),
        glm::vec3(-0.3f, 0.0f, -2.3f),
        glm::vec3( 0.5f, 0.0f, -0.6f)
    };

    // sort the transparent windows before rendering
    // ---------------------------------------------
    std::map sorted;
    for (unsigned int i = 0; i < windows.size(); i++)
    {
        float distance = glm::length(camera.Position - windows[i]);
        sorted[distance] = windows[i];
    }

对排好序的窗户进行遍历:存在了一个map中,用STL的方法进行遍历

        for (std::map::reverse_iterator it = sorted.rbegin(); it != sorted.rend(); ++it)
        {
            model = glm::mat4(1.0f);
            model = glm::translate(model, it->second);
            shader.setMat4("model", model);
            glDrawArrays(GL_TRIANGLES, 0, 6);
        }

对场景中的对象进行排序是一项艰巨的任务,这在很大程度上取决于您拥有的场景类型。

你可能感兴趣的:(图形学,opengles)