glMapBufferRange 在 Android 中返回全零
glMapBufferRange returning all zeros in Android
我无法从使用 glMapBufferRange 映射的缓冲区中读取数据
如果我只是将一些数据放入缓冲区
// Create input VBO and vertex format
int bufferLength = 5 * 4; //5 floats 4 bytes each
FloatBuffer data = ByteBuffer.allocateDirect(bufferLength)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
float[] floatData = { 1.0f, 4.0f, 9.0f, 16.0f, 25.0f };
data.put(floatData).position(0);
在 GL 中生成数组缓冲区并用数据填充它
int[] vbo = new int[1];
GLES30.glGenBuffers(1, vbo, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bufferLength, data, GLES30.GL_STATIC_DRAW);
MyGLRenderer.checkGlError(TAG + " glBufferData GL_ARRAY_BUFFER");
当我使用 glMapBufferRange
映射缓冲区并读取结果时
Buffer mappedBuffer = GLES30.glMapBufferRange(GLES30 .GL_ARRAY_BUFFER,
0, bufferLength, GLES30.GL_MAP_READ_BIT);
if (mappedBuffer!=null){
FloatBuffer transformedBuffer = ((ByteBuffer) mappedBuffer).asFloatBuffer();
MyGLRenderer.checkGlError(TAG + " glMapBufferRange");
Log.d(TAG, String.format("pre-run input values = %f %f %f %f %f\n", transformedBuffer.get(),
transformedBuffer.get(), transformedBuffer.get(), transformedBuffer.get(), transformedBuffer.get()));
transformedBuffer.position(0);
}
GLES30.glUnmapBuffer(GLES30.GL_ARRAY_BUFFER);
logcat 读取全零
D/TransformFeedback﹕ pre-run input values = 0.000000 0.000000 0.000000 0.000000 0.000000
没有产生其他错误,我不确定还要检查什么。我尝试了 GLES30.glCopyBufferSubData(GLES30.GL_ARRAY_BUFFER, GLES30.GL_COPY_READ_BUFFER, 0, 0, bufferLength);
和映射 GL_COPY_READ_BUFFER 并得到了相同的结果。
我正在支持 OpenGL ES 3.1 的 Nexus 6 上进行测试,因此该功能应该存在。
这个 question 建议删除 glfw 中的 OPENGL_FORWARD_COMPAT 提示,是否需要在 MyGLSurfaceView 中进行类似的操作?
非常感谢 Reto Koradi,如果有人想留下答案,我会将其标记为正确。
转换不正确。需要按 LITTLE_ENDIAN 顺序:
ByteBuffer transformedBuffer = ((ByteBuffer) mappedBuffer);
transformedBuffer.order(ByteOrder.LITTLE_ENDIAN);
Log.d(TAG, String.format("pre-run input values = %f %f %f %f %f\n", transformedBuffer.getFloat(),
transformedBuffer.getFloat(), transformedBuffer.getFloat(),
transformedBuffer.getFloat(), transformedBuffer.getFloat()));
这看起来像是读回数据时的字节顺序问题。数据将按本机字节顺序排列,而 Java 假定缓冲区中的数据默认为大端。由于现在大多数体系结构都是小端,这与您需要的相反。
要以适用于大端和小端架构的方式更正此问题,您可以执行以下操作:
ByteBuffer byteBuf = (ByteBuffer)mappedBuffer;
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer floatBuf = byteBuf.asFloatBuffer();
然后当您从 floatBuf
读取时,您应该得到正确的值。
我无法从使用 glMapBufferRange 映射的缓冲区中读取数据
如果我只是将一些数据放入缓冲区
// Create input VBO and vertex format
int bufferLength = 5 * 4; //5 floats 4 bytes each
FloatBuffer data = ByteBuffer.allocateDirect(bufferLength)
.order(ByteOrder.nativeOrder()).asFloatBuffer();
float[] floatData = { 1.0f, 4.0f, 9.0f, 16.0f, 25.0f };
data.put(floatData).position(0);
在 GL 中生成数组缓冲区并用数据填充它
int[] vbo = new int[1];
GLES30.glGenBuffers(1, vbo, 0);
GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]);
GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bufferLength, data, GLES30.GL_STATIC_DRAW);
MyGLRenderer.checkGlError(TAG + " glBufferData GL_ARRAY_BUFFER");
当我使用 glMapBufferRange
映射缓冲区并读取结果时
Buffer mappedBuffer = GLES30.glMapBufferRange(GLES30 .GL_ARRAY_BUFFER,
0, bufferLength, GLES30.GL_MAP_READ_BIT);
if (mappedBuffer!=null){
FloatBuffer transformedBuffer = ((ByteBuffer) mappedBuffer).asFloatBuffer();
MyGLRenderer.checkGlError(TAG + " glMapBufferRange");
Log.d(TAG, String.format("pre-run input values = %f %f %f %f %f\n", transformedBuffer.get(),
transformedBuffer.get(), transformedBuffer.get(), transformedBuffer.get(), transformedBuffer.get()));
transformedBuffer.position(0);
}
GLES30.glUnmapBuffer(GLES30.GL_ARRAY_BUFFER);
logcat 读取全零
D/TransformFeedback﹕ pre-run input values = 0.000000 0.000000 0.000000 0.000000 0.000000
没有产生其他错误,我不确定还要检查什么。我尝试了 GLES30.glCopyBufferSubData(GLES30.GL_ARRAY_BUFFER, GLES30.GL_COPY_READ_BUFFER, 0, 0, bufferLength);
和映射 GL_COPY_READ_BUFFER 并得到了相同的结果。
我正在支持 OpenGL ES 3.1 的 Nexus 6 上进行测试,因此该功能应该存在。
这个 question 建议删除 glfw 中的 OPENGL_FORWARD_COMPAT 提示,是否需要在 MyGLSurfaceView 中进行类似的操作?
非常感谢 Reto Koradi,如果有人想留下答案,我会将其标记为正确。
转换不正确。需要按 LITTLE_ENDIAN 顺序:
ByteBuffer transformedBuffer = ((ByteBuffer) mappedBuffer);
transformedBuffer.order(ByteOrder.LITTLE_ENDIAN);
Log.d(TAG, String.format("pre-run input values = %f %f %f %f %f\n", transformedBuffer.getFloat(),
transformedBuffer.getFloat(), transformedBuffer.getFloat(),
transformedBuffer.getFloat(), transformedBuffer.getFloat()));
这看起来像是读回数据时的字节顺序问题。数据将按本机字节顺序排列,而 Java 假定缓冲区中的数据默认为大端。由于现在大多数体系结构都是小端,这与您需要的相反。
要以适用于大端和小端架构的方式更正此问题,您可以执行以下操作:
ByteBuffer byteBuf = (ByteBuffer)mappedBuffer;
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer floatBuf = byteBuf.asFloatBuffer();
然后当您从 floatBuf
读取时,您应该得到正确的值。