是否可以构造少于24个顶点的立方体


14

我有一个像Minecraft这样的基于多维数据集的世界,我想知道是否有一种方法可以构造一个少于24个顶点的多维数据集,从而减少内存使用量。

在我看来,这是不可能的,原因有两个:法线无法正确显示,每面纹理也无法使用。

是这种情况还是我错了?也许有些新颖的DX11技术可以提供帮助?

编辑:为了明确起见,我有2个要求:我需要每个立方体面的表面法线以进行适当的照明,并且需要一种方法来解决每个立方体面的纹理数组中的不同索引


1
您是否要减少图形卡的内存使用RAM使用
doppelgreener 2012年

1
顶点数据现在存储在RAM中和GPU上,因此减少顶点将减少两者。
Telanor 2012年

Answers:


9

如果只需要按面法线,并且面的texcoords严格为0 / 0、0 / 1、1 / 0、1 / 1(或与您的布局相似),则可以构造具有8个顶点的立方体以及30(带重新启动的条带)或36(列表)索引。使用基于顶点着色器中的SV_VertexID的常量数组查找来获取法线和texcoord。

这样做意味着您甚至不需要在顶点缓冲区中包含texcoords或法线,这将为您节省更多的内存。

更进一步,您仍然可以将每个多维数据集一路转到24个顶点,但也可以使用实例化。每个多维数据集在顶点缓冲区(1x1x1)中都是固定大小的,并且具有按实例数据的缩放因子和位置(假设多维数据集不旋转,如果它们旋转,则为矩阵)。在非旋转情况下,您一次要花费24个顶点,但是每个多维数据集只需要6个浮点数即可完全指定。在旋转情况下,您要查看16个浮点数,但即使这样也可以节省很多钱(在这种情况下,您很可能在矩阵转换时遇到CPU方面的瓶颈-对于非旋转情况下,动态地构造矩阵您的顶点着色器-即使是按顶点完成的,也是如此之快,以至于您甚至不必担心它)。

对于每面纹理,只需使用纹理数组即可。当然,您需要确保数组中每个此类纹理的大小均相同,并且如果数组本身需要更改,您仍需要中断当前的批处理,否则,它将做得很好。在您的顶点定义中添加第三个texcoord,以定义要用于每个面的数组切片。

您不需要带有GS的GS,它的运行速度应比使用GS的运行速度快,因为启用了几何着色器阶段会增加额外的开销。

我的引擎中已经有基准测试代码,使用此方法可以绘制一堆多维数据集,并且可以在相对低端的GPU上轻松地检查超过300,000个多维数据集,同时仍以60fps的速度清除,而无需执行其他任何操作来优化流程。诚然,我既不进行照明也不对其进行纹理处理,但是我确实启用了alpha混合,禁用了背面剔除,并且总体而言,它与我的“不做其他任何事情来优化”部分保持平衡,因此应该为您提供一种合理的想法可以用这种方法击球。


1
我以前使用过实例化,它对于不足40k的多维数据集非常有用。但是我至少有256k多维数据集,实例化也不能很好地处理它。不过,将SV_VertexID与查找结合使用似乎很有希望。
Telanor 2012年

每个实例的缓冲区有多大?试图将它们全部塞入一个巨大的缓冲区中可能最终使您的GPU窒息。我通常将每个实例的缓冲区留在足够的空间中,以容纳64k个对象(如有必要,请分割绘制调用),使用丢弃/不覆盖模式,并直接写入映射的指针,而不是从中间数组进行复制,效果很好。
Maximus Minimus 2012年

此外-保持地图数量少是必不可少的。映射/写入一个多维数据集/取消映射40k次将比仅映射/写入40k多维数据集/取消映射慢得多。如果您正在做前者,请尝试切换到后者。
Maximus Minimus 2012年

15

我认为您可以进行的主要优化基于以下事实:并非每个多维数据集实际上都需要全部24个顶点。实际上,唯一需要24个顶点的立方体是漂浮在空中的立方体,这可能很少见。

通常,仅为与空气接触的面生成四边形。这意味着,如果两个立方体相互接触,则无需为它们接触的面生成任何顶点。

下图演示了此概念,但以2D形式显示以便于理解。在图像中,有11个被占用的块(由实心的灰色圆圈表示),通常需要4 x 11 = 44个边来表示(4个是正方形,而不是立方体)。但是,正如您所看到的,仅当边缘与一个空的正方形接触时才真正需要绘制边缘,在这种情况下,该正方形只有8个边缘。

在此处输入图片说明

如果这样一个简单的2D示例设法将44条边减少到8条边,请想象一下在大型3D世界中的收益...

这是本文中介绍的方法,尽管它针对OpenGL,但我还是建议您阅读该方法。这些概念应该相当普遍。

您可能还可以使用几何着色器在GPU上动态生成顶点,从而无需将其存储在内存中,但是我没有经验,也不知道它在大范围内的性能如何世界。


1
非常有趣的文章。我已经在进行边缘优化,这肯定会有所帮助。我将尝试几何着色器,看看是否可行。
Telanor 2012年

您是说要使用几何着色器和叉积计算法线?我正在考虑使用它,例如为平面创建一个单独的程序(我不关心纹理)。
德雷塔2012年

@dreta不仅如此,还可以只提交立方体质心作为点列表,所有顶点均由GS发出。也许将一些相邻的信息编码为点,以便着色器仅生成真正需要的面,尽管我还没有想到。
David Gouveia 2012年

如果要获得性能,请不要使用几何体着色器。他们完全搞砸了管道。如果要在GPU上生成几何图形,请使用计算着色器或openCL
Robert Fraser
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.