You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 14:03:09