DirectX11 顶点和顶点布局

2023-12-20 09:08
文章标签 布局 顶点 directx11

本文主要是介绍DirectX11 顶点和顶点布局,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

顶点和顶点布局
1. 如何描述顶点?
5.5.1节已经讲过,在Direct3D中,顶点由空间位置和各种附加属性组成,Direct3D可以让我们灵活地建立属于我们自己的顶点格式;换句话说,它允许我们定义顶点的分量。要创建一个自定义的顶点格式,我们必须先创建一个包含顶点数据的结构体。例如,下面是两种不同类型的顶点格式;一个由位置和颜色组成,另一个由位置、法线和纹理坐标组成。

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

2. 顶点布局的作用是什么?
在定义了顶点结构体之后,我们必须设法描述该顶点结构体的分量结构,使Direct3D知道该如何使用每个分量。这一描述信息是以输入布局(ID3D11InputLayout)的形式提供给Direct3D的。

2. 顶点布局如何创建?
输入布局是一个D3D11_INPUT_ELEMENT_DESC数组。D3D11_INPUT_ELEMENT_DESC数组中的每个元素描述了顶点结构体的一个分量。比如,当顶点结构体包含两个分量时,对应的D3D11_INPUT_ELEMENT_DESC数组会包含两个元素。我们将D3D11_INPUT_ELEMENT_DESC称为输入布局描述(input layout description)。D3D11_INPUT_ELEMENT_DESC结构体定义如下:

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

1.SemanticName:一个与元素相关的字符串。它可以是任何有效的语义名。语义(semantic)用于将顶点结构体中的元素映射为顶点着色器参数(参见图6.1)。
这里写图片描述
(图6.1 顶点结构体中的每个元素分别由D3D11_INPUT_ELEMENT_DESC数组中的对应元素描述。语义名和语义索引提供了一种将顶点元素映射为顶点着色器参数的方法。)

2.SemanticIndex:附加在语义上的索引值。图6.1说明了使用该索引的原因;举例来说,当顶点结构体包含多组纹理坐标时,我们不是添加一个新的语义名,而是在语义名的后面加上一个索引值。在着色器代码中没有指定索引的语义默认索引为0,例如,在图6.1中的POSITION相当于POSITION0。

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:指定当前元素来自于哪个输入槽(input slot)。Direct3D支持16个输入槽(索引依次为 0到15),通过这些输入槽我们可以向着色器传入顶点数据。例如,当一个顶点由位置元素和颜色元素组成时,我们既可以使用一个输入槽传送两种元素,也可以将两种元素分开,使用第一个输入槽传送顶点元素,使用第二个输入槽传送颜色元素。Direct3D可以将来自于不同输入槽的元素重新组合为顶点。在本书中,我们只使用一个输入槽,但是在本章结尾的练习2中我们会引导读者做一个使用两个输入槽的练习。

5.AlignedByteOffset:对于单个输入槽来说,该参数表示从顶点结构体的起始位置到顶点元素的起始位置之间的字节偏移量。例如在下面的顶点结构体中,元素Pos的字节偏移量为0,因为它的起始位置与顶点结构体的起始位置相同;元素Normal的字节偏移量为12,因为必须跳过由Pos占用的字节才能到达Normal的起始位置;元素Tex0的字节偏移量为24,因为必须跳过由Pos和Normal占用的字节才能到达Tex0的起始位置;元素Tex1的字节偏移量为32,因为必须跳过由Pos,Normal和Tex0占用的字节才能到达Tex1的起始位置。

struct Vertex2
{XMFLOAT3 Pos;       // 0-byte offsetXMFLOAT3 Normal;   // 12-byte offsetXMFLOAT2 Tex0;      // 24-byte offsetXMFLOAT2 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}
};

指定了输入布局描述之后,我们就可以使用ID3D11Device::CreateInputLayout方法获取一个表示输入布局的ID3D11InputLayout接口的指针:

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:返回创建后的ID3D11InputLayout指针。

