ZBrush 在性能方面非常出色,但我认为这是因为它是由具有组装专业知识的图像处理专家制作的(这也可能是由于他们在移植到 64 位方面迟了近 20 年的大量组装代码) . 它实际上开始时没有任何类型的 3D 雕刻,只是一个 2.5D“像素”画家,您可以在画布上喷涂像素,并为“像素”提供一些深度和照明。它直到 ZB 1.5 左右才开始雕刻。即便如此,当使用 Photoshop 或 Corel Painter 仅绘制平面像素的类似大小的画笔会导致帧率出现断断续续时,它仍然给人们留下了深刻的印象,您可以将这些 2.5D“像素”喷在画布背面的速度有多快。因此,他们甚至在处理任何 3D 问题之前就已经在性能上处于领先地位,并且只是在画布上喷涂像素;这往往需要一些精英的微优化魔法。
当您使用 ZB 雕刻 2000 万个多边形模型时,需要注意的一件事是它甚至不使用 GPU 光栅化。所有的光栅化都是在 CPU 中完成的。因此,它并不能从具有大量 VRAM 支持最新 GLSL/HLSL 版本的强大显卡中受益;它所需要的只是可以将彩色像素绘制到屏幕上的东西。与 MudBox 相比,这可能是它使用如此少内存的原因之一,因为它不必使用 VBO 将内存使用量增加三倍(这往往会使系统内存使用量翻倍,同时还需要数据存储在 GPU 上)。
至于你如何开始使用这些东西,IMO 让你的脚湿透的一个好方法是编写你自己的光线追踪器。我不认为 ZBrush 使用扫描线光栅化,它的成本往往会随着你拥有的多边形越多而成比例地上升,因为它们会减少在旋转模型时渲染的像素数量。这表明他们用于光栅化的任何技术在性能方面更依赖于被渲染的像素数量,而不是被渲染的图元(顶点/三角形/线/体素)的数量。光线追踪符合这些特征。此外,恕我直言,光线追踪器实际上比扫描线光栅器更容易编写,因为您不必费心处理棘手的情况,而且消除过度绘制是免费的。
一旦你得到一个操作成本与渲染像素数量成比例而不是几何数量成正比的软件,那么你就可以向它扔一大堆多边形,就像他们在演示 2000 万时所做的那样大约 17 年前,在 Siggraph 上以柔滑的帧速率进行多边形雕刻。
但是,要让光线追踪器以交互方式更新以响应不仅以交互方式雕刻而且有时还以交互方式更改其拓扑的网格数据是非常困难的。因此,他们很可能正在使用不同于光线追踪中流行的标准 BVH 或 KD-Tree 的其他数据结构,而是非常适合动态网格的数据结构,这些网格不仅变形而且拓扑结构也发生了变化。也许他们可以非常快速地对网格进行体素化和再体素化(或“像素化”和“再像素化”),并将光线直接投射到体素化表示中。考虑到他们的技术最初是如何围绕这些具有深度的 2.5D“像素”旋转的,这将开始变得有意义。
无论如何,我建议开始光线追踪,即使它只是让你的脚湿透并且让你离 ZB 的性能还很远(它仍然是如何将 3D 几何和照明转换为有吸引力的 2D 图像的一个很好的开始) . 您可以在网络上找到仅用一百行代码编写的光线追踪器的最小示例。构建光线追踪器的大部分工作通常是性能以及处理丰富多样的着色器/材质。您不一定需要为后者而烦恼,ZBrush 也不需要那么多(他们使用这些非常便宜的 matcaps 进行建模)。然后,您可能必须创新某种非常适合网格更改的数据结构,以开始与 ZB 相提并论并对其进行微调。
我同样受到 ZB 的启发,但没有直接追随他们的脚步,而是使用 GPU 光栅化器和 OpenGL。我发现很难像 ZB 那样探索在 CPU 上做所有这些事情的原因之一是因为你失去了游戏引擎、NVidia 和 AMD 已经在实时光照模型中提出的大量工业研究和革命性技术的好处等等,所有这些都受益于 GPU 端处理。有 99% 的 3D 行业,然后 ZBrush 在它自己的小角落里做着其他人没有做的事情,你需要大量的空闲时间,也许还有很多球来放弃行业的其他部分并尝试跟进ZB的脚步。
我最接近 ZB 性能的是在 90 年代后期,在 256MB RAM 的 Athlon T-Bird 1.2ghz 上以超过 30 FPS 的速度雕刻 200 万个多边形网格,这是经过 6 周的密集编程和重新审视绘图之后在一个非常简单的演示中一遍又一遍地进行演示,那是非常难得的一次,我的公司给了我这么多研发时间来探索 ZB 正在做什么。尽管如此,即使在当时,在相同的硬件上并使用一半的内存,ZB 仍以相同的帧速率处理 5 倍的几何图形。我什至无法接近,尽管我最终对 Pixologic 的程序员产生了新的尊重和钦佩。我也不得不坚持到我的公司做研究。那里的一些人认为 ZBrush 永远不会成为任何值得注意的东西,只会成为一个可爱的艺术应用程序。
当时很多人认为 ZB 处理这么多多边形的能力是不切实际的,您可以只绘制凹凸/法线/置换贴图并将所需的任何细节添加到纹理中。但这忽略了工作流程方面的事情。当您可以直接处理大量几何图形时,您可以统一应用相同的工具和工作流程来选择顶点、多边形、边缘、刷过事物等。它成为创建如此详细和复杂的模型的最直接方法,然后您可以将细节烘焙到凹凸/法线/位移贴图中,以用于其他引擎,这些引擎会在 2000 万个多边形上呕吐。如今,我认为没有人仍然质疑 ZB 的实用性。
[...] 但它并没有真正解决这些问题,或者我还没有达到这一点。
需要注意的是,没有人发表任何关于如何实现与 ZB 相媲美的性能的文章。否则,在雕刻、dynamesh、zspheres 等方面,会有许多应用程序可以与它的性能和功能相媲美,而且它不会那么特别。你肯定需要你的研发份额来提出任何接近它的东西,但我认为光线追踪是一个好的开始。在那之后,除了大量的微调之外,您可能还需要为算法和数据结构提出一些非常有趣的想法。
我可以相当有信心地说:
- 它们有一些中央数据结构来加速光栅化,可以极快地更新以响应用户对网格所做的更改(包括拓扑结构)。
- 光栅化的成本与渲染的像素数量成正比,而不是与 3D 输入的大小成正比。
- 那里有一些微优化魔法,包括直接的汇编编码(我很确定 ZB 使用汇编编码,因为他们最初要求程序员在 2000 年代招聘时同时具备汇编和 C++ 知识;我真的很想在 Pixologic 工作,但缺乏必备的组装技能)。
- 鉴于模型是如此动态,无论他们使用什么都对内存要求非常轻。上次我检查时,即使在带有纹理贴图的生产模型中加载时,它们每百万多边形使用不到 100MB。除 XSI 之外的其他竞争 3D 软件可以为相同的数据占用千兆字节。XSI 使用的内存甚至比 ZB 的 gigapoly 内核还要少,但不适合处理此类数据,速度慢得像爬行(他们可能以仅适合静态数据的方式优化它,例如将数据卸载到磁盘甚至使用一些昂贵的压缩形式)。
如果你真的有兴趣探索这个,我很想看看你能想出什么。也许我们可以交换笔记。我的大部分职业生涯都只是对弄清 ZB 正在做什么感兴趣,或者至少想出一些可以与它正在做的事情相媲美的自己的东西。对于我多年来处理的几乎所有其他事情,从光线追踪到粒子模拟到流体动力学和视频处理等等,我至少能够提出可以与竞争对手相媲美或超越性能的演示,但是不是ZBrush。ZBrush 仍然是我身边难以捉摸的刺,我只是无法弄清楚他们是如何做到如此高效地完成他们的工作的。
如果你真的想在开始走路之前爬行(我认为光线追踪是一个足够好的开始,但如果你想从更基础的开始),那么自然的进化可能是首先只关注图像处理:过滤图像,用画笔等绘画它们,以及对基本矢量图形的一些支持,如微型 Photoshop/Illustrator。然后逐步对一些基本的 3D 图元进行光栅化,例如使用 Wu 线光栅化和一些基本投影函数渲染模型的线框。然后在没有任何照明或纹理的情况下对填充的三角形进行光栅化,此时我认为你会更接近 ZBrush,专注于光线跟踪,而不是使用深度缓冲区的扫描线。但是,无论如何,做一点后者可能是一个有用的练习。然后处理渲染光照三角形,可能从直接照明和单个光源开始,仅根据法线相对于光源的角度计算亮度。然后使用海湾中心坐标处理纹理三角形,以确定要渲染的纹素。然后朝着间接照明和多个光源的方向努力。这应该是大量的功课,可以让您对光栅化的基础知识有一个相当全面的想法。
现在,一旦您开始进行光线追踪,我实际上会推荐一种效率最低的数据结构,通常是:八叉树,而不是 BVH 或 KD-Tree,主要是因为我相信八叉树可能更接近于 ZB 允许的情况。在这种情况下,您的瓶颈与使用复杂的漫反射材质和间接照明以及用于抗锯齿的亚像素样本渲染最漂亮的图像无关。它与使用简单的照明和简单的着色器以及每个像素一个样本处理大量几何图形有关,这些样本是动态变化的,包括拓扑变化。在这种情况下,八叉树似乎比 KD-tree 或 BVHs 更适合作为起点。
如今忽略基本原理的问题之一是,许多年轻的开发人员已经失去了从三角形到屏幕上的像素的联系。因此,如果您不想将这种栅格化和投影视为理所当然,那么您最初的目标是将 3D 数据投影到 2D 坐标空间中并对其进行栅格化。