@(读书笔记)[读书笔记, 技术交流]
本章主题是介绍渲染管线。通过给出摄像机的坐标和朝向,渲染管线根据一系列步骤搜集摄像机看到的2D图形。本章主要讲述理论方面,在下一章学习如何使用Direct3D绘制时结合实践。在讲述渲染管线前,我们提两点:首先,我们讨论一些3D元素,其次我们解释以下如何使用Direct3D代码以数学方式表现颜色。
在我们着手3D计算机图形学前,抛出一个简单的问题:我们如何把3D世界利用深度和体积在2D屏幕上展现出来?当然这个问题已经被画家们研究过了,本节我们大致描述以下使绘制在2D平面上的图像看起来像3D的几个关键技术。
假设你站在铁路中央,这条铁路笔直地通向远方,那么两条铁轨是保持平行的。但从你的视角出发,两条铁轨越远的地方看起来越靠近彼此,在无穷远处收敛。
在2D图像中,物体的彼此重叠可以推测出物体的深度顺序,被覆盖的物体相对深度大,距离更远。
在图(Figure 5.5)中,我们可以看到一个圆圈和一个光照球。所以我们认为光照和阴影是3D物体的重要组成元素。
最后图(Figure 5.6)展示了一个飞船和它的阴影。这阴影有两个重要的作用,展示了光源和飞船离地距离。
虽然这些都是我们的日常经验,但这几点在我们后续学习3D绘图中很有帮助。
我们用连续的三角网格来近似模拟一个实心的3D物体,越多的三角网格细节表现地越好,当然对性能要求也会增加,所以我们要在两者间找到一个平衡点。
我们也有一些专门的工具去绘制3D图形,并自动解析导出三角网格。如3DMax, LightWave 3D等。
显示器对每个像素显示时会混合红绿蓝三种颜色,通过对三种颜色的比例调整我们可以得到各式各样的颜色。
对于每种颜色的强度,以数字 [0,1] [ 0 , 1 ] 表示,0表示不含此颜色,1表示此颜色的最高强度。如(0.25, 0.67, 1.0)表示25%强度的红色,67%强度的绿色,100%强度的蓝色。所以我们用一个3D色彩向量 (r,g,b) ( r , g , b ) 表示红绿蓝的混合色,其中 0≤r,g,b,≤1 0 ≤ r , g , b , ≤ 1 。
颜色的运算
3D色彩向量和普通向量的运算方式相同,如
- 加法:
(0.0,0.5,0)+(0,0.0,0.25)=(0.0,0.5,0.25) ( 0.0 , 0.5 , 0 ) + ( 0 , 0.0 , 0.25 ) = ( 0.0 , 0.5 , 0.25 )
- 减法:
(1,1,1)–(1,1,0)=(0,0,1) ( 1 , 1 , 1 ) – ( 1 , 1 , 0 ) = ( 0 , 0 , 1 )
- 乘法
0.5(1,1,1)=(0.5,0.5,0.5) 0.5 ( 1 , 1 , 1 ) = ( 0.5 , 0.5 , 0.5 )
- 色彩运算没有点乘和叉乘,相对的有色彩专门的运算方式:调制modulation(或称分量方式componentwise),运算定义如下:
(cr,cg,cb)⊗(kr,kg,kb)=(crkr,cgkg,cbkb) ( c r , c g , c b ) ⊗ ( k r , k g , k b ) = ( c r k r , c g k g , c b k b )
我们常用 α α 组件(alpha component)来表示色彩的透明度。1表示不透明。因此我们可以用4维向量表示色彩, (r,g,b,α) ( r , g , b , α ) ,其中 0≤r,g,b,α≤1 0 ≤ r , g , b , α ≤ 1 。每一种颜色都以float存储,因此4种颜色共128位。在DirectX11中使用数据类型XMVECTOR表示,调制运算的函数调用如下:
XMVECTOR XMColorModulate(// Returns (c r , c g , c b , c a ) ⊗ (k r , k g , k b , k a )
FXMVECTOR C1, // (c r , c g , c b , c a )
FXMVECTOR C2); // (k r , k g , k b , k a )
为了用32位表示上述4种颜色(红,绿,蓝,透明),每种颜色占用8 bits,因此每种颜色能够表示的数据范围是 28=256 2 8 = 256 ,取值区间为 [0,255] [ 0 , 255 ] 。
// ARGB Color; 8-8-8-8 bit unsigned normalized integer components
// packed into a 32 bit integer. The normalized color is packed into
// 32 bits using 8 bit unsigned, normalized integers for the alpha,
// red, green, and blue components.
// The alpha component is stored in the most significant bits and the
// blue component in the least significant bits (A8R8G8B8):
// [32] aaaaaaaa rrrrrrrr gggggggg bbbbbbbb [0]
typedef struct _XMCOLOR
{
union
{
struct
{
UINT b : 8;
UINT g : 8;
UINT r : 8;
UINT a : 8;
};
UINT c;
};
#ifdef __cplusplus
_XMCOLOR() {};
_XMCOLOR(UINT Color) : c(Color) {};
_XMCOLOR(FLOAT _r, FLOAT _g, FLOAT _b, FLOAT _a);
_XMCOLOR(CONST FLOAT *pArray);
operator UINT () { return c; }
_XMCOLOR& operator = (CONST _XMCOLOR& Color);
_XMCOLOR& operator = (CONST UINT Color);
#endif // __cplusplus
以下展示128位色向32位色的转换:
(0.3,0.6,0.9,1.0)→(0.3⋅255,0.6⋅255,0.9⋅255,1.0⋅255)=(77,153,230,255) ( 0.3 , 0.6 , 0.9 , 1.0 ) → ( 0.3 · 255 , 0.6 · 255 , 0.9 · 255 , 1.0 · 255 ) = ( 77 , 153 , 230 , 255 )
反之亦然。
将XMCOLOR数据类型转换为XMVECTOR需使用函数
XMVECTOR XMLoadColor(CONST XMCOLOR* pSource);
且注意颜色在32位数据中的分布,从左到右依次是Alpha, Red, Green, Blue。
将XMVECTOR转换为XMCOLOR使用
VOID XMStoreColor(XMCOLOR* pDestination, FXMVECTOR V);
虽然使用128位色对于运算和精度更高,但当前物理设备能展示的色域有限,通常使用32位色作为存储结果。
网上发现此小节的翻译和彩图版。
给定摄像机在3D场景中的坐标和朝向,渲染管线将依照一个完整的流程收集相机能看到的2D图像。图(Figure 5.11)中解释了渲染管线的各个阶段与资源处理顺序。如输出合并阶段(the output merger stage)是把数据写入材质纹理中(如back buffer和depth/stencil buffer),图中还可以观察到此阶段的箭头是双向的(因为此阶段会读写GPU资源)。而多数阶段对GPU资源是只读的。后续我们会细讲每个阶段。
文章符号使用备注:
此图样中的内容是博主对书中的原文进行翻译摘录的。