Direct3D 11 和 2D:HLSL 中的乘法矩阵向量未给出正确结果
Direct3D 11 and 2D: multiplication matrix-vector in HLSL does not give the correct result
我仍在努力改进我的 Direct3D 11 二维测试程序,没有任何额外的库(参见 )。
现在,我要做的是旋转 window 的内容(客户)区域。 GDI 部分正在工作,但不是 D3D 部分。函数 d3d_resize() 接受一个名为 rot 的参数,根据它的值(0、1、2 或 3),我想旋转客户区。
现在,我关注 rot == 0,即没有旋转。
我使用常量缓冲区来存储旋转矩阵,定义(数学)如下:
|r11 r12 t1|
|r21 r22 t2|
其中子矩阵(r)是旋转部分,子向量(t)是平移
所以对于rot == 0,矩阵基本上就是单位矩阵+没有平移。如果 (x,y)
是我的 2D 向量,我将其扩展为 1 以考虑平移,因此:
|1 0 0| |x| |x|
|0 1 0| * |y| = |y|
|1|
也就是说,如果rot == 0,我想要的。我的旋转C部分是:
typedef struct
{
float rotation[2][3]; /* rotation + translation */
float dummy[2]; /* for 16 bytes padding */
} Const_Buffer;
void d3d_resize(D3d *d3d, int rot, UINT width, UINT height)
{
/* snip */
switch (rot)
{
case 0:
((Const_Buffer *)mapped.pData)->rotation[0][0] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 0.0f;
break;
case 1:
((Const_Buffer *)mapped.pData)->rotation[0][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 2.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 0.0f;
break;
case 2:
((Const_Buffer *)mapped.pData)->rotation[0][0] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 0.0f;
break;
case 3:
((Const_Buffer *)mapped.pData)->rotation[0][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 2.0f;
break;
}
/* snip */
}
顶点着色器是:
cbuffer cv_viewport : register(b0)
{
float2x3 rotation_matrix;
}
struct vs_input
{
float2 position : POSITION;
float4 color : COLOR;
};
struct ps_input
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
ps_input main_vs(vs_input input )
{
ps_input output;
float2 p = input.position;
p = mul(rotation_matrix, float3(input.position, 1.0f));
output.position = float4(p, 0.0f, 1.0f);
output.color = input.color;
return output;
}
我使用 Visual Studio 图形调试器检查 rot == 0 时的常量缓冲区值,它们看起来是正确的。
但是当 rot == 0 时,黄色三角形和蓝色矩形不显示。如果我在着色器中注释乘法完成的行,它们就会显示。我做错了什么,但我不知道是什么地方。在 link 下面找到完整的 C 代码 + 我的 github 中的着色器代码(它太大而无法内联发布)
C代码:https://github.com/vtorri/d3d_rot/blob/master/d3d_rot.c
着色器代码:https://github.com/vtorri/d3d_rot/blob/master/shader_3.hlsl
没有mul的截图:
屏幕截图与 mul:
所以,实际上,问题是在 C 代码中使用矩阵填充常量缓冲区,并在着色器中为矩阵指定行布局(参见 https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-syntax)
解决方案:
C 代码中的常量缓冲区:
float rotation[2][4];
着色器中的常量缓冲区:
row_major float2x3 rotation_matrix;
现在,它正在运行:-)
我仍在努力改进我的 Direct3D 11 二维测试程序,没有任何额外的库(参见
现在,我要做的是旋转 window 的内容(客户)区域。 GDI 部分正在工作,但不是 D3D 部分。函数 d3d_resize() 接受一个名为 rot 的参数,根据它的值(0、1、2 或 3),我想旋转客户区。
现在,我关注 rot == 0,即没有旋转。
我使用常量缓冲区来存储旋转矩阵,定义(数学)如下:
|r11 r12 t1|
|r21 r22 t2|
其中子矩阵(r)是旋转部分,子向量(t)是平移
所以对于rot == 0,矩阵基本上就是单位矩阵+没有平移。如果 (x,y)
是我的 2D 向量,我将其扩展为 1 以考虑平移,因此:
|1 0 0| |x| |x|
|0 1 0| * |y| = |y|
|1|
也就是说,如果rot == 0,我想要的。我的旋转C部分是:
typedef struct
{
float rotation[2][3]; /* rotation + translation */
float dummy[2]; /* for 16 bytes padding */
} Const_Buffer;
void d3d_resize(D3d *d3d, int rot, UINT width, UINT height)
{
/* snip */
switch (rot)
{
case 0:
((Const_Buffer *)mapped.pData)->rotation[0][0] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 0.0f;
break;
case 1:
((Const_Buffer *)mapped.pData)->rotation[0][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 2.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 0.0f;
break;
case 2:
((Const_Buffer *)mapped.pData)->rotation[0][0] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 0.0f;
break;
case 3:
((Const_Buffer *)mapped.pData)->rotation[0][0] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[0][1] = 1.0f;
((Const_Buffer *)mapped.pData)->rotation[0][2] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][0] = -1.0f;
((Const_Buffer *)mapped.pData)->rotation[1][1] = 0.0f;
((Const_Buffer *)mapped.pData)->rotation[1][2] = 2.0f;
break;
}
/* snip */
}
顶点着色器是:
cbuffer cv_viewport : register(b0)
{
float2x3 rotation_matrix;
}
struct vs_input
{
float2 position : POSITION;
float4 color : COLOR;
};
struct ps_input
{
float4 position : SV_POSITION;
float4 color : COLOR;
};
ps_input main_vs(vs_input input )
{
ps_input output;
float2 p = input.position;
p = mul(rotation_matrix, float3(input.position, 1.0f));
output.position = float4(p, 0.0f, 1.0f);
output.color = input.color;
return output;
}
我使用 Visual Studio 图形调试器检查 rot == 0 时的常量缓冲区值,它们看起来是正确的。
但是当 rot == 0 时,黄色三角形和蓝色矩形不显示。如果我在着色器中注释乘法完成的行,它们就会显示。我做错了什么,但我不知道是什么地方。在 link 下面找到完整的 C 代码 + 我的 github 中的着色器代码(它太大而无法内联发布)
C代码:https://github.com/vtorri/d3d_rot/blob/master/d3d_rot.c
着色器代码:https://github.com/vtorri/d3d_rot/blob/master/shader_3.hlsl
没有mul的截图:
屏幕截图与 mul:
所以,实际上,问题是在 C 代码中使用矩阵填充常量缓冲区,并在着色器中为矩阵指定行布局(参见 https://docs.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-variable-syntax)
解决方案:
C 代码中的常量缓冲区:
float rotation[2][4];
着色器中的常量缓冲区:
row_major float2x3 rotation_matrix;
现在,它正在运行:-)