【C++ OpenGL入门-7】使用多个纹理

20 阅读2分钟

最新大型开源项目-云游戏,云桌面系统,欢迎关注

GammaRay源码地址

本项目代码仓库

点击这里

1.加载一张PNG的图片

上一章我们已经成功的显示了一张JPG格式的图片,其颜色格式为RGB。这次我们添加一张PNG格式的图片,颜色格式为RGBA。图片如下所示:

加载的方式与之前是完全相同的,只不过格式稍加改变,将GL_RGB改为GL_RGBA,代码参见:

GLuint texture_logo;
glGenTextures(1, &texture_logo);
glBindTexture(GL_TEXTURE_2D, texture_logo);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTextureParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// Load Image
int logo_width, logo_height, logo_channels;
stbi_set_flip_vertically_on_load(true);
unsigned char* logo_data = stbi_load("../resources/images/logo_big.png", &logo_width, &logo_height, &logo_channels, 0 );
if (logo_data) {
	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, logo_data);
	glGenerateMipmap(GL_TEXTURE_2D);
}
2.纹理单元

之前我们仅仅使用一张图片时,并没有特殊处理,直接在片段着色器中采样它就可以了。
但是,有个细节,我们声明的uniform sampler2D image,这个变量,并没有给他赋值,却可以直接使用。
因为OpenGL默认将它绑定在了第0个纹理单元,也就是默认开启的纹理单元。现在如果使用更多的纹理单元,那么就要手动指定了。

  • 2.1 首先,需要将我们的片段着色器修改一下,即再声明一个纹理的uniform变量,修改如下:
#version 330 core
in vec3 outColor;
in vec2 outTex;

uniform sampler2D image;
uniform sampler2D image2;

void main()
{
    vec4 color = texture(image, outTex);
    vec4 color2 = texture(image2, outTex);
    gl_FragColor = mix(color, color2, 0.5);
}

首先添加了一个image2的变量,然后用texture函数采样它,然后将 color与color2混合后输出。
mix函数作用是混合两个颜色,其最后一个参数表达的是两个颜色的贡献比。
比如 0.3,那么color2贡献0.3, color贡献0.7.

  • 2.2 在代码中使用它 使用一张图片时,并没有做激活纹理单元的操作,因为有默认的使用,但多于一个纹理时,就要手动操作:
//激活纹理单元0
glActiveTexture(GL_TEXTURE0);
//绑定这个纹理单元
glBindTexture(GL_TEXTURE_2D, texture);
//告诉OpenGL,image这个要绑定第0个纹理单元
shader->SetUniform1i("image", 0);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, texture_logo);
shader->SetUniform1i("image2", 1);
  • 2.3 运行 运行的结果如下:

可以看到背景图的亮度降低,叠加的这个透明图片也以0.5倍的透明度被添加到表面。