OpenGL学习脚印:混色(Blending)

写在前面
上一节学习了使用模板缓冲来制作特殊效果,本节将继续学习一个高级主题-混色(Blending)。通过使用混色,我们可以制作透明、半透明效果。本节示例代码均可以在我的github下载

本节内容整理自www.learnopengl.com blending.

混色的概念

所谓混色,就是将当前要绘制的物体的颜色和颜色缓冲区中已经绘制了的物体的颜色进行混合,最终决定了当前物体的颜色。例如下面的图中,狙击枪的瞄准器本身是带有蓝色的,将它和后面的任务混合在一起,形成了我们看到的最终效果,这个效果里既有瞄准器的蓝色成分,也有后面人物的像素,主要是后面人物的像素。

颜色混合

实际上我们通过玻璃看到外面的景象就是一种混色,有的玻璃完全透明则主要显示外面的景象,而另一些玻璃不是完全透明则成像中包含一部分玻璃的颜色。在OpenGL中使用混色,可以实现很多效果,其中比较常见的就是透明效果。下面具体实现完全透明和半透明效果。

完全透明效果

完全透明表现的是,当前物体例如透明玻璃,将后面的像素完全展示出来,而当前物体则不必显示。实现完全透明效果,我们通过对物体的透明度进行判断,当小于一定阈值,例如0.1时,我们则丢弃该片元,使其后面的片元得到显示。
首先我们加载一个草的模型,对于草这种模型,它要么完全透明,可以透过它看到后面的物体,要么不透明展示为草的细节。绘制草这种模型时,我们通过往矩形块上添加草的纹理来实现。加载了草的模型,使用深度测试一节的立方体,绘制出来的效果如下:

没有使用透明

这里我们看到,草模型中透明部分和不透明部分没有得到区分,因而挡住了后面的立方体和草模型。在RGBA表达的颜色重,alpha成分一直以来,我们都是设置为1.0,实际上这个分量表达的就是透明度。1.0表示为完全不透明,0.0则表示完全透明。我们可以根据加载的草模型的alpha值判断是否应该丢弃片元来实现透明效果。

加载RGBA模型,和之前一直实现的加载RGB模型,有少许不同,我们要注意两点:

  • 使用SOIL库的时候参数要从SOIL_LOAD_RGB改为SOIL_LOAD_RGBA

  • glTexImage2D中图片格式和内部表示要从GL_RGB改为GL_RGBA.

  • glTexParameteri纹理的wrap方式需要从GL_REPEAT改为GL_CLAMP_TO_EDGE,这个主要是为了防止由于使用GL_REPEAT时纹理边缘部分插值导致出现我们不需要的半透明的效果

加载纹理的函数声明为:

static  GLuint load2DTexture(const char* filename, GLint internalFormat = GL_RGB,
        GLenum picFormat = GL_RGB, int loadChannels = SOIL_LOAD_RGB, GLboolean alpha=false);

完整的实现可以参考texture.h

在代码中加载纹理变更为:

GLuint transparentTextId =TextureHelper::load2DTexture(
"grass.png", GL_RGBA, GL_RGBA, SOIL_LOAD_RGBA, true);

在片元着色器中,根据alpha值是否小于设定的阈值,我们决定是否丢弃片元:

#version 330 core
in vec2 TextCoord;
uniform sampler2D text;
out vec4 color;
void main()
{
    vec4 textColor = texture(text, TextCoord);
    if(textColor.a < 0.1)  // < 0.1则丢弃片元 
        discard;
    color = textColor;
}

这种方法实现的透明效果如下图所示:

透明效果

使用alpha值决定是否丢弃片元,我们实现的透明效果是要么完全透明(alpha <0.1),要么不透明(alpha >= 0.1)。实际应用中还需要使用半透明效果。

OpenGL中混色计算

混色后可以通过当前物体看到其后的物体,这里当前物体的最终颜色是由当前物体的颜色(源的颜色 source color)和颜色缓冲区中的颜色(目的颜色 destination color)混色决定的,也就是进行相应的混合计算得到的。

要开启混色功能需要使用:

   glEnable(GL_BLEND);

混色是计算出来的,主体的公式是这样的:

Result=so

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值