www.pudn.com > Water_Simulation.rar > bLois.cpp


//----------------------------------------------------------------------------- 
// File: bLois.cpp 
// 
// Desc: DirectX window application created by the DirectX AppWizard 
//----------------------------------------------------------------------------- 
#define STRICT 
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include  
#include "DXUtil.h" 
#include "D3DEnumeration.h" 
#include "D3DSettings.h" 
#include "D3DApp.h" 
#include "D3DFont.h" 
#include "D3DFile.h" 
#include "D3DUtil.h" 
#include "resource.h" 
#include "bLois.h" 
#include  
#include  
 
static float RandMinusOneToOne() 
{ 
	return float( double(rand()) / double(RAND_MAX) * 2.0 - 1.0 ); 
} 
 
static float RandZeroToOne() 
{ 
	return float( double(rand()) / double(RAND_MAX) ); 
} 
 
static const float kGravConst = 30.f; 
 
class ClearVert 
{ 
public: 
	D3DXVECTOR3		m_Pos; 
	D3DXVECTOR2		m_Uv; 
}; 
static const int kVSize = sizeof(ClearVert); 
static const DWORD kClearVertFVF = D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0); 
 
 
//----------------------------------------------------------------------------- 
// Global access to the app (needed for the global WndProc()) 
//----------------------------------------------------------------------------- 
CMyD3DApplication* g_pApp  = NULL; 
HINSTANCE          g_hInst = NULL; 
 
 
 
 
//----------------------------------------------------------------------------- 
// 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; 
 
    g_pApp  = &d3dApp; 
    g_hInst = hInst; 
 
    InitCommonControls(); 
    if( FAILED( d3dApp.Create( hInst ) ) ) 
        return 0; 
 
    return d3dApp.Run(); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: CMyD3DApplication() 
