绘制具有多个纹理的对象,并绘制具有一个纹理的其他对象

时间:2019-08-29 17:18:49

标签: c++ opengl opengl-4

我要绘制具有两个纹理的对象矩形和仅具有一个纹理的三角形。我关注这个网站

LearnOpenGL.com - Textrues
https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/4.2.textures_combined/textures_combined.cpp

使用绘制三角形,我实现如下:

Shader ourShaderTriangle("vshader.glsl", "fshader.glsl");
float firstTriangle[] = {
    // positions         // colors          //textcoord
    -1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,   0.0f,   0.0f,   // bottom right
    -0.5f, 0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   0.5f,   1.0f,   // bottom left
    -0.1f,  0.0f, 0.0f,  0.0f, 0.0f, 1.0f,  1.0f,   0.0f     // top 
};//first
unsigned int VBO1, VAO1;
glGenVertexArrays(1, &VAO1);
glGenBuffers(1, &VBO1);

glBindVertexArray(VAO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
//position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//color
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//textCoord
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
   gl_Position = vec4(aPos, 1.0);
   ourColor = aColor;
   TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

片段:

#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D textureTriangle;
void main()
{
   FragColor = texture(textureTriangle, TexCoord);
}

加载纹理:我使用其他纹理“ container2.png”。我将其存储在“ texture3”中

    glGenTextures(1, &texture3);
glBindTexture(GL_TEXTURE_2D, texture3);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
data = stbi_load(FileSystem::getPath("resources/textures/container2.png").c_str(), &width, &height, &nrChannels, 0);
if (data)
{
    // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
    std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);

在绘图功能中:

  //bind textures on corresponding texture units
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture2);

    // render container
    ourShader.use();
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    //
    ourShaderTriangle.use();
    glBindTexture(GL_TEXTURE_2D, texture3);     
    glBindVertexArray(VAO1);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    //

但是三角形仍在使用纹理单位0(GL_TEXTURE0)。不使用我想要的纹理 enter image description here

我尝试使用“ glDisable”和“ glDeleteTextures”,但是它不起作用。

你能帮我吗?

1 个答案:

答案 0 :(得分:1)

OpenGL是一个状态引擎。由glActiveTexture设置的当前纹理单位是全局状态。因此,以下对glBindTexture的所有调用都将纹理绑定到纹理单元1。
如果要将texture3绑定到纹理单元0,则必须在将纹理绑定到纹理目标之前更改纹理单元:

ourShaderTriangle.use();
glActiveTexture(GL_TEXTURE0); // <---
glBindTexture(GL_TEXTURE_2D, texture3);     
glBindVertexArray(VAO1);
glDrawArrays(GL_TRIANGLES, 0, 3);

如果要使用其他纹理单位,则必须更改纹理采样器制服的绑定点。

这可以通过Binding point Layout Qualifier在着色器代码中完成(为此,至少必须使用GLSL 4.20版)。例如1表示纹理单元1:

#version 420 core

layout(binding = 1) uniform sampler2D textureTriangle;

另一种方法是在通过glUseProgram安装程序之后,将纹理单元(1)分配给纹理采样器统一:

GLuint program = // program "ourShaderTriangle"
GLint texTriLoc = glGetUniformLocation(program, "textureTriangle"); 
// ...
glActiveTexture(GL_TEXTURE1);
// ...
ourShaderTriangle.use();
glUniform1i(texTriLoc, 1); // <----
glBindTexture(GL_TEXTURE_2D, texture3);     
glBindVertexArray(VAO1);
glDrawArrays(GL_TRIANGLES, 0, 3);