3DShader之投影网格(Projected Grid)

哎呀,这个月的最后一天了,赶快在12点之前再写一篇,不然我的持之以恒徽章又要不亮了.


其实这个程序早在20号左右就写出来了,由于水下效果不是很好,所以一直没敢show出来,最近一直在忙于用OGRE改造HYDRAX,哎,帧数太慢了,准备放弃治疗了.现在迫不得已,先贴出来吧,看下水上也不错.国际惯例上图先:



说个大概原理,详细的自己去看论文

http://fileadmin.cs.lth.se/graphics/theses/projects/projgrid/


为了实现无限海洋,我们只需要在摄像机前画一片海洋.具体方法是算出视椎体与平面的相交部分,最后在相交的部分转换到标准设备空间,在标准设备空间中算出x,y平面的包围矩阵,最后只渲染出包围矩阵这一部分的海洋即可.


贴下代码:

/*------------------------------------------------------------
	3D_Shader_ProjectedGrid.cpp -- achieve projected grid
			(c) Seamanj.2013/9/11
------------------------------------------------------------*/
#include "DXUT.h"
#include "resource.h"
// phase0 : use camera we created
// phase1 : add camera
// phase2 : add noise
// phase3 : generate noise textures
// phase4 : generate range matrix
// phase5 : generate projective grid
// phase6 : generate height map texture
// phase7 : generate normal map texture
// phase8 : render the grid
// phase9 : set the grid parameter
// phase10 : render refracted scene to texture
// phase11 : render reflected scene to texture
// phase12 : render sky box
// phase13 : render the actual scene
// phase14 : add refracted island
// phase15 : add actual island
// phase16 : render underwater scene
#define phase0 1
#define phase1 0
#define phase2 1
#define phase3 1
#define phase4 1
#define phase5 1
#define phase6 1
#define phase7 1
#define phase8 1
#define phase9 1
#define phase10 1
#define phase11 1
#define phase12 1
#define phase13 1
#define phase14 1
#define phase15 1
#define phase16 1
#if phase0
#include "mycamera.h"
#include "dxmouse.h"

float mouseX=0, mouseY=0;
float mspeed = 0.005;
bool drag=false;
bool	keys[256];			// Array Used For The Keyboard Routine
MyCamera	*g_pRenderingCamera = NULL,*g_pObservingCamera = NULL;//g_pObservingCamera过时的摄像机
dxmouse *g_pMouse;
#endif
#if phase1
#include "camera.h"
MyCamera* g_pRenderingCamera = NULL;
#endif
#if phase2
#include "noise.h"
float g_fStrength = 0.9f;
float g_fScale = 0.38f;
software_noisemaker myNoise(0.607f, g_fStrength, g_fScale, 1.27f, 8);

#endif
#if phase3
LPDIRECT3DTEXTURE9	g_texPackedNoise[2];
#endif
#if phase4
D3DXMATRIXA16 g_matRange;
D3DXPLANE g_planeBase;
D3DXPLANE g_planeUpper;
D3DXPLANE g_planeLower;
D3DXVECTOR3 g_vec3BasePlaneNormal(0, 1, 0), g_vec3BasePlaneOrigin(0, 0, 0);
MyCamera* g_pProjectingCamera;
float g_fElevation = 7.0f;
bool g_bPlaneWithinFrustrum = false;
#endif
#if phase5
struct SOFTWARESURFACEVERTEX
{
	float x,y,z;
	float nx,ny,nz;
	float tu,tv;
};
#define D3DFVF_SOFTWARESURFACEVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_TEX1)
int gridsize_x = 128, gridsize_y = 256;
int sizeX = gridsize_x + 1, sizeY = gridsize_y + 1;

SOFTWARESURFACEVERTEX *g_pVertices;

// Vertex Buffer
LPDIRECT3DVERTEXBUFFER9 g_pGridVB = NULL;
// Index Buffer
LPDIRECT3DINDEXBUFFER9 g_pGridIB = NULL;

D3DXVECTOR4 t_corners0,t_corners1,t_corners2,t_corners3;

float g_fWaterColorR = 0.17f;
float g_fWaterColorG = 0.27f;
float g_fWaterColorB = 0.26f;
#endif


#if phase6
LPDIRECT3DTEXTURE9	g_texHeightMap;
#define nmapsize_x	512
#define nmapsize_y	1024
#include "SDKmisc.h"//加载文件时会用到
ID3DXEffect*		g_pHeightMapEffect = NULL;
D3DXHANDLE			g_hScale = 0;
D3DXHANDLE			g_hNoiseTex0 = 0;
D3DXHANDLE			g_hNoiseTex1 = 0;
LPDIRECT3DSURFACE9	g_surDepthStencil = 0;
#endif

#if phase7
LPDIRECT3DTEXTURE9  g_texNormalMap;
ID3DXEffect*		g_pNormalMapEffect = NULL;
D3DXHANDLE			g_hInvMapSizeX = 0;
D3DXHANDLE			g_hInvMapSizeY = 0;
D3DXHANDLE			g_hCorner00 = 0;
D3DXHANDLE			g_hCorner01 = 0;
D3DXHANDLE			g_hCorner10 = 0;
D3DXHANDLE			g_hCorner11 = 0;
D3DXHANDLE			g_hAmplitude = 0;
D3DXHANDLE			g_hHeightMap = 0;
#endif



#if phase8
ID3DXEffect*		g_pWaterGridEffect = NULL;
D3DXHANDLE			g_hViewProj = 0;
D3DXHANDLE			g_hView = 0;
D3DXHANDLE			g_hViewPos = 0;
D3DXHANDLE			g_hWaterColor = 0;
D3DXHANDLE			g_hLODbias = 0;
D3DXHANDLE			g_hSunShininess = 0;
D3DXHANDLE			g_hSunStrength = 0;
D3DXHANDLE			g_hSunVec = 0;
D3DXHANDLE			g_hReflRefrOffset = 0;
D3DXHANDLE			g_hDiffuseSkyRef = 0;
D3DXHANDLE			g_hEnvironmentMap = 0;
D3DXHANDLE			g_hFresnelMap = 0;
D3DXHANDLE			g_hRefractionMap = 0;
D3DXHANDLE			g_hReflectionMap = 0;
D3DXHANDLE			g_hHeightMapForWaterGridFX = 0;
D3DXHANDLE			g_hNormalMapForWaterGridFX = 0;



#endif
#if phase9

PDIRECT3DCUBETEXTURE9  g_texEnvironmentMap;
LPDIRECT3DTEXTURE9  g_texFresnelMap;
float g_fSunPosAlpha = 1.38f;
float g_fSunPosTheta = 1.09f;
float g_fSunShininess = 84.0f;
float g_fSunStrength = 12.0f;
float g_fReflRefrOffset = 0.1;
bool g_bDiffuseSkyRef = false;
float g_fLODbias = 0.0f;
D3DLIGHT9 sun;
#endif
#if phase10
#define reflrefrdetail 512
LPDIRECT3DTEXTURE9  g_texRefractionMap;

#endif
#if phase11
LPDIRECT3DTEXTURE9  g_texReflectionMap;
LPDIRECT3DSURFACE9	g_surDepthStencilForRefrRefl = 0;
LPDIRECT3DSURFACE9	g_surOriginDepthStencil		= NULL;
#define PI	3.1415926535898
struct duck
{
	float x,y,z;
	float y_vel;
	float angle;
};

duck duckie_pos;
LPD3DXMESH duckie				= NULL;
LPD3DXBUFFER duck_Adjacency, duck_Materials, duck_EffectInstances;

#endif

#if phase12
ID3DXEffect*		g_pSkyBoxEffect = NULL;
D3DXHANDLE			g_hSkyViewProj = 0;
D3DXHANDLE			g_hSkyInvViewProj = 0;
D3DXHANDLE			g_hSkyInvView = 0;
D3DXHANDLE			g_hSkyViewPosition = 0;
D3DXHANDLE			g_hSkySunAlpha = 0;
D3DXHANDLE			g_hSkySunTheta = 0;
D3DXHANDLE			g_hSkySunShininess = 0;
D3DXHANDLE			g_hSkySunStrength = 0;
D3DXHANDLE			g_hSkyEnvironmentMap = 0;
LPDIRECT3DVERTEXBUFFER9		g_pSkyBoxVB;
LPDIRECT3DINDEXBUFFER9		g_pSkyBoxIB;
#define skyboxdetail 16	

struct SURFACEVERTEX
{
	D3DXVECTOR3	position;	
	float displacement;
};
#define D3DFVF_SURFACEVERTEX (D3DFVF_XYZ|D3DFVF_TEX1) //|D3DFVF_TEX1
#endif

#if phase14
ID3DXEffect*		g_pIslandEffect = NULL;
LPDIRECT3DTEXTURE9	g_texIsland = 0;
D3DXHANDLE			g_hIslandViewProj = 0;
D3DXHANDLE			g_hIslandView = 0;
D3DXHANDLE			g_hIslandViewPos = 0;
D3DXHANDLE			g_hIslandWaterColor = 0;
D3DXHANDLE			g_hIslandSunShininess = 0;
D3DXHANDLE			g_hIslandSunStrength = 0;
D3DXHANDLE			g_hIslandSunVec = 0;
D3DXHANDLE			g_hIslandTex = 0;

LPD3DXMESH island				= NULL;
LPD3DXBUFFER island_Adjacency, island_Materials, island_EffectInstances;

#endif
#if phase16 
ID3DXEffect*		g_pUnderWaterEffect = NULL;
D3DXHANDLE			g_hUnderWaterViewProj = 0;
D3DXHANDLE			g_hUnderWaterViewPos = 0;
D3DXHANDLE			g_hUnderWaterWaterColor = 0;
D3DXHANDLE			g_hUnderWaterSunShininess = 0;
D3DXHANDLE			g_hUnderWaterSunStrength = 0;
D3DXHANDLE			g_hUnderWaterSunAlpha = 0;
D3DXHANDLE			g_hUnderWaterSunTheta = 0;
D3DXHANDLE			g_hUnderWaterEnvironmentMap = 0;
D3DXHANDLE			g_hUnderWaterFresnelMap = 0;
D3DXHANDLE			g_hUnderWaterNormalMap = 0;
#endif
//--------------------------------------------------------------------------------------
// Rejects any D3D9 devices that aren't acceptable to the app by returning false
//--------------------------------------------------------------------------------------
bool CALLBACK IsD3D9DeviceAcceptable( D3DCAPS9* pCaps, D3DFORMAT AdapterFormat, D3DFORMAT BackBufferFormat,
                                      bool bWindowed, void* pUserContext )
{
    // Typically want to skip back buffer formats that don't support alpha blending
    IDirect3D9* pD3D = DXUTGetD3D9Object();
    if( FAILED( pD3D->CheckDeviceFormat( pCaps->AdapterOrdinal, pCaps->DeviceType,
                                         AdapterFormat, D3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING,
                                         D3DRTYPE_TEXTURE, BackBufferFormat ) ) )
        return false;

    return true;
}


//--------------------------------------------------------------------------------------
// Before a device is created, modify the device settings as needed
//--------------------------------------------------------------------------------------
bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
{
#if phase1
	pDeviceSettings->d3d9.pp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
#endif
    return true;
}

