Unity 场景烘培 ——浅谈渲染管线流程的理解 (五)

提示:文章有错误的地方,还望诸位大神不吝指教!


前言

渲染管线是计算机图形中最基础最核心的部分,但大多程序对它不是很了解,当然我也是,所有花时间去了解一下。
我们有一个对知识点的认知度等级:了解,熟悉,精通,专业。在了解前…我对渲染管线认知:听说 。哈哈 !
本文结合:B站视频、CSDN文章、及Siki付费课程结合理解编写(文章内容大多是CSDN道友写的,我看了看写的太好了,干脆搬过来)
主要参考文章:
CSDN链接: Unity3D 渲染管线全流程解析
B站:链接: 什么是渲染管线
SiKi:链接: ShaderGraph入门教程

一、渲染管线流程是什么?

简单来说:把三维场景信息转换成二维图像的过程!也就是说三维场景的各种信息转换成二维的,然后映射到屏幕上,然后我们就看到了。

二、渲染管线具体流程

渲染的流程一般分为三个阶段:应用阶段、几何阶段、光栅化阶段

1.应用阶段

通俗理解:做事情前,先得到所有材料和规则。
具体理解:这个阶段由CPU执行,打包数据向GPU传递。
将模型信息(顶点坐标、顶点颜色、切线、法线)、材质、灯光、渲染顺序、变换矩阵 、FOV等信息发送DrawCall命令。
这时候产生一个DrawCall。

DrawCall为什么会影响性能?链接: Unity 性能优化之数据面板
要将游戏中的物体显示到屏幕上,就需要绘制它们?绘制之前,会先由CPU计算出它们的位置、颜色等信息,然后发送绘制指定给GPU。GPU受到CPU发过来的绘制指令,就会按照要求绘制东西在屏幕上。
Draw Call是指CPU向GPU发送绘制指令的过程,一个Draw Call就是CPU向GPU发送的一组绘制指令,可以绘制出一个或多个物体。
Draw Call太多就会是游戏卡顿,优化就是想办法降低Draw Call。
要降低Draw Call,可以使用合批技术,例如动态合批和静态合批。将多个Draw Call合批成一个批次(batch) ,再由CPU发送给GPU,这样可以提升游戏性能。

000

2.几何阶段

主要任务:把上个阶段得到的顶点坐标变换到屏幕空间,以供给光栅器阶段进行处理
大概步骤:
1.顶点着色器
流水线的第一个阶段,其可以通过编程进行控制。输入来自CPU发送的顶点信息,每个顶点都会调用一次顶点着色器。其主要工作为:坐标转换和逐顶点光照(可选,计算输出顶点的颜色值)。坐标转换是必须完成的一个任务。其把顶点坐标从模型空间转换到齐次裁剪空间。
在这里插入图片描述

2.裁剪
裁剪渲染视锥体之外的物体。
在这里插入图片描述

3.屏幕映射
通过计算将实际场景的对象映射到屏幕上

模型空间—>世界空间—>摄像机空间—>齐次裁剪—>屏幕空间
在这里插入图片描述

3.光栅化阶段

该成像了。
光栅化的主要任务是:决定渲染图元中的哪些像素应该被绘制在屏幕上,然后对其颜色进行合并混合
1.三角形遍历
三角形遍历阶段会根据上一个阶段的计算结果判断一个三角形网格覆盖了哪些像素,并使用三角网格三个顶点的顶点信息对整个覆盖区域进行插值。详细过程见下方介绍:
此阶段会遍历所有的像素点,判断其是否被三角网格所覆盖 (用3-1计算的结果) ,如果被覆盖,则在此像素点上生成一个片元。片元不是单纯的像素点,其还包含很多状态的集合,这些状态用来最终计算检测筛选每个像素点最终的颜色。(部分状态包括:屏幕坐标,深度值,从几何阶段继承来的法线,纹理等等)。
在这里插入图片描述

