zoukankan      html  css  js  c++  java
  • 各语言系统或编程接口中向量与矩阵存储的差异

    *********文中用到的transpose()代表矩阵转置函数,mul()代表矩阵乘法。

    本文试图解释DX,HLSL,CG,OpengGL,GLSL中关于矩阵运算及存储的一些模糊概念。

    0,先弄清楚,用矩阵来变换行/列向量时,怎样的矩阵才是预期的。

    假设有行向量p,列向量q,一个给定的【非对称矩阵】A可以用来变换p可以表示为mul(p,A)(这叫post-multiply),也可以用来变换q,表示为mul(A,q)(这叫pre-multiply)。

    但A通常只能代表一个预期的变换(比如旋转平移啥的),这里假设A代表的是行向量p的预期变换,那mul(p,A)是我们预期的变换,而mul(A,q)代表的变换不是我们预期的,如果我们也想用A来对q进行变换,mul(transpose(A),q)才是我们预期的。

    如下:

    mul(p,A):

    结果记为float3(x*m11+y*m21+z*m31,x*m12+y*m22+z*m32,x*m13+y*m23+z*m33),这是预期的结果。

    mul(A,q):

    结果记为float3(x*m11+y*m12+z*m13,x*m21+y*m22+z*m23,x*m31+y*m32+z*m33),不是预期的结果。

    mul(transpose(A),q):

    结果记为float3(x*m11+y*m21+z*m31,x*m12+y*m22+z*m32,x*m13+y*m23+z*m33),这与我们预期的结果一样。

    其实就是这么个简单的线性代数结果:。对于行向量,如果符合预期的变换矩阵是,那对于列向量,符合同样预期变换的矩阵则是

    1,再弄清楚什么是 row-major和column-major。

    一个矩阵A(如下):

    在内存中,如果按照 {{m11,m12,m13},{m21,m22,m23},{m31,m32,m33}}的顺序来进行存储,我们就说这个矩阵是按row-major(行优先)的方式来存储的;

    如果按照 {{m11,m21,m31},{m12,m22,m32},{m13,m23,m33}}的顺序来进行存储,我们就说这个矩阵是按column-major(列优先)的方式来存储的。

    2,观点:

    Row-major vs. column-major is just a storage order thing and doesn’t have anything to do with what kind of vectors you use. 

    【(在一个系统中,)所谓row-major 和 column-major 不过是(矩阵)数据存储的两种顺序方式,与(系统)使用哪一种向量(行向量或列向量)完全是不相干的两码事。】

    3,几个结论。

    由于某些语言可以通过预处理指令来改变矩阵存储的方式,以下结论都建立在各系统的默认状态上。

    我们假设M=是DirectX中的一个预期的变换,则=

    那么对于DX,HLSL,CG,OpengGL,GLSL,分别有:

    DirectX使用行向量(row vector),使用 row-major 的方式存储。

    通过第0点,知道预期变换的矩阵是M=,按row-major存储顺序结果是: {{m11,m12,m13},{m21,m22,m23},{m31,m32,m33}}

    HLSL    :默认使用行向量(row vector),默认使用 column-major 的方式存储。

    因为也使用行向量,所以预期变换的矩阵是M=,按column-major存储顺序结果是: {{m11,m21,m31},{m12,m22,m32},{m13,m23,m33}}

    特别注意,HLSL是DX的shader语言,但HLSL跟DirectX的矩阵存储方式不一样,存储顺序结果也不一样。

    HLSL中经典的MVP转换写成:OUT.Position = mul(IN.ObjectPosition, WorldViewProjection);

    也可以使用行向量:OUT.Position = mul(transpose(WorldViewProjection),IN.ObjectPosition);

    参考:https://msdn.microsoft.com/en-us/library/windows/desktop/bb509634(v=vs.85).aspx#Matrix_Ordering 中提到:

    Matrix packing order for uniform parameters is set to column-major by default. This means each column of the matrix is stored in a single constant register. 

    CG        :默认使用列向量(column vector),默认使用 row-major 的方式存储。

    因为也使用列向量,通过第0点知道预期变换的矩阵是=,按row-major存储顺序结果是: {{m11,m21,m31},{m12,m22,m32},{m13,m23,m33}}

    特别注意,虽然我们常说CG和HLSL很像,但CG中默认使用的矩阵形式和矩阵的存储形式和HLSL都不一样,但其存储顺序却一样。

    CG,HLSL都可以通过预处理命令来改变矩阵的存储方式。

    CG中经典的MVP转换写成:OUT.Position = mul(WorldViewProjection,IN.ObjectPosition);//这里也跟HLSL刚好相反。

    你也可以使用行向量:OUT.Position = mul(IN.ObjectPosition,transpose(WorldViewProjection));

    OpenGL 默认使用列向量(column vector),默认使用 column-major 的方式存储。

    因为使用列向量,所以预期变换的矩阵是=,按 column-major存储顺序结果是: {{m11,m12,m13},{m21,m22,m23},{m31,m32,m33}}

    https://www.khronos.org/opengl/wiki/Data_Type_(GLSL)

    GLSL      : 同OpenGL

    4,从第3点可以看出,在默认存储情况下:DirectX和OPENGL/GLSL的矩阵存储顺序殊途同归;HLSL与CG的矩阵存储顺序殊途同归。

    参考资料:

    https://fgiesen.wordpress.com/2012/02/12/row-major-vs-column-major-row-vectors-vs-column-vectors/

    https://fgiesen.wordpress.com/2011/05/04/row-major-vs-column-major-and-gl-es/

    http://www.cnblogs.com/soroman/archive/2008/03/21/1115571.html

    http://www.catalinzima.com/2012/12/a-word-on-matrices/

    http://http.developer.nvidia.com/Cg/mul.html

    https://github.com/kakashidinho/Cg2glsl

  • 相关阅读:
    待解决问题集锦
    蓝桥杯--- 历届试题 连号区间数(水题)
    蓝桥杯---历届试题 翻硬币 (水题)
    nyoj 678 最小K个数之和
    hdoj 2 括号配对问题【数组模拟实现+STL实现】
    hdoj 1016 Prime Ring Problem
    nyoj 62 笨小熊
    nyoj 47 过河问题
    nyoj 456 邮票分你一半
    nyoj 171 聪明的kk
  • 原文地址:https://www.cnblogs.com/jackmaxwell/p/6535642.html
Copyright © 2011-2022 走看看