#if phase5
D3DXVECTOR4 calc_worldpos(D3DXVECTOR2 uv)
{	
	// this is hacky.. this does take care of the homogenous coordinates in a correct way, 
	// but only when the plane lies at y=0
	D3DXVECTOR4	origin(uv.x,uv.y,-1,1);
	D3DXVECTOR4	direction(uv.x,uv.y,1,1);

	D3DXVec4Transform( &origin, &origin, &g_matRange );
	D3DXVec4Transform( &direction, &direction, &g_matRange );
	direction -= origin;    

	float	l = -origin.y / direction.y;	// assumes the plane is y=0
	//与世界坐标系中y=0平面的四个交点
	D3DXVECTOR4 worldPos = origin + direction*l;    
	return worldPos;
}
#endif
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that will live through a device reset (D3DPOOL_MANAGED)
// and aren't tied to the back buffer size
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9CreateDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                     void* pUserContext )
{
#if phase3
	HRESULT hr;
#endif
#if phase0
	g_pRenderingCamera = new MyCamera(D3DXVECTOR3(-27,8,0),0.3,450,0,45,1.33,0.3,5000.0);
	g_pMouse = new dxmouse(DXUTGetHWND(), DXUTGetHINSTANCE());
	g_pMouse->Init();
#endif
#if phase1
	g_pRenderingCamera = new MyCamera();
// Setup the camera's view parameters    
	D3DXVECTOR3 vecEye( -27.0f, 8.0f, 0.0f );  
	D3DXVECTOR3 vecAt ( 0.0f, 0.0f, 0.0f );  
	g_pRenderingCamera->SetViewParams( &vecEye, &vecAt );  
	g_pRenderingCamera->SetEnablePositionMovement( true );
	
#endif
#if phase2
	myNoise.init_noise();
#endif
#if phase5
	g_pVertices	= new SOFTWARESURFACEVERTEX[sizeX * sizeY];
	for(int v=0; v<sizeY; v++)
	{
		for(int u=0; u<sizeX; u++)
		{
			g_pVertices[v*sizeX + u].nx =	0.0f;
			g_pVertices[v*sizeX + u].ny =	1.0f;
			g_pVertices[v*sizeX + u].nz =	0.0f;
			g_pVertices[v*sizeX + u].tu = (float)u/(sizeX-1);
			g_pVertices[v*sizeX + u].tv = (float)v/(sizeY-1);
		}
	}	
#endif
#if phase6
	WCHAR str[MAX_PATH];
	// Read the D3DX effect file
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"HeightMapGen.fx" ) );
	// Create the effect 
	LPD3DXBUFFER pErrorBuff = NULL;
	V_RETURN( D3DXCreateEffectFromFile(
		pd3dDevice,		// associated device
		str,			// effect filename
		NULL,			// no preprocessor definitions
		NULL,			// no ID3DXInclude interface
		D3DXSHADER_DEBUG,	// compile flags
		NULL,			// don't share parameters
		&g_pHeightMapEffect,		// return effect
		&pErrorBuff			// return error messages
		) );
	if( pErrorBuff )
		MessageBoxA(0, (char*)pErrorBuff->GetBufferPointer(), 0, 0);
	// get tech
	D3DXHANDLE hTechnique;
	g_pHeightMapEffect->FindNextValidTechnique(NULL, &hTechnique);    
	g_pHeightMapEffect->SetTechnique(hTechnique);
	//get handle
	g_hScale = g_pHeightMapEffect->GetParameterByName(0, "g_fScale");
	g_hNoiseTex0 = g_pHeightMapEffect->GetParameterByName(0, "g_texNoise0");
	g_hNoiseTex1 = g_pHeightMapEffect->GetParameterByName(0, "g_texNoise1");
#endif
#if phase7
	// Read the D3DX effect file
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"NormalMapGen.fx" ) );
	// Create the effect 
	pErrorBuff = NULL;
	V_RETURN( D3DXCreateEffectFromFile(
		pd3dDevice,		// associated device
		str,			// effect filename
		NULL,			// no preprocessor definitions
		NULL,			// no ID3DXInclude interface
		D3DXSHADER_DEBUG,	// compile flags
		NULL,			// don't share parameters
		&g_pNormalMapEffect,		// return effect
		&pErrorBuff			// return error messages
		) );
	if( pErrorBuff )
		MessageBoxA(0, (char*)pErrorBuff->GetBufferPointer(), 0, 0);
	// get tech
	g_pNormalMapEffect->FindNextValidTechnique(NULL, &hTechnique);    
	g_pNormalMapEffect->SetTechnique(hTechnique);
	//get handle
	g_hInvMapSizeX = g_pNormalMapEffect->GetParameterByName(0, "g_fInvMapSizeX");
	g_hInvMapSizeY = g_pNormalMapEffect->GetParameterByName(0, "g_fInvMapSizeY");
	g_hCorner00 = g_pNormalMapEffect->GetParameterByName(0, "corner00");
	g_hCorner01 = g_pNormalMapEffect->GetParameterByName(0, "corner01");
	g_hCorner10 = g_pNormalMapEffect->GetParameterByName(0, "corner10");
	g_hCorner11 = g_pNormalMapEffect->GetParameterByName(0, "corner11");
	g_hAmplitude = g_pNormalMapEffect->GetParameterByName(0, "g_fAmplitude");
	g_hHeightMap = g_pNormalMapEffect->GetParameterByName(0, "g_texHeightMap");
#endif

#if phase8
	// Read the D3DX effect file
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"WaterGrid.fx" ) );
	// Create the effect 
	pErrorBuff = NULL;
	V_RETURN( D3DXCreateEffectFromFile(
		pd3dDevice,		// associated device
		str,			// effect filename
		NULL,			// no preprocessor definitions
		NULL,			// no ID3DXInclude interface
		D3DXSHADER_DEBUG,	// compile flags
		NULL,			// don't share parameters
		&g_pWaterGridEffect,		// return effect
		&pErrorBuff			// return error messages
		) );
	if( pErrorBuff )
		MessageBoxA(0, (char*)pErrorBuff->GetBufferPointer(), 0, 0);
	// get tech
	g_pWaterGridEffect->FindNextValidTechnique(NULL, &hTechnique);    
	g_pWaterGridEffect->SetTechnique(hTechnique);
	//get handle
	g_hViewProj = g_pWaterGridEffect->GetParameterByName(0, "g_mViewProj");
	g_hView = g_pWaterGridEffect->GetParameterByName(0, "g_mView");
	g_hViewPos = g_pWaterGridEffect->GetParameterByName(0, "g_f4ViewPos");
	g_hWaterColor = g_pWaterGridEffect->GetParameterByName(0, "g_f3WaterColor");
	g_hLODbias = g_pWaterGridEffect->GetParameterByName(0, "g_fLODbias");
	g_hSunShininess = g_pWaterGridEffect->GetParameterByName(0, "g_fSunShininess");
	g_hSunStrength = g_pWaterGridEffect->GetParameterByName(0, "g_fSunStrength");
	g_hSunVec = g_pWaterGridEffect->GetParameterByName(0, "g_f3SunVec");
	g_hReflRefrOffset = g_pWaterGridEffect->GetParameterByName(0, "g_fReflRefrOffset");
	g_hDiffuseSkyRef = g_pWaterGridEffect->GetParameterByName(0, "g_bDiffuseSkyRef");
	g_hEnvironmentMap = g_pWaterGridEffect->GetParameterByName(0, "g_texEnvironmentMap");
	g_hFresnelMap = g_pWaterGridEffect->GetParameterByName(0, "g_texFresnelMap");
	g_hRefractionMap = g_pWaterGridEffect->GetParameterByName(0, "g_texRefractionMap");
	g_hReflectionMap = g_pWaterGridEffect->GetParameterByName(0, "g_texReflectionMap");
	g_hHeightMapForWaterGridFX = g_pWaterGridEffect->GetParameterByName(0, "g_texHeightMap");
	g_hNormalMapForWaterGridFX = g_pWaterGridEffect->GetParameterByName(0, "g_texNormalMap");
#endif
#if phase9
		// read textures
	D3DXCreateCubeTextureFromFile(pd3dDevice, L"skybox.dds", &g_texEnvironmentMap);
	D3DXCreateTextureFromFile(pd3dDevice, L"fresnel_water_linear.bmp", &g_texFresnelMap);
#endif

#if phase11
	pd3dDevice->GetDepthStencilSurface(&g_surOriginDepthStencil);
	DWORD n_materials;
	D3DXLoadMeshFromX( L"duckie.x", D3DXMESH_MANAGED, pd3dDevice, &duck_Adjacency, &duck_Materials, 
		&duck_EffectInstances, &n_materials, &duckie );

#endif
#if phase12
		// Read the D3DX effect file
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"SkyBox.fx" ) );
	// Create the effect 
	pErrorBuff = NULL;
	V_RETURN( D3DXCreateEffectFromFile(
		pd3dDevice,		// associated device
		str,			// effect filename
		NULL,			// no preprocessor definitions
		NULL,			// no ID3DXInclude interface
		D3DXSHADER_DEBUG,	// compile flags
		NULL,			// don't share parameters
		&g_pSkyBoxEffect,		// return effect
		&pErrorBuff			// return error messages
		) );
	if( pErrorBuff )
		MessageBoxA(0, (char*)pErrorBuff->GetBufferPointer(), 0, 0);
	// get tech
	g_pSkyBoxEffect->FindNextValidTechnique(NULL, &hTechnique);    
	g_pSkyBoxEffect->SetTechnique(hTechnique);
	//get handle
	g_hSkyViewProj = g_pSkyBoxEffect->GetParameterByName(0, "g_mViewProj");
	g_hSkyInvViewProj = g_pSkyBoxEffect->GetParameterByName(0, "g_mInvViewProj");
	g_hSkyInvView = g_pSkyBoxEffect->GetParameterByName(0, "g_mInvView");
	g_hSkyViewPosition = g_pSkyBoxEffect->GetParameterByName(0, "g_f4ViewPosition");
	g_hSkySunAlpha = g_pSkyBoxEffect->GetParameterByName(0, "g_fSunAlpha");
	g_hSkySunTheta = g_pSkyBoxEffect->GetParameterByName(0, "g_fSunTheta");
	g_hSkySunShininess = g_pSkyBoxEffect->GetParameterByName(0, "g_fSunShiness");
	g_hSkySunStrength = g_pSkyBoxEffect->GetParameterByName(0, "g_fSunStrength");
	g_hSkyEnvironmentMap = g_pSkyBoxEffect->GetParameterByName(0, "g_texEnvironmentMap");
