【问题标题】:glMapBufferRange returning all zeros in AndroidglMapBufferRange 在Android中返回全零
【发布时间】:2015-09-16 08:53:45
【问题描述】:

我无法从使用 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 中生成一个 Array Buffer 并用数据填充它

    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 中是否需要发生类似的事情?

【问题讨论】:

  • 您能否检查这些值是否完全为零,或者当您打印它们时它们看起来是否只是零?例如,记录比较值== 0.0f 的结果。我有一个理论......
  • 说得对,先生,您真是个天才!我假设您的理论是需要翻转缓冲区(或设置为大/小edian),欢迎提出如何做到这一点的建议,我现在正试图弄清楚。 mappedBuffer.flip() 在尝试转换为浮动缓冲区(下溢)时导致崩溃。
  • 第一个元素的值为 4.6006E-41
  • 与天才无关,我几周前恰好遇到了同样的问题。在我的例子中,缓冲区包含整数。所以经过一些初步的困惑之后,我很快就清楚我得到的是字节交换数据。
  • 有浮点数这很奇怪,因为它们都是零。我想也许他们在某个时候的顺序错误,但没有跟进并检查出来。使用 OpenGL,我做了很多事情,却不明白我在寻找错误的地方。我真的很想亲吻你,我已经处理了几天并且打算放弃并从事其他工作,但如果我这样做了,这个功能直到下一个周期才会进入我的应用程序,这可能是一两年。

标签: java android opengl-es opengl-es-3.0


【解决方案1】:

当您读回数据时,这看起来像是一个字节顺序问题。数据将按本机字节顺序排列,而 Java 默认假定缓冲区中的数据是大端。由于现在大多数架构都是小端的,这与您需要的相反。

要以适用于大端和小端架构的方式纠正此问题,您可以执行以下操作:

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

那么当你从floatBuf读取时,你应该得到正确的值。

【讨论】:

    【解决方案2】:

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

    【讨论】:

    • 我认为使用nativeOrder() 而不是LITTLE_ENDIAN 更简洁。然后它将适用于所有架构。看我的回答。
    猜你喜欢
    • 2023-04-07
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-05
    • 2018-03-15
    相关资源
    最近更新 更多