为什么我们在OpenGL(ES)android中以字节而不是浮点数分配块,尽管我们大多数时候都使用float

时间:2014-12-01 18:00:46

标签: android opengl-es allocation bytebuffer floatbuffer

这就是我如何制作一个三角形数组

float[] tableVerticesWithTriangle = {

                    // triangle 1
                    0f, 0f, 9f, 14f, 0f, 14f,

                    // triangle 2
                    0f, 0f, 9f, 0f, 9f, 14f

            };

这就是我在原生环境中分配块的方式

 vertexData = ByteBuffer
                .allocateDirect(
                        tableVerticesWithTriangle.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder()).asFloatBuffer();
 vertexData.put(tableVerticesWithTriangle);

1 个答案:

答案 0 :(得分:4)

人们使用ByteBuffer.allocateDirect()的原因是其他缓冲类(如FloatBuffer)没有allocateDirect()方法。只能将ByteBuffer分配为直接缓冲区。因此,分配ByteBuffer,然后将内存用作FloatBuffer,是获得直接分配FloatBuffer的唯一方法。

什么是直接缓冲区?

isDirect()FloatBuffer的文档解释如下:

  

指示此缓冲区是否为直接缓冲区。直接缓冲区将尽最大努力利用本机内存API,它可能不会留在Java堆中,因此它不受垃圾收集的影响。

     

浮点缓冲区是直接的,如果它基于字节缓冲区并且字节缓冲区是直接的。

在其他(不太正式)的单词中,本机缓冲区是Java没有搞乱的本机内存分配。

何时需要直接缓冲?

奇怪的是,我从未能找到明确的文档。因此,以下假设是我通过实验证实的,到目前为止没有找到任何反例。

当缓冲区传递给OpenGL API时,使用直接缓冲区 ,在调用返回后,OpenGL实现使用内存。

我只能找到一个例子:客户端顶点阵列(BTW在ES 3.0中被标记为遗留功能,但仍然受支持)。这是具有以下签名的glVertexAttribPointer()调用,它支持不使用VBO的顶点数组:

glVertexAttribPointer(int indx, int size, int type, boolean normalized,
                      int stride, Buffer ptr)

在这种情况下,OpenGL将在以后的绘制调用中从缓冲区中提取顶点数据,因此在调用返回后,OpenGL仍然可以访问缓冲区内容,并且可能会直接由GPU读取。

在所有其他情况下(同样根据我的假设),使用直接缓冲区是必要的。例如,您可以执行以下操作:

float[] vertexData = {...};
GLES20.glBufferData(GL_ARRAY_BUFFER, vertexData.length * 4,
                    FloatBuffer.wrap(vertexData), GLES20.GL_STATIC_DRAW);

glBufferData()调用在调用期间消耗数据,并且在调用返回后OpenGL无法访问原始缓冲区。因此,没有必要使用直接缓冲区。