OpenGL中32位无符号整数RGBA纹理绘制黑屏问题排查
OpenGL 32位无符号整数RGBA纹理渲染失败问题
问题描述
尝试绘制一个带有32位unsigned int RGBA像素纹理的四边形,但纹理无法渲染,屏幕显示全黑。四边形可正常渲染静态颜色,UV坐标验证正确,纹理数据也已填充为0xFFFFFFFF(纯白),但片段着色器中texture(tex, uv)的采样结果始终为(0,0,0,0),怀疑问题出在着色器逻辑或glTexImage2D调用参数上。
相关代码
着色器代码
// 顶点着色器 vertex_shader[0] = "#version 330 core\n\ layout(location = 0) in vec3 pos;\n\ layout(location = 1) in vec2 uv;\n\ \n\ out vec2 fuv;\n\ \n\ void main(){\n\ gl_Position = vec4(pos, 1.0);\n\ fuv = uv;\n\ }\n"; // 片段着色器 fragment_shader[0] = "#version 330 core\n\ uniform usampler2D tex;\n\ in vec2 fuv;\n\ out uvec4 color;\n\ \n\ void main(){\n\ color = texture(tex, fuv);\n\ }\n";
纹理数据填充代码
unsigned int *Screen_image; for (int now_y=0; now_y<View_height; now_y++) { for (int now_x=0; now_x<View_width; now_x++) { Screen_image[now_y*View_width + now_x] = 0xFFFFFFFF; } }
全屏四边形顶点数据
int vertc = 6; SVertex vertices[vertc] = { {{-1.0f, 1.0f, 0.0f}, {0.0f, 1.0f}}, // 左上 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}}, // 左下 {{1.0f, 1.0f, 0.0f}, {1.0f, 1.0f}}, // 右上 {{1.0f, 1.0f, 0.0f}, {1.0f, 1.0f}}, // 右上 {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}}, // 左下 {{1.0f, -1.0f, 0.0f}, {1.0f, 0.0f}} // 右下 };
VAO/VBO与纹理初始化代码
glGenVertexArrays(1, &Vao); glBindVertexArray(Vao); // 顶点缓冲 glGenBuffers(1, &Vbo); glBindBuffer(GL_ARRAY_BUFFER, Vbo); glBufferData(GL_ARRAY_BUFFER, sizeof(SVertex)*vertc, vertices, GL_STATIC_DRAW); glEnableVertexAttribArray(0); glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)(0)); glEnableVertexAttribArray(1); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(SVertex), (void*)(sizeof(GLfloat)*3)); // 纹理初始化 Program1 = LoadShaders(); glGenTextures(1, &Tbo); glBindTexture(GL_TEXTURE_2D, Tbo); glActiveTexture(GL_TEXTURE0); glUseProgram(Program1); glUniform1i(glGetUniformLocation(Program1, "tex"), 0);
纹理传递与绘制代码
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, View_width, View_height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT_8_8_8_8, Screen_image); glDrawArrays(GL_TRIANGLES, 0, 6);
调试补充
修改片段着色器调试后,屏幕显示绿色:
vec4 c = texture(tex, fuv); if (c.x<0) {color.x=1.0;} if (c.y==0) {color.y=1.0;}
尝试过以下glTexImage2D调用(无报错),也试过将源类型改为GL_UNSIGNED_BYTE,问题依旧:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, View_width, View_height, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, Screen_image); std::cout << glGetError() << "err\n";
解决方案
1. 修正glTexImage2D参数匹配问题
你的纹理数据是unsigned int*类型,每个像素存储为一个32位无符号整数(RGBA各8位),但当前glTexImage2D的类型参数GL_UNSIGNED_INT_8_8_8_8是告诉OpenGL每个像素由4个独立的8位无符号整数组成,与你的数据存储格式不匹配。
正确调用:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8UI, View_width, View_height, 0, GL_RGBA_INTEGER, GL_UNSIGNED_INT, Screen_image);
- 内部格式
GL_RGBA8UI对应无符号整数纹理,与usampler2D采样器匹配 - 格式参数
GL_RGBA_INTEGER表示使用整数格式读取纹理数据 - 类型参数
GL_UNSIGNED_INT表示每个像素是一个32位无符号整数,与你的Screen_image数据类型一致
2. 修复纹理采样与输出的类型一致性
调试代码中错误地用vec4接收usampler2D的采样结果,整数采样器必须返回uvec4类型,强制转换会导致值异常。正确的调试逻辑应使用无符号整数类型:
uvec4 c = texture(tex, fuv); if (c.y == 0u) { color.y = 255u; } // GL_RGBA8UI的分量范围是0-255
3. 配置纹理过滤与包裹模式
默认情况下OpenGL纹理要求Mipmap,但你未生成Mipmap,会导致采样失败。需显式设置无Mipmap的过滤模式:
glBindTexture(GL_TEXTURE_2D, Tbo); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // 可选:限制UV坐标范围避免边缘采样异常 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
4. 排除数据存储问题
确保Screen_image已正确分配内存(如用malloc或new),避免野指针导致纹理数据未正确传入GPU。
内容的提问来源于stack exchange,提问作者user193661
相关产品推荐
相关产品推荐

