为什么是 FloatBuffer 而不是 float[]?

2022-08-31 21:02:20

我已经在我的Android代码中使用FloatBuffers一段时间了(从一些opengles教程中复制了它),但我无法确切地理解这个结构是什么以及为什么需要它。

例如,我在许多人的代码和Android教程中看到的这个代码(或类似代码):

float[] vertices = ...some array...

ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4); 
vbb.order(ByteOrder.nativeOrder());    // use the device hardware's native byte order
FloatBuffer fb = vbb.asFloatBuffer();  // create a floating point buffer from the ByteBuffer
fb.put(vertices);    // add the coordinates to the FloatBuffer
fb.position(0);      // set the buffer to read the first coordinate

对于一些东西来说,这似乎非常冗长和混乱,据我所知,它只是一系列浮子的花哨包装。

问题:

  • 这种类型的类(ByteBuffer,FloatBuffer)与任何其他类型的集合或简单的浮点数组相比,有什么理由?

  • 在将字节缓冲器转换为 FloatBuffer 之前,创建它背后的想法是什么?


答案 1

主要原因是性能:ByteBuffers和其他NIO类在与本机代码接口时支持加速操作(通常通过避免将数据复制到临时缓冲区的需要)。

例如,如果您正在执行大量OpenGL渲染调用,这一点非常重要。

首先创建 ByteBuffer 的原因是您希望使用 allocateDirect 调用来创建直接字节缓冲区,这受益于加速操作。然后,从中创建一个共享相同内存的 FloatBuffer。由于某种原因,FloatBuffer本身没有displicDirect方法,这就是为什么你必须通过ByteBuffer。


答案 2

我们在Android上用Java进行编码,但OpenGL ES的底层实现实际上是用C编写的。在将数据传递给 OpenGL 之前,我们需要将其转换为它将要理解的形式。Java和本机系统可能不会以相同的顺序存储它们的字节,因此我们使用一组特殊的缓冲区类并创建一个足够大的ByteBuffer来保存我们的数据,并告诉它使用本机字节顺序存储其数据。然后,我们将其转换为 FloatBuffer,以便我们可以使用它来保存浮点数据。最后,我们将数组复制到缓冲区中。


推荐