使用 GLM 的 DirectX11 的 MVP 矩阵
MVP matrix for DirectX11 using GLM
首先是 使用 XMMATH 工作的部分,其中 data.model 是 XMMatrix:
static auto model_matrix = DirectX::XMMatrixIdentity();
static auto pos = DirectX::XMVectorSet(0.0f, 0.0f, -10.0f, 0.0f);
static auto focus = DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
static auto up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
static auto view_matrix = DirectX::XMMatrixLookAtLH(pos, focus, up);
static auto proj_matrix = DirectX::XMMatrixPerspectiveFovLH(glm::radians(45.0f), 16.0f / 9.0f, 0.1f, 10000.0f);
构建 mvp:
data.model = model_matrix * view_matrix * proj_matrix;
data.model = DirectX::XMMatrixTranspose(data.model);
当我将 data.model 交给我的 HLSL 着色器时,一切正常,我可以更改 pos
向量以从不同角度查看我的立方体。 HLSL 顶点着色器:
cbuffer myCbuffer : register(b0) {
float4x4 mat;
}
float4 main(float3 pos : POSITION) : SV_POSITION
{
return mul(float4(pos, 1), mat);
}
现在,当我尝试使用 GLM 制作类似的东西时(我将 data.model 的类型更改为 glm::mat4
):
auto gl_m = glm::mat4(1.0f);
static auto gl_pos = glm::vec3(0.0f, 0.0f, -10.0f);
static auto gl_focus = glm::vec3(0.0f, 0.0f, 0.0f);
static auto gl_up = glm::vec3(0.0f, 1.0f, 0.0f);
auto gl_v = glm::lookAtLH(gl_pos, gl_focus, gl_up);
auto gl_p = glm::perspectiveFovLH_ZO(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f);
构建 MVP:
data.model = gl_m * gl_v * gl_p;
现在,当我将其传递给 data.model 时,立方体确实得到了渲染,但整个屏幕都是黑色的。 (我的立方体是黑色的,清晰的颜色是浅蓝色,所以我认为它正在渲染立方体,但实际上很接近或在里面)。
我不知道去哪里查看如何解决这个问题,投影矩阵应该在正确的裁剪中 space 因为我正在使用 perspectiveFovLH_ZO
,ZO 修复了裁剪 space 到 [0..1]。这可能是 HLSL 着色器 float4x4
处理 glm::mat4
的方式,但我认为两者都是主要列,因此无需转置。
它可能与光栅化器剔除设置和 FrontCounterClockwise
设置有关,但我对 DirectX 还很陌生,不知道它到底做了什么。
D3D11_RASTERIZER_DESC raster_desc = {0};
raster_desc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
raster_desc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE;
raster_desc.FrontCounterClockwise = false;
d3device->CreateRasterizerState(&raster_desc, rasterize_state.GetAddressOf());
感谢任何帮助,如果我忘记了什么,请告诉我。
设法修复它(似乎是创可贴修复,但我现在会使用它)。
在构建 mvp 之后,我添加了:
gl_mvp[3][3] = -10.0f;
gl_mvp = glm::transpose(gl_mvp);
-10 是相机位置的 z 坐标(与您传递给 glm::lookAtLH
的第一个参数相同)。我认为 HLSL/DirectX 匹配 column-major GLM 矩阵但显然不匹配,它需要额外的转置调用。我不确定为什么会这样,MVP 的左下角元素是什么,它必须与位置 z 匹配,也许对它背后的数学有更好理解的人可以澄清。
删除了 gl_mvp[3][3] = -10.0f;
因为它是一个错误的修复,我现在得到了这个:
将 lookAtLH
和 PerspectiveFovLH_ZO
都更改为 RH
变体。
还将构建 MVP 的顺序从 M * V * P 更改为 P * V * M。
似乎运行良好的新代码(甚至使用我的相机 class 飞来飞去):
auto gl_m = glm::mat4(1.0f);
auto gl_v = glm::lookAtRH(position, position + dir, {0, 1, 0});
auto gl_p = glm::perspectiveFovRH_ZO(glm::radians(FOV), 1280.0f, 720.0f, 0.1f, 10000.0f);
glm::mat4 gl_mvp = gl_p * gl_v * gl_m;
return glm::transpose(gl_mvp);
它与之前的代码有点不同,因为它在我的相机中 class,所以位置、方向和 FOV 是我跟踪的变量,但你明白了。将这个 return 结果传递给了我的 HLSL 着色器,到目前为止一切看起来都很好。
首先是 使用 XMMATH 工作的部分,其中 data.model 是 XMMatrix:
static auto model_matrix = DirectX::XMMatrixIdentity();
static auto pos = DirectX::XMVectorSet(0.0f, 0.0f, -10.0f, 0.0f);
static auto focus = DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
static auto up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
static auto view_matrix = DirectX::XMMatrixLookAtLH(pos, focus, up);
static auto proj_matrix = DirectX::XMMatrixPerspectiveFovLH(glm::radians(45.0f), 16.0f / 9.0f, 0.1f, 10000.0f);
构建 mvp:
data.model = model_matrix * view_matrix * proj_matrix;
data.model = DirectX::XMMatrixTranspose(data.model);
当我将 data.model 交给我的 HLSL 着色器时,一切正常,我可以更改 pos
向量以从不同角度查看我的立方体。 HLSL 顶点着色器:
cbuffer myCbuffer : register(b0) {
float4x4 mat;
}
float4 main(float3 pos : POSITION) : SV_POSITION
{
return mul(float4(pos, 1), mat);
}
现在,当我尝试使用 GLM 制作类似的东西时(我将 data.model 的类型更改为 glm::mat4
):
auto gl_m = glm::mat4(1.0f);
static auto gl_pos = glm::vec3(0.0f, 0.0f, -10.0f);
static auto gl_focus = glm::vec3(0.0f, 0.0f, 0.0f);
static auto gl_up = glm::vec3(0.0f, 1.0f, 0.0f);
auto gl_v = glm::lookAtLH(gl_pos, gl_focus, gl_up);
auto gl_p = glm::perspectiveFovLH_ZO(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f);
构建 MVP:
data.model = gl_m * gl_v * gl_p;
现在,当我将其传递给 data.model 时,立方体确实得到了渲染,但整个屏幕都是黑色的。 (我的立方体是黑色的,清晰的颜色是浅蓝色,所以我认为它正在渲染立方体,但实际上很接近或在里面)。
我不知道去哪里查看如何解决这个问题,投影矩阵应该在正确的裁剪中 space 因为我正在使用 perspectiveFovLH_ZO
,ZO 修复了裁剪 space 到 [0..1]。这可能是 HLSL 着色器 float4x4
处理 glm::mat4
的方式,但我认为两者都是主要列,因此无需转置。
它可能与光栅化器剔除设置和 FrontCounterClockwise
设置有关,但我对 DirectX 还很陌生,不知道它到底做了什么。
D3D11_RASTERIZER_DESC raster_desc = {0};
raster_desc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
raster_desc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE;
raster_desc.FrontCounterClockwise = false;
d3device->CreateRasterizerState(&raster_desc, rasterize_state.GetAddressOf());
感谢任何帮助,如果我忘记了什么,请告诉我。
设法修复它(似乎是创可贴修复,但我现在会使用它)。 在构建 mvp 之后,我添加了:
gl_mvp[3][3] = -10.0f;
gl_mvp = glm::transpose(gl_mvp);
-10 是相机位置的 z 坐标(与您传递给 glm::lookAtLH
的第一个参数相同)。我认为 HLSL/DirectX 匹配 column-major GLM 矩阵但显然不匹配,它需要额外的转置调用。我不确定为什么会这样,MVP 的左下角元素是什么,它必须与位置 z 匹配,也许对它背后的数学有更好理解的人可以澄清。
删除了 gl_mvp[3][3] = -10.0f;
因为它是一个错误的修复,我现在得到了这个:
将 lookAtLH
和 PerspectiveFovLH_ZO
都更改为 RH
变体。
还将构建 MVP 的顺序从 M * V * P 更改为 P * V * M。
似乎运行良好的新代码(甚至使用我的相机 class 飞来飞去):
auto gl_m = glm::mat4(1.0f);
auto gl_v = glm::lookAtRH(position, position + dir, {0, 1, 0});
auto gl_p = glm::perspectiveFovRH_ZO(glm::radians(FOV), 1280.0f, 720.0f, 0.1f, 10000.0f);
glm::mat4 gl_mvp = gl_p * gl_v * gl_m;
return glm::transpose(gl_mvp);
它与之前的代码有点不同,因为它在我的相机中 class,所以位置、方向和 FOV 是我跟踪的变量,但你明白了。将这个 return 结果传递给了我的 HLSL 着色器,到目前为止一切看起来都很好。