c++ - 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);
),那么它看起来对我来说是正确的:
解决方案
您必须在片段着色器中查找纹理。顶点着色器只针对图元的每个顶点坐标执行。但是,为每个片段执行片段着色器。顶点着色器输出沿图元插值并传递给片段着色器。因此,您的代码仅查找四边形的 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;
}
推荐阅读
- angular - 将大数据从 AgGrid 复制到剪贴板
- php - Magento 2 - 单击按钮缓存清理目录图像时出现错误消息
- php - 更新/删除多个检查数据
- android - 错误通知:给定区域必须与位图的尺寸相交
- excel - 通过 VBA 关闭应用程序错误仅适用于某些系统
- ios - Swift iOS Intent 扩展:无法读取数据,因为它的格式不正确
- sql - 年度销售额比较的 CASE 表达式?
- java - Java 中 void lambda 的函数纯度
- google-cloud-monitoring - 图表统计视图中的 Stackdriver 相似度
- javascript - 如何根据选择的单选按钮显示和验证文本框