一、渲染管线概述
渲染管线也叫渲染流水线,它是计算机图形学中用于将三维场景转换为最终屏幕所见图像的过程,由一系列的阶段和操作组成,每个阶段都负责执行特定的任务,逐步处理输入的集合数据和纹理信息,最终生成可视化图像的过程。
简单来说,渲染管线就是将数据分阶段的变为屏幕图像的过程。
- 渲染管线的数据:指的是Unity场景上各种相关的数据,比如顶点数据、纹理数据、光照数据等等。
- 渲染管线的阶段:渲染管线分为3个阶段:应用阶段 -> 几何阶段 -> 光栅化阶段。每个阶段都会对数据进行处理,最终目的就是在屏幕上让我们看见最终的图像。
二、渲染阶段——应用阶段
1、CPU和GPU
-
CPU:中央处理器,负责算数运算、逻辑操作、数据传输等通用计算任务,同时还管理和调度计算机的资源。
-
GPU:图形处理器,是专门用于图形和并行计算的处理器。
-
显卡:搭载 GPU 的硬件设备,显卡包含一个或多个GPU芯片,还包含显存(用于存储图像数据)、显示接口、视频解码器等等。
简单来说,CPU 主要处理操作系统管理、程序执行、通用计算等等,而 GPU 主要处理图形渲染、图像处理等等。
2、应用阶段做了什么
应用阶段中大部分的内容都和渲染无关,如游戏逻辑处理、动画更新、物理模拟、场景管理等等,该阶段由 CPU 主导,主要负责的就是数据,将渲染需要用到的数据传递给 GPU 用于后续的两个阶段的处理,数据包括顶点、法线、切线、纹理坐标、变换矩阵、材质属性等等。
当应用阶段完成后,后面的几何阶段以及光栅化阶段将开始处理和图形渲染相关的数据和操作。

应用阶段主要有这三个小阶段:
- 把数据加载到显存中。(硬盘 -> 系统内存RAM -> 显存)
- 设置渲染状态。(着色器、光源属性、材质等)
- 调用 DrawCall。(让 GPU 进行渲染)
3、应用阶段为渲染准备了什么
- 把不可见的物体数据剔除。
- 准备好模型相关数据(顶点、法线、切线、贴图、着色器等等)。
- 将数据加载到显存中。
- 设置渲染状态(设置网格需要使用的着色器、材质、光源属性等等)。
- 调用 DrawCall(CPU 通知 GPU 使用相关的数据和渲染状态进行渲染)。
应用是CPU主导的阶段,它为渲染完成的最主要的工作就是提供后续的渲染数据,这个阶段我们主要就是按照 Unity 的规则进行游戏开发即可,然后需要注意的就是关于 DrawCall 的优化。
4、DrawCall
一次 DrawCall 其实就是 CPU 命令 GPU 进行渲染的命令。而 DrawCall 会影响我们游戏的性能。
每次调用 DrawCall 之前,CPU 需要向 GPU 发送很多内容,包括数据、状态、命令等等。如果 DrawCall 过多,就会导致 CPU 把大量的时间花在提交 DrawCall 上,造成 CPU 过载,让玩家感受到卡顿。
使用批处理可以有效的减少 DrawCall,从而提升性能:
- 合并网格(比如将静态物体合并网格)。
- 共用材质(在不同网格之间共用一种材质)。
- 合并图集(2D 游戏和 UI 中,可以将多张图片合并为一张大图)。
三、渲染阶段——几何阶段
1、图元
在渲染管线中,图元是指几何数据的基本单元,它是构成几何体的最小可绘制的单元。图元可以是点、线、三角形,在几何阶段,顶点数据会被组合为图元,这些图元将在后续的光栅化阶段转换为像素,最终呈现在屏幕上。
2、几何阶段做了什么
几何阶段是 GPU 主导的阶段,因此我们无法拥有绝对的控制权,但是 GPU 为我们开放了部分控制权。它完成的最主要的工作就是根据应用阶段输入的数据信息,进行顶点处理,坐标转换,裁剪画面外图元等等。