// Desc: Application constructor.   Paired with ~CMyD3DApplication() 
//       Member variables should be initialized to a known state here.   
//       The application window has not yet been created and no Direct3D device  
//       has been created, so any initialization that depends on a window or  
//       Direct3D should be deferred to a later stage.  
//----------------------------------------------------------------------------- 
CMyD3DApplication::CMyD3DApplication() 
{ 
    m_dwCreationWidth           = 500; 
    m_dwCreationHeight          = 375; 
    m_strWindowTitle            = TEXT( "bLois" ); 
    m_d3dEnumeration.AppUsesDepthBuffer   = TRUE; 
	m_bStartFullscreen			= false; 
	m_bShowCursorWhenFullscreen	= false; 
 
	m_bShowHelp = false; 
	m_bSortWater = true; 
	m_bDrawBump = false; 
	m_LastToggle = 0.f; 
 
    // Create a D3D font using d3dfont.cpp 
    m_pFont                     = new CD3DFont( _T("Arial"), 12, D3DFONT_BOLD ); 
    m_bLoadingApp               = TRUE; 
 
    memset(m_bKey, 0x00, sizeof(m_bKey)); 
 
    D3DXMatrixIdentity(&m_matView); 
    D3DXMatrixIdentity(&m_matPosition); 
    D3DXMatrixIdentity(&m_matProjection); 
 
	m_CompCosinesEff = NULL; 
	m_WaterEff = NULL; 
	m_WaterMesh = NULL; 
	m_LandMesh = NULL; 
	m_PillarsMesh = NULL; 
 
	m_EnvMap = NULL; 
	m_LandTex = NULL; 
 
	m_CosineLUT = NULL; 
	m_BiasNoiseMap = NULL; 
	 
	m_BumpTex = NULL; 
	m_BumpSurf = NULL; 
	m_BumpRender = NULL; 
	m_BumpVBuffer = NULL; 
 
	m_WaterIndices = NULL; 
	m_WaterFacePos = NULL; 
	m_WaterSortData = NULL; 
 
 
	ResetWater(); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: ~CMyD3DApplication() 
// Desc: Application destructor.  Paired with CMyD3DApplication() 
//----------------------------------------------------------------------------- 
CMyD3DApplication::~CMyD3DApplication() 
{ 
	delete [] m_WaterIndices; 
	delete [] m_WaterFacePos; 
	delete [] m_WaterSortData; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: OneTimeSceneInit() 
// Desc: Paired with FinalCleanup(). 
//       The window has been created and the IDirect3D9 interface has been 
//       created, but the device has not been created yet.  Here you can 
//       perform application-related initialization and cleanup that does 
//       not depend on a device. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::OneTimeSceneInit() 
{ 
    // TODO: perform one time initialization 
 
    // Drawing loading status message until app finishes loading 
    SendMessage( m_hWnd, WM_PAINT, 0, 0 ); 
 
    m_bLoadingApp = FALSE; 
 
    // Misc stuff 
 
	D3DXMatrixLookAtLH(&m_matView,  
		&D3DXVECTOR3(0.f, -150.f, 50.f), 
		&D3DXVECTOR3(0.f, 0.f, 0.f), 
		&D3DXVECTOR3(0.f, 0.f, 1.f)); 
 
    D3DXMatrixInverse(&m_matPosition, NULL, &m_matView); 
 
    return S_OK; 
} 
 
 
 
 
 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: ConfirmDevice() 
// Desc: Called during device initialization, this code checks the display device 
//       for some minimum set of capabilities 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::ConfirmDevice( D3DCAPS9* pCaps, DWORD dwBehavior, 
                                          D3DFORMAT Format ) 
{ 
    UNREFERENCED_PARAMETER( Format ); 
    UNREFERENCED_PARAMETER( dwBehavior ); 
    UNREFERENCED_PARAMETER( pCaps ); 
     
    BOOL bCapsAcceptable; 
 
    // TODO: Perform checks to see if these display caps are acceptable. 
    bCapsAcceptable = TRUE; 
 
    if( bCapsAcceptable )          
        return S_OK; 
    else 
        return E_FAIL; 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// Name: InitDeviceObjects() 
// Desc: Paired with DeleteDeviceObjects() 
//       The device has been created.  Resources that are not lost on 
//       Reset() can be created here -- resources in D3DPOOL_MANAGED, 
//       D3DPOOL_SCRATCH, or D3DPOOL_SYSTEMMEM.  Image surfaces created via 
//       CreateImageSurface are never lost and can be created here.  Vertex 
//       shaders and pixel shaders can also be created here as they are not 
//       lost on Reset(). 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::InitDeviceObjects() 
{ 
    // TODO: create device objects 
 
    HRESULT hr; 
 
    // Init the font 
    m_pFont->InitDeviceObjects( m_pd3dDevice ); 
 
	if( FAILED(hr = CreateCosineLUT()) ) 
		return hr; 
 
	if( FAILED(hr = CreateBiasNoiseMap()) ) 
		return hr; 
 
	if( FAILED(hr = D3DXCreateCubeTextureFromFile( m_pd3dDevice, TEXT("nvlobby_new_cube_mipmap.dds"), &m_EnvMap)) ) 
        return DXTRACE_ERR( "EnvMap load", hr ); 
 
	if( FAILED(hr = D3DXCreateTextureFromFile( m_pd3dDevice, "Sandy.dds", &m_LandTex)) ) 
		return hr; 
 
    if( FAILED(hr = D3DXLoadMeshFromX(TEXT("LandMesh.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &m_LandMesh)) ) 
		return hr; 
 
    if( FAILED(hr = D3DXLoadMeshFromX(TEXT("pillars.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &m_PillarsMesh)) ) 
		return hr; 
 
	ID3DXMesh* waterMesh = NULL; 
    if( FAILED(hr = D3DXLoadMeshFromX(TEXT("WaterMesh.x"), D3DXMESH_MANAGED, m_pd3dDevice, NULL, NULL, NULL, NULL, &waterMesh)) ) 
		return hr; 
 
	if( FAILED( hr = CreateWaterMesh(waterMesh)) ) 
		return hr; 
 
	if( FAILED(hr = CreateClearBuffer()) ) 
		return hr; 
 
    LPD3DXBUFFER pBufferErrors = NULL; 
    if( FAILED( hr = D3DXCreateEffectFromFile( m_pd3dDevice, "CompCosines.fx", NULL, NULL, 
                                            0, NULL, &m_CompCosinesEff, &pBufferErrors) ) ) 
    { 
		char* errStr = (char*)pBufferErrors->GetBufferPointer(); 
		OutputDebugString(errStr); 
        return hr; 
    } 
	GetCompCosineEffParams(); 
 
	if( FAILED(hr =  D3DXCreateEffectFromFile( m_pd3dDevice, "WaterRip.fx", NULL, NULL, 
                                            0, NULL, &m_WaterEff, &pBufferErrors) ) ) 
    { 
		char* errStr = (char*)pBufferErrors->GetBufferPointer(); 
		OutputDebugString(errStr); 
        return hr; 
    } 
	GetWaterParams(); 
 
    return S_OK; 
} 
 
HRESULT CMyD3DApplication::CreateWaterMesh(ID3DXMesh* waterMesh) 
{ 
	// All this should happen off line. In particular, note the assumption of even 
	// spacing in calculating the edge lengths, which defeats the whole purpose. 
	// Still, it's a demo, not a game. 
	struct OutVert 
	{ 
		D3DXVECTOR3		m_Pos; 
		DWORD			m_Color; 
	}; 
 
	const DWORD kWaterFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE; 
	HRESULT hr = waterMesh->CloneMeshFVF(D3DXMESH_MANAGED, 
							kWaterFVF, 
							m_pd3dDevice, 
							&m_WaterMesh); 
 
	SAFE_RELEASE(waterMesh); 
 
	if( FAILED(hr) ) 
		return hr; 
 
	const int nVerts = m_WaterMesh->GetNumVertices(); 
 
	OutVert* oVert; 
	if( FAILED(hr = m_WaterMesh->LockVertexBuffer(0, (void**)&oVert)) ) 
		return hr; 
	OutVert* origVert = oVert; 
 
	D3DXVECTOR3 del = oVert[0].m_Pos - oVert[1].m_Pos; 
	float dist = D3DXVec3Length(&del); 
	if( dist < 1.f ) 
		dist = 1.f; 
	UINT alpha = UINT(255.9f / dist); 
	int i; 
	for( i = 0; i < nVerts; i++ ) 
	{ 
		oVert->m_Color = alpha << 24 | 0x00ffffff; 
		oVert++; 
	} 
 
	oVert = origVert; 
 
	const int nFaces = m_WaterMesh->GetNumFaces(); 
 
	m_WaterIndices = new FaceIndices[nFaces]; 
	m_WaterFacePos = new D3DXVECTOR3[nFaces]; 
	m_WaterSortData = new FaceSortData[nFaces]; 
 
	DWORD* oIdx; 
	if( FAILED(hr = m_WaterMesh->LockIndexBuffer(0, (void**)&oIdx)) ) 
	{ 
		m_WaterMesh->UnlockVertexBuffer(); 
		return hr; 
	} 
	memcpy(m_WaterIndices, oIdx, nFaces * sizeof(*m_WaterIndices)); 
 
	for( i = 0; i < nFaces; i++ ) 
	{ 
		D3DXVECTOR3 pos = oVert[m_WaterIndices[i].m_Idx[0]].m_Pos; 
 
		pos += oVert[m_WaterIndices[i].m_Idx[1]].m_Pos; 
		pos += oVert[m_WaterIndices[i].m_Idx[2]].m_Pos; 
		pos.z = 0; 
 
		pos /= 3.f; 
 
		m_WaterFacePos[i] = pos; 
	} 
 
 
	m_WaterMesh->UnlockIndexBuffer(); 
 
	m_WaterMesh->UnlockVertexBuffer(); 
 
	return hr; 
} 
 
struct CompSortFace : public std::binary_function 
{ 
	bool operator()( const FaceSortData& lhs, const FaceSortData& rhs) const 
	{ 
		return lhs.m_Dist < rhs.m_Dist; 
	} 
}; 
 
 
void CMyD3DApplication::SortWaterMesh() 
{ 
	const D3DXVECTOR3 eyePos(m_matPosition._41, m_matPosition._42, 0.f); 
	const int nFaces = m_WaterMesh->GetNumFaces(); 
	int i; 
	for( i = 0; i < nFaces; i++ ) 
	{ 
		D3DXVECTOR3 del(eyePos - m_WaterFacePos[i]); 
		m_WaterSortData[i].m_Dist = D3DXVec3LengthSq(&del); 
		m_WaterSortData[i].m_Idx = i; 
	} 
 
	FaceSortData* begin = m_WaterSortData; 
	FaceSortData* end = begin + nFaces; 
 
	std::sort(begin, end, CompSortFace()); 
 
	FaceIndices* oIdx; 
	if( FAILED(m_WaterMesh->LockIndexBuffer(0, (void**)&oIdx)) ) 
	{ 
		m_WaterMesh->UnlockVertexBuffer(); 
		return; 
	} 
 
	for( i = 0; i < nFaces; i++ ) 
	{ 
		oIdx[i].m_Idx[0] = m_WaterIndices[m_WaterSortData[i].m_Idx].m_Idx[0]; 
		oIdx[i].m_Idx[1] = m_WaterIndices[m_WaterSortData[i].m_Idx].m_Idx[1]; 
		oIdx[i].m_Idx[2] = m_WaterIndices[m_WaterSortData[i].m_Idx].m_Idx[2]; 
	} 
 
	m_WaterMesh->UnlockIndexBuffer(); 
} 
 
HRESULT CMyD3DApplication::CreateClearBuffer() 
{ 
	HRESULT hr; 
	if( FAILED( hr = m_pd3dDevice->CreateVertexBuffer( 4 * kVSize, 
												D3DUSAGE_WRITEONLY,  
												0, 
												D3DPOOL_MANAGED,  
												&m_BumpVBuffer, 
												NULL) ) ) 
	{ 
		return hr; 
	} 
 
 
	ClearVert* ptr; 
	if( FAILED( hr = m_BumpVBuffer->Lock( 0, 0, (void **)&ptr, 0 ) ) ) 
		return hr; 
 
	ptr[2].m_Pos.x = -1.f; 
	ptr[2].m_Pos.y = -1.f; 
	ptr[2].m_Pos.z = 0.5f; 
 
	ptr[2].m_Uv.x = 0.5f / kBumpTexSize; 
	ptr[1].m_Uv.y = 0.5f / kBumpTexSize; 
 
	ptr[0] = ptr[2]; 
	ptr[0].m_Pos.y += 2.f; 
	ptr[0].m_Uv.y += 1.f; 
 
	ptr[1] = ptr[2]; 
	ptr[1].m_Pos.x += 2.f; 
	ptr[1].m_Pos.y += 2.f; 
	ptr[1].m_Uv.x += 1.f; 
	ptr[1].m_Uv.y += 1.f; 
 
	ptr[3] = ptr[2]; 
	ptr[3].m_Pos.x += 2.f; 
	ptr[3].m_Uv.x += 1.f; 
 
	m_BumpVBuffer->Unlock(); 
 
	return S_OK; 
} 
 
 
//----------------------------------------------------------------------------- 
// Name: RestoreDeviceObjects() 
// Desc: Paired with InvalidateDeviceObjects() 
//       The device exists, but may have just been Reset().  Resources in 
//       D3DPOOL_DEFAULT and any other device state that persists during 
//       rendering should be set here.  Render states, matrices, textures, 
//       etc., that don't change during rendering can be set once here to 
//       avoid redundant state setting during Render() or FrameMove(). 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::RestoreDeviceObjects() 
{ 
    // TODO: setup render states 
 
    // Setup a material 
    D3DMATERIAL9 mtrl; 
    D3DUtil_InitMaterial( mtrl, 1.0f, 1.0f, 1.0f ); 
    m_pd3dDevice->SetMaterial( &mtrl ); 
 
    // Set up the textures 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP,   D3DTOP_MODULATE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); 
    m_pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); 
    m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR ); 
    m_pd3dDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR ); 
 
    // Set miscellaneous render states 
	m_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); 
    m_pd3dDevice->SetRenderState( D3DRS_DITHERENABLE,   FALSE ); 
    m_pd3dDevice->SetRenderState( D3DRS_SPECULARENABLE, FALSE ); 
    m_pd3dDevice->SetRenderState( D3DRS_ZENABLE,        TRUE ); 
    m_pd3dDevice->SetRenderState( D3DRS_AMBIENT,        0x000F0F0F ); 
	m_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); 
 
    // Set the world matrix 
    D3DXMATRIX matIdentity; 
    D3DXMatrixIdentity( &matIdentity ); 
    m_pd3dDevice->SetTransform( D3DTS_WORLD,  &matIdentity ); 
 
 
    // Set the projection matrix 
    FLOAT fAspect = ((FLOAT)m_d3dsdBackBuffer.Width) / m_d3dsdBackBuffer.Height; 
    D3DXMatrixPerspectiveFovLH( &m_matProjection, D3DX_PI/4, fAspect, 1.0f, 10000.0f ); 
    m_pd3dDevice->SetTransform( D3DTS_PROJECTION, &m_matProjection); 
 
    // Set up lighting states 
    D3DLIGHT9 light; 
    D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, -1.0f, -1.0f, -2.0f ); 
    m_pd3dDevice->SetLight( 0, &light ); 
    m_pd3dDevice->LightEnable( 0, TRUE ); 
    m_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE ); 
 
    // Restore the font 
    m_pFont->RestoreDeviceObjects(); 
 
	HRESULT hr; 
	// Create our bump map. We'll composite the normals of our texture waves into this with renders. 
    if(FAILED(hr = D3DXCreateTexture(m_pd3dDevice, kBumpTexSize, kBumpTexSize, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_BumpTex)) && 
       FAILED(hr = D3DXCreateTexture(m_pd3dDevice, kBumpTexSize, kBumpTexSize, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_BumpTex))) 
    { 
        return hr; 
    } 
 
    D3DSURFACE_DESC desc; 
    m_BumpTex->GetSurfaceLevel(0, &m_BumpSurf); 
    m_BumpSurf->GetDesc(&desc); 
 
    if(FAILED(hr = D3DXCreateRenderToSurface(m_pd3dDevice, desc.Width, desc.Height,  
									        desc.Format, FALSE, D3DFMT_UNKNOWN, &m_BumpRender))) 
        return hr; 
 
    m_CompCosinesEff->OnResetDevice(); 
	m_WaterEff->OnResetDevice(); 
 
    return S_OK; 
} 
 
static void Clamp(float& val, float lo, float hi) 
{ 
	if( val < lo ) 
		val = lo; 
	else if( val > hi ) 
		val = hi; 
} 
 
void CMyD3DApplication::MoveOnInput() 
{ 
    // 
    // Process keyboard input 
    // 
 
    D3DXVECTOR3 vecT(0.0f, 0.0f, 0.0f); 
    D3DXVECTOR3 vecR(0.0f, 0.0f, 0.0f); 
    D3DXVECTOR3 vecZ(0.0f, 0.0f, 0.0f); 
 
    if(m_bKey[VK_NUMPAD1] || m_bKey[VK_LEFT])  vecT.x -= 1.0f; // Slide Left 
    if(m_bKey[VK_NUMPAD3] || m_bKey[VK_RIGHT]) vecT.x += 1.0f; // Slide Right 
    if(m_bKey[VK_DOWN])                        vecT.y -= 1.0f; // Slide Down 
    if(m_bKey[VK_UP])                          vecT.y += 1.0f; // Slide Up 
    if(m_bKey['W'])                            vecT.z += 2.0f; // Move Forward 
    if(m_bKey['S'])                            vecT.z -= 2.0f; // Move Backward 
    if(m_bKey['A'] || m_bKey[VK_NUMPAD8])      vecR.x -= 1.0f; // Pitch Down 
    if(m_bKey['Z'] || m_bKey[VK_NUMPAD2])      vecR.x += 1.0f; // Pitch Up 
    if(m_bKey['E'] || m_bKey[VK_NUMPAD6])      vecZ.z -= 1.0f; // Turn Right 
    if(m_bKey['Q'] || m_bKey[VK_NUMPAD4])      vecZ.z += 1.0f; // Turn Left 
    if(m_bKey[VK_NUMPAD9])                     vecR.z -= 2.0f; // Roll CW 
    if(m_bKey[VK_NUMPAD7])                     vecR.z += 2.0f; // Roll CCW 
 
	const float speed = 10.f; 
	const float angSpeed = D3DX_PI / 5.f; 
	vecT *= speed * m_fElapsedTime; 
	vecR *= angSpeed * m_fElapsedTime; 
	vecZ *= angSpeed * m_fElapsedTime; 
 
	if(m_bKey[VK_SHIFT]) 
	{ 
		vecT *= 4.f; 
		vecR *= 4.f; 
		vecZ *= 4.f; 
	} 
 
    // 
    // Update position and view matricies 
    // 
 
    D3DXMATRIXA16 matT, matR, matZ; 
    D3DXQUATERNION qR; 
    D3DXQUATERNION qZ; 
 
 
    D3DXMatrixTranslation(&matT, vecT.x, vecT.y, vecT.z); 
    D3DXMatrixMultiply(&m_matPosition, &matT, &m_matPosition); 
 
    D3DXQuaternionRotationYawPitchRoll(&qR, vecR.y, vecR.x, vecR.z); 
    D3DXMatrixRotationQuaternion(&matR, &qR); 
 
    D3DXQuaternionRotationYawPitchRoll(&qZ, vecZ.y, vecZ.x, vecZ.z); 
    D3DXMatrixRotationQuaternion(&matZ, &qZ); 
 
    D3DXMatrixMultiply(&m_matPosition, &matR, &m_matPosition); 
    D3DXMatrixMultiply(&m_matPosition, &m_matPosition, &matZ); 
 
    D3DXMatrixInverse(&m_matView, NULL, &m_matPosition); 
 
	float timeScale = m_bKey[VK_SHIFT] ? m_fElapsedTime : -m_fElapsedTime; 
	// MoreOptions 
	// Debounce the toggles 
	const float kMinToggle = 0.5f; 
	if( m_fTime - m_LastToggle > kMinToggle ) 
	{ 
		// Reset 
		if(m_bKey['R']) 
		{ 
			if( m_bKey[VK_SHIFT] ) 
				ResetWater(); 
			else 
				InitWaves(); 
			m_LastToggle = m_fTime; 
		} 
		// Show bump 
		if(m_bKey['B']) 
		{ 
			m_bDrawBump = !m_bDrawBump; 
			m_LastToggle = m_fTime; 
		} 
 
		if(m_bKey[VK_SPACE]) 
		{ 
			m_bShowHelp = !m_bShowHelp; 
			m_LastToggle = m_fTime; 
		} 
	} 
	// Water Height 
	if(m_bKey['H']) 
		m_GeoState.m_WaterLevel += timeScale * 3.f; 
	// Geo Wave Height 
	if(m_bKey['J']) 
	{ 
		m_GeoState.m_AmpOverLen += timeScale * 0.05f; 
		Clamp(m_GeoState.m_AmpOverLen, 0.f, 0.1f); 
	} 
	// Geo Chop 
	if(m_bKey['K']) 
	{ 
		m_GeoState.m_Chop += timeScale * 0.5f; 
		Clamp(m_GeoState.m_Chop, 0.f, 4.f); 
	} 
	// Tex Wave Height 
	if(m_bKey['U']) 
	{ 
		m_TexState.m_AmpOverLen += timeScale * 0.05f; 
		Clamp(m_TexState.m_AmpOverLen, 0.f, 0.5f); 
	} 
	// Tex scale 
	if(m_bKey['Y']) 
	{ 
		m_TexState.m_RippleScale += timeScale * 1.f; 
		Clamp(m_TexState.m_RippleScale, 5.f, 50.f); 
	} 
	if(m_bKey['N']) 
	{ 
		m_TexState.m_Noise += timeScale * 0.1f; 
		Clamp(m_TexState.m_Noise, 0.f, 1.f); 
	} 
	if(m_bKey['O']) 
	{ 
		m_GeoState.m_AngleDeviation += timeScale * 10.f; 
		Clamp(m_GeoState.m_AngleDeviation, 0.f, 180.f); 
	} 
	if(m_bKey['P']) 
	{ 
		m_TexState.m_AngleDeviation += timeScale * 10.f; 
		Clamp(m_TexState.m_AngleDeviation, 0.f, 180.f); 
	} 
	if(m_bKey['G']) 
	{ 
		m_GeoState.m_EnvRadius *= 1.f + timeScale * 0.5f; 
		Clamp(m_GeoState.m_EnvRadius, 100.f, 10000.f); 
	} 
	if(m_bKey['F']) 
	{ 
		m_GeoState.m_EnvHeight += timeScale * 10.f; 
		Clamp(m_GeoState.m_EnvHeight, -100.f, 100.f); 
	} 
} 
 
 
//----------------------------------------------------------------------------- 
// Name: FrameMove() 
// Desc: Called once per frame, the call is the entry point for animating 
//       the scene. 
//----------------------------------------------------------------------------- 
HRESULT CMyD3DApplication::FrameMove() 
{ 
    // TODO: update world 
 
    // Update user input state 
	MoveOnInput(); 
 
	UpdateTexWaves(m_fElapsedTime); 
	UpdateGeoWaves(m_fElapsedTime); 
 
    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 ); 
 
	pUserInput->bMoveUp = ( m_bActive && (GetAsyncKeyState( VK_UP )    & 0x8000) == 0x8000 ); 
} 
 
 
 
 
//----------------------------------------------------------------------------- 
// 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() 
{ 
	RenderTexture(); 
 
    // Clear the viewport 
    m_pd3dDevice->Clear( 0L, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 
                         0x00707070, 1.0f, 0L ); 
 
    // Begin the scene 
    if( SUCCEEDED( m_pd3dDevice->BeginScene() ) ) 
    { 
        // TODO: render world 
		m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &m_matProjection); 
		m_pd3dDevice->SetTransform(D3DTS_VIEW, &m_matView); 
         
		m_pd3dDevice->SetTexture(0, m_LandTex); 
		m_LandMesh->DrawSubset(0); 
		m_pd3dDevice->SetTexture(0, NULL); 
 
		m_PillarsMesh->DrawSubset(0); 
 
		RenderWater(); 
 
		if( m_bDrawBump ) 
		{ 
			D3DXMATRIXA16 matIdent; 
			D3DXMatrixIdentity(&matIdent); 
 
			m_pd3dDevice->SetTransform(D3DTS_VIEW, &matIdent); 
			matIdent._11 = 0.5f; 
			matIdent._22 = 0.5f; 
			m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matIdent); 
 
			m_pd3dDevice->SetRenderState(D3DRS_SRCBLEND,  D3DBLEND_ONE); 
			m_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO); 
			m_pd3dDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_ALWAYS); 
 
			m_pd3dDevice->SetTexture(0, m_BumpTex); 
			m_pd3dDevice->SetFVF(kClearVertFVF); 
			m_pd3dDevice->SetStreamSource(0, m_BumpVBuffer, 0, kVSize); 
 
			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->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); 
 
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLOROP,   D3DTOP_MODULATE ); 
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); 
			m_pd3dDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); 
} 
 
        // 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;  
 
 
    lstrcpy( szMsg, TEXT("Spacebar toggles help") ); 
    fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
	if( m_bShowHelp ) 
	{ 
		lstrcpy( szMsg, TEXT("Press 'F2' to configure display") ); 
		fNextLine -= 40.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'F' - Environment map height") ); 
		fNextLine -= 40.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'G' - Environment map radius") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'P' - Texture wave angle deviation") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'O' - Geometric wave angle deviation") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'N' - Texture Noise") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'Y' - Texture scaling") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'U' - Texture wave height") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'K' - Geometric wave choppiness") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'J' - Geometric wave height") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'H' - Water level") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("Parameters - Shift goes up, non-shift goes down") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'B' - Show bump map") ); 
		fNextLine -= 40.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'r' - Reinitializes system with current settings") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("'R' - Resets system settings to default and re-init") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("Toggles:") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("Left/right arrow - slide left/right") ); 
		fNextLine -= 40.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("Up/down arrow - move up/down") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("W/S - move forward/backward") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("A/Z - pitch up/down") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("E/Q - rotate scene right/left") ); 
		fNextLine -= 20.0f; m_pFont->DrawText( 2, fNextLine, fontColor, szMsg ); 
 
		lstrcpy( szMsg, TEXT("Movement - Shift is faster:") ); 
		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: 
            m_bKey[wParam] = TRUE; 
            break; 
 
        case WM_KEYUP: 
            m_bKey[wParam] = FALSE; 
            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(); 
    m_CompCosinesEff->OnLostDevice(); 
	m_WaterEff->OnLostDevice(); 
 
	SAFE_RELEASE(m_BumpTex); 
	SAFE_RELEASE(m_BumpSurf); 
	SAFE_RELEASE(m_BumpRender); 
 
    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_CompCosinesEff); 
	SAFE_RELEASE(m_WaterEff); 
	SAFE_RELEASE(m_CosineLUT); 
	SAFE_RELEASE(m_BiasNoiseMap); 
	SAFE_RELEASE(m_EnvMap); 
	SAFE_RELEASE(m_LandTex); 
 
	SAFE_RELEASE(m_WaterMesh); 
	SAFE_RELEASE(m_LandMesh); 
	SAFE_RELEASE(m_PillarsMesh); 
 
	SAFE_RELEASE(m_BumpVBuffer); 
 
    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; 
} 
 
