如果我們能時時刻刻都在學習,從觀察、聆聽、注視和行動中學習,那么你會發現,學習是不斷進展,永無過去 | 學習技術不是發財之道 | 學習技術,因為崇尚科學與真理
就我所知常用的環境貼圖有兩種,一種是球狀的環境貼圖;一種是立方體的環境貼圖。如果是制作水體的反射或折射效果也可以只做平面的環境貼圖。 DirectX中提供了一個很方便的立方體環境貼圖。立方體的六個面定義如下:
D3DCUBEMAP_FACE_FORCE_DWORD = 0x7fffffff} D3DCUBEMAP_FACES;
如下圖所示: 實現原理也很簡單: 1、把立方體環境貼圖放到反射物體所知位置,并把該反射物體以外的東西映射到立方體環境貼圖上。 2、根據攝像機到反射物體表面的點的向量a和該點的法向量n,求出a的反射向量b。 3、以反射向量b作為立方體環境貼圖的尋址,把它所對應的顏色賦給反射物體上的點。 實現過程需要用到一個立方體環境貼圖和一個深度表面,步驟如下:
//創建 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(); }}
實現效果如下:
Copyright Copyright Herbert