DirectX11--HLSL中矩阵的内存布局和mul函数探讨

在csdn博客上看到这篇文章DirectX11--HLSL中矩阵的内存布局和mul函数探讨

通过对这篇文章的学习,大致了解了矩阵内存布局和mul函数的使用情况,为了让自己以后能快速理解这篇博文的知识点,所以特别写了这篇博文来总结自己对博文的一些理解:

  1. 数据如何从C++的DirectXMath中传入HLSL的matrix对象中:

假设我们在C++的DirectXMath中有矩阵数据如下(XMFLOAT4X4/XMMATRIX),矩阵数据在内存中是依次排列的:

m11,m12,m13,m14,m21,m22,m23,m24,m31,m32,m33,m34,m41,m42,m43,m44.

上述数据流传递到HLSL后,若是传递给cb的寄存器的前4个向量,那么它内存布局一定如下:

cb[0].xyzw = (m11, m12, m13, m14);
cb[1].xyzw = (m21, m22, m23, m24);
cb[2].xyzw = (m31, m32, m33, m34);
cb[3].xyzw = (m41, m42, m43, m44);

数据传入到寄存器以后,HLSL中的矩阵变量如何解析寄存器的数据,和矩阵变量前面的声明标识有关系。

  • 如果是行主序(row_major)矩阵,则把

cb[0]寄存器保存的数据解析为矩阵的第1行,

cb[1]寄存器保存的数据解析为矩阵的第2行,

cb[2]寄存器保存的数据解析为矩阵的第3行,

cb[3]寄存器保存的数据解析为矩阵的第4行.

例如HLSL中矩阵定义如下:

cbuffer cb : register(b0)
{
    (row_major) matrix g_World;//定义为行主序矩阵
}

则:

g_World[0]表示矩阵的第1行,读取到的数据为cb[0]寄存器保存的数据。

g_World[1]表示矩阵的第2行,读取到的数据为cb[1]寄存器保存的数据。

g_World[2]表示矩阵的第3行,读取到的数据为cb[2]寄存器保存的数据。

g_World[3]表示矩阵的第4行,读取到的数据为cb[3]寄存器保存的数据。

  • 如果是列主序(column_major)矩阵,则把

cb[0]寄存器保存的数据解析为矩阵的第1列,

cb[1]寄存器保存的数据解析为矩阵的第2列,

cb[2]寄存器保存的数据解析为矩阵的第3列,

cb[3]寄存器保存的数据解析为矩阵的第4列.

例如HLSL中矩阵定义如下:

cbuffer cb : register(b0)
{
     matrix g_World;//定义为列主序矩阵
}

则:

g_World矩阵的第1列为cb[0]寄存器保存的数据。

g_World矩阵的第2列为cb[1]寄存器保存的数据。

g_World矩阵的第3列为cb[2]寄存器保存的数据。

g_World矩阵的第4列为cb[3]寄存器保存的数据。

g_World[0]表示矩阵的第1行,读取到的数据为cb[0],cb[1],cb[2],cb[3]这4个寄存器中的第1个值.

g_World[1]表示矩阵的第2行,读取到的数据为cb[0],cb[1],cb[2],cb[3]这4个寄存器中的第2个值。

g_World[2]表示矩阵的第3行,读取到的数据为cb[0],cb[1],cb[2],cb[3]这4个寄存器中的第3个值。

g_World[3]表示矩阵的第4行,读取到的数据为cb[0],cb[1],cb[2],cb[3]这4个寄存器中的第4个值。

row_major和column_major标识只对数据从C++传入HLSL以后如何解析数据有影响,后续在HLSL中使用矩阵数据不受这个标识的影响。

  1. HLSL中mul是如何执行运算的

HLSL中mul函数执行运算和矩阵前面的标识符无关,它都是用第一个参数矩阵的行和第二个参数矩阵的列相乘来得到最终矩阵里面的某个值。

例如HLSL代码如下:

cbuffer cb : register(b0)
{
    row_major matrix gView;
    row_major matrix gProj;
}

// 顶点着色器
float4  VS(float3 PosL : POSITION): SV_POSITION
{
    row_major matrix viewProj = mul(gView, gProj);
    return mul(float4(pOut.PosW, 1.0f), viewProj);

}

viewProj._11=g_View矩阵的第一行和g_Proj矩阵的第一列点乘的值。

viewProj._mn=g_View矩阵的第m行和g_Proj矩阵的第n列点乘的值。

