📄 shadow.cpp
字号:
D3DXMatrixRotationX( &matRotX, m_fWorldRotX );
D3DXMatrixRotationY( &matRotY, m_fWorldRotY );
// 物体的变换矩阵
D3DXMatrixMultiply( &matWorld, &matRotY, &matRotX );
D3DXMatrixTranslation( &matPos, 0, 1, 0 );
m_matWorld = matWorld * matPos;
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: UpdateInput()
// Desc: Update the user input. Called once per frame
//-----------------------------------------------------------------------------
void CMyD3DApplication::UpdateInput( UserInput* pUserInput )
{
pUserInput->bRotateUp = ( m_bActive && (GetAsyncKeyState( VK_UP ) & 0x8000) == 0x8000 );
pUserInput->bRotateDown = ( m_bActive && (GetAsyncKeyState( VK_DOWN ) & 0x8000) == 0x8000 );
pUserInput->bRotateLeft = ( m_bActive && (GetAsyncKeyState( VK_LEFT ) & 0x8000) == 0x8000 );
pUserInput->bRotateRight = ( m_bActive && (GetAsyncKeyState( VK_RIGHT ) & 0x8000) == 0x8000 );
}
// 绘制底.
void CMyD3DApplication::DrawFloor()
{
D3DXMATRIXA16 matWorld;
D3DXMatrixIdentity( &matWorld );
D3DXMatrixRotationX( &matWorld, -(D3DX_PI)/2.0f );
matWorld._41 = -.5f;
matWorld._42 = -.1f;
matWorld._43 = 6.0f;
m_pd3dDevice->SetMaterial( &m_matFloor );
m_pd3dDevice->SetTexture( 0, m_ptexFloor );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matWorld );
m_pMeshFloor->DrawSubset(0);
}
// 绘制物体.
void CMyD3DApplication::DrawOcc()
{
m_pd3dDevice->SetMaterial( &m_matOcc );
m_pd3dDevice->SetTexture( 0, m_ptexOcc );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld );
m_pMeshOcc->DrawSubset(0);
}
// 在stencil缓冲绘制物体阴影.
void CMyD3DApplication::DrawStencil()
{
D3DXMATRIXA16 matShadow;
D3DXMatrixShadow( &matShadow, &m_vLightPos, &m_planeFloor );
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); // 关闭Z缓冲
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE ); // 禁止在Z缓冲书写
m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE ); // 打开stencil缓冲
m_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT ); // 防止出现瑕疵,flat着色器
m_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_ALWAYS ); // 设定stencil参数
m_pd3dDevice->SetRenderState( D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP );
m_pd3dDevice->SetRenderState( D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP );
m_pd3dDevice->SetRenderState( D3DRS_STENCILREF, 0x1 ); // 增加的值
m_pd3dDevice->SetRenderState( D3DRS_STENCILMASK, 0xffffffff );
m_pd3dDevice->SetRenderState( D3DRS_STENCILWRITEMASK, 0xffffffff );
m_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_INCR ); // 如果绘制了点,就会在stencil中一个一个增加
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); // 防止在画面绘制网格
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ZERO );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
matShadow = m_matWorld * matShadow;
m_pd3dDevice->SetTransform( D3DTS_WORLD, &matShadow );
m_pMeshOcc->DrawSubset(0); // 在stencil绘制网格.
// 渲染状态复原
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
m_pd3dDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
}
// 在画面绘制物体阴影.
void CMyD3DApplication::DrawShadow()
{
struct SQUARE
{
enum { FVF = D3DFVF_XYZRHW | D3DFVF_DIFFUSE };
D3DXVECTOR4 p; // pos
DWORD d; // diffuse
};
// 覆盖整个画面的网格(四边形)
SQUARE v[4];
FLOAT sx = (FLOAT)m_d3dsdBackBuffer.Width;
FLOAT sy = (FLOAT)m_d3dsdBackBuffer.Height;
v[0].p = D3DXVECTOR4( 0, sy, 0.0f, 1.0f );
v[1].p = D3DXVECTOR4( 0, 0, 0.0f, 1.0f );
v[2].p = D3DXVECTOR4( sx, sy, 0.0f, 1.0f );
v[3].p = D3DXVECTOR4( sx, 0, 0.0f, 1.0f );
v[0].d = 0x7f000000;
v[1].d = 0x7f000000;
v[2].d = 0x7f000000;
v[3].d = 0x7f000000;
DrawStencil(); // 在stencil缓冲绘制阴影
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); // 关闭Z缓冲
m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, TRUE ); // 打开stencil
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE ); // 打开alpha blending
m_pd3dDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
m_pd3dDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE );
m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
m_pd3dDevice->SetRenderState( D3DRS_STENCILREF, 0x1 ); // 和1比较运算
m_pd3dDevice->SetRenderState( D3DRS_STENCILFUNC, D3DCMP_LESSEQUAL ); // 如果(stencil值 >= 1) ,就绘制.
m_pd3dDevice->SetRenderState( D3DRS_STENCILPASS, D3DSTENCILOP_KEEP );
m_pd3dDevice->SetFVF( SQUARE::FVF );
m_pd3dDevice->DrawPrimitiveUP( D3DPT_TRIANGLESTRIP, 2, &v[0], sizeof(SQUARE) );
m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_STENCILENABLE, FALSE );
m_pd3dDevice->SetRenderState( D3DRS_FOGENABLE, TRUE );
m_pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );
}
//-----------------------------------------------------------------------------
// Name: Render()
// Desc: Called once per frame, the call is the entry point for 3d
// rendering. This function sets up render states, clears the
// viewport, and renders the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::Render()
{
// Clear the viewport
m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL,
0xffc0c0c0, 1.0f, 0L );
// Begin the scene
if( SUCCEEDED( m_pd3dDevice->BeginScene() ) )
{
DrawFloor(); // 绘制底
if( m_bShadow ) DrawShadow(); // 绘制阴影
DrawOcc(); // 绘制网格
// Render stats and help text
RenderText();
// End the scene.
m_pd3dDevice->EndScene();
}
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: RenderText()
// Desc: Renders stats and help text to the scene.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::RenderText()
{
D3DCOLOR fontColor = D3DCOLOR_ARGB(255,255,255,0);
TCHAR szMsg[MAX_PATH] = TEXT("");
// Output display stats
FLOAT fNextLine = 40.0f;
lstrcpy( szMsg, m_strDeviceStats );
fNextLine -= 20.0f;
m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
lstrcpy( szMsg, m_strFrameStats );
fNextLine -= 20.0f;
m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
// Output statistics & help
fNextLine = (FLOAT) m_d3dsdBackBuffer.Height;
wsprintf( szMsg, TEXT("Arrow keys: Up=%d Down=%d Left=%d Right=%d"),
m_UserInput.bRotateUp, m_UserInput.bRotateDown, m_UserInput.bRotateLeft, m_UserInput.bRotateRight );
fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
lstrcpy( szMsg, TEXT("Use arrow keys to rotate object") );
fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
lstrcpy( szMsg, TEXT("Press 'F2' to configure display") );
fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: MsgProc()
// Desc: Overrrides the main WndProc, so the sample can do custom message
// handling (e.g. processing mouse, keyboard, or menu commands).
//-----------------------------------------------------------------------------
LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT msg, WPARAM wParam,
LPARAM lParam )
{
switch( msg )
{
case WM_KEYDOWN :
{
switch( wParam )
{
case VK_ESCAPE :
PostMessage( hWnd, WM_DESTROY, 0, 0L );
break;
case '1' :
m_bWireframe = !m_bWireframe;
m_pd3dDevice->SetRenderState( D3DRS_FILLMODE, m_bWireframe ? D3DFILL_WIREFRAME : D3DFILL_SOLID );
break;
case '2' :
m_bShadow = !m_bShadow;
break;
}
}
case WM_PAINT:
{
if( m_bLoadingApp )
{
// Draw on the window tell the user that the app is loading
// TODO: change as needed
HDC hDC = GetDC( hWnd );
TCHAR strMsg[MAX_PATH];
wsprintf( strMsg, TEXT("Loading... Please wait") );
RECT rct;
GetClientRect( hWnd, &rct );
DrawText( hDC, strMsg, -1, &rct, DT_CENTER|DT_VCENTER|DT_SINGLELINE );
ReleaseDC( hWnd, hDC );
}
break;
}
}
return CD3DApplication::MsgProc( hWnd, msg, wParam, lParam );
}
//-----------------------------------------------------------------------------
// Name: InvalidateDeviceObjects()
// Desc: Invalidates device objects. Paired with RestoreDeviceObjects()
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::InvalidateDeviceObjects()
{
// TODO: Cleanup any objects created in RestoreDeviceObjects()
m_pFont->InvalidateDeviceObjects();
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: DeleteDeviceObjects()
// Desc: Paired with InitDeviceObjects()
// Called when the app is exiting, or the device is being changed,
// this function deletes any device dependent objects.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::DeleteDeviceObjects()
{
// TODO: Cleanup any objects created in InitDeviceObjects()
m_pFont->DeleteDeviceObjects();
SAFE_RELEASE( m_pMeshFloor );
SAFE_RELEASE( m_pMeshOcc );
SAFE_RELEASE( m_ptexFloor );
SAFE_RELEASE( m_ptexOcc );
return S_OK;
}
//-----------------------------------------------------------------------------
// Name: FinalCleanup()
// Desc: Paired with OneTimeSceneInit()
// Called before the app exits, this function gives the app the chance
// to cleanup after itself.
//-----------------------------------------------------------------------------
HRESULT CMyD3DApplication::FinalCleanup()
{
// TODO: Perform any final cleanup needed
// Cleanup D3D font
SAFE_DELETE( m_pFont );
return S_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -