1. 磐创AI首页
  2. Medium

3D计算机图形学概论

3D计算机图形(CGI)是使用存储在计算机中的几何数据的三维表示并产生(称为“渲染”)2D图像的图形。通过称为3D渲染的过程,3D模型可以可视地显示为二维图像。

渲染和渲染器:

从本质上讲,3D虚拟世界可以通过两种方式转换为2D图像(或一组2D图像):光传输模拟和光栅化。光传输模拟也可以分为几类,但我们将重点介绍光线跟踪用于光传输模拟。

1.光线跟踪-如果一些读者最近一直在关注视频游戏,他们可能已经熟悉了这个术语。光线跟踪或路径跟踪是生成3D场景的“物理精确”2D表示的技术。这项技术非常简单。物理学家对反射和折射定律(以及其他定律)的了解由来已久。他们还知道人类是如何感知颜色的–当物体散射的光到达眼睛时,物体的颜色就会被感知到。因此,要生成2D场景,我们需要做的就是将一束光线投射到场景中,看看是什么击中了眼睛(或者这个场景中的相机)!这里唯一的区别是,我们追溯光线。也就是说,光线从眼睛(或相机)通过每个像素射入场景。然后测试光线是否与场景中的每个3D对象发生碰撞。如果光线确实击中了某物,则会根据该对象的属性进行散射。重复此过程,直到达到所需的精度。渲染的准确性取决于世界上跟踪了多少光线。该技术背后的数学原理将在下面的“蒙特卡罗光线跟踪”一节中详细解释。光线跟踪一直是几乎每一部3D动画电影的支柱。第一篇关于光线跟踪的论文于1980年6月由特纳·怀特发表。但它最近已经被电子游戏所采用。原因是,虽然这项技术提供了非常精确的物理图像,但速度非常慢。图1(原始尺寸800×800)花了大约12个小时来制作,尽管我实现了多线程!虽然这个数字可以通过在GPU上使用并行计算来降低,但光线跟踪不可能实时工作,这是视频游戏中实际实现所绝对需要的。

*一个周末的光线追踪Raytracing in One Weekend

  • 下面是我用C++实现上述光线跟踪器,并在CPU上进行多线程渲染:cpp-raytracer


2.光栅化–这项技术已经支持了超过5代的视频游戏。栅格化是获取矢量图像(在笛卡尔系统中定义为点的图像)并将其转换为光栅图像(一系列像素)的任务。然而,要生成矢量图像,我们必须将三维空间中的场景转换到其他空间。更准确地说,场景被转换为“图像空间”。这项技术要快得多,因为我们不需要精确地模拟光的属性。对于上下文,图2中的茶壶场景是实时运行的。场景的照明是由Phong Shading、Gouraud Shading、Toon Shading等技术生成的。在行业中,渲染引擎被设计为支持所谓的Graphics API,这些API基本上帮助我们使用GPU的功能。主要的API是OpenGL、Vulkan、DirectX11/12和Apple的Metal。我已经在“变换和投影”一节中解释了从3D笛卡尔空间到2D图像空间的转换过程的数学原理。由于这个主题太复杂,不能在博客中详细解释,我想我最好推荐其他详细解释这个主题的资源,并举例说明。此方法通常与其他概念(如Z缓冲区/深度缓冲区)一起使用。

*光栅化:实际实施Rasterization : A Practical Implementation

*其他资源Other Resources

  • 这是我一直在使用微软的Win32API和DirectX11API开发的3D图形引擎和游戏引擎:Simple-Game-Engine


蒙特卡罗光线跟踪

我们感觉到的颜色属于电磁波的可见区域。因此,它是一个连续的谱。我们如何在计算机中表示连续谱呢?答案有很多。我要最简单的,RGB或红绿蓝。这就是我们屏幕上的像素表示不同色调的方式。但是,当我们只有三维对象时,我们如何计算这些RGB值呢?这就是蒙特卡罗积分法的用武之地。

1.蒙特卡罗方法–其背后的概念是非常直观的。比方说,我们必须找到大量数据的平均值,比如人口的平均身高。要得到每个人的身高几乎是不可能的,要计算这么多数字的平均值就更难了。因此,我们必须找到一个近似值。要做到这一点,最简单的方法是使用随机性。在大量数据中,我们随机选择数据并使用它们来求和,从而求出平均值的近似值。下面是如何通过随机选择N个数据量来计算平均值的近似值。随机选择数据也称为“抽样”。

近似值(∑(X))=(平均值Xn)/N,其中n从1到N。