#endif
#if phase14
			// Read the D3DX effect file
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"Island.fx" ) );
	// Create the effect 
	pErrorBuff = NULL;
	V_RETURN( D3DXCreateEffectFromFile(
		pd3dDevice,		// associated device
		str,			// effect filename
		NULL,			// no preprocessor definitions
		NULL,			// no ID3DXInclude interface
		D3DXSHADER_DEBUG,	// compile flags
		NULL,			// don't share parameters
		&g_pIslandEffect,		// return effect
		&pErrorBuff			// return error messages
		) );
	if( pErrorBuff )
		MessageBoxA(0, (char*)pErrorBuff->GetBufferPointer(), 0, 0);
	// get tech
	g_pIslandEffect->FindNextValidTechnique(NULL, &hTechnique);    
	g_pIslandEffect->SetTechnique(hTechnique);

	//get handle
	g_hIslandViewProj = g_pIslandEffect->GetParameterByName(0, "g_mViewProj");
	g_hIslandView = g_pIslandEffect->GetParameterByName(0, "g_mView");
	g_hIslandViewPos = g_pIslandEffect->GetParameterByName(0, "g_f4ViewPos");
	g_hIslandWaterColor = g_pIslandEffect->GetParameterByName(0, "g_f3WaterColor");
	g_hIslandSunShininess = g_pIslandEffect->GetParameterByName(0, "g_fSunShininess");
	g_hIslandSunStrength = g_pIslandEffect->GetParameterByName(0, "g_fSunStrength");
	g_hIslandSunVec = g_pIslandEffect->GetParameterByName(0, "g_f3SunVec");
	g_hIslandTex = g_pIslandEffect->GetParameterByName(0, "g_texDiffuse");

		// read textures
	D3DXCreateTextureFromFile(pd3dDevice, L"Island.png", &g_texIsland);

	// read mesh
	D3DXLoadMeshFromX( L"Island.x", D3DXMESH_MANAGED, pd3dDevice, &island_Adjacency, &island_Materials, 
		&island_EffectInstances, &n_materials, &island );

#endif


#if phase16

	// Read the D3DX effect file
	V_RETURN( DXUTFindDXSDKMediaFileCch( str, MAX_PATH, L"UnderWater.fx" ) );
	// Create the effect 
	pErrorBuff = NULL;
	V_RETURN( D3DXCreateEffectFromFile(
		pd3dDevice,		// associated device
		str,			// effect filename
		NULL,			// no preprocessor definitions
		NULL,			// no ID3DXInclude interface
		D3DXSHADER_DEBUG,	// compile flags
		NULL,			// don't share parameters
		&g_pUnderWaterEffect,		// return effect
		&pErrorBuff			// return error messages
		) );
	if( pErrorBuff )
		MessageBoxA(0, (char*)pErrorBuff->GetBufferPointer(), 0, 0);
	// get tech
	g_pUnderWaterEffect->FindNextValidTechnique(NULL, &hTechnique);    
	g_pUnderWaterEffect->SetTechnique(hTechnique);

	//get handle
	g_hUnderWaterViewProj = g_pUnderWaterEffect->GetParameterByName(0, "g_mViewProj");
	g_hUnderWaterViewPos = g_pUnderWaterEffect->GetParameterByName(0, "g_f4ViewPos");
	g_hUnderWaterWaterColor = g_pUnderWaterEffect->GetParameterByName(0, "g_f3WaterColor");
	g_hUnderWaterSunShininess = g_pUnderWaterEffect->GetParameterByName(0, "g_fSunShiness");
	g_hUnderWaterSunStrength = g_pUnderWaterEffect->GetParameterByName(0, "g_fSunStrength");
	g_hUnderWaterSunAlpha = g_pUnderWaterEffect->GetParameterByName(0, "g_fSunAlpha");
	g_hUnderWaterSunTheta = g_pUnderWaterEffect->GetParameterByName(0, "g_fSunTheta");
	g_hUnderWaterEnvironmentMap = g_pUnderWaterEffect->GetParameterByName(0, "g_texEnvironmentMap");
	g_hUnderWaterFresnelMap = g_pUnderWaterEffect->GetParameterByName(0, "g_texFresnelMap");
	g_hUnderWaterNormalMap = g_pUnderWaterEffect->GetParameterByName(0, "g_texNormalMap");

#endif
    return S_OK;
}

#if phase5
static HRESULT initVertexIndexBuffer(IDirect3DDevice9* pd3dDevice)
{
	// create the vertexbuffer used in the softwaremode (it can be empty as it'll be memcpy-ed to)
	if (FAILED(pd3dDevice->CreateVertexBuffer(sizeX * sizeY * sizeof(SOFTWARESURFACEVERTEX),
		D3DUSAGE_WRITEONLY|D3DUSAGE_DYNAMIC, D3DFVF_SOFTWARESURFACEVERTEX,
		D3DPOOL_DEFAULT,
		&g_pGridVB, NULL))) {
			return E_FAIL;
	}


	// Create and initialize index buffer

	if (FAILED(pd3dDevice->CreateIndexBuffer(sizeof(unsigned int) * 6 * gridsize_x * gridsize_y ,
		D3DUSAGE_WRITEONLY, 
		D3DFMT_INDEX32,
		D3DPOOL_DEFAULT,
		&g_pGridIB, NULL))) {
			return E_FAIL;
	}
	unsigned int* pIndices;
	if (FAILED(g_pGridIB->Lock(0, 0, /* map entire buffer */
		(void**)&pIndices, 0))) {
			return E_FAIL;
	}
	int i = 0;
	for(int v=0; v<gridsize_y; v++)
	{
		for(int u=0; u<gridsize_x; u++)
		{
			// face 1 |/
			pIndices[i++]	= v*sizeX + u;
			pIndices[i++]	= v*sizeX + u + 1;
			pIndices[i++]	= (v+1)*sizeX + u;

			// face 2 /|
			pIndices[i++]	= (v+1)*sizeX + u;
			pIndices[i++]	= v*sizeX + u + 1;
			pIndices[i++]	= (v+1)*sizeX + u + 1;
		}
	}
	g_pGridIB->Unlock();
#if phase12
	// create the skybox vertexbuffer
	if (FAILED(pd3dDevice->CreateVertexBuffer(skyboxdetail * skyboxdetail * sizeof(SURFACEVERTEX),
		D3DUSAGE_WRITEONLY, D3DFVF_SURFACEVERTEX,
		D3DPOOL_DEFAULT,
		&g_pSkyBoxVB, NULL))) 
	{
			return E_FAIL;
	}
	SURFACEVERTEX* pVertices;
	if( FAILED( g_pSkyBoxVB->Lock( 0, 0, (void**)&pVertices, 0 ) ) )
		return E_FAIL;

	for(int v=0; v<skyboxdetail; v++)
	{
		for(int u=0; u<skyboxdetail; u++)
		{
			float	al = -2*3.14159265*((float)u/(skyboxdetail-1.0f)),
				th = 0.6*3.14159265*((float)v/(skyboxdetail-1.0f));
			pVertices[v*skyboxdetail+u].position.x = sin(th)*sin(al);
			pVertices[v*skyboxdetail+u].position.y = cos(th);
			pVertices[v*skyboxdetail+u].position.z = sin(th)*cos(al);
			pVertices[v*skyboxdetail+u].displacement = 0.0f;
		}
	}
	g_pSkyBoxVB->Unlock();
	// create / fill the skybox indexbuffer
	if(	FAILED( pd3dDevice->CreateIndexBuffer(	sizeof(unsigned int) * 6 * (skyboxdetail-1)*(skyboxdetail-1),
		D3DUSAGE_WRITEONLY,			
		D3DFMT_INDEX32,	D3DPOOL_DEFAULT,&g_pSkyBoxIB,NULL)))
	{
		return E_FAIL;
	}

	if( FAILED( g_pSkyBoxIB->Lock(0,0,(void**)&pIndices,0 ) ) )
		return E_FAIL;
	i = 0;
	for(int v=0; v<skyboxdetail-1; v++)
	{
		for(int u=0; u<skyboxdetail-1; u++)
		{
			// face 1 |/
			pIndices[i++]	= v*skyboxdetail + u;
			pIndices[i++]	= v*skyboxdetail + u + 1;
			pIndices[i++]	= (v+1)*skyboxdetail + u;

			// face 2 /|
			pIndices[i++]	= (v+1)*skyboxdetail + u;
			pIndices[i++]	= v*skyboxdetail + u + 1;
			pIndices[i++]	= (v+1)*skyboxdetail + u + 1;
		}
	}
	g_pSkyBoxIB->Unlock();
#endif
	return S_OK;
}

#endif
//--------------------------------------------------------------------------------------
// Create any D3D9 resources that won't live through a device reset (D3DPOOL_DEFAULT) 
// or that are tied to the back buffer size 
//--------------------------------------------------------------------------------------
HRESULT CALLBACK OnD3D9ResetDevice( IDirect3DDevice9* pd3dDevice, const D3DSURFACE_DESC* pBackBufferSurfaceDesc,
                                    void* pUserContext )
{
#if phase3
	HRESULT hr;
#endif
#if phase1
	pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );  
	//关闭光照处理, 默认情况下启用光照处理   
	pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );  
//Setup the camera's projection parameters   
	float fAspectRatio = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;    
	//g_pRenderingCamera->SetProjParams( D3DX_PI / 2, fAspectRatio, 0.1f, 5000.0f );  
	g_pRenderingCamera->SetProjParams( 45, fAspectRatio, 0.1f, 5000.0f );  
#endif
#if phase3
	// create two noise textures
	V( D3DXCreateTexture( pd3dDevice, np_size, np_size, 0, D3DUSAGE_DYNAMIC, D3DFMT_L16, 
		D3DPOOL_DEFAULT, &g_texPackedNoise[0] ));
	V( D3DXCreateTexture( pd3dDevice, np_size, np_size, 0, D3DUSAGE_DYNAMIC, D3DFMT_L16, 
		D3DPOOL_DEFAULT, &g_texPackedNoise[1] ));
#endif

#if phase6

		// create height map
	V( D3DXCreateTexture( pd3dDevice, nmapsize_x, nmapsize_y, 1, D3DUSAGE_RENDERTARGET, D3DFMT_A16B16G16R16, 
		D3DPOOL_DEFAULT, &g_texHeightMap ));
	// create z/stencil buffer
	V( pd3dDevice->CreateDepthStencilSurface(nmapsize_x, nmapsize_y, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 
		0, true, &g_surDepthStencil, NULL  ) );


	if( g_pHeightMapEffect )
        V_RETURN( g_pHeightMapEffect->OnResetDevice() );

#endif

#if phase7
	// 	// create normal map
	V( D3DXCreateTexture( pd3dDevice, nmapsize_x, nmapsize_y, 1, D3DUSAGE_AUTOGENMIPMAP|D3DUSAGE_RENDERTARGET, 
		D3DFMT_A16B16G16R16, D3DPOOL_DEFAULT, &g_texNormalMap ));
	if( g_pNormalMapEffect )
		V_RETURN( g_pHeightMapEffect->OnResetDevice() );
#endif
#if phase8
	if( g_pWaterGridEffect )
        V_RETURN( g_pWaterGridEffect->OnResetDevice() );
#endif
#if phase10
	// create refracted scene map
	V( D3DXCreateTexture(pd3dDevice,reflrefrdetail, reflrefrdetail, 1, D3DUSAGE_RENDERTARGET,
		D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_texRefractionMap) );
#endif
#if phase11
		// create reflected scene map
	V( D3DXCreateTexture(pd3dDevice,reflrefrdetail, reflrefrdetail, 1, D3DUSAGE_RENDERTARGET,
		D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &g_texReflectionMap) );
		// create z/stencil buffer
	V( pd3dDevice->CreateDepthStencilSurface(reflrefrdetail, reflrefrdetail, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 
		0, true, &g_surDepthStencilForRefrRefl, NULL  ) );
#endif
#if phase12
	if( g_pSkyBoxEffect )
        V_RETURN( g_pSkyBoxEffect->OnResetDevice() );
#endif
#if phase14
	if( g_pIslandEffect )
		V_RETURN( g_pIslandEffect->OnResetDevice() );
#endif
#if phase16
	if( g_pUnderWaterEffect )
		V_RETURN( g_pUnderWaterEffect->OnResetDevice() );
#endif

#if !phase5
    return S_OK;
