3

我正在 Maya 中创建一个一分钟长的动画,我打算在 OpenGL 中渲染它。我这样做是作为大学的一个项目。

场景中只有一张人脸做出扭曲的表情。网格有大约 2200 个四边形面。

我找到了一个将 Wavefront 对象文件转换为顶点和法线数组的 perl 脚本。我打算在 Maya 中以 24fps 的速度制作动画,然后将每一帧中的网格导出到 Wavefront 对象文件,然后通过 perl 脚本运行所有这些,这将为我提供顶点和法线数组。

因此,为了测试可行性,我将 Maya 中的两帧动画转换为目标文件,并通过脚本运行它(调整后),这给了我数千次glVertex调用glNormal。我将所有这些复制到我的 C++ 程序并编译它。它运行顺利。

考虑到当我将 60sec*24frame 的glVertexglNormal语句复制到程序中时程序会有多大,我想尝试使用 VBO。所以,我读到了它,但我不太了解它的实现。

所以我的第一个问题是:在这种情况下实现 VBO 的最佳方法是什么?

我正在考虑顶点和法线的二维数组,每帧一个;GL_STATIC_DRAW_ARB对于glBufferDataARB(). _

假设我的动画是 5 帧长,我的面部网格由 2200 个顶点和法线组成,那么我将创建:

GLfloat face_vertices[5][2200] = {.....};
GLfloat face_normals[5][2200] = {.....};

我的第二个问题:上面的代码会在 VBO 上工作或表现得“好”吗?

另外,我不确定这些信息是否重要,但我的计算机运行在 Intel 82945G 显卡上,而且我很确定我大学的 PC 也运行在 Intel 上。只是想我会提到这一点。

更新

性能也是一个问题。

4

2 回答 2

1

如果您可以流畅地运行动画的两帧,则可以流畅地运行 60*24 帧“值得 glVertex 和 glNormal 语句”,如果您可以从 Maya 动画自动生成 GL 调用。这种方法的唯一问题是您的源代码和二进制可执行文件将非常庞大。这是使您的方法“不好”的问题。

因此,首先,您可以将数据放在一个数组(或 std::vector,就此而言)中,而不是对每个顶点数据进行一次 glVertex 调用,并使用简单的循环遍历它:

std::vector<int> idx;
std::vector<vertex> frame_data;
...
glBegin(GL_QUADS);
for(int i = 0; i < idx.size(); ++i) {
  glVertex3f(frame_data[idx].x, frame_data[idx].y, frame_data[idx].z);
  glNormal3f(frame_data[idx].nx, frame_data[idx].ny, frame_data[idx].nz);
}
glEnd();

idx 表示面,idx 中的每 4 个元素组成一个四边形。frame_data 是该帧的特定顶点数据,每一帧必须有一个这样的数组,并且该数据由 idx 索引。这样,您唯一需要解决的问题就是如何将这些数据读入您的应用程序。如果您可以从网格文件生成 glVertex 调用,则可以改为生成一个文件,您可以使用 C++ fstream 在应用程序中轻松加载该文件,并构建数据数组,然后遍历它们并进行绘图调用。

在这种情况下,您不会看到使用 glBegin()/glEnd() 和 VBO 之间的性能差异,因为 2200 个四边形的数量太少,无法产生任何影响,但这对您来说将是一个有趣的练习。组织数组中的数据(idx 和 vertex_data)是使用 VBO 的第一步。您必须将与一个顶点相关的所有数据打包到一个结构中:

struct vertex {
  float x, y, z; // Position
  float nx, ny, nz; // Normal
};
...
vertex frame_data[v_count];
uint16_t idx[2200 * 4]; // 4 vertices makes one face

请注意,v_count不是2200。这是您的四边形计数,因此该数字与 idx 大小相关,而不是 frame_data,即可以在多个四边形面中使用相同的顶点。

您将需要两个缓冲区,一个静态来保存 idx(一个 GL_ELEMENT_ARRAY_BUFFER 和 GL_STATIC_DRAW),因为这在执行期间不会改变,另一个“流”缓冲区来保存顶点数据(GL_ARRAY_BUFFER 和 GL_STREAM_DRAW)。最后一个使用“GL_STREAM_DRAW”,因为您需要为动画每帧重写其内容。请参阅glBufferData

于 2012-04-22T18:53:05.823 回答
1

我正在考虑顶点和法线的二维数组,每帧一个;和

我认为这是不正确的解决方案。有了这么多的数据,流式传输它是有意义的。例如,将 1 秒的动画保留在内存中,其余的按需加载。我相信有GL_STREAM_****这种情况的标志。

更好的解决方案是从 Maya 及其动画中导出骨骼。(在这种情况下,您需要一个永远不会改变的网格)

您必须逐帧导出每个顶点动画的唯一情况是导出计算量非常大的东西。我能想到的唯一现实场景是 3D 流体网格(拓扑改变非常框架等)——其他一切都可以在 CPU 或 GPU 上计算。但是,您的帖子并不表明这是您的情况。因此,根据墨菲定律,我将不得不假设您正在使用低效的解决方案来解决可以以不同方式解决的问题。

: 上面的代码会在 VBO 上工作或表现得“好”吗?

无法回答,因为你没有说你将如何绘制数据。通过滥用着色器、alpha 混合或多次渲染相同的东西,即使是简单的几何图形,也有可能让任何机器屈服。

于 2012-04-22T16:25:46.473 回答