D3D12渲染技术之矩阵向量运算

2023-10-11 16:59

本文主要是介绍D3D12渲染技术之矩阵向量运算,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

向量,矩阵运算这个是老生常谈的话题了,作为程序员来说必须要掌握的,游戏开发逻辑编写中用的最多的也是矩阵向量相关的运算,向量矩阵运算它也是引擎的最基础部分,几乎每个引擎都会封装自己的向量运算类,矩阵运算类,Unity引擎它也封装了自己的矩阵向量类,虚幻也是一样的。学习D3D12,它们也是绕不过去的,大学的课本《线性代数》主讲的就是它们,如果大家没有学习过或者是跨行业的,可以学习一下。如果大家已经掌握了线性代数中的向量矩阵运算,接下来我们就要把向量矩阵运算转换成编程语言,将在D3D12中展示,先看向量的运算封装。

向量运算封装

向量有点乘,叉乘,加,减,标准化等等操作,在D3D12中提供的文件DirectXMath.h为我们提供了向量的定义为:XMVECTOR,所以我们要查看一下该文件都提供了哪些内容,这个跟我们使用引擎有点类似,先看看有没有相关的接口,如果没有再自己封装。
我们通过DirectXMath看到了如下代码:

#if defined(_XM_SSE_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
typedef __m128 XMVECTOR;
#elif defined(_XM_ARM_NEON_INTRINSICS_) && !defined(_XM_NO_INTRINSICS_)
typedef float32x4_t XMVECTOR;
#else
typedef __vector4 XMVECTOR;
#endif

D3D12已经为我们定义了向量,该向量是四维的,是四个32位浮点分量在16字节上对齐,考虑了内存占用,代码很严谨。每个接下来做的事情就是赋值,然后我们做运算,看看有没有给向量的赋值函数,我们继续在D3D12中查找,在文件DirectXMathVector.inl中找到了给向量赋值的内联函数:

inline XMVECTOR XM_CALLCONV XMVectorSet
(float x, float y, float z, float w
)
{
#if defined(_XM_NO_INTRINSICS_)XMVECTORF32 vResult = { { { x, y, z, w } } };return vResult.v;
#elif defined(_XM_ARM_NEON_INTRINSICS_)float32x2_t V0 = vcreate_f32(((uint64_t)*(const uint32_t *)&x) | ((uint64_t)(*(const uint32_t *)&y) << 32));float32x2_t V1 = vcreate_f32(((uint64_t)*(const uint32_t *)&z) | ((uint64_t)(*(const uint32_t *)&w) << 32));return vcombine_f32(V0, V1);
#elif defined(_XM_SSE_INTRINSICS_)return _mm_set_ps( w, z, y, x );
#endif
}

我们可以自己调用接口XMVectorSet对向量进行赋值操作,比如下面代码所示:

    XMVECTOR n = XMVectorSet(1.0f, 0.0f, 0.0f, 0.0f);XMVECTOR u = XMVectorSet(1.0f, 2.0f, 3.0f, 0.0f);XMVECTOR v = XMVectorSet(-2.0f, 1.0f, -3.0f, 0.0f);XMVECTOR w = XMVectorSet(0.707f, 0.707f, 0.0f, 0.0f);

下一步就是运算符重载函数了,D3D12应该已经为我们定义好了,这个还是在DirectXMath.h
文件中,代码如下所示:

