OpenGL与DirectX,本地与全局?

时间:2016-10-26 14:33:59

标签: opengl math matrix directx direct3d

我已阅读多篇关于前/后乘法,列/行专业,DirectX与OpenGL的文章和帖子,我可能比开头时更困惑。

所以,假设我们在OpenGL中编写这些指令(伪代码):

旋转(...) 翻译(...)

据我所知,OpenGL会做v'= R * T * v,有效地转换向量的局部坐标系。

但是在DirectX中,如果我们以相同的顺序进行转换(伪代码),

旋转(...) 翻译(...)

结果会不一样吧?由于DirectX预乘,结果将是v'= v * R * T,因此使用全局坐标变换矢量。

所以,当我说OpenGL是后乘法并且DirectX是预乘时就像是说OpenGL在局部坐标中移动而DirectX在全局坐标中移动时,我是否正确?

谢谢。

2 个答案:

答案 0 :(得分:1)

最好的办法是阅读Matrices, Handedness, Pre and Post Multiplication, Row vs Column Major, and Notations

  • OpenGL代码通常使用右手坐标系,列主矩阵,列向量和后乘法。

  • Direct3D代码通常使用左手坐标系,行主矩阵,行向量和预乘。

XNA Game Studio的数学库(以及Monogame,Unity等)使用右手坐标系,行主矩阵,行向量和预乘。

DirectXMath库使用行主矩阵,行向量和预乘,但您可以选择使用左手或右手坐标系统。对于年龄较大的deprecated D3DXMath来说,情况确实如此。

在任一系统中,您仍在使用相同的对象坐标 - >世界坐标 - >眼坐标 - >剪辑坐标转换。

因此,您可以使用OpenGL GLM:

using namespace glm;

mat4 myTranslationMatrix = translate(10.0f, 0.0f, 0.0f);

mat4 myRotationMatrix = rotate( 90.f, vec3( 0, 1, 0 ) );

mat4 myScaleMatrix = scale(2.0f, 2.0f, 2.0f);

mat4 myModelMatrix = myTranslationMatrix * myRotationMatrix * myScaleMatrix;
vec4 myTransformedVector = myModelMatrix * myOriginalVector;

在DirectXMath中你会做:

using namespace DirectX;

XMMATRIX myTranslationMatrix = XMMatrixTranslation(10.0f, 0.0f, 0.0f);

XMMATRIX myRotationMatrix = XMMatrixRotationY(XMConvertToRadians(90.f));

XMMATRIX myScaleMatrix = XMMatrixScaling(2.0f, 2.0f, 2.0f)

XMMATRIX myModelMatrix = myScaleMatrix * myRotationMatrix * myTranslationMatrix;
XMVECTOR myTransformedVector = XMVector4Transform( myOriginalVector, myModelMatrix );

结果你会得到同样的转变。

  

如果您不熟悉DirectXMath,那么您应该查看SimpleMath中的DirectX Tool Kit包装器,该包装器隐藏了一些与C ++构造函数和运算符一致的严格SIMD友好对齐要求。因为SimpleMath基于XNA Game Studio C#数学设计,所以它采用右手视图坐标,但您可以轻松地将其与“本机”DirectXMath混合,以便在需要时使用左手视图坐标。

这些决定中的大多数是任意的,但确实有合理的设计推理。 OpenGL的数学库试图匹配后乘法的正常数学约定,这导致它们采用列主矩阵。在Direct3D的早期阶段,团队认为连接顺序的逆转令人困惑,因此它们颠覆了所有惯例。

许多年后,XNA游戏工作室团队认为传统的Direct3D连接顺序很直观,但是“向前”是负面的z令人困惑,所以他们切换到右手坐标。因此,许多更现代的Direct3D样本都使用右手视图系统,但你仍会看到Direct3D样本的左手和右手观看设置的混合。所以在这一点上,我们真的有“OpenGL风格”,“经典的Direct3D风格“和”现代Direct3D风格“。

  

请注意,当使用固定功能硬件完成任务时,这些约定确实很重要,但使用可编程着色器管道,重要的是您保持一致。事实上,HLSL着色器默认为期望矩阵为列主格式,因此您经常会看到DirectXMath矩阵在复制到常量缓冲区时进行转置。

答案 1 :(得分:0)

在OpenGL中没有预乘这样的东西。

你认为OpenGL反转乘法的原因是它将矩阵存储在列主要布局中:

a c
b d

乘以转置矩阵的数学规则是:

A^T * B^T = (B*A)^T

因此,如果你想计算v' = v * R * T(所有行主矩阵),你将不得不写

(v')^T = v * R * T

或在您的伪代码中:

translate(...) rotate(...) translate(...)

另外您也可以存储旋转和翻译矩阵专栏。