Direct3D 中的顶点可以存储其他属性数据。为了创建自定义的顶点格式,首先要创建一个结构体来容纳选定的顶点数据。
例如:
struct Vertex1 // 位置和颜色信息组成
{
XMFLOAT3 Pos;
XMFLOAT4 Color;
};
struct Vertex2 // 位置、法向量以及两组 2D 纹理坐标组成
{
XMFLOAT3 Pos;
XMFLOAT3 Normal;
XMFLOAT2 Tex0;
XMFLOAT2 Tex1;
};
定义了顶点结构体之后,我们还需要向 Direct3D 提供该顶点结构体的描述,使它了解应怎样来处理结构体中的每个成员。用户提供给 Direct3D 的这种描述被称为输入布局描述 (input layout description),用结构体 D3D12_INPUT_LAYOUT_DESC 来表示。
typedef struct D3D12_INPUT_LAYOUT_DESC
{
const D3D12_INPUT_ELEMENT_DESC *pInputElementDescs;
UINT NumElements;
} D3D12_INPUT_LAYOUT_DESC;
输入布局描述实由两部分组成:一个 D3D12_INPUT_ELEMENT_DESC 元素构成的数组,以及该数组的元素数量。
D3D12_INPUT_ELEMENT_DESC 数组中的元素依次描述了顶点结构体中所对应的成员。这就是说,如果某顶点结构体中有两个成员,那么与之对应的 D3D12_INPUT_ELEMENT_DESC 数组也将存有两个元素。D3D12_INPUT_ELEMENT_DESC 结构体的定义如下:
typedef struct D3D12_INPUT_ELEMENT_DESC
{
LPCSTR SemanticName;
UINT SemanticIndex;
DXGI_FORMAT Format;
UINT InputSlot;
UINT AlignedByteOffset;
D3D12_INPUT_CLASSIFICATION InputSlotClass;
UINT InstanceDataStepRate;
} D3D12_INPUT_ELEMENT_DESC;
1.SemanticName: 一个与元素相关联的特定字符串,我们称之为语义 (semantic),它传达了元素的预期用途。该参数可以是任意合法的语义名。通过语义即可将顶点结构体 (struct Vertex) 中的元素与顶点着色器输入签名 (vertex shader input signature,signature: 着色器的输入或输出参数列表) 中的元素一一映射起来。
2.SemanticIndex: 附加到语义上的索引。
3.Format: 在 Direct3D 中,要通过枚举类型 DXGI_FORMAT 中的成员来指定顶点元素的格式 (即数据类型)。常用的格式:
DXGI_FORMAT_R32_FLOAT // 1D 32位浮点标量
DXGI_FORMAT_R32G32_FLOAT // 2D 32位浮点向量
DXGI_FORMAT_R32G32B32_FLOAT // 3D 32位浮点向量
DXGI_FORMAT_R32G32B32A32_FLOAT // 4D 32位浮点向量
DXGI_FORMAT_R8_UINT // 1D 8位无符号整型标量
DXGI_FORMAT_R16G16_SINT // 2D 16位有符号整型向量
DXGI_FORMAT_R32G32B32_UINT // 3D 32位无符号整型向量
DXGI_FORMAT_R8G8B8A8_SINT // 4D 8位有符号整型向量
DXGI_FORMAT_R8G8B8A8_UINT // 4D 8位无符号整型向量
4.InputSlot: 指定传递元素所用的输入槽 (input slot index) 索引。Direct3D 共支持 16 个输入槽(索引值为 0~15),可以通过它们来向输入装配阶段传递顶点数据。目前我们只会用到输入槽 0(即所有的顶点元素都来自同一个输入槽)。
5.AlignedByteOffset: 在特定输入槽中,从 C++ 顶点结构体的首地址到其中某点元素起始地址的偏移量(用字节表示)。例如,在 Vertex2 中:
struct Vertex2
{
XMFLOAT3 Pos; // 偏移量为0字节
XMFLOAT3 Normal; // 偏移量为12字节
XMFLOAT2 Tex0; // 偏移量为24字节
XMFLOAT2 Tex1; // 偏移量为32字节
};
InputSlotClass: 我们暂且把此参数指定为 D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA。而另一选项(D3D12_INPUT_CLASSIFICATION_PER_INSTANCE_DATA) 则用于实现实例化 (instancing) 这种高级技术。
InstanceDataStepRate: 目前仅将此值指定为 0。若要采用实例化这种高级技术,则将此参数设为1。
前面的 Vertex1 和 Vertex2 这两个顶点结构体的例子来说,相应的输入布局描述为:
D3D12_INPUT_ELEMENT_DESC desc1[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}
};
D3D12_INPUT_ELEMENT_DESC desc2[] =
{
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0},
{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}
{"TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 32,
D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0}
};