最近几天看了《GPU编程与CG语言之阳春白雪下里巴人》这本书,书的内容和之前看的《Unity Shader入门精要》很相似,但是侧重点有所不同。因此,下面的三篇文章是在阅读《GPU》之后,结合之前一本书的内容,做一些更深入的理解或逻辑的理顺。
这一篇文章是对渲染流水线的知识做一下进一步理解。老生常谈地,渲染流水线分为应用阶段、几何阶段、光栅化阶段。
应用阶段
主要使用高级语言,在应用层面准备数据。本书中举例如碰撞检测、场景图建立、空间八叉树更新、视锥裁剪等。
我理解的是:我们在Unity的shader文件中声明了变量(例如vertex、normal等),应用阶段是在这些变量被传到shader之前做的事情。
几何阶段
包括顶点坐标变换、光照、裁剪、投影、屏幕映射等操作。
顶点坐标变换
顶点坐标变换就是《Unity》一书第四章中的几个坐标系之间的转换。其余的几个步骤其实包含在顶点坐标变换的过程中。
-
模型空间
需要注意的是从模型空间转变到世界空间下,不只顶点坐标要变换,法线也要跟着变化,法线的变换矩阵是顶点变换矩阵的逆转置矩阵。推导过程详见《Unity》一书第四章4.7节。 -
世界空间
-
相机空间
相机空间到裁剪空间的映射过程通常称为投影,可分为透视投影和正交投影。 -
投影/裁剪空间
在裁剪空间做裁剪,把视锥之外的顶点剔除。
这一个步骤将模型作为一个整体,对顶点进行剔除。如果一个模型对所有顶点都在视锥里,则保留;如果顶点全不在视锥里,则剔除;如果一部分在一部分不在则依具体算法计算。这一步不涉及到对具体三角形片元的裁剪。 -
NDC空间
-
屏幕空间
图元装配
上述变换都是对顶点的操作,在这一步骤中,我们根据顶点坐标和索引构建出三角形网格。
-
三角形剔除
不在视锥内的三角形剔除。 -
三角形裁剪
对有一部分在视锥内的三角形裁剪,先裁剪成四边形,再拆成两个三角形。 -
背面剔除
使用右手定则确定法线方向,法线方向和视线方向的点积为正,说明该三角形正面朝向相机,否则该三角形背对相机,会被剔除。但是可以设置是否进行背面剔除,如《Unity》一书使用透明度检测实现透明效果时,就关闭了背面剔除。
这一阶段结束后,我们得到了一些三角形面片用于下一步的光栅化。
光栅化阶段
像素位置计算
将顶点的屏幕坐标转换为像素位置,并使用一定的算法计算出每一条线(三角形设置)和面(三角形遍历)占用的像素位置。
像素颜色计算
- 深度/模版检测
- 纹理
- 混合(Blending)
深度缓冲(Z-buffer)
Z-buffer中储存的z值并不是欧氏距离,而是一个相对的值。我们只储存了顶点的z值,内部像素点的z值需要通过插值获得,而得到的z值并不能反应真实的空间点的深度关系,有可能获得错误的结果。
如下图所示,A、E是顶点,B、C、D为真实的深度,而B'、C'、D'为插值计算出来的深度。
Tips:
坐标变换时旋转、缩放、平移的顺序:
--缩放变换不改变坐标轴的走向,也不改变原点的位置,所以两个坐标系仍然重合。
--旋转变换改变坐标轴的走向,但不改变原点的位置,所以两个坐标系坐标轴不再处于相同走向。
--平移变换不改变坐标轴走向,但改变原点位置,两个坐标系原点不再重合。
因此,变换顺序只能是 缩放 -> 旋转 -> 平移 。
图片来自 东隆咚
网友评论