最后一类是渲染函数,类CDXUTMesh重载了两个渲染函数Render(),其作用都是用来渲染当前的网格模型。所不同的是,第一个函数用在固定函数流水线中,第二个函数用在可编程流水线技术中,这两个函数的最后两个参数用于指定是否渲染网格模型中的不透明和半透明部分。
首先来看第一个Render()函数:
HRESULT CDXUTMesh::Render( LPDIRECT3DDEVICE9 pd3dDevice, bool bDrawOpaqueSubsets, bool bDrawAlphaSubsets )
{
if( NULL == m_pMesh )
return E_FAIL;
// Frist, draw the subsets without alpha
if( bDrawOpaqueSubsets )
{
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
if( m_bUseMaterials )
{
if( m_pMaterials[i].Diffuse.a < 1.0f )
continue;
pd3dDevice->SetMaterial( &m_pMaterials[i] );
pd3dDevice->SetTexture( 0, m_pTextures[i] );
}
m_pMesh->DrawSubset( i );
}
}
// Then, draw the subsets with alpha
if( bDrawAlphaSubsets && m_bUseMaterials )
{
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
if( m_pMaterials[i].Diffuse.a == 1.0f )
continue;
// Set the material and texture
pd3dDevice->SetMaterial( &m_pMaterials[i] );
pd3dDevice->SetTexture( 0, m_pTextures[i] );
m_pMesh->DrawSubset( i );
}
}
return S_OK;
}
代码简洁明了,首先绘制不透明的网格(alpha == 1.0f),接着绘制半透明的网格(alpha
!= 1.0f)。
接着来看第二个Render()函数:
HRESULT CDXUTMesh::Render( ID3DXEffect *pEffect,
D3DXHANDLE hTexture, D3DXHANDLE hDiffuse, D3DXHANDLE hAmbient,
D3DXHANDLE hSpecular, D3DXHANDLE hEmissive, D3DXHANDLE hPower,
bool bDrawOpaqueSubsets, bool bDrawAlphaSubsets )
{
if( NULL == m_pMesh )
return E_FAIL;
UINT cPasses;
// Frist, draw the subsets without alpha
if( bDrawOpaqueSubsets )
{
pEffect->Begin( &cPasses, 0 );
for( UINT p = 0; p < cPasses; ++p )
{
pEffect->BeginPass( p );
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
if( m_bUseMaterials )
{
if( m_pMaterials[i].Diffuse.a < 1.0f )
continue;
if( hTexture )
pEffect->SetTexture( hTexture, m_pTextures[i] );
// D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical.
// No conversion is needed.
if( hDiffuse )
pEffect->SetVector( hDiffuse, (D3DXVECTOR4*)&m_pMaterials[i].Diffuse );
if( hAmbient )
pEffect->SetVector( hAmbient, (D3DXVECTOR4*)&m_pMaterials[i].Ambient );
if( hSpecular )
pEffect->SetVector( hSpecular, (D3DXVECTOR4*)&m_pMaterials[i].Specular );
if( hEmissive )
pEffect->SetVector( hEmissive, (D3DXVECTOR4*)&m_pMaterials[i].Emissive );
if( hPower )
pEffect->SetFloat( hPower, m_pMaterials[i].Power );
pEffect->CommitChanges();
}
m_pMesh->DrawSubset( i );
}
pEffect->EndPass();
}
pEffect->End();
}
// Then, draw the subsets with alpha
if( bDrawAlphaSubsets )
{
pEffect->Begin( &cPasses, 0 );
for( UINT p = 0; p < cPasses; ++p )
{
pEffect->BeginPass( p );
for( DWORD i=0; i<m_dwNumMaterials; i++ )
{
if( m_bUseMaterials )
{
if( m_pMaterials[i].Diffuse.a == 1.0f )
continue;
if( hTexture )
pEffect->SetTexture( hTexture, m_pTextures[i] );
// D3DCOLORVALUE and D3DXVECTOR4 are data-wise identical.
// No conversion is needed.
if( hDiffuse )
pEffect->SetVector( hDiffuse, (D3DXVECTOR4*)&m_pMaterials[i].Diffuse );
if( hAmbient )
pEffect->SetVector( hAmbient, (D3DXVECTOR4*)&m_pMaterials[i].Ambient );
if( hSpecular )
pEffect->SetVector( hSpecular, (D3DXVECTOR4*)&m_pMaterials[i].Specular );
if( hEmissive )
pEffect->SetVector( hEmissive, (D3DXVECTOR4*)&m_pMaterials[i].Emissive );
if( hPower )
pEffect->SetFloat( hPower, m_pMaterials[i].Power );
pEffect->CommitChanges();
}
m_pMesh->DrawSubset( i );
}
pEffect->EndPass();
}
pEffect->End();
}
return S_OK;
}
代码也是相当简洁明了,首先绘制不透明网格,接着绘制半透明网格。在绘制时遍历所有的通道,并设置纹理,材质的漫反射光、环境光、镜面反射光、自发光、镜面反射光指数。