OpenGL 纹理在 3.3 中都是黑色的 - 但在 3.1 中有效

Posted

技术标签:

【中文标题】OpenGL 纹理在 3.3 中都是黑色的 - 但在 3.1 中有效【英文标题】:OpenGL Textures are all black in 3.3 - but work in 3.1 【发布时间】:2013-04-18 11:30:32 【问题描述】:

我目前正在使用 OpenGL3.3 制作一个简单的 3D 场景,但是在尝试对对象进行纹理处理时 - 所有对象都被纹理化为完全黑色。但是,如果我将上下文版本更改为 3.1;在模型上正确渲染纹理没有问题。

我不确定这是否表明我正在使用已弃用的功能/方法,但我正在努力找出问题所在。

设置纹理

(load texture from file)
...
glGenTextures(1, &TexID);               // Create The Texture ( CHANGE )
glBindTexture(GL_TEXTURE_2D, TexID);

glTexImage2D(GL_TEXTURE_2D, 0, texture_bpp / 8, texture_width, texture_height, 0, texture_type, GL_UNSIGNED_BYTE, texture_imageData);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
...

将纹理绑定到渲染

// mLocation is the layout location in the shader, from glGetUniformLocation
// mTextureUnit is the specified texture unit to load into. Currently using 0.
// mTextureID is the ID of the loaded texture, as generated above.
glActiveTexture( GL_TEXTURE0 + mData.mTextureUnit );
glBindTexture( GL_TEXTURE_2D, mData.mTextureID );
glUniform1i( mLocation, mData.mTextureUnit );

片段着色器

uniform sampler2D diffusemap;
in vec2 passUV;
out vec3 outColour;
...
outColour = texture( diffusemap, passUV ).rgb;

所有使用的纹理都是 2 的幂,正方形大小。


显示问题的图片。

GL3.1:http://i.imgur.com/NUgj6vA.png

GL3.3:http://i.imgur.com/oOc0jcd.png


顶点着色器

#version 330 core

uniform mat4 p;
uniform mat4 v;
uniform mat4 m;

in vec3 vertex;
in vec3 normal;
in vec2 uv;

out vec3 passVertex;
out vec3 passNormal;
out vec2 passUV;

void main( void )

    gl_Position = p * v * m * vec4( vertex, 1.0 );

    passVertex = vec3( m * vec4( vertex, 1.0 ) );
    passNormal = vec3( m * vec4( normal, 1.0 ) );
    passUV = uv;

【问题讨论】:

你的顶点着色器是什么样子的? 在底部为你添加了。但就纹理而言,它只是将 uv 数据传递给片段着色器而不进行任何转换。只是为了确保正确传递 UV/不是问题 - 我已经快速将 UV 渲染为颜色(红色,绿色)。似乎表明 UV 数据可以毫无问题地进入碎片着色器:imgur.com/N4Zp0ir 【参考方案1】:

行内:

glTexImage2D(GL_TEXTURE_2D, 0, texture_bpp / 8, texture_width, texture_height, 0, texture_type, GL_UNSIGNED_BYTE, texture_imageData);

(texture_bpp / 8) 将返回正确格式类型的假设是不正确的。它应该是指定内部格式的 GLenum 值之一,例如 GL_RGBA。

将其更正为(或与纹理文件的内部格式匹配的任何格式)完全解决了该问题并适用于 GL3.3 和 GL3.1:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture_width, texture_height, 0, texture_type, GL_UNSIGNED_BYTE, texture_imageData);

【讨论】:

Answer 正确识别了问题,但如果它解释了为什么之前的假设适用于 3.1 而不是 3.3,将会很有帮助。 可能 3.1 内部使用默认格式,而 3.3 在这方面更严格。无论如何,答案很好。【参考方案2】:

为了完整起见,internal format of a texture 应该是一个枚举器。和 sized 枚举数之一,而不是未调整大小的枚举数之一。当您可以使用GL_RGB8时,请停止使用GL_RGB

Answer 正确识别了问题,但它会帮助解释为什么之前的假设适用于 3.1 而不是 3.3。

在 [1, 4] 范围内使用数字的功能在 OpenGL 3.0 中已被弃用,并在 OpenGL 3.1 中被移除。 然而,当时并没有办法说“给我OpenGL 3.1版的实际核心配置文件”; WGL/GLX_CONTEXT_CORE_PROFILE_BIT_ARBs 不存在。因此,当您获得 3.1 上下文时,导出 ARB_compatibility extension 的实现完全合法,这仍然允许所有已删除的功能。

在 3.2 中,explicitly select a profile 的功能被添加到 OpenGL。在这一点上,您不会让某人在核心配置文件中公开ARB_compatibility。这就是为什么您的代码在您要求 3.1 时有效(因为它可以免费为您提供 3.1 兼容性),但在您要求 3.3 核心配置文件时无效。

【讨论】:

以上是关于OpenGL 纹理在 3.3 中都是黑色的 - 但在 3.1 中有效的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL 多重渲染目标 - 黑色输出

OpenGL ES 2.0 - 纹理总是黑色

Qt OpenGL纹理是黑色的

openGL FBO 复制到纹理导致黑色/深色图像

opengl - 黑色纹理,如何在缓冲区上使用 glm::vec*?

OpenGL生成的纹理总是黑色的?