大家好。之前我的文章是 和 游戏开发中的反应式编程:Unity 的细节 。 在 Unity 上开发游戏:检查组织架构的方法 今天我想谈谈Unity中的渲染和着色器这样的话题。着色器(简单来说)是视频卡的指令,告诉它们如何渲染和变换游戏中的对象。所以,欢迎来到俱乐部,伙计。 警告!这篇文章有一公里长,所以我分成两部分! Unity 中的渲染是如何工作的? 在当前版本的 中,我们拥有三种不同的渲染管道 - 内置、HDRP 和 URP。在处理渲染之前,我们需要了解Unity为我们提供的渲染管道的概念。 Unity 每个渲染管线执行一些步骤,执行更重要的操作并形成完整的渲染流程。当我们将模型(例如 .fbx)加载到舞台上时,在它到达我们的显示器之前,它会走了很长一段路,就像从华盛顿在不同的道路上行驶到洛杉矶一样。 每个渲染管道都有我们将使用的属性。材质属性、光源、纹理以及着色器内部的所有功能都会影响屏幕上对象的外观和优化。 那么,这个过程是如何发生的呢?为此,我们需要讨论渲染管道的基本架构。 Unity 将一切分为四个阶段:应用程序功能、几何处理、光栅化和像素处理。 应用功能 函数的处理从 CPU 开始并在我们的场景中进行。这可以包括: 物理处理和碰撞误算 纹理动画 键盘和鼠标输入 我们的脚本 这是我们的应用程序读取存储在内存中的数据以进一步生成我们的图元(三角形、顶点等)的地方。在应用程序阶段结束时,所有这些都被发送到几何处理阶段,以使用矩阵变换进行顶点变换。 几何处理 当计算机通过 CPU 在屏幕上看到的图像时,这分两个阶段完成: 从 GPU 请求我们 当渲染状态设置完毕,并且从几何处理到像素处理的步骤已经通过 当对象呈现在屏幕上时 几何处理阶段发生在 GPU 上,负责处理 我们对象的顶点。该阶段分为四个子过程:顶点着色、投影、裁剪、显示在屏幕上。 当我们的图元在第一个应用阶段成功加载和组装后,它们将被发送到顶点着色阶段。它有两个任务: 计算对象中顶点的位置 将位置转换为其他空间坐标(例如,从本地坐标到世界坐标),以便可以在屏幕上渲染它们 此外,在此步骤中,我们还可以选择下一步绘制图形所需的属性。其中包括法线、切线、UV 坐标和其他参数。 投影和剪切作为附加步骤进行,并取决于场景中的相机设置。请注意,整个渲染过程是相对于相机视锥体完成的。 投影将负责透视或正交映射,而裁剪允许我们修剪相机平截头体之外的多余几何体。 光栅化和像素处理 是光栅化。它包括在投影中查找与屏幕上的 2D 坐标相对应的像素。查找屏幕对象占据的所有像素的过程称为光栅化。这个过程可以被认为是场景中的对象和屏幕上的像素之间的同步步骤。 渲染工作的下一阶段 对屏幕上的每个对象执行以下步骤: Triangle Setup 负责生成我们对象的数据并传输它以进行遍历。 三角形遍历枚举属于多边形组的所有像素;在这种情况下,这组像素称为片段。 当我们收集了所有数据并准备好在屏幕上显示像素时,就进行了最后一步。此时,片段着色器启动,它负责每个像素的可见性。它负责在屏幕上渲染每个像素的颜色。 前向和延迟着色 众所周知,Unity 具有三种类型的渲染管线:Built-In、URP 和 HDRP。一方面,我们有内置(满足所有 Unity 标准的最古老的渲染类型)。相反,我们有更现代、更优化、更灵活的 HDRP 和 URP(称为 Scriptable RP)。 每个渲染管道都有其图形处理路径,这些路径对应于从加载几何图形到将其渲染到屏幕上所需的一组操作。这使我们能够以图形方式处理照明场景(例如,具有定向光和风景的场景)。 渲染路径的示例包括正向路径、延迟路径以及传统延迟和传统顶点光照。每个都支持某些功能和限制,并具有其性能。 在Unity中,前向路径是渲染的默认路径。这是因为支持它的显卡数量最多。但前进的道路在照明和其他功能方面有其局限性。 请注意,URP 仅支持正向路径,而 HDRP 有更多选择,可以组合正向和延迟路径。 为了更好地理解这个概念,我们应该考虑一个例子,其中有一个物体和一个定向光。这些对象如何交互将决定我们的渲染路径(光照模型)。 此外,结果还会受到以下因素的影响: 材质特性 照明光源的特点 基本光照模型对应于 3 个不同属性的总和:环境颜色、漫反射和镜面反射。 光照计算在着色器中完成。它可以针对每个顶点或片段来完成。当光照按顶点计算时,称为逐顶点光照,并在顶点着色器阶段完成。同样,如果按片段计算光照,则称为逐片段或逐像素着色器,并在片段(像素)着色器阶段完成。 顶点光照比像素光照快得多,但您必须考虑到您的模型必须具有许多多边形才能获得漂亮的结果。 Unity 中的矩阵 那么,让我们回到渲染阶段,更准确地说,回到处理顶点的阶段。矩阵用于它们的变换。矩阵是遵循某些算术规则的数字元素列表,通常在计算机图形学中使用。 在 Unity 中,矩阵表示空间变换。其中,我们可以发现: UNITY_MATRIX_MVP UNITY_MATRIX_MV UNITY_MATRIX_V UNITY_MATRIX_P UNITY_MATRIX_VP UNITY_MATRIX_T_MV UNITY_MATRIX_IT_MV unity_ObjectToWorld unity_WorldToObject 它们都对应于四乘四 (4x4) 矩阵。每个矩阵都有四行四列数值。矩阵的示例可以是以下选项: 正如之前所说 - 我们的对象有两个节点(在某些图形编辑器中,它们被称为变换和形状),并且两者都负责我们的顶点在对象空间中的位置。对象空间定义节点相对于对象中心的位置。 每次我们更改对象顶点的位置、旋转或比例时,我们都会将每个顶点乘以模型矩阵(对于 Unity - UNITY_MATRIX_M)。 为了将坐标从一个空间转移到另一个空间并在其中工作,我们将不断使用不同的矩阵。 多边形对象的属性 继续使用多边形对象的主题,我可以说在 3D 图形世界中,每个对象都是由多边形网格组成的。我们场景中的对象具有属性;每个总是包含顶点、切线、法线、UV 坐标和颜色。所有这些一起形成一个网格。这都是 。 由着色器管理的 通过着色器,我们可以访问和修改每个参数。在处理这些参数时,我们通常会使用向量 (float4)。接下来,让我们分析一下对象的每个参数。 顶点 对象的顶点对应于定义 2D 或 3D 空间中的表面积的一组点。在 3D 编辑器中,顶点通常表示为网格和对象之间的交点。 通常,顶点由 2 个点来表征: 它们是转换组件的子组件 它们根据局部空间中共同对象的中心有一定的位置 这意味着每个顶点都有其负责其大小、旋转和位置的变换组件,以及指示这些顶点相对于对象中心的位置的属性。 法线 法线本质上可以帮助我们确定对象切片的面所在的位置。法线对应于多边形表面上的垂直向量,用于确定面或顶点的方向或方位。 切线 查阅Unity文档,我们得到如下描述: 切线是 。 Unity 中的切线表示为 Vector4,其中 x、y、z 分量定义矢量,w 用于在需要时翻转副法线 - Unity 手册 沿着水平 (U) 纹理方向跟随网格表面的单位长度向量 我刚刚读到了什么?简单来说,每个几何形状的切线都遵循 UV 中的 U 坐标。 紫外坐标 很多人都看过 的皮肤,也许,像我一样,甚至尝试画一些自己的东西。而UV坐标正好与此相关。我们可以使用它们在 3D 对象上放置 2D 纹理。 《侠盗猎车手:罪恶都市》 这些坐标充当参考点,控制纹理贴图中的哪些纹理像素对应于网格中的每个顶点。 UV 坐标的面积等于 0.0(浮点)和 1.0(浮点)之间的范围,其中“0”代表起点,“1”代表终点。 顶点颜色 除了位置、旋转和大小之外,顶点还有颜色。当我们从 3D 软件导出对象时,它会为需要受光照影响或复制另一种颜色的对象分配一种颜色。 默认顶点颜色为白色 (1,1,1,1,1,1),颜色以 RGBA 编码。例如,借助顶点颜色,您可以使用纹理混合,如上图所示。 小结论 第 1 部分到此结束。在第二部分中,我将讨论: 什么是着色器 着色器语言 Unity 中的基本着色器类型 着色器结构 着色实验室 混合 Z 缓冲区(深度缓冲区) 剔除 CG/HLSL 着色器图 如果您有任何疑问,请在评论中留下!