3D渲染管线
2013-08-11 22:24 北漂男孩 阅读(635) 评论(0) 编辑 收藏 举报渲染管线
从最开始的Input Assembler阶段到最终的Output Merger阶段,每个阶段处理完的输出,传递给下一个阶段,作为其输入。
1. Input Assembler Stage
这个阶段的主要目的是根据用户提供的顶点及索引信息,构建多边形,主要有点、线段、三角形。给定顶点和索引,构建多边形的方法取决于所使用的基本图元的拓扑类型(Primitive Topology)。D3D11中常见的拓扑类型有以下几种:
1. Point List:定义的每一个顶点作为一个单独的点进行绘制,如图:
2. Line Strip:所有的顶点按顺序逐个连接成线段,如图:
3. Line List:所有的顶点按顺序两两配对连接成线段,如图:
4. Triangle Strip:所有的顶点按顺序组成三角形,前三个顶点为第一个三角形,从第四个开始每个顶点与位于其前面的两个顶点组成一个三角形,如图:
5. Triangle List:类似于Line List,按顺序三三配对组成三角形,如图:
举个例子,对于下图,9个顶点及拓扑类型Triangle List,对应索引:[0,1,2, 0,2,3, 0,3,4, 0,4,5, 0,5,6, 0,6,7, 0,7,8]。
Input Assembler会三个三个地读取索引组成三角形,形成图中的七个三角形。
对于另一个图,4个顶点及拓扑类型Triangle Strip,对应索引:[1,2,0,3]。
2. Vertex Shader Stage
这是一个完全可编程的阶段,即完全由程序员自己来实现。该阶段的核心为模型顶点的各种空间变化。3D图形学定义了以下几种坐标系空间:
1. 模型空间:Model Space,也叫Local Space
直观的讲,这个坐标系一般以模型中心为原点,所有的模型在建模的时候给定的模型顶点坐标都以这个坐标系为基准,用户最开始所指定的顶点坐标也是位于该空间。
给出模型空间的好处在于方便建模,以及单个模型的重重利用。因为一个物体可被放置到场景的多个地方,这时每个物体的顶点坐标显然是不一样的,但可以共享同一个模型。
2. 世界空间:World Space
这个坐标系即3D场景给各个物体指定坐标的基准。场景有不同的物体具有不同的世界坐标。
3. 视角空间:View Space
这个坐标是以照相机为基准的,以照相机位置为原点,照相机朝向z轴正方向,右边为x轴正方向,上边为y轴正方向。之所以设置这个坐标系,主要是为了主便接下来的投影及裁剪操作。如果直接在世界空间下进行,由于照相机位置、朝向灵活多变,计算将会十分复杂。有了视角空间,一切计算以原点为基准,会大大方便计算。
4. 投影、裁剪空间:Projection Clip Space
这个空间即世界空间的物体被投影到相应的投影面上之后,继而进行裁剪操作所在的空间。
用户指定的所有顶点都是基于模型空间的,在Vertex Shader阶段,每个顶点要依次经历所有这些空间,最终转换为屏幕上对应的二维坐标,不同空间之间的切换称为“空间变换”,实现空间变换的基本工作即矩阵。
I. 模型、世界空间变换
从模型空间到世界的变换主要包括:缩放、旋转和平移。缩放和旋转操作通过3X3矩阵及可实现,为了实现平移操作,则需要4X4型矩阵,因此所有的空间变换统一采用4X4矩阵,且顶点坐标也采用相应的[x,y,z,w]型。大多数情况下,w=1,[x,y,z]与顶点本身坐标保持一致。此外,多出的w在投影变换中发挥了至关重要的作用。
II. 世界、视角空间变换
从世界空间到视角空间通过相应的“视角矩阵”实现。为了更好的理解视角矩阵的作用,可以这样理解:
在任意时刻,相机在世界空间都有一个位置坐标[Px,Py,Pz],同时也有相应的朝向,我们可以用三个坐标轴来确定其朝向,即U,V,W,U指向相机右侧,V指定相机上侧,W为相机注视方向。那么视角矩阵的作用,即把相机位置移回到世界坐标系原点,且三个坐标轴U,V,W与世界坐标系的X,Y,Z分别重合。这就是视角矩阵的目的!理解这一点对于自己来实现灵活的照相机非常重要,因为实现照相机最重要的一点即根据任意时刻相机的位置、朝向来计算其视角矩阵。
III. 视角、投影空间变换
从视角空间到投影、裁剪空间依靠“投影矩阵”来实现。投影有两种:正交投影和透明投影,大多数情况下,比如游戏中,用到的投影为透视投影,因为这种投影方式与人观察物体的方式是一样的。
要计算投影矩阵,首先要确定照相机的几项基本参数:近、远平面(n,f),投影平面的宽、高比(r),以及上、下视野角度大小(a)。近、远平面规定照相机能看到的最近和最远的距离。有了这些参数,所有能投影到屏幕上的点组成了如下所示的多面体:
即一个被切掉顶部的金字塔。
投影变换的效果即把这个多面体转换成长方体,长、宽分别位于[-1,1]之间,z位于[0,1]之间。真正的裁剪操作就是在这个长方体中进行的,因此将大大简化裁剪的计算。
关于投影变换,要注意一点的是,很多人误以为投影即把三维顶点投影到二维平面 上,投影变换后顶点的z坐标即被抛弃,只剩下x,y坐标用于后面的屏幕变换。实际上,投影变换后z坐标并没有消失,位于[0,1]之间。屏幕坐标的变换不再使用z坐标,但z坐标在后面的Output Merger阶段用于深度比较时发挥的关键作用。
整个顶点着色阶段到此结束。
5. Rasterizer Stage
这个阶段属于不可编程阶段,即完全由硬件实现,主要包括:
1. 视口变换
即把投影变换后得到的顶点的x,y坐标,根据用户设定的视口参数,变换到屏幕上对应的坐标。
2. 隐藏面消除(Backface Culling)
即使经过了裁剪操作,对于每一个物体,照相机只能看到其正对着相机的一面,对背对着相机的一面是看不到的。这一步的任务即是把看不到的这一面消除掉,以免继续对其进行处理影响效率。
为了确定一个多边形是正对着相机还是背对着相机,就要用到我们在Input Assembler Stage指定多边形(三角形)时的顶点顺序了。默认情况下,D3D规定按顺时针顺序指定的三角形属于正面,逆时针为背面。如果V0,V1,V2按顺时针排序,则该三角形为正面,将通过这一步的检测,如果为逆时针,则被抛弃。
确定顺时针还是逆时针,可以用如下方法:
给出两个向量:E0 = V1-V0 E1 = V2-V0对E0和E1进行叉乘操作N = E0 X E1。如果N指向相机,则为正面,否则为背面。
3. 顶点属性的插值计算
在Input Assembler Stage中,用户指定的仅仅是一系列的多边形,以三角形为合例,每个三角形由三个顶点组成,每个顶点包含一系列的属性,如坐标、法线、纹理坐标等等。在经过顶点着色阶段、视口变换后,这三个顶点在屏幕上都有对应的坐标。但为了显示该三角形,仅仅三个顶点显然是不够的,为了计算该三角形所覆盖的屏幕上每个像素处的属性,要进行正确的插值计算。
注意,插值计算的要求是,在世界空间中保证以三个顶点为基准进行线性计算,在二维屏幕上,以相应的投影后的三个顶点进行插值时不再是线性。
6. Pixel Shader Stage
这个阶段也是完全可编程的一个阶段,也是跟顶点着色器阶段一样十分重要的阶段。因为在D3D11中,顶点着色器和像素着色器是程序员实现的两个最基本的阶段。
7. Output Merger Stage
这个阶段即输出片段的混合阶段。该阶段不可编程,但是高度可调节。程序员可以灵活地调整管线的状态来实现不同的特效。比如针对深度缓冲区、模板缓冲区,混合等可以有各种不同的状态。利用它们来实现各种特效后面也有特别详细的介绍。
D3D11整个渲染管线到这一步就结束了,小结一下:
3D渲染管线的作用就是,给定场景描述:顶点属性、索引、照相机、光源、材质等信息,计算其在光栅显示器屏幕上对应的显示结果。其主要阶段包括:Input Assembler Stage、Vertex Shader Stage、Tessellation Stage(包括三个子阶段:Hull Shader Stage、Tessellator、Domain Shader Stage)、Geometry Shader Stage、Rasterizer Stage、Pixel Shader Stage、Output Merger Stage。
3D渲染管线对于学习3D图形学还是D3D API,都相当重要。因此,请务必花时间深刻理解之,否则是不可能灵活地写Shader的。