无法在OpenGL碎片着色器中正确检索16位整数

Cannot correctly retrieve 16-bit integers inside openGL fragment shader

本文关键字:检索 整数 16位 OpenGL 碎片      更新时间:2023-10-16

我想做的:在片段着色器中使用符号的16位整数进行GPGPU计算,使用iOS上的OpenGL ES 2.0。

我已经验证了我已经正确设置了我的(输入)纹理缓冲区和(输出)帧缓冲区,并且可以将16位整数传递(通过使用未签名的8位指针将其放在缓冲区上),渲染单个字节到框架缓冲区,并在CPU侧重建字节并重建正确的16位值。

如果我致电GlclearColor,我可以传递

之类的值
glClearColor(0.5, 0.5, 0.5, 0.5);  // endian-agnostic way to initialize buffer with "no data" values (-32640)
glClear(GL_COLOR_BUFFER_BIT);

我使用的是(0.5、0.5、0.5、0.5)的测试值。这些应该等于传递-32640(签名)或32896(未签名)。

i可以正确检索片段着色器内部的值(作为无符号的等效物)

#extension GL_EXT_shader_framebuffer_fetch : require
varying highp vec2 vTexCoord;
uniform sampler2D myTexture;
void main()
{
    lowp vec4 myIntArray = texture2D( myTexture, vTexCoord);
    // Retrieve value from frame buffer
    lowp vec4 lastFragColor = gl_LastFragData[0];
    // Recover the value (stored in alpha (high byte) and red (low byte)
    highp float signed_value = lastFragColor.a;
    signed_value = signed_value*255.0*256.0 + lastFragColor.r*255.0;
    //  ... Do stuff with the recovered value.
    // Here, I simply verify value is recovered correctly (as an unsigned int equivalent):
    // This draws the pixel green, indicating success
    if (signed_value >= 32896.0) {
        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
    }
    else {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
    // But changing the threshold value very slightly (replacing the lines
    // above with those below) draws the pixel red, correctly
    // indicating the condition is not met, because the value is
    // 32896
    if (signed_value >= 32896.01) {
        gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
    }
    else {
        gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
    }
}

但是,我想传递一系列不同的值,因此我不使用glclearcolor,而是设置了一个缓冲区,并将其传递给我签名的16位整数的数组(基本上是在我签名的INT16_T上,字节好像它们只是未签名字节。)

然后,我可以将它们渲染到框架缓冲区,并使用GlreadPixels并将正确的值归还正确的值,并将INT16_T指针与CPU上的该数组混为一谈。但是,使用与上述相同的逻辑,但访问我的纹理而不是框架缓冲区:
highp float signed_value = myIntArray.a;
signed_value = value*255.0*256.0 + myIntArray.r*255.0;

使用我的纹理值,我只能在片段着色器内正确重建从0到32767的值,但不正确的值> 32767。未签名。有什么想法,为什么我可以从框架缓冲区重建大于32767的值,但不能从我的纹理缓冲区中重建值?

(编辑为添加:校正 - 看来我无法传递,渲染和检索 all 通过我的纹理进行...使用glclear()。我通过纹理呈现为黑色传递的负值并在CPU上重建为零。正确处理0和32767之间的值。或未签名的INT16值> 32767)并正确地重建片段着色器?)

结果,片段着色器代码很好;我看着错误的地方。对我来说,"客户"不为人知,将投入限制为非负。神秘的人解决了,尽管额头上有大耳光。