#else
	return initVertexIndexBuffer(pd3dDevice);
#endif
}


//--------------------------------------------------------------------------------------
// Handle updates to the scene.  This is called regardless of which D3D API is used
//--------------------------------------------------------------------------------------
void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
{
#if phase3
	HRESULT hr;
#endif
#if phase0
	g_pMouse->Update(); update mouse & kbd
	float movespeed;
	if( GetAsyncKeyState(VK_LCONTROL) != 0)
	{
		mspeed = 0.05;
		movespeed = 5.0f;
	}
	else
	{
		mspeed = 0.005;
		movespeed = 0.3f;
	}
	
	if(keys['A'])
		g_pRenderingCamera->position -= movespeed*g_pRenderingCamera->right;
	if(keys['D'])
		g_pRenderingCamera->position += movespeed*g_pRenderingCamera->right;
	if(keys['W'])
		g_pRenderingCamera->position += movespeed*g_pRenderingCamera->forward;
	if(keys['S'])
		g_pRenderingCamera->position -= movespeed*g_pRenderingCamera->forward;
	g_pRenderingCamera->FrameMove( fElapsedTime );
	if(g_pMouse->mousedown(MOUSE_LEFT)){
		g_pRenderingCamera->roty -= 0.005 * g_pMouse->x;
		g_pRenderingCamera->rotx -= 0.005 * g_pMouse->y;
		g_pRenderingCamera->update();
	}

#endif
#if phase1
	g_pRenderingCamera->FrameMove( fElapsedTime );
#endif

#if phase0
	delete g_pObservingCamera;
	g_pObservingCamera = new MyCamera(g_pRenderingCamera);
#endif
	// Setup the world, view, and projection matrices (this is used to render the frustum)
	D3DXMATRIXA16 matWorld,matProj;// obsolete with vertexshaders
	D3DXMatrixIdentity(&matWorld);
	DXUTGetD3D9Device()->SetTransform( D3DTS_WORLD, &matWorld );
	DXUTGetD3D9Device()->SetTransform( D3DTS_VIEW,  g_pObservingCamera->GetViewMatrix());//设置摄像机矩阵
	DXUTGetD3D9Device()->SetTransform( D3DTS_PROJECTION, g_pObservingCamera->GetProjMatrix());//设置投影矩阵
//先渲染出几何体再计算
#if phase5//render geometry
	

	if( g_bPlaneWithinFrustrum )
	{
		#if phase2
			myNoise.calc_noise();
		#endif
		float magnitude = n_dec_magn * g_fScale;
		float inv_magnitude_sq = 1.0f/(g_fScale * g_fScale);
		//计算Projector的视椎体与y = 0平面的四个交点
		t_corners0 = calc_worldpos(D3DXVECTOR2(0.0f,0.0f));  //  2      3
		t_corners1 = calc_worldpos(D3DXVECTOR2(+1.0f,0.0f));
		t_corners2 = calc_worldpos(D3DXVECTOR2(0.0f,+1.0f));
		t_corners3 = calc_worldpos(D3DXVECTOR2(+1.0f,+1.0f));//  0      1

		D3DXMATRIXA16 surface_to_world;
		float	du = 1.0f/float(sizeX-1),
			dv = 1.0f/float(sizeY-1),
			u,v=0.0f;
		D3DXVECTOR4 result;
		int i=0;
		for(int iv=0; iv<sizeY; iv++)
		{
			u = 0.0f;		
			for(int iu=0; iu<sizeX; iu++)
			{							
				result.x = (1.0f-v)*( (1.0f-u)*t_corners0.x + u*t_corners1.x ) + 
					v*( (1.0f-u)*t_corners2.x + u*t_corners3.x );				
				result.z = (1.0f-v)*( (1.0f-u)*t_corners0.z + u*t_corners1.z ) + 
					v*( (1.0f-u)*t_corners2.z + u*t_corners3.z );				
				result.w = (1.0f-v)*( (1.0f-u)*t_corners0.w + u*t_corners1.w ) + 
					v*( (1.0f-u)*t_corners2.w + u*t_corners3.w );				

				float divide = 1.0f/result.w;				
				result.x *= divide;
				result.z *= divide;

				g_pVertices[i].x = result.x;
				g_pVertices[i].z = result.z;
				g_pVertices[i].y = myNoise.get_height_dual(magnitude*result.x, magnitude*result.z );

				i++;
				u += du;
			}
			v += dv;			
		}

		// smooth the heightdata

		//for(int n=0; n<3; n++)
		for(int v=1; v<(sizeY-1); v++)
		{
			for(int u=1; u<(sizeX-1); u++)
			{				
				g_pVertices[v*sizeX + u].y =	
					0.2f * (g_pVertices[v*sizeX + u].y +
					g_pVertices[v*sizeX + (u+1)].y + 
					g_pVertices[v*sizeX + (u-1)].y + 
					g_pVertices[(v+1)*sizeX + u].y + 
					g_pVertices[(v-1)*sizeX + u].y);															
			}
		}
	#if phase3// upload noise
		// write data to noise textures
		D3DLOCKED_RECT lockedRect;
		unsigned short* imageData;
		int tempdata[np_size_sq];
		for (int t = 0; t < 2; ++t)
		{
			int offset = np_size_sq * t;
			g_texPackedNoise[t]->LockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD);
			imageData = (unsigned short*)lockedRect.pBits;
			for(int i = 0; i < np_size_sq; ++i)
				imageData[i] = 32768 + myNoise.p_noise[i + offset];
			g_texPackedNoise[t]->UnlockRect(0);
			int c = g_texPackedNoise[t]->GetLevelCount();
			V(g_texPackedNoise[t]->LockRect(1, &lockedRect, NULL, 0));
			imageData = (unsigned short*)lockedRect.pBits;
			int sz = np_size >> 1;
			for(int v=0; v<sz; v++)
			{
				for(int u=0; u<sz; u++)
				{				
					tempdata[v*np_size + u] = (myNoise.p_noise[((v<<1))*np_size + (u<<1)+offset] +
						myNoise.p_noise[((v<<1))*np_size + (u<<1) + 1+offset] + 
						myNoise.p_noise[((v<<1)+1)*np_size + (u<<1)+offset] + 
						myNoise.p_noise[((v<<1)+1)*np_size + (u<<1) + 1+offset])>>2;
					imageData[v*sz+u] = 32768+tempdata[v*np_size + u];
				}
			}
			g_texPackedNoise[t]->UnlockRect(1);
			for(int j=2; j<c; j++)//mipmap
			{
				hr = g_texPackedNoise[t]->LockRect( j, &lockedRect, NULL, 0 );
				imageData = (unsigned short*)lockedRect.pBits;
				int pitch = (lockedRect.Pitch)>>1;
				sz = np_size>>j;			
				for(int v=0; v<sz; v++){
					for(int u=0; u<sz; u++)
					{
						tempdata[v*np_size + u] =	
							(tempdata[((v<<1))*np_size + (u<<1)] + 
							tempdata[((v<<1))*np_size + (u<<1) + 1] +
							tempdata[((v<<1)+1)*np_size + (u<<1)] + 
							tempdata[((v<<1)+1)*np_size + (u<<1) + 1])>>2;
						imageData[v*pitch+u] = 32768+tempdata[v*np_size + u];
					}
				}		
				g_texPackedNoise[t]->UnlockRect( j );
			}
		}
		D3DXSaveTextureToFile(L"MyPerlinNoiseTex1.dds", D3DXIFF_DDS,g_texPackedNoise[0],NULL);
		//这种生成的随机图片可以看得到
		D3DXSaveTextureToFile(L"MyPerlinNoiseTex2.dds", D3DXIFF_DDS,g_texPackedNoise[1],NULL);
	#endif

		//fill vertex buffer
		D3DVERTEXBUFFER_DESC pDesc;
		SOFTWARESURFACEVERTEX *vertices;
		V( g_pGridVB->GetDesc( &pDesc ) );
		
		if( FAILED(g_pGridVB->Lock( 0, 0, (void**) &vertices, D3DLOCK_DISCARD)))	
		{
			MessageBoxA(NULL, "Could not lock vertexbuffer", 0, MB_OK);
		}
		else
		{
			int size = pDesc.Size;
			memcpy(vertices, g_pVertices, size);
			g_pGridVB->Unlock();	
		}	

	}

