c++ - OpenGL中动态模型的实例化绘制

标签 c++ opengl opengl-3

我目前正在开发一个框架,可以方便地渲染大量动画模型。

一个模型被组织为一个简单的骨骼层次结构,根是躯干/骨盆,通常:

My simple modeling hierarchy

因此,作为伪代码,我目前正在渲染这样一个模型:

RenderBone(Bone b, Mat4x4 currentTransform){
    Mat4x4 pos = currentTransform * b.boneTransform;
    SetUniform("transformation", pos);
    Draw(bone.mesh);
    for each Bone bc in b.children do{
         RenderBone(bc, pos);
    }
}

因此对于使用具有 n 个骨骼的模型的单个 actor,我需要 n 个 SetUniform(不包括设置纹理之类的东西)和 n 个绘制调用。

为了减少这种开销并同时使用同一模型渲染所有 Actor ,我考虑切换到实例化渲染。

但是,我能找到的所有信息和教程都是关于绘制立方体、球体或类似简单对象的。在任何地方,我都看不到一些关于如何使用实例化绘图来渲染模型的简单易懂的信息,其中每个部分(骨骼)都需要为着色器提供不同的变换矩阵。

所以,问题: 使用 glVertexAttribDivisorgl_InstanceID 我只能指定与实例相关的矩阵,而不是骨骼相关矩阵。那么我该如何应用我的骨骼转换?

我能想到的唯一可行的解​​决方案是 - 我可以实例化每个骨骼,而不是实例化整个模型。因此绘制一种骨骼类型的所有实例,然后绘制另一种,依此类推。 但是我仍然需要相对频繁地使用转换矩阵更新缓冲区,而且这是更多的内务处理代码。

那么这是最好的选择吗?或者,更一般地说,是否有更好的不太复杂的渲染方式? 还是实例化渲染只有在与静态几何体一起使用时才真正发挥作用?

最佳答案

当您需要绘制数千 相同模型的拷贝时,您可以使用实例化。通常,带有骨骼的网格不是您需要绘制成千上万的东西。

实例化是一种优化,并不总能得到返回。除非您知道您需要它(通过分析并查看您是否达到性能目标),否则您不应该费心尝试使用它。即便如此,对于何时才是真正的性能改进也可能非常敏感。

有时,它只是无济于事。但这里有一些一般的经验法则:

  1. 除非您要渲染数千个实例,否则实例化是不值得的。
  2. 实例化不应用于顶点过多或过少的网格。 100-1,000 左右。

请记住,这些是一般规则,而不是绝对的法律。它们还依赖于硬件。

So, the problem: Using glVertexAttribDivisor or gl_InstanceID I can only specify an instance-related matrix, not a bone-realted matrix. How do I apply my bone transformations then?

根据您看到的例子或您看到其他人所做的事情,您考虑得太多了。像程序员一样思考。

gl_InstanceID 不是“与实例相关的矩阵”;它是一个索引。您如何处理该索引完全取决于您。您见过的大多数示例都使用此索引来查找矩阵数组,可能存储在 uniform block 中或 buffer texture .该矩阵是您用于渲染的变换。每个索引代表单个实例的转换。

您的每个实例都有多个矩阵、多个转换。但是每个实例都有相同数量的骨骼(否则它不会被实例化渲染)。假设您有 5 根骨头。

同样,每个索引都是单个实例的转换。您的案例与标准之间的区别在于每个实例需要多少信息。常规情况需要一个矩阵;你需要五个。但无论哪种方式,想法都是一样的。

如果当前实例需要骨骼索引 3,只需使用以下表达式访问矩阵数组:(gl_InstanceID * 5) + 3,其中 5 是每个实例的骨骼数。

剩下的就是使用每个顶点属性传递骨骼索引以用于变换每个顶点的简单问题。

关于c++ - OpenGL中动态模型的实例化绘制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11972855/

相关文章:

python - 使用 OpenGL 在 Python 中进行 3d 绘图

java - OpenGL:读取帧缓冲区的深度纹理

c++ - OpenGL/GLUT 试图使水平杆以不同方式波动

opengl - glTexImage2DMultisample 如何工作?

c++ - GDB:运行没有符号的cpp进程调试

c++ - 限制构造函数的功能

c++ - 评价顺序

c++ - 为什么 <cstring> 中的所有函数都不能有 constexpr?

c++ - 如何在mac上使用cmake链接OpenGL相关库?

OpenGL VAO 最佳实践