Realtime Rendering之 02渲染管线

第二章主要是整个渲染流水线的总结捏。这一部分不会涉及到太多细节,当成目录看就好啦!٩(๑❛ᴗ❛๑)۶

这一章的前面我会大概翻译下内容(有损版),最后贴出一张总结的脑图捏~

2.1 概括(11.8)

渲染快慢取决于计算复杂程度,可以用FPS,Hz,渲染一张图的ms数来表示渲染的快慢。
应用层靠软件驱动,在CPU上运行。这些CPU通常情况下包含多核,能够运行多线程。这能使CPU能够更加有效率的在应用阶段处理大量的任务。
在CPU上执行的任务通常包括碰撞检测,全局加速算法,动画,物理模拟和一些其他任务,这取决于应用软件。
几何阶段,处理变换,投影和其他几何处理。这个阶段计算了绘制什么,怎样绘制,应该在哪里绘制。几何阶段在GPU上运行,包含很多programmable cores。
光栅化阶段通常输入三个顶点形成一个三角形,并且找到这个三角形的所有像素给下一个阶段使用。
像素阶段,决定每个像素的颜色,执行深度检测判断物体是否可见。也会在这个阶段执行混合操作。光栅化阶段与像素阶段也是在GPU中进行。



2.2 应用阶段

开发者可以在应用阶段控制所有部分。比如,应用阶段的算法或者设置可以减少三角形渲染的数目。
但是一些应用工作也可以通过使用compute shader模式在GPU中计算。这种模式将GPU视为高度并行的通用处理器,忽略了其专门用于渲染图形的特殊功能。在应用阶段的结尾,通常将几何体给几何阶段,包括渲染中的面,点,线,三角形。这是应用阶段最重要的任务。
CPU不会被划分为多个子阶段(就像几何阶段和光栅化阶段和像素阶段那种)。然而,为了提高表现,应用阶段通常可以通过多个处理器并行运行,在CPU设计中,叫做superscalar 。
碰撞检测在这个阶段执行。如果检测到两个物体之间的碰撞的话,会对正在碰撞的物体做出回应。应用阶段也会关注其他来源的输入,比如键盘鼠标等等。针对于不同的输入也可以做出不同的动作。加速算法,如culling也会在这个阶段中执行。



2.3 几何阶段

几何阶段分为以下几个步骤

2.3.1 Vertex Shading 顶点着色

顶点着色有两个主要任务:计算顶点的位置,计算顶点的其他Data,比如normal和texture coordinate。现代GPU已经把计算大部分都放在像素着色器上了,顶点着色器很少进行shading的计算。顶点着色器通常会进行顶点的计算,比如顶点动画
在顶点着色器阶段通常会进行坐标转换。每个物体可以有自己的几何实例。在moedl transform中,顶点和法线被转换到世界坐标中。
摄像机空间包含位置和方向信息,模型会被view transform 转换到摄像机空间。摄像机空间会把摄像机放到远点,指向Z方向上,y方向向上,x方向向右。有些会使用-z有些会使用+z。
仅仅有物体的位置和形状是不够的,还需要计算材质。材质可能在顶点着色器中计算也可能在像素着色器中计算。顶点着色器中的顶点信息,包括顶点位置,法线,顶点色,和其他信息需要用来计算shading。顶点着色器的结果,可以是颜色,向量,纹理坐标和其他里欸行的shading data会被送到光栅化和像素阶段继续计算。
顶点着色器也会将物体进行投影变换放入 canonical view volume。投影变换包括正交投影和透视投影。在经过投影变换后,会进入裁剪空间。经过变换后,z坐标上的信息会被存储到z缓存中。


2.3.2 可选顶点处理

一旦顶点着色结束,就会有一些可选的步骤:曲面细分,几何着色器和流输出。这些操作依赖于硬件,并不是所有的GPU都有这些功能。
首先一个阶段是细分。通过细分,可以在合适的位置产生出合适数量的三角形。
在此之前的处理流程中,我们只是在处理顶点。这些顶点可以用来表示点、线、三角形或其他对象。顶点也可以用来描述曲面,例如球面。这样的曲面可以通过一组小块(patch)来指定,每个小块由一组顶点组成。细分阶段(tessellation stage)本身由一系列阶段组成——包括外壳着色器(hull shader)、细分器(tessellator)和域着色器(domain shader)——它将这些小块的顶点集转换为通常更大的顶点集,随后用这些顶点集生成新的三角形集合。场景中的相机可以决定生成的三角形数量:当小块靠近时生成更多三角形,远离时生成较少三角形。
下一个阶段是几何阶段。几何阶段比细分阶段出现的早,因此在更多的GPU中有这个功能。几何着色器可以产生新的顶点,但是限制较多。几何着色器有一些用处,比如粒子生成。几何着色器可以通过点生成一直面向观察者的正方形(通过两个三角形生成)。
最后一个可选阶段是流输出。这个阶段让我们使用GPU作为一个几何引擎,把处理过的顶点输出到数组中进行进一步处理,而不是将处理过的顶点发送到管渲染管线的其他部分。这些数据可以被CPU或者GPU本身使用。这个阶段通常用于粒子模拟。


2.3.3 裁剪