#endif
#if phase4//获取range矩阵
	g_bPlaneWithinFrustrum = false;
	D3DXPlaneFromPointNormal( &g_planeBase, &g_vec3BasePlaneOrigin, &g_vec3BasePlaneNormal);
	D3DXPlaneFromPointNormal( &g_planeUpper, &(g_vec3BasePlaneOrigin +g_fStrength * g_vec3BasePlaneNormal),
		&g_vec3BasePlaneNormal); 
	D3DXPlaneFromPointNormal( &g_planeLower, &(g_vec3BasePlaneOrigin - g_fStrength * g_vec3BasePlaneNormal),
		&g_vec3BasePlaneNormal); 
	float		x_min,y_min,x_max,y_max;
	D3DXVECTOR3 frustum[8],proj_points[24];		// frustum to check the camera against

	int n_points=0;
	int cube[] = {	
		0,1,	0,2,	2,3,	1,3,
		0,4,	2,6,	3,7,	1,5,
		4,6,	4,5,	5,7,	6,7};	// which frustum points are connected together?

	// transform frustum points to worldspace (should be done to the rendering_camera because it's the interesting one)
	//将标准设备坐标系中的点转到世界坐标系中,获取视椎体的8个点在世界坐标系中的坐标
	D3DXVec3TransformCoord(&frustum[0], &D3DXVECTOR3(-1,-1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[1], &D3DXVECTOR3(+1,-1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[2], &D3DXVECTOR3(-1,+1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[3], &D3DXVECTOR3(+1,+1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[4], &D3DXVECTOR3(-1,-1,+1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[5], &D3DXVECTOR3(+1,-1,+1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[6], &D3DXVECTOR3(-1,+1,+1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[7], &D3DXVECTOR3(+1,+1,+1), g_pRenderingCamera->GetInvViewProjMatrix());	
	
	// check intersections with upper_bound and lower_bound	
	for(int i=0; i<12; i++)
	{
		int src=cube[i*2], dst=cube[i*2+1];
		if ((g_planeUpper.a*frustum[src].x + g_planeUpper.b*frustum[src].y + g_planeUpper.c*frustum[src].z + g_planeUpper.d*1)*
			(g_planeUpper.a*frustum[dst].x + g_planeUpper.b*frustum[dst].y + g_planeUpper.c*frustum[dst].z + g_planeUpper.d*1)<0){			
			D3DXPlaneIntersectLine( &proj_points[n_points++], &g_planeUpper, &frustum[src], &frustum[dst]);			
		}
		if ((g_planeLower.a*frustum[src].x + g_planeLower.b*frustum[src].y + g_planeLower.c*frustum[src].z + g_planeLower.d*1)*
			(g_planeLower.a*frustum[dst].x + g_planeLower.b*frustum[dst].y + g_planeLower.c*frustum[dst].z + g_planeLower.d*1)<0){			
			D3DXPlaneIntersectLine( &proj_points[n_points++], &g_planeLower, &frustum[src], &frustum[dst]);			
		}
	}
	// check if any of the frustums vertices lie between the upper_bound and lower_bound planes
	{
		for(int i=0; i<8; i++){		
			if ((g_planeUpper.a*frustum[i].x + g_planeUpper.b*frustum[i].y + g_planeUpper.c*frustum[i].z + g_planeUpper.d*1)*
				(g_planeLower.a*frustum[i].x + g_planeLower.b*frustum[i].y + g_planeLower.c*frustum[i].z + g_planeLower.d*1)<0){			
				proj_points[n_points++] = frustum[i];
			}		
		}	
	}
	delete g_pProjectingCamera;
	g_pProjectingCamera = new MyCamera(*g_pRenderingCamera);
	// make sure the camera isn't too close to the plane
	float fHeightInPlane = (g_planeLower.a * g_pProjectingCamera->GetEyePt()->x +
							 g_planeLower.b * g_pProjectingCamera->GetEyePt()->y +
						     g_planeLower.c * g_pProjectingCamera->GetEyePt()->z);
	bool bKeepItSimple = false;
	bool bUnderWater = false;

	if (fHeightInPlane < 0.0f) 
		bUnderWater = true;//小于最低平面,则是处于水下

	if(!bKeepItSimple)//简单的方式就是直接运用渲染摄像机的视椎体
	{

	}
	else
	{
		D3DXVECTOR3 aimpoint, aimpoint2;		

		if (fHeightInPlane < (g_fStrength + g_fElevation))
		{					
			if(bUnderWater)//把摄像机提高到距水平面p_fElevation + abs(height_in_plane)的高度
				*g_pProjectingCamera->GetEyePt() += D3DXVECTOR3(g_planeLower.a,g_planeLower.b,g_planeLower.c) *
				(g_fStrength + g_fElevation - 2 * fHeightInPlane);															
			else//把摄像机提高到距水面平距水平面p_fElevation的高度
				*g_pProjectingCamera->GetEyePt() += D3DXVECTOR3(g_planeLower.a,g_planeLower.b,g_planeLower.c)*
				(g_fStrength + g_fElevation - fHeightInPlane);
		} 
		// aim the projector at the point where the camera view-vector intersects the plane
		// if the camera is aimed away from the plane, mirror it's view-vector against the plane
		if( ((D3DXPlaneDotNormal(&g_planeBase, g_pRenderingCamera->GetWorldAhead()) < 0.0f) && 
			(D3DXPlaneDotCoord(&g_planeBase, g_pRenderingCamera->GetWorldAhead()) >= 0.0f )) ||
			((D3DXPlaneDotNormal(&g_planeBase, g_pRenderingCamera->GetWorldAhead()) >= 0.0f) && 
			(D3DXPlaneDotCoord(&g_planeBase, g_pRenderingCamera->GetWorldAhead()) < 0.0f ))
			)
		{				
			D3DXPlaneIntersectLine( &aimpoint, &g_planeBase, g_pRenderingCamera->GetEyePt(),
				&(*g_pRenderingCamera->GetEyePt() + *g_pRenderingCamera->GetWorldAhead()) );			
		}
		else
		{
			D3DXVECTOR3 flipped;
			flipped = *g_pRenderingCamera->GetWorldAhead() - 2 * g_vec3BasePlaneNormal * 
				D3DXVec3Dot(g_pRenderingCamera->GetWorldAhead(),&g_vec3BasePlaneNormal);
			D3DXPlaneIntersectLine( &aimpoint, &g_planeBase, g_pRenderingCamera->GetEyePt(),
				&(*g_pRenderingCamera->GetEyePt() + flipped) );			
		}
			// force the point the camera is looking at in a plane, and have the projector look at it
			// works well against horizon, even when camera is looking upwards
			// doesn't work straight down/up
			float af = fabs(D3DXPlaneDotNormal(&g_planeBase, g_pRenderingCamera->GetWorldAhead()));
			//af = 1 - (1-af)*(1-af)*(1-af)*(1-af)*(1-af);
			//aimpoint2 = (rendering_camera->position + rendering_camera->zfar * rendering_camera->forward);
			aimpoint2 = (*g_pRenderingCamera->GetEyePt() + 10.0f * *g_pRenderingCamera->GetWorldAhead());
			aimpoint2 = aimpoint2 - g_vec3BasePlaneNormal * D3DXVec3Dot(&aimpoint2, &g_vec3BasePlaneNormal);
		
			// fade between aimpoint & aimpoint2 depending on view angle
			
			aimpoint = aimpoint*af + aimpoint2*(1.0f-af);
			//aimpoint = aimpoint2;
			
			*g_pProjectingCamera->GetWorldAhead() = aimpoint - *g_pProjectingCamera->GetEyePt();
			g_pProjectingCamera->FrameMove(0);
	}
	for(int i=0; i<n_points; i++)
	{
		// project the point onto the surface plane
		proj_points[i] = proj_points[i] - g_vec3BasePlaneNormal * D3DXVec3Dot(&proj_points[i], &g_vec3BasePlaneNormal);	
	}
	for(int i=0; i<n_points; i++)
	{
		D3DXVec3TransformCoord( &proj_points[i], &proj_points[i], g_pProjectingCamera->GetViewMatrix());	 
		D3DXVec3TransformCoord( &proj_points[i], &proj_points[i], g_pProjectingCamera->GetProjMatrix());
	}
	if (n_points > 0)
	{
		x_min = proj_points[0].x;
		x_max = proj_points[0].x;
		y_min = proj_points[0].y;
		y_max = proj_points[0].y;
		for(int i=1; i<n_points; i++)
		{
			if (proj_points[i].x > x_max) x_max = proj_points[i].x;
			if (proj_points[i].x < x_min) x_min = proj_points[i].x;
			if (proj_points[i].y > y_max) y_max = proj_points[i].y;
			if (proj_points[i].y < y_min) y_min = proj_points[i].y;
		}
		// build the packing matrix that spreads the grid across the "projection window"
		D3DXMATRIXA16 pack(	x_max-x_min,	0,				0,		x_min,
							0,				y_max-y_min,	0,		y_min,
							0,				0,				1,		0,	
							0,				0,				0,		1);
		D3DXMatrixTranspose(&pack,&pack);
		g_matRange = pack * *g_pProjectingCamera->GetInvViewProjMatrix();
		g_bPlaneWithinFrustrum = true;
	}
#endif


#if phase11
	// move the duck
	duckie_pos.angle += 0.001;
	if (duckie_pos.angle > (2*PI)) duckie_pos.angle -= 2*PI;
	duckie_pos.x = 20*cos(duckie_pos.angle);
	duckie_pos.z = -20*sin(duckie_pos.angle);
	float new_y = myNoise.get_height_at(duckie_pos.x,duckie_pos.z);
	duckie_pos.y_vel = new_y - duckie_pos.y;
	duckie_pos.y += 0.2*duckie_pos.y_vel;		
#endif
}


//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

//     // Clear the render target and the zbuffer 
//     V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 0, 45, 50, 170 ), 1.0f, 0 ) );

    // Render the scene
    if( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
#if phase5
	D3DXMATRIXA16 matWorld,matProj;// obsolete with vertexshaders
	D3DXMatrixIdentity(&matWorld);
	DXUTGetD3D9Device()->SetTransform( D3DTS_WORLD, &matWorld );
	DXUTGetD3D9Device()->SetTransform( D3DTS_VIEW,  g_pRenderingCamera->GetViewMatrix());//设置摄像机矩阵
	DXUTGetD3D9Device()->SetTransform( D3DTS_PROJECTION, g_pRenderingCamera->GetProjMatrix());//设置投影矩阵
//获取Range矩阵
#if phase4
	g_bPlaneWithinFrustrum = false;
	D3DXPlaneFromPointNormal( &g_planeBase, &g_vec3BasePlaneOrigin, &g_vec3BasePlaneNormal);
	D3DXPlaneFromPointNormal( &g_planeUpper, &(g_vec3BasePlaneOrigin +g_fStrength * g_vec3BasePlaneNormal),
		&g_vec3BasePlaneNormal); 
	D3DXPlaneFromPointNormal( &g_planeLower, &(g_vec3BasePlaneOrigin - g_fStrength * g_vec3BasePlaneNormal),
		&g_vec3BasePlaneNormal); 
	float		x_min,y_min,x_max,y_max;
	D3DXVECTOR3 frustum[8],proj_points[24];		// frustum to check the camera against

	int n_points=0;
	int cube[] = {	
		0,1,	0,2,	2,3,	1,3,
		0,4,	2,6,	3,7,	1,5,
		4,6,	4,5,	5,7,	6,7};	// which frustum points are connected together?

	// transform frustum points to worldspace (should be done to the rendering_camera because it's the interesting one)
	//将标准设备坐标系中的点转到世界坐标系中,获取视椎体的8个点在世界坐标系中的坐标
	D3DXVec3TransformCoord(&frustum[0], &D3DXVECTOR3(-1,-1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[1], &D3DXVECTOR3(+1,-1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[2], &D3DXVECTOR3(-1,+1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[3], &D3DXVECTOR3(+1,+1,-1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[4], &D3DXVECTOR3(-1,-1,+1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[5], &D3DXVECTOR3(+1,-1,+1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[6], &D3DXVECTOR3(-1,+1,+1), g_pRenderingCamera->GetInvViewProjMatrix());
	D3DXVec3TransformCoord(&frustum[7], &D3DXVECTOR3(+1,+1,+1), g_pRenderingCamera->GetInvViewProjMatrix());	
	
	// check intersections with upper_bound and lower_bound	
	for(int i=0; i<12; i++)
	{
		int src=cube[i*2], dst=cube[i*2+1];
		if ((g_planeUpper.a*frustum[src].x + g_planeUpper.b*frustum[src].y + g_planeUpper.c*frustum[src].z + g_planeUpper.d*1)*
			(g_planeUpper.a*frustum[dst].x + g_planeUpper.b*frustum[dst].y + g_planeUpper.c*frustum[dst].z + g_planeUpper.d*1)<0){			
			D3DXPlaneIntersectLine( &proj_points[n_points++], &g_planeUpper, &frustum[src], &frustum[dst]);			
		}
		if ((g_planeLower.a*frustum[src].x + g_planeLower.b*frustum[src].y + g_planeLower.c*frustum[src].z + g_planeLower.d*1)*
			(g_planeLower.a*frustum[dst].x + g_planeLower.b*frustum[dst].y + g_planeLower.c*frustum[dst].z + g_planeLower.d*1)<0){			
			D3DXPlaneIntersectLine( &proj_points[n_points++], &g_planeLower, &frustum[src], &frustum[dst]);			
		}
	}
	// check if any of the frustums vertices lie between the upper_bound and lower_bound planes
	{
		for(int i=0; i<8; i++){		
			if ((g_planeUpper.a*frustum[i].x + g_planeUpper.b*frustum[i].y + g_planeUpper.c*frustum[i].z + g_planeUpper.d*1)*
				(g_planeLower.a*frustum[i].x + g_planeLower.b*frustum[i].y + g_planeLower.c*frustum[i].z + g_planeLower.d*1)<0){			
				proj_points[n_points++] = frustum[i];
			}		
		}	
	}
	delete g_pProjectingCamera;
	g_pProjectingCamera = new MyCamera(*g_pRenderingCamera);
	// make sure the camera isn't too close to the plane
	float fHeightInPlane = (g_planeLower.a * g_pProjectingCamera->GetEyePt()->x +
							 g_planeLower.b * g_pProjectingCamera->GetEyePt()->y +
						     g_planeLower.c * g_pProjectingCamera->GetEyePt()->z);
	bool bKeepItSimple = false;
	bool bUnderWater = false;

	if (fHeightInPlane < 0.0f) 
		bUnderWater = true;//小于最低平面,则是处于水下

	if(bKeepItSimple)//简单的方式就是直接运用渲染摄像机的视椎体
	{

	}
	else
	{
		D3DXVECTOR3 aimpoint, aimpoint2;		

		if (fHeightInPlane < (g_fStrength + g_fElevation))
		{					
			if(bUnderWater)//把摄像机提高到距水平面p_fElevation + abs(height_in_plane)的高度
				*g_pProjectingCamera->GetEyePt() += D3DXVECTOR3(g_planeLower.a,g_planeLower.b,g_planeLower.c) *
				(g_fStrength + g_fElevation - 2 * fHeightInPlane);															
			else//把摄像机提高到距水面平距水平面p_fElevation的高度
				*g_pProjectingCamera->GetEyePt() += D3DXVECTOR3(g_planeLower.a,g_planeLower.b,g_planeLower.c)*
				(g_fStrength + g_fElevation - fHeightInPlane);
		} 
		// aim the projector at the point where the camera view-vector intersects the plane
		// if the camera is aimed away from the plane, mirror it's view-vector against the plane
		if( ((D3DXPlaneDotNormal(&g_planeBase, g_pRenderingCamera->GetWorldAhead()) < 0.0f) && 
			(D3DXPlaneDotCoord(&g_planeBase, g_pRenderingCamera->GetEyePt()) >= 0.0f )) ||
			((D3DXPlaneDotNormal(&g_planeBase, g_pRenderingCamera->GetWorldAhead()) >= 0.0f) && 
			(D3DXPlaneDotCoord(&g_planeBase, g_pRenderingCamera->GetEyePt()) < 0.0f ))
			)
		{				
			D3DXPlaneIntersectLine( &aimpoint, &g_planeBase, g_pRenderingCamera->GetEyePt(),
				&(*g_pRenderingCamera->GetEyePt() + *g_pRenderingCamera->GetWorldAhead()) );			
		}
		else
		{
			D3DXVECTOR3 flipped;
			flipped = *g_pRenderingCamera->GetWorldAhead() - 2 * g_vec3BasePlaneNormal * 
				D3DXVec3Dot(g_pRenderingCamera->GetWorldAhead(),&g_vec3BasePlaneNormal);
			D3DXPlaneIntersectLine( &aimpoint, &g_planeBase, g_pRenderingCamera->GetEyePt(),
				&(*g_pRenderingCamera->GetEyePt() + flipped) );			
		}
			// force the point the camera is looking at in a plane, and have the projector look at it
			// works well against horizon, even when camera is looking upwards
			// doesn't work straight down/up
			float af = fabs(D3DXPlaneDotNormal(&g_planeBase, g_pRenderingCamera->GetWorldAhead()));
			//af = 1 - (1-af)*(1-af)*(1-af)*(1-af)*(1-af);
			//aimpoint2 = (rendering_camera->position + rendering_camera->zfar * rendering_camera->forward);
			aimpoint2 = (*g_pRenderingCamera->GetEyePt() + 10.0f * *g_pRenderingCamera->GetWorldAhead());
			aimpoint2 = aimpoint2 - g_vec3BasePlaneNormal * D3DXVec3Dot(&aimpoint2, &g_vec3BasePlaneNormal);
		
			// fade between aimpoint & aimpoint2 depending on view angle
			
			aimpoint = aimpoint*af + aimpoint2*(1.0f-af);
			//aimpoint = aimpoint2;
			
			*g_pProjectingCamera->GetWorldAhead() = aimpoint - *g_pProjectingCamera->GetEyePt();
			g_pProjectingCamera->update_lookat();
	}
	for(int i=0; i<n_points; i++)
	{
		// project the point onto the surface plane
		proj_points[i] = proj_points[i] - g_vec3BasePlaneNormal * D3DXVec3Dot(&proj_points[i], &g_vec3BasePlaneNormal);	
	}
	for(int i=0; i<n_points; i++)
	{
		D3DXVec3TransformCoord( &proj_points[i], &proj_points[i], g_pProjectingCamera->GetViewMatrix());	 
		D3DXVec3TransformCoord( &proj_points[i], &proj_points[i], g_pProjectingCamera->GetProjMatrix());
	}
	if (n_points > 0)
	{
		x_min = proj_points[0].x;
		x_max = proj_points[0].x;
		y_min = proj_points[0].y;
		y_max = proj_points[0].y;
		for(int i=1; i<n_points; i++)
		{
			if (proj_points[i].x > x_max) x_max = proj_points[i].x;
			if (proj_points[i].x < x_min) x_min = proj_points[i].x;
			if (proj_points[i].y > y_max) y_max = proj_points[i].y;
			if (proj_points[i].y < y_min) y_min = proj_points[i].y;
		}
		// build the packing matrix that spreads the grid across the "projection window"
		D3DXMATRIXA16 pack(	x_max-x_min,	0,				0,		x_min,
							0,				y_max-y_min,	0,		y_min,
							0,				0,				1,		0,	
							0,				0,				0,		1);
		D3DXMatrixTranspose(&pack,&pack);
		g_matRange = pack * *g_pProjectingCamera->GetInvViewProjMatrix();
		g_bPlaneWithinFrustrum = true;
	}
#endif

#if phase6
	LPDIRECT3DSURFACE9 target, bb, old_depthstencil;
#endif
//水的折射部分
#if phase10
	{
		V( pd3dDevice->GetRenderTarget(0, &bb) );
		V( g_texRefractionMap->GetSurfaceLevel(0, &target) );
		V( pd3dDevice->SetRenderTarget(0, target) );
		V( pd3dDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 
			D3DCOLOR_XRGB((int)(255 * g_fWaterColorR), (int)(255*g_fWaterColorG), (int)(255*g_fWaterColorB)), 1.0f, 0 ));
		D3DXMATRIXA16 store, scale;	
		// squach the scene
		pd3dDevice->GetTransform(D3DTS_WORLD, &store);
		D3DXMatrixScaling( &scale, 1, 0.75, 1 );
		pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale );
		pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW  );	
		// add a clip-plane as well	
		float plane[4];

		plane[0] = 0;
		plane[1] = -1;
		plane[2] = 0;
		plane[3] = 1.7*g_fStrength;	// a slight offset to avoid seams
		pd3dDevice->SetClipPlane(0,plane);
		///
		sun.Direction.x = -cos(g_fSunPosTheta) *sin(g_fSunPosAlpha);
		sun.Direction.y = -sin(g_fSunPosTheta);
		sun.Direction.z = -cos(g_fSunPosTheta)*cos(g_fSunPosAlpha);
		sun.Diffuse.r = 1.0f;
		sun.Diffuse.g = 1.0f;
		sun.Diffuse.b = 1.0f;
		sun.Diffuse.a = 1.0f;
		sun.Ambient.a = 1.0f;
		sun.Ambient.r = 0.2f;
		sun.Ambient.g = 0.3f;
		sun.Ambient.b = 0.3f;
		sun.Specular.r = 1.0f;
		sun.Specular.g = 1.0f;
		sun.Specular.b = 1.0f;
		sun.Specular.a = 1.0f;
		sun.Attenuation0 = 1.0f;
		sun.Type = D3DLIGHT_DIRECTIONAL;
		pd3dDevice->SetLight(0, &sun);
#if phase14		
		LPDIRECT3DVERTEXBUFFER9 vb;
		LPDIRECT3DINDEXBUFFER9 ib;
		island->GetVertexBuffer(&vb);
		island->GetIndexBuffer(&ib);	
		pd3dDevice->SetStreamSource(0, vb, 0, island->GetNumBytesPerVertex());
		pd3dDevice->SetIndices(ib);
		pd3dDevice->SetFVF( island->GetFVF() );

		g_pIslandEffect->Begin(NULL,NULL);
		g_pIslandEffect->BeginPass(0);			
		g_pIslandEffect->SetMatrix(g_hIslandViewProj, g_pObservingCamera->GetViewProjMatrix());
		g_pIslandEffect->SetMatrix(g_hIslandView, g_pObservingCamera->GetViewMatrix());			
		g_pIslandEffect->SetVector(g_hIslandSunVec,&D3DXVECTOR4(cos(g_fSunPosTheta)*sin(g_fSunPosAlpha), 
			sin(g_fSunPosTheta), cos(g_fSunPosTheta)*cos(g_fSunPosAlpha),0));
		g_pIslandEffect->SetFloat(g_hIslandSunShininess, g_fSunShininess);			
		g_pIslandEffect->SetFloat(g_hIslandSunStrength, g_fSunStrength);
		g_pIslandEffect->SetVector(g_hIslandWaterColor, &D3DXVECTOR4(g_fWaterColorR, g_fWaterColorG, g_fWaterColorB, 1));
		g_pIslandEffect->SetVector(g_hIslandViewPos, &D3DXVECTOR4(g_pObservingCamera->GetEyePt()->x,
			g_pObservingCamera->GetEyePt()->y, g_pObservingCamera->GetEyePt()->z,1));
		g_pIslandEffect->SetTexture(g_hIslandTex, g_texIsland);						
	
		pd3dDevice->DrawIndexedPrimitive(	D3DPT_TRIANGLELIST, 0,	0, island->GetNumVertices(), 0, island->GetNumFaces() );				
		g_pIslandEffect->EndPass();
		g_pIslandEffect->End();
		SAFE_RELEASE(vb);
		SAFE_RELEASE(ib);
#endif
		// restore stuff
		pd3dDevice->SetRenderState( D3DRS_LIGHTING, false);		
		pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );
		
		// restore	
		pd3dDevice->SetRenderState( D3DRS_ZFUNC, D3DCMP_LESSEQUAL );
		pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0);
		pd3dDevice->SetTransform(D3DTS_WORLD, &store);	
		pd3dDevice->SetRenderTarget(0, bb);
		SAFE_RELEASE(target);
		SAFE_RELEASE(bb);
	}
#endif
//水的反射部分
#if phase11 
	{
		pd3dDevice->GetRenderTarget(0, &bb );
		g_texReflectionMap->GetSurfaceLevel( 0,&target );
		pd3dDevice->SetRenderTarget(0, target);
		pd3dDevice->SetDepthStencilSurface( g_surDepthStencilForRefrRefl );

		// alpha & z must be cleared
		pd3dDevice->Clear( 0, NULL,D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0, 1.0f, 0 );

		D3DXMATRIXA16 store, scale;	
		// mirror the scene
		pd3dDevice->GetTransform(D3DTS_WORLD,&store);
		D3DXMatrixScaling( &scale, 1, -1, 1 );
		pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale );
		pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );		

		// add a clip-plane as well	
		float plane[4];

		plane[0] = 0;
		plane[1] = -1;
		plane[2] = 0;
		plane[3] = 0;

		pd3dDevice->SetClipPlane(0,plane);
		pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 1);
		/
		sun.Direction.x = -cos(g_fSunPosTheta) *sin(g_fSunPosAlpha);
		sun.Direction.y = sin(g_fSunPosTheta);
		sun.Direction.z = -cos(g_fSunPosTheta)*cos(g_fSunPosAlpha);
		sun.Diffuse.r = 1.0f;
		sun.Diffuse.g = 1.0f;
		sun.Diffuse.b = 1.0f;
		sun.Diffuse.a = 1.0f;
		sun.Ambient.a = 1.0f;
		sun.Ambient.r = 0.2f;
		sun.Ambient.g = 0.3f;
		sun.Ambient.b = 0.3f;
		sun.Specular.r = 1.0f;
		sun.Specular.g = 1.0f;
		sun.Specular.b = 1.0f;
		sun.Specular.a = 1.0f;
		sun.Attenuation0 = 1.0f;
		sun.Type = D3DLIGHT_DIRECTIONAL;
		pd3dDevice->SetLight(0, &sun);
		pd3dDevice->LightEnable( 0, true);	
		/ draw duck
		{
			D3DXMATRIXA16 store, offset, yrot,scale;
			pd3dDevice->GetTransform(D3DTS_WORLD,&store);
			float duckX = -15, duckZ = -5;
			D3DXMatrixTranslation( &offset, duckie_pos.x, -duckie_pos.y + 
				myNoise.get_height_at(duckie_pos.x,duckie_pos.z), duckie_pos.z);

			pd3dDevice->MultiplyTransform(D3DTS_WORLD, &offset );
			D3DXMatrixRotationY( &yrot, duckie_pos.angle);
			pd3dDevice->MultiplyTransform(D3DTS_WORLD, &yrot );
			D3DXMatrixScaling( &scale, 3, 3, 3 );
			pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale );

			//g_pd3dDevice->SetMaterial((D3DMATERIAL9*)duck_Materials->GetBufferPointer());
			pd3dDevice->SetRenderState( D3DRS_LIGHTING, true);

			pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );
			pd3dDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR1 );
			pd3dDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1 );

			float plane[4];
			pd3dDevice->GetClipPlane(0,plane);
			plane[3] = myNoise.get_height_at(duckX, duckZ) + 0.1;
			pd3dDevice->SetClipPlane(0,plane);
			duckie->DrawSubset(0);		
			pd3dDevice->SetTransform(D3DTS_WORLD, &store);
		}
			

		// restore stuff
		pd3dDevice->SetRenderState( D3DRS_LIGHTING, false);		
		pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );
		///
		
		// restore
		pd3dDevice->SetRenderState( D3DRS_CLIPPLANEENABLE, 0);
		pd3dDevice->SetTransform(D3DTS_WORLD, &store);	
		pd3dDevice->SetRenderTarget(0, bb);
		pd3dDevice->SetDepthStencilSurface( g_surOriginDepthStencil );
		SAFE_RELEASE(target);
		SAFE_RELEASE(bb);
	}
