3

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

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);
4

1 回答 1

5

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

什么是直接缓冲区?

该类的文档是isDirect()这样FloatBuffer解释的:

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

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

换句话说(不太正式),本机缓冲区是 Java 不会搞乱的本机内存分配。

什么时候需要直接缓冲区?

奇怪的是,我从来没有找到明确的文档。所以以下是我通过实验证实的假设,目前还没有找到任何反例。

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

我只能找到一个这样的例子:客户端顶点数组(顺便说一句,它在 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访问。因此,没有必要使用直接缓冲区。

于 2014-12-02T07:06:13.117 回答