2.片元着色器
非常重要的可编程着色器阶段。片元着色器的输入是上一个阶段对顶点信息插值得到的结果,输出为每个片元的颜色值。这一阶段可以按需完成很多重要的渲染技术,最重要的技术之一就是纹理采样。
纹理采样
为了在片元着色器中进行纹理采样,先在顶点着色器阶段输出每个顶点对应的纹理坐标,然后经过光栅化阶段对三角形网格的三个顶点对应的纹理坐标进行插值后,就可以得到其覆盖的片元的纹理坐标了。其局限在于仅可以影响单个片元。即执行片元着色器时,不能将结果直接发给旁边的邻居。片段着色器输出颜色的具体过程如下图(图8)
在这里插入图片描述

3.逐片元操作
这是OpenGL中的说法,在DirectX中,这阶段被称为输出合并阶段(Output-Merger)。
该阶段是对每一片 片元 进行操作,主要任务有:
①决定每个片元的可见性,如深度测试、模板测试。
②如果一个片元通过了所有测试,就把这个片元的颜色值和已经存储在颜色缓冲区的颜色进行合并,混合。
该阶段是高度可配置的,我们可以设置每一步的操作细节。该阶段首先解决的是,每个 片元的可见性问题。这需要进行一系列测试,只有通过了才能和颜色缓冲区进行合并。没通过任何一 个测试,片元都会被丢弃。
在这里插入图片描述

4.模板测试
开启了模板测试,GPU就会使用读取掩码读取模板缓冲区中该片元的模板值,将该值和读取到的参考值进行比较。这个比较函数可以是开发者指定的,例如小于模板值时则舍弃该片元或者大于模板值时舍弃该片元。片元无论有没有通过模板测试都可以根据模板测试和下面的深度测试结果来修改模板缓冲区。这个修改操作也是由开发者指定的。模板测试通常用于限制渲染的区域。
5.深度测试
通过模板测试后,片元就会进行深度测试。其同样是高度可配置的。
开启后,GPU会把该片元深度值和已存在与深度缓冲区的深度值进行比较,这个比较函数也是开发者设置的。例如小于缓冲区深度值时舍弃该片元,或者大于缓冲区深度值等于时舍弃该片元。通常人们更希望显示离摄像机最近的物体,所以一般比较函数设置为当前片元深度值要小于缓冲区深度值,深度值大无法通过测试。如果片元没有通过测试,则会被丢弃掉。
与模板测试不同,只有通过之后开发者才能指定是否用该片元的深度值覆盖原有缓冲区的深度值。这是通过开启/关闭深度写入做到的。

6.合并操作
通过了所有测试后,片元就来到了合并操作。
每个像素的信息被存储在一个名为颜色缓冲区的地方,因此执行此次渲染时,颜色缓冲区中往往已经有了上次渲染之后的结果。所以需要合并的方式使其达到一种均衡状态。
对于不透明物体,开发者可以选择关闭混合操作。这样片元着色器计算得到的颜色值就会直接覆盖原来颜色缓冲区中的像素值。
对于半透明物体,需要使用混合操作来让这个物体看起来是透明的。
混合操作也是可以高度配置的。开启了混合,GPU会取出源颜色和目标颜色将两者混合。
源颜色是片元着色器得到的颜色,目标颜色是已经存在于颜色缓冲区中的颜色值。

7.提前测试
提前测试的目的主要是为了提高性能
虽然逻辑上这些测试是在片元着色器之后进行的,但对于大多数GPU来说,他们会尽可能在执行片元着色器之前进行这些测试。
尽可能早知道哪些片元会被舍弃可以提高性能,比如unity的渲染流水线中的深度测试就在片元着色器之前。这种将深度测试提前的技术被称为Early-Z技术。
但将这些测试提前其检验结果可能会与片元着色器中一些操作产生冲突。

总结

好记性不如烂笔头!

猜你喜欢

转载自blog.csdn.net/qq_37524903/article/details/134493570