《UnityShader入门精要笔记》 冯乐乐著,一位女性的技术文章,公认的笔触细腻,Shader入门首选的好教材。以下是个人的学习笔记。
渲染流水线
应用阶段(CPU)
- 把数据加载到显存中。
把所有渲染所需的数据(顶点的位置信息、法线方向、顶点颜色、纹理坐标等)从硬盘(HDD)中加载到系统内存(RAM)中。然后,网格和纹理等数据又被加载到显卡上的存储空间–显存(VRAM)中。 - 设置渲染状态。设置(顶点着色器/片元着色器、光源属性、材质)等数据。
- 调用Draw Call。
CPU指挥GPU → 渲染命令(Draw Call)(命令 → 渲染的图元列表)
几何阶段:
顶点数据 → 【顶点着色器 → {曲面细分着色器} → {几何着色器} → 裁剪 → 屏幕映射】→
光栅化阶段:
屏幕映射 → 【三角形设置 → 三角形遍历 → {片元着色器}】 → 逐片元操作 → 屏幕图像
个人认为作者在书中这里表达的是逐片元操作拥有许多重要操作,可以从光栅化阶段抽离出来另成一派。
几何阶段(GPU)
- 顶点着色器 [完全可编程的]。 (顶点的空间变换、顶点着色等功能)
①只有一个个的顶点数据(0,-125)
②坐标转换 (把顶点坐标从模型空间转换到齐次裁剪空间,进行输出后再由硬件做透视除法得到NDC下的坐标)
③逐顶点光照(计算顶点颜色)
④还可以输出后续阶段所需的数据
⑤该阶段最重要的输出是渲染所需的几何信息,即渲染图元。渲染图元可以是点、线、三角面等。 - 曲面细分着色器 [可选的着色器] (用于细分图元)
- 几何着色器 [可选的着色器](执行逐图元的着色操作,或者被用于产生更多的图元)
- 裁剪 [可配置的](把看不见的顶点裁剪掉,并剔除某些三角图元的面片)
①可配置裁剪的方法(比如一个顶点一般被裁时生成两个顶点,此时可配置成生成更多个。) - 屏幕映射 [不可编程不可配置](它负责把每个图元的坐标转换到屏幕坐标系中)
①把每个图元的x和y坐标转换到(二维)屏幕坐标系(和我们的画面分辨率有很大的影响,会拉伸等等)下。
②屏幕坐标系(x,y)和暂不做处理的 z 坐标构成 窗口坐标系。这些值会一起被传递到光栅化阶段。
③差异(OpenGL 左下 原点 , DirectX 左上 原点)
光栅化阶段(GPU)
- 三角形设置 [固定函数]
计算三角网格表示数据的过程。 - 三角形遍历 [固定函数] 检查每个像素是否被一个三角网格所覆盖。(也称扫描变换)
①被覆盖的像素会生成一个片元(相当于像素,但并不等同),而片元中的状态是对3个顶点的信息进行插值得到的。)
②输出一个 片元序列 = [片元:{屏幕坐标,深度信息,顶点信息(法线,纹理坐标)}] - 片元着色器 [完全可编程](用于实现逐片元的着色操作)
①前面的光栅化阶段实际上并不会影响屏幕上每个像素的颜色值(没赋值),而是产生一系列的数据信息(表述一个三角网格是怎样覆盖每个像素的信息 = 片元序列)
②可完成很多重要的渲染技术(纹理采样等等)
③局限:每个片元数据独立计算,不共享 - 逐片元操作 [可配置](负责执行很多重要的操作:修改颜色、深度缓冲、进行混合等)对片元输出合并。
①决定每个片元的可见性。(这涉及了很多测试工作,例如深度测试,模板测试等。)
②如果一个片元通过了所有的测试,就需要把这个片元的颜色值和已经存储在颜色缓冲区中的颜色进行合并,或者说是混合。
个人见解
个人认为:比喻描述 绝对是 理解 未知事物的 最优手法。
我将 渲染流程 比作 画画 的创作过程。
那么:
应用阶段 → 大脑
①准备场景数据(摄像机的位置及视锥体、模型、使用了哪些光源等)
→ 画画准备工作(什么样的画布,想画一个什么样的人(根据参考物 ),选择用台灯还是白炽灯照射模型等)
②粗粒度剔除工作。把不可见的物体剔除出去。这样就不需要再交给几何阶段进行处理。
→ 人物参考模型的后背有一对小翅膀,但我画的是正面,看不见这对小翅膀,所以就剔除不画了。
③设置每个模型的渲染状态 = 材质(漫反射颜色、高光反射颜色)、纹理、Shader等。
→这个人物参考模型身穿金属材质的铠甲(被光源照射下的表面颜色,被光源照射下最亮地方的颜色)、铠甲上有很繁复的花纹。(Shader 此处不好比喻 )
④应用阶段输出渲染所需的几何信息,即渲染图元(点、线、三角面等)。传递给几何阶段。
→大脑分析了眼睛看到的人物参考模型,分析了一下它的轮廓大体(点、线、面),通知手准备描绘。
几何阶段 → 手
顶点着色器 [完全可编程]
①顶点着色器只有一个个顶点的数据。(不能增减,但可更改)。
→我们从参考模型上选出N个能描述它的轮廓,这N个点确定后,不可再选或去掉某个点,但可将某个我们选出的点进行移动,比如我想象将肚子周围的点向外扩散点,这样我们画出的人物可以更显肥硕。
②将顶点坐标从模型空间转换到齐次裁剪空间,坐标转换。
→人物参考模型是3D立体的,且与我有距离,需要透视分析,最终要画到纸上,此时我们将这个参考模型想象到一个边长与纸等宽的立方体中,好让我们更好的用几何思维+数字(x,y,z)来准确地描述这个模型。
③逐顶点光照(计算顶点颜色)
→我们不仅用脑记录了所有轮廓点的坐标,此时我们将这些轮廓点实际上的颜色也记住。(比如我头发末梢取的点是黑色,铠甲上的取的点是银色。)
曲面细分着色器 [可缺省]
①待研究
几何着色器 [可缺省]
①待研究
裁剪 [完全可编程]
①把不可见的顶点裁剪掉。
→这个人物参考模型穿着铠甲拿着一个41cm的大刀,但画布的宽才40cm,本来在超出1cm的刀尖上取的一个顶点不得不舍弃掉,只能用刀与画布的边界交界处的点代替了。
屏幕映射 [不可编程不可配置]
①把每个图元的x和y坐标转换到(二维)屏幕坐标系。
→这时,我只根据之前得到的轮廓点坐标的x,y值(此时不考虑z值),将轮廓点画在画布上。
三角形设置 [固定函数 ⊃ 不可编程不可配置]
→这时,我只根据之前得到的轮廓点坐标的x,y值,点在画布上。
三角形遍历 [固定函数 ⊃ 不可编程不可配置]
暂时先写到这,明天继续。。。