使用 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; 因为它是一个错误的修复,我现在得到了这个: 将 lookAtLHPerspectiveFovLH_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 着色器,到目前为止一切看起来都很好。