在csdn博客上看到这篇文章DirectX11--HLSL中矩阵的内存布局和mul函数探讨
通过对这篇文章的学习,大致了解了矩阵内存布局和mul函数的使用情况,为了让自己以后能快速理解这篇博文的知识点,所以特别写了这篇博文来总结自己对博文的一些理解:
假设我们在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中的矩阵变量如何解析寄存器的数据,和矩阵变量前面的声明标识有关系。
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]寄存器保存的数据。
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中使用矩阵数据不受这个标识的影响。
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博客):
经过组合,就一共有四种能够正常绘制的情况:
可参考博文:矩阵:行主序、列主序、行向量、列向量