我们需要进一步解释一下第3个参数的含义。本质上,顶点着色器以一组顶点元素作为它的输入参数——也就是所谓的输入签名(input signature)。自定义顶点结构体中的元素必须被映射为与它们对应的顶点着色器参数,图6.1解释了这一问题。通过在创建输入布局时传入顶点着色器签名,Direct3D在创建时就可以验证输入布局是否与输入签名匹配,并建立从顶点结构体到着色器参数之间的映射关系。一个ID3D11InputLayout对象可以在多个参数完全相同的着色器中重复使用。

假设有下列输入参数和顶点结构:

VertexOut VS(float3 Pos:POSITION, float4 Color:COLOR,float3 Normal: NORMAL){ }
struct Vertex
{XMFLOAT3  Pos ;XMFLOAT4  Color;
};

这样会产生错误,VC++的调试输出窗口会显示以下信息:

D3D11:ERROR:ID3D11Device::CreateInputLayout:The provided input
signature expects to read an element with SemanticName/Index:
‘NORMAL’/0, but the declaration doesn’t provide a matching name.

假如顶点结构和输入参数与输入元素匹配,但类型不同:

VertexOut VS(int3 Pos:POSITION, float4 Color:COLOR) { }
struct Vertex
{
XMFLOAT3 Pos;
XMFLOAT4 Color;
} ;

这样做是可行的,因为Direct3D允许输入寄存器中的字节被重新解释。但是,VC ++调试输出窗口会显示以下信息:

D3D11:WARNING:ID3D11Device::CreateInputLayout:The provided input
signature expects to read an element with SemanticName/Index:
‘POSITION’/0 and component(s) of the type ‘int32’. However,the
matching entry in the InputLayout declaration, element[0],
specifies mismatched format:’R32G32B32_FLOAT’.This is not an error,
since behavior is well defined :The element format determines what
data conversion algorithm gets applied before it shows up in a
shader register.Independently,the shader input signature defines
how the shader will interpret the data that has been placed in its
input registers,with no change in the bits stored.It is valid for
the application to reinterpret data as a different type once it is
in the vertex shader,so this warning is issued just in case reinte rpretation was not intended by the author.

下面的代码说明了该如何调用ID3D11Device::CreateInputLayout方法。注意,这些代码涉及了一些我们还未讨论的内容(比如ID3D11Effect)。本质上,一个effect可以封装一个或多个pass,而每个pass都会与一个顶点着色器相连。所以,我们可以从effect中得到有关pass的描述信息(D3D11_PASS_DESC),然后再从中得到顶点着色器的输入签名。

ID3D11Effect* mFX;
ID3D11EffectTechnique* mTech;
ID3D11InputLayout* mVertexLayout;
/* ...create the effect... */
mTech = mFX->GetTechniqueByName("Tech");
D3D11_PASS_DESC PassDesc;
mTech->GetPassByIndex(0)->GetDesc(&PassDesc);
HR(md3dDevice->CreateInputLayout(vertexDesc, 4,PassDesc.pIAInputSignature, PassDesc.IAInputSignatureSize,&mVertexLayout));

创建了输入布局对象之后,它不会自动绑定到设备上。我们必须调用下面的语句来实现绑定:

ID3D11InputLayout* mVertexLayout;
/* ...create the input layout... */
md3dImmediateContext->IASetInputLayout(mVertexLayout);

如果你打算用一个输入布局来绘制一些物体,然后再使用另一个的布局来绘制另一些物体,那你必须按照下面的形式来组织代码:

md3dImmediateContext->IASetInputLayout(mVertexLayout1);
/* ...draw objects using input layout 1... */
md3dImmediateContext->IASetInputLayout(mVertexLayout2);
/* ...draw objects using input layout 2... */

换句话说,当一个ID3D11InputLayout对象被绑定到设备上时,如果不去改变它,那么它会始终驻留在那里。

这篇关于DirectX11 顶点和顶点布局的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/515482

相关文章

CSS3 最强二维布局系统之Grid 网格布局

《CSS3最强二维布局系统之Grid网格布局》CS3的Grid网格布局是目前最强的二维布局系统,可以同时对列和行进行处理,将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,本文介... 深入学习 css3 目前最强大的布局系统 Grid 网格布局Grid 网格布局的基本认识Grid 网

