我想做的是:在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/