纹理单元
我们可以给纹理采样器分配一个位置值,这样的话我们能够在一个片段着色器中设置多个纹理。一个纹理的位置值通常称为一个纹理单元(Texture Unit)。一个纹理的默认纹理单元是0,它是默认的激活纹理单元,所以教程前面部分我们没有分配一个位置值。
纹理单元的主要目的是让我们在着色器中可以使用多于一个的纹理。通过把纹理单元赋值给采样器,我们可以一次绑定多个纹理,只要我们首先激活对应的纹理单元。
OpenGL至少保证有16个纹理单元供你使用,也就是说你可以激活从GL_TEXTURE0
到GL_TEXTRUE15
。它们都是按顺序定义的,所以我们也可以通过GL_TEXTURE0 + 8
的方式获得GL_TEXTURE8
,这在当我们需要循环一些纹理单元的时候会很有用。
就像glBindTexture
一样,我们可以使用glActiveTexture
激活纹理单元,传入我们需要使用的纹理单元:
OpenGL激活纹理单元传统的方法:
glActiveTexture(GL_TEXTURE0); // 在绑定纹理之前先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture1);
glActiveTexture(GL_TEXTURE1); // 在绑定纹理之前先激活纹理单元
glBindTexture(GL_TEXTURE_2D, texture2);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
激活纹理单元之后,接下来的glBindTexture
函数调用会绑定这个纹理到当前激活的纹理单元,纹理单元GL_TEXTURE0
默认总是被激活,所以我们在前面的例子里当我们使用glBindTexture
的时候,无需激活任何纹理单元。
如果我们使用QT封装好的类应该怎么做呢?(很简便!!!)
在资源文件里加上一张笑脸图片:
修改片段着色器代码:
#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D textureWall;
uniform sampler2D textureSmile;
void main()
{
FragColor = mix(texture(textureWall, TexCoord),texture(textureSmile, TexCoord),0.5);
}
增加一个纹理单元对象指针:
class ZjjOpenGLWidget : public QOpenGLWidget,QOpenGLFunctions_4_5_Core
{
......
QOpenGLTexture* textureWall;
QOpenGLTexture* textureWSmile;
......
};
创建纹理单元,并且进行绑定:
textureWall = new QOpenGLTexture(QImage(":/image/wall.jpg").mirrored());
textureWSmile = new QOpenGLTexture(QImage(":/image/awesomeface.png").mirrored());
shaderProgram.bind();
shaderProgram.setUniformValue("textureWall", 0);
shaderProgram.setUniformValue("textureSmile", 1);
绘制:
switch (m_shape) {
case Rect:
textureWall->bind(0);
textureWSmile->bind(1);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
break;
default:
break;