HRESULT CMyD3DApplication::CreateCosineLUT() 
{ 
	HRESULT hr = D3DXCreateTexture(m_pd3dDevice, 
		kBumpTexSize, 
		1, 
		1, 
		0, 
		D3DFMT_A8R8G8B8, 
		D3DPOOL_MANAGED, 
		&m_CosineLUT); 
 
	if( FAILED(hr) ) 
		return hr; 
 
	D3DLOCKED_RECT lockedRect; 
	hr = m_CosineLUT->LockRect(0, &lockedRect, NULL, 0); 
	if( FAILED(hr) ) 
		return hr; 
 
	unsigned long* pDat = (unsigned long*)lockedRect.pBits; 
	int i; 
	for( i = 0; i < kBumpTexSize; i++ ) 
	{ 
		float dist = float(i) / float(kBumpTexSize-1) * 2.f * D3DX_PI; 
		float c = float(cos(dist)); 
		float s = float(sin(dist)); 
		s *= 0.5f; 
		s += 0.5f; 
		s = float(pow(s, m_TexState.m_Chop)); 
		c *= s; 
		unsigned char cosDist = (unsigned char)((c * 0.5 + 0.5) * 255.999f); 
		pDat[i] = (0xff << 24) 
					| (cosDist << 16) 
					| (cosDist << 8) 
					| 0xff; 
	} 
 
	m_CosineLUT->UnlockRect(0); 
 
	return S_OK; 
} 
 
