/** \brief Data type to define fullscreen quad vertices. */ struct Vertex { float x, y, z; float nx, ny, nz; float tu, tv; }; /** \brief Most of application-specific logic is here. */ class EnvMap { /// Callback function to evaluate reflectivity integral. See GenerateCosTexture() and eval(). typedef float (*eval_fn)(float,float); IDirect3DDevice9* pd3dDevice; ///< THE D3D DEVICE ID3DXEffect* g_pEffect; ///< THE EFFECT FILE CModelViewerCamera* camera; ///< Rotate/zoom camera, always looking to the origin HRESULT hr; // return codes /// \brief Cubemap that stores the environment as seen from the reference point. /// \brief See method RenderCubeMap(). IDirect3DCubeTexture9* pCubeTexture; /// \brief Low-resolution (downsampled) cubemap, derived from #pCubeTexture. /// \brief See ReduceCubeMapSize(). IDirect3DCubeTexture9* pCubeTextureSmall; /// \brief Low-resolution cubemap that stores preconvolved data for diffuse/specular environment mapping. /// \brief See method PreConvolve(). IDirect3DCubeTexture9* pCubeTexturePreConvolved; /// Helper texture with precomputed geometric factor values IDirect3DTexture9* pCosValuesTexture; /// Texture to be displayed on the walls of the cubic room. IDirect3DTexture9* pRoomTexture; bool bCubeMapIsValid; /// indicates that the cube map has to be re-generated bool bShininessIsValid; /// indicates that the reflectivity integral has to be re-calculated Cube* cube; /// Simple cube centralMesh for the room. See EnvMap::DrawEnvObjects(). float roomSize; /// Size of the cubic room. Mesh* centralMesh; /// The diffuse/glossy object to be shaded. Mesh* meshes[10]; /// Objects of the environment (fireballs, etc.). int meshCount; /// Number of objects in the environment. D3DXVECTOR3 reference_pos; public: EnvMap() { bCubeMapIsValid = true; bShininessIsValid = false; pCubeTexture = NULL; pCubeTextureSmall = NULL; pCubeTexturePreConvolved = NULL; pCosValuesTexture = NULL; centralMesh = NULL; roomSize = 2.2; reference_pos = D3DXVECTOR3(0,0,0); } void SetCamera(CModelViewerCamera* camera) { this->camera = camera; } void InvalidateCubeMap() { bCubeMapIsValid = false; } void InvalidateShininess() { bShininessIsValid = false; } void InvalidateResolution(); D3DXVECTOR3& GetReferencePos() { return reference_pos; } void ChooseMesh(int whichMesh); void SetMeshSize(float d) { if (centralMesh != NULL) centralMesh->SetPreferredDiameter(d); } void SetMeshPosition(D3DXVECTOR3 pos) { centralMesh->SetMeshPosition(pos); } D3DXVECTOR3 GetMeshPosition() { return centralMesh->GetMeshPosition(); } void KeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown ); void DoRendering(D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj); void DrawCenterObjects( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj ); void DrawEnvObjects( D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj ); void SetWorldViewProj(D3DXMATRIXA16& mWorld, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj ); D3DXMATRIXA16 ScaleAndOffset(float fScale, D3DXVECTOR3 vOffset); D3DXMATRIXA16 ScaleAndOffset(D3DXVECTOR3 vScale, D3DXVECTOR3 vOffset); void RenderCubeMap(IDirect3DCubeTexture9* pCubeTexture); //IDirect3DTexture9* GenerateCosTexture(); IDirect3DTexture9* GenerateCosTexture( eval_fn evaluator ); //void GenerateCosTextureIfNotFound(); void GenerateCosTextureIfNotFound( wchar_t* fileName, eval_fn evaluator ); void OnFrameRender( IDirect3DDevice9* pd3dDevice, D3DXMATRIXA16& mView, D3DXMATRIXA16& mProj ); void OnCreateDevice( IDirect3DDevice9* pd3dDevice, ID3DXEffect* g_pEffect ); void OnDestroyDevice(); void OnResetDevice(); void OnLostDevice(); IDirect3DVertexBuffer9 *pVertexBuffer; void InitFullScreenQuad() { Vertex g_quadVertices[] = { {-1, 1, 0, 0, 0, 1, 0,0 }, { 1, 1, 0, 0, 0, 1, 1,0 }, {-1,-1, 0, 0, 0, 1, 0,1 }, { 1,-1, 0, 0, 0, 1, 1,1 } }; pd3dDevice->CreateVertexBuffer( sizeof(g_quadVertices), D3DUSAGE_WRITEONLY, D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1, D3DPOOL_DEFAULT, &pVertexBuffer, NULL ); void *pVertices = NULL; pVertexBuffer->Lock( 0, sizeof(g_quadVertices), (void**)&pVertices, 0 ); memcpy( pVertices, g_quadVertices, sizeof(g_quadVertices) ); pVertexBuffer->Unlock(); } void DrawFullScreenQuad() { // draw a square pd3dDevice->SetStreamSource( 0, pVertexBuffer, 0, sizeof(Vertex) ); pd3dDevice->SetFVF( D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 ); pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2); } void ReduceCubeMapSize(IDirect3DCubeTexture9* pSourceCube, IDirect3DCubeTexture9* pDestCube); void PreConvolve(IDirect3DCubeTexture9* pSourceCube, IDirect3DCubeTexture9* pDestCube); //void RenderToCubeTexture(IDirect3DCubeTexture9* pDestCube); void SaveCubeMap(IDirect3DCubeTexture9* pCubeTexture, char* FileNamePrefix, char* FileNameSuffix = ""); IDirect3DCubeTexture9* CreateCubeTexture( int size, D3DFORMAT Format ) { HRESULT hr; IDirect3DCubeTexture9* pCubeTexture; if( FAILED(hr = D3DXCreateCubeTexture( pd3dDevice, size, 1, // mipmap levels = 1 D3DUSAGE_RENDERTARGET, Format, D3DPOOL_DEFAULT, &pCubeTexture ))) { MessageBox(NULL, L"Cube texture creation failed!", L"Error", MB_OK|MB_TOPMOST); exit(-1); } return pCubeTexture; } };