体素地形引擎如何制造?


53

几天前,我发现了一种称为体素地形的东西,我认为它们非常酷。但是我什么都不知道。您是在建模软件中对其建模还是使用高度图之类的东西?我在维基百科上读到,体素就像3d像素或体积像素。

制作体素地形后,如何获取这些体素并使它们可 破坏/可挖掘


我将基于以下因素选择最佳答案:

  1. 代码和算法。最好基于C#
  2. 解释。我是算法的初学者,但是我对面向对象的编程非常熟悉
  3. 逐步演示。不仅是概念,而且是方向。
  4. 图表/插图。不,不是其他引擎的屏幕截图。


我知道这是一个复杂的话题。但是,谢谢您的帮助!

不,我不是要克隆我的世界。


编辑

感谢大家的大力帮助(尤其是Nick Wiggill)!就是我设法做到的(正在进行中)。


[团结]和C?那……毫无意义。
马丁·索伊卡


8
如此大胆的要求使您对社区充满信心。我的意思是,针对具有良好FPS的当今硬件的完整动态体素地形的完整论文,应该很容易,对吧?好吧,这个主题是如此广泛和困难,我怀疑您会看到一个通用的解决方案,即使那样,它对于您的情况也可能完全没有用。但是谁知道呢,这取决于您的榜样。您想要Crysis 2体素地形还是Delta Force地形?也许您正在制作Minecraft副本,或者只需要模拟沙子来进行挖掘游戏?请定义一个范围。
2011年

2
查看此中间件:forum.unity3d.com/threads/…。特别是演示
Tetrad

1
GPU Gems 3有一章关于体素地形:http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html
Tamschi,2011年

Answers:


58

生成体素地形

(a)一种常见的方法是使用Perlin噪声生成高度图。高度图基本上是一张单色图像,通过其像素的暗或亮表示不同的高度。

在此处输入图片说明

您将查看此高度图中的各个像素,以根据高度图图像中该像素的亮度,在不同(x,y)位置创建高达不同高度(z轴)的体素“堆栈”。由于Perlin噪点图像是平滑的(没有锐利的边缘相对于黑暗),因此您将获得平滑滚动的地形。

(b)您可以通过使用不同的多面体创建景观来逐步构建它。创建一个多面体矢量形状,该形状近似于所需的体素形状。使用任何3D多面体点方法(最常见的是凸面壳),检查世界网格中哪些点落在该多面体体积之内。例如,在空间中定义金字塔。在根据该金字塔体量检查了世界空间局部区域中的每个点之后,您将知道其中包含哪些点,并且可以将这些单元格设置为“当前”,这意味着它们成为体素而不是空白空间。现在,您的空间中有一个体素金字塔。您可以通过这种方式继续添加各种形状,直到形成地形。

(c)(与b完全相同)编写建模工具。Voxatron展示了外观。这只是在替代世界(编辑器)中创建体素表单,然后将它们导入您的实际运行时游戏世界中。我相信Voxlap拥有第一个开源的体素开源编辑器。您可以放置​​单个体素,也可以使用形状/体积不同的体素“画笔”将体素吸引到您的世界中。


构造自己的基于体素的游戏所需的内容

我之所以包括这一部分,是因为体素之路并非易事,至少目前不是这样。最近,大型公司再次对体素引擎进行大量研究,以进行渲染和物理应用。

简单性可能是个问题,因为用原始体素动态构建世界是构建世界的一种程序方法,而这并不是天生的简单。非常抱歉,这里将有一些技术术语。编写体素引擎是一项非常严肃的工作,需要跨多个游戏引擎开发领域的知识,尤其是在空间概念方面,这意味着要在一定程度上理解3D向量数学,矩阵和基本演算。

话虽如此,您的“体素地形的生成”需要一个可以在其中工作的环境,因为体素引擎并不完全普及。让我们对体素引擎如何工作进行基本描述。

体素是您世界的基本构建块。它们的位置由整数索引的3D网格(数组)定义,而不是由连续的浮点空间(如在基于矢量的3D游戏中使用)定义。这些将成为您世界的“原子”。它们可能比《我的世界》这样的游戏高3英尺,或者它们可能比虚拟角色的眼睛实际看到的要小,除非大量聚集在一起-有点像分子。有两种:

  • 基于立方网格的体素(示例)-是一种较新的种类,为简单起见,可与现代图形技术结合使用。用于MineCrat和Dungeon Keeper等游戏。
  • 点体素(exampleexample)-原始体素。每个空间都是一个单独的,可碰撞的点,尽管它可能被球形的边界体积包围。它们比较简单,因此您可以在自己的世界中拥有更多它们,因此可以使它们更小,这通常是有利的。使用它们的两个游戏是科曼奇(Comanche)和1990年代重制的《午夜之王》。

无论哪种方式,操作世界中体素的方法都大致相同,如下所示。

要在您的世界中构造和移动对象,您将需要上述数学工具。例如,创建墙:使用向量在3D空间中构造一个具有适当尺寸的盒子。使用矩阵数学将框转换为3D世界中所需的旋转和位置(在连续向量空间中)。对于体素引擎,额外的步骤是现在使用3D多面体点算法来确定哪些体素落在该旋转空间内。

本质上,这就是构造世界上大多数对象的方式。除此之外,您可以编写自己的工具,以用Maya或3DS Max这样的方式“建模”角色。但是,由于要进行建模,因此您要使用体素而不是点,边和面来进行角色设计,因此方法将大不相同。如果您决定在世界中旋转这些对象,则需要类似地使用矩阵转换。

