Viewport 和 Frustum 有什么区别?
答:Viewport 是定义图形输出区域的2D矩形。Viewport 不能超出屏幕范围,一个游戏可以有多个 Viewport。一般平台 Viewport 和 Scissoring Rectangle 是同时设置不可分离的,因此设置 Viewport 同时也设置了 Scissoring Rectangle。但是 PS2 Scissoring 可以分开设置,使很多 Filtering 特效成为可能或更加快捷。
投影包括平行投影和 Perspective 投影。Frustum 一般是指3D投影的平行六面体,而3D投影中用的最多的是对称的3D投影(比如用 OpenGL的 glFrustum(aspect, fov, znear, zfar),但是不对称的3D投影(同样是平行六面体,截面不一定是梯形)也很有用,比如用拼凑两个显示器,每个显示器显示一般视野.Viewport 和 Frustum 的 Near Clip Plane 有什么区别?
答:Near Clip Plane 和 Far Clip Plane 是对应于 Frustum 的,跟 Viewport 无关。但是根据 Near Clip Plane 和 Far Clip Plane 的2D特性,有的 API将 Viewport 和 Frustum 一起设置。Frustum 的作用是将世界空间中一个平行六面体区域映射到一个单位矩形中(Homogeneous Clipping Space),然后单位矩形再映射到屏幕上。Near Clip Plane 是这个六面体正对着视点的那个面。任何视点和 Near Clip Plane 之间的物体都会被裁减掉。Vertex, Point, Vector 有什么含义上的区别? Plane, Face 和 Mesh 呢?
答:Vertex 是顶点,一般在游戏中常指三角形或线段的顶点,有时也用来指多边型的顶点。Point 是广意的“点”,一般在游戏中常指3D空间中的任何一点。Vector 是向量,游戏中常用 $(3, 2, 4)$ 维向量。Vertex 和 Point 和其他的任何数据都可以用向量来表示。 Plane 是平面,Face 大多表示三角形,也可以表示在一个平面上的多边形。Mesh 是一个三角形的组,可以有其逻辑意义,比如一个人,一个物体; 也可以没有逻辑意义,比如一个椅子中所有用到某个特定贴图的被 group 到一个 strip 中的所有三角形的集合。Mesh 的概念比 Plane 或 Face 高很多,什么都可以泛指,什么 static mesh, skined mesh, soft mesh, graphics mesh, collision mesh, 等等。但是其跟本意义是 triangle soup。为什么顶点会有 W 分量,它怎么算出来的?干什么用的?
答:输入顶点的 W 表示你希望对他的放大倍数。比如 $(1, 1, 1, 2)$ 实际是单位话后的 $(2, 2, 2, 1)$ (特例:DirectX中2D顶点的 W用来表示希望显示的“Z”)
在透视投影后, W的值相当于 View Space 中的线性的 Z, 用来剪裁, 同时用来做贴图透视纠正和雾化景深(有些平台包括颜色透视纠正)。这里不能用透视投影后的 Z因为这个 Z是非线性的,这里也不能用透视投影之前的 Z因为这个 Z没有单位化。在一次完整的顶点渲染管线中,最多会出现多少种坐标系?(例如世界坐标系)
答:逻辑上,Local Space -> World Space -> View Space -> Clipping Space -> Unit Space(Homo Clipping Space), Screen Space. 实际上,对于一般的 pipeline 来说,用户负责提供的 World Matrix 包括了前两步的转换。上面的每个坐标系的实际意义是什么?互相之间怎么转换?转换矩阵怎么写,意义又是什么?
- Local space: 给物体定一个原点和 X,Y,Z轴建立起来的空间。
- World space: 定义“世界”的概念。
- View space: 原点在视点,Z轴沿视线方向,X轴是看的人侧举的一只手臂的方向。
- Clipping Space: 没有单位化的 Unit Space,用于裁减。
- Unit Space: $(-1, -1, -1)$ 到 $(1, 1, 1)$ 的正方形。(DirectX中 Z的范围是反向的 $(0,1)$ 的范围)
- Screen Space: 屏幕空间,原点在屏幕的左下(OpenGL)或左上(DirectX)。Unit Space 平行投影到 Screen Space 中的 Viewport 区域。(Screen Space 可以分成 Virtual Screen Space 和 Physics Screen Space): 比如在 PS2上, 用于支持 Guardband。)
光照是怎么计算的?光源可以设置 Ambient, Diffuse…为什么 Material 也可以设置 Ambient, Diffuse…?为什么顶点数据中还可以再指定 Diffuse, Specular?
答:光照公式用的是简化的逼近模型,具体看图形学的书去。Material 的 Ambient, Diffuse 定义的是 Material 的 反光特性和强度。在每帧的颜色混合过程中,我们可以在 Set Texture Stage State-中指定 Alpha Op, Color Op,在 Set Render State 中指定 Src Blend 和 Dest Blend,它们互相是什么关系?
答:对于每个 Texture Stage, Alpha 的计算和 Color 的计算是独立的。 如果希望 Color Final-=Color Texture * Color Constant, Color Op 就要设置成 MODULATE,表示乘法。Color Arg0用 TEX,Color Arg1用 CONST.
所有的 Texture Stage 之后,是 Alpha Blend 的 Stage。 Src Blend 定义如何在最终结果中混合刚计算完的 pixel 的颜色和 Alpha, Dest Blend 定义如何在最终结果中混合 Frame Color Buffer 以存的颜色和 Alpha。比如 Src Blend=ONE, Dest Blend=ONE, 表示两者相加。几种 Alpha Blend-方式对应的实际含义是什么?
答:看书。Alpha Test 和 Alpha Blend-有什么区别? Alpha Blend-可以完全取代 Alpha Test 吗?
答:不同,不能各自替代。Test 就象是过滤,过去了或筛剩下了。Blend 是混合,象配化学药水一样。红的配绿的居然是黄的。。。Texture Sampler Mode 中,可以分别对 MIN, MAG, MIP指定 Point 和 Linear,它们可以有哪些组合?各代表什么意义?
答:MIN和 MAG表示放大或缩小。比如放大,如果 MAG是 Linear, 放大的时候用线性插值。MIP是做 MIPMAP的时候,如何混合相邻的两个 MIPMAP中采样出的颜色。 Linear 表示对两个采样出的颜色进行线性插值。全屏抗锯齿和 Texture Sampler Mode 有关系吗? 和 Montion Blur 有关系吗?
答:都没有。Cull_CW, Cull_CCW是干什么用的? 不做 Cull 行吗? Cull 和 Clip 有区别吗?
答:Cull 是反面剔除。Clip 是裁减。
不做 Cull 道理上不成,比如同一面墙用正反两个矩形表示,各自有其不同的光照和不同的贴图(一面水泥一面墙纸),各自有其不同的正方向。 打开 Cull, 就能在任何一个方向只看到一个正确的面。但是,实际从性能考虑上有时不能或最好不用 cull,比如 PS2。此时就需要在两个墙之间留距离,再在墙的侧面多加表示厚度的墙面。。。Shading Mode 可以指定 FLAT, GOURAUD, PHONG,这发生在渲染过程中的哪一步? 和 Fill Mode 有什么关系?
答:Shading Mode 现在的技术还不能指定 PHONG。 有的平台发生在渲染的 rasterization,少数平台在 vertex processing-. 或两者。 比如即使 rasterization 支持 FLAT mode, 你也可以人为编程简化 vertex processing-,只计算 triangle 中一点的光照,甚至根本就只传一个 Vertex normal 到 VU1或 GPU中。 和 Fill Mode 有关系,因为大多平台对 FLAT mode 做了优化, 性能提高。UV有什么用?UV和 ST有什么区别?UV在光栅化时需要被插值吗?插值完了再做什么?
答:这是 PS2特有的概念。
UV是在贴图坐标定义的。比如贴图是128*128, U和 V各自的范围就是从0到128。
ST是逻辑的,U和 V的范围都是从0到1。(超出重复)Vertex Shader 和 Pixel Shader 分别对应于 Fixed Pipeline 的哪些步骤? 先搞清楚 Fixed Pipeline 对进一步研究 Programmable Pipeline-很有好处,你同意吗?为什么?
答:Fixed Pipeline 可以又很多的 API function 提供参数控制。大部分都是对应于 Vertex Shader 的。但是 Texture Stage,Alpha Blending,Bump 等特效对应于 Pixel Shader。Fixed Pipeline 本身还是有用的。同意,不告诉你为什么。清晰地描述每一个三角形, 是如何从刚开始的模型数据, 成为屏幕上的象素点?
答:BSP, OSP, Voxel…它们处于 Render Pipeline 的什么地位上?
答:没有位置。 这些是图形 Scene Graph 中的部分,一般跟 Render Pipeline 不着边。当然,在 PS2上你可以在 VU1中写你自己的 BSP surface renderer,等等。Viewport 和 Frustum 有什么区别? Viewport 和 Frustum 的 Near Clip Plane 有什么区别?
答:Viewport 是定义在”屏幕坐标系”下的,它是渲染目标表面的一个区域.渲染到这个区域以外的图形将被 Clip 掉.
View Frustum 是定义在”世界坐标系”下的,它是一个四楞台.顶面就叫做 Near Clip Plane,底面就叫做 Far Clip Plane.落在 View Frustum 之外的物体,默认情况下会被 Clip. View Frustum 的顶点就是 Camera 也就是眼睛所在的位置,顶角的一半成为 FOV(视域,即视野范围)
那么, View Frustum 实际上就是从”世界坐标系”下的眼睛位置去观察 Viewport…Vertex, Point, Vector 有什么含义上的区别? Plane, Face 和 Mesh 呢?
答:Point, Vector(向量)是数学名词,当我们提到它们,往往是在做一些物理和几何运算,比如碰撞检测.而 Vertex 则是具有图形意义的顶点,往往带有除了空间位置以外的其他信息,例如 Normal, Diffuse…
类似的 Plane 也属于数学概念,我们常常在 BSP树的切分面时提到它.Face 是带有一组顶点和边信息的面,是进行 Shading 的基本单位.Mesh 是一组面,又叫网格,含有更多的图形信息,比如 Texture…为什么顶点会有 W分量,它怎么算出来的?干什么用的?
答:当我们使用标准4x4的 Matrix(特别是 Projection Matrix,它必须是齐次的,它的3行4列元素必须=1.0f)进行坐标变换,而为每个初始顶点额外指定一个 W=1.0f 时,那么在变换到齐次坐标系下时, W分量可以用来进行 Clip:
$-W < X <= W, -W < Y <= W, 0 < Z <= W$
凡是不满足上式的点将被 Clip.(注意 Clip 不简单等于不画)
此外 W还被用于 Fog 和 Depth Buffe r.
最后就是不要把 XYZW和四元数搞混了,后者是为了解决 Gimbal Lock?和平滑的旋转插值等问题引入的数学方式.在一次完整的顶点渲染管线中,最多会出现多少种坐标系(例如世界坐标系)?上面的每个坐标系的实际意义是什么?互相之间怎么转换?转换矩阵怎么写,意义又是什么?
答:会顺次出现”Model Space”(Local Space)->”World Space”->”View Space”(Camera Space)->”Projection Space”->”Screen Space”
在 Model Space 下,各个 Object 之间没有相互关系,也不知道 Camera 和 Frustum 的存在.为了把孤立的 Object 全部放在 World Space?下,通常会乘以一些最初的变换矩阵.另外, Model Space?并不是一个必须的概念, OpenGL就没有 Model Space.
在 World Space?下,所有 Object 都有了统一的坐标定义.所以在这里开始可以做很多工作.比如场景数据结构 的遍历,碰撞检测等等,光源也在这里被初始化.在这里乘以 View Matrix 就可以变换到 View Space.通常用 eye,look,up 来定义一 个 View Matrix.
在 View Space 下,坐标原点位于 Camera 的点也就是 View Frustum 的顶点,而方向对齐 Camera 的方向.这里进行 Backface Culling:
Visibility = plane Norma l.dot Product(View Vector) > 0
此时乘以 Projection Matrix 变换到 Projection Space.
在 Projection Space 下,坐标系变成方形.这里进行 Frustum Culling(使用 W),和利用 Depth Buffe r 来隐面消除.
在做完 Viewport Scale 之后,就到了 Screen Space.此时实际上3D的顶点已经成为2D的顶点.接下来就可以进行光照计算,光栅化, Alpha 混合和贴图了.
变换矩阵:
平移: 缩放: 旋转(以 X为例): 投影:
| 1 0 0 0 | | Sx 0 0 0 | | 1 0 0 0 | | w 0 0 0 |
| 0 1 0 0 | | 0 Sy 0 0 | | 0 cos sin 0 | | 0 h 0 0 |
| 0 0 1 0 | | 0 0 Sz 0 | | 0 -sin cos 0 | | 0 0 Q 1 |
| Tx Ty Tz 1 | | 0 0 0 1 | | 0 0 0 1 | | 0 0 -QZn 0 |
其中:$w=\cot(FOVh/2)$. $h=\cot(FOVv/2)$. $Q=Zf/(Zf Zn)$
如果使用 DX或者 GL的话,往往有非常方便的接口可以调用,不需要牢记这些数学公式.光照是怎么计算的?光源可以设置 Ambient, Diffuse…为什么 Material 也可以设置 Ambient, Diffuse…?为什么顶点数据中还可以再指定 Diffuse, Specular?
答:光分为全局环境光,平光,点光,聚光.
光照计算公式比较复杂,总的来说就是
$Lighting = Ambient + Diffuse + Specular + Emissive$
也就是四个分量.而其中的每个分量,简单来说就是光源和 Materail 以某种方式相乘累加的结果.
$$
\begin{align}
Ambient Lighting &= Ca*[Ga + sum(LaAttenSpot)] \
Diffuse Lighting &= sum[CdLd(N.Ldir)AttenSpot] \
Specular Lighting &= Cssum[Ls(N.H)PAttenSpot] \
Emissive Lighting &= Ce
\end{align}
$$
上面 Ca 代表 Material 的属性, La 代表 Light 的属性, 从上面式子我们可以看得出光照计算的大概过程.
一些细节:
Ga:全局环境光,我们在 Render State 里可以设置.
Atten:光的衰减因子,可以分为常数,线性,和平方衰减.
Atten = 1/( att0i + att1i * d + att2i * d2) d 表示 Vertex 到光源的距离.
对于平行光, Atten=1; 如果光源超出范围, Atten=0
Spot:光的聚光因子.这个计算比较复杂,对于非聚光灯, Spot=1.
N:Vertex Normal.
Ldir:从顶点到光源的向量.
H:被称为 Half way vector(中间向量)
H = norm(norm(Cp - Vp) + Ldir) Cp:Camera 位置 Vp:顶点位置. norm 表示单位化.
P:Specular 的反射强度.也称为 Shiness.在指定 Material 的 Specular 时通常会一起指定.
总结一下:
对于 Ambient 和 Emissive 的计算,是不用考虑 Normal 和光的方向的.尤其是 Emissive(自发光)只和 Material 有关,光源没有这个属性.
注意所有光源都可以有 Amient 分量,它和全局环境光不是一个概念.
最重要的是:
光照计算的结果,是由 Light 和 Material 共同决定的.Light 的 Ambient, Diffuse…指定了光源本身的属性.而 Material 的 Ambient, Diffuse…指定了被照亮的物体以何种程度受到光的影响.
一定还有一个疑问:
为什么顶点的数据中还可以指定 Diffuse 和 Specular 呢?这其实是逐顶点指定了 Material.你可以通过 Render State 的设置,而决定 Material 的来源:从顶点数据得到,或者从全局设置的 Material 得到.
默认情况下 Ambient 和 Emissive 从 Material 得到, Diffuse 和 Specular 从 Vertex 得到.这时你设置 Material 的 Diffuse 和 Specular 是没用的.在每帧的颜色混合过程中,我们可以在 Set Texture Stage State?中指定 Alpha Op, Color Op,在 Set Render State 中指定 Src Blend 和 Dest Blend,它们互相是什么关系?
答:Alpha 和 Color 信息从哪里来? 可以来自于 Vertex, Material, Texture.
Alpha 和 Color 信息到哪里去? 我们最终的视觉效果,也就是 Frame Buffe r 中的像素点.
在 Frame Buffe r 的 Alpha 混合的过程中,我们可以指定各种各样的混合公式,这通过指定 Src Blend 和 Dest Blend 实现.
例如 DX默认的混合公式:
Final Color = Src Color * Src Alpha + Dest Color * (1-Src Alpha)
这实际上是指定 Src Blend = D3DBLEND_S RCALPHA; Dest Blend = D3DBLEND_I NVSRCALPHA?.
而 Src Blend 和 Dest Blend 这两个因数,无非来自于以下四个可能的来源.
Src Color, Src Alpha, Dest Color, Dest Alpha.
这四个因素本身可以取反,如 Inv Src Alpha. 再加上 Zero 和 One,就形成了各种各样的混合方式.
Dest Color, Dest Alpha 的来源显然是 Frame Buffe r 目前的 Pixel 数据,那么 Src Color, Src Alpha 呢?它们来源于纹理混合的 Alpha Op, Color Op.
以 Alpha 为例,假设指定 Alpha Arg1=Texture, Alpha Arg2=Diffuse, Alpha Op=Modulate,那么该点的 Alpha 值实际上是由贴图的 Alpha 通道的 Alpha 值,与 Diffuse 色的 Alpha 值相乘得到.
而 Diffuse 的来源又可以是 Vertex 或者 Material.(参看光照计算)
Color 的情况一样,只不过来源为贴图的颜色通道,和 Diffuse 的 Color 值.
总结一下:
对于 Alpha 或者 Color:
Vertex/Material —| blend
|——-| blend
Texture ———–| |——-Final Pixel?
Frame Buffe r—————-|
注意:
Texture 的 Blend 公式,只对当前描画的 Primitive 有效,而 Frame Blend?公式,则对所有 Primitive 都有作用.
为了进行 Alpha Blend,当然要先把 Enable Alpha Blending 打开,否则…几种 Alpha Blend 方式对应的实际含义是什么?
答:通过 Alpha Blend 可以实现非常多的常见特效,比如火,烟,云雾,爆炸等等.与粒子系统也有着非常密切的关系.而一切特效,无非都是通过指定不同的 Alpha 混合方式实现的.
打个比方,如果要实现火的效果,首先 Texture 上应该有 Alpha 通道,然后把 Diffuse 的 Alpha 和 Color 都指定为255.
此时
Alpha Arg1=Texture, Alpha Arg2=Diffuse, Alpha Op=Modulate
Color Arg1=Texture, Color Arg2=Diffuse, Color Op=Modulate
Src Blend = Src Alpha, Dest Blend = One
就可以了.结合粒子系统,你会看到耀眼的火光把屏幕照亮.
而且这种 Frame Blend?方式还有一个优点:因为 Dest Blend=One,所以混合顺序不影响描画结果.对于带 Alpha 粒子 Z排序通常是比较麻烦的,利用这个公式可以避免这一点.
又比如:
Src Blend = Src Alpha, Dest Blend = Inv Src Alpha 对应单色滤镜.
Src Blend = Src Color, Dest Blend = Inv Src Color 对应彩色滤镜.
总之可能实现的效果非常多,各位不妨试试看各种有趣的组合,这里就不多说了.Alpha Test 和 Alpha Blend?有什么区别? Alpha Blend?可以完全取代 Alpha Test 吗?
答:Alpha Test 指的是,对于 Src Alpha 值(参看上面 Alpha Blend 的介绍),与某个参考值进行比较,如果不满足某种条件,那么该点就不会被描画.
虽然 Alpha Test 也利用到了 Src Alpha,但是却不是用来混合.
Alpha Test 可以实现镂空(比如2D中经典的透明色问题),消除 Texture 拉伸引起的黑边等效果,它和 Alpha Blend?不是等价的, Alpha Blend?也不能完全代替 Alpha Test.
举一个两者可以互相等价的例子:
假如有一个 Bill Board 显示的树.它的 Texture 具有 Alpha 通道,而且透明部分的 Alpha=0,其余部分=255.
那么设定 Alpha Test 参考值为0,比较公式为 Not Equal,就可以实现透明色.
有趣的是,这个结果和采用 Alpha Blend?得到的结果相同.
可是,如果 Texture 的 Alpha 通道有 Alpha 渐变,那么 Alpha Test 就显得力不从心了…
理解了 Alpha Test 的基本思想,就可以很容易理解 Depth Test 和 Stencil Test.Texture Sampler Mode 中,可以分别对 MIN, MAG, MIP指定 Point 和 Linear,它们可以有哪些组合?各代表什么意义?
答:在纹理映射的过程中,插值得到的 Texel 的地址一般都不是一个整数,而是个小数.也就是没有一个 Texel 能够和这个地址精确对应.
怎么办?默认的方式是采用 Nearest Point Sample,在这种方式下,会找到最近的 Texel,直接作为最终结果.
下边举个例子,在此之前,顺便提下 Texture Add ress Mode.分为3种:Wrap, Clamp, Mirror, Border
不太严谨地表示下:
Wrap: EEEEEE (顺延下去)
Clamp: E===== (拉伸出去)
Mirror: E3E3E3 (顺延且不断取反)
Border: E????? (你想填啥色就填啥色)
还有, U的范围[0.0, 1.0],对应到水平具有 N个 Texel 的贴图,范围就是[-0.5, N-0.5].
假 设现在取 Wrap 方式,那么对于一个 U值0.999,按照 Nearest Point Sample,取到的 Texel 就是贴图的最右边的那一点,而永远 不会是贴图最左边的那个点.这时如果下一个插出的 U值对应到贴图最左边的第二个点.那么就产生了跳跃,贴图效果就会有断裂感.
当贴图比被贴图的表面大(Texel 采样不足),或者小很多时(Texel 过度采样),类似结果尤其明显.
现在 Linear Sample 就很容易解释:对于一个不能精确对应的 Texel 地址,我们取以下四个 Texel:
Nearest Point 上,下,左,右.
并计算 Weight(权值):$$
\begin{align}
W1 &= (1 - Ufrac) * (1 - Vfrac)\
W2 &= Ufrac * (1 - Vfrac)\
W3 &= (1 - Ufrac) * Vfrac\
W4 &= Ufrac * Vfrac
\end{align}
$$而混合出最终的结果.
这就是 Linear Sample.
Nearest Point Sample 和 Linear Sample 都分别可以应用于 MIN(贴图比被贴图的表面大), MAG(贴图比被贴图的表面小)方式上,产生想要的结果.
MIP的情况有所不同.
首先 MIP是指 Mip Map.什么是 Mip Map 呢?
假设你看着 CS的一面墙,墙上有花纹.
现在你向这面墙走近,是不是觉得本来细致的花纹变成了大的色斑?
现在你离开这面墙走远,是不是觉得花纹好像揉皱了看不清楚?
其实这个道理还是 Texel 采样不足和 Texel 过度采样.同一个表面,在不同的距离观察,应该采用不同分辨率和精度级别的贴图.
于是我们从具有最大精度的贴图开始,逐步降低分辨率(通常是长宽除2),直到到达最低分辨率(通常是8级),这样产生的一组贴图,就称为 Mip Map.
注意 Mip Map 会同时提高渲染效率和渲染效果,而付出在于 Memory.
对于 MIP指定 Nearest Point Sample,意味着你将直接选择一个最接近的精度级别的 Mip Map 作为贴图,然后再应用上面提过的方式进行映射.
对于 MIP指定 Linear Sample,意味着你将选择两个最接近的精度级别的 Mip Map 作为贴图,然后再应用上面提过的方式进行映射,然后结果再根据权值再混合.
这是最高质量的纹理映射方式,有时被戏称为”三线滤波”.(MIN:LINEAR, MAG:LINEAR, MIP:LINEAR)全屏抗锯齿和 Texture Sam pler Mode 有关系吗? 和 Montion Blu r 有关系吗?
Cull_CW, Cull_CCW是干什么用的? 不做 Cull 行吗? Cull 和 Clip 有区别吗?
Shading Mod e 可以指定 FLAT, GOURAUD, PHONG,这发生在渲染过程中的哪一步? 和 Fill Mode 有什么关系?
UV有什么用?UV和 ST有什么区别?UV在光栅化时需要被插值吗?插值完了再做什么?
Vertex Shad er 和 Pixel Shade r 分别对应于 Fixed Pipel ine 的哪些步骤? 先搞清楚 Fixed Pipel ine 对进一步研究 Programmab le Pipeline?很有好处,你同意吗?为什么?
如果上面的问题你都搞清楚了, 你能在心中清晰地描述出每一个三角形, 是如何从刚开始的模型数据, 成为屏幕上的象素点?
BSP, OSP, Voxel…它们处于 Render Pipe line 的什么地位上?
现在,请用 Vertex 和 Pixel Shade r,实现出和 DX9的 Fixed Pipel ine 一样的功能.
思考第19个问题,然后说说看,这其中可以玩哪些花招?(Shader 是用来玩的…)