www.pudn.com > d3d_grass.rar > Grass.cpp


#define STRICT 
#include  
#include  
#include  
#include  
#include  
#include  
#include "D3DApp.h" 
#include "D3DFile.h" 
#include "D3DFont.h" 
#include "D3DUtil.h" 
#include "DXUtil.h" 
#include "resource.h" 
 
 
 
/* 
 regular vert with tex coord 
*/ 
typedef struct 
{ 
    FLOAT x, y, z; 
    FLOAT tu1, tv1; 
 } VERTEX; 
 
DWORD dwVertexDecl[] = 
{ 
	D3DVSD_STREAM( 0 ), 
	D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // Position 
	D3DVSD_REG( 7, D3DVSDT_FLOAT2 ), // Tex coord 
	D3DVSD_END() 
}; 
#define D3DFVF_VERTEX (D3DFVF_XYZ|D3DFVF_TEX1)  
 
static VERTEX g_Vertices[]= 
{ 
    //  x       y      z     tu1   tv1     
    { -10.0f, 0.0f,   0.0f, 1.0f,  1.0f  }, 
    {  10.0f, 0.0f,   0.0f, 0.01f, 1.0f  }, 
    {  10.0f, 0.0f, -10.0f, 0.01f, 0.01f }, 
 
    { -10.0f, 0.0f,   0.0f, 1.0f,   1.0f }, 
    {  10.0f, 0.0f, -10.0f, 0.01f, 0.01f }, 
	{ -10.0f, 0.0f, -10.0f, 1.0f,  0.01f }, 
}; 
 
static VERTEX g_GroundVertices[]= 
{ 
    //  x       y      z     tu1   tv1     
    { -60.0f,  30.0f, 0.0f, 10.0f, 10.0f }, 
    {  60.0f,  30.0f, 0.0f, 0.0f,  10.0f }, 
    {  60.0f, -30.0f, 0.0f, 0.0f,   0.0f }, 
    { -60.0f, -30.0f, 0.0f, 10.0f,  0.0f }, 
}; 
 
 
 
//----------------------------------------------------------------------------- 
// Name: class CMyD3DApplication 
// Desc: Application class. The base class (CD3DApplication) provides the  
//       generic functionality needed in all Direct3D samples. CMyD3DApplication  
//       adds functionality specific to this sample program. 
//----------------------------------------------------------------------------- 
class CMyD3DApplication : public CD3DApplication 
{ 
    CD3DFont*	m_pStatsFont; 
    CD3DFont*	m_pSmallFont; 
 
 
	DWORD         m_iNumQuads; 
	LPDIRECT3DVERTEXBUFFER8 m_pQuadsVB; 
 	LPDIRECT3DVERTEXBUFFER8 m_pGroundQuadVB; 
 	LPDIRECT3DTEXTURE8 m_pTex; 
 	LPDIRECT3DTEXTURE8 m_pGroundTex; 
  
	DWORD        m_dwVShader; 
	DWORD        m_dwPShader; 
 
	D3DXMATRIX  m_matWorld, m_matView, m_matProj; 
	D3DXMATRIX  m_matInitial; 
 
	BOOL        m_bShowHelp; 
	BOOL        m_bVertexShader; 
	BOOL        m_bPixelShader; 
	BOOL        m_bZBuffer; 
 
 
  
protected: 
	HRESULT InitDeviceObjects(); 
    HRESULT RestoreDeviceObjects(); 
    HRESULT InvalidateDeviceObjects(); 
    HRESULT DeleteDeviceObjects(); 
    HRESULT Render(); 
    HRESULT FrameMove(); 
    HRESULT FinalCleanup(); 
 
public: 
    LRESULT MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam ); 
    CMyD3DApplication(); 
}; 
 
//----------------------------------------------------------------------------- 
// Name: WinMain() 
// Desc: Entry point to the program. Initializes everything, and goes into a 
//       message-processing loop. Idle time is used to render the scene. 
//----------------------------------------------------------------------------- 
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT ) 
{ 
    CMyD3DApplication d3dApp; 
 
    if( FAILED( d3dApp.Create( hInst ) ) ) 
        return 0; 
 
    return d3dApp.Run(); 
} 
 