可破坏地形很简单,要么根据您选择的某种方法一次删除一个体素,要么对大量体素使用CSG(本构几何)操作,以根据某个预定义的体积将其删除;例如,如果将激光束发射穿过岩石,则可以使用圆柱体体积减去在此处穿过岩石发射的体素。CSG是一个相对简单的过程,使用形成您的体素世界的3D空间栅格,并对照另一个栅格(在此情况下为激光束)检查基本栅格(在这种情况下为岩石)的一部分中的每个单元格

为了使物质“流动”(如Vigil在他对沙子的评论中所暗示的那样),您将需要研究流体动力学和细胞自动机。矮人要塞作者塔恩·亚当斯(Tarn Adams)的作者在本质上也是体素的世界中使用了这些元素(尽管在这种情况下体素要大得多,与Dungeon Keeper相当,原理仍然相同)。这些是最前沿的主题,而不是所定义的体素引擎的必要条件,因此我将其保留为您自己研究的“存根”。

最后,CSG和流体动力学使我感到最优化。当前正在开发的体素引擎几乎仅使用稀疏体素八叉树(SVO),这是一种将体素空间细分为不同分辨率的方法,如该视频中展示的即将推出的Atomontage引擎所示。使用八叉树/ SVO比优化选择更为必要,因为处理一个庞大,统一的网格会涉及处理开销。八叉树本质上是一棵树(有向无环图),其中每个节点都有8个或0个子节点,具体取决于它表示的空间是否包含任何物理卷。八叉树如何细分空间以形成体素的图在此处

我知道的最好的开源体素实现是Ken Silverman的Voxlap Engine,该引擎用于Voxelstein3D。它用C ++编写,并实现了用于地形变形的CSG操作。


社区Wiki更改是永久性的,无法撤消。您将需要删除并重新创建您的答案(当然会牺牲您现有的选票)
杰西·多尔西

meta.stackexchange.com/questions/2974/…声称版主可以删除它。不过,不知道情况是否已改变。感谢您对这两种方式的研究。
工程师

1
去图,下次要小心。
杰西·多尔西

2
前者是离散空间,实体只能直接位于单元上。就像放在棋盘上的棋子一样,它们不能位于“单元”之间或边界重叠处。在大多数物理引擎中都可以找到连续的空间,即它基于浮点数,因此是连续的而不是量化的。就像在现实生活中一样,您的实体可以坐在您选择的空间中的任意位置。
工程师

1
纹理是隐式的。真实体素,无论是否基于网格,均具有纯色。前面提到的方法只是创建了更逼真的细节,并启用了组合网格方法(google Unity VoxelForm)。体素越精细,生成的纹理细节越精细。示例:将河床建模为岩石(灰色)。通过将这些体素设置为具有material =“ sand”,将距离表面x距离内的每个像素转换为沙;然后可以将它们渲染为沙色。此外,这也可能影响它们的物理交互性,因此沙子可能会被水移动或挖走。
工程师

33

生成有趣的体素地形的最佳方法是使用Perlin噪声密度贴图。与其使用定义3D世界高度的2D Perlin噪声图,不如使用3D Perlin噪声图。对地图加权,使靠近底部的值更可能是实心的,而靠近顶部的值肯定是空气。这不仅可以使您达到世界的高度,而且还可以进行悬垂和塌陷,类似于Minecraft地形,如该地形切片的侧视图所示:

悬垂的世界

在这里,您可以测试浮岛,或使用分形噪声添加洞穴系统:

洞穴系统的世界

上面的图片和洞穴系统的想法来自这个优秀的博客。您可以在此处了解有关Perlin噪声的全部知识,并且有一些示例代码可以帮助您从这里开始。


4

这里的其他答案非常好,但是我采用了稍微不同的方法。

我在建模工具(3DSMAX)中生成一个环境,并从中构建一个稀疏的八叉树。每个立方非空叶节点都是一个体素。在渲染时,我使用光线投射(在HLSL中实现)来查找哪个体素占据哪个像素,并将该像素设置为存储在节点中的颜色,该颜色是我在生成树时通过平均源模型中的纹理值计算得出的。

这给您带来了很多好处-免费的碰撞检测,可变的LOD,视图空间剔除等-并且除了raycaster之外-它易于实现。

不幸的是,几乎不可能从电话中发布示例代码。


+1替代。虽然并非没有可能以合理的性能实现,但缺点却远远超过了优点。体素射线追踪给GPU带来了巨大的消耗。当这些相同的GPU周期可能会施加许多令人印象深刻的屏幕空间效果时,为此所需的算术和条件非常昂贵。SSAO。最大的问题是,在光能传递中,光线投射看起来具有多次反弹的最佳效果-不适用于由数百万或数十亿体素组成的场景,并且每个光线片段都需要花费大量精力才能反弹和合成。
工程师

...这就是为什么我在回答(VoxLap)时仅提及鳞片射线投射的原因-即使很难很好地实现。如果您可以使用垂直扫描线方法,则成本将比每像素光线跟踪小一个数量级,因为您已将渲染过程的尺寸从3D减少到了2D。我仍然坚持使用这种方法,尽管它确实排除了传统RTRT可能使用的复杂照明解决方案。
工程师
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.