哎呀,这个月的最后一天了,赶快在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(); }
源代码请点此