学习目标
- 了解几个用以表达真实场景的标志和2D图像的深度空间;
- 学习在Direct3D中如何表示3D物体;
- 学习如何模拟虚拟摄像机;
- 理解渲染流水线:如何用几何描述的3D场景渲染出2D图像;
1 3D幻觉
如何在2D平面(显示器)上产生3D场景的幻觉:
1、根据与摄像机的距离缩放;
2、遮挡关系;
3、光照;
4、阴影
2 模型的表示
一个模型是由三角形网格近似模拟,常用的建模工具有:
3D Studio Max (http://usa.autodesk.com/3ds-max/)
LightWave 3D (https://www.lightwave3d.com/)
Maya (http://usa.autodesk.com/maya/)
Softimage|XSI (www.softimage.com)
Blender (www.blender.org/) 对业余爱好者比较好,因为它开源并且免费
3 颜色计算基础
计算机显示器通过发射红绿蓝混合的光线,在人眼中产生颜色:
其每种光线的强度在0~1之间。
3.1 颜色的运算
部分向量的运算也可以应用到颜色的运算,比如向量的加法:
(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)
标量相乘:
0.5(1, 1, 1) = (0.5, 0.5, 0.5)
但是向量的点积和叉积都不能用于颜色的运算,颜色相乘有自己的计算公式:分量相乘(modulation or componentwise multiplication):
这个运算主要用以光照计算中。
颜色值在进行运算后可能会超出0~1的范围,需要把他们固定到0到1之间(大于1的等于1,小于0的等于0)。
3.2 128位的颜色
它在基本颜色上增加了一个透明度组件(alpha component),可以用一个4D向量来表示,所以就可以使用XMVECTOR类型来表示,这样就可以使用DirectX数学库函数利用SIMD操作的好处进行加减和标量相乘;对于分量相乘运算,DirectX数学库中提供下面的方法:
XMVECTOR XM_CALLCONV XMColorModulate( // Returns c1 ⊗ c2
FXMVECTOR C1,
FXMVECTOR C2);
3.3 32位颜色
在32位颜色中,每个字节表示一个颜色组件,所以每个颜色有255种不同的值。在DirectX数学库中((#include
<DirectXPackedVector.h>)提供了下面的结构来保存32位颜色:
namespace DirectX
{
namespace PackedVector
{
// 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]
struct XMCOLOR
{
union
{
struct
{
uint8_t b; // Blue: 0/255 to 255/255
uint8_t g; // Green: 0/255 to 255/255
uint8_t r; // Red: 0/255 to 255/255
uint8_t a; // Alpha: 0/255 to 255/255
};
uint32_t c;
};
XMCOLOR() {}
XMCOLOR(uint32_t Color) : c(Color) {}
XMCOLOR(float _r, float _g, float _b, float _a);
explicit XMCOLOR(_In_reads_(4) const float *pArray);
operator uint32_t () const { return c; }
XMCOLOR& operator= (const XMCOLOR& Color) { c = Color.c; return *this; }
XMCOLOR& operator= (const uint32_t Color) { c = Color; return *this; }
};
} // end PackedVector namespace
} // end DirectX namespace
DirectX数学库提供了XMCOLOR转化为XMVECTOR的函数:
XMVECTOR XM_CALLCONV PackedVector::XMLoadColor(
const XMCOLOR* pSource);
同时也提供了XMVECTOR转化为XMCOLOR的函数:
void XM_CALLCONV PackedVector::XMStoreColor(
XMCOLOR* pDestination,
FXMVECTOR V);
通常情况下,128位颜色用来进行高精度的计算,这样算法上的错误积累就少很多;最终颜色一般保存为32位(在back buffer中也通常是32位),当前的物理显示设备无法体现128位颜色的好处。
4 概述渲染流水线
箭头的指向代表可以读取/写入资源:
5 输入装配阶段
输入装配阶段(IA)从内存中读取数据(顶点和索引)来装配称几何基元(三角形、线段等)。
5.1 顶点
顶点不仅包含基本的位置信息,也可以包含其他数据比如法向量,UV值等。
5.2 基元的拓扑机构
顶点是通过顶点缓冲(vertex buffer)来绑定到渲染流水线的,顶点缓冲只是在一段连续的内存中保存一系列点点,它并不知道拓扑结构,所以就需要通过Direct3D指定拓扑结构:
void ID3D12GraphicsCommandList::IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY Topology);
typedef enum D3D_PRIMITIVE_TOPOLOGY
{
D3D_PRIMITIVE_TOPOLOGY_UNDEFINED = 0,
D3D_PRIMITIVE_TOPOLOGY_POINTLIST = 1,
D3D_PRIMITIVE_TOPOLOGY_LINELIST = 2,
D3D_PRIMITIVE_TOPOLOGY_LINESTRIP = 3,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST = 4,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP = 5,
D3D_PRIMITIVE_TOPOLOGY_LINELIST_ADJ = 10,
D3D_PRIMITIVE_TOPOLOGY_LINESTRIP_ADJ = 11,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ = 12,
D3D_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP_ADJ = 13,
D3D_PRIMITIVE_TOPOLOGY_1_CONTROL_POINT_PATCHLIST = 33,
D3D_PRIMITIVE_TOPOLOGY_2_CONTROL_POINT_PATCHLIST = 34,
.
.
.
D3D_PRIMITIVE_TOPOLOGY_32_CONTROL_POINT_PATCHLIST = 64,
} D3D_PRIMITIVE_TOPOLOGY;
后续的绘制调用(drawing calls)都将使用当前的拓扑结构,直到拓扑结构被改变:
mCommandList->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_LINELIST);
/* …draw objects using line list… */
mCommandList->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
/* …draw objects using triangle list… */
mCommandList->IASetPrimitiveTopology( D3D_PRIMITIVE_TOPOLOGY_TRIAN