koilin

beautiful graphics, beautiful world!

常用链接

统计

最新评论

cube map

转自:http://memecha24.blog.163.com/blog/static/118137909200942494851483/

环境反射效果

图像处理   2009-05-24 21:48   阅读24   评论0  
字号:    

环境反射效果

  就我所知常用的环境贴图有两种,一种是球状的环境贴图;一种是立方体的环境贴图。如果是制作水体的反射或折射效果也可以只做平面的环境贴图。

  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;

 

如下图所示:

环境反射效果  - Ben - Ben

   实现原理也很简单:

   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(); 

 }

}

 

实现效果如下:

环境反射效果  - Ben - Ben

环境反射效果  - Ben - Ben

posted on 2009-09-28 10:27 koilin 阅读(863) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理