OpenGL 无法正确采样 2D 纹理

OpenGL doesn't sample 2D texture correctly

我将此代码用于所有 OpenGL 准备工作。我从我的源代码中获取了这些片段,因此可以省略部分和未初始化或未声明的变量等,但这有效。我试图 post 仅代码中有意义的部分。

// Texture reading
int w{}, h{}, channels{};
unsigned char * bytes = stbi_load(path.c_str(), &w, &h, &channels, 0);
// produce Texture object

// GL texture code

glCall(glGenTextures(1, &m_textureId));
glCall(glBindTexture(GL_TEXTURE_2D, m_textureId));

glCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT));
glCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT));
glCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST));
glCall(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST));

glCall(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_texture->width, m_texture->height, 0, GL_BGR, GL_UNSIGNED_BYTE, m_texture->bytes));
glCall(glGenerateMipmap(GL_TEXTURE_2D));

// Create shader (I omitted this code) and bind texture

glCall(glActiveTexture(GL_TEXTURE0));
glCall(glBindTexture(GL_TEXTURE_2D, m_textureId));

glCall(glUseProgram(m_programId)); // using the shader
// pass texture index into shader
glCall(location = glGetUniformLocation(m_programId, "u_tex0"));
glCall(glUniform1i(location, 0));


// code that sets up uv VBO
/* UV0 positions */
glCall(glGenBuffers(1, &m_VBO[2]));
glCall(glBindBuffer(GL_ARRAY_BUFFER, m_VBO[2]));
glCall(glBufferData(GL_ARRAY_BUFFER, m_model->uv0SizeBytes(), m_model->uv0.data(), GL_STATIC_DRAW));
glCall(glEnableVertexArrayAttrib(m_VAO, 2));
glCall(glVertexAttribPointer(2, m_model->uv0Channels /* 2 here */, GL_FLOAT, GL_FALSE, m_model->uv0Channels * sizeof(m_model->uv0.front()), nullptr));

着色器代码:

#version 460 core
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec3 a_norm;
layout (location = 2) in vec2 a_uv0;

uniform mat4 u_mMVP;
uniform sampler2D u_tex0;

out vec4 v_vertexColor;

void main()
{
    gl_Position = u_mMVP * vec4(a_pos, 1.0);
    v_vertexColor = texture(u_tex0, a_uv0);
}

输出图像:

如果我绘制 uv 而不是 texture (v_vertexColor = vec4(a_uv0, 0.0, 1.0);),那么它对我来说看起来是正确的:

目标图片是这样的:

你必须在片段着色器中查找纹理。顶点着色器仅针对图元的每个顶点坐标执行。然而,片段着色器是为每个片段执行的。顶点着色器的输出沿图元进行插值并传递给片段着色器。因此,您的代码仅查找四边形的 4 个角的纹理。

将纹理坐标传递给片段着色器:

#version 460 core
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec3 a_norm;
layout (location = 2) in vec2 a_uv0;

uniform mat4 u_mMVP;
out vec2 v_uv;

void main()
{
    gl_Position = u_mMVP * vec4(a_pos, 1.0);
    v_uv = a_uv0;
}

在片段着色器中使用内插纹理坐标查找每个片段的纹理:

#version 460 core

in vec2 v_uv;
out vec4 FragColor;
uniform sampler2D u_tex0;

void main()
{
    vec4 vertexColor = texture(u_tex0, v_uv);
    FragColor = vertexColor;
}