就我所知常用的环境贴图有两种,一种是球状的环境贴图;一种是立方体的环境贴图。如果是制作水体的反射或折射效果也可以只做平面的环境贴图。 DirectX中提供了一个很方便的立方体环境贴图。立方体的六个面定义如下: typedef enum _D3DCUBEMAP_FACES { 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作为立方体环境贴图的寻址,把它所对应的颜色赋给反射物体上的点。 实现过程需要用到一个立方体环境贴图和一个深度表面,步骤如下: 1、定义 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, NULL ); if( FAILED( hr) ) return hr; 3、把被反射物体渲染到立方体环境贴图中 //------------------------------------------------------------ //desc: 渲染反射场景 //param: pDev 设备 //return: 是否创建成功 //------------------------------------------------------------ HRESULT GRenderMaterialProxy::RenderReflectScene(LPDIRECT3DDEVICE9 pDev) { HRESULT hr; 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(); } } 实现效果如下: http://www.cppblog.com/Herbert/archive/2009/02/11/73489.html