【发布时间】:2014-12-27 01:04:47
【问题描述】:
我已经了解了现有的主题并自己进行了一些测试,但我不太确定我是否以正确的方式做这件事,所以我宁愿提出一个问题,也不愿花更多时间来弄清楚自己我对使用多个 OpenGL ES 2.0 教程的误解。
我已经实现了 VBO,因为它们在“适用于 Android 的 OpenGL ES 2 - 快速入门指南”中有所介绍,我发现我需要一个动态 VBO,该动态 VBO 在每一帧都通过一些矩阵计算进行更新(这可能是我错的地方)在模型顶点上。在这些计算之后,我想用这段 Android/Java 代码将那些转移(更新)到已经分配的 VBO(使用 glBufferData):
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, this.id);
//GLES20.glBufferData(GLES20.GL_ARRAY_BUFFER, this.getLength() * Utils.BYTES_PER_FLOAT, null, GLES20.GL_DYNAMIC_DRAW);
/* CREATE BUFFER AND SET POSITION */
FloatBuffer fBuffer = ByteBuffer.allocateDirect((this.length = vertices.length) * Utils.BYTES_PER_FLOAT)
.order(ByteOrder.nativeOrder()).asFloatBuffer().put(vertices);
fBuffer.position(0);
GLES20.glBufferSubData(GLES20.GL_ARRAY_BUFFER, 0, fBuffer.capacity(), fBuffer);
GLES20.glBindBuffer(GLES20.GL_ARRAY_BUFFER, 0);
- this.id - 先前生成的缓冲区的 ID
- this.getLength - 初始分配的 FloatBuffer 长度
正如您所注意到的,我已经注释掉了其他问题中提到的那行,只是因为保持它在屏幕上以我无法正确理解的闪烁对象结束。以这种方式一切正常,但我注意到在应用程序运行期间有一些 GC_FOR_ALLOC 确保我可能不是有效的代码。
问题——或多或少——是:
- 这是更新此类缓冲区的有效方法吗?或者在我提供的情况下(OpenGL ES 2.0、Android 4+),我能否获得如何正确执行此操作的建议?
子问题是:
- 在这些情况下,将 VBO 用于动态模型是否比使用 VAO 更好,还是我应该为静态实现 VBO 方法,为动态模型实现 VAO?
- 我什么时候应该开始担心内存问题,只需查看 GC_FOR_ALLOC 调试信息?
- (有点超出主题子问题)使用正交等距视图矩阵(正交 + 2x 旋转 + Z 平移)为应用程序创建 GUI 的合适方法是什么?
编辑 (27.12):
要实现等距投影矩阵,我只需使用以下几行:
Matrix.orthoM(this.orthoProjectionMatrix, 0, -screenAspect, screenAspect, -1.0f, 1.0f, -1.0f, 10.0f);
Matrix.translateM(this.viewProjectionMatrix, 0, this.orthoProjectionMatrix, 0, 0.0f, 0.0f, -5.0f);
Matrix.rotateM(this.viewProjectionMatrix, 0, 45, 1.0f, 0.0f, 0.0f);
Matrix.rotateM(this.viewProjectionMatrix, 0, 45, 0.0f, 1.0f, 0.0f);
这很简单:
- 根据屏幕的纵横比创建正交、纵向投影
- 仅在 Z 轴上平移移动(因此从远处可以看到场景)
- 将 X 轴旋转 45 度
- 将 Y 轴旋转 45 度
有些元素是放在一起的,所以请不要考虑到有些翻译是就地的,有些是与另一个矩阵的结果。
【问题讨论】:
-
您在问题中描述的内容与我有关。您正在使用 OpenGL ES 2.0,但您正在谈论将矩阵变换应用于存储在 VBO 中的顶点。如果您可以访问着色器,通常不会这样做。您可以将要转换顶点的矩阵传递给顶点着色器,并在每次绘制时应用该转换。您的顶点缓冲区数据实际上是静态的,它将是完成所有工作的顶点着色器(重复)。 从事物的声音来看,您可以在矩阵而不是顶点缓冲区中累积变换。
-
我已经弄清楚了。在下面检查我的一个 cmets。这确实是一种无效的做法。我现在在渲染场景或 HUD 时在附加到着色器的统一矩阵之间切换。参考您刚才所说的 - 每当我应用一些每帧变换时 - 我是否应该始终对传递给着色器的变换矩阵进行操作,或者对模型顶点进行操作并且拥有动态 VBO 更有效?我无法找到任何引用 OpenGL ES 2.0 (Android) 并以平易近人的方式描述它的书籍/材料。我感到困惑。
-
除非必须,否则您永远不想更改顶点缓冲区中的顶点。如果您将顶点缓冲区视为存储在 GPU 内存中,这可能会有所帮助,您希望在每帧中尽可能少地将数据从 CPU 传输到 GPU。更新矩阵(16 个浮点数)几乎总是比更新每个顶点的数据少。因此,如果您想每帧将同一模型旋转不同的量,请更新矩阵并让顶点着色器进行实际转换。动态 VBO 更适合诸如“有状态”粒子系统之类的东西,它依赖于以前的顶点着色器输出。
-
经过两天的开发,我得出结论,在这些 cmets 中,我一直在寻找答案。它——无论如何——对我来说似乎有点不合理。让我解释一下为什么我有这些疑问。考虑一种情况: 1) 一个对象位于 (0, 0, 0) 2) 一个对象正被 vextor (1, 0, 0) 从它的位置移动我应该: A) 转换
viewProjectionMatrix所以它由 (-1, 0, 0) 平移,然后将其传输到着色器 B) 更新包含此类对象顶点的 VBO。这个例子的答案应该让我的愿景变得清晰。
标签: java android opengl-es vbo