您的位置:首页 > 其它

3DShader之投影网格(Projected Grid)

2013-09-30 23:06 405 查看
哎呀,这个月的最后一天了,赶快在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();
}


源代码请点此
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: