现代OpenGL中如何将C语言二维数组转为纹理并显示?
解决32位有符号整数纹理渲染问题
针对你用现代OpenGL渲染32位有符号整数二维数组时遇到的黑屏/异常颜色问题,以下是关键修复步骤:
1. 修正纹理创建的参数不匹配问题
你当前使用GL_R32I(有符号32位整数内部格式),但type参数传了GL_UNSIGNED_INT,这会导致GPU错误解析数据。必须将type改为GL_INT,对应有符号整数类型:
// 注意:先确保二维数组是连续内存(见下一步) glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, width, height, 0, GL_RED_INTEGER, GL_INT, flat_data);
2. 处理二维数组的内存连续性
int**是指针数组,每行数据可能在内存中不连续,OpenGL要求纹理数据是连续的内存块。需要先将二维数组拷贝到一维连续数组:
int width = ...; // 你的数组宽度 int height = ...; // 你的数组高度 int* flat_data = malloc(width * height * sizeof(int)); if (!flat_data) { /* 内存分配失败处理 */ } for (int y = 0; y < height; y++) { memcpy(flat_data + y * width, plane[y], width * sizeof(int)); } // 传递给OpenGL后释放临时数组 glTexImage2D(GL_TEXTURE_2D, 0, GL_R32I, width, height, 0, GL_RED_INTEGER, GL_INT, flat_data); free(flat_data);
3. 片段着色器使用正确的采样器类型
整数纹理必须用isampler2D而非普通的sampler2D(后者用于浮点纹理),否则读取会出错:
#version 330 core out vec4 FragColor; in vec2 TexCoords; uniform isampler2D texture_plane; // 注意是isampler2D void main() { // 读取整数纹理,返回ivec4,取x分量得到对应值 int value = texture(texture_plane, TexCoords).x; if (value == 0) { FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 左半区设为红色 } else if (value == 1) { FragColor = vec4(0.0, 1.0, 0.0, 1.0); // 右半区设为绿色 } else { FragColor = vec4(1.0, 1.0, 1.0, 1.0); // 其他值默认白色 } }
4. 设置整数纹理的过滤模式
整数纹理不支持线性过滤(线性过滤需要浮点插值),必须将过滤模式设为GL_NEAREST:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); // 可选:设置边缘包装模式避免采样异常 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
5. 验证纹理坐标范围
确保传递给顶点着色器的纹理坐标是[0.0, 1.0]区间,比如矩形四个顶点的纹理坐标应为:
- 左下角:
(0.0, 0.0) - 右下角:
(1.0, 0.0) - 右上角:
(1.0, 1.0) - 左上角:
(0.0, 1.0)
这样才能完整覆盖整个纹理区域,避免采样到无效数据。
完成以上步骤后,应该能正确渲染左半区红色、右半区绿色的效果,后续可以引入1D调色板纹理,通过整数值作为索引采样调色板实现更丰富的颜色映射。
内容的提问来源于stack exchange,提问作者Ramiro Magno
相关产品推荐
相关产品推荐