#ifndef _XM_NO_XMVECTOR_OVERLOADS_
XMVECTOR    XM_CALLCONV     operator+ (FXMVECTOR V);
XMVECTOR    XM_CALLCONV     operator- (FXMVECTOR V);XMVECTOR&   XM_CALLCONV     operator+= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR&   XM_CALLCONV     operator-= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR&   XM_CALLCONV     operator*= (XMVECTOR& V1, FXMVECTOR V2);
XMVECTOR&   XM_CALLCONV     operator/= (XMVECTOR& V1, FXMVECTOR V2);XMVECTOR&   operator*= (XMVECTOR& V, float S);
XMVECTOR&   operator/= (XMVECTOR& V, float S);XMVECTOR    XM_CALLCONV     operator+ (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR    XM_CALLCONV     operator- (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR    XM_CALLCONV     operator* (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR    XM_CALLCONV     operator/ (FXMVECTOR V1, FXMVECTOR V2);
XMVECTOR    XM_CALLCONV     operator* (FXMVECTOR V, float S);
XMVECTOR    XM_CALLCONV     operator* (float S, FXMVECTOR V);
XMVECTOR    XM_CALLCONV     operator/ (FXMVECTOR V, float S);
#endif /* !_XM_NO_XMVECTOR_OVERLOADS_ */

最后就比较简单了,我们把向量的运算一并写出来,包括向量的角度,向量加减,点乘,叉乘等运算,代码如下所示:

    // Vector addition: XMVECTOR operator + XMVECTOR a = u + v;// Vector subtraction: XMVECTOR operator - XMVECTOR b = u - v;// Scalar multiplication: XMVECTOR operator * XMVECTOR c = 10.0f*u;// ||u||XMVECTOR L = XMVector3Length(u);// d = u / ||u||XMVECTOR d = XMVector3Normalize(u);// s = u dot vXMVECTOR s = XMVector3Dot(u, v);// e = u x vXMVECTOR e = XMVector3Cross(u, v);// Find proj_n(w) and perp_n(w)XMVECTOR projW;XMVECTOR perpW;XMVector3ComponentsFromNormal(&projW, &perpW, w, n);// Does projW + perpW == w?bool equal = XMVector3Equal(projW + perpW, w) != 0;bool notEqual = XMVector3NotEqual(projW + perpW, w) != 0;// The angle between projW and perpW should be 90 degrees.XMVECTOR angleVec = XMVector3AngleBetweenVectors(projW, perpW);float angleRadians = XMVectorGetX(angleVec);float angleDegrees = XMConvertToDegrees(angleRadians);

最终实现的效果截图:
这里写图片描述

矩阵运算

矩阵有运算有矩阵相加,相减,相乘,单位矩阵,转置矩阵等等。矩阵的定义以及函数在DirectXMath.h文件中都有定义,给读者展示如下所示:

#if ( defined(_M_ARM64) || defined(_M_HYBRID_X86_ARM64) || _XM_VECTORCALL_ ) && !defined(_XM_NO_INTRINSICS_)
typedef const XMMATRIX FXMMATRIX;
#else
typedef const XMMATRIX& FXMMATRIX;
#endif// Fix-up for (2nd+) XMMATRIX parameters to pass by reference
typedef const XMMATRIX& CXMMATRIX;#ifdef _XM_NO_INTRINSICS_
struct XMMATRIX
#else
__declspec(align(16)) struct XMMATRIX
#endif
{
#ifdef _XM_NO_INTRINSICS_union{XMVECTOR r[4];struct{float _11, _12, _13, _14;float _21, _22, _23, _24;float _31, _32, _33, _34;float _41, _42, _43, _44;};float m[4][4];};
#elseXMVECTOR r[4];
#endifXMMATRIX() XM_CTOR_DEFAULT
#if defined(_MSC_VER) && _MSC_VER >= 1900constexpr XMMATRIX(FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3) : r{ R0,R1,R2,R3 } {}
#elseXMMATRIX(FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3) { r[0] = R0; r[1] = R1; r[2] = R2; r[3] = R3; }
#endifXMMATRIX(float m00, float m01, float m02, float m03,float m10, float m11, float m12, float m13,float m20, float m21, float m22, float m23,float m30, float m31, float m32, float m33);explicit XMMATRIX(_In_reads_(16) const float *pArray);#ifdef _XM_NO_INTRINSICS_float       operator() (size_t Row, size_t Column) const { return m[Row][Column]; }float&      operator() (size_t Row, size_t Column) { return m[Row][Column]; }
#endifXMMATRIX&   operator= (const XMMATRIX& M) { r[0] = M.r[0]; r[1] = M.r[1]; r[2] = M.r[2]; r[3] = M.r[3]; return *this; }XMMATRIX    operator+ () const { return *this; }XMMATRIX    operator- () const;XMMATRIX&   XM_CALLCONV     operator+= (FXMMATRIX M);XMMATRIX&   XM_CALLCONV     operator-= (FXMMATRIX M);XMMATRIX&   XM_CALLCONV     operator*= (FXMMATRIX M);XMMATRIX&   operator*= (float S);XMMATRIX&   operator/= (float S);XMMATRIX    XM_CALLCONV     operator+ (FXMMATRIX M) const;XMMATRIX    XM_CALLCONV     operator- (FXMMATRIX M) const;XMMATRIX    XM_CALLCONV     operator* (FXMMATRIX M) const;XMMATRIX    operator* (float S) const;XMMATRIX    operator/ (float S) const;friend XMMATRIX     XM_CALLCONV     operator* (float S, FXMMATRIX M);
};

同样,在文件DirectXMathVector.inl中也定义了矩阵的单位化,转置等操作函数:

inline XMMATRIX XM_CALLCONV XMMatrixIdentity()
{XMMATRIX M;M.r[0] = g_XMIdentityR0.v;M.r[1] = g_XMIdentityR1.v;M.r[2] = g_XMIdentityR2.v;M.r[3] = g_XMIdentityR3.v;return M;
}

在此就不一一列举了,我们用代码实现矩阵运算的示例如下所示:

    XMMATRIX A(1.0f, 0.0f, 0.0f, 0.0f,0.0f, 2.0f, 0.0f, 0.0f,0.0f, 0.0f, 4.0f, 0.0f,1.0f, 2.0f, 3.0f, 1.0f);XMMATRIX B = XMMatrixIdentity();XMMATRIX C = A * B;XMMATRIX D = XMMatrixTranspose(A);XMVECTOR det = XMMatrixDeterminant(A);XMMATRIX E = XMMatrixInverse(&det, A);XMMATRIX F = A * E;

代码运行效果如下所示:
这里写图片描述

小结:

编程实现矩阵,向量运算没有那么复杂,但是我们要考虑到问题很多,就像D3D12定义的向量运算一样,我们还要考虑到位对齐,内存的优化,主要是告诉读者,D3D12是如何封装接口的,参考D3D12的我们也可以自己封装。引擎的封装跟这个类似。
代码下载地址:链接:https://pan.baidu.com/s/1X0Vikf6qGYGPKU-Nwf-wYA 密码:h79q

这篇关于D3D12渲染技术之矩阵向量运算的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/189513

相关文章

详解如何在React中执行条件渲染

《详解如何在React中执行条件渲染》在现代Web开发中,React作为一种流行的JavaScript库,为开发者提供了一种高效构建用户界面的方式,条件渲染是React中的一个关键概念,本文将深入探讨... 目录引言什么是条件渲染?基础示例使用逻辑与运算符(&&)使用条件语句列表中的条件渲染总结引言在现代

【专题】2024飞行汽车技术全景报告合集PDF分享(附原数据表)

原文链接: https://tecdat.cn/?p=37628 6月16日,小鹏汇天旅航者X2在北京大兴国际机场临空经济区完成首飞,这也是小鹏汇天的产品在京津冀地区进行的首次飞行。小鹏汇天方面还表示,公司准备量产,并计划今年四季度开启预售小鹏汇天分体式飞行汽车,探索分体式飞行汽车城际通勤。阅读原文,获取专题报告合集全文,解锁文末271份飞行汽车相关行业研究报告。 据悉,业内人士对飞行汽车行业

【Prometheus】PromQL向量匹配实现不同标签的向量数据进行运算

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。 🏆《博客》:Python全栈,前后端开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi

uva 575 Skew Binary(位运算)

求第一个以(2^(k+1)-1)为进制的数。 数据不大,可以直接搞。 代码: #include <stdio.h>#include <string.h>const int maxn = 100 + 5;int main(){char num[maxn];while (scanf("%s", num) == 1){if (num[0] == '0')break;int len =

金融业开源技术 术语

金融业开源技术  术语 1  范围 本文件界定了金融业开源技术的常用术语。 本文件适用于金融业中涉及开源技术的相关标准及规范性文件制定和信息沟通等活动。

hdu 4565 推倒公式+矩阵快速幂

题意 求下式的值: Sn=⌈ (a+b√)n⌉%m S_n = \lceil\ (a + \sqrt{b}) ^ n \rceil\% m 其中: 0<a,m<215 0< a, m < 2^{15} 0<b,n<231 0 < b, n < 2^{31} (a−1)2<b<a2 (a-1)^2< b < a^2 解析 令: An=(a+b√)n A_n = (a +

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出

AI(文生语音)-TTS 技术线路探索学习:从拼接式参数化方法到Tacotron端到端输出 在数字化时代,文本到语音(Text-to-Speech, TTS)技术已成为人机交互的关键桥梁,无论是为视障人士提供辅助阅读,还是为智能助手注入声音的灵魂,TTS 技术都扮演着至关重要的角色。从最初的拼接式方法到参数化技术,再到现今的深度学习解决方案,TTS 技术经历了一段长足的进步。这篇文章将带您穿越时

系统架构设计师: 信息安全技术

简简单单 Online zuozuo: 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo 简简单单 Online zuozuo :本心、输入输出、结果 简简单单 Online zuozuo : 文章目录 系统架构设计师: 信息安全技术前言信息安全的基本要素:信息安全的范围:安全措施的目标:访问控制技术要素:访问控制包括:等保

hdu 6198 dfs枚举找规律+矩阵乘法

number number number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Problem Description We define a sequence  F : ⋅   F0=0,F1=1 ; ⋅   Fn=Fn

前端技术(七)——less 教程

一、less简介 1. less是什么? less是一种动态样式语言,属于css预处理器的范畴,它扩展了CSS语言,增加了变量、Mixin、函数等特性,使CSS 更易维护和扩展LESS 既可以在 客户端 上运行 ,也可以借助Node.js在服务端运行。 less的中文官网:https://lesscss.cn/ 2. less编译工具 koala 官网 http://koala-app.