//----------------------------------------------------------------------------- 
// Name: CMyD3DApplication() 
// Desc: Application constructor. Sets attributes for the app. 
//----------------------------------------------------------------------------- 
CMyD3DApplication::CMyD3DApplication() 
{ 
    m_strWindowTitle    = _T("Grass"); 
    m_bUseDepthBuffer   = TRUE; 
 
    m_pStatsFont  = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); 
    m_pSmallFont  = new CD3DFont( _T("Arial"), 9, D3DFONT_BOLD ); 
 
	m_pQuadsVB = NULL; 
	m_pGroundQuadVB = NULL; 
	m_pTex = NULL; 
	m_pGroundTex = NULL; 
	m_dwVShader = 0; 
	m_dwPShader = 0; 
 
	m_bShowHelp        = FALSE; 
	m_bVertexShader    = TRUE; 
	m_bPixelShader     = TRUE; 
	m_bZBuffer         = TRUE; 
	D3DXMatrixIdentity( &m_matInitial ); 
 
	m_iNumQuads = 400; 
} 
 
 
//----------------------------------------------------------------------------- 
// Name: FrameMove() 
// Desc: Called once per frame, the call is the entry point for animating 
//       the scene. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::FrameMove() 
{ 
	float r = (float) rand()/RAND_MAX; 
 
    m_matWorld = m_matInitial; 
   
	// Set up the vertex shader constants 
    { 
     
		// c0  - commonConst ( 0.0, 0.5, 1.0, 2.0); 
		// c1  - appConst( time, 0.0, 0.0, 0.0); 
		// c4  - Composite World-View-Projection Matrix 
		// c8  - sin9 ( -1/3!, 1/5!, -1/7!, 1/9! ) 
		// c10 - frcFixup ( 1.07, 0.0, 0.0, 0.0) 
		// c11 - waveDistortx ( 3.0, 0.4, 0.0, 0.3) 
		// c12 - waveDistorty ( 3.0, 0.4, 0.0, 0.3) 
		// c13 - waveDistortz ( -1.0, -0.133, -0.333, -0.10) 
		// c14 - waveDirx ( -0.006, -0.012, 0.024, 0.048) 
		// c15 - waveDiry ( -0.003, -0.006, -0.012, -0.048) 
		// c16 - waveSpeed ( 0.3, 0.6, 0.7, 1.4) 
		// c17 - piVector (4.0, pi/2, pi, pi*2) 
		// c18 - lightingWaveScale ( 0.35, 0.10, 0.10, 0.03); 
		// c19 - lightingScaleBias ( 0.6, 0.7, 0.2, 0.0); 
 
		D3DXVECTOR4 c0( 0.0f, 0.5f, 1.0f, 2.0f);	 
		D3DXVECTOR4 c1( (float)m_fTime, 0.0f, 0.0f, 0.0f);		 
		D3DXVECTOR4 c8( -0.16161616f, 0.0083333f, -0.00019841f, 0.000002755731f);		 
		D3DXVECTOR4 c10( 1.07f, 0.0f, 0.0f, 0.0f);		 
		D3DXVECTOR4 c11( 3.0f, 0.4f, 0.0f, 0.3f);		 
		D3DXVECTOR4 c12( 3.0f, 0.4f, 0.0f, 0.3f);		 
		D3DXVECTOR4 c13( -1.0f, -0.133f, -0.333f, -0.10f);		 
		D3DXVECTOR4 c14( -0.006f, -0.012f, 0.024f, 0.048f);		 
		D3DXVECTOR4 c15( -0.003f, -0.006f, -0.012f, -0.048f);		 
		D3DXVECTOR4 c16( 0.3f, 0.6f, 0.7f, 1.4f);		 
		D3DXVECTOR4 c17( 4.0f, 1.57079632f, 3.14159265f, 6.28318530f);		 
		D3DXVECTOR4 c18( 0.35f, 0.10f, 0.10f, 0.03f);		 
		D3DXVECTOR4 c19( 0.6f, 0.7f, 0.2f, 0.0f);		 
	 
		m_pd3dDevice->SetVertexShaderConstant(  0, c0,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant(  1, c1,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant(  8, c8,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 10, c10,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 11, c11,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 12, c12,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 13, c13,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 14, c14,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 15, c15,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 16, c16,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 17, c17,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 18, c18,  1 ); 
		m_pd3dDevice->SetVertexShaderConstant( 19, c19,  1 ); 
 
		D3DXMATRIX mat; 
        D3DXMatrixMultiply( &mat, &m_matView, &m_matProj ); 
        D3DXMatrixMultiply( &mat, &m_matWorld, &mat ); 
        D3DXMatrixTranspose( &mat, &mat ); 
       	m_pd3dDevice->SetVertexShaderConstant(  4, &mat,  4 ); 
     
	 
    } 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// 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, 0x004010C0, 1.0f, 0L ); 
   
    // Begin the scene  
    if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) 
    {	 
         
		// Render the ground plane 
		m_pd3dDevice->SetStreamSource( 0, m_pGroundQuadVB, sizeof(VERTEX) ); 
       
		m_pd3dDevice->SetTexture(0, m_pGroundTex); 
 
		m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX ); 
	   
	   	m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, 0, 2 ); 
 
		// Render the waving grass 
		m_pd3dDevice->SetStreamSource( 0, m_pQuadsVB, sizeof(VERTEX) ); 
       
		m_pd3dDevice->SetTransform( D3DTS_WORLD, &m_matWorld ); 
		m_pd3dDevice->SetTexture(0, m_pTex); 
 
		m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, m_bZBuffer ); 
		if (m_bVertexShader)  
		    m_pd3dDevice->SetVertexShader( m_dwVShader ); 
		else	 
  			m_pd3dDevice->SetVertexShader( D3DFVF_VERTEX ); 
 
        if (m_bPixelShader)  
			m_pd3dDevice->SetPixelShader( m_dwPShader ); 
 
	    m_pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0,  m_iNumQuads*2 ); 
 
	 
        // Show frame rate 
        m_pStatsFont->DrawText( 2,  0, D3DCOLOR_ARGB(255,255,255,0), m_strFrameStats ); 
        m_pStatsFont->DrawText( 2, 20, D3DCOLOR_ARGB(255,255,255,0), m_strDeviceStats ); 
 
 
		 if( m_bShowHelp ) 
        { 
            m_pSmallFont->DrawText(  2, 40, D3DCOLOR_ARGB(255,255,255,255), 
                                    _T("Keyboard controls:") ); 
            m_pSmallFont->DrawText( 20, 60, D3DCOLOR_ARGB(255,255,255,255), 
                                    _T("Toggle Vertex Shader\n") 
                                    _T("Toggle Pixel Shader\n") 
                                    _T("Help\nChange device\nExit") ); 
            m_pSmallFont->DrawText( 210, 60, D3DCOLOR_ARGB(255,255,255,255), 
                                    _T("V\n") 
                                    _T("P\n") 
                                    _T("F1\nF2\nEsc") ); 
        } 
        else 
        { 
            m_pSmallFont->DrawText(  2, 40, D3DCOLOR_ARGB(255,255,255,255),  
                               _T("Press F1 for help") ); 
        } 
 
 
        // End the scene. 
        m_pd3dDevice->EndScene(); 
    } 
 
    return S_OK; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: InitDeviceObjects() 
