main.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. // ---------------------------------------------------------------------------
  2. // Simple Assimp Directx11 Sample
  3. // This is a very basic sample and only reads diffuse texture
  4. // but this can load both embedded textures in fbx and non-embedded textures
  5. //
  6. //
  7. // Replace ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx") this with your
  8. // model name (line 480)
  9. // If your model isn't a fbx with embedded textures make sure your model's
  10. // textures are in same directory as your model
  11. //
  12. //
  13. // Written by IAS. :)
  14. // ---------------------------------------------------------------------------
  15. #include <Windows.h>
  16. #include <windowsx.h>
  17. #include <d3d11_1.h>
  18. #include <dxgi1_2.h>
  19. #include <DirectXMath.h>
  20. #include <d3dcompiler.h>
  21. #include "ModelLoader.h"
  22. #pragma comment (lib, "d3d11.lib")
  23. #pragma comment (lib, "Dxgi.lib")
  24. #pragma comment(lib,"d3dcompiler.lib")
  25. #pragma comment (lib, "dxguid.lib")
  26. using namespace DirectX;
  27. // ------------------------------------------------------------
  28. // Structs
  29. // ------------------------------------------------------------
  30. struct ConstantBuffer {
  31. XMMATRIX mWorld;
  32. XMMATRIX mView;
  33. XMMATRIX mProjection;
  34. };
  35. // ------------------------------------------------------------
  36. // Window Variables
  37. // ------------------------------------------------------------
  38. #define SCREEN_WIDTH 800
  39. #define SCREEN_HEIGHT 600
  40. const char g_szClassName[] = "directxWindowClass";
  41. UINT width, height;
  42. HWND hwnd;
  43. // ------------------------------------------------------------
  44. // DirectX Variables
  45. // ------------------------------------------------------------
  46. D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
  47. D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
  48. ID3D11Device *dev;
  49. ID3D11Device1 *dev1;
  50. ID3D11DeviceContext *devcon;
  51. ID3D11DeviceContext1 *devcon1;
  52. IDXGISwapChain *swapchain;
  53. IDXGISwapChain1 *swapchain1;
  54. ID3D11RenderTargetView *backbuffer;
  55. ID3D11VertexShader *pVS;
  56. ID3D11PixelShader *pPS;
  57. ID3D11InputLayout *pLayout;
  58. ID3D11Buffer *pConstantBuffer;
  59. ID3D11Texture2D *g_pDepthStencil;
  60. ID3D11DepthStencilView *g_pDepthStencilView;
  61. ID3D11SamplerState *TexSamplerState;
  62. XMMATRIX m_World;
  63. XMMATRIX m_View;
  64. XMMATRIX m_Projection;
  65. // ------------------------------------------------------------
  66. // Function identifiers
  67. // ------------------------------------------------------------
  68. void InitD3D(HINSTANCE hinstance, HWND hWnd);
  69. void CleanD3D(void);
  70. void RenderFrame(void);
  71. void InitPipeline();
  72. void InitGraphics();
  73. HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob);
  74. void Throwanerror(LPCSTR errormessage);
  75. // ------------------------------------------------------------
  76. // Our Model
  77. // ------------------------------------------------------------
  78. ModelLoader *ourModel;
  79. LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  80. {
  81. switch (msg)
  82. {
  83. case WM_CLOSE:
  84. DestroyWindow(hwnd);
  85. break;
  86. case WM_DESTROY:
  87. PostQuitMessage(0);
  88. break;
  89. default:
  90. return DefWindowProc(hwnd, msg, wParam, lParam);
  91. }
  92. return 0;
  93. }
  94. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
  95. LPSTR lpCmdLine, int nCmdShow)
  96. {
  97. WNDCLASSEX wc;
  98. MSG msg;
  99. wc.cbSize = sizeof(WNDCLASSEX);
  100. wc.style = 0;
  101. wc.lpfnWndProc = WndProc;
  102. wc.cbClsExtra = 0;
  103. wc.cbWndExtra = 0;
  104. wc.hInstance = hInstance;
  105. wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  106. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  107. wc.hbrBackground = NULL;
  108. wc.lpszMenuName = NULL;
  109. wc.lpszClassName = g_szClassName;
  110. wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
  111. if (!RegisterClassEx(&wc))
  112. {
  113. MessageBox(NULL, "Window Registration Failed!", "Error!",
  114. MB_ICONEXCLAMATION | MB_OK);
  115. return 0;
  116. }
  117. RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
  118. AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
  119. hwnd = CreateWindowEx(
  120. WS_EX_CLIENTEDGE,
  121. g_szClassName,
  122. " Simple Textured Directx11 Sample ",
  123. WS_OVERLAPPEDWINDOW,
  124. CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
  125. NULL, NULL, hInstance, NULL
  126. );
  127. if (hwnd == NULL)
  128. {
  129. MessageBox(NULL, "Window Creation Failed!", "Error!",
  130. MB_ICONEXCLAMATION | MB_OK);
  131. return 0;
  132. }
  133. ShowWindow(hwnd, nCmdShow);
  134. UpdateWindow(hwnd);
  135. width = wr.right - wr.left;
  136. height = wr.bottom - wr.top;
  137. InitD3D(hInstance, hwnd);
  138. while (true)
  139. {
  140. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  141. {
  142. TranslateMessage(&msg);
  143. DispatchMessage(&msg);
  144. if (msg.message == WM_QUIT)
  145. break;
  146. }
  147. RenderFrame();
  148. }
  149. CleanD3D();
  150. return msg.wParam;
  151. }
  152. void InitD3D(HINSTANCE hinstance, HWND hWnd)
  153. {
  154. HRESULT hr;
  155. UINT createDeviceFlags = 0;
  156. #ifdef _DEBUG
  157. createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
  158. #endif
  159. D3D_DRIVER_TYPE driverTypes[] =
  160. {
  161. D3D_DRIVER_TYPE_HARDWARE,
  162. D3D_DRIVER_TYPE_WARP,
  163. D3D_DRIVER_TYPE_REFERENCE,
  164. };
  165. UINT numDriverTypes = ARRAYSIZE(driverTypes);
  166. D3D_FEATURE_LEVEL featureLevels[] =
  167. {
  168. D3D_FEATURE_LEVEL_11_1,
  169. D3D_FEATURE_LEVEL_11_0,
  170. D3D_FEATURE_LEVEL_10_1,
  171. D3D_FEATURE_LEVEL_10_0,
  172. };
  173. UINT numFeatureLevels = ARRAYSIZE(featureLevels);
  174. for (UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++)
  175. {
  176. g_driverType = driverTypes[driverTypeIndex];
  177. hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, featureLevels, numFeatureLevels,
  178. D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
  179. if (hr == E_INVALIDARG)
  180. {
  181. // DirectX 11.0 platforms will not recognize D3D_FEATURE_LEVEL_11_1 so we need to retry without it
  182. hr = D3D11CreateDevice(nullptr, g_driverType, nullptr, createDeviceFlags, &featureLevels[1], numFeatureLevels - 1,
  183. D3D11_SDK_VERSION, &dev, &g_featureLevel, &devcon);
  184. }
  185. if (SUCCEEDED(hr))
  186. break;
  187. }
  188. if (FAILED(hr))
  189. Throwanerror("Directx Device Creation Failed!");
  190. UINT m4xMsaaQuality;
  191. dev->CheckMultisampleQualityLevels(
  192. DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
  193. // Obtain DXGI factory from device (since we used nullptr for pAdapter above)
  194. IDXGIFactory1* dxgiFactory = nullptr;
  195. {
  196. IDXGIDevice* dxgiDevice = nullptr;
  197. hr = dev->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
  198. if (SUCCEEDED(hr))
  199. {
  200. IDXGIAdapter* adapter = nullptr;
  201. hr = dxgiDevice->GetAdapter(&adapter);
  202. if (SUCCEEDED(hr))
  203. {
  204. hr = adapter->GetParent(__uuidof(IDXGIFactory1), reinterpret_cast<void**>(&dxgiFactory));
  205. adapter->Release();
  206. }
  207. dxgiDevice->Release();
  208. }
  209. }
  210. if (FAILED(hr))
  211. Throwanerror("DXGI Factory couldn't be obtained!");
  212. // Create swap chain
  213. IDXGIFactory2* dxgiFactory2 = nullptr;
  214. hr = dxgiFactory->QueryInterface(__uuidof(IDXGIFactory2), reinterpret_cast<void**>(&dxgiFactory2));
  215. if (dxgiFactory2)
  216. {
  217. // DirectX 11.1 or later
  218. hr = dev->QueryInterface(__uuidof(ID3D11Device1), reinterpret_cast<void**>(&dev1));
  219. if (SUCCEEDED(hr))
  220. {
  221. (void)devcon->QueryInterface(__uuidof(ID3D11DeviceContext1), reinterpret_cast<void**>(&devcon1));
  222. }
  223. DXGI_SWAP_CHAIN_DESC1 sd;
  224. ZeroMemory(&sd, sizeof(sd));
  225. sd.Width = SCREEN_WIDTH;
  226. sd.Height = SCREEN_HEIGHT;
  227. sd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  228. sd.SampleDesc.Count = 4;
  229. sd.SampleDesc.Quality = m4xMsaaQuality - 1;
  230. sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  231. sd.BufferCount = 1;
  232. hr = dxgiFactory2->CreateSwapChainForHwnd(dev, hWnd, &sd, nullptr, nullptr, &swapchain1);
  233. if (SUCCEEDED(hr))
  234. {
  235. hr = swapchain1->QueryInterface(__uuidof(IDXGISwapChain), reinterpret_cast<void**>(&swapchain));
  236. }
  237. dxgiFactory2->Release();
  238. }
  239. else
  240. {
  241. // DirectX 11.0 systems
  242. DXGI_SWAP_CHAIN_DESC sd;
  243. ZeroMemory(&sd, sizeof(sd));
  244. sd.BufferCount = 1;
  245. sd.BufferDesc.Width = SCREEN_WIDTH;
  246. sd.BufferDesc.Height = SCREEN_HEIGHT;
  247. sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  248. sd.BufferDesc.RefreshRate.Numerator = 60;
  249. sd.BufferDesc.RefreshRate.Denominator = 1;
  250. sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
  251. sd.OutputWindow = hWnd;
  252. sd.SampleDesc.Count = 1;
  253. sd.SampleDesc.Quality = m4xMsaaQuality - 1;
  254. sd.Windowed = TRUE;
  255. hr = dxgiFactory->CreateSwapChain(dev, &sd, &swapchain);
  256. }
  257. // Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
  258. dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
  259. dxgiFactory->Release();
  260. if (FAILED(hr))
  261. Throwanerror("Swapchain Creation Failed!");
  262. ID3D11Texture2D *pBackBuffer;
  263. swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
  264. dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
  265. pBackBuffer->Release();
  266. D3D11_TEXTURE2D_DESC descDepth;
  267. ZeroMemory(&descDepth, sizeof(descDepth));
  268. descDepth.Width = SCREEN_WIDTH;
  269. descDepth.Height = SCREEN_HEIGHT;
  270. descDepth.MipLevels = 1;
  271. descDepth.ArraySize = 1;
  272. descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
  273. descDepth.SampleDesc.Count = 4;
  274. descDepth.SampleDesc.Quality = m4xMsaaQuality - 1;
  275. descDepth.Usage = D3D11_USAGE_DEFAULT;
  276. descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
  277. descDepth.CPUAccessFlags = 0;
  278. descDepth.MiscFlags = 0;
  279. hr = dev->CreateTexture2D(&descDepth, nullptr, &g_pDepthStencil);
  280. if (FAILED(hr))
  281. Throwanerror("Depth Stencil Texture couldn't be created!");
  282. // Create the depth stencil view
  283. D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
  284. ZeroMemory(&descDSV, sizeof(descDSV));
  285. descDSV.Format = descDepth.Format;
  286. descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
  287. descDSV.Texture2D.MipSlice = 0;
  288. hr = dev->CreateDepthStencilView(g_pDepthStencil, 0, &g_pDepthStencilView);
  289. if (FAILED(hr))
  290. {
  291. Throwanerror("Depth Stencil View couldn't be created!");
  292. }
  293. devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
  294. D3D11_RASTERIZER_DESC rasterDesc;
  295. ID3D11RasterizerState *rasterState;
  296. rasterDesc.AntialiasedLineEnable = false;
  297. rasterDesc.CullMode = D3D11_CULL_BACK;
  298. rasterDesc.DepthBias = 0;
  299. rasterDesc.DepthBiasClamp = 0.0f;
  300. rasterDesc.DepthClipEnable = true;
  301. rasterDesc.FillMode = D3D11_FILL_SOLID;
  302. rasterDesc.FrontCounterClockwise = false;
  303. rasterDesc.MultisampleEnable = false;
  304. rasterDesc.ScissorEnable = false;
  305. rasterDesc.SlopeScaledDepthBias = 0.0f;
  306. dev->CreateRasterizerState(&rasterDesc, &rasterState);
  307. devcon->RSSetState(rasterState);
  308. D3D11_VIEWPORT viewport;
  309. ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
  310. viewport.TopLeftX = 0;
  311. viewport.TopLeftY = 0;
  312. viewport.MinDepth = 0.0f;
  313. viewport.MaxDepth = 1.0f;
  314. viewport.Width = SCREEN_WIDTH;
  315. viewport.Height = SCREEN_HEIGHT;
  316. devcon->RSSetViewports(1, &viewport);
  317. InitPipeline();
  318. InitGraphics();
  319. }
  320. void CleanD3D(void)
  321. {
  322. swapchain->SetFullscreenState(FALSE, NULL);
  323. ourModel->Close();
  324. g_pDepthStencil->Release();
  325. g_pDepthStencilView->Release();
  326. pLayout->Release();
  327. pVS->Release();
  328. pPS->Release();
  329. pConstantBuffer->Release();
  330. swapchain->Release();
  331. backbuffer->Release();
  332. dev->Release();
  333. devcon->Release();
  334. }
  335. void RenderFrame(void)
  336. {
  337. static float t = 0.0f;
  338. static ULONGLONG timeStart = 0;
  339. ULONGLONG timeCur = GetTickCount64();
  340. if (timeStart == 0)
  341. timeStart = timeCur;
  342. t = (timeCur - timeStart) / 1000.0f;
  343. float clearColor[4] = { 0.0f, 0.2f, 0.4f, 1.0f };
  344. devcon->ClearRenderTargetView(backbuffer, clearColor);
  345. devcon->ClearDepthStencilView(g_pDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
  346. devcon->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
  347. m_World = XMMatrixRotationY(-t);
  348. ConstantBuffer cb;
  349. cb.mWorld = XMMatrixTranspose(m_World);
  350. cb.mView = XMMatrixTranspose(m_View);
  351. cb.mProjection = XMMatrixTranspose(m_Projection);
  352. devcon->UpdateSubresource(pConstantBuffer, 0, nullptr, &cb, 0, 0);
  353. devcon->VSSetShader(pVS, 0, 0);
  354. devcon->VSSetConstantBuffers(0, 1, &pConstantBuffer);
  355. devcon->PSSetShader(pPS, 0, 0);
  356. devcon->PSSetSamplers(0, 1, &TexSamplerState);
  357. ourModel->Draw(devcon);
  358. swapchain->Present(0, 0);
  359. }
  360. void InitPipeline()
  361. {
  362. ID3DBlob *VS, *PS;
  363. CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
  364. CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
  365. dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
  366. dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
  367. D3D11_INPUT_ELEMENT_DESC ied[] =
  368. {
  369. { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
  370. { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 }
  371. };
  372. dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
  373. devcon->IASetInputLayout(pLayout);
  374. }
  375. void InitGraphics()
  376. {
  377. HRESULT hr;
  378. m_Projection = XMMatrixPerspectiveFovLH(XM_PIDIV4, SCREEN_WIDTH / (float)SCREEN_HEIGHT, 0.01f, 1000.0f);
  379. D3D11_BUFFER_DESC bd;
  380. ZeroMemory(&bd, sizeof(bd));
  381. bd.Usage = D3D11_USAGE_DEFAULT;
  382. bd.ByteWidth = sizeof(ConstantBuffer);
  383. bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
  384. bd.CPUAccessFlags = 0;
  385. hr = dev->CreateBuffer(&bd, nullptr, &pConstantBuffer);
  386. if (FAILED(hr))
  387. Throwanerror("Constant buffer couldn't be created");
  388. D3D11_SAMPLER_DESC sampDesc;
  389. ZeroMemory(&sampDesc, sizeof(sampDesc));
  390. sampDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
  391. sampDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
  392. sampDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
  393. sampDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
  394. sampDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
  395. sampDesc.MinLOD = 0;
  396. sampDesc.MaxLOD = D3D11_FLOAT32_MAX;
  397. hr = dev->CreateSamplerState(&sampDesc, &TexSamplerState);
  398. if (FAILED(hr))
  399. Throwanerror("Texture sampler state couldn't be created");
  400. XMVECTOR Eye = XMVectorSet(0.0f, 5.0f, -300.0f, 0.0f);
  401. XMVECTOR At = XMVectorSet(0.0f, 100.0f, 0.0f, 0.0f);
  402. XMVECTOR Up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  403. m_View = XMMatrixLookAtLH(Eye, At, Up);
  404. ourModel = new ModelLoader;
  405. if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx"))
  406. Throwanerror("Model couldn't be loaded");
  407. }
  408. HRESULT CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefines, LPCSTR pEntryPoint, LPCSTR pShaderModel, ID3DBlob** ppBytecodeBlob)
  409. {
  410. UINT compileFlags = D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR;
  411. #ifdef _DEBUG
  412. compileFlags |= D3DCOMPILE_DEBUG;
  413. #endif
  414. ID3DBlob* pErrorBlob = NULL;
  415. HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
  416. if (FAILED(result))
  417. {
  418. if (pErrorBlob != NULL)
  419. OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
  420. }
  421. if (pErrorBlob != NULL)
  422. pErrorBlob->Release();
  423. return result;
  424. }
  425. void Throwanerror(LPCSTR errormessage)
  426. {
  427. MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
  428. }