Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on May 21st, 2012  |  syntax: C++  |  size: 35.34 KB  |  hits: 26  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. #include <windows.h>
  2. #include <d3d11.h>
  3. #include <d3dx11.h>
  4. #include <d3dcompiler.h>
  5. #include <xnamath.h>
  6. #include <vector>
  7. #include <iostream>
  8. #include <fstream>
  9. #include <sstream>
  10. #include <string>
  11. #include <cstdint>
  12. #include "resource.h"
  13.  
  14. #include "DXUT/Core/dxut.h"
  15. #include "DXUTmisc.h"
  16. #include "DXUTcamera.h"
  17. #include "DXUTgui.h"
  18. #include "DXUTsettingsDlg.h"
  19. #include "SDKmisc.h"
  20.  
  21. #include "Effects11/Inc/d3dx11effect.h"
  22.  
  23. #include "ntx/NTX.h"
  24.  
  25. #include "debug.h"
  26.  
  27. // Convenience macros for safe effect variable retrieval
  28. #define SAFE_GET_PASS(Technique, name, var)   {assert(Technique!=NULL); var = Technique->GetPassByName( name );                                         assert(var->IsValid());}
  29. #define SAFE_GET_TECHNIQUE(effect, name, var) {assert(effect!=NULL); var = effect->GetTechniqueByName( name );                                          assert(var->IsValid());}
  30. #define SAFE_GET_SCALAR(effect, name, var)    {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsScalar();                       assert(var->IsValid());}
  31. #define SAFE_GET_VECTOR(effect, name, var)    {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsVector();                       assert(var->IsValid());}
  32. #define SAFE_GET_MATRIX(effect, name, var)    {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsMatrix();                       assert(var->IsValid());}
  33. #define SAFE_GET_SAMPLER(effect, name, var)   {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsSampler();                      assert(var->IsValid());}
  34. #define SAFE_GET_RESOURCE(effect, name, var)  {assert(effect!=NULL); var = effect->GetVariableByName( name )->AsShaderResource();       assert(var->IsValid());}
  35.  
  36. // Help macros
  37. #define DEG2RAD( a ) ( (a) * D3DX_PI / 180.f )
  38.  
  39. using namespace std;
  40.  
  41. //--------------------------------------------------------------------------------------
  42. // Global variables
  43. //--------------------------------------------------------------------------------------
  44.  
  45. // Camera
  46. struct CAMERAPARAMS {
  47.         float   m_Fovy;
  48.         float   m_Aspect;
  49.         float   m_NearPlane;
  50.         float   m_FarPlane;
  51. }                                       g_CameraParams;
  52. float                                   g_CameraMoveScaler = 1000.f;
  53. float                                   g_CameraRotateScaler = 0.01f;
  54. CFirstPersonCamera                      g_Camera;               // A first person camera
  55.  
  56. // User Interface
  57. CDXUTDialogResourceManager              g_DialogResourceManager; // manager for shared resources of dialogs
  58. CD3DSettingsDlg                         g_SettingsDlg;          // Device settings dialog
  59. CDXUTTextHelper*                        g_TxtHelper = NULL;
  60. CDXUTDialog                             g_HUD;                  // dialog for standard controls
  61. CDXUTDialog                             g_SampleUI;             // dialog for sample specific controls
  62.  
  63. // A D3DX rendering effect
  64. ID3DX11Effect*                          g_Effect = NULL; // The whole rendering effect
  65. ID3DX11EffectTechnique*                 g_Technique = NULL; // One technique to render the effect
  66. ID3DX11EffectPass*                      g_Pass0 = NULL; // One rendering pass of the technique
  67. ID3DX11EffectMatrixVariable*            g_WorldEV = NULL; // World matrix effect variable
  68. ID3DX11EffectMatrixVariable*            g_WorldViewProjectionEV = NULL; // WorldViewProjection matrix effect variable
  69. ID3DX11EffectShaderResourceVariable*    g_DiffuseEV = NULL; // Effect variable for the diffuse color texture
  70. ID3DX11EffectVectorVariable*            g_LightDirEV = NULL; // Light direction in object space
  71.  
  72. // Background color
  73. D3DXVECTOR4                             g_ClearColor;
  74.  
  75. // Terrain meta information
  76. struct PtfHeader {
  77.         int16_t magicNumber;    // Must be 0x00DA
  78.         int16_t version;                // Must be 1
  79.         int32_t heightSize;         // Height data size
  80.         int32_t colorSize;          // Color data size
  81.         int32_t normalSize;         // Normal data size
  82. }                                       g_TerrainHeader;
  83. char                                    g_TerrainPath[MAX_PATH] = { '\0' };
  84. int                                     g_TerrainResolution;
  85. int                                     g_TerrainNumVertices = 3;
  86. int                                     g_TerrainNumTriangles = 1;
  87. float                                   g_TerrainWidth = 1000.0f;
  88. float                                   g_TerrainDepth = 1000.0f;
  89. float                                   g_TerrainHeight = 400.0f;
  90. bool                                    g_TerrainSpinning = true;
  91. float                                   g_TerrainSpinSpeed = 0.0f;
  92. D3DXMATRIX                              g_TerrainWorld; // object- to world-space transformation
  93.  
  94. // Terrain rendering resources
  95. ID3D11InputLayout*                      g_TerrainVertexLayout = NULL; // Describes the structure of the vertex buffer to the input assembler stage
  96. ID3D11Buffer*                           g_TerrainVB = NULL; // The terrain's vertices
  97. ID3D11Buffer*                           g_TerrainIB = NULL; // The terrain's triangulation
  98. ID3D11Texture2D*                        g_TerrainDiffuseTex = NULL; // The terrain's material color for diffuse lighting
  99. ID3D11ShaderResourceView*               g_TerrainDiffuseSRV = NULL; // Describes the structure of the diffuse texture to the shader stages
  100.  
  101. // Scene information
  102. D3DXVECTOR4                             g_LightDir;
  103.  
  104. // General meta data
  105. char                                    g_DebugTexPath[MAX_PATH] = { '\0' };
  106.  
  107. // General resources
  108. ID3D11ShaderResourceView*               g_DebugSRV = NULL;
  109.  
  110. //--------------------------------------------------------------------------------------
  111. // UI control IDs
  112. //--------------------------------------------------------------------------------------
  113. #define IDC_TOGGLEFULLSCREEN    1
  114. #define IDC_TOGGLEREF           2
  115. #define IDC_CHANGEDEVICE        3
  116. #define IDC_TOGGLESPIN          4
  117. #define IDC_RELOAD_SHADERS              101
  118.  
  119. //--------------------------------------------------------------------------------------
  120. // Forward declarations
  121. //--------------------------------------------------------------------------------------
  122. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
  123.         void* pUserContext );
  124. void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext );
  125. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext );
  126. void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext );
  127. bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext );
  128.  
  129. bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo,
  130.         DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext );
  131. HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice, const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc,
  132.         void* pUserContext );
  133. HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain,
  134.         const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext );
  135. void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext );
  136. void CALLBACK OnD3D11DestroyDevice( void* pUserContext );
  137. void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
  138.         float fElapsedTime, void* pUserContext );
  139.  
  140. void InitApp();
  141. void RenderText();
  142.  
  143. void ReleaseShader();
  144. HRESULT ReloadShader(ID3D11Device* pd3dDevice);
  145.  
  146. //--------------------------------------------------------------------------------------
  147. // Entry point to the program. Initializes everything and goes into a message processing
  148. // loop. Idle time is used to render the scene.
  149. //--------------------------------------------------------------------------------------
  150. int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
  151. {
  152.         // Enable run-time memory check for debug builds.
  153. #if defined(DEBUG) | defined(_DEBUG)
  154.         _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
  155. #endif
  156.  
  157.         // Old Direct3D Documentation:
  158.         // Start > All Programs > Microsoft DirectX SDK (June 2010) > Windows DirectX Graphics Documentation
  159.  
  160.         // DXUT Documentaion:
  161.         // Start > All Programs > Microsoft DirectX SDK (June 2010) > DirectX Documentation for C++ : The DirectX Software Development Kit > Programming Guide > DXUT
  162.  
  163.  
  164.         // New Direct3D Documentaion (just for reference, use old documentation to find explanations):
  165.         // http://msdn.microsoft.com/en-us/library/windows/desktop/hh309466%28v=vs.85%29.aspx
  166.  
  167.  
  168.  
  169.         // Set DXUT callbacks
  170.         DXUTSetCallbackMsgProc( MsgProc );
  171.         DXUTSetCallbackKeyboard( OnKeyboard );
  172.         DXUTSetCallbackFrameMove( OnFrameMove );
  173.         DXUTSetCallbackDeviceChanging( ModifyDeviceSettings );
  174.  
  175.         DXUTSetCallbackD3D11DeviceAcceptable( IsD3D11DeviceAcceptable );
  176.         DXUTSetCallbackD3D11DeviceCreated( OnD3D11CreateDevice );
  177.         DXUTSetCallbackD3D11SwapChainResized( OnD3D11ResizedSwapChain );
  178.         DXUTSetCallbackD3D11SwapChainReleasing( OnD3D11ReleasingSwapChain );
  179.         DXUTSetCallbackD3D11DeviceDestroyed( OnD3D11DestroyDevice );
  180.         DXUTSetCallbackD3D11FrameRender( OnD3D11FrameRender );
  181.  
  182.         InitApp();
  183.         DXUTInit( true, true, NULL ); // Parse the command line, show msgboxes on error, no extra command line params
  184.         DXUTSetCursorSettings( true, true );
  185.         DXUTCreateWindow( L"Terrain Viewer v0.0.1.33.7a" ); // You may change the title
  186.  
  187.         DXUTCreateDevice( D3D_FEATURE_LEVEL_10_0, true, 1280, 720 );
  188.  
  189.         DXUTMainLoop(); // Enter into the DXUT render loop
  190.  
  191.         return DXUTGetExitCode();
  192. }
  193.  
  194. //--------------------------------------------------------------------------------------
  195. // Initialize the app
  196. //--------------------------------------------------------------------------------------
  197. void InitApp()
  198. {
  199.         HRESULT hr;
  200.         WCHAR path[MAX_PATH];
  201.  
  202.         // Parse the config file
  203.  
  204.         V(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"game.cfg"));
  205.         ifstream stream(path);
  206.         if(!stream) {
  207.                 MessageBoxA (NULL, "Fatal Error: game.cfg not found.",
  208.                         "Missing file", MB_ICONERROR | MB_OK);
  209.                 return;
  210.         }
  211.  
  212.         std::string var;
  213.         while(!stream.eof())
  214.         {
  215.                 stream >> var;
  216.  
  217.                 if ( var.compare("DebugTexPath")   ==0 ) stream >> g_DebugTexPath;
  218.                 if ( var.compare("Spinning")       ==0 ) stream >> g_TerrainSpinning;
  219.                 if ( var.compare("SpinSpeed")      ==0 ) stream >> g_TerrainSpinSpeed;
  220.                 if ( var.compare("BackgroundColor")==0 ) stream >> g_ClearColor.x >> g_ClearColor.y >> g_ClearColor.z >> g_ClearColor.w;
  221.  
  222.                 // BEGIN: Assignment 3.2.1
  223.  
  224.                 // TODO: Parse the additional information in the config file into the variables:
  225.                 // g_TerrainPath, g_TerrainWidth, g_TerrainDepth and g_TerrainHeight
  226.                 // HINT: the operator '>>' converts the next word in 'stream' into the format of
  227.                 //       its right hand side and is really flexible
  228.                 if ( var.compare("TerrainPath")    ==0 ) stream >> g_TerrainPath;
  229.                 if ( var.compare("TerrainWidth")   ==0 ) stream >> g_TerrainWidth;
  230.                 if ( var.compare("TerrainDepth")   ==0 ) stream >> g_TerrainDepth;
  231.                 if ( var.compare("TerrainHeight")  ==0 ) stream >> g_TerrainHeight;
  232.  
  233.                 // END: Assignment 3.2.1
  234.         }
  235.  
  236.         stream.close();
  237.  
  238.         // Intialize the user interface
  239.  
  240.         g_SettingsDlg.Init( &g_DialogResourceManager );
  241.         g_HUD.Init( &g_DialogResourceManager );
  242.         g_SampleUI.Init( &g_DialogResourceManager );
  243.  
  244.         g_HUD.SetCallback( OnGUIEvent );
  245.         int iY = 30;
  246.         int iYo = 26;
  247.         g_HUD.AddButton( IDC_TOGGLEFULLSCREEN, L"Toggle full screen", 0, iY, 170, 22 );
  248.         g_HUD.AddButton( IDC_TOGGLEREF, L"Toggle REF (F3)", 0, iY += iYo, 170, 22, VK_F3 );
  249.         g_HUD.AddButton( IDC_CHANGEDEVICE, L"Change device (F2)", 0, iY += iYo, 170, 22, VK_F2 );
  250.  
  251.         g_HUD.AddButton (IDC_RELOAD_SHADERS, L"Reload shaders (F5)", 0, iY += 24, 170, 22, VK_F5);
  252.  
  253.         g_SampleUI.SetCallback( OnGUIEvent ); iY = 10;
  254.         iY += 24;
  255.         g_SampleUI.AddCheckBox( IDC_TOGGLESPIN, L"Toggle Spinning", 0, iY += 24, 125, 22, g_TerrainSpinning );  
  256. }
  257.  
  258.  
  259. //--------------------------------------------------------------------------------------
  260. // Render the help and statistics text. This function uses the ID3DXFont interface for
  261. // efficient text rendering.
  262. //--------------------------------------------------------------------------------------
  263. void RenderText()
  264. {
  265.         g_TxtHelper->Begin();
  266.         g_TxtHelper->SetInsertionPos( 5, 5 );
  267.         g_TxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  268.         g_TxtHelper->DrawTextLine( DXUTGetFrameStats(true)); //DXUTIsVsyncEnabled() ) );
  269.         g_TxtHelper->DrawTextLine( DXUTGetDeviceStats() );
  270.         g_TxtHelper->End();
  271. }
  272.  
  273.  
  274. //--------------------------------------------------------------------------------------
  275. // Reject any D3D11 devices that aren't acceptable by returning false
  276. //--------------------------------------------------------------------------------------
  277. bool CALLBACK IsD3D11DeviceAcceptable( const CD3D11EnumAdapterInfo *AdapterInfo, UINT Output, const CD3D11EnumDeviceInfo *DeviceInfo,
  278.         DXGI_FORMAT BackBufferFormat, bool bWindowed, void* pUserContext )
  279. {
  280.         return true;
  281. }
  282.  
  283.  
  284. //--------------------------------------------------------------------------------------
  285. // Specify the initial device settings
  286. //--------------------------------------------------------------------------------------
  287. bool CALLBACK ModifyDeviceSettings( DXUTDeviceSettings* pDeviceSettings, void* pUserContext )
  288. {
  289.         // For the first device created if its a REF device, optionally display a warning dialog box
  290.         static bool s_bFirstTime = true;
  291.         if( s_bFirstTime )
  292.         {
  293.                 s_bFirstTime = false;
  294.                 if( ( DXUT_D3D9_DEVICE == pDeviceSettings->ver && pDeviceSettings->d3d9.DeviceType == D3DDEVTYPE_REF ) ||
  295.                         ( DXUT_D3D11_DEVICE == pDeviceSettings->ver &&
  296.                         pDeviceSettings->d3d11.DriverType == D3D_DRIVER_TYPE_REFERENCE ) )
  297.                 {
  298.                         DXUTDisplaySwitchingToREFWarning( pDeviceSettings->ver );
  299.                 }
  300.  
  301.         }
  302.         //// Enable anti aliasing
  303.         //pDeviceSettings->d3d11.sd.SampleDesc.Count = 4;
  304.         //pDeviceSettings->d3d11.sd.SampleDesc.Quality = 1;
  305.  
  306.         return true;
  307. }
  308.  
  309.  
  310. //--------------------------------------------------------------------------------------
  311. // Create any D3D11 resources that aren't dependant on the back buffer
  312. //--------------------------------------------------------------------------------------
  313. HRESULT CALLBACK OnD3D11CreateDevice( ID3D11Device* pd3dDevice,
  314.         const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
  315. {
  316.         HRESULT hr;
  317.  
  318.         ID3D11DeviceContext* pd3dImmediateContext = DXUTGetD3D11DeviceContext(); // http://msdn.microsoft.com/en-us/library/ff476891%28v=vs.85%29
  319.         V_RETURN( g_DialogResourceManager.OnD3D11CreateDevice( pd3dDevice, pd3dImmediateContext ) );
  320.         V_RETURN( g_SettingsDlg.OnD3D11CreateDevice( pd3dDevice ) );
  321.         g_TxtHelper = new CDXUTTextHelper( pd3dDevice, pd3dImmediateContext, &g_DialogResourceManager, 15 );
  322.  
  323.         V_RETURN( ReloadShader(pd3dDevice) );
  324.  
  325.         errno_t error;
  326.         WCHAR path[MAX_PATH];
  327.         stringstream ss;
  328.         wstringstream wss;      
  329.  
  330.         // Initialize the camera
  331.         D3DXVECTOR3 Eye( 0.0f, 2 * g_TerrainHeight, -0.5f * g_TerrainDepth );
  332.         D3DXVECTOR3 At( 0.0f, 0.0f, 0.0f );
  333.         g_Camera.SetViewParams( &Eye, &At ); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206342%28v=vs.85%29.aspx
  334.         g_Camera.SetScalers( g_CameraRotateScaler, g_CameraMoveScaler );
  335.  
  336.         // Load the debug texture and create a shader resource view
  337.         wss.str(L""); wss << g_DebugTexPath;
  338.         V(DXUTFindDXSDKMediaFileCch( path, MAX_PATH, wss.str().c_str()));
  339.         if (hr != S_OK) {
  340.                 ss.str();
  341.                 ss << "Could not find '" << g_DebugTexPath << "'";
  342.                 MessageBoxA (NULL, ss.str().c_str(), "Missing file", MB_ICONERROR | MB_OK);
  343.                 return hr;
  344.         }
  345.         V(D3DX11CreateShaderResourceViewFromFile(pd3dDevice, path, NULL, NULL, &g_DebugSRV, &hr));
  346.         if (hr != S_OK) {
  347.                 ss.str();
  348.                 ss << "Could not load texture '" << g_DebugTexPath << "'";
  349.                 MessageBoxA (NULL, ss.str().c_str(), "Invalid texture", MB_ICONERROR | MB_OK);
  350.                 return hr;
  351.         }
  352.  
  353.         // Define the input layout
  354.         const D3D11_INPUT_ELEMENT_DESC layout[] = // http://msdn.microsoft.com/en-us/library/bb205117%28v=vs.85%29.aspx
  355.         {
  356.                 { "SV_POSITION",    0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  357.                 { "NORMAL",         0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  358.                 { "TEXCOORD",       0, DXGI_FORMAT_R32G32_FLOAT,       0, 32, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  359.         };
  360.         UINT numElements = sizeof( layout ) / sizeof( layout[0] );
  361.  
  362.         // Create the input layout
  363.         D3DX11_PASS_DESC pd;
  364.         V_RETURN(g_Pass0->GetDesc(&pd));
  365.         V_RETURN( pd3dDevice->CreateInputLayout( layout, numElements, pd.pIAInputSignature,
  366.                 pd.IAInputSignatureSize, &g_TerrainVertexLayout ) );
  367.  
  368.  
  369.         // BEGIN: Assignment 3.2.2
  370.  
  371.         // Find the terrain file
  372.         wss.str(L""); wss << g_TerrainPath;
  373.         V(DXUTFindDXSDKMediaFileCch( path, MAX_PATH, wss.str().c_str()));
  374.         if (hr != S_OK) {
  375.                 ss.str();
  376.                 ss << "Could not find '" << g_TerrainPath << "'";
  377.                 MessageBoxA (NULL, ss.str().c_str(), "Missing file", MB_ICONERROR | MB_OK);
  378.                 return hr;
  379.         }
  380.  
  381.         // Open the terrain file
  382.         FILE* file;
  383.         error = _wfopen_s(&file, path, L"rb");
  384.         if (file == nullptr) {
  385.                 ss.str();
  386.                 ss << "Could not open '" << g_TerrainPath << "'";
  387.                 MessageBoxA (NULL, ss.str().c_str(), "File error", MB_ICONERROR | MB_OK);
  388.                 return E_FAIL;
  389.         }
  390.  
  391.         // Read the terrain header
  392.         {
  393.                 auto r = fread (&g_TerrainHeader, sizeof (g_TerrainHeader), 1, file);
  394.                 if (r != 1) {
  395.                         MessageBoxA (NULL, "Could not read the header.",
  396.                                 "Invalid terrain file", MB_ICONERROR | MB_OK);
  397.                         return E_FAIL;
  398.                 }
  399.         }
  400.  
  401.         // Check the magic number
  402.         if (g_TerrainHeader.magicNumber != 0x00DA) {
  403.                 MessageBoxA (NULL, "The magic number is incorrect.",
  404.                         "Invalid terrain file header", MB_ICONERROR | MB_OK);
  405.                 return E_FAIL;
  406.         }
  407.  
  408.         // Check the version
  409.         if (g_TerrainHeader.version != 1) {
  410.                 MessageBoxA (NULL, "The header version is incorrect.",
  411.                         "Invalid terrain file header", MB_ICONERROR | MB_OK);
  412.                 return E_FAIL;
  413.         }
  414.  
  415.         // Calculate the terrain resoultion from the height size
  416.         g_TerrainResolution = (int)sqrt(g_TerrainHeader.heightSize / 2.0); // Assume a square terrain
  417.         g_TerrainNumVertices = g_TerrainResolution * g_TerrainResolution;
  418.         g_TerrainNumTriangles = 2 * (g_TerrainResolution - 1) * (g_TerrainResolution - 1) ;
  419.         assert((g_TerrainHeader.heightSize / 2) == g_TerrainNumVertices);
  420.  
  421.         // Read the terrain heights
  422.         std::vector<unsigned short> terrainHeights;
  423.         terrainHeights.resize(g_TerrainNumVertices);
  424.         {
  425.                 if (g_TerrainHeader.heightSize != (int)::fread (&terrainHeights[0], sizeof(BYTE), g_TerrainHeader.heightSize, file)) {
  426.                         MessageBoxA(NULL, "Error while reading height data.",
  427.                                 "Invalid terrain file", MB_ICONERROR | MB_OK);
  428.                         return E_FAIL;
  429.                 }    
  430.         }
  431.  
  432.         // Read the terrain color texture for diffuse lighting
  433.         std::vector<unsigned char> terrainDiffuseNtx;
  434.         terrainDiffuseNtx.resize(g_TerrainHeader.colorSize);
  435.         {
  436.                 const auto requestedSize = terrainDiffuseNtx.size();
  437.                 if (requestedSize != fread (&terrainDiffuseNtx[0], sizeof(unsigned char), requestedSize, file)) {
  438.                         MessageBoxA (NULL, "Error while reading color data.",
  439.                                 "Invalid terrain file", MB_ICONERROR | MB_OK);
  440.                         return E_FAIL;
  441.                 }    
  442.         }
  443.  
  444.         fclose(file);
  445.  
  446.         // END: Assignment 3.2.2
  447.  
  448.  
  449.         // Create the vertex buffer for the terrain
  450.  
  451.         std::vector<float> terrainVB;
  452.         terrainVB.resize(g_TerrainNumVertices * (4 + 4 + 2)); // Position / Normal / TexCoord
  453.  
  454.         // BEGIN: Assignment 3.2.3
  455.  
  456.         // Note:
  457.         //
  458.         // In the coordinate system of the packed terrain file (input):
  459.         // u = east,    v = south,    height = up      height in [0,65535] (unsigned short)
  460.         //
  461.         // In the coordinate system of the vertex buffer (output):
  462.         // x = east,    y = south,    z = up,          x,y,z in [0,1] (float)
  463.  
  464.         int iVB = 0; // You can use this variable as index into the vertex buffer ( terrainVB[iVB++] = ... )
  465.         float snx = (g_TerrainHeight * (g_TerrainResolution - 1)) / (g_TerrainWidth * 2.0f);
  466.         float sny = (g_TerrainHeight * (g_TerrainResolution - 1)) / (g_TerrainDepth * 2.0f);
  467.         for(int v = 0; v < g_TerrainResolution; v++) {
  468.                 for(int u = 0; u < g_TerrainResolution; u++) {
  469.                         // Retrieve the height
  470.                         float height = terrainHeights[u + v * g_TerrainResolution] / 65535.f; // [0, 1]
  471.  
  472.                         // Calculate the normal
  473.                         float heightL = terrainHeights[max(0, u - 1) + v * g_TerrainResolution] / 65535.f;
  474.                         float heightR = terrainHeights[min(g_TerrainResolution - 1, u + 1) + v * g_TerrainResolution] / 65535.f;
  475.                         float heightU = terrainHeights[u + max(0, v - 1) * g_TerrainResolution] / 65535.f;
  476.                         float heightD = terrainHeights[u + min(g_TerrainResolution - 1, v + 1) * g_TerrainResolution] / 65535.f;
  477.                         D3DXVECTOR3 n(snx * (heightL - heightR), sny * (heightU - heightD), 1.f);
  478.                         D3DXVec3Normalize(&n, &n);
  479.  
  480.                         // Write the position into the "terrainVB" vertex buffer contents (pos.x, pos.y, pos.z, 1)
  481.                         // Write the normal into the  "terrainVB" vertex buffer contents  (nor.x, nor.y, nor.z, 0)
  482.                         // Write the texture coordinates into the "terrainVB" vertex buffer contents (tex.u, tex.v)
  483.                         float tu = static_cast<float>(u / (g_TerrainResolution-1));
  484.                         float tv = static_cast<float>(v / (g_TerrainResolution-1));
  485.                         float px  = static_cast<float>(tu * g_TerrainResolution);
  486.                         float py  = static_cast<float>(tv * g_TerrainResolution);
  487.                         float pz  = static_cast<float>(g_TerrainResolution * height);
  488.  
  489.                         terrainVB[iVB++] = px;
  490.                         terrainVB[iVB++] = py;
  491.                         terrainVB[iVB++] = pz;
  492.                         terrainVB[iVB++] = 1.0f;
  493.                         terrainVB[iVB++] = n.x;
  494.                         terrainVB[iVB++] = n.y;
  495.                         terrainVB[iVB++] = n.z;
  496.                         terrainVB[iVB++] = 0.0f;
  497.                         terrainVB[iVB++] = tu;
  498.                         terrainVB[iVB++] = tv;
  499.                 }
  500.         }
  501.  
  502.         // END: Assignment 3.2.3
  503.  
  504.         D3D11_SUBRESOURCE_DATA id;
  505.         id.pSysMem = &terrainVB[0];
  506.         id.SysMemPitch = 10 * sizeof(float); // Stride
  507.         id.SysMemSlicePitch = 0;
  508.  
  509.         D3D11_BUFFER_DESC bd;
  510.         bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
  511.         bd.ByteWidth = g_TerrainNumVertices * id.SysMemPitch;
  512.         bd.CPUAccessFlags = 0;
  513.         bd.MiscFlags = 0;
  514.         bd.Usage = D3D11_USAGE_DEFAULT;
  515.  
  516.         pd3dDevice->CreateBuffer(&bd, &id, &g_TerrainVB); // http://msdn.microsoft.com/en-us/library/ff476899%28v=vs.85%29.aspx
  517.  
  518.         // BEGIN: Assignment 3.2.4
  519.  
  520.         // TODO: Create the terrain index buffer
  521.         std::vector<unsigned int> terrainIB;
  522.         terrainIB.resize((g_TerrainResolution-1)*(g_TerrainResolution-1) * 6);
  523.  
  524.         int iIB = 0;
  525.         for(int v = 0; v < g_TerrainResolution - 1; v++) {
  526.             for(int u = 0; u < g_TerrainResolution - 1; u++) {
  527.                 // TODO: Write the three indices for the first triangle into the "terrainIB" index buffer contents
  528.                         terrainIB[iIB++] = v + u * g_TerrainResolution;
  529.                         terrainIB[iIB++] = v + (u+1) * g_TerrainResolution;
  530.                         terrainIB[iIB++] = (v+1) + u * g_TerrainResolution;
  531.                 // TODO: Write the three indices for the second triangle into the "terrainIB" index buffer contents
  532.                         terrainIB[iIB++] = (v+1) + u * g_TerrainResolution;
  533.                         terrainIB[iIB++] = v + (u+1) * g_TerrainResolution;
  534.                         terrainIB[iIB++] = (v+1) + (u+1) * g_TerrainResolution;
  535.             }
  536.         }
  537.  
  538.         //define initial data
  539.         D3D11_SUBRESOURCE_DATA iid;
  540.         iid.pSysMem = &terrainIB[0];
  541.         iid.SysMemPitch = 6 * sizeof(unsigned int); // Stride
  542.         iid.SysMemSlicePitch = 0;
  543.         //create the index buffer and fill desc
  544.         D3D11_BUFFER_DESC ibd;
  545.         ::ZeroMemory(&ibd,sizeof(ibd));
  546.         ibd.Usage = D3D11_USAGE_DEFAULT;
  547.         ibd.ByteWidth = g_TerrainNumVertices * iid.SysMemPitch;
  548.         ibd.BindFlags = D3D10_BIND_INDEX_BUFFER;
  549.         ibd.CPUAccessFlags = 0;
  550.         ibd.MiscFlags = 0;
  551.         //define initial data
  552.  
  553.  
  554.         hr = pd3dDevice->CreateBuffer(&ibd,&iid,&g_TerrainIB);
  555.         if(FAILED(hr))
  556.                 return hr;
  557.  
  558.         // END: Assignment 3.2.4
  559.  
  560.         // BEGIN: Assignment 3.2.5
  561.  
  562.         // TODO: Create the terrain color texture
  563.  
  564.         D3D11_TEXTURE2D_DESC tex2DDesc;
  565.         std::vector<std::vector<unsigned char>> textureData;
  566.         std::vector<D3D11_SUBRESOURCE_DATA> subresourceData;
  567.         bool sRgb;
  568.         LoadNtx(terrainDiffuseNtx,&tex2DDesc,textureData,subresourceData,sRgb);
  569.         pd3dDevice->CreateTexture2D(&tex2DDesc,&subresourceData[0],&g_TerrainDiffuseTex);
  570.         pd3dDevice->CreateShaderResourceView(g_TerrainDiffuseTex,NULL,&g_TerrainDiffuseSRV);
  571.  
  572.  
  573.         // END: Assignment 3.2.5
  574.  
  575.         return S_OK;
  576. }
  577.  
  578.  
  579. //--------------------------------------------------------------------------------------
  580. // Release D3D11 resources created in OnD3D11CreateDevice
  581. //--------------------------------------------------------------------------------------
  582. void CALLBACK OnD3D11DestroyDevice( void* pUserContext )
  583. {
  584.         g_DialogResourceManager.OnD3D11DestroyDevice();
  585.         g_SettingsDlg.OnD3D11DestroyDevice();
  586.         DXUTGetGlobalResourceCache().OnDestroyDevice();
  587.         SAFE_RELEASE( g_DebugSRV );
  588.         SAFE_RELEASE( g_TerrainVertexLayout );
  589.         SAFE_RELEASE( g_TerrainVB );
  590.  
  591.         // Assignment 3.2.4
  592.         // Release the index buffer
  593.         SAFE_RELEASE( g_TerrainIB );
  594.         // Assignment 3.2.5
  595.         // Release the terrain's shader resource view and texture
  596.         SAFE_RELEASE( g_TerrainDiffuseSRV );
  597.         SAFE_RELEASE( g_TerrainDiffuseTex );
  598.  
  599.         SAFE_DELETE( g_TxtHelper );
  600.         ReleaseShader();
  601. }
  602.  
  603.  
  604. //--------------------------------------------------------------------------------------
  605. // Create any D3D11 resources that depend on the back buffer
  606. //--------------------------------------------------------------------------------------
  607. HRESULT CALLBACK OnD3D11ResizedSwapChain( ID3D11Device* pd3dDevice, IDXGISwapChain* pSwapChain,
  608.         const DXGI_SURFACE_DESC* pBackBufferSurfaceDesc, void* pUserContext )
  609. {
  610.         HRESULT hr;
  611.  
  612.         // Intialize the user interface
  613.  
  614.         V_RETURN( g_DialogResourceManager.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
  615.         V_RETURN( g_SettingsDlg.OnD3D11ResizedSwapChain( pd3dDevice, pBackBufferSurfaceDesc ) );
  616.  
  617.         g_HUD.SetLocation( pBackBufferSurfaceDesc->Width - 170, 0 );
  618.         g_HUD.SetSize( 170, 170 );
  619.         g_SampleUI.SetLocation( pBackBufferSurfaceDesc->Width - 170, pBackBufferSurfaceDesc->Height - 300 );
  620.         g_SampleUI.SetSize( 170, 300 );
  621.  
  622.         // Initialize the camera
  623.  
  624.         g_CameraParams.m_Aspect = pBackBufferSurfaceDesc->Width / ( FLOAT )pBackBufferSurfaceDesc->Height;
  625.         g_CameraParams.m_Fovy = 0.785398;
  626.         g_CameraParams.m_NearPlane = 1.f;
  627.         g_CameraParams.m_FarPlane = 2000.f;
  628.  
  629.         g_Camera.SetProjParams(g_CameraParams.m_Fovy, g_CameraParams.m_Aspect, g_CameraParams.m_NearPlane, g_CameraParams.m_FarPlane);
  630.         g_Camera.SetEnablePositionMovement(true);
  631.         g_Camera.SetRotateButtons(true, false, false);
  632.         g_Camera.SetScalers( g_CameraRotateScaler, g_CameraMoveScaler );
  633.         g_Camera.SetDrag( true );
  634.  
  635.         return S_OK;
  636. }
  637.  
  638.  
  639. //--------------------------------------------------------------------------------------
  640. // Release D3D11 resources created in OnD3D11ResizedSwapChain
  641. //--------------------------------------------------------------------------------------
  642. void CALLBACK OnD3D11ReleasingSwapChain( void* pUserContext )
  643. {
  644.         g_DialogResourceManager.OnD3D11ReleasingSwapChain();
  645. }
  646.  
  647.  
  648. //--------------------------------------------------------------------------------------
  649. // Loads the effect from file
  650. // and retrieves all dependent variables
  651. //--------------------------------------------------------------------------------------
  652. HRESULT ReloadShader(ID3D11Device* pd3dDevice)
  653. {
  654.         assert(pd3dDevice != NULL);
  655.  
  656.         HRESULT hr;
  657.  
  658.         ReleaseShader();
  659.  
  660.         WCHAR path[MAX_PATH];
  661.         stringstream ss;
  662.         wstringstream wss;
  663.  
  664.         // Find and load the rendering effect
  665.         V_RETURN(DXUTFindDXSDKMediaFileCch(path, MAX_PATH, L"game.fxo"));
  666.         ifstream is(path, ios_base::binary);
  667.         is.seekg(0, ios_base::end);
  668.         streampos pos = is.tellg();
  669.         is.seekg(0, ios_base::beg);
  670.         vector<char> effectBuffer((unsigned int)pos);
  671.         is.read(&effectBuffer[0], pos);
  672.         is.close();
  673.         V_RETURN(D3DX11CreateEffectFromMemory((const void*)&effectBuffer[0], effectBuffer.size(), 0, pd3dDevice, &g_Effect));    
  674.         assert(g_Effect->IsValid());
  675.  
  676.         // Obtain the effect technique
  677.         SAFE_GET_TECHNIQUE(g_Effect, "Render", g_Technique);
  678.  
  679.         // Obtain the effect pass
  680.         SAFE_GET_PASS(g_Technique, "P0", g_Pass0);
  681.  
  682.         // Obtain the effect variables
  683.         SAFE_GET_RESOURCE(g_Effect, "g_Diffuse", g_DiffuseEV);
  684.         SAFE_GET_MATRIX(g_Effect, "g_World", g_WorldEV);
  685.         SAFE_GET_MATRIX(g_Effect, "g_WorldViewProjection", g_WorldViewProjectionEV);  
  686.         SAFE_GET_VECTOR(g_Effect, "g_LightDir", g_LightDirEV);  
  687.  
  688.         return S_OK;
  689. }
  690.  
  691.  
  692. //--------------------------------------------------------------------------------------
  693. // Release resources created in ReloadShader
  694. //--------------------------------------------------------------------------------------
  695. void ReleaseShader()
  696. {
  697.         SAFE_RELEASE( g_Effect );
  698. }
  699.  
  700. //--------------------------------------------------------------------------------------
  701. // Handle messages to the application
  702. //--------------------------------------------------------------------------------------
  703. LRESULT CALLBACK MsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, bool* pbNoFurtherProcessing,
  704.         void* pUserContext )
  705. {
  706.         // Pass messages to dialog resource manager calls so GUI state is updated correctly
  707.         *pbNoFurtherProcessing = g_DialogResourceManager.MsgProc( hWnd, uMsg, wParam, lParam );
  708.         if( *pbNoFurtherProcessing )
  709.                 return 0;
  710.  
  711.         // Pass messages to settings dialog if its active
  712.         if( g_SettingsDlg.IsActive() )
  713.         {
  714.                 g_SettingsDlg.MsgProc( hWnd, uMsg, wParam, lParam );
  715.                 return 0;
  716.         }
  717.  
  718.         // Give the dialogs a chance to handle the message first
  719.         *pbNoFurtherProcessing = g_HUD.MsgProc( hWnd, uMsg, wParam, lParam );
  720.         if( *pbNoFurtherProcessing )
  721.                 return 0;
  722.         *pbNoFurtherProcessing = g_SampleUI.MsgProc( hWnd, uMsg, wParam, lParam );
  723.         if( *pbNoFurtherProcessing )
  724.                 return 0;
  725.  
  726.         // Use the mouse weel to control the movement speed
  727.         if(uMsg == WM_MOUSEWHEEL) {
  728.                 int zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
  729.                 g_CameraMoveScaler *= (1 + zDelta / 500.0f);
  730.                 if (g_CameraMoveScaler < 0.1f)
  731.                         g_CameraMoveScaler = 0.1f;
  732.                 g_Camera.SetScalers(g_CameraRotateScaler, g_CameraMoveScaler);
  733.         }
  734.  
  735.         // Pass all remaining windows messages to camera so it can respond to user input
  736.         g_Camera.HandleMessages( hWnd, uMsg, wParam, lParam );
  737.  
  738.         return 0;
  739. }
  740.  
  741.  
  742. //--------------------------------------------------------------------------------------
  743. // Handle key presses
  744. //--------------------------------------------------------------------------------------
  745. void CALLBACK OnKeyboard( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
  746. {
  747. }
  748.  
  749.  
  750. //--------------------------------------------------------------------------------------
  751. // Handles the GUI events
  752. //--------------------------------------------------------------------------------------
  753. void CALLBACK OnGUIEvent( UINT nEvent, int nControlID, CDXUTControl* pControl, void* pUserContext )
  754. {
  755.         switch( nControlID )
  756.         {
  757.         case IDC_TOGGLEFULLSCREEN:
  758.                 DXUTToggleFullScreen(); break;
  759.         case IDC_TOGGLEREF:
  760.                 DXUTToggleREF(); break;
  761.         case IDC_CHANGEDEVICE:
  762.                 g_SettingsDlg.SetActive( !g_SettingsDlg.IsActive() ); break;
  763.         case IDC_TOGGLESPIN:
  764.                 g_TerrainSpinning = g_SampleUI.GetCheckBox( IDC_TOGGLESPIN )->GetChecked();
  765.                 break;
  766.         case IDC_RELOAD_SHADERS:
  767.                 ReloadShader(DXUTGetD3D11Device ());
  768.                 break;
  769.         }
  770. }
  771.  
  772.  
  773. //--------------------------------------------------------------------------------------
  774. // Handle updates to the scene.  This is called regardless of which D3D API is used
  775. //--------------------------------------------------------------------------------------
  776. void CALLBACK OnFrameMove( double fTime, float fElapsedTime, void* pUserContext )
  777. {
  778.         // Update the camera's position based on user input
  779.         g_Camera.FrameMove( fElapsedTime );
  780.  
  781.         D3DXMATRIX mTmp;
  782.  
  783.         // Initialize the terrain world matrix
  784.         // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206365%28v=vs.85%29.aspx
  785.  
  786.         // Set origin to (0.5, 0.5, 0)
  787.         D3DXMatrixTranslation(&g_TerrainWorld, -0.5f, -0.5f, 0.f); // Assume: x, y and z are in [0,1]
  788.  
  789.         // Scale to terrain extents
  790.         D3DXMatrixScaling(&mTmp, g_TerrainWidth, g_TerrainDepth, g_TerrainHeight);
  791.         g_TerrainWorld = g_TerrainWorld * mTmp;
  792.  
  793.         // Since "up" is z-axis in object space, but y-axis in world space, we rotate around the x-axis
  794.         D3DXMatrixRotationX( &mTmp, DEG2RAD( -90.0f ) );
  795.         g_TerrainWorld *= mTmp;
  796.  
  797.         if( g_TerrainSpinning ) {
  798.                 D3DXMatrixRotationY( &mTmp, g_TerrainSpinSpeed * DEG2RAD((float)fTime) );
  799.                 g_TerrainWorld *= mTmp; // Rotate around world-space "up" axis
  800.         }
  801.  
  802.         g_LightDir = D3DXVECTOR4(1, 1, 1, 0); // Direction to the directional light in world space    
  803.  
  804.         // Transform the light vector to terrain object space
  805.         D3DXMATRIX invWorld;
  806.         D3DXMatrixInverse(&invWorld, NULL, &g_TerrainWorld);
  807.         D3DXVec4Transform(&g_LightDir, &g_LightDir, &invWorld);
  808.  
  809.         D3DXVec3Normalize((D3DXVECTOR3*)&g_LightDir, (D3DXVECTOR3*)&g_LightDir); // Normalize the light direction
  810. }
  811.  
  812.  
  813. //--------------------------------------------------------------------------------------
  814. // Render the scene using the D3D11 device
  815. //--------------------------------------------------------------------------------------
  816. void CALLBACK OnD3D11FrameRender( ID3D11Device* pd3dDevice, ID3D11DeviceContext* pd3dImmediateContext, double fTime,
  817.         float fElapsedTime, void* pUserContext )
  818. {
  819.         HRESULT hr;
  820.  
  821.         // If the settings dialog is being shown, then render it instead of rendering the app's scene
  822.         if( g_SettingsDlg.IsActive() )
  823.         {
  824.                 g_SettingsDlg.OnRender( fElapsedTime );
  825.                 return;
  826.         }    
  827.  
  828.         ID3D11RenderTargetView* pRTV = DXUTGetD3D11RenderTargetView();
  829.         pd3dImmediateContext->ClearRenderTargetView( pRTV, g_ClearColor );
  830.  
  831.         if(g_Effect == NULL) {
  832.                 g_TxtHelper->Begin();
  833.                 g_TxtHelper->SetInsertionPos( 5, 5 );
  834.                 g_TxtHelper->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 0.0f, 1.0f ) );
  835.                 g_TxtHelper->DrawTextLine( L"SHADER ERROR" );
  836.                 g_TxtHelper->End();
  837.                 return;
  838.         }
  839.  
  840.         // Clear the depth stencil
  841.         ID3D11DepthStencilView* pDSV = DXUTGetD3D11DepthStencilView();
  842.         pd3dImmediateContext->ClearDepthStencilView( pDSV, D3D11_CLEAR_DEPTH, 1.0, 0 );
  843.  
  844.         //
  845.         // Update variables that change once per frame
  846.         //
  847.         D3DXMATRIX const * view = g_Camera.GetViewMatrix(); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb206342%28v=vs.85%29.aspx
  848.         D3DXMATRIX const * proj = g_Camera.GetProjMatrix(); // http://msdn.microsoft.com/en-us/library/windows/desktop/bb147302%28v=vs.85%29.aspx
  849.         D3DXMATRIX worldViewProj = g_TerrainWorld * (*view) * (*proj);
  850.         g_WorldEV->SetMatrix( ( float* )&g_TerrainWorld );
  851.         g_WorldViewProjectionEV->SetMatrix( ( float* )&worldViewProj );
  852.         g_LightDirEV->SetFloatVector( ( float* )&g_LightDir );
  853.  
  854.         // Set input layout
  855.         pd3dImmediateContext->IASetInputLayout( g_TerrainVertexLayout );
  856.  
  857.         // Bind the terrain vertex buffer to the input assembler stage
  858.         ID3D11Buffer* vbs[] = { g_TerrainVB, };
  859.         unsigned int strides[] = { 10 * sizeof(float), }, offsets[] = { 0, };
  860.         pd3dImmediateContext->IASetVertexBuffers(0, 1, vbs, strides, offsets);
  861.  
  862.         // Tell the input assembler stage which primitive topology to use
  863.         pd3dImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  864.  
  865.         // Assignment 3.2.4
  866.         // Bind the terrain index buffer to the input assembler stage
  867.         pd3dImmediateContext->IASetIndexBuffer(g_TerrainIB,DXGI_FORMAT_R32_UINT,0);
  868.  
  869.         // Assignment 3.2.5
  870.         // Bind the SRV of the terrain diffuse texture to the effect variable
  871.         // (instead of the SRV of the debug texture)
  872.         V(g_DiffuseEV->SetResource( g_TerrainDiffuseSRV));
  873.  
  874.         // Apply the rendering pass in order to submit the necessary render state changes to the device
  875.         g_Pass0->Apply(0, pd3dImmediateContext);
  876.  
  877.         // Draw
  878.  
  879.         // Assignment 3.2.6
  880.         // TODO: Use DrawIndexed to draw the terrain geometry using as shared vertex list
  881.         // (instead of drawing only the vertex buffer)
  882.         pd3dImmediateContext->DrawIndexed(g_TerrainNumTriangles*3,0,0);
  883.  
  884.         DXUT_BeginPerfEvent( DXUT_PERFEVENTCOLOR, L"HUD / Stats" );
  885.         g_HUD.OnRender( fElapsedTime );
  886.         g_SampleUI.OnRender( fElapsedTime );
  887.         RenderText();
  888.         DXUT_EndPerfEvent();
  889.  
  890.         static DWORD dwTimefirst = GetTickCount();
  891.         if ( GetTickCount() - dwTimefirst > 5000 )
  892.         {    
  893.                 OutputDebugString( DXUTGetFrameStats( DXUTIsVsyncEnabled() ) );
  894.                 OutputDebugString( L"\n" );
  895.                 dwTimefirst = GetTickCount();
  896.         }
  897. }