|
|
对于Cubic Environment Mapping,如何解决反射物不在中心原点的情况?
这几天在接触Cubic Environment Mapping,在研究MS的例子时发现一个问题:
就是茶壶(即反射物)只能在世界坐标的原点处(0, 0, 0)
如果将茶壶移动的话,则茶壶反射的景物还是“茶壶在原点处”反射的那些景物。
后来看一些资料,说:
The preceding discussion mentioned that environment mapping assumes that the environment is infinitely distant from the object. Now we explore the implications of this assumption.
The reason for the assumption is that environment maps are accessed solely based on a 3D direction. Environment mapping has no allowance for variations in position to affect the reflected appearance of surfaces. If everything in the environment is sufficiently far away from the surface, then this assumption is approximately true.
换句话说,如果周围的景物足够远,则反射物即使移动也不会产生不太好的效果。
可是对于比较近的景物,比如d3d上的例子(一个房间,一架飞机(暂时改为一架)),则稍微移动一点距离则会出大问题
我想过几个解决办法:
1.作相对移动:即将景物渲染到cube map上时,让景物作反射物的相反运动(矩阵逆变换),这样相当于反射物不动,景物动。但感觉开销比较大,而且渲染的效果并没有达到预期的目的
2.修改DXUTGetCubeMapViewMatrix
将DXUT提供的函数:
D3DXMATRIX DXUTGetCubeMapViewMatrix( DWORD dwFace )
{
D3DXVECTOR3 vEyePt = D3DXVECTOR3( 0.0f, 0.0f, 0.0f );
D3DXVECTOR3 vLookDir;
D3DXVECTOR3 vUpDir;
switch( dwFace )
{
case D3DCUBEMAP_FACE_POSITIVE_X:
vLookDir = D3DXVECTOR3( 1.0f, 0.0f, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
case D3DCUBEMAP_FACE_NEGATIVE_X:
vLookDir = D3DXVECTOR3(-1.0f, 0.0f, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
case D3DCUBEMAP_FACE_POSITIVE_Y:
vLookDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y:
vLookDir = D3DXVECTOR3( 0.0f,-1.0f, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
break;
case D3DCUBEMAP_FACE_POSITIVE_Z:
vLookDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z:
vLookDir = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
}
// Set the view transform for this cubemap surface
D3DXMATRIX mView;
D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookDir, &vUpDir );
return mView;
}
改为
D3DXMATRIX GetCubeMapViewMatrix( DWORD dwFace )
{
D3DXVECTOR3 vEyePt = g_vEnvMeshPos; //反射物在世界坐标中位置
D3DXVECTOR3 vLookDir;
D3DXVECTOR3 vUpDir;
float x, y, z;
x = fabs(g_vEnvMeshPos.x) + 10;
y = fabs(g_vEnvMeshPos.y) + 10;
z = fabs(g_vEnvMeshPos.z) + 10;
switch( dwFace )
{
case D3DCUBEMAP_FACE_POSITIVE_X:
vLookDir = D3DXVECTOR3( x, 0.0f, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
case D3DCUBEMAP_FACE_NEGATIVE_X:
vLookDir = D3DXVECTOR3(-x, 0.0f, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
case D3DCUBEMAP_FACE_POSITIVE_Y:
vLookDir = D3DXVECTOR3( 0.0f, y, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 0.0f,-1.0f );
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y:
vLookDir = D3DXVECTOR3( 0.0f, -y, 0.0f );
vUpDir = D3DXVECTOR3( 0.0f, 0.0f, 1.0f );
break;
case D3DCUBEMAP_FACE_POSITIVE_Z:
vLookDir = D3DXVECTOR3( 0.0f, 0.0f, z );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z:
vLookDir = D3DXVECTOR3( 0.0f, 0.0f, -z );
vUpDir = D3DXVECTOR3( 0.0f, 1.0f, 0.0f );
break;
}
// Set the view transform for this cubemap surface
D3DXMATRIX mView;
D3DXMatrixLookAtLH( &mView, &vEyePt, &vLookDir, &vUpDir );
return mView;
}
这样做的目的很明显,就是从反射物中心的角度作为视点渲染景物到六个面(这也是cube map算法的思想)
我这样改了之后的确能“大概”渲染出想像中的影像,但明显还是发生了问题,如下图:
(注意飞机在世界坐标原点,茶壶离世界坐标有一定距离,并绕Y轴旋转)
(另:反射线是在世界坐标系下求得的)
很明显发生了重影:
http://blog.csdn.net/images/blog_csdn_net/cywater2000/102371/r_cm.jpg
http://blog.csdn.net/images/blog_csdn_net/cywater2000/102371/r_cm2.jpg
没办法,上网找到一个类似的帖:
http://www.gamedev.net/community/forums/topic.asp?topic_id=286471&whichpage=1&#1801494
好像nvidia和ati的人已经解决了?
http://download.nvidia.com/developer/presentations/GDC_2004/GDC_2004_Gems_IBL.pdf
http://www.ati.com/developer/shaderx/ShaderX_CubeEnvironmentMapCorrection.pdf
用球求交的方式?但没太看明白,主要解释得不太清楚...
求助
PS:像<极品飞车9>这样的游戏,是如何在不影响速度的前提下比较精确反射景物的?
|
|