几何阶段又分为了这几个小阶段:
- 顶点着色器:处理来自应用阶段的顶点相关数据,输入进来的每一个顶点都会调用一次顶点着色器中的逻辑。顶点着色器需要完成的工作主要有:坐标变换、顶点属性处理、顶点插值等等。对于我们来说顶点着色器是完全可编程的。
- 曲面细分着色器、几何着色器:它们是可选的着色器,曲面细分着色器用于细分图元;几何着色器用于执行逐图元的着色操作,或者用于产生更多的图元。这两个都需要硬件和驱动程序的支持才能使用,因此学习过程中不做详细讲解。
- 裁剪:裁剪阶段会自动的将不在视野内和部分在视野内的图元(点、线、三角形)进行裁剪,我们可以进行一些配置,但是一般我们不需要进行任何处理,渲染管线会自动帮助我们进行处理。
- 屏幕映射:将输入的三维坐标系下的图元坐标转换到屏幕坐标系中。
3、几何阶段为渲染准备了什么
它为渲染完成的最主要的工作就是对顶点进行处理,进行坐标转换,裁剪画面外的图元。将模型的顶点从其本地坐标转换到最终的屏幕坐标中。
在几何阶段中,我们主要通过自定义顶点着色器为我们带来一些不同的画面表现效果,如水波纹、布料等等。
四、渲染阶段——光栅化阶段
1、像素
像素是计算机图形学中的基本概念,它是组成图像的最小可控单位,具有位置和属性,用于表示图像中的颜色和其他信息。它是二位图像中的一个点,每个像素都占据屏幕上的一个固定位置。
比如我们常见的显示器分辨率为:1920 x 1080,就表示宽度为1920个像素,高度为1080个像素。
2、片元
在渲染管线中,片元是指在光栅化阶段生成的像素或像素片段,是渲染管线中进行像素级别操作和计算的基本单位。每个片元代表了屏幕上的一个像素,并且具有位置信息和与之相关的属性,如颜色、深度值、法线等等。
可以简单理解为,片元包含像素,但不仅仅是像素,还包括了像素的一些额外信息。
3、光栅化阶段做了什么
光栅化阶段同样由 GPU 主导,我们无法拥有绝对的控制权,但 GPU 为我们开放了部分控制权。它完成的最主要的工作是根据几何阶段输入的信息计算每个图元覆盖哪些像素,以及为这些像素计算他们的颜色。

光栅化阶段又分为了这几个小阶段:
-
三角形设置:几何阶段输入的主要是三角形网格的顶点信息,即三角形网格每条边的两个端点信息。如果要得到整个三角形网格对像素的覆盖情况,就必须计算每条边上的像素坐标。为了能计算三角形边界像素的坐标信息, 我们必须得到三角形边界的表示方式。 这样一个计算三角形网格的表示数据的过程就是三角形设置。
-
三角形遍历:根据三角形设置中计算出的三角形网格数据,检查每个像素是否被一个三角形网格所覆盖,如果覆盖的话,就会生成一个片元(包含屏幕坐标、深度、法线等等信息)。这样一个找到哪些像素被三角网格覆盖的过程就是三角形遍历,也叫扫描变换。

-
片元着色器:主要任务是根据三角形遍历生成的片元序列中的每个片元的着色计算和属性处理。片元着色器需要完成的工作主要有:光照计算、纹理映射、材质属性处理、阴影计算等等。对于我们来说片元着色器是完全可编程的。
-
逐片元操作:也叫输出合并阶段,它主要对片元着色器输出数据进行各种处理和计算。逐片元操作主要完成的工作主要有:决定每个片元的可见性,比如深度测试、模板测试;如果通过了所有测试,需要把片元的颜色值和已经存储在颜色缓冲区的颜色进行混合。(关于深度测试和混合,在 ShaderLab 语法中的渲染状态章节会提及)

