You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从DirectX 11投影XMMatrix中获取Left/Right/Top/Bottom值?

在DirectX 11中通过OpenXR获取投影矩阵的left/right/top/bottom参数

我正尝试在DirectX 11应用中通过OpenXR集成VR头显,需要使用DirectX::XMMatrixPerspectiveOffCenterLH创建投影矩阵,目前已拥有OpenXR的XrCompositionLayerProjectionView对象。

OpenXR示例中的视图与投影矩阵计算代码

const DirectX::XMMATRIX viewMatrix = DirectX::XMMatrixTranspose(DirectX::XMMatrixInverse(nullptr, poseToXmMatrix(view.pose)));
//XMStoreFloat4x4(&m_constants.data.view, viewMatrix);
Matrix4x4f projectionMatrix{};
createProjectionFov(&projectionMatrix, view.fov, nearZ, farZ);
const DirectX::XMMATRIX projection = DirectX::XMMatrixTranspose(LoadXrMatrix(projectionMatrix));

inline DirectX::XMMATRIX XM_CALLCONV ToXmMatrix(const XrPosef& pose, float scale)
{
    return XMMatrixAffineTransformation(DirectX::XMVectorReplicate(scale), DirectX::g_XMZero,
        XMLoadFloat4(reinterpret_cast<const DirectX::XMFLOAT4*>(&pose.orientation)), XMLoadFloat3(reinterpret_cast<const DirectX::XMFLOAT3*>(&pose.position)));
}

DirectX::XMMATRIX XM_CALLCONV poseToXmMatrix(const XrPosef& pose)
{
    return XMMatrixAffineTransformation(DirectX::g_XMOne, DirectX::g_XMZero, XMLoadFloat4(reinterpret_cast<const DirectX::XMFLOAT4*>(&pose.orientation)),
        XMLoadFloat3(reinterpret_cast<const DirectX::XMFLOAT3*>(&pose.position)));
}

自定义投影类的相关方法

void FI3PerspectiveOffCenterProjection::Calculate()
{
    //float w = fabs(r-l);
    //float h = fabs(t-b);
    FI3MATRIX matProjection = FI3MatrixPerspectiveOCFOVLH(m_fNearClip * l, m_fNearClip * r, m_fNearClip * b, m_fNearClip * t, m_fNearClip, m_fFarClip);
    FI3Matrix4x4AFromMatrix(&m_matProjection, matProjection);
}


void FI3PerspectiveOffCenterProjection::setParams(float _l, float _t, float _r, float _b, float _fFarClip, float _fNearClip, bool _bAngular /*= false*/)
{
    if (_bAngular)
    {
        l = tan(_l);
        t = tan(_t);
        r = tan(_r);
        b = tan(_b);
        //      float w = r - l;
        //      float h = b - t;
    }
    else
    {
        l = _l;
        r = _r;
        t = _t;
        b = _b;
    }
    Calculate();
}

解决方案

从XrCompositionLayerProjectionView的fov字段(类型为XrFovf)可以直接提取左右上下的角度值,适配自定义投影类有两种方式:

方式一:利用类的角度转换功能

XrFovf包含angleLeft、angleRight、angleUp、angleDown四个弧度制角度值,直接传入setParams并启用_bAngular参数,类内部会自动完成切线值计算:

// 假设已获取XrCompositionLayerProjectionView对象view
XrFovf fov = view.fov;
float nearZ = 0.01f; // 按应用需求设置近裁剪面
float farZ = 100.0f; // 按应用需求设置远裁剪面

FI3PerspectiveOffCenterProjection proj;
proj.setParams(
    fov.angleLeft, 
    fov.angleUp, 
    fov.angleRight, 
    fov.angleDown, 
    farZ, 
    nearZ, 
    true // 传入角度值,启用内部切线转换
);

方式二:手动计算切线值传入

如果不想启用类的角度转换,可以自行计算各方向的切线值后传入:

XrFovf fov = view.fov;
float nearZ = 0.01f;
float farZ = 100.0f;

// 手动计算切线值
float l = tan(fov.angleLeft);
float r = tan(fov.angleRight);
float t = tan(fov.angleUp);
float b = tan(fov.angleDown);

FI3PerspectiveOffCenterProjection proj;
proj.setParams(l, t, r, b, farZ, nearZ, false);

两种方式都能生成与OpenXR示例逻辑一致的投影矩阵,完美适配自定义投影类的需求。

内容的提问来源于stack exchange,提问作者Priyank shishodia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 12:42:09