为什么DirectX 11 在把矩阵(例如View矩阵)传给shader之前要进行转置
2015-11-16 16:47
786 查看
一,
在DirectX11里, 能看到这样的代码
D3DXMatrixTranspose(&worldMatrix, &worldMatrix);
D3DXMatrixTranspose(&viewMatrix, &viewMatrix);
D3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
目的是把矩阵转置, 之后再传给shader
二,
根据3D数学的相关知识, 把一个矩阵代表的变换作用于一个Vector(或Point), 需要矩阵和Vector相乘
如果矩阵是row-major, 则矩阵在右, Vector在左
如果矩阵是column-major, 则矩阵在左, Vector在右 (例如UNITY)
注意这里的左乘/右乘和内存中的数据存放方式没有关系, 它只是纯粹的数学
三,
下面来看在DirectX11里的shader代码
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
这里的矩阵都已经是转置过的矩阵, 即column-major, 但是为什么它们都是在乘法的右侧呢
根据前面所说的, column-major矩阵应该是在乘法左边才对
四, 详细解释
矩阵位置索引
[ 1 2 3 4 ]
[ 5 6 7 8 ]
[ 9 10
11 12 ]
[ 13 14
15 16 ]
如果有一个矩阵形如
[ a b c d]
[ e f g h]
[ i j k l ]
[m n o p]
那么
行主, 内存位置索引为
a b c d e f h i j k l m n o p
列主, 内存位置索引为
a e i m b f j n c g k o d h l p
行主乘法如下
V * M = 数字为内存位置索引[V * M[1,5,9,13], ...] = 数字为矩阵位置索引[V * M[1,5,9,13], ...] = [V * M[a,e,i,m], ...]
列主乘法如下
M * V = 数字为内存位置索引[M[1,5,9,13] * V, ...] = 数字为矩阵位置索引[M[1,2,3,4] * V, ...] = [V * M[a,e,i,m], ...]
在HLSL中比较特殊, 按理说矩阵在右侧应该是行主乘法, 但是HLSL又默认期望所有矩阵都是列主
所以HLSL中的矩阵乘法和前面有所不同, 如下
V * M = 数字为内存位置索引[V * M[1,2,3,4], ...] = 数字为矩阵位置索引[V * M[1,2,3,4], ...] = [V * M[a,e,i,m], ...]
五, 为什么要这样? 因为速度
根据
http://www.gamedev.net/topic/662986-hlsl-mul-and-rowcolumn-major-matricies-in-directx
里的回复
HLSL生成的shader代码型如
dp4 oPos.x, v0, c0
dp4 oPos.y, v0, c1
dp4 oPos.z, v0, c2
dp4 oPos.w, v0, c3
正如[四,]里写出的HLSL乘法公式, 注意是数字为内存索引位置的那个
而使用普通的列主乘法, shader代码会变成
mul r0, v0.y, c1
mad r0, c0, v0.x, r0
mad r0, c2, v0.z, r0
mad oPos, c3, v0.w, r0
回复者的原话是
"Having single column in one constant register allows to quickly calc resulting vector component
with one dot instruction."
参考资料:
http://www.gamedev.net/topic/662986-hlsl-mul-and-rowcolumn-major-matricies-in-directx/ http://xboxforums.create.msdn.com/forums/t/112276.aspx http://stackoverflow.com/questions/16578765/hlsl-mul-variables-clarification http://www.rastertek.com/dx11tut04.html
在DirectX11里, 能看到这样的代码
D3DXMatrixTranspose(&worldMatrix, &worldMatrix);
D3DXMatrixTranspose(&viewMatrix, &viewMatrix);
D3DXMatrixTranspose(&projectionMatrix, &projectionMatrix);
目的是把矩阵转置, 之后再传给shader
二,
根据3D数学的相关知识, 把一个矩阵代表的变换作用于一个Vector(或Point), 需要矩阵和Vector相乘
如果矩阵是row-major, 则矩阵在右, Vector在左
如果矩阵是column-major, 则矩阵在左, Vector在右 (例如UNITY)
注意这里的左乘/右乘和内存中的数据存放方式没有关系, 它只是纯粹的数学
三,
下面来看在DirectX11里的shader代码
output.position = mul(input.position, worldMatrix);
output.position = mul(output.position, viewMatrix);
output.position = mul(output.position, projectionMatrix);
这里的矩阵都已经是转置过的矩阵, 即column-major, 但是为什么它们都是在乘法的右侧呢
根据前面所说的, column-major矩阵应该是在乘法左边才对
四, 详细解释
矩阵位置索引
[ 1 2 3 4 ]
[ 5 6 7 8 ]
[ 9 10
11 12 ]
[ 13 14
15 16 ]
如果有一个矩阵形如
[ a b c d]
[ e f g h]
[ i j k l ]
[m n o p]
那么
行主, 内存位置索引为
a b c d e f h i j k l m n o p
列主, 内存位置索引为
a e i m b f j n c g k o d h l p
行主乘法如下
V * M = 数字为内存位置索引[V * M[1,5,9,13], ...] = 数字为矩阵位置索引[V * M[1,5,9,13], ...] = [V * M[a,e,i,m], ...]
列主乘法如下
M * V = 数字为内存位置索引[M[1,5,9,13] * V, ...] = 数字为矩阵位置索引[M[1,2,3,4] * V, ...] = [V * M[a,e,i,m], ...]
在HLSL中比较特殊, 按理说矩阵在右侧应该是行主乘法, 但是HLSL又默认期望所有矩阵都是列主
所以HLSL中的矩阵乘法和前面有所不同, 如下
V * M = 数字为内存位置索引[V * M[1,2,3,4], ...] = 数字为矩阵位置索引[V * M[1,2,3,4], ...] = [V * M[a,e,i,m], ...]
五, 为什么要这样? 因为速度
根据
http://www.gamedev.net/topic/662986-hlsl-mul-and-rowcolumn-major-matricies-in-directx
里的回复
HLSL生成的shader代码型如
dp4 oPos.x, v0, c0
dp4 oPos.y, v0, c1
dp4 oPos.z, v0, c2
dp4 oPos.w, v0, c3
正如[四,]里写出的HLSL乘法公式, 注意是数字为内存索引位置的那个
而使用普通的列主乘法, shader代码会变成
mul r0, v0.y, c1
mad r0, c0, v0.x, r0
mad r0, c2, v0.z, r0
mad oPos, c3, v0.w, r0
回复者的原话是
"Having single column in one constant register allows to quickly calc resulting vector component
with one dot instruction."
参考资料:
http://www.gamedev.net/topic/662986-hlsl-mul-and-rowcolumn-major-matricies-in-directx/ http://xboxforums.create.msdn.com/forums/t/112276.aspx http://stackoverflow.com/questions/16578765/hlsl-mul-variables-clarification http://www.rastertek.com/dx11tut04.html
相关文章推荐
- C#使用Matrix执行缩放的方法
- 如何使用Matrix对bitmap的旋转与镜像水平垂直翻转
- Android中Matrix用法实例分析
- HP Z800 Workstation - Configuring RAID devices (HP Z800 做磁盘Raid1,Raid0的阵列)
- Android Matrix类以及ColorMatrix类详解
- 用css实现图片的旋转
- 让舞台上的按钮btn灰掉
- Android中Bitmap和Drawable
- 反编译ARB program to GLSL shader日记
- Android 简单的图片缩放方法
- 虚幻3引擎
- Feelings after the test.
- 用于线性代数的Ruby模块linalg 0.32发布收藏(来自ruby-talk)
- Android之涂鸦(简单的画图)
- 基于顶点纹理的无限大海水仿真
- c++ Primer 之 类的初始化,赋值和析构
- 图形加速卡技术 [专业的基础技术文章]
- 哪部电影是技术人员最应该看的?
- 关于VR(主要是虚拟城市场景)的一些想法及实现(可能会连载)
- 堆