4、光栅化阶段为渲染准备了什么
它为渲染完成的最主要的工作就是对片元进行最终处理,确定片元(像素)最终是否渲染到屏幕上,确定片元最终渲染的颜色效果。
在光栅化阶段中,我们主要在片元着色器中进行一些处理就可以带来不同的表现效果,如逼真的水面效果、火焰、黑白、模糊等等效果。
五、Shader初步认识
1、Shader 是什么
Shader 的中文是着色器,是一种用于描述如何渲染图形和计算图形外观的程序,主要用于控制图形的颜色、光照、纹理和其他视觉效果。着色器通常由着色器语言编写,这些着色器语言提供了指令和语法,用于编写描述光照、纹理映射、阴影、反射等图形外观的代码。
可以简单理解为:Shader就是着色器,是用于编写图形表现效果的程序代码。Shader 开发的本质就是通过对渲染管线中的数据进行自定义处理来决定最终的渲染效果。
2、Shader 与渲染管线的关系
Shader和渲染管线的关系是密不可分的,渲染管线是将数据分阶段的变为屏幕图像的过程,而 Shader 开发就是针对其中某些阶段的自定义开发,从而决定图形图像最终呈现到屏幕上的表现效果。
我们Shader开发主要针对的就是几何阶段的顶点着色器,以及光栅化阶段的片元着色器。
3、如何学习Shader开发
学习 Shader 开发,主要学习的是数学知识、语法知识、着色器开发知识等,学习了这些知识后,我们就能按照需求去处理渲染数据,最终才能在屏幕上显示出符合需求的图像效果。
- 数学相关知识:在几何阶段,我们主要处理的核心工作之一就是坐标转换,要了解坐标转换的原理,就需要学习数学相关的知识,比如:向量、线性代数等。在顶点着色器中,我们需要利用这些知识完成坐标转换等相关的工作。
- 语法相关知识:Shader 要自定义处理数据,就需要学习着色器开发的语言,比如 Unity 中,我们会学习 Unity 的 ShaderLab 语法,以及着色开发的 CG 语言等。
- 着色器开发相关知识:渲染管线的本质是将数据最终呈现为屏幕图像,为了让最终图像效果更好,更符合需求,我们就必须学习一些效果处理的计算规范,如:光照效果的颜色如何计算得到,纹理颜色应该如何从图片中获取,透明、阴影效果应该如何计算处理等。
六、一些必备概念
1、计算机图形程序接口
计算机图形程序接口(Graphics API)是一套可编程的开放标准,不管做 2D 还是 3D 游戏都需要这部分的底层API支持。它本质上是软件而不是硬件,是前辈们提前写好的调用系统硬件(GPU)绘制图形的代码。可以简单理解成是显卡厂商定义的一系列底层的进行图形操作的加速 API 接口。
由于各种游戏引擎的出现,即使没有系统学习过图形学知识,也能独立的通过游戏引擎开发游戏。但是你必须知道的是,游戏引擎的一部分本质就是对图形程序接口的封装,游戏引擎通过图形程序接口帮助我们完成了图像渲染相关的工作,我们只需要把工作重心放在游戏逻辑开发上了。
因此,计算机图形程序接口对于游戏开发来说,是非常重要的内容。
2、必须了解的图形程序接口
- OpenGL(Open Graphics Library):开放图形库,它定义了一个跨平台、跨语言的编程接口规格的专业图形程序接口,可以用于3D、2D图形渲染,是一个功能强大、调用方便的底层图形库。由于它跨平台、跨语言、出现时间早,因此它的应用极其广泛。
- OpenGL ES(OpenGL for Embedded Systems):用于嵌入式系统的开放图形库,它是 OpenGL 的子级,主要针对手机、游戏主机等嵌入式设备而设计,免授权费、跨平台、功能完善。GLES2.0、GLES3.0 指的就是OpenGL ES这套标准,他们也是Android和IOS手机上常用的图形处理标准。Unity 在移动平台进行图形渲染处理时,就包含了 OpenGL ES 方案。
- Vulkan:“下一代”开放的图形显示API,是与DX12能够匹敌的GPU API标准。它有一套最新的图形加速API接口,目标是提供更灵活和丰富的底层操作接口,以替代 OpenGL 和 OpenGL ES 接口,可以把Vulkan看做是OpenGL的升级版,目前新版本的Unity支持使用Vulkan方案。
- Directx(Direct eXtension):直接拓展,简称DX。它是由微软公司创建的多媒体编程接口。它不跨平台,只针对微软的相关产品,被广泛使用于Windows操作系统、xBox游戏主机的图形应用程序开发中。其中的 D3D 算是 DX 一部分,是对标 OpenGL 的图形程序接口
- WebGL(Web Graphics Library):网页图形库,它是针对 Web 端的 3D 绘图协议,这个标准允许把 JavaScript和 OpenGL ES 2.0 结合在一起,网页开发人员可以借助系统显卡在浏览器里流畅的展示 3D 场景和模型,可以在网页里进行3D图形开发。
- Metal:中文是金属,它是苹果公司为游戏开发者提供的图形技术,该技术能够为 3D 图像提高10倍渲染性能,但是它不支持跨平台,主要针对 IOS、macOS 苹果自家的操作系统,只有苹果手机、电脑能够使用。
3、了解图形程序接口的意义
从上面的描述中我们知道,他们主要支持的平台为
- Windows:DX、OpenGL、Vulkan
- 苹果电脑:Metal、OpenGL、Vulkan
- 安卓手机:OpenGL ES、Vulkan
- 苹果手机:OpenGL ES、Vulkan、Metal
- 网站网页:Web GL
如果不通过游戏引擎,想在这些平台上开发游戏,那么就必须要针对不同平台学习对应的图形程序接口相关的知识。你会发现 OpenGL 的在各主流平台中都占有一席之地,由于它出现早、跨平台、跨语言,所以这就是为什么在学习图形学时,OpenGL 是必学的内容。
我们现在使用游戏引擎开发游戏,在绝大多数情况下,不需要直接和图形程序接口打交道,但是 我们在Unity当中发布应用程序时,经常会看到和他们相关的一些设置,你必须要了解了他们的基本概念,才能清楚我们在设置什么。
你还需要知道的是,这些图形程序接口还有不同的版本,比如DX10、DX11、DX12,比如OpenGL ES 2.0、OpenGL ES 3.0。不同的设备、不同的操作系统他们支持的版本也是不同的。比如我们进行手机游戏开发时,我们可以去查询主流移动设备支持的图形程序接口的版本,来决定在发布时,对于图形程序接口版本的兼容选择。这样才能保证我们发布的应用程序能够支持更多的移动设备。
4、图形程序接口总结
对于Unity来说,它针对你发布的不同平台,会进行图形程序接口方案的切换,比如:
- 发布Windows应用时,使用 DX 方案
- 发布苹果电脑应用时,使用 Metal 方案
- 发布移动平台应用时,使用 OpenGL ES 或 Vulkan 方案
- 发布网页应用时,使用 Web GL 方案
我们不需要掌握对应图形程序接口方案的相关知识,也能利用 Unity 开发游戏,因为引擎已经把图形渲染的核心内容封装了。但是计算机图形学还是游戏开发程序员的必学知识,因为它可以帮助你理解渲染相关的原理,理解的更深。
5、渲染管线和图形接口程序的关系
图形接口程序(OpenGL、DX等)主要用于控制和管理渲染管线流程,通过图形接口程序的API,我们就可以配置和操作渲染管线中的某些阶段,设置输入数据、控制图形处理、应用各种渲染效果,最终实现图形渲染和呈现。图形接口程序充当了开发者和图形硬件之间的中间层,将开发者的渲染命令和设置转化为硬件能够理解和执行的指令。
简单来说:图形接口程序提供了对渲染管线的控制和管理功能,它是开发者和硬件打交道的中间层。
6、Shader 和图形接口程序的关系
Shader 是一种小型程序,用于自定义渲染数据的处理,从而决定最终的渲染效果。图形接口程序为 Shader 开发提供了各种 API,Shader 开发需要针对不同的图形接口程序使用不同的 Shader 开发语言来调用相关 API。
图形接口程序会将 Shader 程序和渲染管线的各个阶段连接起来,把数据和指令传递给硬件(GPU 等),从而实现图形渲染的最终呈现。
简单来说:Shader 属于图形接口程序的一部分。
7、不同图形接口程序对Shader开发的影响
- 使用的着色器语言不同
- OpenGL:GLSL(OpenGL Shading Language)
- DX: HLSL(High-Level Shading Language)
- Metal: MSL(Metal Shading Language)
- WebGL: GLSL ES(OpenGL ES Shading Language)
- 坐标系原点不同
- OpenGL、WebGL、Metal: 原点位于屏幕左下角
- DX:原点位于屏幕左上角(最新的 DX12 可以改原点为左下角)