Shader入门精要项目链接:
渲染流水线分为3个概念性阶段:应用阶段(Application Stage)、几何阶段(Geometry Stage)、光栅化阶段(Rasterizer Stage)。
一、应用阶段(CPU)
3个主要任务:
(1)把数据加载到显存中。
数据:场景数据,如摄像机的位置、视锥体、模型、光源、顶点位置、法线方向、顶点颜色、纹理坐标等。
数据会从硬盘(Hard Disk Drive,HDD)加载到系统内容(Random Access Memory,RAM),其中,网格和纹理等数据会从RAM加载到显卡上的存储空间一显存(Video Random Access Memory, VRAM)。因为显卡对于显存的访问速度更快,大多数显卡对于RAM没有直接的访问权利。数据加载到显存中后,RAM中一部分不再需要使用的数据会被移除。(HDD加载到RAM的过程十分耗时)
(2)设置渲染状态。
渲染状态:材质、纹理、Shader等。
这些状态定义了场景中的网格是怎么被渲染的。如:使用哪个Shader、光源属性、材质等。
(3)调用Draw Call。
在设置渲染状态后,CPU调用渲染命令(Draw Call)通知GPU进行渲染。
GPU会根据渲染状态(材质、纹理、Shader等)和顶点数据(顶点位置、顶点颜色、纹理坐标、法线方向等)进行计算,最终输出成屏幕上显示的那些漂亮的像素。这个具体过程在下一节GPU流水线解释。
GPU流水线
二、几何阶段
顶点着色器、曲面细分着色器、几何着色器、裁剪、屏幕映射
(1)顶点着色器(可编程)
对单个顶点进行操作(在一次渲染中,每一个网格顶点都会进入一次顶点着色器处理)
功能:实现顶点的空间变换、顶点着色等
必须完成的是把顶点坐标从模型空间转换到齐次裁剪空间 ( o.pos = mul(UNITY_MVP, v.position )
之后传递给Unity顶点坐标会由硬件做透视除法,得到归一化的设备坐标(NDC)
在顶点着色器我们可以通过改变顶点位置来模拟水面、布料等。
(2)曲面细分着色器(可选)
功能:细分图元
(3)几何着色器(可选)
功能:执行逐图元的着色操作,或者产生更多的图元。
(4)裁剪(可配置)
功能:将那些不在摄像机视野内的顶点裁剪掉,并剔除某些三角图元的面片
这个裁剪功能是一种优化手段,在摄像机视野范围之外的物体被裁剪掉。
(5)屏幕映射(可编程、可配置)
功能:负责把每个图元的坐标转换到屏幕坐标系中。
三、光栅化阶段
从几何阶段获取到三角网格的顶点数据(仅仅是顶点坐标变换成在屏幕坐标系下,其他都没变动)
三角形设置、三角形遍历、片元着色器、逐片元操作
(1)三角形设置、三角形遍历
三角形设置:根据三角形顶点通过插值运算得出三角形边界坐标点;
三角形遍历:检查每一个像素是否被一个三角网格所覆盖,如果被覆盖会生成一个片元(fragment),这个过程就称呼为三角形遍历(又称为扫描变换(Scan Conversion))
三角形遍历过程中,通过三角形设置得出的三角形边界坐标点来判断像素是否被覆盖,若是被覆盖会生成一个片元。
片元中保存有像素坐标、像素深度、法线方向、纹理坐标等数据。(此时还不包含像素颜色)
其中,像素坐标是通过三角形顶点坐标插值运算得出,像素颜色是根据三角形顶点颜色插值运算得出,像素深度是根据三角形顶点深度插值运算得出,其他数据同理。
(2)片元着色器(可编程)
对单个片元进行操作(在一次渲染中,每一个片元都会进入一次片元着色器)
在此阶段最关键的一步是通过片元的纹理坐标来进行纹理采样,纹理采样是指通过纹理坐标从纹理上进行采取颜色值,片元着色器可以对这个颜色值进行修改,然后输出到下一个流水操作。
(3)逐片元操作(可配置)
在DirectX中称为输出合并阶段;
2个主要任务:
①通过一系列测试(如:模板测试、深度测试等),决定每个片元的可见性。通过测试的片元才可见。
其中,模板测试是比较参考值,参考值存于模板缓冲中;而深度测试是比较片元深度和深度缓冲的深度,若通过深度测试且开启了深度写入就会将片元深度写入深度缓冲区,作为下一次判断依据。
②将通过测试的片元颜色值和已经存储在颜色缓冲中的颜色进行合并(混合),再放回到颜色缓冲区。
混合操作是在开启了混合材会进行的,在Shader中默认是不开启的,不开启混合的话就会直接使用片元颜色值覆盖屏幕上的颜色值。例如在Shader的SubShader{}里面写上 Blend SrcAlpha OneMinusSrcAlpha 一行代码就是开启了混合(与画面混合)
事实上,在片元着色器我们也会对片元颜色值进行进行合并处理,例如:和一张半透明纹理进行混合处理。