CSS弹性布局常用设置方式

《CSS弹性布局常用设置方式》文章总结了CSS布局与样式的常用属性和技巧,包括视口单位、弹性盒子布局、浮动元素、背景和边框样式、文本和阴影效果、溢出隐藏、定位以及背景渐变等,通过这些技巧,可以实现复杂... 一、单位元素vm 1vm 为视口的1%vh 视口高的1%vmin 参照长边vmax 参照长边re

CSS3中使用flex和grid实现等高元素布局的示例代码

《CSS3中使用flex和grid实现等高元素布局的示例代码》:本文主要介绍了使用CSS3中的Flexbox和Grid布局实现等高元素布局的方法,通过简单的两列实现、每行放置3列以及全部代码的展示,展示了这两种布局方式的实现细节和效果,详细内容请阅读本文,希望能对你有所帮助... 过往的实现方法是使用浮动加

HarmonyOS学习(七)——UI(五)常用布局总结

自适应布局 1.1、线性布局(LinearLayout) 通过线性容器Row和Column实现线性布局。Column容器内的子组件按照垂直方向排列,Row组件中的子组件按照水平方向排列。 属性说明space通过space参数设置主轴上子组件的间距,达到各子组件在排列上的等间距效果alignItems设置子组件在交叉轴上的对齐方式,且在各类尺寸屏幕上表现一致,其中交叉轴为垂直时,取值为Vert

POJ3041 最小顶点覆盖

N*N的矩阵,有些格子有物体,每次消除一行或一列,最少要几次消灭完。 行i - >列j 连边,表示(i,j)处有物体,即 边表示 物体。 import java.io.BufferedReader;import java.io.InputStream;import java.io.InputStreamReader;import java.io.PrintWriter;impo

lvgl8.3.6 控件垂直布局 label控件在image控件的下方显示

在使用 LVGL 8.3.6 创建一个垂直布局,其中 label 控件位于 image 控件下方,你可以使用 lv_obj_set_flex_flow 来设置布局为垂直,并确保 label 控件在 image 控件后添加。这里是如何步骤性地实现它的一个基本示例: 创建父容器:首先创建一个容器对象,该对象将作为布局的基础。设置容器为垂直布局:使用 lv_obj_set_flex_flow 设置容器

Apache Tiles 布局管理器

陈科肇 =========== 1.简介 一个免费的开源模板框架现代Java应用程序。  基于该复合图案它是建立以简化的用户界面的开发。 对于复杂的网站,它仍然最简单,最优雅的方式来一起工作的任何MVC技术。 Tiles允许作者定义页面片段可被组装成在运行一个完整的网页。  这些片段,或Tiles,可以用于为了降低公共页面元素的重复,简单地包括或嵌入在其它瓦片,制定了一系列可重复使用

【CSS in Depth 2 精译_023】第四章概述 + 4.1 Flexbox 布局的基本原理

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第一章 层叠、优先级与继承(已完结) 1.1 层叠1.2 继承1.3 特殊值1.4 简写属性1.5 CSS 渐进式增强技术1.6 本章小结 第二章 相对单位(已完结) 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性2.7 本章小结 第三章 文档流与盒模型(已

ConstraintLayout布局里的一个属性app:layout_constraintDimensionRatio

ConstraintLayout 这是一个约束布局,可以尽可能的减少布局的嵌套。有一个属性特别好用,可以用来动态限制宽或者高app:layout_constraintDimensionRatio 关于app:layout_constraintDimensionRatio参数 app:layout_constraintDimensionRatio=“h,1:1” 表示高度height是动态变化

OPENGL顶点数组, glDrawArrays,glDrawElements

顶点数组, glDrawArrays,glDrawElements  前两天接触OpenGL ES的时候发现里面没有了熟悉的glBegin(), glEnd(),glVertex3f()函数,取而代之的是glDrawArrays()。有问题问google,终于找到答案:因为OpenGL ES是针对嵌入式设备这些对性能要求比较高的平台,因此把很多影响性能的函数都去掉了,上述的几个函数都被移除了。接