HRESULT CMyD3DApplication::CreateBiasNoiseMap() 
{ 
	HRESULT hr = D3DXCreateTexture(m_pd3dDevice, 
		kBumpTexSize, 
		kBumpTexSize, 
		1, 
		0, 
		D3DFMT_A8R8G8B8, 
		D3DPOOL_MANAGED, 
		&m_BiasNoiseMap); 
 
	if( FAILED(hr) ) 
		return hr; 
 
	D3DLOCKED_RECT lockedRect; 
	hr = m_BiasNoiseMap->LockRect(0, &lockedRect, NULL, 0); 
	if( FAILED(hr) ) 
		return hr; 
 
	unsigned long* pDat = (unsigned long*)lockedRect.pBits; 
 
	const int size = kBumpTexSize; 
	int i; 
	for( i = 0; i < size; i++ ) 
	{ 
		int j; 
		for( j = 0; j < size; j++ ) 
		{ 
			float x = RandZeroToOne(); 
			float y = RandZeroToOne(); 
 
			unsigned char r = (unsigned char)(x * 255.999f); 
			unsigned char g = (unsigned char)(y * 255.999f); 
	 
			pDat[j] = (0xff << 24) 
				| (r << 16) 
				| (g << 8) 
				| 0xff; 
		} 
 
		pDat += lockedRect.Pitch / 4; 
	} 
 
	m_BiasNoiseMap->UnlockRect(0); 
 
	return S_OK; 
} 
 
