如何在我的openGL程序中添加多个纹理?

时间:2019-04-22 19:58:49

标签: c++ opengl glsl shader

我正在编写一个openGL程序,并在环境中绘制了多个模型,但是我不知道如何对每个模型应用不同的纹理,因此目前它们都具有相同的纹理。我读过我需要在程序中添加多个纹理单元或使用纹理图集。纹理图集似乎更复杂,因此我尝试添加纹理单位。

我认为此过程有效的方式是:

  1. 使用glGenTextures生成两个纹理单元。
  2. 使用glBindTexture和glTexImage2D将第一个图像的数据绑定到第一个纹理单元。
  3. 对第二张图片执行相同操作。

从这里开始,我想我可以使用glActiveTexture告诉openGL我要使用哪个纹理单位。这似乎只适用于一种纹理(即,跳过步骤3),但不能适用于两种或多种纹理。

我确定我缺少什么,所以有人可以指出我正确的方向吗?

//Generate textures
int texturec=2;
int w[texturec],h[texturec];
unsigned char *data[texturec];
data[0]=getImage(&w[0],&h[0],"resources/a.png");
data[1]=getImage(&w[1],&h[1],"resources/b.png");

//Apply textures
GLuint textures[texturec];
glGenTextures(texturec, textures);

//Bind a.png to the first texture unit
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[0], h[0], 0, GL_RGB, GL_UNSIGNED_BYTE, data[0]);

//Bind b.png to the second texture unit
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[1], h[1], 0, GL_RGB, GL_UNSIGNED_BYTE, data[1]);

glActiveTexture(GL_TEXTURE0);

//Not super clear on what this does, but it needs to be here.
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

这是我的着色器:

片段:

#version 330 core

in vec2 UV;
out vec3 color;

uniform sampler2D textureSampler;

void main(){
    color=texture(textureSampler,UV).rgb;
}

顶点:

#version 330 core

layout(location=0) in vec3 vertexPos;
layout(location=1) in vec2 vertexUV;

out vec2 UV;

uniform mat4 MVP;

void main(){
    gl_Position=MVP*vec4(vertexPos,1);
    UV=vertexUV;
}

编辑:

在应用Rabid76的建议之后,这是我的新代码:

//Generate textures
int texturec=2;
int w[texturec],h[texturec];
unsigned char *data[texturec];
data[0]=getImage(&w[0],&h[0],"resources/a.png");
data[1]=getImage(&w[1],&h[1],"resources/b.png");

//Apply textures
GLuint textures[texturec];
glGenTextures(texturec, textures);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[0], h[0], 0, GL_RGB, GL_UNSIGNED_BYTE, data[0]);

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
glTexImage2D(GL_TEXTURE_2D, 0,GL_RGB, w[1], h[1], 0, GL_RGB, GL_UNSIGNED_BYTE, data[1]);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

//Shaders
programID=loadShaders("shaders/vertex.shader","shaders/fragment.shader");
glUseProgram(programID);

//Use texture unit 1
glActiveTexture(GL_TEXTURE1);
GLint texLoc=glGetUniformLocation(programID, "textureSampler");
glUniform1i(texLoc, 1);

1 个答案:

答案 0 :(得分:3)

  
      
  1. 使用glGenTextures生成两个纹理单元。
  2.   

不。 glGenTextures不会生成纹理单元。

glGenTextures保留名称值,可用于纹理对象。

glBindTexture将命名纹理绑定到纹理目标。调用此函数时,纹理对象将绑定到当前纹理单元。
当前纹理单位可以通过glActiveTexture设置:

例如

GLuint textures[texturec];
glGenTextures(texturec, textures);

glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, textures[0]);
// [...]

glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, textures[1]);
// [...]

纹理对象名称值和纹理单位完全不同。
纹理单位是纹理对象与着色器程序之间的绑定点。
一方面,纹理对象必须绑定到纹理单元,另一方面,纹理单元必须设置为均匀的纹理采样器。因此,纹理单位是两者之间的“链接”。

从GLSL 4.2版开始,可以通过着色器中的Layout Qualifier (GLSL)设置纹理单位。 Binding point对应于纹理单位。例如binding = 1表示纹理单元1:

layout(binding = 1) uniform sampler2D textureSampler;

或者可以通过glUniform1i将纹理单元索引分配给纹理采样器:

GLint texLoc = glGetUniformLocation(programID, "textureSampler");
glUniform1i(texLoc, 1);

如果着色器程序使用1个均匀的纹理采样器

uniform sampler2D textureSampler;

然后在绘制调用之前绑定适当的纹理对象就足够了:

glActiveTexture(GL_TEXTURE0); // this is default 
glBindTexture(GL_TEXTURE_2D, textures[0]);

但是,如果着色器程序使用(同一目标的)多个纹理采样器制服,则必须将不同的纹理对象绑定到不同的纹理单元:

例如

layout(binding = 3) uniform sampler2D textureSampler1;
layout(binding = 4) uniform sampler2D textureSampler2;
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, textures[1]);

分别

layout(location = 7) uniform sampler2D textureSampler1;
layout(location = 8) uniform sampler2D textureSampler2;
glActiveTexture(GL_TEXTURE3);
glBindTexture(GL_TEXTURE_2D, textures[0]);

glActiveTexture(GL_TEXTURE4);
glBindTexture(GL_TEXTURE_2D, textures[1]);

glUseProgram(programID);
glUniform1i(7, 3); // location = 7 <- texture unit 3
glUniform1i(8, 4); // location = 8 <- texture unit 4