Answers:
我正在考虑一个我的世界(Minecraft)类型的场景,在这里用体素表示一个实际上是使用多边形渲染的块的世界:
如果使用几何体着色器,将很难避免每个体素恰好具有三个面(或其他任何面)。
如果您有许多相邻的块具有相同的纹理,则可以使用纹理的平铺,以VBO方法在(退化的)条中使用更少的三角形。我的意思是,如果有一个很好的6x6的大平面草体素区域,则可以仅用2个三角形而不是64个三角形绘制整个顶部。
使用GS方法,您无法对相邻体素所遮挡的面进行琐碎的剔除,而这对于VBO方法而言也非常简单。
我没有尝试过GS方法,但是我可以说VBO方法与重复相邻图块的组合效果很好。我发现弄乱元素索引比仅仅重复顶点要慢得多。如果将世界分割成漂亮的小立方体,则通常每个顶点每个组件只能使用一个字节,甚至可以将纹理信息和法线打包(轴对齐的立方体上的一个面只有3个可能的法线),等等,到第四字节即可每个顶点4个字节,这是很好且快速的。
我为6个面中的每个面使用了单独的VBO-显然,您最多只需要绘制3个即可。这非常适合通常用于Minecraft样式体素顶部的不同纹理。因为对于每个集合,法线等都是统一的。
通过GL_REPEAT
在水平轴的地图集中使用垂直平铺的像素图,并在同一地图集中使用像素图的90度旋转版本,我发现可以在同一调用中使用相同的VBO绘制大量明显不同的块。在6x6的草地区域示例中,我将其分成12个三角形,因为我只在地图集中的一个维度上进行重复。
我主要是在集成显卡芯片和移动设备的低端工作,而GS只是我有一天可以玩的梦想。
使用实例数组的第三种选择呢?基本上,您可以通过一次绘制调用来绘制许多框(由一个简单的8顶点的多维数据集制成),并从体素数据VBO(glVertexAttribDivisor
在OpenGL中使用)确定每个实例的位置(以及其他数据)的位置(和其他数据)DX也有)。尽管应用程序代码(非着色器)应该非常相似,但是这可能比几何着色器方法要快,因为我记得几何着色器以其速度较慢而著称,尽管我仍然没有使用它们的经验(或实例化)在2.1硬件上。
但是无论如何,几何体着色器或实例化数组都应该比CPU构建的体素几何体更适合,尤其是当体素数据可能发生变化时。结合转换反馈(DX中的流输出?),您可以设置一些基于GPU的良好剔除技术。
几何着色器版本对我来说听起来要好得多。您只能动态运行vbo点和构造框(输入点,输出三角形流)。它会更快(如果您在5 eq。DX11着色器模型中使用曲面细分单元,甚至会更快),并且会极大地减少带宽,这将是一个很好的解决方案。
关于GS。将其放在顶点着色器和像素着色器之间,并修改输出的顶点(基元)流。虽然顶点着色器仅对顶点起作用,但是几何着色器对整个图元起作用。该流的输出仅到达像素着色器(并在偏离路线之前被光栅化:)),并且无法保存它。(也许通过疯狂地渲染到纹理然后解析它……但是没有真正简单的可能性)
性能说明:您应该能够访问几何着色器中的所有内容并跳过(仅传递数据)顶点着色器。但这不是最好的方法。更好(更快)的方法是在顶点着色器上进行大多数可能的转换,并尝试最小化几何着色器程序。如果需要,不要害怕用于循环(例如,用于创建盒子)。编译器将为您展开它。