#endif
	pd3dDevice->Clear( 0, NULL,D3DCLEAR_ZBUFFER|D3DCLEAR_TARGET, 
		D3DCOLOR_XRGB((int)(255 * g_fWaterColorR),(int)(255 * g_fWaterColorG),
		(int)(255 * g_fWaterColorB)), 1.0f, 0 );	
	// set rendering states		
	pd3dDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
	pd3dDevice->SetRenderState(D3DRS_ZWRITEENABLE,true);
	pd3dDevice->SetRenderState(D3DRS_ZFUNC,D3DCMP_LESSEQUAL);
	pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,false);
//天空盒
#if phase12
	pd3dDevice->SetStreamSource( 0, g_pSkyBoxVB, 0, sizeof(SURFACEVERTEX) );
	pd3dDevice->SetFVF( D3DFVF_SURFACEVERTEX);
	pd3dDevice->SetIndices(g_pSkyBoxIB);
	g_pSkyBoxEffect->Begin(NULL,NULL);
	g_pSkyBoxEffect->BeginPass(0);
	

	// build the 'fake' viweproj with the distance vector set to 0,0,0

	D3DXMATRIXA16 fvproj(*g_pObservingCamera->GetViewMatrix());
	fvproj._41 = 0;
	fvproj._42 = 0;
	fvproj._43 = 0;
	fvproj = fvproj * *g_pObservingCamera->GetProjMatrix();

	g_pSkyBoxEffect->SetMatrix(g_hSkyViewProj,&fvproj);
	//g_pSkyBoxEffect->SetMatrix(g_hSkyViewProj, g_pRenderingCamera->GetViewProjMatrix());
	g_pSkyBoxEffect->SetMatrix(g_hSkyInvViewProj,g_pObservingCamera->GetInvViewProjMatrix());	
	g_pSkyBoxEffect->SetMatrix(g_hSkyInvView,g_pObservingCamera->GetInvViewMatrix());	
	g_pSkyBoxEffect->SetFloat(g_hSkySunAlpha, g_fSunPosAlpha);
	g_pSkyBoxEffect->SetFloat(g_hSkySunTheta, g_fSunPosTheta);
	g_pSkyBoxEffect->SetFloat(g_hSkySunShininess, g_fSunShininess);
	g_pSkyBoxEffect->SetFloat(g_hSkySunStrength, g_fSunStrength);	

	g_pSkyBoxEffect->SetVector(g_hSkyViewPosition, &D3DXVECTOR4(g_pObservingCamera->GetEyePt()->x,
		g_pObservingCamera->GetEyePt()->y, g_pObservingCamera->GetEyePt()->z,1));	
	g_pSkyBoxEffect->SetTexture(g_hSkyEnvironmentMap, g_texEnvironmentMap);	
	pd3dDevice->DrawIndexedPrimitive(	D3DPT_TRIANGLELIST,	0,	0, skyboxdetail*skyboxdetail, 0, 2*(skyboxdetail-1)*(skyboxdetail-1) );
	g_pSkyBoxEffect->EndPass();
	g_pSkyBoxEffect->End();
