beautiful graphics, beautiful world!
转自:http://memecha24.blog.163.com/blog/static/118137909200942494851483/环境反射效果
环境反射效果
就我所知常用的环境贴图有两种,一种是球状的环境贴图;一种是立方体的环境贴图。如果是制作水体的反射或折射效果也可以只做平面的环境贴图。
DirectX中提供了一个很方便的立方体环境贴图。立方体的六个面定义如下:
{
D3DCUBEMAP_FACE_POSITIVE_X = 0,
D3DCUBEMAP_FACE_NEGATIVE_X = 1,
D3DCUBEMAP_FACE_POSITIVE_Y = 2,
D3DCUBEMAP_FACE_NEGATIVE_Y = 3,
D3DCUBEMAP_FACE_POSITIVE_Z = 4,
D3DCUBEMAP_FACE_NEGATIVE_Z = 5,
D3DCUBEMAP_FACE_FORCE_DWORD = 0x7fffffff
} D3DCUBEMAP_FACES;
如下图所示:
实现原理也很简单:
1、把立方体环境贴图放到反射物体所知位置,并把该反射物体以外的东西映射到立方体环境贴图上。
2、根据摄像机到反射物体表面的点的向量a和该点的法向量n,求出a的反射向量b。
3、以反射向量b作为立方体环境贴图的寻址,把它所对应的颜色赋给反射物体上的点。
实现过程需要用到一个立方体环境贴图和一个深度表面,步骤如下:
LPDIRECT3DCUBETEXTURE9 m_pReflectCubeTex; //反射的立方贴图
LPDIRECT3DSURFACE9 m_pSurfDepthCube; // DepthStencilSurface
2、初始化
HRESULT hr;
//创建 DepthStencilSurface
DXUTDeviceSettings d3dSettings = DXUTGetDeviceSettings();
hr = pDev->CreateDepthStencilSurface( ENVMAPSIZE,
ENVMAPSIZE,
d3dSettings.pp.AutoDepthStencilFormat,
D3DMULTISAMPLE_NONE,
0,
TRUE,
& m_pSurfDepthCube,
NULL );
if( FAILED( hr))
return hr;
//创建立方体贴图
hr = pDev->CreateCubeTexture( ENVMAPSIZE,
1,
D3DUSAGE_RENDERTARGET,
D3DFMT_A16B16G16R16F,
D3DPOOL_DEFAULT,
& m_pReflectCubeTex,
if( FAILED( hr) )
3、把被反射物体渲染到立方体环境贴图中
//------------------------------------------------------------
//desc: 渲染反射场景
//param: pDev 设备
//return: 是否创建成功
HRESULT GRenderMaterialProxy::RenderReflectScene(LPDIRECT3DDEVICE9 pDev)
if( pDev == NULL)
return E_FAIL;
LPDIRECT3DSURFACE9 pSufRTBackup; //RenderTarget 备份
LPDIRECT3DSURFACE9 pSufDSBackup; //DepthStencilSurface 备份
pDev->GetRenderTarget( 0, & pSufRTBackup);
if( SUCCEEDED( pDev->GetDepthStencilSurface( & pSufDSBackup) ) )
pDev->SetDepthStencilSurface( m_pSurfDepthCube);
}
//以反射物体为中心,设置视口投影矩阵
LPDIRECT3DSURFACE9 pSurf;
D3DXMATRIXA16 mView, mProj;
D3DXMATRIXA16 mViewDir( * GCameraManager::GetInstance()->GetCamera()->GetViewMatrix() );
mViewDir._41 = mViewDir._42 = mViewDir._43 = 0.0f;
D3DXMatrixPerspectiveFovLH( &mProj, D3DX_PI * 0.5f, 1.0f, 0.01f, 10000.0f );
std::vector< IRenderObject *>::iterator itRenderObj;
//渲染Cube 6个表面
for( int iFace = 0; iFace < 6; ++iFace)
//获取立方体环境贴图表面,并设为设备的渲染目标
//注意:GetCubeMapSurface的第二个参数0表示获取立方体环境贴图的表面
//如果是 n则表示获取立方体环境贴图的第n层表面
V( m_pReflectCubeTex->GetCubeMapSurface( ( D3DCUBEMAP_FACES) iFace, 0, & pSurf));
V( pDev->SetRenderTarget( 0, pSurf));
mView = DXUTGetCubeMapViewMatrix( iFace);
D3DXMatrixMultiply( & mView, & mViewDir, & mView);
V( pDev->Clear( 0L, NULL, D3DCLEAR_ZBUFFER, 0x000000ff, 1.0f, 0L ));
//渲染被反射物体
for( itRenderObj = m_vpReflectObjects.begin(); itRenderObj != m_vpReflectObjects.end(); itRenderObj++)
(*itRenderObj)->Render( pDev, & mView, & mProj);
SAFE_RELEASE( pSurf);
if( pSufDSBackup)
pDev->SetDepthStencilSurface( pSufDSBackup); //恢复深度表面
SAFE_RELEASE( pSufDSBackup);
pDev->SetRenderTarget( 0, pSufRTBackup); //恢复渲染目标
SAFE_RELEASE( pSufRTBackup);
return S_OK;
4、根据立方体环境贴图确定反射物体的颜色(用HLSL实现)
//渲染环境贴图
if( m_bEnableReflect)
RenderReflectScene( pDev);
D3DXMATRIXA16 mWorld, mView, mProj, mWorldView;
CBaseCamera * pCamera = GCameraManager::GetInstance()->GetCamera();
D3DXVECTOR4 vEyePos = D3DXVECTOR4(* GCameraManager::GetInstance()->GetCamera()->GetEyePt(), 0.0f);
D3DXMATRIXA16 mEyePos;
::D3DXMatrixTranslation( & mEyePos, vEyePos.x, vEyePos.y, vEyePos.z);
::D3DXMatrixTranslation( & mWorld, 0.0f, 0.0f, 0.0f);
mView = * pCamera->GetViewMatrix();
mProj = * pCamera->GetProjMatrix();
GVector4 * pLightDirList = G3DSceneManager::GetInstance()->GetLightDirList();
UINT iLightCount = G3DSceneManager::GetInstance()->GetLightCount();
//设置变化矩阵
m_pEffect->SetMatrix("g_mWorld", &mWorld);
m_pEffect->SetMatrix("g_mProj", &mProj);
m_pEffect->SetMatrix("g_mView", &mView);
m_pEffect->SetTexture("g_texReflect", m_pReflectCubeTex); //设置立方体环境贴图
m_pEffect->SetFloat("g_fReflectivity", m_fReflectivity); //设置反射率
( fx文件代码如下)
extern matrix g_mWorld;
extern matrix g_mView;
extern matrix g_mProj;
texture g_texReflect;
float g_fReflectivity = 0.9f;
samplerCUBE g_samReflect =
sampler_state
Texture = <g_texReflect>;
MinFilter = Linear;
MagFilter = Linear;
MipFilter = Linear;
};
void VS_Reflect( float4 iPos : POSITION,
float3 iNor : NORMAL,
out float4 oPos : POSITION,
out float3 oEnvTex : TEXCOORD0 )
matrix mWorldView = mul( g_mWorld, g_mView);
oPos = mul( iPos, mWorldView);
float3 vN = mul( iNor, mWorldView);
vN = normalize( vN);
float3 vEyeR = -normalize( oPos);
float3 vRef;
vRef = 2 * dot( vEyeR, vN) * vN - vEyeR;
//vRef = reflect( vEyeR, vN);
oEnvTex = vRef;
oPos = mul( oPos, g_mProj);
float4 PS_Reflect( float3 iTex : TEXCOORD0 ) : COLOR
float4 fColor = texCUBE( g_samReflect, iTex);
fColor.x = fColor.x * g_fReflectivity;
fColor.y = fColor.y * g_fReflectivity;
fColor.z = fColor.z * g_fReflectivity;
return fColor;
technique Tec_RenderMaterial
pass p0
vertexShader = compile vs_2_0 VS_Reflect();
pixelShader = compile ps_2_0 PS_Reflect();
实现效果如下:
posted on 2009-09-28 10:27 koilin 阅读(886) 评论(0) 编辑 收藏 引用
Powered by: C++博客 Copyright © koilin