最终总结HLSL矩阵使用方法如下(参考:DirectX11--HLSL中矩阵的内存布局和mul函数探讨_X_Jun96的博客-CSDN博客):

经过组合,就一共有四种能够正常绘制的情况:

  1. C++代码端不进行转置,HLSL中使用row_major matrix(行主序矩阵),mul函数让向量放在左边(行向量),这样实际运算就是(行向量 X 行主序矩阵) 。这种方法易于理解,但是这样做dp4运算取矩阵的列很不方便,在HLSL中会产生用于转置矩阵的大量指令,性能上有损失。
  2. C++代码端进行转置,HLSL中使用matrix(列主序矩阵) ,mul函数让向量放在左边(行向量),这样就是(行向量 X 列主序矩阵),但C++这边需要进行一次矩阵转置,HLSL内部不产生转置 。这是官方例程所使用的方式,这样可以使得dp4运算可以直接取列主序矩阵的行,从而避免内部产生大量的转置指令。后续我会将教程的项目也使用这种方式。
  3. C++代码端不进行转置,HLSL中使用matrix(列主序矩阵),mul函数让向量放在右边(列向量),实际运算是(列主序矩阵 X 列向量)。这种方法的确可行,取列矩阵的行也比较方便,效率上又和2等同,就是HLSL那边的矩阵乘法都要反过来写,然而DX本身就是崇尚行主矩阵的,把OpenGL的习惯带来这边有点。。。
  4. C++代码端进行转置,HLSL中使用row_major matrix(行主序矩阵),mul函数让向量放在右边(列向量),实际运算是(行主序矩阵 X 列向量)。 就算这种方法也可以绘制出来,但还是很让人难受,比第2点还难受,我甚至不想去说它。

可参考博文:矩阵:行主序、列主序、行向量、列向量

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 《DirectX 3D HLSL 高级实例精讲》是一本关于图形编程技术的书籍,主要讲解了DirectX 3D的高级编程以及HLSL着色语言的使用。 这本书首先介绍了DirectX 3D的基本概念和原理,包括渲染管线、顶点和像素着色器以及纹理等。然后详细介绍了HLSL着色语言,包括语法、变量类型、常量缓冲区和输入输出布局等。通过深入理解HLSL,读者可以编写高效的着色器代码,实现更加逼真和优化的图形效果。 除了基础知识,该书还提供了一些高级实例,涵盖了可见性及遮挡剔除、阴影技术、光照模型、反射折射效果、法线贴图、粒子系统和后期处理等。每一个实例都详细介绍了实现思路和具体的代码实现,读者可以通过跟随实例学习如何使用DirectX 3DHLSL来实现各种复杂的图形效果。 这本书适合有一定图形编程基础的读者,特别是对DirectX 3DHLSL感兴趣的开发者。通过学习本书,读者可以深入了解DirectX 3DHLSL的原理和应用,掌握高级图形编程技术,提升自己在游戏开发、虚拟现实、计算机图形学等领域的能力。 总之,《DirectX 3D HLSL 高级实例精讲》是一本介绍DirectX 3DHLSL高级编程技术的实用指南,适合有一定图形编程基础的读者学习和参考。它详细讲解了基础原理和实例实现,读者可以通过学习本书提升自己在图形编程领域的能力。 ### 回答2: "DirectX 3D HLSL高级实例精讲" 是一本介绍DirectX 3DHLSL编程的高级实例教材。该PDF文件详细讲解了如何使用DirectX 3DHLSL编写高效的图形渲染程序。 该教材涵盖了多个实例,从基本的渲染技术到更高级的图形效果。它从介绍DirectX 3DHLSL的基础知识开始,然后深入探讨了渲染管线的不同阶段以及如何利用HLSL语言编写高级着色器来实现各种图形效果。 该PDF还提供了大量的代码实例和详细的解释,帮助读者理解和实践所学内容。它包括了如何创建3D对象、设置材质和光照效果、实现纹理映射、使用几何着色器和像素着色器等内容。同时,它还介绍了一些高级技术,如阴影算法、法线贴图、环境光遮蔽等,使读者能够进一步提升图形渲染的质量和效果。 通过学习这本教材,读者可以深入了解DirectX 3DHLSL的基本原理和技术,掌握如何使用它们来实现各种复杂的图形效果。无论是想要进一步学习图形渲染相关知识的专业人士,还是对图形编程感兴趣的爱好者,该教材都是一本值得阅读的参考书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值