能否使用GL_PACK_SKIP_PIXELS加载结构体数组中的指定像素数据?
解决方案
无法仅通过glPixelStorei()的参数让glTexImage2D()跳过每个像素结构体后的额外成员——OpenGL的像素存储参数(包括GL_UNPACK_*系列)主要用于控制行与行之间的字节跳过,而非单个像素之间的间隔。不过有两种无需重新排列数组的可行方案:
1. 使用纹理缓冲区对象(TBO)
这是最高效的方案,直接将结构体数组绑定到GPU缓冲区,在着色器中按需读取x/y/z成员:
- 步骤:
- 创建缓冲区对象,将结构体数组数据传入GPU
- 将缓冲区绑定为纹理缓冲区对象(TBO)
- 在着色器中通过采样器访问结构体的目标成员
- 示例代码:
typedef struct { float x, y, z; // 其他额外成员 } PixelData; GLuint tbo, texture; size_t pixelCount = width * height; // 创建并填充缓冲区 glGenBuffers(1, &tbo); glBindBuffer(GL_TEXTURE_BUFFER, tbo); glBufferData(GL_TEXTURE_BUFFER, sizeof(PixelData) * pixelCount, pixels, GL_STATIC_DRAW); // 创建TBO纹理 glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_BUFFER, texture); glTexBuffer(GL_TEXTURE_BUFFER, GL_RGB32F, tbo); - 着色器访问示例:
uniform samplerBuffer pixelSampler; void main() { int pixelIndex = gl_VertexID; // 或根据纹理坐标计算索引 vec3 pixelColor = texelFetch(pixelSampler, pixelIndex).rgb; // 后续渲染逻辑 }
2. 手动分批上传(适合小纹理)
如果无法使用TBO(比如OpenGL版本低于3.1),可以循环计算每个像素的地址,调用glTexSubImage2D()逐个或按行上传:
for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { PixelData* currentPixel = &pixels[y * width + x]; // 仅上传x/y/z成员 glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, 1, 1, GL_RGB, GL_FLOAT, ¤tPixel->x); } }
关于GL_PACK_SKIP_PIXELS的说明
你提到的GL_PACK_SKIP_PIXELS属于GPU读取像素到CPU的GL_PACK_*参数,和当前CPU上传像素到GPU的场景无关。对应的GL_UNPACK_*参数也无法解决单个像素间的额外数据问题,因为它们仅控制行级别的字节对齐或跳过。
内容的提问来源于stack exchange,提问作者Стефан Йовев
相关产品推荐
相关产品推荐

