6.1 顶点和输入布局

从§5.5.1回想一下,在Direct3D中的顶点可以由除了空间位置的其他数据组成。要创建一个自定义的顶点格式,我们首先创建一个拥有我们所选择的顶点数据的结构。例如,下面示出了两种不同类型的顶点格式; 1:包含位置和颜色,2:包含位置,法线和纹理坐标

struct Vertex1
{
	XMFLOAT3 Pos;
	XMFLOAT4 Color;
};
struct Vertex2
{
	XMFLOAT3 Pos;
	XMFLOAT3 Normal;
	XMFLOAT2 Tex0;
	XMFLOAT2 Tex1;
};

一旦我们定义了一个顶点结构,我们需要提供顶点结构的描述,以便Direct3D知道如何处理每个组件。这种描述是由Direct3D的输入布局(ID3D11InputLayout)的形式提供。一个输入布局由D3D11_INPUT_ELEMENT_DESC数组元素指定。D3D11_INPUT_ELEMENT_DESC数组的每个元素描述并且对应于在顶点结构中的一个组成部分。因此,如果在顶点结构有两个组成部分,那么相应的D3D11_INPUT_ELEMENT_DESC的数组将有两个元素。我们指的是D3D11_INPUT_ELEMENT_DESC数组作为输入布局描述。该D3D11_INPUT_ELEMENT_DESC结构定义如下:

typedef struct D3D11_INPUT_ELEMENT_DESC {
	LPCSTR SemanticName;
	UINT SemanticIndex;
	DXGI_FORMAT Format;
	UINT InputSlot;
	UINT AlignedByteOffset;
	D3D11_INPUT_CLASSIFICATION InputSlotClass;
	UINT InstanceDataStepRate;
} D3D11_INPUT_ELEMENT_DESC;

1. SemanticName:与元素相关联的字符串。这可以是任何有效的变量名。被用于在顶点着色器输入签名中映射元素;见图6.1。

2. SemanticIndex:附加到语义的索引。如图6.1,其中一个顶点结构可具有多余一个纹理坐标组;因此,我们可以添加索引来区分纹理坐标,而不是引入一个新的语义的名称。在着色器代码中语义没有指定索引意味着索引默认到0;例如,POSITION等同于POSITION0。

D3D11_INPUT_ELEMENT_DESC

3.Format:由DXGI_FORMAT枚举类型成员指定的顶点元素的格式(即数据类型);这里是使用格式一些常见的例子:

DXGI_FORMAT_R32_FLOAT // 1D 32-bit float scalar
DXGI_FORMAT_R32G32_FLOAT // 2D 32-bit float vector
DXGI_FORMAT_R32G32B32_FLOAT // 3D 32-bit float vector
DXGI_FORMAT_R32G32B32A32_FLOAT // 4D 32-bit float vector
DXGI_FORMAT_R8_UINT // 1D 8-bit unsigned integer scalar
DXGI_FORMAT_R16G16_SINT // 2D 16-bit signed integer vector
DXGI_FORMAT_R32G32B32_UINT // 3D 32-bit unsigned integer vector
DXGI_FORMAT_R8G8B8A8_SINT // 4D 8-bit signed integer vector
DXGI_FORMAT_R8G8B8A8_UINT // 4D 8-bit unsigned integer vector

4. InputSlot:指定输入插槽索引。 Direct3D的支持16个输入插槽(0-15索引)通过它可以适配顶点数据。例如,如果一个顶点由位置和颜色元素组成,则既可以通过一个单一的输入槽适配这两个元素,或者也可以分割元素,并通过第一输入槽适配位置元素和通过第二输入槽适配颜色元素。Direct3D将使用来自不同输入插槽中的元素以组装顶点。在这本书中,我们只使用一个输入插槽。

5. AlignedByteOffset:对于单输入槽,这是偏移量,以字节为单位,从C++顶点结构的开始到顶点组件的开始。例如,在下面的顶点结构,元素Pos有一个0字节偏移自其开始与顶点结构的开始重合;元素Normal有一个12字节的偏移,因为我们要跳过Pos的字节去获得Normal的开始;元素Tex0有一个24个字节的偏移,因为我们需要跳过Pos和Normal的字节到达Tex0的开始;元素Tex1有一个32字节偏移,因为我们需要跳过Pos,Normal和Tex0的字节去Tex1的开始。

struct Vertex2
{
	XMFLOAT3 Pos; // 0-byte offset
	XMFLOAT3 Normal; // 12-byte offset
	XMFLOAT2 Tex0; // 24-byte offset
	XMFLOAT2 Tex1; // 32-byte offset
};

6. InputSlotClass:现在指定为D3D11_INPUT_PER_VERTEX_DATA;另一选项是用于实例化高级技术。

7. InstanceDataStepRate:现在指定为0;其他值仅用于实例化的高级技术。对于前两个例子顶点结构,Vertex1和Vertex2,相应的输入布局描述将是:

D3D11_INPUT_ELEMENT_DESC desc1[] =
{
	{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
			D3D11_INPUT_PER_VERTEX_DATA, 0},
	{"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12,
			D3D11_INPUT_PER_VERTEX_DATA, 0}
};
D3D11_INPUT_ELEMENT_DESC desc2[] =
{
	{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,
			D3D11_INPUT_PER_VERTEX_DATA, 0},
	{"NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12,
			D3D11_INPUT_PER_VERTEX_DATA, 0},
	{"TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24,
			D3D11_INPUT_PER_VERTEX_DATA, 0},
	{"TEXCOORD", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 32,
			D3D11_INPUT_PER_VERTEX_DATA, 0}
};

一旦一个输入布局描述被指定,我们可以得到一个指向ID3D11InputLayout接口的指针,该接口表示输入的布局,使用ID3D11Device:: CreateInputLayout方法:

HRESULT ID3D11Device::CreateInputLayout(
	const D3D11_INPUT_ELEMENT_DESC *pInputElementDescs,
	UINT NumElements,
	const void *pShaderBytecodeWithInputSignature,
	SIZE_T BytecodeLength,
	ID3D11InputLayout **ppInputLayout);

1.pInputElementDescs:描述顶点结构D3D11_INPUT_ELEMENT_DESC元素的数组。

2.NumElements:在D3D11_INPUT_ELEMENT_DESC元素的数组元素的数量。

3.pShaderBytecodeWithInputSignature:一个指向顶点着色器的输入签名的着色器字节码的指针。

4.BytecodeLength:传递到前一个参数的顶点着色器签名数据的字节数。

5.ppInputLayout:返回指向创建的输入布局。

 

本文固定链接:http://www.oxox.work/web/directx11/vertices-input-layouts/ | 虚幻大学

 

 

 

发表评论

电子邮件地址不会被公开。