OpenGL - 纹理映射不完整

Posted

技术标签:

【中文标题】OpenGL - 纹理映射不完整【英文标题】:OpenGL - texture mapping is incomplete 【发布时间】:2015-08-05 02:45:16 【问题描述】:

我在 OpenGL 中对 OBJ 文件进行纹理处理时遇到了这个奇怪的问题。我已经成功地正确解析和渲染模型,我现在正在尝试对其应用纹理。这是我的做法。

GLuint vao;
glGenVertexArrays(1, &vao);
glBindVertexArray(vao);

// bind the vertices coord
GLuint buffer;
glGenBuffers(1, &buffer);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, cc * sizeof(GLfloat), vertices,   GL_STATIC_DRAW);


// bind the textures coord
GLuint tcbuffer;
glGenBuffers(1, &tcbuffer);
glBindBuffer(GL_ARRAY_BUFFER, tcbuffer);
glBufferData(GL_ARRAY_BUFFER, tcc * sizeof(GLfloat), textures GL_STATIC_DRAW);

// for the texture itself
GLuint tid;
glGenTextures(1, &tid);
glBindTexture(GL_TEXTURE_2D, tid);
glGenerateMipmap(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); 
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR_MIPMAP_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nptr);

glEnableVertexAttribArray(m_vert);
glBindBuffer(GL_ARRAY_BUFFER, vbufferid);
glVertexAttribPointer(m_vert, 3, GL_FLOAT, GL_FALSE, 0, 0);

glEnableVertexAttribArray(m_texcoord);
glBindBuffer(GL_ARRAY_BUFFER, tcbufferid);
glVertexAttribPointer(m_texcoord, 2, GL_FLOAT, GL_FALSE, 0, 0);

glDrawArrays(GL_TRIANGLES, 0, vc);

对于解析器中的纹理坐标,我交换 y 坐标(从 1 中减去 y)以获得纹理的正确方向。此代码适用于不同的模型,但对于这个特定的模型,纹理是不完整的。您可以here 获得我使用此模型获得的输出,here 获得工作模型。希望你能帮忙! :)

P.S: 代码被缩短以供查看:)

【问题讨论】:

不确定这是否是您的直接问题,但glGenerateMipmap() 调用必须在glTexImage2D() 之后。否则它没有纹理数据来生成 mipmap。 @RetoKoradi 感谢您的指出。我尝试在 glTexImage2D 之后移动它,但它并没有解决问题。我注意到的是纹理本身只提供了模型的一半,看这里link 我在说什么:D 但是我应该做些什么来以某种方式复制纹理吗?据我所知,obj 会处理这个问题,因为它提供每个面的纹理坐标。 文件的纹理坐标是否超出 [0.0, 1.0] 范围?尝试将GL_REPEAT 用于纹理环绕模式。 @RetoKoradi - 我尝试使用 GL_REPEAT,现在它可以工作了!谢谢 :) 我只是想问一下 GL_REPEAT 是否总是可以在其他模型中使用?因为我的计划是为任何模型制作一个 OBJ 解析器,而不需要修改我尝试过的所有其他模型的代码。 @RetoKoradi - 我刚刚测试了其他模型,效果很好!谢谢老兄。 【参考方案1】:

根据建模程序生成纹理和纹理坐标的方式,它可能会生成超出标准 [0.0, 1.0] 范围的纹理坐标。由于您将换行模式设置为:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

所有超出此范围的纹理坐标都将获得最近边缘纹素的颜色。看起来你的纹理边缘有黑色,所以所有这些像素都将被采样为黑色。

如果是这个问题,需要设置参数为:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);

从理论上讲,建模程序生成纹理坐标以处理镜像重复也是有可能的,尽管可能性较小。如果切换到GL_REPEAT后,纹理图像出现在当前黑色的部分,但它们看起来像纹理的错误部分,您也可以尝试:

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);

OP 已经发现了一个相关问题,但我会在这里提到它,以防其他有类似问题的人遇到这个答案:在我看到的带有纹理的 OBJ 文件中,第二个纹理坐标(yt,如果您更喜欢该命名法)与 OpenGL 使用它们的方式相反(又名 y 反转)。我不确定这是否是 OBJ 中的标准,或者取决于生成文件的软件。典型的症状是纹理显示在几何体上,但纹理的完全错误部分被映射。这可以通过在读取文件时镜像第二个坐标(将y 替换为1.0 - y)或通过在着色器中应用纹理坐标的相应映射来解决。

【讨论】:

以上是关于OpenGL - 纹理映射不完整的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL的纹理映射问题

OpenGL 半球纹理映射

opengl 把纹理映射到立方体的六个面。

OpenGL_Qt学习笔记之_05(纹理映射)(转)

OpenGL纹理映射总结

opengl使用bmp纹理映射画不出东西