为啥我们在 OpenGL (ES) android 中以字节分配块而不是浮点数,尽管我们大部分时间都使用浮点数
Posted
技术标签:
【中文标题】为啥我们在 OpenGL (ES) android 中以字节分配块而不是浮点数,尽管我们大部分时间都使用浮点数【英文标题】:why do we allocate blocks in bytes rather than floats in OpenGL (ES) android , though we work with float most of the times为什么我们在 OpenGL (ES) android 中以字节分配块而不是浮点数,尽管我们大部分时间都使用浮点数 【发布时间】:2014-12-01 18:00:45 【问题描述】:这就是我如何制作一个三角形数组
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】:人们使用ByteBuffer.allocateDirect()
的原因是其他缓冲区类,如FloatBuffer
,没有allocateDirect()
方法。只有ByteBuffer
可以分配为直接缓冲区。所以分配ByteBuffer
,然后将内存用作FloatBuffer
,是获得直接分配FloatBuffer
的唯一方法。
什么是直接缓冲区?
FloatBuffer
类的isDirect()
的文档是这样解释的:
指示此缓冲区是否是直接的。直接缓冲区会尽力利用本机内存 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访问。因此,没有必要使用直接缓冲区。
【讨论】:
以上是关于为啥我们在 OpenGL (ES) android 中以字节分配块而不是浮点数,尽管我们大部分时间都使用浮点数的主要内容,如果未能解决你的问题,请参考以下文章
Android OpenGL ES和OpenGL一起学------理解Viewport(视口)和坐标系Android OpenGL ES篇(转帖)
为啥这个 OpenGL ES 代码在 iPhone 上运行缓慢?