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

能否使用GL_PACK_SKIP_PIXELS加载结构体数组中的指定像素数据?

解决方案

无法仅通过glPixelStorei()的参数让glTexImage2D()跳过每个像素结构体后的额外成员——OpenGL的像素存储参数(包括GL_UNPACK_*系列)主要用于控制行与行之间的字节跳过,而非单个像素之间的间隔。不过有两种无需重新排列数组的可行方案:

1. 使用纹理缓冲区对象(TBO)

这是最高效的方案,直接将结构体数组绑定到GPU缓冲区,在着色器中按需读取x/y/z成员:

  • 步骤:
    1. 创建缓冲区对象,将结构体数组数据传入GPU
    2. 将缓冲区绑定为纹理缓冲区对象(TBO)
    3. 在着色器中通过采样器访问结构体的目标成员
  • 示例代码:
    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, &currentPixel->x);
    }
}

关于GL_PACK_SKIP_PIXELS的说明

你提到的GL_PACK_SKIP_PIXELS属于GPU读取像素到CPU的GL_PACK_*参数,和当前CPU上传像素到GPU的场景无关。对应的GL_UNPACK_*参数也无法解决单个像素间的额外数据问题,因为它们仅控制行级别的字节对齐或跳过。

内容的提问来源于stack exchange,提问作者Стефан Йовев

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 16:35:23