我如何通过glReadPixels读取数据?

时间:2015-06-03 08:37:01

标签: opengl-es-2.0 opengl-es-3.0

我正在开发Android上的openGL。 现在我遇到了一个问题。我定义了一个float数组,用于传递给片段着色器。

float[] data = new float[texWidth*texHeight];
// test data
for (int i = 0; i < data.length; i++) {
    data[i] = 0.123f;
}

1。 initTexture:

glGenTextures...
glBindTexture...
glTexParameteri...
FloatBuffer fb = BufferUtils.array2FloatBuffer(data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, fb);

2.FBO:

glGenBuffers...
glBindFramebuffer...
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);

3.onDrawFrame:

glUseProgram(mProgram);...
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);...

IntBuffer fb = BufferUtils.iBufferAllocateDirect(texWidth*texHeight);
glReadPixels(0, 0, texWidth, texHeight, GL_RGBA, GL_UNSIGNED_BYTE, fb);
System.out.println(Integer.toHexString(fb.get(0)));
System.out.println(Integer.toHexString(fb.get(1)));
System.out.println(Integer.toHexString(fb.get(2)));

片段着色器:

precision mediump float;
uniform sampler2D sTexture;
varying vec2 vTexCoord;

void main()
{
    tex = texture2D(sTexture, vTexCoord.st);
    vec4 color = tex;
    gl_FragColor = color;
}

那么,我怎么能得到glReadPixels的浮点数据(0.123f,我之前定义的)?现在我得到的是ff000000(ABGR),所以我怀疑着色器不能通过这种方式获取数据。有人可以告诉我为什么以及如何处理它?我是一个新手,真的很感激。

1 个答案:

答案 0 :(得分:0)

您的主要问题发生在glReadPixels()之前。主要问题在于您使用glTexImage2D()的方式:

FloatBuffer fb = BufferUtils.array2FloatBuffer(data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0,
             GL_RGBA, GL_UNSIGNED_BYTE, fb);

第8个参数的GL_UNSIGNED_BYTE值指定传入的数据由无符号字节组成。但是,缓冲区中的值是浮点数。所以你的浮点值被解释为字节,它们可能很好地结束,因为它们是完全不同的格式,具有不同的大小和内存布局。

现在,您可能会想要这样做:

FloatBuffer fb = BufferUtils.array2FloatBuffer(data);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, texWidth, texHeight, 0,
             GL_RGBA, GL_FLOAT, fb);

这适用于桌面OpenGL,它支持隐式格式转换,作为指定纹理数据的一部分。但OpenGL ES支持 。在ES 2.0中,GL_FLOAT甚至不是format参数的合法值。在ES 3.0中,它是合法的,但仅适用于实际存储浮点数的内部格式,例如GL_RGBA16FGL_RGBA32F。将它与GL_RGBA内部格式(第三个参数)结合使用是错误的。

因此,除非您在ES 3.0中使用浮动纹理(消耗更多内存),否则您需要将原始数据转换为字节。如果浮点值介于0.0和1.0之间,则可以将它们乘以255,然后舍入到下一个整数。

然后你可以将它们作为带有glReadPixels()的字节读回来,并且应该再次获得相同的值。