#endif
	if( g_bPlaneWithinFrustrum )
	{
//渲染水下
#if phase16
	// underwater pass
			pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW  );
			pd3dDevice->SetStreamSource( 0, g_pGridVB, 0, sizeof(SOFTWARESURFACEVERTEX) );
			pd3dDevice->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX);			
			pd3dDevice->SetIndices(g_pGridIB);

			g_pUnderWaterEffect->Begin(NULL,NULL);
			g_pUnderWaterEffect->BeginPass(0);			
			g_pUnderWaterEffect->SetMatrix(g_hUnderWaterViewProj, g_pObservingCamera->GetViewProjMatrix());
			g_pUnderWaterEffect->SetFloat(g_hUnderWaterSunAlpha, g_fSunPosAlpha);
			g_pUnderWaterEffect->SetFloat(g_hUnderWaterSunTheta, g_fSunPosTheta);
			g_pUnderWaterEffect->SetFloat(g_hUnderWaterSunShininess, g_fSunShininess);
			g_pUnderWaterEffect->SetFloat(g_hUnderWaterSunStrength, g_fSunStrength);
			g_pUnderWaterEffect->SetVector(g_hUnderWaterWaterColor, &D3DXVECTOR4(g_fWaterColorR, g_fWaterColorG, g_fWaterColorB, 1));
			g_pUnderWaterEffect->SetVector(g_hUnderWaterViewPos, &D3DXVECTOR4(g_pObservingCamera->GetEyePt()->x,
				g_pObservingCamera->GetEyePt()->y, g_pObservingCamera->GetEyePt()->z,1));
			g_pUnderWaterEffect->SetTexture(g_hUnderWaterEnvironmentMap,g_texEnvironmentMap);
			g_pUnderWaterEffect->SetTexture(g_hUnderWaterFresnelMap,g_texFresnelMap);
			g_pUnderWaterEffect->SetTexture(g_hUnderWaterNormalMap,g_texNormalMap);
			V( pd3dDevice->DrawIndexedPrimitive(	D3DPT_TRIANGLELIST, 0,	0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) ) );			
			g_pUnderWaterEffect->EndPass();
			g_pUnderWaterEffect->End();
#endif
			pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE  );	
			pd3dDevice->SetStreamSource( 0, g_pGridVB, 0, sizeof(SOFTWARESURFACEVERTEX) );
			pd3dDevice->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX);			
			pd3dDevice->SetIndices(g_pGridIB);

#if phase6
			// write data to height map

	//写高度图纹理
	V( pd3dDevice->GetRenderTarget(0, &bb) );
	V( g_texHeightMap->GetSurfaceLevel(0, &target) );
	V( pd3dDevice->GetDepthStencilSurface(&old_depthstencil) );
	V( pd3dDevice->SetFVF( D3DFVF_SOFTWARESURFACEVERTEX ) );
	V( g_pHeightMapEffect->Begin(NULL, NULL) );
	V( g_pHeightMapEffect->BeginPass(0) );
	g_pHeightMapEffect->SetFloat(g_hScale, g_fScale);
	g_pHeightMapEffect->SetTexture(g_hNoiseTex0, g_texPackedNoise[0]);
	g_pHeightMapEffect->SetTexture(g_hNoiseTex1, g_texPackedNoise[1]);
	V( pd3dDevice->SetRenderTarget(0, target) );
	V( pd3dDevice->SetDepthStencilSurface(g_surDepthStencil) );
	V( pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE ));
	V( pd3dDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) ));	
	V( g_pHeightMapEffect->EndPass() );
	V( g_pHeightMapEffect->End());
	//D3DXSaveTextureToFile(L"HeightMap.dds", D3DXIFF_DDS,g_texHeightMap,NULL);
	//写法向量纹理
#if phase7
	SAFE_RELEASE(target);
	V( g_texNormalMap->GetSurfaceLevel(0, &target) );
	V( pd3dDevice->SetRenderTarget(0, target) );
	V( g_pNormalMapEffect->Begin(NULL, NULL) );
	V( g_pNormalMapEffect->BeginPass(0) );
	g_pNormalMapEffect->SetFloat(g_hInvMapSizeX, 1.0f / nmapsize_x);
	g_pNormalMapEffect->SetFloat(g_hInvMapSizeY, 1.0f / nmapsize_y);
	g_pNormalMapEffect->SetFloatArray(g_hCorner00, (const FLOAT *)&t_corners0, 4);
	g_pNormalMapEffect->SetFloatArray(g_hCorner01, (const FLOAT *)&t_corners1, 4);
	g_pNormalMapEffect->SetFloatArray(g_hCorner10, (const FLOAT *)&t_corners2, 4);
	g_pNormalMapEffect->SetFloatArray(g_hCorner11, (const FLOAT *)&t_corners3, 4);
	g_pNormalMapEffect->SetFloat(g_hAmplitude, g_fStrength);
	g_pNormalMapEffect->SetTexture(g_hHeightMap, g_texHeightMap);
	V( pd3dDevice->DrawIndexedPrimitive(	D3DPT_TRIANGLELIST, 0,	0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) ) );			
	V( g_pNormalMapEffect->EndPass() );
	V( g_pNormalMapEffect->End() );
	//D3DXSaveTextureToFile(L"NormalMap.dds", D3DXIFF_DDS,g_texNormalMap,NULL);
#endif
	// restore the device
	pd3dDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_TRUE );
	pd3dDevice->SetRenderTarget( 0, bb );
	pd3dDevice->SetDepthStencilSurface( old_depthstencil );
	/
	SAFE_RELEASE(target);
	SAFE_RELEASE(bb);
	SAFE_RELEASE(old_depthstencil);
#endif