void CMyD3DApplication::InitTexWaves() 
{ 
	int i; 
	for( i = 0; i < kNumTexWaves; i++ ) 
		InitTexWave(i); 
} 
 
void CMyD3DApplication::UpdateTexWaves(FLOAT dt) 
{ 
	int i; 
	for( i = 0; i < kNumTexWaves; i++ ) 
		UpdateTexWave(i, dt); 
} 
 
void CMyD3DApplication::UpdateTexWave(int i, FLOAT dt) 
{ 
	if( i == m_TexState.m_TransIdx ) 
	{ 
		m_TexWaves[i].m_Fade += m_TexState.m_TransDel * dt; 
		if( m_TexWaves[i].m_Fade < 0 ) 
		{ 
			// This wave is faded out. Re-init and fade it back up. 
			InitTexWave(i); 
			m_TexWaves[i].m_Fade = 0; 
			m_TexState.m_TransDel = -m_TexState.m_TransDel; 
		} 
		else if( m_TexWaves[i].m_Fade > 1.f ) 
		{ 
			// This wave is faded back up. Start fading another down. 
			m_TexWaves[i].m_Fade = 1.f; 
			m_TexState.m_TransDel = -m_TexState.m_TransDel; 
			if( ++m_TexState.m_TransIdx >= kNumTexWaves ) 
				m_TexState.m_TransIdx = 0; 
		} 
	} 
	m_TexWaves[i].m_Phase -= dt * m_TexWaves[i].m_Speed; 
	m_TexWaves[i].m_Phase -= int(m_TexWaves[i].m_Phase); 
} 
 
void CMyD3DApplication::InitTexWave(int i) 
{ 
	float rads = RandMinusOneToOne() * m_TexState.m_AngleDeviation * D3DX_PI / 180.f; 
	float dx = float(sin(rads)); 
	float dy = float(cos(rads)); 
 
 
	float tx = dx; 
	dx = m_TexState.m_WindDir.y * dx - m_TexState.m_WindDir.x * dy; 
	dy = m_TexState.m_WindDir.x * tx + m_TexState.m_WindDir.y * dy; 
 
	float maxLen = m_TexState.m_MaxLength * kBumpTexSize / m_TexState.m_RippleScale; 
	float minLen = m_TexState.m_MinLength * kBumpTexSize / m_TexState.m_RippleScale; 
	float len = float(i) / float(kNumTexWaves-1) * (maxLen - minLen) + minLen; 
 
	float reps = float(kBumpTexSize) / len; 
 
	dx *= reps; 
	dy *= reps; 
	dx = float(int(dx >= 0 ? dx + 0.5f : dx - 0.5f)); 
	dy = float(int(dy >= 0 ? dy + 0.5f : dy - 0.5f)); 
 
	m_TexWaves[i].m_RotScale.x = dx; 
	m_TexWaves[i].m_RotScale.y = dy; 
 
	float effK = float(1.0 / sqrt(dx*dx + dy*dy)); 
	m_TexWaves[i].m_Len = float(kBumpTexSize) * effK; 
	m_TexWaves[i].m_Freq = D3DX_PI * 2.f / m_TexWaves[i].m_Len; 
	m_TexWaves[i].m_Amp = m_TexWaves[i].m_Len * m_TexState.m_AmpOverLen; 
	m_TexWaves[i].m_Phase = RandZeroToOne(); 
	 
	m_TexWaves[i].m_Dir.x = dx * effK; 
	m_TexWaves[i].m_Dir.y = dy * effK; 
 
	m_TexWaves[i].m_Fade = 1.f; 
 
	float speed = float( 1.0 / sqrt(m_TexWaves[i].m_Len / (2.f * D3DX_PI * kGravConst)) ) / 3.f; 
	speed *= 1.f + RandMinusOneToOne() * m_TexState.m_SpeedDeviation; 
	m_TexWaves[i].m_Speed = speed; 
} 
 
void CMyD3DApplication::InitTexState() 
{ 
	m_TexState.m_Noise = 0.2f; 
	m_TexState.m_Chop = 1.f; 
	m_TexState.m_AngleDeviation = 15.f; 
	m_TexState.m_WindDir.x = 0; 
	m_TexState.m_WindDir.y = 1.f; 
	m_TexState.m_MaxLength = 10.f; 
	m_TexState.m_MinLength = 1.f; 
	m_TexState.m_AmpOverLen = 0.1f; 
	m_TexState.m_RippleScale = 25.f; 
	m_TexState.m_SpeedDeviation = 0.1f; 
 
	m_TexState.m_TransIdx = 0; 
	m_TexState.m_TransDel = -1.f / 5.f; 
} 
 
