Mathematics for 3D Game Programming and Computer Graphics 笔记 Chapter 0

Chapter 0  The Rendering Pipeline 渲染管线

0.1 Graphics Processors

一个典型的3D场景由许多物体组成,每个物体由一组顶点(vertices)表示,同时要指定一个 graphics primitive 来表明顶点数据应怎样组合在一起.下图为 OpenGL 支持的10种 primitive,通常3D模型由三角形列表表示,每个三角形指向顶点列表的3个顶点.

primitive

显卡上的GPU独立于CPU执行指令,CPU将命令送至GPU,然后继续其它工作,GPU异步执行渲染操作.将几何信息送至渲染库(如 OpenGL )后,GPU需要一定时间来完成渲染,这通常没什么问题,但有时候需要知道确切的时间,有 OpenGL 扩展能在CPU上运行并得到某组渲染指令完成的时间,但这样做可能会减慢程序速度.

OpenGL 与显卡驱动的接口叫硬件抽象层HAL,通过HAL可以控制所有支持 OpenGL 架构的显卡驱动,而驱动则可以直接控制GPU进行工作.

CPU_GPU

3D显卡有自己的存储空间VRAM,可存储任何信息.VRAM有前后图像缓冲 Image Buffer,视口 Viewport 中显示的图像来自前缓冲的信息,GPU则在后缓冲中进行渲染操作,在渲染完成后一次性与前缓冲进行交换(buffer swap),后缓冲中的信息被显示出来,前缓冲用于下一帧的渲染.交换通常与刷新频率同步来避免抖动现象.当交换发生在屏幕刷新时,视口上下会显示不同缓冲中的内容,就会产生抖动.VRAM中还有深度缓冲(depth buffer/z-buffer)来存储像素的深度信息,模板缓冲(stencil buffer)存储 integer mask 和贴图纹理信息(Texture Maps).

0.2 Vertex Transformation

transformation

object space :物体建模时的坐标

world space:物体放入世界中的坐标

camera space:以相机为原点的坐标,xy轴与屏幕对齐,z轴与观察方向平行

homogeneous clip space:进行透视变换后的坐标,xyz分量都在[-1,1]之间,在屏幕外的点会被裁剪掉,反映了在视口中的位置关系

window space:屏幕坐标,z坐标通常在[0,1]之间,后被转换成整数用于 z-buffer 的深度测试

进行坐标变换时通常还会进行光照计算等操作

0.3 Rasterization and Fragment Operations

在物体的顶点坐标转换至 window space 后,GPU还要决定每个 primitive 显示在哪些像素上.把物体的数学描述以及与物体相关的颜色信息转换为屏幕上的像素,这个过程称为光栅化.GPU会为每个像素计算深度,插值后的颜色,纹理坐标,这些信息和像素的位置信息一起,叫做 fragment.

primitive 的后续操作过程如下:

Graphics primitives                     Fragments
Face Culling(将物体的正面或背面剔除掉)——————-> Rasterization ———-> Fragment Shading —–> Fragment Operations

shading 的过程是可编程的,程序可以控制该段过程来控制像素的深度和颜色.在 shading 后会执行一系列 fragment operations,虽然逻辑上这些操作在 shading 之后,但是大多数GPU在 shading 之前都会进行一系列测试来避免对最后不显示的像素进行计算.

Fragment Operations 过程如下:

Fragment —> Pixel Ownership Test —> Scissor Test —> Alpha Test —> Stencil Test —> Depth Test —>Blending —> Image Buffer

ownership test 是唯一一个不能被关闭的操作,这个操作判断当前 fragment 是否可见,如果被其他窗口遮挡住的话,就将其丢弃.

程序可以在视口中指定的一个 scissor rectangle ,在 scissor test 中,在 scissor rectangle 外的 fragment 将被丢弃.

Alpha test :当计算一个 fragment 的颜色时, alpha value 也会同时计算. Application 指定一个值和一个关系(小于,大于或等于),通过测试的被保留,否则丢弃.

Stencil Test:读取在 stencil buffer 中相应位置的值,与程序设定的值比较,满足设定的条件即可通过,否则为失败,程序可指定通过或失败时 stencil buffer 执行的操作.这个测试用于实现一些特殊效果.

depth test 将 fragment 的深度值与 depth buffer 的深度值比较,将满足条件的留下并写入新值.通常设置为小于等于时通过来让前面的物体遮挡后面的物体.

前面的测试都通过时, fragment 的颜色值将与 image buffer 中的颜色进行混合 blending. 同样混合方式可以指定,可以简单覆盖原值,或是利用 alpha 值进行混合来制作透明效果等.