📄 shader_trees.cpp
字号:
{
m_pD3DDev->DeleteVertexShader(m_dwTreeShader);
m_pD3DDev->DeleteVertexShader(m_dwTerrainShader);
SAFE_RELEASE(m_pD3DDev);
}
return S_OK;
}
HRESULT CShaderTrees::Start()
{
return S_OK;
}
HRESULT CShaderTrees::SetTransform()
{
D3DXMATRIX matTemp;
D3DXMATRIX matWorldViewProj;
D3DXMATRIX matWorldView;
D3DXMATRIX matWorldViewIT;
D3DXMATRIX matWorld = m_pNVDevice->GetWorldTransform();
D3DXMATRIX matView = m_pNVDevice->GetViewTransform();
D3DXMATRIX matProj = m_pNVDevice->GetProjectionTransform();
D3DXMatrixMultiply(&matTemp, &matWorld, &matView);
D3DXMatrixMultiply(&matWorldViewProj, &matTemp, &matProj);
D3DXMatrixMultiply(&matWorldView, &matWorld, &matView);
// Create a 3x3 invertse of the worldview for the normal transformation (we transpose it as we load it into
// the constant store)
D3DXMatrixInverse(&matWorldViewIT, NULL, &matWorldView);
// Projection to clip space
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWPROJ_0, &matWorldViewProj(0, 0), 4);
D3DXMatrixTranspose(&matWorldViewProj, &matWorldViewProj);
// Transform to eye space
D3DXMatrixTranspose(&matWorldView, &matWorldView);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEW_0, &matWorldView(0, 0), 4);
D3DXMatrixTranspose(&matWorldView, &matWorldView);
// Transform from eye to projection
D3DXMatrixTranspose(&matProj, &matProj);
m_pD3DDev->SetVertexShaderConstant(CV_PROJ_0, &matProj(0, 0), 4);
D3DXMatrixTranspose(&matProj, &matProj);
// Transform for normals
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_0, &matWorldViewIT(0, 0), 1);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_1, &matWorldViewIT(1, 0), 1);
m_pD3DDev->SetVertexShaderConstant(CV_WORLDVIEWIT_2, &matWorldViewIT(2, 0), 1);
// Sometimes we don't need the shader - just draw with the current world/view/projection matrices
m_pD3DDev->SetTransform(D3DTS_WORLD, &matWorld);
m_pD3DDev->SetTransform(D3DTS_VIEW, &matView);
m_pD3DDev->SetTransform(D3DTS_PROJECTION, &matProj);
return S_OK;
}
HRESULT CShaderTrees::DrawFishViewport()
{
// Draw the background
m_pD3DDev->SetTexture(0, m_pFishViewTexture);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, FALSE);
m_pD3DDev->SetStreamSource(0, m_pFishViewVB, sizeof(TLVertex));
m_pD3DDev->SetVertexShader(D3DFVF_TLVERTEX);
// Enable alpha testing to overdraw the outer pixels
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDev->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_SRCALPHA);
m_pD3DDev->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
m_pD3DDev->SetRenderState( D3DRS_ALPHAREF, 0x80);
m_pD3DDev->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_LESS);
m_pD3DDev->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2 );
// Restore render states
m_pD3DDev->SetRenderState(D3DRS_ZENABLE, TRUE);
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
m_pD3DDev->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE);
return S_OK;
}
HRESULT CShaderTrees::DrawTrees(bool bDistort)
{
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
m_pNVDevice->SetWorldTransform(&matWorld);
SetTransform();
// Set state for drawing trees
m_pD3DDev->SetTexture( 0, m_pTreeTexture);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_NONE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
// Set diffuse blending for alpha set in vertices.
m_pD3DDev->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
m_pD3DDev->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pD3DDev->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
// Enable alpha testing (skips pixels with less than a certain alpha.)
m_pD3DDev->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE );
m_pD3DDev->SetRenderState( D3DRS_ALPHAREF, 0x80);
m_pD3DDev->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATER);
if (bDistort)
{
m_pD3DDev->SetVertexShader(m_dwTreeShader);
}
else
{
m_pD3DDev->SetVertexShader(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1);
}
// Copy tree mesh into vertexbuffer
TREEVERTEX* v;
m_pTreeVB->Lock( 0, 0, (BYTE**)&v, D3DLOCK_DISCARD );
for( DWORD i=0; i<NUM_TREES; i++ )
{
memcpy( v, m_vecTrees[i].v, 4*sizeof(TREEVERTEX) );
v += 4;
}
m_pTreeVB->Unlock();
m_pD3DDev->SetStreamSource( 0, m_pTreeVB, sizeof(TREEVERTEX) );
// Loop through and render all trees
for( i=0; i<NUM_TREES; i++ )
{
// Translate the billboard into place
m_matBillboardMatrix._41 = m_vecTrees[i].vPos.x;
m_matBillboardMatrix._42 = m_vecTrees[i].vPos.y;
m_matBillboardMatrix._43 = m_vecTrees[i].vPos.z;
// Load values
m_pNVDevice->SetWorldTransform(&m_matBillboardMatrix);
SetTransform();
// Render the billboard
m_pD3DDev->DrawPrimitive( D3DPT_TRIANGLESTRIP, i*4, 2 );
}
m_pD3DDev->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
m_pD3DDev->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
return S_OK;
}
HRESULT CShaderTrees::DrawTerrain(bool bDistort)
{
D3DXMATRIX matWorld;
D3DXMatrixIdentity(&matWorld);
m_pNVDevice->SetWorldTransform(&matWorld);
SetTransform();
// Set terrain state
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE);
m_pD3DDev->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0);
m_pD3DDev->SetTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
m_pD3DDev->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
m_pD3DDev->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
// Draw the terrain
if (bDistort)
{
m_pTerrain->SetVertexShader(m_dwTerrainShader);
}
else
{
m_pTerrain->SetVertexShader(0);
}
// Call the terrain object to do the work
m_pTerrain->Render(m_pNVDevice);
return S_OK;
}
HRESULT CShaderTrees::Tick(EBTimer* pTimer)
{
HRESULT hr = S_OK;
D3DXMATRIX matTemp;
D3DXMATRIX matWorld;
D3DXMATRIX matView;
D3DVIEWPORT8 Viewport;
D3DVIEWPORT8 NewViewport;
D3DXVECTOR3 vEyePt;
D3DXVECTOR3 vLookatPt;
D3DXVECTOR3 vUpVec( 0.0f, 1.0f, 0.0f );
m_pD3DDev->SetRenderState(D3DRS_FILLMODE, (mbWireFrame) ? D3DFILL_WIREFRAME : D3DFILL_SOLID);
hr = m_pD3DDev->Clear(0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB( 0xAA, 0xAA, 0xAA ), 1.0, 0);
float const kSpeed = 20.0f;
if (!m_bPause)
{
m_fDuration = pTimer->GetDuration();
}
// Move the camera about a large circle through the trees
vEyePt.x = 30.0f*cosf( ((m_fDuration+0.0f)/kSpeed) * 2 * D3DX_PI );
vEyePt.z = 30.0f*sinf( ((m_fDuration+0.0f)/kSpeed) * 2 * D3DX_PI );
vEyePt.y = 5.5f + HeightField( vEyePt.x, vEyePt.z );
vLookatPt.x = 30.0f*cosf( ((m_fDuration+0.5f)/kSpeed) * 2 * D3DX_PI );
vLookatPt.z = 30.0f*sinf( ((m_fDuration+0.5f)/kSpeed) * 2 * D3DX_PI );
vLookatPt.y = 4.2f + HeightField(vEyePt.x, vEyePt.z);
// Identity world transform
D3DXMatrixIdentity(&matWorld);
// Set the app view matrix for normal viewing
D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec );
// Set up a rotation matrix to orient the billboard towards the camera.
D3DXVECTOR3 vDir = vLookatPt - vEyePt;
if( vDir.x > 0.0f )
D3DXMatrixRotationY( &m_matBillboardMatrix, -atanf(vDir.z/vDir.x)+D3DX_PI/2 );
else
D3DXMatrixRotationY( &m_matBillboardMatrix, -atanf(vDir.z/vDir.x)-D3DX_PI/2 );
// Sort trees in back-to-front order
sort(m_vecTrees.begin(), m_vecTrees.end(), CompareToEye(vEyePt) );
// Get the current viewport
m_pD3DDev->GetViewport(&Viewport);
memcpy(&NewViewport, &Viewport, sizeof(D3DVIEWPORT8));
// Draw fish-eye pass
// Setup the viewport to the top half
NewViewport.Height = Viewport.Height / 2;
m_pD3DDev->SetViewport(&NewViewport);
// Set the current transform
m_pNVDevice->SetWorldTransform(&matWorld);
m_pNVDevice->SetViewTransform(&matView);
SetTransform();
// Draw the terrain
DrawTerrain(true);
// Draw the trees
DrawTrees(true);
// Draw the fisheye view
DrawFishViewport();
// Draw the undistorted view of the world
// Set viewport to be the bottom
NewViewport.Y = (Viewport.Height / 2) + 2;
NewViewport.Height -= 2;
m_pD3DDev->SetViewport(&NewViewport);
SetTransform();
// Draw terrain
DrawTerrain(false);
// Draw the trees
DrawTrees(false);
// Restore the viewport
m_pD3DDev->SetViewport(&Viewport);
return hr;
}
void NVTreeDevice::SetWorldTransform(const D3DXMATRIX* pValue)
{
NVDevice::SetWorldTransform(pValue);
m_pTreeShader->SetTransform();
}
HRESULT CShaderTrees::ConfirmDevice(D3DCAPS8* pCaps, DWORD dwBehavior, D3DFORMAT Format)
{
return S_OK;
}
void CShaderTrees::Keyboard(DWORD dwKey, UINT nFlags, bool bDown)
{
eEBKeyAction Action = TranslateEffectKey(dwKey, nFlags, bDown);
switch ( Action )
{
case EB_HELP:
{
::MessageBoxEx( NULL, " Help : F1 - Help \n\n W - Wireframe Toggle \n\n P\\Pause - Pause animation\n\n",
"Help", MB_ICONINFORMATION | MB_TASKMODAL, MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ) );
}
break;
case EB_WIREFRAME:
{
mbWireFrame = !mbWireFrame;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
case EB_PAUSE:
{
m_bPause = !m_bPause;
m_dwEffectDirtyFlags |= EBEFFECT_DIRTY_PUBLICSTATE;
}
break;
default:
break;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -