#include #include #include #include #include #include #include #include #include #include #include #include "resource.h" #include "DXUT/Core/dxut.h" #include "DXUTmisc.h" #include "DXUTcamera.h" #include "DXUTgui.h" #include "DXUTsettingsDlg.h" #include "SDKmisc.h" #include "Effects11/Inc/d3dx11effect.h" #include "ntx/NTX.h" #include "debug.h" // Convenience macros for safe effect variable retrieval #define SAFE_GET_PASS(Technique, name, var) {assert(Technique!=NULL); var = Technique->GetPassByName( name ); assert(var->IsValid());} #define SAFE_GET_TECHNIQUE(effect, name, var) {assert(effect!=NULL); var = effect->GetTechniqueByName( name ); assert(var->IsValid());} #define SAFE_GET_SCALAR(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsScalar(); assert(var->IsValid());} #define SAFE_GET_VECTOR(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsVector(); assert(var->IsValid());} #define SAFE_GET_MATRIX(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsMatrix(); assert(var->IsValid());} #define SAFE_GET_SAMPLER(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsSampler(); assert(var->IsValid());} #define SAFE_GET_RESOURCE(effect, name, var) {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsShaderResource(); assert(var->IsValid());} // Help macros #define DEG2RAD( a ) ( (a) * D3DX_PI / 180.f ) using namespace std; //-------------------------------------------------------------------------------------- // Global variables //-------------------------------------------------------------------------------------- // Camera struct CAMERAPARAMS { float m_Fovy; float m_Aspect; float m_NearPlane; float m_FarPlane; } g_CameraParams; float g_CameraMoveScaler = 1000.f; float g_CameraRotateScaler = 0.01f; CFirstPersonCamera g_Camera; // A first person camera // User Interface CDXUTDialogResourceManager g_DialogResourceManager; // manager for shared resources of dialogs CD3DSettingsDlg g_SettingsDlg; // Device settings dialog CDXUTTextHelper* g_TxtHelper = NULL; CDXUTDialog g_HUD; // dialog for standard controls CDXUTDialog g_SampleUI; // dialog for sample specific controls // A D3DX rendering effect ID3DX11Effect* g_Effect = NULL; // The whole rendering effect // BEGIN: Assignment 4.2.1 ID3DX11EffectShaderResourceVariable* g_HeightEV = NULL; ID3DX11EffectShaderResourceVariable* g_NormalEV = NULL; ID3DX11EffectScalarVariable* g_TerrainResEV = NULL; ID3DX11EffectScalarVariable* g_TerrainQuadResEV = NULL; // END: Assignment 4.2.1 ID3DX11EffectTechnique* g_Technique = NULL; // One technique to render the effect ID3DX11EffectPass* g_Pass0 = NULL; // One rendering pass of the technique ID3DX11EffectMatrixVariable* g_WorldEV = NULL; // World matrix effect variable ID3DX11EffectMatrixVariable* g_WorldViewProjectionEV = NULL; // WorldViewProjection matrix effect variable ID3DX11EffectShaderResourceVariable* g_DiffuseEV = NULL; // Effect variable for the diffuse color texture ID3DX11EffectVectorVariable* g_LightDirEV = NULL; // Light direction in object space // Background color D3DXVECTOR4 g_ClearColor; // Terrain meta information struct PtfHeader { int16_t magicNumber; // Must be 0x00DA int16_t version; // Must be 1 int32_t heightSize; // Height data size int32_t colorSize; // Color data size int32_t normalSize; // Normal data size } g_TerrainHeader; char g_TerrainPath[MAX_PATH] = { '\0' }; int g_TerrainResolution; int g_TerrainNumVertices = 3; int g_TerrainNumTriangles = 1; int g_TerrainNumIndices; float g_TerrainWidth = 1000.0f; float g_TerrainDepth = 1000.0f; float g_TerrainHeight = 400.0f; bool g_TerrainSpinning = true; float g_TerrainSpinSpeed = 0.0f; D3DXMATRIX g_TerrainWorld; // object- to world-space transformation // Terrain rendering resources // BEGIN: Assignment 4.2.2 ID3D11Buffer* g_TerrainHeightBuf = NULL; ID3D11ShaderResourceView* g_TerrainHeightSRV = NULL; ID3D11Texture2D* g_TerrainNormalTex = NULL; ID3D11ShaderResourceView* g_TerrainNormalSRV = NULL; // END: Assignment 4.2.2 ID3D11Texture2D* g_TerrainDiffuseTex = NULL; // The terrain's material color for diffuse lighting ID3D11ShaderResourceView* g_TerrainDiffuseSRV = NULL; // Describes the structure of the diffuse texture to the shader stages // Scene information D3DXVECTOR4 g_LightDir; // General meta data char g_DebugTexPath[MAX_PATH] = { '\0' }; // General resources ID3D11ShaderResourceView* g_DebugSRV = NULL; //-------------------------------------------------------------------------------------- // UI control IDs //-------------------------------------------------------------------------------------- #define IDC_TOGGLEFULLSCREEN 1 #define IDC_TOGGLEREF 2 #define IDC_CHANGEDEVICE 3 #define IDC_TOGGLESPIN 4 #define IDC_RELOAD_SHADERS 101 //-------------------------------------------------------------------------------------- // Forward declarations //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ); void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ); void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ); void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext ); bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext ); bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext ); HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ); void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext ); void CALLBACK OnD3D11DestroyDevice( void* pUserContext ); void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext ); void InitApp(); void RenderText(); void ReleaseShader(); HRESULT ReloadShader(ID3D11Device* pd3dDevice); //-------------------------------------------------------------------------------------- // Entry point to the program. Initializes everything and goes into a message processing // loop. Idle time is used to render the scene. //-------------------------------------------------------------------------------------- int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow ) { // Enable run-time memory check for debug builds. #if defined(DEBUG) | defined(_DEBUG) _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ); #endif // Old Direct3D Documentation: // Start > All Programs > Microsoft DirectX SDK (June 2010) > Windows DirectX Graphics Documentation // DXUT Documentaion: // Start > All Programs > Microsoft DirectX SDK (June 2010) > DirectX Documentation for C++ : The DirectX Software Development Kit > Programming Guide > DXUT // New Direct3D Documentaion (just for reference, use old documentation to find explanations): // http://msdn.microsoft.com/en-us/library/windows/desktop/hh309466%28v=vs.85%29.aspx // Set DXUT callbacks DXUTSetCallbackMsgProc( MsgProc ); DXUTSetCallbackKeyboard( OnKeyboard ); DXUTSetCallbackFrameMove( OnFrameMove ); DXUTSetCallbackDeviceChanging( ModifyDeviceSettings ); DXUTSetCallbackD3D11DeviceAcceptable( IsD3D11DeviceAcceptable ); DXUTSetCallbackD3D11DeviceCreated( OnD3D11CreateDevice ); DXUTSetCallbackD3D11SwapChainResized( OnD3D11ResizedSwapChain ); DXUTSetCallbackD3D11SwapChainReleasing( OnD3D11ReleasingSwapChain ); DXUTSetCallbackD3D11DeviceDestroyed( OnD3D11DestroyDevice ); DXUTSetCallbackD3D11FrameRender( OnD3D11FrameRender ); InitApp(); DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params DXUTSetCursorSettings( true, true ); DXUTCreateWindow( L"TODO: Insert Title Here" ); // You may change the title DXUTCreateDevice( D3D_FEATURE_LEVEL_10_0, true, 1280, 720 ); DXUTMainLoop(); // Enter into the DXUT render loop return DXUTGetExitCode(); } //-------------------------------------------------------------------------------------- // Initialize the app //-------------------------------------------------------------------------------------- void InitApp() { HRESULT hr; WCHAR path[MAX_PATH]; // Parse the config file V(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"game.cfg")); ifstream stream(path); if(!stream) { MessageBoxA (NULL, "Fatal Error: game.cfg not found.", "Missing file", MB_ICONERROR | MB_OK); return; } std::string var; while(!stream.eof()) { stream >> var; if ( var.compare("DebugTexPath") ==0 ) stream >> g_DebugTexPath; if ( var.compare("Spinning") ==0 ) stream >> g_TerrainSpinning; if ( var.compare("SpinSpeed") ==0 ) stream >> g_TerrainSpinSpeed; if ( var.compare("BackgroundColor")==0 ) stream >> g_ClearColor.x >> g_ClearColor.y >> g_ClearColor.z >> g_ClearColor.w; // BEGIN: Assignment 3.2.1 // TODO: Parse the additional information in the config file into the variables: // g_TerrainPath, g_TerrainWidth, g_TerrainDepth and g_TerrainHeight // HINT: the operator '>>' converts the next word in 'stream' into the format of // its right hand side and is really flexible if ( var.compare("TerrainPath") ==0 ) stream >> g_TerrainPath; if ( var.compare("TerrainWidth") ==0 ) stream >> g_TerrainWidth; if ( var.compare("TerrainDepth") ==0 ) stream >> g_TerrainDepth; if ( var.compare("TerrainHeight") ==0 ) stream >> g_TerrainHeight; // END: Assignment 3.2.1 } stream.close(); // Intialize the user interface g_SettingsDlg.Init( &g_DialogResourceManager ); g_HUD.Init( &g_DialogResourceManager ); g_SampleUI.Init( &g_DialogResourceManager ); g_HUD.SetCallback( OnGUIEvent ); int iY = 30; int iYo = 26; g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, 170, 22 ); g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += iYo, 170, 22, VK_F3 ); g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += iYo, 170, 22, VK_F2 ); g_HUD.AddButton (IDC_RELOAD_SHADERS, L"Reload shaders (F5)", 0, iY += 24, 170, 22, VK_F5); g_SampleUI.SetCallback( OnGUIEvent ); iY = 10; iY += 24; g_SampleUI.AddCheckBox( IDC_TOGGLESPIN, L"Toggle Spinning", 0, iY += 24, 125, 22, g_TerrainSpinning ); } //-------------------------------------------------------------------------------------- // Render the help and statistics text. This function uses the ID3DXFont interface for // efficient text rendering. //-------------------------------------------------------------------------------------- void RenderText() { g_TxtHelper->Begin(); g_TxtHelper->SetInsertionPos( 5, 5 ); g_TxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) ); g_TxtHelper->DrawTextLine( DXUTGetFrameStats(true)); //DXUTIsVsyncEnabled() ) ); g_TxtHelper->DrawTextLine( DXUTGetDeviceStats() ); g_TxtHelper->End(); } //-------------------------------------------------------------------------------------- // Reject any D3D11 devices that aren't acceptable by returning false //-------------------------------------------------------------------------------------- bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo, DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext ) { return true; } //-------------------------------------------------------------------------------------- // Specify the initial device settings //-------------------------------------------------------------------------------------- bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext ) { // For the first device created if its a REF device, optionally display a warning dialog box static bool s_bFirstTime = true; if( s_bFirstTime ) { s_bFirstTime = false; if( ( DXUT_D3D9_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF ) || ( DXUT_D3D11_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) ) { DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver ); } } //// Enable anti aliasing //pDeviceSettings->d3d11.sd.SampleDesc.Count = 4; //pDeviceSettings->d3d11.sd.SampleDesc.Quality = 1; return true; } //-------------------------------------------------------------------------------------- // Create any D3D11 resources that aren't dependant on the back buffer //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); // http://msdn.microsoft.com/en-us/library/ff476891%28v=vs.85%29 V_RETURN( g_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) ); V_RETURN( g_SettingsDlg.OnD3D11CreateDevice( pd3dDevice ) ); g_TxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15 ); V_RETURN( ReloadShader(pd3dDevice) ); errno_t error; WCHAR path[MAX_PATH]; stringstream ss; wstringstream wss; // Initialize the camera D3DXVECTOR3 Eye( 0.0f, 2 * g_TerrainHeight, -0.5f * g_TerrainDepth ); D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f ); g_Camera.SetViewParams( &Eye, &At ); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206342%28v=vs.85%29.aspx g_Camera.SetScalers( g_CameraRotateScaler, g_CameraMoveScaler ); // Load the debug texture and create a shader resource view wss.str(L""); wss << g_DebugTexPath; V(DXUTFindDXSDKMediaFileCch( path, MAX_PATH, wss.str().c_str())); if (hr != S_OK) { ss.str(); ss << "Could not find '" << g_DebugTexPath << "'"; MessageBoxA (NULL, ss.str().c_str(), "Missing file", MB_ICONERROR | MB_OK); return hr; } V(D3DX11CreateShaderResourceViewFromFile(pd3dDevice, path, NULL, NULL, &g_DebugSRV, &hr)); if (hr != S_OK) { ss.str(); ss << "Could not load texture '" << g_DebugTexPath << "'"; MessageBoxA (NULL, ss.str().c_str(), "Invalid texture", MB_ICONERROR | MB_OK); return hr; } // BEGIN: Assignment 3.2.2 // TODO: Uncomment // Find the terrain file wss.str(L""); wss << g_TerrainPath; V(DXUTFindDXSDKMediaFileCch( path, MAX_PATH, wss.str().c_str())); if (hr != S_OK) { ss.str(); ss << "Could not find '" << g_TerrainPath << "'"; MessageBoxA (NULL, ss.str().c_str(), "Missing file", MB_ICONERROR | MB_OK); return hr; } // Open the terrain file FILE* file; error = _wfopen_s(&file, path, L"rb"); if (file == nullptr) { ss.str(); ss << "Could not open '" << g_TerrainPath << "'"; MessageBoxA (NULL, ss.str().c_str(), "File error", MB_ICONERROR | MB_OK); return E_FAIL; } // Read the terrain header { auto r = fread (&g_TerrainHeader, sizeof (g_TerrainHeader), 1, file); if (r != 1) { MessageBoxA (NULL, "Could not read the header.", "Invalid terrain file", MB_ICONERROR | MB_OK); return E_FAIL; } } // Check the magic number if (g_TerrainHeader.magicNumber != 0x00DA) { MessageBoxA (NULL, "The magic number is incorrect.", "Invalid terrain file header", MB_ICONERROR | MB_OK); return E_FAIL; } // Check the version if (g_TerrainHeader.version != 1) { MessageBoxA (NULL, "The header version is incorrect.", "Invalid terrain file header", MB_ICONERROR | MB_OK); return E_FAIL; } // Calculate the terrain resoultion from the height size g_TerrainResolution = (int)sqrt(g_TerrainHeader.heightSize / 2.0); // Assume a square terrain g_TerrainNumVertices = g_TerrainResolution * g_TerrainResolution; g_TerrainNumTriangles = 2 * (g_TerrainResolution - 1) * (g_TerrainResolution - 1) ; g_TerrainNumIndices = 6 * (g_TerrainResolution-1) * (g_TerrainResolution - 1); assert((g_TerrainHeader.heightSize / 2) == g_TerrainNumVertices); // Read the terrain heights std::vector terrainHeights; terrainHeights.resize(g_TerrainNumVertices); { if (g_TerrainHeader.heightSize != (int)::fread (&terrainHeights[0], sizeof(BYTE), g_TerrainHeader.heightSize, file)) { MessageBoxA(NULL, "Error while reading height data.", "Invalid terrain file", MB_ICONERROR | MB_OK); return E_FAIL; } } // Read the terrain color texture for diffuse lighting std::vector terrainDiffuseNtx; terrainDiffuseNtx.resize(g_TerrainHeader.colorSize); { const auto requestedSize = terrainDiffuseNtx.size(); if (requestedSize != fread (&terrainDiffuseNtx[0], sizeof(unsigned char), requestedSize, file)) { MessageBoxA (NULL, "Error while reading color data.", "Invalid terrain file", MB_ICONERROR | MB_OK); return E_FAIL; } } // Read the terrain normal texture std::vector terrainNormalNtx; terrainNormalNtx.resize(g_TerrainHeader.normalSize); { const auto requestedSize = terrainNormalNtx.size(); if (requestedSize != fread (&terrainNormalNtx[0], sizeof(unsigned char), requestedSize, file)) { MessageBoxA (NULL, "Error while reading normal data.", "Invalid terrain file", MB_ICONERROR | MB_OK); return E_FAIL; } } // BEGIN: Assignment 4.2.6 D3D11_SUBRESOURCE_DATA id; id.pSysMem = &terrainHeights[0]; id.SysMemPitch = sizeof(unsigned short); id.SysMemSlicePitch = 0; D3D11_BUFFER_DESC bd; bd.BindFlags = D3D11_BIND_SHADER_RESOURCE; bd.ByteWidth = g_TerrainNumVertices * id.SysMemPitch; bd.CPUAccessFlags = 0; bd.MiscFlags = 0; bd.Usage = D3D11_USAGE_DEFAULT; pd3dDevice->CreateBuffer(&bd, &id, &g_TerrainHeightBuf); D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; srvDesc.Format = DXGI_FORMAT_R16_UNORM; srvDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER; srvDesc.Buffer.FirstElement = 0; srvDesc.Buffer.NumElements = g_TerrainResolution * g_TerrainResolution; V_RETURN(pd3dDevice->CreateShaderResourceView(g_TerrainHeightBuf, &srvDesc, &g_TerrainHeightSRV)); // END: Assignment 4.2.6 fclose(file); // TODO: Create the terrain color texture D3D11_TEXTURE2D_DESC tex2DDesc; std::vector> textureData; std::vector subresourceData; bool sRgb; LoadNtx(terrainDiffuseNtx, &tex2DDesc, textureData, subresourceData, sRgb); pd3dDevice->CreateTexture2D( &tex2DDesc, &subresourceData[0], &g_TerrainDiffuseTex); D3D11_SHADER_RESOURCE_VIEW_DESC resourceDESC; resourceDESC.Texture2D; pd3dDevice->CreateShaderResourceView(g_TerrainDiffuseTex, NULL, &g_TerrainDiffuseSRV); // END: Assignment 3.2.5 // Normal Texture D3D11_TEXTURE2D_DESC tex2DDesc1; std::vector> textureData1; std::vector subresourceData1; bool sRgb1; LoadNtx(terrainNormalNtx, &tex2DDesc1, textureData1, subresourceData1, sRgb1); pd3dDevice->CreateTexture2D( &tex2DDesc1, &subresourceData1[0], &g_TerrainNormalTex); D3D11_SHADER_RESOURCE_VIEW_DESC resourceDESC1; resourceDESC1.Texture2D; pd3dDevice->CreateShaderResourceView(g_TerrainNormalTex, NULL, &g_TerrainNormalSRV); return S_OK; } //-------------------------------------------------------------------------------------- // Release D3D11 resources created in OnD3D11CreateDevice //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11DestroyDevice( void* pUserContext ) { g_DialogResourceManager.OnD3D11DestroyDevice(); g_SettingsDlg.OnD3D11DestroyDevice(); DXUTGetGlobalResourceCache().OnDestroyDevice(); SAFE_RELEASE( g_DebugSRV ); SAFE_RELEASE( g_TerrainHeightBuf ); SAFE_RELEASE( g_TerrainHeightSRV ); SAFE_RELEASE( g_TerrainNormalTex ); SAFE_RELEASE( g_TerrainNormalSRV ); // Assignment 3.2.4 // TODO: Release the index buffer // Assignment 3.2.5 // TODO: Release the terrain's shader resource view and texture SAFE_RELEASE( g_TerrainDiffuseSRV ); SAFE_RELEASE( g_TerrainDiffuseTex ); SAFE_DELETE( g_TxtHelper ); ReleaseShader(); } //-------------------------------------------------------------------------------------- // Create any D3D11 resources that depend on the back buffer //-------------------------------------------------------------------------------------- HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext ) { HRESULT hr; // Intialize the user interface V_RETURN( g_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) ); V_RETURN( g_SettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) ); g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 ); g_HUD.SetSize( 170, 170 ); g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 300 ); g_SampleUI.SetSize( 170, 300 ); // Initialize the camera g_CameraParams.m_Aspect = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height; g_CameraParams.m_Fovy = 0.785398; g_CameraParams.m_NearPlane = 1.f; g_CameraParams.m_FarPlane = 2000.f; g_Camera.SetProjParams(g_CameraParams.m_Fovy, g_CameraParams.m_Aspect, g_CameraParams.m_NearPlane, g_CameraParams.m_FarPlane); g_Camera.SetEnablePositionMovement(true); g_Camera.SetRotateButtons(true, false, false); g_Camera.SetScalers( g_CameraRotateScaler, g_CameraMoveScaler ); g_Camera.SetDrag( true ); return S_OK; } //-------------------------------------------------------------------------------------- // Release D3D11 resources created in OnD3D11ResizedSwapChain //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext ) { g_DialogResourceManager.OnD3D11ReleasingSwapChain(); } //-------------------------------------------------------------------------------------- // Loads the effect from file // and retrieves all dependent variables //-------------------------------------------------------------------------------------- HRESULT ReloadShader(ID3D11Device* pd3dDevice) { assert(pd3dDevice != NULL); HRESULT hr; ReleaseShader(); WCHAR path[MAX_PATH]; stringstream ss; wstringstream wss; // Find and load the rendering effect V_RETURN(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"game.fxo")); ifstream is(path, ios_base::binary); is.seekg(0, ios_base::end); streampos pos = is.tellg(); is.seekg(0, ios_base::beg); vector effectBuffer((unsigned int)pos); is.read(&effectBuffer[0], pos); is.close(); V_RETURN(D3DX11CreateEffectFromMemory((const void*)&effectBuffer[0], effectBuffer.size(), 0, pd3dDevice, &g_Effect)); assert(g_Effect->IsValid()); // Obtain the effect technique SAFE_GET_TECHNIQUE(g_Effect, "Render", g_Technique); // Obtain the effect pass SAFE_GET_PASS(g_Technique, "P0", g_Pass0); // Obtain the effect variables SAFE_GET_RESOURCE(g_Effect, "g_Diffuse", g_DiffuseEV); SAFE_GET_MATRIX(g_Effect, "g_World", g_WorldEV); SAFE_GET_MATRIX(g_Effect, "g_WorldViewProjection", g_WorldViewProjectionEV); SAFE_GET_VECTOR(g_Effect, "g_LightDir", g_LightDirEV); SAFE_GET_RESOURCE(g_Effect, "g_Height", g_HeightEV); SAFE_GET_RESOURCE(g_Effect, "g_Normal", g_NormalEV); SAFE_GET_SCALAR(g_Effect, "g_TerrainRes", g_TerrainResEV); SAFE_GET_SCALAR(g_Effect, "g_TerrainQuadRes", g_TerrainQuadResEV); return S_OK; } //-------------------------------------------------------------------------------------- // Release resources created in ReloadShader //-------------------------------------------------------------------------------------- void ReleaseShader() { SAFE_RELEASE( g_Effect ); } //-------------------------------------------------------------------------------------- // Handle messages to the application //-------------------------------------------------------------------------------------- LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing, void* pUserContext ) { // Pass messages to dialog resource manager calls so GUI state is updated correctly *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; // Pass messages to settings dialog if its active if( g_SettingsDlg.IsActive() ) { g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam ); return 0; } // Give the dialogs a chance to handle the message first *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam ); if( *pbNoFurtherProcessing ) return 0; // Use the mouse weel to control the movement speed if(uMsg == WM_MOUSEWHEEL) { int zDelta = GET_WHEEL_DELTA_WPARAM(wParam); g_CameraMoveScaler *= (1 + zDelta / 500.0f); if (g_CameraMoveScaler < 0.1f) g_CameraMoveScaler = 0.1f; g_Camera.SetScalers(g_CameraRotateScaler, g_CameraMoveScaler); } // Pass all remaining windows messages to camera so it can respond to user input g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam ); return 0; } //-------------------------------------------------------------------------------------- // Handle key presses //-------------------------------------------------------------------------------------- void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext ) { } //-------------------------------------------------------------------------------------- // Handles the GUI events //-------------------------------------------------------------------------------------- void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext ) { switch( nControlID ) { case IDC_TOGGLEFULLSCREEN: DXUTToggleFullScreen(); break; case IDC_TOGGLEREF: DXUTToggleREF(); break; case IDC_CHANGEDEVICE: g_SettingsDlg.SetActive( !g_SettingsDlg.IsActive() ); break; case IDC_TOGGLESPIN: g_TerrainSpinning = g_SampleUI.GetCheckBox( IDC_TOGGLESPIN )->GetChecked(); break; case IDC_RELOAD_SHADERS: ReloadShader(DXUTGetD3D11Device ()); break; } } //-------------------------------------------------------------------------------------- // Handle updates to the scene. This is called regardless of which D3D API is used //-------------------------------------------------------------------------------------- void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext ) { // Update the camera's position based on user input g_Camera.FrameMove( fElapsedTime ); D3DXMATRIX mTmp; // Initialize the terrain world matrix // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206365%28v=vs.85%29.aspx // Set origin to (0.5, 0.5, 0) D3DXMatrixTranslation(&g_TerrainWorld, -0.5f, -0.5f, 0.f); // Assume: x, y and z are in [0,1] // Scale to terrain extents D3DXMatrixScaling(&mTmp, g_TerrainWidth, g_TerrainDepth, g_TerrainHeight); g_TerrainWorld = g_TerrainWorld * mTmp; // Since "up" is z-axis in object space, but y-axis in world space, we rotate around the x-axis D3DXMatrixRotationX( &mTmp, DEG2RAD( -90.0f ) ); g_TerrainWorld *= mTmp; if( g_TerrainSpinning ) { D3DXMatrixRotationY( &mTmp, g_TerrainSpinSpeed * DEG2RAD((float)fTime) ); g_TerrainWorld *= mTmp; // Rotate around world-space "up" axis } g_LightDir = D3DXVECTOR4(1, 1, -1, 0); // Direction to the directional light in world space // Transform the light vector to terrain object space D3DXMATRIX invWorld; D3DXMatrixInverse(&invWorld, NULL, &g_TerrainWorld); D3DXVec4Transform(&g_LightDir, &g_LightDir, &invWorld); D3DXVec3Normalize((D3DXVECTOR3*)&g_LightDir, (D3DXVECTOR3*)&g_LightDir); // Normalize the light direction } //-------------------------------------------------------------------------------------- // Render the scene using the D3D11 device //-------------------------------------------------------------------------------------- void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime, float fElapsedTime, void* pUserContext ) { D3DXMATRIX inverseTerrainWorldDir; D3DXMatrixTranspose(&inverseTerrainWorldDir, &g_TerrainWorld); D3DXVECTOR4 lightDirObject; D3DXVec4Transform(&lightDirObject, &g_LightDir, &inverseTerrainWorldDir); D3DXVec3Normalize((D3DXVECTOR3*)&lightDirObject, (D3DXVECTOR3*)&lightDirObject); HRESULT hr; // If the settings dialog is being shown, then render it instead of rendering the app's scene if( g_SettingsDlg.IsActive() ) { g_SettingsDlg.OnRender( fElapsedTime ); return; } ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView(); pd3dImmediateContext->ClearRenderTargetView( pRTV, g_ClearColor ); if(g_Effect == NULL) { g_TxtHelper->Begin(); g_TxtHelper->SetInsertionPos( 5, 5 ); g_TxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) ); g_TxtHelper->DrawTextLine( L"SHADER ERROR" ); g_TxtHelper->End(); return; } // Clear the depth stencil ID3D11DepthStencilView* pDSV = DXUTGetD3D11DepthStencilView(); pd3dImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0, 0 ); // // Update variables that change once per frame // D3DXMATRIX const * view = g_Camera.GetViewMatrix(); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206342%28v=vs.85%29.aspx D3DXMATRIX const * proj = g_Camera.GetProjMatrix(); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb147302%28v=vs.85%29.aspx D3DXMATRIX worldViewProj = g_TerrainWorld * (*view) * (*proj); g_WorldEV->SetMatrix( ( float* )&g_TerrainWorld ); g_WorldViewProjectionEV->SetMatrix( ( float* )&worldViewProj ); g_LightDirEV->SetFloatVector( ( float* )&lightDirObject ); // Set input layout pd3dImmediateContext->IASetInputLayout( NULL ); // Bind the terrain vertex buffer to the input assembler stage ID3D11Buffer* vbs[] = { NULL, }; unsigned int strides[] = { 0, }, offsets[] = { 0, }; pd3dImmediateContext->IASetVertexBuffers(0, 1, vbs, strides, offsets); // Tell the input assembler stage which primitive topology to use pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); // Assignment 3.2.4 // TODO: Bind the terrain index buffer to the input assembler stage //pd3dImmediateContext->IASetIndexBuffer(g_TerrainIB, DXGI_FORMAT_R32_UINT, 0); // Assignment 3.2.5 // TODO: Bind the SRV of the terrain diffuse texture to the effect variable // (instead of the SRV of the debug texture) V(g_DiffuseEV->SetResource( g_TerrainDiffuseSRV)); V(g_HeightEV->SetResource( g_TerrainHeightSRV)); V(g_NormalEV->SetResource( g_TerrainNormalSRV)); // Apply the rendering pass in order to submit the necessary render state changes to the device g_Pass0->Apply(0, pd3dImmediateContext); // Draw // Assignment 3.2.6 // TODO: Use DrawIndexed to draw the terrain geometry using as shared vertex list // (instead of drawing only the vertex buffer) pd3dImmediateContext->Draw( 6 * (g_TerrainResolution - 1) * (g_TerrainResolution - 1), 0); DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" ); g_HUD.OnRender( fElapsedTime ); g_SampleUI.OnRender( fElapsedTime ); RenderText(); DXUT_EndPerfEvent(); static DWORD dwTimefirst = GetTickCount(); if ( GetTickCount() - dwTimefirst > 5000 ) { OutputDebugString( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) ); OutputDebugString( L"\n" ); dwTimefirst = GetTickCount(); } g_TerrainResEV->SetInt(-1); g_TerrainQuadResEV->SetInt(-1); }