我正在使用webgl做一个小游戏。在这个游戏中,我有一种森林,它由许多(100+)树对象组成。因为我只有几个不同的树模型,所以在显示它们之前,我会以不同的方式旋转和缩放这些模型。
此刻,我环游了所有的树来展示它们:
for (var tree in trees) {
tree.display();
}虽然树的display()方法看起来像:
display : function() { // tree
this.treeModel.setRotation(this.rotation);
this.treeModel.setScale(this.scale);
this.treeModel.setPosition(this.position);
this.treeModel.display();
}许多树对象共享相同的treeModel对象,因此我必须在每次显示模型之前设置模型的旋转/缩放/位置。每棵树的旋转/比例/位置值是不同的。
treeModel的显示方法完成了所有的gl操作:
display : function() { // treeModel
// bind texture
// set uniforms for projection/modelview matrix based on rotation/scale/position
// bind buffers
// drawArrays
}所有的树模型使用相同的着色器,但可以使用不同的纹理。
由于单个树模型仅由几个三角形组成,所以我希望将所有树合并到一个VBO中,并使用一个drawArrays()调用显示整个森林。
有些假设使得谈论数字变得更容易:
我有以下问题:
目前,
50 * 3 * 8 (position + normal + texCoord) * floatSize字节大小的缓冲区。当我想用一个vbo显示所有树时,我将有一个250 * 50 * 3 * 8 * floatSize字节大小的缓冲区。我认为我不能使用索引缓冲区,因为我对每棵树都有不同的位置值(根据树模型的位置值和树的位置/比例/旋转值计算)。这是正确的,还是仍然有一种方法,我可以使用索引缓冲区,以减少缓冲区大小至少一点?也许还有其他的优化方法?,
glMapBuffer不能添加新的值。对吗?发布于 2012-03-17 18:11:30
索引元素缓冲区只能覆盖长度等于或小于65535的属性,因此需要使用drawArrays。这通常不是什么大损失。
可以使用GL.bufferSubData将树添加到缓冲区的末尾。
如果你的纹理尺寸合理(比如128x128或256x256),你可能可以把它们合并成一个大的纹理,然后用紫外线和弦来处理整个事情。如果没有,您可以添加另一个属性,表示顶点属于什么纹理,并且在顶点着色器中有一个条件,或者添加一个sampler2Ds数组(不确定它是否工作,从未尝试过)。记住,着色器的条件是相当缓慢的。
如果您决定坚持您的当前解决方案,确保排序的树木,因此一旦使用相同的纹理后,相互渲染-保持状态切换是必不可少的,始终。
发布于 2012-03-18 20:30:53
几点想法:
是什么
发布于 2012-03-17 01:19:27
你现在的方法还不错。我会说:坚持到底,直到你撞到墙上。
50三角形已经是一个合理的批次大小一个单一的绘图/绘图already调用。这不是最理想的,但也不是很糟糕。所以每一棵树都会通过制服来改变位置、纹理和形状等参数。然后对每棵树进行抽签。另外,总共250个drawElements调用也不是那么糟糕。
所以我会使用一个VBO,它包含所有使用过的树形变体。我实际上把这些树分成了几块,这样我就可以重新组合它们以增加品种。对于每棵树,在调用drawArrays或drawElements之前,都要将适当的偏移量放到VBO中。
此外,不要忘记,你可以做一个非常便宜的视野,每棵树的剔除。
https://stackoverflow.com/questions/9746088
复制相似问题