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

我已经验证我已经正确设置了(输入)纹理缓冲区和(输出)帧缓冲区,并且可以传入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);

我正在使用glClearColor的测试值(0.5,0.5,0.5,0.5)。这些应该等效于传递-32640(带符号)或32896(无符号)。

我可以正确地获取片段着色器中的值(作为无符号等效项),如下所示:
#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将这些渲染到帧缓冲区,并获取正确的值,并在CPU上别名化指向该数组的int16_t指针。但是,使用与上述相同的逻辑,但是访问我的纹理而不是帧缓冲区:
highp float signed_value = myIntArray.a;
signed_value = value*255.0*256.0 + myIntArray.r*255.0;

使用纹理的值,我只能在片段着色器中正确地重建0到32767之间的值,而不能正确重建大于32767的值。我需要能够重建2 ^ 16个可能的值中的任何一个,无论是带符号的还是无符号的。有什么想法为什么我可以从帧缓冲区而不是纹理缓冲区中重建大于32767的值?

(编辑:校正-看来我无法通过我的纹理传递,渲染和检索所有16位整数……以前出现的结果是,负值是使用glClear()初始化的产物。我传递的负值通过我的纹理渲染将其渲染为黑色,并在CPU上将其重构为零。可以正确处理0到32767(包括0和32767)之间的值。因此...可以传递有符号的int16值(或无符号的int16值> 32767)并正确地进行重构它们在片段着色器中?)

最佳答案

事实证明片段着色器代码很好;我看错地方了。我不知道,“客户”将输入限制为非负数。谜底解决了,尽管额头巴掌很大。

关于c++ - 无法正确检索openGL片段着色器中的16位整数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30202732/

10-11 21:57
查看更多