防忘:本笔记是以《Unity Shader入门精要》为根据,以及我对于重点的把握情况设计的。所有章节没有顺序都是按书本的章节相对应。
2.1 渲染流水线
渲染流程分为3个阶段,应用阶段(Application Stage)、几何阶段(Geometry Stage)、光栅化阶段(Rasterizer Stage)。但这只是概念阶段,我的理解的大致可以分为3个比较重要的阶段,而这3个阶段中的每个阶段又是一条流水线系统。
- 应用阶段,由CPU负责,我们开发者拥有绝对的控制权。输出渲染所需要的集合信息即渲染图元,渲染图元可以是点、线、三角面,该阶段是由开发者利用应用程序决定的,不是本书详细讲述的。
- 几何阶段,由GPU负责,决定绘制的图元是什么,怎么绘制,在哪里绘制,该阶段会输出屏幕空间的二维顶点坐标、每个顶点的深度值、着色等相关信息。
- 光栅化阶段,由GPU负责,将几何阶段传递的信息进行处理最终渲染出最终图像,对上阶段的数据进行插值,然后逐像素处理。
2.2 CPU和GPU通信
应该是发生在应用阶段之后将数据传给GPU。
- 把数据加载到显存中(显存也叫帧缓存应该是显卡或者GPU用来存储图形数据,还进行3D函数运算,存在但不限于存储这些数据),硬盘->RAM->显存,前两步由CPU运算,后者由GPU运算。RAM中数据转储到显存后就可以移除,但例如碰撞检测等功能的实现CPU还需要从RAM中访问数据,所以我们就不想这些数据被移除,硬盘转储到RAM很耗时。
- 设置渲染状态,定义场景中的网格是怎么渲染,使用什么样的顶点着色器或片元着色器。
- 调用Draw Call告诉GPU帮我渲染一下东西(该步骤会很大程度上影响性能,也存在一些理论专门去讲解怎么优化Draw Call)
2.3 GPU流水线
绿色代表该结算完全可编程、黄色不可以编程,蓝色表示由 GPU固定管线实现开发者没有任何控制权。实现表示必须由开发者编程实现,虚线表示该Shader是可选的。
几何阶段(Geometry Stage):
- 顶点着色器(Vertex Shader)是完全可以编程的,实现顶点的空间变换(水体的流动和布料动画等,必须完成顶点坐标从模型空间准环到齐次裁剪空间)、顶点的着色。速度快,坐标变换和逐顶点光照,需要时可以计算输出顶点颜色,准备后续所需要的数据。
- 曲面细分着色器(Tessellation Shader)可选着色器,用于细分图元。
- 几何着色器(Geometry Shader)可选着色器,执行主图元,产生更多图元。
- 裁剪(Cliping) 用于剔除不在摄像机内的顶点,并剔除某些三角图元的面片,可配置。
- 屏幕映射(Screen Mapping),不可配置和编程,负责将图元的左边转换到屏幕左边中。把每个图元的x和y坐标(还存在z坐标为深度坐标)转换到屏幕坐标系(Screen Coordinates)。OpenGL和DirectX屏幕坐标系存在差 异,作为开发者要时刻注意这样的差异。
光栅化阶段(Rasterizer Stage):
- 三角形设置(Triangle Setup)和三角形遍历(Triangle Traversal)阶段也是固定函数(Fixed-Function)阶段。计算三角形网格覆盖像素,并对三角形区域的像素进行插值。输出为片元序列,片元不是真正意义上的像素,而是包含信息的集合,这些状态用于计算像素最终的颜色(包括但不限于屏幕坐标、深度信息、以及其他从集合阶段输出的顶点信息,例如法线、纹理坐标等。个人猜想:此时的片元不是呈现最终我们在屏幕上看到的样子,大概是我们在软件中设置的该物体的受到光照深度影响的固有色,经过片元着色器后将纹理信息等其他信息最终合成为最终屏幕上看到的样子。)
- 片元着色器(Fragment Shader),完全可编程,它用于实现逐片元(Per-Fragment)的作色操作。是一个非常重要的可编程的着色器阶段,存在重要的一步纹理采样,将顶点着色器中输出的顶点纹理坐标,然后对顶点进行插值,形成其覆盖片元的纹理坐标。DirectX中片元着色器被称之为像素着色器(Pixel Shader)
- 逐片元从操作(Per-Fragment Operations)不可以编程,但可以配置。OpenGL称之为逐片元操作,DirectX称之为输出合并阶段。后者更加贴切实际效果。片元是否可见,深度测试、模板测试等。完成测试则把该片元的颜色和存储在颜色缓冲区的颜色混合。