Opengl es 如何使用webgl实现批处理?

Opengl es 如何使用webgl实现批处理?,opengl-es,3d,webgl,Opengl Es,3d,Webgl,我正在使用webgl开发一个小游戏。在这个游戏中,我有一些森林,由100多个树对象组成。因为我只有几个不同的树模型,所以在显示它们之前,我会以不同的方式旋转和缩放这些模型 此时,我在所有树上循环以显示它们: for (var tree in trees) { tree.display(); } 而树的显示方式如下所示: display : function() { // tree this.treeModel.setRotation(this.rotation); this.tre

我正在使用webgl开发一个小游戏。在这个游戏中,我有一些森林,由100多个树对象组成。因为我只有几个不同的树模型,所以在显示它们之前,我会以不同的方式旋转和缩放这些模型

此时,我在所有树上循环以显示它们:

for (var tree in trees) {
  tree.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中,并通过一个DrawArray调用显示整个森林

让谈论数字更容易的一些假设:

有250棵树要展示 有5种不同的树模型 每个树模型有50个三角形 我的问题是:

目前我有5个缓冲区,它们是50*3*8位置+普通+texCoord*floatSize字节大。当我想用一个vbo显示所有树时,我会有一个250*50*3*8*floatSize字节大小的缓冲区。我想我不能使用索引缓冲区,因为根据树模型的位置值和树的位置/比例/旋转,我对每棵树都有不同的位置值。这是正确的还是仍然有一种方法可以使用索引缓冲区来至少减少一点缓冲区大小?也许还有其他方法可以优化这一点

如何处理树模型的不同纹理?我可以将所有纹理绑定到不同的纹理单元,但如何在着色器中确定当前显示的片段应使用哪个纹理

当我想在运行时向这个缓冲区添加一个新的树或任何其他类型的对象时:我必须创建一个新的缓冲区并复制内容吗?我认为不能使用glMapBuffer添加新值。这是正确的吗


你目前的方法还不错。我会说:坚持下去,直到你撞到墙为止

对于单个drawElements/drawArrays调用,50个三角形已经是一个合理的批量大小。这不是最优的,但也不是那么糟糕。因此,对于每棵树,都要改变参数,比如位置、纹理,或者通过制服改变形状。然后对每棵树进行绘制调用。另外,总共250个抽屉元素调用也不是那么糟糕

因此,我将使用一个VBO,其中包含所有使用的树几何体变体。实际上,我把这些树分成了几个积木,这样我就可以把它们重新组合起来,增加种类。对于每个树,在调用DrawArray或DrawElement之前,在VBO中设置适当的偏移量


也不要忘记,你可以对每棵树进行非常便宜的视场剔除。

你目前的方法还不错。我会说:坚持下去,直到你撞到墙为止

对于单个drawElements/drawArrays调用,50个三角形已经是一个合理的批量大小。这不是最优的,但也不是那么糟糕。因此,对于每棵树,都要改变参数,比如位置、纹理,或者通过制服改变形状。然后对每棵树进行绘制调用。另外,总共250个抽屉元素调用也不是那么糟糕

因此,我将使用一个VBO,其中包含所有使用的树几何体变体。实际上,我把这些树分成了几个积木,这样我就可以把它们重新组合起来,增加种类。对于每个树,在调用DrawArray或DrawElement之前,在VBO中设置适当的偏移量


另外,不要忘记,您可以对每棵树进行非常便宜的视场剔除。

索引元素缓冲区只能覆盖长度等于或小于65535的属性,因此您需要使用DrawArray。这通常不是什么大损失

可以使用GL.bufferSubData将树添加到缓冲区的末尾

如果你的纹理大小合理,比如128x128或256x256,你可以把它们合并成一个大的纹理,然后用UV坐标处理整个事情。如果没有,则可以添加另一个属性,说明顶点所属的纹理,并在顶点着色器中具有条件,或者添加一组采样器2。如果不确定它是否有效,则从未尝试过。请记住,着色器中的条件非常缓慢


如果您决定坚持使用当前解决方案,请确保对树进行排序,以便使用相同纹理的树在彼此之后进行渲染-始终保持状态向下切换至关重要。

索引元素缓冲区只能覆盖长度等于或低于65535的属性,因此您需要改用DrawArray。这通常不是什么大损失

可以使用GL.bufferSubData将树添加到缓冲区的末尾

如果你的纹理大小合理,比如128x128或256x256,你可以把它们合并成一个大的纹理,然后用UV坐标处理整个事情。如果不是,你 可以添加另一个属性,说明顶点所属的纹理,并在顶点着色器中具有一个条件,或者一组采样器2D不确定它是否工作,从未尝试过。请记住,着色器中的条件非常缓慢

如果您决定坚持使用当前解决方案,请确保对树进行排序,以便使用相同纹理的树在彼此之后进行渲染-始终保持状态切换关闭非常重要。

一些想法:

一旦你在你的世界里种了一棵树,你会修改它吗?它会有生气吗?还是仅仅是静态几何?如果它真的是静态的,那么您总是可以用每个树的多个副本构建一个缓冲区。在附加树时,首先在Javascript中将该实例的世界变换应用于顶点。如果使用三角形条带,则可以使用退化多边形将树链接在一起。 您可以滚动自己的伪实例化图形: 在数组缓冲区中编码实例ID。对于属于同一树实例的所有顶点,只需将其设置为相同的值。我似乎记得,ES GLSL中不能有非浮动顶点属性,这可能是Chrome的限制,所以需要将其作为浮点引入,但将其作为int使用。因为它是作为浮点引入的,所以必须处理它在三角形上插值的事实,因此,这个值会有微小的波动,但只要四舍五入到最接近的整数就可以修正。 使用一个单独的纹理,我将称之为数据纹理来编码所有每个实例的信息。在顶点着色器中,查看当前顶点的实例ID,并使用该ID计算数据纹理中的纹理坐标。拉出变换当前顶点所需的任何内容,并应用它。我认为这被称为依赖纹理读取,这通常是不赞成的,因为它可能会导致性能问题,但它可能会帮助您批处理几何体,这有助于解决性能问题。如果你感兴趣的话,你得试试看会发生什么。 希望有一个扩展来支持真实的实例化图形。 一些想法:

一旦你在你的世界里种了一棵树,你会修改它吗?它会有生气吗?还是仅仅是静态几何?如果它真的是静态的,那么您总是可以用每个树的多个副本构建一个缓冲区。在附加树时,首先在Javascript中将该实例的世界变换应用于顶点。如果使用三角形条带,则可以使用退化多边形将树链接在一起。 您可以滚动自己的伪实例化图形: 在数组缓冲区中编码实例ID。对于属于同一树实例的所有顶点,只需将其设置为相同的值。我似乎记得,ES GLSL中不能有非浮动顶点属性,这可能是Chrome的限制,所以需要将其作为浮点引入,但将其作为int使用。因为它是作为浮点引入的,所以必须处理它在三角形上插值的事实,因此,这个值会有微小的波动,但只要四舍五入到最接近的整数就可以修正。 使用一个单独的纹理,我将称之为数据纹理来编码所有每个实例的信息。在顶点着色器中,查看当前顶点的实例ID,并使用该ID计算数据纹理中的纹理坐标。拉出变换当前顶点所需的任何内容,并应用它。我认为这被称为依赖纹理读取,这通常是不赞成的,因为它可能会导致性能问题,但它可能会帮助您批处理几何体,这有助于解决性能问题。如果你感兴趣的话,你得试试看会发生什么。 希望有一个扩展来支持真实的实例化图形。
+1.纹理图谱。另外,我不认为WebGL很好,至少Chrome在Mac OS上的实现是这样,但WebGL本身可能支持数组纹理。将多个纹理合并为一个是个好主意。我会调查的。我也不知道索引限制在65k。很好的信息,谢谢。由于用于索引元素的数据类型为Uint16Array,所以限制为65k。纹理图集为+1。另外,我不认为WebGL很好,至少Chrome在Mac OS上的实现是这样,但WebGL本身可能支持数组纹理。将多个纹理合并为一个是个好主意。我会调查的。我也不知道索引限制在65k。很好的信息,谢谢。由于用于索引元素的数据类型Uint16Array,它被限制为65k。到1:目前树是完全静态的。不过,我想有一个选项,以动画他们以后不改变一切。我认为动画是我目前方法的另一个问题。谢谢你的阅读想法。To 1:现在树木完全静止了。不过,我想有一个选项,以动画他们以后不改变一切。我认为动画是我目前方法的另一个问题。谢谢你的依赖纹理 我读了这个想法。我一定会调查的。