#if phase8
	pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW );
	V( g_pWaterGridEffect->Begin(NULL, NULL) );
	V( g_pWaterGridEffect->BeginPass(0) );
	g_pWaterGridEffect->SetMatrix(g_hViewProj, g_pObservingCamera->GetViewProjMatrix());
	g_pWaterGridEffect->SetMatrix(g_hView, g_pObservingCamera->GetViewMatrix());
	g_pWaterGridEffect->SetVector(g_hViewPos, &D3DXVECTOR4(g_pObservingCamera->GetEyePt()->x,
		g_pObservingCamera->GetEyePt()->y, g_pObservingCamera->GetEyePt()->z,1));
	
#if phase9

	g_pWaterGridEffect->SetVector(g_hSunVec,&D3DXVECTOR4(cos(g_fSunPosTheta)*sin(g_fSunPosAlpha), 
		sin(g_fSunPosTheta), cos(g_fSunPosTheta)*cos(g_fSunPosAlpha),0));
	g_pWaterGridEffect->SetFloat(g_hSunShininess, g_fSunShininess);
	g_pWaterGridEffect->SetFloat(g_hSunStrength, g_fSunStrength);
	g_pWaterGridEffect->SetFloat(g_hReflRefrOffset, g_fReflRefrOffset);
	g_pWaterGridEffect->SetBool(g_hDiffuseSkyRef, g_bDiffuseSkyRef);
	g_pWaterGridEffect->SetVector(g_hWaterColor, &D3DXVECTOR4(g_fWaterColorR, g_fWaterColorG, g_fWaterColorB, 1));
	g_pWaterGridEffect->SetFloat(g_hLODbias, g_fLODbias);
	g_pWaterGridEffect->SetTexture(g_hEnvironmentMap, g_texEnvironmentMap);
	g_pWaterGridEffect->SetTexture(g_hHeightMapForWaterGridFX, g_texHeightMap);
	g_pWaterGridEffect->SetTexture(g_hNormalMapForWaterGridFX, g_texNormalMap);
	g_pWaterGridEffect->SetTexture(g_hFresnelMap, g_texFresnelMap);
	
#endif
#if phase10
	g_pWaterGridEffect->SetTexture(g_hRefractionMap, g_texRefractionMap);
#endif
#if phase11
	g_pWaterGridEffect->SetTexture(g_hReflectionMap, g_texReflectionMap);
#endif
	V( pd3dDevice->DrawIndexedPrimitive(	D3DPT_TRIANGLELIST, 0,	0, sizeX*sizeY, 0, 2*(sizeX-1)*(sizeY-1) ) );			
	V( g_pWaterGridEffect->EndPass() );
	V( g_pWaterGridEffect->End() );
#endif
#if phase13
	pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CCW  );	
	pd3dDevice->SetDepthStencilSurface(g_surOriginDepthStencil);
		/
	sun.Direction.x = -cos(g_fSunPosTheta) *sin(g_fSunPosAlpha);
	sun.Direction.y = sin(g_fSunPosTheta);
	sun.Direction.z = -cos(g_fSunPosTheta)*cos(g_fSunPosAlpha);
	sun.Diffuse.r = 1.0f;
	sun.Diffuse.g = 1.0f;
	sun.Diffuse.b = 1.0f;
	sun.Diffuse.a = 1.0f;
	sun.Ambient.a = 1.0f;
	sun.Ambient.r = 0.2f;
	sun.Ambient.g = 0.3f;
	sun.Ambient.b = 0.3f;
	sun.Specular.r = 1.0f;
	sun.Specular.g = 1.0f;
	sun.Specular.b = 1.0f;
	sun.Specular.a = 1.0f;
	sun.Attenuation0 = 1.0f;
	sun.Type = D3DLIGHT_DIRECTIONAL;
	pd3dDevice->SetLight(0, &sun);
	pd3dDevice->LightEnable( 0, true);	
	/ draw duck
	{
		D3DXMATRIXA16 store, offset, yrot,scale;
		pd3dDevice->GetTransform(D3DTS_WORLD,&store);
		float duckX = -15, duckZ = -5;
// 		D3DXMatrixTranslation( &offset, duckie_pos.x, -duckie_pos.y + 
// 			myNoise.get_height_at(duckie_pos.x,duckie_pos.z), duckie_pos.z);
		D3DXMatrixTranslation( &offset, duckie_pos.x, duckie_pos.y, duckie_pos.z);
		pd3dDevice->MultiplyTransform(D3DTS_WORLD, &offset );
		D3DXMatrixRotationY( &yrot, duckie_pos.angle);
		pd3dDevice->MultiplyTransform(D3DTS_WORLD, &yrot );
		D3DXMatrixScaling( &scale, 3, 3, 3 );
		pd3dDevice->MultiplyTransform(D3DTS_WORLD, &scale );

		//g_pd3dDevice->SetMaterial((D3DMATERIAL9*)duck_Materials->GetBufferPointer());
		pd3dDevice->SetRenderState( D3DRS_LIGHTING, true);

		pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );
		pd3dDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR1 );
		pd3dDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_COLOR1 );

		float plane[4];
		pd3dDevice->GetClipPlane(0,plane);
		plane[3] = myNoise.get_height_at(duckX, duckZ) + 0.1;
		pd3dDevice->SetClipPlane(0,plane);
		duckie->DrawSubset(0);		
		pd3dDevice->SetTransform(D3DTS_WORLD, &store);
	}
		
#if phase15
	{
		sun.Direction.y = -sin(g_fSunPosTheta);
		pd3dDevice->SetLight(0, &sun);
		pd3dDevice->SetRenderState( D3DRS_LIGHTING, true);

		pd3dDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );
		pd3dDevice->SetRenderState( D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL );
		pd3dDevice->SetRenderState( D3DRS_AMBIENTMATERIALSOURCE, D3DMCS_MATERIAL );
		pd3dDevice->SetTexture(0, g_texIsland);
		float plane[4];
		pd3dDevice->GetClipPlane(0,plane);
		plane[3] = 0;
		pd3dDevice->SetClipPlane(0,plane);
		for(int i=0; i<7; i++)
		{
			LPD3DXMATERIAL mat = (LPD3DXMATERIAL) island_Materials->GetBufferPointer();			
			pd3dDevice->SetMaterial(&(mat->MatD3D));
			island->DrawSubset(i);
		}					
	}
#endif
	// restore stuff
	pd3dDevice->SetRenderState( D3DRS_LIGHTING, false);		
	pd3dDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_CW  );
	///
#endif

	}

#endif

        V( pd3dDevice->EndScene() );
    }
}


//--------------------------------------------------------------------------------------
// Handle messages to the application 
//--------------------------------------------------------------------------------------
LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                          bool* pbNoFurtherProcessing, void* pUserContext )
{
#if phase0
	switch( uMsg )
	{
	case WM_KEYDOWN:
		{
			keys[wParam] = true;
			break;
		}
	case WM_KEYUP:
		{
			keys[wParam] = false;
			break;
		}
	}
#endif
#if phase1
	if( g_pRenderingCamera)
		g_pRenderingCamera->HandleMessages( hWnd, uMsg, wParam, lParam );
#endif

    return 0;
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9ResetDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9LostDevice( void* pUserContext )
{
#if phase3
	SAFE_RELEASE(g_texPackedNoise[0]);
	SAFE_RELEASE(g_texPackedNoise[1]);
#endif
#if phase5
	SAFE_RELEASE(g_pGridVB);
	SAFE_RELEASE(g_pGridIB);
#endif
#if phase6
	if( g_pHeightMapEffect )
        g_pHeightMapEffect->OnLostDevice();
	SAFE_RELEASE(g_texHeightMap);
	SAFE_RELEASE(g_surDepthStencil);
#endif

#if phase7
	if( g_pNormalMapEffect )
		g_pNormalMapEffect->OnLostDevice();
	SAFE_RELEASE(g_texNormalMap);
#endif
#if phase8
	if( g_pWaterGridEffect )
		g_pWaterGridEffect->OnLostDevice();
#endif
#if phase10
	SAFE_RELEASE(g_texRefractionMap);

#endif
#if phase11
	SAFE_RELEASE(g_texReflectionMap);
	SAFE_RELEASE(g_surDepthStencilForRefrRefl);
#endif
#if phase12
	SAFE_RELEASE(g_pSkyBoxVB);
	SAFE_RELEASE(g_pSkyBoxIB);
#endif
#if phase14
	if( g_pIslandEffect )
		g_pIslandEffect->OnLostDevice();
#endif
#if phase16
	if( g_pUnderWaterEffect)
		g_pUnderWaterEffect->OnLostDevice();
#endif
}


//--------------------------------------------------------------------------------------
// Release D3D9 resources created in the OnD3D9CreateDevice callback 
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9DestroyDevice( void* pUserContext )
{
#if phase1
	delete g_pRenderingCamera;
#endif

#if phase5
	delete [] g_pVertices;
#endif
#if phase6
	SAFE_RELEASE(g_pHeightMapEffect);
#endif
#if phase7
	SAFE_RELEASE(g_pNormalMapEffect);
#endif
#if phase8
	SAFE_RELEASE(g_pWaterGridEffect);
#endif
#if phase9
	SAFE_RELEASE(g_texEnvironmentMap);
	SAFE_RELEASE(g_texFresnelMap);
#endif
#if phase11
	SAFE_RELEASE(duckie);
	SAFE_RELEASE(duck_Adjacency);
	SAFE_RELEASE(duck_Materials);
	SAFE_RELEASE(duck_EffectInstances);
	SAFE_RELEASE(g_surOriginDepthStencil);
#endif
#if phase12
	SAFE_RELEASE(g_pSkyBoxEffect);
#endif
#if phase14
	SAFE_RELEASE(g_pIslandEffect);
	SAFE_RELEASE(g_texIsland);
	SAFE_RELEASE(island);
	SAFE_RELEASE(island_Adjacency);
	SAFE_RELEASE(island_Materials);
	SAFE_RELEASE(island_EffectInstances);
#endif
#if phase16
	SAFE_RELEASE(g_pUnderWaterEffect);
#endif
}


//--------------------------------------------------------------------------------------
// Initialize everything and go into a render loop
//--------------------------------------------------------------------------------------
INT WINAPI wWinMain( HINSTANCE, HINSTANCE, LPWSTR, int )
{
    // Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
    _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
#endif

    // Set the callback functions
    DXUTSetCallbackD3D9DeviceAcceptable( IsD3D9DeviceAcceptable );
    DXUTSetCallbackD3D9DeviceCreated( OnD3D9CreateDevice );
    DXUTSetCallbackD3D9DeviceReset( OnD3D9ResetDevice );
    DXUTSetCallbackD3D9FrameRender( OnD3D9FrameRender );
    DXUTSetCallbackD3D9DeviceLost( OnD3D9LostDevice );
    DXUTSetCallbackD3D9DeviceDestroyed( OnD3D9DestroyDevice );
    DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
    DXUTSetCallbackMsgProc( MsgProc );
    DXUTSetCallbackFrameMove( OnFrameMove );

    // TODO: Perform any application-level initialization here

    // Initialize DXUT and create the desired Win32 window and Direct3D device for the application
    DXUTInit( true, true ); // Parse the command line and show msgboxes
    DXUTSetHotkeyHandling( true, true, true );  // handle the default hotkeys
    DXUTSetCursorSettings( true, true ); // Show the cursor and clip it when in full screen
    DXUTCreateWindow( L"3D_Shader_ProjectedGrid" );
    DXUTCreateDevice( true, 1024, 768 );

    // Start the render loop
    DXUTMainLoop();

    // TODO: Perform any application-level cleanup here

    return DXUTGetExitCode();
}



源代码请点此


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值