问题
I am having trouble reading out from a buffer mapped with glMapBufferRange
If I simply put some data in a buffer
// 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);
Generate a Array Buffer in GL and fill it with the data
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");
When I map the buffer using glMapBufferRange
and read the results
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);
The logcat reads all zeros
D/TransformFeedback﹕ pre-run input values = 0.000000 0.000000 0.000000 0.000000 0.000000
No other errors are generated and I am not really sure what else to check. I have tried GLES30.glCopyBufferSubData(GLES30.GL_ARRAY_BUFFER, GLES30.GL_COPY_READ_BUFFER, 0, 0, bufferLength);
and mapping GL_COPY_READ_BUFFER and gotten the same results.
I am testing on a Nexus 6 which supports OpenGL ES 3.1 so this functionality should be present.
This question suggests removing the OPENGL_FORWARD_COMPAT hint in glfw, could there be something similar that needs to happen in MyGLSurfaceView?
回答1:
This looks like a byte order problem when you read back the data. The data will be in native byte order, while Java assumes by default that data in buffers is big endian. Since most architectures are little endian these days, that's the opposite of what you need.
To correct for this in a way that will work for both big and little endian architectures, you can do the following:
ByteBuffer byteBuf = (ByteBuffer)mappedBuffer;
byteBuf.order(ByteOrder.nativeOrder());
FloatBuffer floatBuf = byteBuf.asFloatBuffer();
Then when you read from floatBuf
, you should get the correct values.
回答2:
Big thanks to Reto Koradi, if anyone wants to leave an answer I will mark it as correct.
The casting was incorrect. Needs to be in LITTLE_ENDIAN order:
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()));
来源:https://stackoverflow.com/questions/31123376/glmapbufferrange-returning-all-zeros-in-android