首页 > 解决方案 > OpenGL 无法正确采样 2D 纹理

问题描述

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

// 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);),那么它看起来对我来说是正确的:
在此处输入图像描述

目标图像是这样的:
在此处输入图像描述

标签: c++openglglsltextures

解决方案


您必须在片段着色器中查找纹理。顶点着色器只针对图元的每个顶点坐标执行。但是,为每个片段执行片段着色器。顶点着色器输出沿图元插值并传递给片段着色器。因此,您的代码仅查找四边形的 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;
}

推荐阅读