【问题标题】:OpenGL: UV values not interpolating in fragment shaderOpenGL:UV值不在片段着色器中插值
【发布时间】:2014-01-23 10:16:58
【问题描述】:

我一直在尝试将一些旧的 OpenGL 代码转换为使用着色器,但在让我的片段着色器在立方体上绘制纹理时遇到了问题。然而,我看到的只是一个灰色的立方体。我已经调试了我的 .obj 加载器代码,并且我知道 UV 正在正确加载,并且我知道纹理正在从磁盘加载并正确放置在 GPU 上。经过大量测试后,我发现我的 UV 值没有在每个三角形的面上进行插值。也就是说,看起来每个片段的 uv 值都是 0.0,0.0(这是我缓冲区中的第一个 uv 值)有什么想法吗?

这是我的片段着色器:

#version 430 core

in vec3 color;
in vec2 uv;
uniform sampler2D tex;
out vec3 frag_color;

void main()
{
    //frag_color = color;
    frag_color = texture(tex,uv).rgb;
}

还有我的顶点着色器:

#version 430 core

layout(location = 0) in vec3 pos;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 uv;
uniform mat4 mvMatrix;
uniform mat4 mvpMatrix;
attribute vec3 lightPos;
out vec3 color;
out vec2 uv_out;

void main()
{
uv_out = uv;

vec3 modelViewVertex = vec3(mvMatrix * vec4(pos,1.0));
vec3 modelViewNormal = vec3(mvMatrix * vec4(normal,0.0));
vec3 modelViewLightPos = vec3(mvMatrix * vec4(lightPos,1.0));

vec3 lightVector = normalize(lightPos - pos);
float diffuse = clamp(dot(normal,lightVector),0,1);

gl_Position = mvpMatrix * vec4(pos,1.0);
color = vec3(diffuse,0.0,0.0);

}

这里是我设置缓冲区的地方:

glGenVertexArrays(1, &vertexBufferObjectID);
glBindVertexArray(vertexBufferObjectID);
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertices.size()*sizeof(vec3), &vertices[0], GL_STATIC_DRAW);
glGenBuffers(1, &normalBuffer);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glBufferData(GL_ARRAY_BUFFER, normals.size()*sizeof(vec3), &normals[0], GL_STATIC_DRAW);
glGenBuffers(1, &UVBuffer);
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer);
glBufferData(GL_ARRAY_BUFFER, uvs.size()*sizeof(vec2), &uvs[0], GL_STATIC_DRAW);

最后,这是我的渲染循环:

glUseProgram(shaderProgram);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture);
glUniform1i(textureID, 0);
glEnableVertexAttribArray(0);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(1);
glBindBuffer(GL_ARRAY_BUFFER, normalBuffer);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
glEnableVertexAttribArray(2);
glBindBuffer(GL_ARRAY_BUFFER, UVBuffer);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

mvpMatrix = projectionMatrix * viewMatrix * modelMatrix;
glUniformMatrix4fv(mvpMatrixID, 1, GL_FALSE, &mvpMatrix[0][0]);
mvMatrix = viewMatrix * modelMatrix;
glUniformMatrix4fv(mvMatrixID, 1, GL_FALSE, &mvMatrix[0][0]); 
glVertexAttrib3fv(lightposID, &lightpos[0]);
glDrawArrays(GL_TRIANGLES, 0, vertices.size());

glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);

再一次,根据我的阅读内容,一切看起来都是正确的。有什么不对劲的地方吗?

【问题讨论】:

  • 你从glGetError()得到什么了吗?
  • 这甚至不应该编译,你的#version指令中间有一些无效的空格,使它成为# version。您还应该在核心 GLSL 3.30 着色器中使用 texture (...) 而不是 texture2D (...)(已弃用)。
  • @zero: 当我调用 glVertexAttrib3fv(lightposID, &lightpos[0]); 时 glGetError() 返回错误但是,当我重新启用顶点照明时,它就消失了。错误是“lightposID”没有正确初始化(我猜着色器优化了它,因为我没有使用它)除此之外,什么都没有。
  • @Andon,我根据您的建议(见上文)修改了代码,但仍然没有。不知道为什么即使我有语法错误它仍然在编译,我猜 Nvidia 的驱动程序是相当宽松的
  • 好吧,还有另一个问题:glTexImage2D(GL_TEXTURE_2D, 0, 3, surf->w, surf->h, 0, GL_BGR, GL_UNSIGNED_BYTE, surf->pixels)。假设这是一个核心配置文件上下文,将您希望图像具有的通道数作为内部格式传递给glTexImage2D (...) 不再可接受,您需要使用实际格式枚举(例如GL_RGB8 而不是 3)。由于我们讨论的是 3 分量纹理,因此完全没有必要这样做:vec4 (texture (...).rgb, 1.0),因为当您对 3 分量纹理进行采样时,GL 会自动为 .a 填充 1.0

标签: opengl glsl texture-mapping texture2d


【解决方案1】:

您必须将uv 从顶点传递到片段着色器。顶点着色器和片段着色器中不能有同名的in 属性。相反,您必须在顶点着色器中有一些in 属性,然后将其传递给与片段着色器中对应的in 同名的out

在您的情况下,您的顶点着色器已经有一个out 变化的uv_out。因此,片段着色器变化也需要命名为uv_out,即在片段着色器中

in vec2 uv_out

当然uv_out 这个名字有点误导。

【讨论】:

  • 效果很好,我不敢相信我忘记了 :) 谢谢!
猜你喜欢
  • 2014-07-26
  • 2012-02-10
  • 1970-01-01
  • 2021-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-20
  • 2018-07-03
相关资源
最近更新 更多