2015-06-29 27 views
2

我无法从glMapBufferRangeglMapBufferRange返回全零Android中

映射一个缓冲器中读出。如果我只是把一些数据缓冲区

// 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中是否会出现类似的情况?

+1

您可以检查这些值是否恰好为零,或者当您打印它们时只显示为零?例如,记录比较值“== 0.0f”的结果。我有一个理论...... –

+0

这是正确的先生,你是一个天才!我假设你的理论是缓冲区需要翻转(或设置为大/小edian),如何做到这一点的建议是受欢迎的,我现在试图找出它。 'mappedBuffer.flip()'在尝试转换为浮点缓冲区(下溢)时导致崩溃。 – HPP

+0

第一个元素的值是4.6006E-41 – HPP

回答

1

当您读回数据时,看起来像是一个字节顺序问题。数据将采用本地字节顺序,而Java默认假设缓冲区中的数据为大端。由于现在大多数体系结构都是小端,所以这与你所需要的相反。

要的方式,才能既为大和little endian架构工作,纠正这一点,你可以做到以下几点:

ByteBuffer byteBuf = (ByteBuffer)mappedBuffer; 
byteBuf.order(ByteOrder.nativeOrder()); 
FloatBuffer floatBuf = byteBuf.asFloatBuffer(); 

然后,当你从floatBuf阅读,你应该得到正确的值。

0

非常感谢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())); 
+1

我认为使用'nativeOrder()'而不是'LITTLE_ENDIAN'更清洁。那么它将适用于所有体系结构。看到我的答案。 –

+0

发布工作代码要求,https://gist.github.com/hpp/d2d26adc5987002eb520 – HPP