在OpenGL中渲染网格作为一系列子组?

时间:2012-04-23 23:12:44

标签: opengl shader .obj wavefront

我正在完成一个波前对象解析器,我想用它来构造泛型网格对象。我的引擎使用OpenGL 4和着色器在我的引擎中绘制所有内容。

我的问题是如何确保渲染网格的最佳渲染效率。

wavefront .obj file通常指定了许多对象子组。

可能会为子组指定特定材质(例如闪亮的红色)。

因此,网格可能是一个相当复杂的子组集合,每个子组都有自己的材质。

我的问题是 -

Q值。我是否需要单独绘制每个子组,例如为每个子组调用glDrawElements? (因此,如果我有4个独立的子组,我必须进行四次glDrawElements调用,从而通过4次统一更改(对于材质/纹理)调用着色器4次)

glDrawElements( GL_TRIANGLES, nNumIndicesInGroup, GL_UNSIGNED_INT, ((char*)NULL)+ first-vertex-offset );

如果这是正确的,那么我必须计算:

每个子组中的索引(表示每个子组的单独索引数组和VAO)   子组开始的顶点偏移量

这看起来非常低效,我是在咆哮错误的树吗?

另外,来自Wavefront obj wiki page

Smooth shading across polygons is enabled by smoothing groups.
 s 1
 ...
  # Smooth shading can be disabled as well.
  s off
  ...

任何人都可以建议平滑阴影值表示什么?例如。 s1,s2,s4等。

1 个答案:

答案 0 :(得分:9)

是的,您应该将每个子组与其他子组分开绘制。这是必需的,直到子组之间的状态不同。

但是你迈出了太长的一步。

为避免多次绘制调用,可以引入顶点属性,指示用于访问统一数组值的索引(材质数组,纹理数组)。通过这种方式,您只需要一次绘制调用,但您将获得一个额外属性及其相对管理的成本。

我会避免上述方法。如果一个子组有纹理而另一个没有纹理怎么办?你怎么辨别是否纹理?介绍其他属性?似乎令人困惑。

第一点是缓冲对象管理非常灵活。实际上,您可以拥有单个元素缓冲区对象和单个顶点缓冲区对象:使用偏移和交错可以满足各种复杂程度。然后,在现代硬件上,使用顶点数组对象可以最大限度地降低不同缓冲区绑定的成本。

第二点是你的软件可以将具有相同统一状态的不同子组分组,将多个绘制调用连接成一个。请记住,您可以使用 Multi 绘制入口点变体,还有可以帮助您的原始重启(在剥离原语的情况下)。

其他考虑因素无用,因为无论如何,无论是否复杂,您都必须进行绘制。接下来,当你有一个正确的渲染时,你可以分析应用程序和渲染,切断热点。


平滑组是共享相同选项属性(法线,纹理坐标)的顶点集合。这是元素索引顶点的情况。

要深入了解主题,请阅读谷歌搜索找到的specification之一。