void CMyD3DApplication::GetCompCosineEffParams() 
{ 
	m_CompCosineParams.m_UTrans[0] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans0"); 
	m_CompCosineParams.m_UTrans[1] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans1"); 
	m_CompCosineParams.m_UTrans[2] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans2"); 
	m_CompCosineParams.m_UTrans[3] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans3"); 
	m_CompCosineParams.m_UTrans[4] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans4"); 
	m_CompCosineParams.m_UTrans[5] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans5"); 
	m_CompCosineParams.m_UTrans[6] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans6"); 
	m_CompCosineParams.m_UTrans[7] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans7"); 
	m_CompCosineParams.m_UTrans[8] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans8"); 
	m_CompCosineParams.m_UTrans[9] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans9"); 
	m_CompCosineParams.m_UTrans[10] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans10"); 
	m_CompCosineParams.m_UTrans[11] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans11"); 
	m_CompCosineParams.m_UTrans[12] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans12"); 
	m_CompCosineParams.m_UTrans[13] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans13"); 
	m_CompCosineParams.m_UTrans[14] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans14"); 
	m_CompCosineParams.m_UTrans[15] = m_CompCosinesEff->GetParameterByName(NULL, "cUTrans15"); 
 
	m_CompCosineParams.m_Coef[0] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef0"); 
	m_CompCosineParams.m_Coef[1] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef1"); 
	m_CompCosineParams.m_Coef[2] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef2"); 
	m_CompCosineParams.m_Coef[3] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef3"); 
	m_CompCosineParams.m_Coef[4] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef4"); 
	m_CompCosineParams.m_Coef[5] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef5"); 
	m_CompCosineParams.m_Coef[6] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef6"); 
	m_CompCosineParams.m_Coef[7] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef7"); 
	m_CompCosineParams.m_Coef[8] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef8"); 
	m_CompCosineParams.m_Coef[9] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef9"); 
	m_CompCosineParams.m_Coef[10] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef10"); 
	m_CompCosineParams.m_Coef[11] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef11"); 
	m_CompCosineParams.m_Coef[12] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef12"); 
	m_CompCosineParams.m_Coef[13] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef13"); 
	m_CompCosineParams.m_Coef[14] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef14"); 
	m_CompCosineParams.m_Coef[15] = m_CompCosinesEff->GetParameterByName(NULL, "cCoef15"); 
 
	m_CompCosineParams.m_ReScale = m_CompCosinesEff->GetParameterByName(NULL, "cReScale"); 
 
	m_CompCosineParams.m_NoiseXform[0] = m_CompCosinesEff->GetParameterByName(NULL, "cNoiseXForm0_00"); 
	m_CompCosineParams.m_NoiseXform[1] = m_CompCosinesEff->GetParameterByName(NULL, "cNoiseXForm0_10"); 
	m_CompCosineParams.m_NoiseXform[2] = m_CompCosinesEff->GetParameterByName(NULL, "cNoiseXForm1_00"); 
	m_CompCosineParams.m_NoiseXform[3] = m_CompCosinesEff->GetParameterByName(NULL, "cNoiseXForm1_10"); 
 
	D3DXVECTOR4 init(20.f, 0.f, 0.f, 0.f); 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_NoiseXform[0], &init); 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_NoiseXform[2], &init); 
	init.x = 0; 
	init.y = 20.f; 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_NoiseXform[1], &init); 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_NoiseXform[3], &init); 
 
	m_CompCosineParams.m_ScaleBias = m_CompCosinesEff->GetParameterByName(NULL, "cScaleBias"); 
 
	m_CompCosineParams.m_CosineLUT = m_CompCosinesEff->GetParameterByName(NULL, "tCosineLUT"); 
	m_CompCosineParams.m_BiasNoise = m_CompCosinesEff->GetParameterByName(NULL, "tBiasNoise"); 
} 
 
void CMyD3DApplication::SetCompCosineEffParams() 
{ 
	int i; 
	for( i = 0; i < 16; i++ ) 
	{ 
		D3DXVECTOR4 UTrans(m_TexWaves[i].m_RotScale.x, m_TexWaves[i].m_RotScale.y, 0.f, m_TexWaves[i].m_Phase); 
		m_CompCosinesEff->SetVector(m_CompCosineParams.m_UTrans[i], &UTrans); 
 
		float normScale = m_TexWaves[i].m_Fade / float(kNumBumpPasses); 
		D3DXVECTOR4 Coef(m_TexWaves[i].m_Dir.x * normScale, m_TexWaves[i].m_Dir.y * normScale, 1.f, 1.f); 
		m_CompCosinesEff->SetVector(m_CompCosineParams.m_Coef[i], &Coef); 
 
	} 
 
	D3DXVECTOR4 xform; 
	 
	const FLOAT kRate = 0.1f; 
	m_CompCosinesEff->GetVector(m_CompCosineParams.m_NoiseXform[0], &xform); 
	xform.w += m_fElapsedTime * kRate; 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_NoiseXform[0], &xform); 
 
	m_CompCosinesEff->GetVector(m_CompCosineParams.m_NoiseXform[3], &xform); 
	xform.w += m_fElapsedTime * kRate; 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_NoiseXform[3], &xform); 
 
	float s = 0.5f / (float(kNumBumpPerPass) + m_TexState.m_Noise); 
	D3DXVECTOR4 reScale(s, s, 1.f, 1.f); 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_ReScale, &reScale); 
 
	float scaleBias = 0.5f * m_TexState.m_Noise / (float(kNumBumpPasses) + m_TexState.m_Noise); 
	D3DXVECTOR4 scaleBiasVec(scaleBias, scaleBias, 0.f, 1.f); 
	m_CompCosinesEff->SetVector(m_CompCosineParams.m_ScaleBias, &scaleBiasVec); 
 
	m_CompCosinesEff->SetTexture(m_CompCosineParams.m_CosineLUT, m_CosineLUT); 
	m_CompCosinesEff->SetTexture(m_CompCosineParams.m_BiasNoise, m_BiasNoiseMap); 
} 
 
void CMyD3DApplication::InitGeoWaves() 
{ 
	int i; 
	for( i = 0; i < kNumGeoWaves; i++ ) 
		InitGeoWave(i); 
} 
 
void CMyD3DApplication::InitGeoWave(int i) 
{ 
	m_GeoWaves[i].m_Phase = RandZeroToOne() * D3DX_PI * 2.f; 
	m_GeoWaves[i].m_Len = m_GeoState.m_MinLength + RandZeroToOne() * (m_GeoState.m_MaxLength - m_GeoState.m_MinLength); 
	m_GeoWaves[i].m_Amp = m_GeoWaves[i].m_Len * m_GeoState.m_AmpOverLen / float(kNumGeoWaves); 
	m_GeoWaves[i].m_Freq = 2.f * D3DX_PI / m_GeoWaves[i].m_Len; 
	m_GeoWaves[i].m_Fade = 1.f; 
 
	float rotBase = m_GeoState.m_AngleDeviation * D3DX_PI / 180.f; 
 
	float rads = rotBase * RandMinusOneToOne(); 
	float rx = float(cosf(rads)); 
	float ry = float(sinf(rads)); 
 
	float x = m_GeoState.m_WindDir.x; 
	float y = m_GeoState.m_WindDir.y; 
	m_GeoWaves[i].m_Dir.x = x * rx + y * ry; 
	m_GeoWaves[i].m_Dir.y = x * -ry + y * rx; 
} 
 
void CMyD3DApplication::UpdateGeoWave(int i, FLOAT dt) 
{ 
	if( i == m_GeoState.m_TransIdx ) 
	{ 
		m_GeoWaves[i].m_Fade += m_GeoState.m_TransDel * dt; 
		if( m_GeoWaves[i].m_Fade < 0 ) 
		{ 
			// This wave is faded out. Re-init and fade it back up. 
			InitGeoWave(i); 
			m_GeoWaves[i].m_Fade = 0; 
			m_GeoState.m_TransDel = -m_GeoState.m_TransDel; 
		} 
		else if( m_GeoWaves[i].m_Fade > 1.f ) 
		{ 
			// This wave is faded back up. Start fading another down. 
			m_GeoWaves[i].m_Fade = 1.f; 
			m_GeoState.m_TransDel = -m_GeoState.m_TransDel; 
			if( ++m_GeoState.m_TransIdx >= kNumGeoWaves ) 
				m_GeoState.m_TransIdx = 0; 
		} 
	} 
 
	const float speed = float(1.0 / sqrt(m_GeoWaves[i].m_Len / (2.f * D3DX_PI * kGravConst))); 
 
	m_GeoWaves[i].m_Phase += speed * dt; 
	m_GeoWaves[i].m_Phase = float(fmod(m_GeoWaves[i].m_Phase, 2.f*D3DX_PI)); 
 
	m_GeoWaves[i].m_Amp = m_GeoWaves[i].m_Len * m_GeoState.m_AmpOverLen / float(kNumGeoWaves) * m_GeoWaves[i].m_Fade; 
} 
 
void CMyD3DApplication::UpdateGeoWaves(FLOAT dt) 
{ 
	int i; 
	for( i = 0; i < kNumGeoWaves; i++ ) 
		UpdateGeoWave(i, dt); 
} 
 