完全在可见空间的几何体会被渲染;完全在可见空间之外的几何体不会被渲染;部分在可见空间内的几何体需要裁剪。view transformation 和 projection 都在裁剪之前进行。

除了6个裁剪平面外,用户也可以定义额外的裁剪平面让物体可见或不可见。这个过程叫sectioning。
裁剪使用投影步骤中的齐次坐标。最后,perspective division步骤会将三角形的位置放在三维的归一化后的设备坐标中,范围是(−1, −1, −1) to (1, 1, 1)。几何阶段的最后一步是将这个空间转化到屏幕空间。

 

2.3.4 Screen Mapping

接下来,只有在视线体积内的物体才会被传递到下一阶段,此时坐标系仍旧是三维的。x坐标和y坐标会被转换到screen coordinates,而屏幕坐标空间和z坐标一起被称作window coordinates。window coordinates和Remap后的z坐标(OpenGL在\[-1,1],DX在\[0,1] )会被传递到光栅化阶段。

接下来,我们会讨论整数和浮点数是如何与像素(以及纹理坐标)关联的。利用笛卡尔坐标系,OpenGL和DX10及之后的版本都使用最左边像素的最左边缘作为0.0,像素的重心为0.5。因此,从\[0,9]的像素便可以被转换为浮点数\[0.0,10.0),转换公式如下:
d = floor(c)
c = d + 0.5
其中,d是像素的索引数,c是像素内的连续浮点数。

虽然对于所有的API来说,像素的位置都是从左到右,但是上下却不同。OpenGL更倾向于笛卡尔坐标系(也就是从左下角开始),DX又是会定义左上角作为起点。



2.4 光栅化

这个阶段是为了找到所有需要被渲染的像素,包括三角形设置和三角形遍历。光栅化阶段会把屏幕空间中的二维顶点(包含深度数值)转换到屏幕空间中。
三角形是否会overlap取决于渲染管线。比如,可以对每个像素只采样一次,也可以采样多次用来抗锯齿。


2.4.1 三角形设置

在这个阶段会计算differentials, edge equations和其他数据,这些数据会用来进行接下来的三角形遍历。这一任务使用fixed-function hardware。


2.4.2 三角形遍历

这个阶段决定了每个像素被一个三角形覆盖的地方,会如何被检测到,以及生成。




2.5 像素阶段

像素阶段可以被分为像素着色和混合阶段。


2.5.1 像素着色

这个阶段使用插值之后的着色数据作为输入,进行逐像素计算,给下一阶段输出一个或一个以上的颜色。不像三角形设置和三角形遍历,这一阶段通常会使用可编程的GPU核心,程序员可以在这一阶段用像素着色器或者片元着色器来控制。这一阶段可以使用大量的技术,其中最广为人知的就是纹理,可以使用二维纹理或者三维纹理。


2.5.2 混合

每个像素信息都会存储在color buffer中,然后再这一阶段进行混合。这个阶段也被称作“ROP”,即 “raster operations (pipeline)” 或者 “render output unit” 。不像着色阶段,这一阶段并不是完全可编程的,但是是高度可配置的。
这个阶段需要计算可见性。对于大多数图形硬件来说,这个通过Z缓冲算法来计算。z缓冲中存储的图片应该与颜色缓冲的形状与大小相同。如果一个像素中的primitive的z缓冲中的数值比之前的数值小,那么存储在颜色缓冲区中的值就会被渲染出来,反之则不会。深度缓冲算法非常简单,有O(n)的时间复杂度,n是被渲染的primitive的数量。但是这种算法无法计算透明或者半透明物体,需要在不透明物体被渲染之后再去混合。

除了颜色缓冲和深度缓冲之外,还有其他通道和缓冲区。比如alpha缓冲就是用来过滤和专区fragment信息的。alpha通道用来和颜色缓冲练习,为每个像素存储了不透明度。在老版的API中,alpha test通过测试舍弃一些像素 ,这种方式可以保证全透明的fragment不会影响到z缓冲。

模板缓冲是另一个屏幕空间的缓冲区,用来记录primitive的位置,通常每个像素包含8比特信息。primitive可以用多种计算方程来被渲染到模板缓冲中,然后影响颜色缓冲和z缓冲。比如一个圆已经被绘制到模板缓冲中,通过操作手段只让圆区域中的颜色缓冲渲染到后续操作中。模板缓冲可以制作强大的特殊效果,比如将颜色缓冲区中的颜色与模板缓冲区中的颜色混合等等,这些功能都被称作ROP。混合操作是不可编程但是高度可配的,但是在一些API中支持raster order views,支持可编程的混合操作。

framebuffer(帧缓冲)包含几乎所有的缓冲。

在经过光栅化后,摄像机视角出发的view会被渲染到屏幕上,屏幕显示颜色缓冲区的内容。为了避免让观察者看到primitives被光栅化和投送到屏幕的过程,采用双缓冲的办法。这意味着在back buffer中会渲染出一个scene,然后再渲染到屏幕中。将back buffer中的内容渲染到屏幕中后,下一帧的内容会交换到back buffer中。




2.6 渲染管线

呜呼!总算结束啦!

总体而言这里还算是简单捏(毕竟没有任何细节),以后可不会这样啦!٩(๑❛ᴗ❛๑)۶

这部分主要就是对前文的总结啦~这里我就把自己做的脑图贴上来啦

发表评论