如何从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
相关产品推荐
相关产品推荐