void CMyD3DApplication::InitGeoState() 
{ 
	m_GeoState.m_Chop = 2.5f; 
	m_GeoState.m_AngleDeviation = 15.f; 
	m_GeoState.m_WindDir.x = 0; 
	m_GeoState.m_WindDir.y = 1.f; 
 
	m_GeoState.m_MinLength = 15.f; 
	m_GeoState.m_MaxLength = 25.f; 
	m_GeoState.m_AmpOverLen = 0.1f; 
 
	m_GeoState.m_EnvHeight = -50.f; 
	m_GeoState.m_EnvRadius = 100.f; 
	m_GeoState.m_WaterLevel = -2.f; 
 
	m_GeoState.m_TransIdx = 0; 
	m_GeoState.m_TransDel = -1.f / 6.f; 
 
	m_GeoState.m_SpecAtten = 1.f; 
	m_GeoState.m_SpecEnd = 200.f; 
	m_GeoState.m_SpecTrans = 100.f; 
} 
 
void CMyD3DApplication::GetWaterParams() 
{ 
	m_WaterParams.m_cWorld2NDC = m_WaterEff->GetParameterByName(NULL, "cWorld2NDC"); 
	m_WaterParams.m_cWaterTint = m_WaterEff->GetParameterByName(NULL, "cWaterTint"); 
	m_WaterParams.m_cFrequency = m_WaterEff->GetParameterByName(NULL, "cFrequency"); 
	m_WaterParams.m_cPhase = m_WaterEff->GetParameterByName(NULL, "cPhase"); 
	m_WaterParams.m_cAmplitude = m_WaterEff->GetParameterByName(NULL, "cAmplitude"); 
	m_WaterParams.m_cDirX = m_WaterEff->GetParameterByName(NULL, "cDirX"); 
	m_WaterParams.m_cDirY = m_WaterEff->GetParameterByName(NULL, "cDirY"); 
	m_WaterParams.m_cSpecAtten = m_WaterEff->GetParameterByName(NULL, "cSpecAtten"); 
	m_WaterParams.m_cCameraPos = m_WaterEff->GetParameterByName(NULL, "cCameraPos"); 
	m_WaterParams.m_cEnvAdjust = m_WaterEff->GetParameterByName(NULL, "cEnvAdjust"); 
	m_WaterParams.m_cEnvTint = m_WaterEff->GetParameterByName(NULL, "cEnvTint"); 
	m_WaterParams.m_cLocal2World = m_WaterEff->GetParameterByName(NULL, "cLocal2World"); 
	m_WaterParams.m_cLengths = m_WaterEff->GetParameterByName(NULL, "cLengths"); 
	m_WaterParams.m_cDepthOffset = m_WaterEff->GetParameterByName(NULL, "cDepthOffset"); 
	m_WaterParams.m_cDepthScale = m_WaterEff->GetParameterByName(NULL, "cDepthScale"); 
	m_WaterParams.m_cFogParams = m_WaterEff->GetParameterByName(NULL, "cFogParams"); 
	m_WaterParams.m_cDirXK = m_WaterEff->GetParameterByName(NULL, "cDirXK"); 
	m_WaterParams.m_cDirYK = m_WaterEff->GetParameterByName(NULL, "cDirYK"); 
	m_WaterParams.m_cDirXW = m_WaterEff->GetParameterByName(NULL, "cDirXW"); 
	m_WaterParams.m_cDirYW = m_WaterEff->GetParameterByName(NULL, "cDirYW"); 
	m_WaterParams.m_cKW = m_WaterEff->GetParameterByName(NULL, "cKW"); 
	m_WaterParams.m_cDirXSqKW = m_WaterEff->GetParameterByName(NULL, "cDirXSqKW"); 
	m_WaterParams.m_cDirXDirYKW = m_WaterEff->GetParameterByName(NULL, "cDirXDirYKW"); 
	m_WaterParams.m_cDirYSqKW = m_WaterEff->GetParameterByName(NULL, "cDirYSqKW"); 
 
	m_WaterParams.m_tEnvMap = m_WaterEff->GetParameterByName(NULL, "tEnvMap"); 
	m_WaterParams.m_tBumpMap = m_WaterEff->GetParameterByName(NULL, "tBumpMap"); 
} 
 