为了更好地解释蒙特卡罗方法,下面是计算单位圆面积的示例代码。这是一个非常不切实际的例子,但它能完成工作。首先,我们定义了一个统一的概率分布函数(PDF)来产生随机数。然后使用这些数字对1×1正方形中的随机点进行采样。如果距离(`l‘)小于1,则落在四分之一圆以下,因此会增加命中计数器。四分之一圆的面积近似为“击球总数的分数”。增加N会提高精确度,但也会损害性能。

1.蒙特卡罗光线追踪-如何计算每个像素的颜色?利用蒙特卡罗积分和平均的概念,我们计算了每个像素的颜色近似值。我们发射射线(表示为r=O+Td,其中O是射线的原点,d是射线的方向。参数t提供光线上的点与原点的分离。)从相机的位置,到每个像素(每个像素的位置是使用我的光线跟踪器中解释的简单数学计算出来的)。然后测试该光线与所有对象的碰撞,之后提取该对象的颜色,然后根据该对象的材质进一步处理该光线。这是我的光线跟踪器中的代码片段。下面的代码是为每条光线调用的递归函数的一部分(函数名称为`ray_Color`)。

下面的代码片断调用`ray_color(…)每个像素`n次,用(i,j)表示。NS称为采样频率。`ray_Color`也有一个术语叫做`epth`。此术语用于指定射线可以散射的最大次数。

下面是在函数`cam.get_ray(浮点u,浮点v)中生成光线的方式。

光线跟踪的下一部分是散射光线的实际计算。首先,让我们以金属反射为例。这是最容易编码的,因为我们已经了解了向量是如何反射的,如下所示。

如果材质是金属的,则在对象的材质的“散射函数”中调用上述函数。

下一种类型的散射将在透明/半透明对象中观察到。但是,我们也必须在方程式中考虑反射比。反射率也随角度变化。这可以用施利克近似近似,如下所示。

这两个函数都用于确定‘MAT_DiElectric’散射函数中的散射射线,如下所示。

最后要讨论的散射函数是MAT_DISCOVER材质的散射函数。具有漫反射属性的对象不会像金属一样完美反射。它们在表面上有缺陷,可以防止镜面反射,我们通过随机散射入射光线来模拟。

正如我们所看到的,不同的散射函数改变了物体表面的感知方式以及与环境的交互方式。可以对其他散布函数进行编码,以使对象的行为类似于体积实体(例如,雾),但是对于介绍性博客来说,它们太复杂了。

变换和投影

我还想介绍一下变换和投影的工作原理。这是因为,虽然上面的方法有效并生成了视觉上令人愉快的图像,但它不是最快的方法。出于实际目的,我们需要以某种方式将任意曲面和对象从3D笛卡尔空间投影到2D空间。我们如何取一个点,比方说P(x,y,z),并将其转换为某个点P‘(x’,y‘,0){z在这里是0,因为我们必须将所有点投影到表示视口的平面}?为此,我们使用变换,准确地说,使用投影变换。

本质上,变换是乘以点阵{[x,y,z,w]}以修改它的矩阵。这些修改可能包括平移、旋转和缩放。使用这些变换,我们必须从所谓的“世界空间”到所谓的“图像空间”。图像空间如图10所示。用于正交投影和透视投影的矩阵如下所示。

通过将这些投影矩阵中的任何一个与每个顶点相乘,我们得到图像空间坐标,这些坐标被馈送到渲染管道的睡觉。图2中的犹他州茶壶已使用透视投影进行渲染。顶点着色器代码如下所示。

我不会在这段代码中涉及太多细节,因为它需要我完整地解释呈现管道。如果我们看到‘vsmain`,我们可以了解每个顶点是如何处理的。首先,将顶点从它自己的局部空间{也称为框架},也称为对象空间,带到全局世界空间。然后,将顶点从世界空间带到一个称为“视图空间”的辅助空间。视图空间或摄影机空间是相对于摄影机的帧。这意味着世界发生了变化,相机位于新空间的原点。这样,所有对象都是从这个角度渲染的。最后,顶点被投影到由摄影机在其属性中定义的锥体的近平面上。显然,这只是场景如何实时渲染的概述。GPU有专门的系统用于快速矩阵乘法,因此这种方法可以完美地工作。然而,人们也必须考虑到,这只是故事的一半。这会提供快速图像,但没有照明。要生成照明场景,必须实施着色技术,作为近似真实照明的快速技巧。一个很好的模型是Phong着色,如下所示。Phong模型的实际实现可以在GitHub存储库“Simple-Game-Engine”中看到,链接如下[图12]。

要很好地介绍所有的算法和方法,可以参考Eric Haines等人的“实时渲染,第四版”。有关着色模型的快速介绍,可以参考第5章“着色基础知识”和第9章“基于物理的着色”。

这一领域的重要意义

计算机图形学的世界是一个有趣的世界。大多数人都不知道,计算机图形学的研究已经成为许多其他领域的支柱,如计算机视觉、机器人、增强和虚拟现实。它还给我们带来了许多电子游戏和大片(比如“阿凡达”)。它在医学影像、汽车工业等领域也得到了广泛的应用。飞行模拟器用于在极端条件下培训飞行员,而手术模拟器用于培训外科新手,而不会危及患者。

我希望这个博客能帮助人们,特别是学生,对计算机生成的图形有一些了解。上面解释的概念很容易入门,也说明了数学和物理的重要性。

目录学

·“光线追踪:一个周末”、“光线追踪:下一周”,以及彼得·雪莉著的“光线追踪:你生活中的睡觉”。Raytracing : In One Weekend Raytracing : The Next Week Raytracing : The Rest of Your Life

·ScratchaPixel.comScratchapixel.com

·“实时渲染,第四版”,埃里克·海恩斯(Eric Haines)等人著。

·杰森·津克(Jason Zink)、马特·佩蒂内奥(Matt Pettineo)和杰克·霍克斯利(Jack Hoxley)的“Direct3D 11的实用渲染与计算”

·GitHub存储库:

1.C++中的光线跟踪器Raytracer in C++

2.使用DirectX11的游戏引擎Game Engine using DirectX11

原创文章,作者:fendouai,如若转载,请注明出处:https://panchuang.net/2021/07/17/3d%e8%ae%a1%e7%ae%97%e6%9c%ba%e5%9b%be%e5%bd%a2%e5%ad%a6%e6%a6%82%e8%ae%ba/

联系我们

400-800-8888

在线咨询:点击这里给我发消息

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息