投影矩阵到底长什么样子?
2013-07-18 21:25
176 查看
首先很惭愧的说,我学了好多年图形学连这个问题都回答不出。所以回过头来补充一下这方面的知识。这个问题是我在看DirectX中的Pick sample中的Pick()函数时发现的。Pick()函数里把一条屏幕射线变换到模型局部空间。看它是怎么变的:
const D3DXMATRIX* pmatProj = g_Camera.GetProjMatrix();
POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( DXUTGetHWND(), &ptCursor );
// Compute the vector of the Pick ray in screen space
D3DXVECTOR3 v;
v.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
v.z = 1.0f;
// Get the inverse view matrix
const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
D3DXMATRIX mWorldView = matWorld * matView;
D3DXMATRIX m;
D3DXMatrixInverse( &m, NULL, &mWorldView );
// Transform the screen space Pick ray into 3D space
vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;
vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;
vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
先回顾一些知识。1)DirectX和OpenGL中矩阵向量区别,详见这里 2)齐次坐标,3D变换,详见这里
3 ) 透视投影变换推导请看这里。4) view与world的区别。
从Normalized device space 到 window space的具体变换公式是
xw,yw是屏幕坐标, 也就是ptCursor.x,ptCursor.y。
xnd,ynd是做完投影归一化后得到的坐标。
x, y是窗口左下角的坐标。在本例Pick例中x = y = 0。
现在来看
v.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ),-( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 )是将屏幕坐标变换到归一化的投影坐标空间,这个可以理解了。
( 这个归一化的空间是个axis-aligned cube. 在OpenGL中是[-1,-1,-1], [1, 1, 1]分别作为cube的minimum corner and maximum corner。在DirectX中是[-1,-1, 0],[1, 1, 0]。详情请查看Realtime Rendering 3rd version )
现在还差/pmatProj->_11, /pmatProj->_22暂时无法理解。
OpenGL中透视矩阵为
DirectX中是以上矩阵的转置。
不论是从Realtime rendering 3rd version上还是某大牛的具体推导,都是以上矩阵形式。 那为什么会是/pmatProj->_11, /pmatProj->_22?
百思不得其解以后,我调试进入相应代码位置,发现这个pmatProj矩阵不同于以上所谓的投影矩阵,它是从函数
D3DXMatrixPerspectiveFovLH( &m_mProj, fFOV, fAspect, fNearPlane, fFarPlane )返回的。
m_mProj这个矩阵只有_11,_22, _33,_34, _43, 不为0,其他元素都为0。
回头一想,肯定是由于right = -left, top = -bottom, 所以_30 = 0, _31 = 0.
所以/pmatProj->_11, /pmatProj->_22之后就是投影之前的x, y坐标了。
最后的变换是将射线变换到局部空间,
// Get the inverse view matrix
const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
D3DXMATRIX mWorldView = matWorld * matView;
D3DXMATRIX m;
D3DXMatrixInverse( &m, NULL, &mWorldView );
// Transform the screen space Pick ray into 3D space
vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;
vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;
vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
最后一个问题是为什么vPickRayOrig只跟 m 有关系而跟拾取点无关呢?希望有大牛来帮忙解答一下。
今天看到OpenGPU坛子上有朋友也发了这个问题而且有好多朋友已经回答了。
原来view 空间其实应该是从视点发出来的一些斜线。
http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=15692
const D3DXMATRIX* pmatProj = g_Camera.GetProjMatrix();
POINT ptCursor;
GetCursorPos( &ptCursor );
ScreenToClient( DXUTGetHWND(), &ptCursor );
// Compute the vector of the Pick ray in screen space
D3DXVECTOR3 v;
v.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
v.z = 1.0f;
// Get the inverse view matrix
const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
D3DXMATRIX mWorldView = matWorld * matView;
D3DXMATRIX m;
D3DXMatrixInverse( &m, NULL, &mWorldView );
// Transform the screen space Pick ray into 3D space
vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;
vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;
vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
先回顾一些知识。1)DirectX和OpenGL中矩阵向量区别,详见这里 2)齐次坐标,3D变换,详见这里
3 ) 透视投影变换推导请看这里。4) view与world的区别。
从Normalized device space 到 window space的具体变换公式是
xw,yw是屏幕坐标, 也就是ptCursor.x,ptCursor.y。
xnd,ynd是做完投影归一化后得到的坐标。
x, y是窗口左下角的坐标。在本例Pick例中x = y = 0。
现在来看
v.x = ( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ) / pmatProj->_11;
v.y = -( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 ) / pmatProj->_22;
( ( ( 2.0f * ptCursor.x ) / pd3dsdBackBuffer->Width ) - 1 ),-( ( ( 2.0f * ptCursor.y ) / pd3dsdBackBuffer->Height ) - 1 )是将屏幕坐标变换到归一化的投影坐标空间,这个可以理解了。
( 这个归一化的空间是个axis-aligned cube. 在OpenGL中是[-1,-1,-1], [1, 1, 1]分别作为cube的minimum corner and maximum corner。在DirectX中是[-1,-1, 0],[1, 1, 0]。详情请查看Realtime Rendering 3rd version )
现在还差/pmatProj->_11, /pmatProj->_22暂时无法理解。
OpenGL中透视矩阵为
DirectX中是以上矩阵的转置。
不论是从Realtime rendering 3rd version上还是某大牛的具体推导,都是以上矩阵形式。 那为什么会是/pmatProj->_11, /pmatProj->_22?
百思不得其解以后,我调试进入相应代码位置,发现这个pmatProj矩阵不同于以上所谓的投影矩阵,它是从函数
D3DXMatrixPerspectiveFovLH( &m_mProj, fFOV, fAspect, fNearPlane, fFarPlane )返回的。
m_mProj这个矩阵只有_11,_22, _33,_34, _43, 不为0,其他元素都为0。
回头一想,肯定是由于right = -left, top = -bottom, 所以_30 = 0, _31 = 0.
所以/pmatProj->_11, /pmatProj->_22之后就是投影之前的x, y坐标了。
最后的变换是将射线变换到局部空间,
// Get the inverse view matrix
const D3DXMATRIX matView = *g_Camera.GetViewMatrix();
const D3DXMATRIX matWorld = *g_Camera.GetWorldMatrix();
D3DXMATRIX mWorldView = matWorld * matView;
D3DXMATRIX m;
D3DXMatrixInverse( &m, NULL, &mWorldView );
// Transform the screen space Pick ray into 3D space
vPickRayDir.x = v.x * m._11 + v.y * m._21 + v.z * m._31;
vPickRayDir.y = v.x * m._12 + v.y * m._22 + v.z * m._32;
vPickRayDir.z = v.x * m._13 + v.y * m._23 + v.z * m._33;
vPickRayOrig.x = m._41;
vPickRayOrig.y = m._42;
vPickRayOrig.z = m._43;
最后一个问题是为什么vPickRayOrig只跟 m 有关系而跟拾取点无关呢?希望有大牛来帮忙解答一下。
今天看到OpenGPU坛子上有朋友也发了这个问题而且有好多朋友已经回答了。
原来view 空间其实应该是从视点发出来的一些斜线。
http://www.opengpu.org/bbs/forum.php?mod=viewthread&tid=15692
相关文章推荐
- 喜欢到底是什么样子呢
- 线性矩阵到底是什么
- 我们所期待的WPF/E到底是什么样子?
- 聊聊目标文件到底长什么样子
- 真正的程序员到底应该是什么样子的?
- 那些NB哄哄的负载均衡算法到底是什么样子的?
- 互联网究竟带来中心化还是去中心化 那些赚钱的模式 探讨下互联网会把社会改造成什么样子,到底是中心化还是去中心化
- hadoop的版本到底什么样子
- 矩阵的相似对角化到底有什么用?该不会是纯粹的理论吧?
- 成熟--到底是什么样子的?
- 喜欢到底是什么样子呢
- 互联网思维到底是什么?
- javascript中的this到底指什么?
- 投影矩阵和模型视角矩阵
- Others6_USB Type-C到底是什么
- 绝对路径在不同环境下 到底是相对于什么的绝对
- Java进阶(二)当我们说线程安全时,到底在说什么
- 钱到底是个什么东西?
- 2007-08-28 日志:佛穿上西装是什么样子?记几个小小的开悟