Introduction to 3D Game Programming with DirectX 11学习笔记 6 Direct3D中的绘制(二)顶点着色器
来源:互联网 发布:梦幻西游网络错误 编辑:程序博客网 时间:2024/05/14 11:28
下面是一个顶点着色器的示例,它的代码非常简单:
cbuffer cbPerObject { float4x4 gWVP; }; void VS(float3 iPosL : POSITION, float4 iColor : COLOR, out float4 oPosH : SV_POSITION, out float4 oColor : COLOR) { // 转换到齐次裁剪空间 oPosH = mul(float4(iPosL, 1.0f), gWVP); // 把顶点颜色直接传到像素着色器 oColor = iColor; }
着色器使用一种称为高级着色语言(High-Level Shading Language,简称HLSL)的脚本语言来编写,它的语法与C++相似,很容易就能学会。附录B提供了一些有关HLSL的简要概述。在本书中,我们将采用一种基于示例的方式讲解HLSL及着色器编程。也就是,根据贯穿本书的每个演示程序所涉及的技术讲解相关的HLSL概念。着色器通常保存在一种称为effect文件(.fx)的纯文本文件中。我们会在本章随后的小节中讨论effect文件,而现在我们主要讨论顶点着色器。
这里,顶点着色器是一个称为VS的函数。注意,你可以为顶点着色器指定任何有效的函数名。该顶点着色器包含4个参数;前两个是输入参数,后两个是输出参数(由out关键字表示)。HLSL没有类似于C++的引用和指针,所以当一个函数要返回多个值时,我们必须使用结构体或输出参数。
前两个输入参数对应于我们在顶点结构体中定义的数据成员。参数语义“:POSITION”和“:COLOR”用于将顶点结构体的数据成员映射为顶点着色器的输入参数,如图6.4所示。
图6.4 D3D11_INPUT_ELEMENT_DESC数组为每个顶点元素指定了一个相关的语义,而顶点着色器的每个参数也都带有一个附加语义。语义用于建立顶点元素和顶点着色器参数之间的对应关系。
输出参数也带有附加语义(“:SV_POSITION”和“:COLOR”)。这些语义用于将顶点着色器的输出数据映射为下一阶段(几何着色器或像素着色器)的输入数据。注意,SV_POSITION是一个特殊的语义(SV表示系统值,即system value的缩写)。它用于告诉顶点着色器该元素存储的是顶点位置。顶点位置的处理方式与其他顶点属性不同,因为它涉及到一些其他属性所没有的特殊运算,比如裁剪。若不是系统值,那么输出参数的语义名称可以是任何有效的语义名称。
该顶点着色器的代码非常简单。第一行通过与一个4×4矩阵gWorldViewProj相乘,将顶点位置从局部空间变换到齐次裁剪空间,矩阵gWorldViewProj是世界矩阵、观察矩阵和投影矩阵的组合矩阵:
// 转换到齐次裁剪空间oPosH = mul(float4(iPosL, 1.0f), gWorldViewProj);
构造函数语法“float4(iPosL, 1.0f)”用于创建4D向量,它相当于“float4(iPosL.x, iPosL.y, iPosL.z, 1.0f)”;**我们知道,顶点位置是一个点而不是一个向量,所以第4个分量应设为1(即w=1)。**float2和float3分别表示2D和3D向量。矩阵变量gWorldViewProj定义在一个常量缓冲区中,我们会在下一节讨论对它进行讨论。内置函数mul用于实现向量-矩阵乘法,它为不同维数的矩阵乘法定义了多个重载版本;例如,该函数可以实现4×4矩阵乘法、3×3矩阵乘法、或者1×3向量与3×3矩阵的向量-矩阵乘法。最后一行是将输入的颜色赋值给输出参数,把颜色传递给管线的下一阶段:
oColor = iColor;
我们可以使用结构体来重写上面的顶点着色器,实现相同的功能:
cbuffer cbPerObject { float4x4 gWVP; }; struct VS_IN { float3 posL : POSITION; float4 color : COLOR; }; struct VS_OUT { float4 posH : SV_POSITION; float4 color : COLOR; }; VS_OUT VS(VS_IN input) { VS_OUT output; output.posH = mul(float4(input.posL, 1.0f), gWVP); output.color = input.color; return output; }
注意:当没有几何着色器时,顶点着色器至少要实现投影变换,因为当顶点离开顶点着色器时(在没有几何着色器的情况下),硬件假定顶点位于投影空间。当包含一个几何着色器时,投影工作可以转嫁到几何着色器中完成。
注意:顶点着色器(或几何着色器)不执行透视除法;它只完成投影矩阵部分。透视除法会随后由硬件完成。
常量缓冲
在上一节的顶点着色器示例中包含如下代码:
cbuffer cbPerObject { float4x4 gWorldViewProj; };
这段代码定义了一个称为cbPerObject的cbuffer对象(constant buffer,常量缓冲)。常量缓冲只是一个用于存储各种变量的数据块,这些变量可以由着色器来访问。在本例中,常量缓冲区只存储了一个称为gWorldViewProj的4×4矩阵,它是世界矩阵、观察矩阵和投影矩阵的组合矩阵,用于将顶点从局部空间变换到齐次裁剪空间。在HLSL中,4×4矩阵由内置的float4x4类型表示;与之类似,要定义一个3×4矩阵和一个2×2矩阵,可以分别使用float3x4和float2x2类型。顶点着色器不能修改常量缓冲中的数据,但是通过effect框架(6.9节),C++应用程序代码可以在运行时修改常量缓冲中的内容。它为C++应用程序代码和effect代码提供了一种有效的通信方式。例如,因为每个物体的世界矩阵各不相同,所以每个物体的“WVP”组合矩阵也各不相同;所以,当使用上述顶点着色器绘制多个物体时,我们必须在绘制每个物体前修改gWorldViewProj变量。
通常的建议是根据变量修改的频繁程度创建不同的常量缓冲。比如,你可以创建下面的常量缓冲:
cbuffer cbPerObject { float4x4 gWVP; }; cbuffer cbPerFrame { float3 gLightDirection; float3 gLightPosition; float4 gLightColor; }; cbuffer cbRarely { float4 gFogColor; float gFogStart; float gFogEnd; };
在本例中,我们使用了3个常量缓冲区。第1个常量缓冲区存储“WVP”组合矩阵。该变量随物体而定,所以它必须在物体级别上更新。也就是,当我们每帧渲染100个物体时,每帧都要对这个变量更新100次。第2个常量缓冲存储了场景中的灯光变量。这里,我们假设要生成灯光动画,所以些变量必须在每帧中更新一次。最后一个常量缓冲存储了用于控制雾效的变量。这里,我们假设场景的雾效变化频率很低(例如,在游戏的一个特定时段中变化一次)。
对常量缓冲进行分组是为了提高运行效率。当一个常量缓冲区被更新时,它里面的所有变量都会同时更新;所以,根据它们的更新频率进行分组,可以减少不必要的更新操作,提高运行效率。
- Introduction to 3D Game Programming with DirectX 11学习笔记 6 Direct3D中的绘制(二)顶点着色器
- Introduction to 3D Game Programming with DirectX 11学习笔记 6 Direct3D中的绘制(三)像素着色器
- Introduction to 3D Game Programming with DirectX 11学习笔记 6 Direct3D中的绘制(一)
- Introduction to 3D Game Programming with DirectX 11学习笔记 6 Direct3D中的绘制(四)渲染状态
- Introduction to 3D Game Programming with DirectX 11学习笔记 4.1 初识Direct3D
- Introduction to 3D Game Programming with DirectX 11学习笔记 4.2Direct3D进行初始化
- Introduction to 3D Game Programming with DirectX 11学习笔记 5 渲染管线(二)
- Introduction to 3D Game Programming with DirectX 11学习笔记 5 渲染管线(一)
- Introduction to 3D Game Programming with DirectX 11学习笔记 5 渲染管线(三)
- 学习《Introduction to 3D Game Programming with DirectX 11》
- Introduction to 3D Game Programming with DirectX 11学习笔记 1~3章
- Introduction to 3D Game Programming with DirectX 11学习笔记 4.3 计时和动画
- Introduction to 3D Game Programming with DirectX 11学习笔记 4.4 演示程序框架
- Introduction to 3D Game Programming with DirectX 9.0
- 终于译完了《Introduction to 3D Game Programming with DirectX 11》
- Game Programming with DirectX -- 05[3D中的太阳]
- Game Programming with DirectX -- 01[初识Direct3D]
- Game Programming with DirectX -- 01[初识Direct3D]
- arm概念
- 谷歌浏览器跨域问题
- leetcode:44. Wildcard Matching
- 安装yii2的过程中可能会出现的问题
- Python学习-语句、语法
- Introduction to 3D Game Programming with DirectX 11学习笔记 6 Direct3D中的绘制(二)顶点着色器
- Unity3D 大型游戏 最后一站 源码 部分重点匹配战斗(三)(12)
- 开发史上最强模块加载工具
- 软件需求规格说明书模板
- iOS USB调试
- js在设置角标的时候因为浏览器默认样式(User Agent Stylesheet)不起作用
- Java--GUI
- C++ 运算符重载 operator xxx * ()
- leon_hm android状态栏颜色修改