// Desc: Initialize scene objects. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::InitDeviceObjects() 
{ 
	 
	HRESULT hr; 
 
	hr = D3DXCreateTextureFromFile(m_pd3dDevice, "media\\thingrass0000.tga", &m_pTex); 
	hr = D3DXCreateTextureFromFile(m_pd3dDevice, "media\\grass_ground.tga", &m_pGroundTex); 
 
    m_pStatsFont->InitDeviceObjects( m_pd3dDevice ); 
    m_pSmallFont->InitDeviceObjects( m_pd3dDevice ); 
 
 
 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: RestoreDeviceObjects() 
// Desc: Initialize scene objects. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::RestoreDeviceObjects() 
{ 
    m_pStatsFont->RestoreDeviceObjects(); 
    m_pSmallFont->RestoreDeviceObjects(); 
 
	 
 	m_pd3dDevice->SetTexture(0, m_pTex); 
  
 	m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR ); 
 
	m_pd3dDevice->SetRenderState( D3DRS_ZENABLE, FALSE ); 
    m_pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE ); 
    m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE ); 
  
 
    m_pd3dDevice->SetRenderState( D3DRS_ALPHAREF, (DWORD)0x000000FF); 
    m_pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); 
	m_pd3dDevice->SetRenderState( D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); 
 
    // Set the transform matrices 
 	D3DXVECTOR3 vEyePt    = D3DXVECTOR3( 0.0f, -20.0f, -10.0f ); 
    D3DXVECTOR3 vLookatPt = D3DXVECTOR3( 0.0f,   0.0f,  -5.0f ); 
    D3DXVECTOR3 vUpVec    = D3DXVECTOR3( 0.0f,   0.0f,  -1.0f ); 
     
 
    D3DXMatrixIdentity( &m_matWorld ); 
    D3DXMatrixLookAtLH( &m_matView, &vEyePt, &vLookatPt, &vUpVec ); 
    FLOAT fAspect = m_d3dsdBackBuffer.Width / (FLOAT)m_d3dsdBackBuffer.Height; 
    D3DXMatrixPerspectiveFovLH( &m_matProj, D3DX_PI/2, fAspect, 1.0f, 1000.0f ); 
 
    m_pd3dDevice->SetTransform( D3DTS_WORLD,      &m_matWorld ); 
    m_pd3dDevice->SetTransform( D3DTS_VIEW,       &m_matView ); 
    m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProj ); 
 
		 
	D3DXMATRIX mat; 
	D3DXMatrixIdentity( &m_matInitial); 
 
	// Create grass quads VB 
    HRESULT  hr; 
	hr = m_pd3dDevice->CreateVertexBuffer( m_iNumQuads*6*sizeof(VERTEX), 
                                           D3DUSAGE_WRITEONLY, D3DFVF_VERTEX, 
                                           D3DPOOL_MANAGED, &m_pQuadsVB ); 
    if( FAILED(hr) ) 
        return hr; 
 
	VERTEX* pVertices = NULL; 
	hr = m_pQuadsVB->Lock( 0,  m_iNumQuads*6*sizeof(VERTEX), (BYTE**)&pVertices, 0 ); 
    if( FAILED(hr) ) 
        return hr; 
 
     for( DWORD j=0; j< m_iNumQuads; j++ ) 
	{ 
		// Generate each quad at random position, orientation, height 
		D3DXMATRIX matRandom; 
		D3DXMatrixIdentity( &matRandom); 
		float scale = 40.0f; 
		float angle = ((float)rand()/RAND_MAX - 0.5f) * 8.0f; 
		float dx = ((float)rand()/RAND_MAX - 0.5f) * scale*2; 
		float dy = ((float)rand()/RAND_MAX - 0.5f) * scale; 
		float heightScale = ((float)rand()/RAND_MAX - 0.5f) / 2.0f + 1.0f; 
 
		D3DXMatrixRotationZ( &mat, D3DX_PI * angle); 
		D3DXMatrixMultiply( &matRandom, &matRandom, &mat ); 
		D3DXMatrixTranslation( &mat, dx, dy, 0.0f);			 
    	D3DXMatrixMultiply( &matRandom, &matRandom, &mat ); 
		D3DXMatrixScaling( &mat, 1.0f, 1.0f, heightScale);			 
    	D3DXMatrixMultiply( &matRandom, &matRandom, &mat ); 
 
		// Apply the transformation to each vertex of the quad 
		for( DWORD i=0; i< 6; i++ ) 
		{ 
			D3DXVECTOR4 pos, outPos; 
			pos.x = g_Vertices[i].x; 
			pos.y = g_Vertices[i].y; 
			pos.z = g_Vertices[i].z; 
			D3DXVec3Transform(&outPos, &(const struct D3DXVECTOR3)pos, &(CONST D3DXMATRIX)matRandom); 
			DWORD index = j * 6 + i; 
			pVertices[index].x = outPos.x; 
			pVertices[index].y = outPos.y; 
			pVertices[index].z = outPos.z; 
			pVertices[index].tu1 = g_Vertices[i].tu1; 
			pVertices[index].tv1 = g_Vertices[i].tv1; 
		} 
	} 
 
		 
    m_pQuadsVB->Unlock(); 
 
 
	// Create ground quad VB 
	hr = m_pd3dDevice->CreateVertexBuffer( 4*sizeof(VERTEX), 
                                           D3DUSAGE_WRITEONLY, D3DFVF_VERTEX, 
                                           D3DPOOL_MANAGED, &m_pGroundQuadVB ); 
    if( FAILED(hr) ) 
        return hr; 
 
	pVertices = NULL; 
	hr = m_pGroundQuadVB->Lock( 0, 4*sizeof(VERTEX), (BYTE**)&pVertices, 0 ); 
    if( FAILED(hr) ) 
        return hr; 
 
    for( DWORD i=0; i<4; i++ ) 
        pVertices[i] = g_GroundVertices[i]; 
 
    m_pGroundQuadVB->Unlock(); 
 
 
	// Create vertex shader 
    { 
        LPD3DXBUFFER pCode; 
 
        // Assemble the vertex shader from the file 
        if( FAILED( hr = D3DXAssembleShaderFromFile( "shaders\\grass.vsh",  
                                                     0, NULL, &pCode, NULL ) ) ) 
            return hr; 
 
        // Create the vertex shader 
        hr = m_pd3dDevice->CreateVertexShader( dwVertexDecl, (DWORD*)pCode->GetBufferPointer(), 
                                               &m_dwVShader, 0 ); 
        pCode->Release(); 
        if( FAILED(hr) ) 
            return hr; 
    } 
 
	// Create pixel shader 
    { 
        LPD3DXBUFFER pCode; 
 
        // Assemble the pixel shader from the file 
         if( FAILED( hr = D3DXAssembleShaderFromFile( "shaders\\grass.psh",  
                                                     0, NULL, &pCode, NULL ) ) ) 
            return hr; 
 
        // Create the pixel shader 
        hr = m_pd3dDevice->CreatePixelShader( (DWORD*)pCode->GetBufferPointer(), 
                                              &m_dwPShader); 
        pCode->Release(); 
        if( FAILED(hr) ) 
            return hr; 
    } 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: InvalidateDeviceObjects() 