void CMyD3DApplication::SetWaterParams() 
{ 
	D3DXMATRIXA16 world2NDC = m_matView * m_matProjection; 
	m_WaterEff->SetMatrixTranspose(m_WaterParams.m_cWorld2NDC, &world2NDC); 
 
	D3DXVECTOR4 waterTint(0.05f, 0.1f, 0.1f, 0.5f); 
	m_WaterEff->SetVector(m_WaterParams.m_cWaterTint, &waterTint); 
 
	D3DXVECTOR4 freq(m_GeoWaves[0].m_Freq, m_GeoWaves[1].m_Freq, m_GeoWaves[2].m_Freq, m_GeoWaves[3].m_Freq); 
	m_WaterEff->SetVector(m_WaterParams.m_cFrequency, &freq); 
 
	D3DXVECTOR4 phase(m_GeoWaves[0].m_Phase, m_GeoWaves[1].m_Phase, m_GeoWaves[2].m_Phase, m_GeoWaves[3].m_Phase); 
	m_WaterEff->SetVector(m_WaterParams.m_cPhase, &phase); 
 
	D3DXVECTOR4 amp(m_GeoWaves[0].m_Amp, m_GeoWaves[1].m_Amp, m_GeoWaves[2].m_Amp, m_GeoWaves[3].m_Amp); 
	m_WaterEff->SetVector(m_WaterParams.m_cAmplitude, &); 
 
	D3DXVECTOR4 dirX(m_GeoWaves[0].m_Dir.x, m_GeoWaves[1].m_Dir.x, m_GeoWaves[2].m_Dir.x, m_GeoWaves[3].m_Dir.x); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirX, &dirX); 
 
	D3DXVECTOR4 dirY(m_GeoWaves[0].m_Dir.y, m_GeoWaves[1].m_Dir.y, m_GeoWaves[2].m_Dir.y, m_GeoWaves[3].m_Dir.y); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirY, &dirY); 
 
	FLOAT normScale = m_GeoState.m_SpecAtten * m_TexState.m_AmpOverLen * 2.f * D3DX_PI; 
	normScale *= (float(kNumBumpPasses) + m_TexState.m_Noise); 
	normScale *= (m_TexState.m_Chop + 1.f); 
 
	D3DXVECTOR4 specAtten(m_GeoState.m_SpecEnd, 1.f / m_GeoState.m_SpecTrans, normScale, 1.f / m_TexState.m_RippleScale); 
	m_WaterEff->SetVector(m_WaterParams.m_cSpecAtten, &specAtten); 
 
	D3DXVECTOR3 camPos(m_matPosition._41, m_matPosition._42, m_matPosition._43); 
	m_WaterEff->SetVector(m_WaterParams.m_cCameraPos, &D3DXVECTOR4(camPos.x, camPos.y, camPos.z, 1.f)); 
 
 
	D3DXVECTOR3 envCenter(0.f, 0.f, m_GeoState.m_EnvHeight); // Just happens to be centered at origin. 
	D3DXVECTOR3 camToCen = envCenter - camPos; 
	float G = D3DXVec3LengthSq(&camToCen) - m_GeoState.m_EnvRadius * m_GeoState.m_EnvRadius; 
	m_WaterEff->SetVector(m_WaterParams.m_cEnvAdjust, &D3DXVECTOR4(camToCen.x, camToCen.y, camToCen.z, G)); 
 
	D3DXVECTOR4 envTint(1.f, 1.f, 1.f, 1.f); 
	m_WaterEff->SetVector(m_WaterParams.m_cEnvTint, &envTint); 
 
	D3DXMATRIXA16 matIdent; 
	D3DXMatrixIdentity(&matIdent); 
	m_WaterEff->SetMatrixTranspose(m_WaterParams.m_cLocal2World, &matIdent); 
 
	D3DXVECTOR4 lengths(m_GeoWaves[0].m_Len, m_GeoWaves[1].m_Len, m_GeoWaves[2].m_Len, m_GeoWaves[3].m_Len); 
	m_WaterEff->SetVector(m_WaterParams.m_cLengths, &lengths); 
 
	D3DXVECTOR4 depthOffset(m_GeoState.m_WaterLevel + 1.f,  
		m_GeoState.m_WaterLevel + 1.f,  
		m_GeoState.m_WaterLevel + 0.f,  
		m_GeoState.m_WaterLevel); 
	m_WaterEff->SetVector(m_WaterParams.m_cDepthOffset, &depthOffset); 
 
	D3DXVECTOR4 depthScale(1.f / 2.f, 1.f / 2.f, 1.f / 2.f, 1.f); 
	m_WaterEff->SetVector(m_WaterParams.m_cDepthScale, &depthScale); 
 
	D3DXVECTOR4 fogParams(-200.f, 1.f / (100.f - 200.f), 0.f, 1.f); 
	m_WaterEff->SetVector(m_WaterParams.m_cFogParams, &fogParams); 
 
	float K = 5.f; 
	if( m_GeoState.m_AmpOverLen > m_GeoState.m_Chop / (2.f * D3DX_PI * kNumGeoWaves * K) ) 
		K = m_GeoState.m_Chop / (2.f*D3DX_PI* m_GeoState.m_AmpOverLen * kNumGeoWaves); 
	D3DXVECTOR4 dirXK(m_GeoWaves[0].m_Dir.x * K,  
		m_GeoWaves[1].m_Dir.x * K,  
		m_GeoWaves[2].m_Dir.x * K,  
		m_GeoWaves[3].m_Dir.x * K); 
	D3DXVECTOR4 dirYK(m_GeoWaves[0].m_Dir.y * K,  
		m_GeoWaves[1].m_Dir.y * K,  
		m_GeoWaves[2].m_Dir.y * K,  
		m_GeoWaves[3].m_Dir.y * K); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirXK, &dirXK); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirYK, &dirYK); 
 
	D3DXVECTOR4 dirXW(m_GeoWaves[0].m_Dir.x * m_GeoWaves[0].m_Freq,  
		m_GeoWaves[1].m_Dir.x * m_GeoWaves[1].m_Freq,  
		m_GeoWaves[2].m_Dir.x * m_GeoWaves[2].m_Freq,  
		m_GeoWaves[3].m_Dir.x * m_GeoWaves[3].m_Freq); 
	D3DXVECTOR4 dirYW(m_GeoWaves[0].m_Dir.y * m_GeoWaves[0].m_Freq,  
		m_GeoWaves[1].m_Dir.y * m_GeoWaves[1].m_Freq,  
		m_GeoWaves[2].m_Dir.y * m_GeoWaves[2].m_Freq,  
		m_GeoWaves[3].m_Dir.y * m_GeoWaves[3].m_Freq); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirXW, &dirXW); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirYW, &dirYW); 
 
	D3DXVECTOR4 KW(K * m_GeoWaves[0].m_Freq, 
		K * m_GeoWaves[1].m_Freq, 
		K * m_GeoWaves[2].m_Freq, 
		K * m_GeoWaves[3].m_Freq); 
	m_WaterEff->SetVector(m_WaterParams.m_cKW, &KW); 
 
	D3DXVECTOR4 dirXSqKW(m_GeoWaves[0].m_Dir.x * m_GeoWaves[0].m_Dir.x * K * m_GeoWaves[0].m_Freq, 
		m_GeoWaves[1].m_Dir.x * m_GeoWaves[1].m_Dir.x * K * m_GeoWaves[1].m_Freq, 
		m_GeoWaves[2].m_Dir.x * m_GeoWaves[2].m_Dir.x * K * m_GeoWaves[2].m_Freq, 
		m_GeoWaves[3].m_Dir.x * m_GeoWaves[3].m_Dir.x * K * m_GeoWaves[3].m_Freq); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirXSqKW, &dirXSqKW); 
 
	D3DXVECTOR4 dirYSqKW(m_GeoWaves[0].m_Dir.y * m_GeoWaves[0].m_Dir.y * K * m_GeoWaves[0].m_Freq, 
		m_GeoWaves[1].m_Dir.y * m_GeoWaves[1].m_Dir.y * K * m_GeoWaves[1].m_Freq, 
		m_GeoWaves[2].m_Dir.y * m_GeoWaves[2].m_Dir.y * K * m_GeoWaves[2].m_Freq, 
		m_GeoWaves[3].m_Dir.y * m_GeoWaves[3].m_Dir.y * K * m_GeoWaves[3].m_Freq); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirYSqKW, &dirYSqKW); 
 
	D3DXVECTOR4 dirXdirYKW(m_GeoWaves[0].m_Dir.y * m_GeoWaves[0].m_Dir.x * K * m_GeoWaves[0].m_Freq, 
		m_GeoWaves[1].m_Dir.x * m_GeoWaves[1].m_Dir.y * K * m_GeoWaves[1].m_Freq, 
		m_GeoWaves[2].m_Dir.x * m_GeoWaves[2].m_Dir.y * K * m_GeoWaves[2].m_Freq, 
		m_GeoWaves[3].m_Dir.x * m_GeoWaves[3].m_Dir.y * K * m_GeoWaves[3].m_Freq); 
	m_WaterEff->SetVector(m_WaterParams.m_cDirXDirYKW, &dirXdirYKW); 
 
	m_WaterEff->SetTexture(m_WaterParams.m_tEnvMap, m_EnvMap); 
	m_WaterEff->SetTexture(m_WaterParams.m_tBumpMap, m_BumpTex); 
} 
 
void CMyD3DApplication::ResetWater() 
{ 
	InitTexState(); 
	InitGeoState(); 
 
	InitWaves(); 
} 
 
void CMyD3DApplication::InitWaves() 
{ 
	InitTexWaves(); 
	InitGeoWaves(); 
} 
 
void CMyD3DApplication::RenderWater() 
{ 
	SetWaterParams(); 
 
	if( m_bSortWater ) 
		SortWaterMesh(); 
 
	UINT nPass; 
	m_WaterEff->Begin(&nPass, 0); 
 
	UINT i; 
	for( i = 0; i < nPass; i++ ) 
	{ 
		m_WaterEff->Pass(i); 
 
		m_WaterMesh->DrawSubset(0); 
 
	} 
	m_WaterEff->End(); 
} 
 
void CMyD3DApplication::RenderTexture() 
{ 
	if( SUCCEEDED(m_BumpRender->BeginScene(m_BumpSurf, NULL)) ) 
	{ 
 
		D3DXMATRIXA16 matIdent; 
		D3DXMatrixIdentity(&matIdent); 
		m_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matIdent); 
		m_pd3dDevice->SetTransform(D3DTS_VIEW, &matIdent); 
		m_pd3dDevice->SetTransform(D3DTS_WORLD, &matIdent); 
 
		m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); 
 
		SetCompCosineEffParams(); 
 
		UINT nPass; 
		m_CompCosinesEff->Begin(&nPass, 0); 
 
		UINT i; 
		for( i = 0; i < nPass; i++ ) 
		{ 
			m_CompCosinesEff->Pass(i); 
 
			m_pd3dDevice->SetFVF(kClearVertFVF); 
			m_pd3dDevice->SetStreamSource(0, m_BumpVBuffer, 0, kVSize); 
			m_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); 
		} 
		m_CompCosinesEff->End(); 
 
		m_pd3dDevice->SetRenderState(D3DRS_ZENABLE, TRUE); 
 
		m_BumpRender->EndScene( 0 ); 
	} 
}