渲染流水线
仅为本菜鸡自己学习记录分享,如有错误还请各位大佬指出。

渲染管线整体流程分为主要四个阶段:
应用阶段
几何阶段
光栅化阶段
逐片元操作(在一些资料中这个阶段也并入光栅化阶段)
1.应用阶段
是一般图形渲染管线概念上的第一个阶段,通过软件方式在CPU上实现,开发者能够对该阶段进行完全控制。在这一阶段中所有数据需要从硬盘(HDD)加载到系统内存(RAM)中。然后将数据加载到显卡的储存空间显存中(VRAM)。

其中又可细分为下图中几个阶段
(1)准备基本场景数据
物体数据:变换数据(位置,旋转,缩放等)网格数据(顶点位置,UV贴图等)
光源信息:光源类型(方向光,点光,聚光等),颜色,位置方向角度等
摄像机参数:位置,方向,近远裁剪平面,正交透视,视口比例尺寸等
阴影信息:是否开启,判断光源范围内是否有可投射阴影物体,阴影强度等参数
(2)加速算法,粗粒度剔除等
碰撞检测,加速算法,输入检测,动画,力反馈,纹理动画,变换仿真,几何变形
(3)设置渲染状态,准备渲染参数
渲染设置:合批方式,光源属性材质,使用哪个顶点/片元着色器等
绘制物体的顺序:材质RenderQueue,UICanvas,相对摄像机距离等等
渲染目标:FrameBuffer,RenderTexture
渲染模式:前向渲染,延迟渲染
(4)输出到显存
顶点数据:位置颜色法线纹理uv等
其他收据:MVP变换,纹理贴图,其他数据
在这些都完成之后 CPU就会调用一个渲染命令DrawCall来调用GPU

GPU和CPU之间有一个命令缓冲区,可以实现相互独立工作
提交大量很小的DrawCall会造成CPU性能瓶颈
可以使用批处理合并过程一个大的DrawCall
2.几何阶段
几何阶段主要负责大部分多边形操作和顶点操作

其中顶点着色前模型视图变换后 中间可选曲面细分着色器,几何着色器等顶点处理
(1)模型和视图变换 Model and View Transform
为了方便投影和裁剪,需要对相机和所有模型进行视点变换,模型变换是为了让模型变换到合适的渲染空间中,视图变换为了让相机位于原点,同时朝向z轴负方向。这个空间通常称为观察空间或相机空间。

(1.5)曲面细分着色器,几何着色器
在曲面细分中可以使用合适的细分算法,生成高精度网格提升细节
在几何中可以添加额外vertex 转换为新的图元
a.曲面细分着色器 Tessellation Shader
主要由三部分构成,其中Hull Shader和Domain Shader是可编程的
他的输入是多个顶点的集合,包含每个顶点属性,可以指定一个Patch包含的顶点数以及自己的属性。
作用就是将图元细分(可以是三角形 矩形等) 输出细分后的顶点

<1>Hull Shader
主要作用是来定义一些细分的参数,比如每一条线上边上如何细分
参数解析:
·Tesselation Factor:决定一个边分为几部分

equal_Spacing:几就几等分

fractional_even_spacing:最小值2向上取最小偶数,把周长分为n-2的等长部分以及两端不等长部分

fractional_odd_spacing:最小值1 向上取最近的奇数,把周长分为n-2个不等长部分以及两端不等长部分
·Inner Tessellation Factor:决定内部如何画,通过延长线做交点直到不能做为止

<2>Tessellation Primitive Generator
进行细分操作
<3>Domain Shader
细分后的空间是重心空间,Domain Shader要把他转换到我们要用的空间
b. 几何着色器 Geometry Shader
输入为图元(三角形,矩形,线等)根据图元的不同,shader中会出现对应不同数量的顶点
输出同样为图元,一个或多个,需要自己从顶点构建,顺序很重要
同时需要定义最大输出的顶点数
(2)顶点着色 Vertex Shading
着色计算的一部分在顶点着色着色器上执行,其他计算可在光栅化期间进行,顶点着色的数据计算完毕后会发送到光栅化阶段进行插值操作。
(3)投影 Projection
投影是为了将视体变换到规范立方体(CVV)中,目前主要有两种投影方式:正交投影(orthographic projection)和透视投影(perspective projection)

(4)裁剪Clipping
主要是对于部分位于内部的图元进行裁剪操作,将单位立方体之外的图元剔除掉,保留内部,产生一个新图元

(5)屏幕映射 Screen Mapping
屏幕映射主要目标就是找到在屏幕坐标系上的对应位置

3.光栅化阶段
这个阶段完成从二维顶点所处屏幕空间到屏幕上像素的转换,光栅化中不只是会处理三角形图元(含有Triangle只是因为大部分是三角形) 同样也要处理点线等其他图元,以方便后续的Pixel Processing

(1)三角形设置Triangle Setup
在这里会计算每条边上的像素坐标,得到三角形边界的表示方式,以几何阶段处理的各种着色数据的插值操作
(2)三角形遍历
会逐像素进行检查 判断该像素中心是否由三角形覆盖。每个三角形片段的属性由三个三角形顶点数据插值形成。
通过向量叉乘可以快速判断是否在三角形内,
处理边界上的点不同的API规定不同。

目前比较传统的划分方式为Standard Rasterization除此外DX11还引入了两种新遍历类型Conservative Rasterization CR。

在此图中常规方法是取黄色+绿色 在outer-CR在取绿+黄+蓝 在inner-CR只取绿
对于插值方法常用的有三种:
最近邻Nearest Neighbor,距离Distance和重心坐标coordinate system
下面浅谈一下重心坐标的解决方法:

三角形平面内任意一点都可以用三个点的坐标线性表示出来
如果都非负那么就在三角形内

重心坐标计算可以用面积来计算
但有更加方便的方法 叉乘计算

之后就可以对顶点的各个属性 如颜色,法线等进行插值
4.逐片元操作
逐片元阶段主要是为给各个像素填上正确颜色与正确的可见性,得到相应图像信息
(1)像素着色阶段
通过插值得到的着色数据计算出一种或多种颜色信息传入下一阶段。在这一阶段中有大量的技术可使用(如纹理贴图等)。
但他局限在于仅可影响单个片元,不可以将自己的任何结果发给邻居(但个人认为实际操作可以rendertex进行这样操作,有点费就是了)

(2)融合Merging
通常运行阶段的GPU子单元并非完全可编程,但可高度配置,支持多种效果。
在此阶段不仅要通过模板测试 深度测试等进行可见性测试,还要将当前储存于缓冲中的颜色与当前颜色进行合并。
其中模板测试和深度测试分别主要通过模板缓冲器和Z缓冲区实现

除此之外还有累计缓冲区,alpha通道等来过滤和捕获片段信息。
5.其他操作

在渲染流程完成之后,再对最后输出的结果进行处理,简称后处理
参考:
1.渲染流水线 - 知乎 (zhihu.com)
Unity Shader入门精要