// Desc: Called when the app is exiting, or the device is being changed, 
//       this function deletes any device dependent objects. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::InvalidateDeviceObjects() 
{ 
 	SAFE_RELEASE( m_pQuadsVB ); 
	SAFE_RELEASE( m_pGroundQuadVB ); 
 
	m_pd3dDevice->DeleteVertexShader( m_dwVShader ); 
	m_pd3dDevice->DeletePixelShader( m_dwPShader ); 
	m_pStatsFont->InvalidateDeviceObjects(); 
	m_pSmallFont->InvalidateDeviceObjects(); 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: DeleteDeviceObjects() 
// Desc: Called when the app is exiting, or the device is being changed, 
//       this function deletes any device dependent objects. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::DeleteDeviceObjects() 
{ 
	SAFE_RELEASE( m_pQuadsVB ); 
	SAFE_RELEASE( m_pGroundQuadVB ); 
 
	m_pd3dDevice->SetTexture(0, NULL); 
	SAFE_RELEASE( m_pTex ); 
	SAFE_RELEASE( m_pGroundTex ); 
 
    m_pStatsFont->DeleteDeviceObjects(); 
    m_pSmallFont->DeleteDeviceObjects(); 
  
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: FinalCleanup() 
// Desc: Called before the app exits, this function gives the app the chance 
//       to cleanup after itself. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::FinalCleanup() 
{ 
    SAFE_DELETE( m_pStatsFont ); 
	SAFE_DELETE( m_pSmallFont ); 
 
 
    return S_OK; 
} 
 
//----------------------------------------------------------------------------- 
// Name: MsgProc() 
// Desc: Message proc function to handle key and menu input 
//----------------------------------------------------------------------------- 
LRESULT CMyD3DApplication::MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, 
                                    LPARAM lParam ) 
{ 
	// Trap context menu 
    if( WM_CONTEXTMENU == uMsg ) 
        return 0; 
 
 
    // Perform commands when keys are released 
    if( WM_KEYUP == uMsg ) 
    { 
        switch( wParam ) 
        { 
        case 'V':  
			 m_bVertexShader = !m_bVertexShader; 
            break; 
         case 'P':  
			 m_bPixelShader = !m_bPixelShader; 
            break; 
       case VK_F1: 
            m_bShowHelp = !m_bShowHelp; 
            break; 
        } 
    } 
 
    return CD3DApplication::MsgProc( hWnd, uMsg, wParam, lParam ); 
}