我目前正在开发一个框架,可以方便地渲染大量的动画模型。
模型被组织为一个简单的骨骼层次结构,其根部是躯干/骨盆,通常是:
所以,作为伪代码,我目前正在渲染这样的模型:
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使用相同模型,我考虑切换到实例化渲染。
但是,我能找到的所有信息和教程都是关于绘制立方体,球体或类似的简单对象。无处可以看到一些简单易懂的信息,关于如何使用实例化绘制来渲染模型,其中每个部分(骨骼)需要为着色器提供不同的变换矩阵。
所以,问题是:
使用glVertexAttribDivisor
或gl_InstanceID
我只能指定与实例相关的矩阵,而不是骨骼矩阵。我如何应用骨骼转换?
我能想到的唯一可行的解决方案是 - 我可以实例化每个骨骼,而不是实例化整个模型。从而绘制一个骨骼类型的所有实例,然后绘制另一个骨骼类型等 但是,我仍然需要相对经常使用转换矩阵更新缓冲区,而且它是更多的内务代码。
这是最好的选择吗?或者,更一般地说,是否有更好的不太复杂的渲染方式? 或者,实例化渲染在与静态几何体一起使用时才真正发光?
答案 0 :(得分:14)
当你需要绘制相同模型的数千个副本时,就会使用实例化。一般来说,骨骼网格不是你需要绘制成千上万个的东西。
实例化是一种优化,不总是得到回报。你不应该费心去尝试使用它,除非你知道你需要它(通过剖析并看你是否达到了性能目标)。即使这样,它在实际性能提升时也会非常敏感。
有时,它没有帮助。但这里有一些一般的经验法则:
请记住,这些是一般规则,而不是绝对规则。它们也依赖于硬件。
所以,问题是:使用glVertexAttribDivisor或gl_InstanceID我只能指定与实例相关的矩阵,而不是骨骼矩阵。我如何应用骨骼转换?
从你看过的例子或者其他人看到的例子来看,你的想法太多了。像程序员一样思考。
gl_InstanceID
不是“与实例相关的矩阵”;它是索引。您对该索引的处理完全取决于您。您见过的大多数示例都使用此索引来查找矩阵数组,可能存储在uniform block或buffer texture中。此矩阵是用于渲染的变换。每个索引代表单个实例的转换。
每个实例都有多个矩阵,多个变换。但是每个实例具有相同数量的骨骼(否则它将不是实例化渲染)。假设你有5个骨头。
同样,每个索引都是单个实例的转换。您的案例与标准之间的区别在于每个实例需要多少信息。常规案例需要一个矩阵;你需要五个。但这个想法无论如何都是一样的。
如果您需要当前实例的骨骼索引3,则只需使用以下表达式访问矩阵数组:(gl_InstanceID * 5) + 3
,其中5是每个实例的骨骼数。
其余的是使用每顶点属性来传递用于变换每个顶点的骨骼索引的简单问题。