summaryrefslogtreecommitdiffstats
path: root/Projects/Asteroids/src/asteroids_d3d11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Projects/Asteroids/src/asteroids_d3d11.cpp')
-rw-r--r--Projects/Asteroids/src/asteroids_d3d11.cpp594
1 files changed, 594 insertions, 0 deletions
diff --git a/Projects/Asteroids/src/asteroids_d3d11.cpp b/Projects/Asteroids/src/asteroids_d3d11.cpp
new file mode 100644
index 0000000..85602e5
--- /dev/null
+++ b/Projects/Asteroids/src/asteroids_d3d11.cpp
@@ -0,0 +1,594 @@
+// Copyright 2014 Intel Corporation All Rights Reserved
+//
+// Intel makes no representations about the suitability of this software for any purpose.
+// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
+// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
+// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
+// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+// Intel does not assume any responsibility for any errors which may appear in this software
+// nor any responsibility to update it.
+
+#include <d3dcompiler.h>
+#include <directxmath.h>
+#include <math.h>
+
+#include <iostream>
+#include <algorithm>
+#include <vector>
+#include <future>
+#include <limits>
+#include <random>
+#include <locale>
+#include <codecvt>
+
+#include "asteroids_d3d11.h"
+#include "util.h"
+#include "mesh.h"
+#include "noise.h"
+#include "texture.h"
+#include "DDSTextureLoader.h"
+
+#include "asteroid_vs.h"
+#include "asteroid_ps_d3d11.h"
+#include "skybox_vs.h"
+#include "skybox_ps.h"
+#include "sprite_vs.h"
+#include "sprite_ps.h"
+#include "font_ps.h"
+
+using namespace DirectX;
+
+namespace AsteroidsD3D11 {
+
+Asteroids::Asteroids(AsteroidsSimulation* asteroids, GUI* gui, bool warp)
+ : mAsteroids(asteroids)
+ , mGUI(gui)
+ , mSwapChain(nullptr)
+ , mDevice(nullptr)
+ , mDeviceCtxt(nullptr)
+ , mRenderTarget(nullptr)
+ , mRenderTargetView(nullptr)
+ , mDepthStencilView(nullptr)
+ , mDepthStencilState(nullptr)
+ , mInputLayout(nullptr)
+ , mIndexBuffer(nullptr)
+ , mVertexBuffer(nullptr)
+ , mVertexShader(nullptr)
+ , mPixelShader(nullptr)
+ , mDrawConstantBuffer(nullptr)
+ , mSkyboxVertexShader(nullptr)
+ , mSkyboxPixelShader(nullptr)
+ , mSkyboxConstantBuffer(nullptr)
+ , mSamplerState(nullptr)
+ , mD3D11Sprite( new GUISprite(5, 10, 140, 50, "directx11.dds") )
+{
+ QueryPerformanceFrequency((LARGE_INTEGER*)&mPerfCounterFreq);
+
+ memset(&mViewPort, 0, sizeof(mViewPort));
+ memset(&mScissorRect, 0, sizeof(mScissorRect));
+ memset(mTextures, 0, sizeof(mTextures));
+ memset(mTextureSRVs, 0, sizeof(mTextureSRVs));
+
+ // Create device and swap chain
+ {
+ IDXGIAdapter* adapter = nullptr;
+ D3D_DRIVER_TYPE driverType = ( warp ) ? D3D_DRIVER_TYPE_WARP : D3D_DRIVER_TYPE_HARDWARE;
+ HMODULE swModule = NULL;
+ UINT flags = 0;
+ D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
+ UINT numFeatureLevels = ARRAYSIZE(featureLevels);
+ UINT sdkVersion = D3D11_SDK_VERSION;
+
+#ifdef _DEBUG
+ flags = flags | D3D11_CREATE_DEVICE_DEBUG;
+#endif
+
+ auto hr = D3D11CreateDevice(adapter, driverType, swModule,
+ flags, featureLevels, numFeatureLevels, sdkVersion, &mDevice, nullptr, &mDeviceCtxt);
+ if (FAILED(hr)) {
+ // Try again without the debug flag...
+ flags = flags & ~D3D11_CREATE_DEVICE_DEBUG;
+ ThrowIfFailed(D3D11CreateDevice(adapter, driverType, swModule,
+ flags, featureLevels, numFeatureLevels, sdkVersion, &mDevice, nullptr, &mDeviceCtxt));
+ }
+ }
+
+ // create pipeline state
+ {
+ D3D11_INPUT_ELEMENT_DESC inputDesc[] = {
+ { "ATTRIB", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "ATTRIB", 1, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc),
+ g_asteroid_vs, sizeof(g_asteroid_vs), &mInputLayout));
+
+ {
+ D3D11_DEPTH_STENCIL_DESC desc = CD3D11_DEPTH_STENCIL_DESC(D3D11_DEFAULT);
+ desc.DepthFunc = D3D11_COMPARISON_GREATER_EQUAL;
+ ThrowIfFailed(mDevice->CreateDepthStencilState(&desc, &mDepthStencilState));
+ }
+ {
+ CD3D11_BLEND_DESC desc = CD3D11_BLEND_DESC(CD3D11_DEFAULT());
+ ThrowIfFailed(mDevice->CreateBlendState(&desc, &mBlendState));
+
+ // Premultiplied over blend
+ desc.RenderTarget[0].BlendEnable = TRUE;
+ desc.RenderTarget[0].SrcBlend = D3D11_BLEND_ONE;
+ desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
+ desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
+ ThrowIfFailed(mDevice->CreateBlendState(&desc, &mSpriteBlendState));
+ }
+
+ ThrowIfFailed(mDevice->CreateVertexShader(g_asteroid_vs, sizeof(g_asteroid_vs), NULL, &mVertexShader));
+ ThrowIfFailed(mDevice->CreatePixelShader(g_asteroid_ps_d3d11, sizeof(g_asteroid_ps_d3d11), NULL, &mPixelShader));
+ }
+ // create skybox pipeline state
+ {
+ D3D11_INPUT_ELEMENT_DESC inputDesc[] = {
+ { "ATTRIB", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "ATTRIB", 1, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc),
+ g_skybox_vs, sizeof(g_skybox_vs), &mSkyboxInputLayout));
+
+ ThrowIfFailed(mDevice->CreateVertexShader(g_skybox_vs, sizeof(g_skybox_vs), NULL, &mSkyboxVertexShader));
+ ThrowIfFailed(mDevice->CreatePixelShader(g_skybox_ps, sizeof(g_skybox_ps), NULL, &mSkyboxPixelShader));
+ }
+
+ // Sprites and fonts
+ {
+ D3D11_INPUT_ELEMENT_DESC inputDesc[] = {
+ { "ATTRIB", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ { "ATTRIB", 1, DXGI_FORMAT_R32G32_FLOAT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
+ };
+
+ ThrowIfFailed(mDevice->CreateInputLayout(inputDesc, ARRAYSIZE(inputDesc),
+ g_sprite_vs, sizeof(g_sprite_vs), &mSpriteInputLayout));
+
+ ThrowIfFailed(mDevice->CreateVertexShader(g_sprite_vs, sizeof(g_sprite_vs), NULL, &mSpriteVertexShader));
+ ThrowIfFailed(mDevice->CreatePixelShader(g_sprite_ps, sizeof(g_sprite_ps), NULL, &mSpritePixelShader));
+ ThrowIfFailed(mDevice->CreatePixelShader(g_font_ps, sizeof(g_font_ps), NULL, &mFontPixelShader));
+ }
+
+ // Create draw constant buffer
+ {
+ D3D11_BUFFER_DESC desc = {};
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = sizeof(DrawConstantBuffer);
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mDrawConstantBuffer));
+ }
+ // Create skybox constant buffer
+ {
+ D3D11_BUFFER_DESC desc = {};
+ desc.Usage = D3D11_USAGE_DYNAMIC;
+ desc.ByteWidth = sizeof(SkyboxConstantBuffer);
+ desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
+ desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
+ ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mSkyboxConstantBuffer));
+ }
+
+ // Create sampler
+ {
+ D3D11_SAMPLER_DESC desc = {};
+ desc.Filter = D3D11_FILTER_ANISOTROPIC;
+ desc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
+ desc.MinLOD = -D3D11_FLOAT32_MAX;
+ desc.MaxLOD = D3D11_FLOAT32_MAX;
+ desc.MipLODBias = 0.0f;
+ desc.MaxAnisotropy = TEXTURE_ANISO;
+ desc.ComparisonFunc = D3D11_COMPARISON_NEVER;
+ ThrowIfFailed(mDevice->CreateSamplerState(&desc, &mSamplerState));
+ }
+
+ CreateMeshes();
+ InitializeTextureData();
+ CreateGUIResources();
+
+ // Load textures
+ ThrowIfFailed(CreateDDSTextureFromFile(mDevice, L"starbox_1024.dds", &mSkyboxSRV, true));
+}
+
+Asteroids::~Asteroids()
+{
+ ReleaseSwapChain();
+
+ SafeRelease(&mDepthStencilState);
+ SafeRelease(&mInputLayout);
+ SafeRelease(&mIndexBuffer);
+ SafeRelease(&mVertexBuffer);
+ SafeRelease(&mVertexShader);
+ SafeRelease(&mPixelShader);
+ SafeRelease(&mDrawConstantBuffer);
+ SafeRelease(&mSamplerState);
+
+ SafeRelease(&mBlendState);
+ SafeRelease(&mSpriteBlendState);
+
+ for (auto i : mSpriteTextures) {
+ i.second->Release();
+ }
+ SafeRelease(&mSpriteInputLayout);
+ SafeRelease(&mSpriteVertexShader);
+ SafeRelease(&mSpritePixelShader);
+ SafeRelease(&mSpriteVertexBuffer);
+
+ SafeRelease(&mFontPixelShader);
+ SafeRelease(&mFontTextureSRV);
+
+ SafeRelease(&mSkyboxVertexShader);
+ SafeRelease(&mSkyboxPixelShader);
+ SafeRelease(&mSkyboxConstantBuffer);
+ SafeRelease(&mSkyboxVertexBuffer);
+ SafeRelease(&mSkyboxInputLayout);
+ SafeRelease(&mSkyboxSRV);
+
+ for (auto& texture : mTextures) SafeRelease(&texture);
+ for (auto& srv : mTextureSRVs) SafeRelease(&srv);
+
+ if (mSwapChain != nullptr) {
+ mSwapChain->Release();
+ mSwapChain = nullptr;
+ }
+ SafeRelease(&mDeviceCtxt);
+ SafeRelease(&mDevice);
+
+ delete mD3D11Sprite;
+}
+
+
+void Asteroids::ReleaseSwapChain()
+{
+ // Cleanup any references...
+ SafeRelease(&mRenderTarget);
+ SafeRelease(&mRenderTargetView);
+ SafeRelease(&mDepthStencilView);
+ SafeRelease(&mSwapChain);
+ mDeviceCtxt->ClearState();
+ mDeviceCtxt->Flush();
+}
+
+inline void DisableDXGIWindowChanges(IUnknown* device, HWND window)
+{
+ IDXGIDevice * pDXGIDevice;
+ ThrowIfFailed(device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)));
+ IDXGIAdapter * pDXGIAdapter;
+ ThrowIfFailed(pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)));
+ IDXGIFactory * pIDXGIFactory;
+ ThrowIfFailed(pDXGIAdapter->GetParent(IID_PPV_ARGS(&pIDXGIFactory)));
+
+ ThrowIfFailed(pIDXGIFactory->MakeWindowAssociation(window, DXGI_MWA_NO_WINDOW_CHANGES | DXGI_MWA_NO_ALT_ENTER));
+
+ pIDXGIFactory->Release();
+ pDXGIAdapter->Release();
+ pDXGIDevice->Release();
+}
+
+void Asteroids::ResizeSwapChain(IDXGIFactory2* dxgiFactory, HWND outputWindow, unsigned int width, unsigned int height)
+{
+ ReleaseSwapChain();
+
+ // Create swap chain
+ {
+ DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
+ swapChainDesc.Width = width;
+ swapChainDesc.Height = height;
+ swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // Can create an SRGB render target view on the swap chain buffer
+ swapChainDesc.Stereo = FALSE;
+ swapChainDesc.SampleDesc.Count = 1;
+ swapChainDesc.SampleDesc.Quality = 0;
+ swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ swapChainDesc.BufferCount = NUM_SWAP_CHAIN_BUFFERS;
+ swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
+ swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
+ swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; // Not used
+ swapChainDesc.Flags = 0;
+
+ ThrowIfFailed(dxgiFactory->CreateSwapChainForHwnd(
+ mDevice, outputWindow, &swapChainDesc, nullptr, nullptr, &mSwapChain));
+ // MakeWindowAssociation must be called after CreateSwapChain
+ DisableDXGIWindowChanges(mDevice, outputWindow);
+ }
+
+ // create render target view
+ {
+ ThrowIfFailed(mSwapChain->GetBuffer(0, IID_PPV_ARGS(&mRenderTarget)));
+
+ D3D11_RENDER_TARGET_VIEW_DESC desc = {};
+ desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB;
+ desc.Texture2D.MipSlice = 0;
+ ThrowIfFailed(mDevice->CreateRenderTargetView(mRenderTarget, &desc, &mRenderTargetView));
+ }
+
+ // create depth stencil view
+ {
+ CD3D11_TEXTURE2D_DESC desc = CD3D11_TEXTURE2D_DESC(
+ DXGI_FORMAT_D32_FLOAT, width, height, 1, 1, D3D11_BIND_DEPTH_STENCIL);
+
+ ID3D11Texture2D* depthStencil = nullptr;
+ ThrowIfFailed(mDevice->CreateTexture2D(&desc, nullptr, &depthStencil));
+ ThrowIfFailed(mDevice->CreateDepthStencilView(depthStencil, nullptr, &mDepthStencilView));
+ depthStencil->Release();
+ }
+
+ // update the viewport and scissor
+ ZeroMemory(&mViewPort, sizeof(D3D11_VIEWPORT));
+ mViewPort.TopLeftX = 0;
+ mViewPort.TopLeftY = 0;
+ mViewPort.Width = (float)width;
+ mViewPort.Height = (float)height;
+ mViewPort.MinDepth = 0.0f;
+ mViewPort.MaxDepth = 1.0f;
+
+ mScissorRect.left = 0;
+ mScissorRect.top = 0;
+ mScissorRect.right = width;
+ mScissorRect.bottom = height;
+}
+
+
+void Asteroids::CreateMeshes()
+{
+ auto asteroidMeshes = mAsteroids->Meshes();
+
+ // create vertex buffer
+ {
+ CD3D11_BUFFER_DESC desc(
+ (UINT)asteroidMeshes->vertices.size() * sizeof(asteroidMeshes->vertices[0]),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT);
+
+ D3D11_SUBRESOURCE_DATA data = {};
+ data.pSysMem = asteroidMeshes->vertices.data();
+
+ ThrowIfFailed(mDevice->CreateBuffer(&desc, &data, &mVertexBuffer));
+ }
+
+ // create index buffer
+ {
+ CD3D11_BUFFER_DESC desc(
+ (UINT)asteroidMeshes->indices.size() * sizeof(asteroidMeshes->indices[0]),
+ D3D11_BIND_INDEX_BUFFER,
+ D3D11_USAGE_DEFAULT);
+
+ D3D11_SUBRESOURCE_DATA data = {};
+ data.pSysMem = asteroidMeshes->indices.data();
+
+ ThrowIfFailed(mDevice->CreateBuffer(&desc, &data, &mIndexBuffer));
+ }
+
+ std::vector<SkyboxVertex> skyboxVertices;
+ CreateSkyboxMesh(&skyboxVertices);
+
+ // create skybox vertex buffer
+ {
+ CD3D11_BUFFER_DESC desc(
+ (UINT)skyboxVertices.size() * sizeof(skyboxVertices[0]),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DEFAULT);
+
+ D3D11_SUBRESOURCE_DATA data = {};
+ data.pSysMem = skyboxVertices.data();
+
+ ThrowIfFailed(mDevice->CreateBuffer(&desc, &data, &mSkyboxVertexBuffer));
+ }
+
+ // create sprite vertex buffer (dynamic)
+ {
+ CD3D11_BUFFER_DESC desc(
+ MAX_SPRITE_VERTICES_PER_FRAME * sizeof(SpriteVertex),
+ D3D11_BIND_VERTEX_BUFFER,
+ D3D11_USAGE_DYNAMIC, D3D11_CPU_ACCESS_WRITE);
+
+ ThrowIfFailed(mDevice->CreateBuffer(&desc, nullptr, &mSpriteVertexBuffer));
+ }
+}
+
+void Asteroids::InitializeTextureData()
+{
+ D3D11_TEXTURE2D_DESC textureDesc = {};
+ textureDesc.Width = TEXTURE_DIM;
+ textureDesc.Height = TEXTURE_DIM;
+ textureDesc.ArraySize = 3;
+ textureDesc.MipLevels = 0; // Full chain
+ textureDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
+ textureDesc.SampleDesc.Count = 1;
+ textureDesc.Usage = D3D11_USAGE_DEFAULT;
+ textureDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
+
+ for (UINT t = 0; t < NUM_UNIQUE_TEXTURES; ++t) {
+ ThrowIfFailed(mDevice->CreateTexture2D(&textureDesc, mAsteroids->TextureData(t), &mTextures[t]));
+ ThrowIfFailed(mDevice->CreateShaderResourceView(mTextures[t], nullptr, &mTextureSRVs[t]));
+ }
+}
+
+void Asteroids::CreateGUIResources()
+{
+ auto font = mGUI->Font();
+ D3D11_TEXTURE2D_DESC textureDesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8_UNORM, font->BitmapWidth(), font->BitmapHeight(), 1, 1);
+
+ D3D11_SUBRESOURCE_DATA initialData = {};
+ initialData.pSysMem = font->Pixels();
+ initialData.SysMemPitch = font->BitmapWidth();
+
+ ID3D11Texture2D* texture = nullptr;
+ ThrowIfFailed(mDevice->CreateTexture2D(&textureDesc, &initialData, &texture));
+ ThrowIfFailed(mDevice->CreateShaderResourceView(texture, nullptr, &mFontTextureSRV));
+ SafeRelease(&texture);
+
+ // Load any GUI sprite textures
+ for (int i = -1; i < (int)mGUI->size(); ++i) {
+ auto control = i >= 0 ? (*mGUI)[i] : mD3D11Sprite;
+ if (control->TextureFile().length() > 0 && mSpriteTextures.find(control->TextureFile()) == mSpriteTextures.end()) {
+ std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+ ID3D11ShaderResourceView* textureSRV = nullptr;
+ ThrowIfFailed(CreateDDSTextureFromFile(mDevice, converter.from_bytes(control->TextureFile()).c_str(), &textureSRV, true));
+ mSpriteTextures[control->TextureFile()] = textureSRV;
+ }
+ }
+}
+
+static_assert(sizeof(IndexType) == 2, "Expecting 16-bit index buffer");
+
+void Asteroids::Render(float frameTime, const OrbitCamera& camera, const Settings& settings)
+{
+ LONG64 currCounter = 0;
+ QueryPerformanceCounter((LARGE_INTEGER*)&currCounter);
+
+ // Frame data
+ mAsteroids->Update(frameTime, camera.Eye(), settings);
+
+ mTotalUpdateTicks = currCounter;
+ QueryPerformanceCounter((LARGE_INTEGER*)&currCounter);
+ mTotalUpdateTicks = currCounter - mTotalUpdateTicks;
+
+ auto staticAsteroidData = mAsteroids->StaticData();
+ auto dynamicAsteroidData = mAsteroids->DynamicData();
+
+ // Clear the render target
+ float clearcol[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
+ mDeviceCtxt->ClearRenderTargetView(mRenderTargetView, clearcol);
+ mDeviceCtxt->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH, 0.0f, 0);
+
+ QueryPerformanceCounter((LARGE_INTEGER*)&currCounter);
+ {
+ ID3D11Buffer* ia_buffers[] = { mVertexBuffer };
+ UINT ia_strides[] = { sizeof(Vertex) };
+ UINT ia_offsets[] = { 0 };
+ mDeviceCtxt->IASetInputLayout(mInputLayout);
+ mDeviceCtxt->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
+ mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets);
+ mDeviceCtxt->IASetIndexBuffer(mIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+ }
+
+ mDeviceCtxt->VSSetShader(mVertexShader, nullptr, 0);
+ mDeviceCtxt->VSSetConstantBuffers(0, 1, &mDrawConstantBuffer);
+
+ mDeviceCtxt->RSSetViewports(1, &mViewPort);
+ mDeviceCtxt->RSSetScissorRects(1, &mScissorRect);
+
+ mDeviceCtxt->PSSetShader(mPixelShader, nullptr, 0);
+ mDeviceCtxt->PSSetSamplers(0, 1, &mSamplerState);
+
+ mDeviceCtxt->OMSetRenderTargets(1, &mRenderTargetView, mDepthStencilView);
+ mDeviceCtxt->OMSetDepthStencilState(mDepthStencilState, 0);
+ mDeviceCtxt->OMSetBlendState(mBlendState, nullptr, 0xFFFFFFFF);
+
+ auto viewProjection = camera.ViewProjection();
+ for (UINT drawIdx = 0; drawIdx < NUM_ASTEROIDS; ++drawIdx)
+ {
+ auto staticData = &staticAsteroidData[drawIdx];
+ auto dynamicData = &dynamicAsteroidData[drawIdx];
+
+ D3D11_MAPPED_SUBRESOURCE mapped = {};
+ ThrowIfFailed(mDeviceCtxt->Map(mDrawConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped));
+
+ auto drawConstants = (DrawConstantBuffer*) mapped.pData;
+ XMStoreFloat4x4(&drawConstants->mWorld, dynamicData->world);
+ XMStoreFloat4x4(&drawConstants->mViewProjection, viewProjection);
+ drawConstants->mSurfaceColor = staticData->surfaceColor;
+ drawConstants->mDeepColor = staticData->deepColor;
+
+ mDeviceCtxt->Unmap(mDrawConstantBuffer, 0);
+
+ mDeviceCtxt->PSSetShaderResources(0, 1, &mTextureSRVs[staticData->textureIndex]);
+
+ mDeviceCtxt->DrawIndexedInstanced(dynamicData->indexCount, 1, dynamicData->indexStart, staticData->vertexStart, 0);
+ }
+
+ mTotalRenderTicks = currCounter;
+ QueryPerformanceCounter((LARGE_INTEGER*)&currCounter);
+ mTotalRenderTicks = currCounter - mTotalRenderTicks;
+
+ // Draw skybox
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped = {};
+ ThrowIfFailed(mDeviceCtxt->Map(mSkyboxConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped));
+ auto skyboxConstants = (SkyboxConstantBuffer*) mapped.pData;
+ XMStoreFloat4x4(&skyboxConstants->mViewProjection, camera.ViewProjection());
+ mDeviceCtxt->Unmap(mSkyboxConstantBuffer, 0);
+
+ ID3D11Buffer* ia_buffers[] = { mSkyboxVertexBuffer };
+ UINT ia_strides[] = { sizeof(SkyboxVertex) };
+ UINT ia_offsets[] = { 0 };
+ mDeviceCtxt->IASetInputLayout(mSkyboxInputLayout);
+ mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets);
+
+ mDeviceCtxt->VSSetShader(mSkyboxVertexShader, nullptr, 0);
+ mDeviceCtxt->VSSetConstantBuffers(0, 1, &mSkyboxConstantBuffer);
+
+ mDeviceCtxt->PSSetShader(mSkyboxPixelShader, nullptr, 0);
+ mDeviceCtxt->PSSetSamplers(0, 1, &mSamplerState);
+ mDeviceCtxt->PSSetShaderResources(0, 1, &mSkyboxSRV);
+
+ mDeviceCtxt->Draw(6*6, 0);
+ }
+
+ mDeviceCtxt->OMSetRenderTargets(1, &mRenderTargetView, 0); // No more depth buffer
+
+ // Draw sprites and fonts
+ {
+ // Fill in vertices (TODO: could move this vector to be a member - not a big deal)
+ std::vector<UINT> controlVertices;
+ controlVertices.reserve(mGUI->size());
+
+ {
+ D3D11_MAPPED_SUBRESOURCE mapped = {};
+ ThrowIfFailed(mDeviceCtxt->Map(mSpriteVertexBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped));
+ auto vertexBase = (SpriteVertex*)mapped.pData;
+ auto vertexEnd = vertexBase;
+
+
+ for (int i = -1; i < (int)mGUI->size(); ++i) {
+ auto control = i >= 0 ? (*mGUI)[i] : mD3D11Sprite;
+ controlVertices.push_back((UINT)(control->Draw(mViewPort.Width, mViewPort.Height, vertexEnd) - vertexEnd));
+ vertexEnd += controlVertices.back();
+ }
+
+ mDeviceCtxt->Unmap(mSpriteVertexBuffer, 0);
+ }
+
+ ID3D11Buffer* ia_buffers[] = { mSpriteVertexBuffer };
+ UINT ia_strides[] = { sizeof(SpriteVertex) };
+ UINT ia_offsets[] = { 0 };
+ mDeviceCtxt->IASetInputLayout(mSpriteInputLayout);
+ mDeviceCtxt->IASetVertexBuffers(0, 1, ia_buffers, ia_strides, ia_offsets);
+ mDeviceCtxt->VSSetShader(mSpriteVertexShader, 0, 0);
+ mDeviceCtxt->OMSetBlendState(mSpriteBlendState, nullptr, 0xFFFFFFFF);
+
+ // Draw
+ UINT vertexStart = 0;
+
+ for (int i = -1; i < (int)mGUI->size(); ++i) {
+ auto control = i >= 0 ? (*mGUI)[i] : mD3D11Sprite;
+ if (control->Visible()) {
+ if (control->TextureFile().length() == 0) { // Font
+ mDeviceCtxt->PSSetShader(mFontPixelShader, 0, 0);
+ mDeviceCtxt->PSSetShaderResources(0, 1, &mFontTextureSRV);
+ } else { // Sprite
+ auto textureSRV = mSpriteTextures[control->TextureFile()];
+ mDeviceCtxt->PSSetShader(mSpritePixelShader, 0, 0);
+ mDeviceCtxt->PSSetShaderResources(0, 1, &textureSRV);
+ }
+ mDeviceCtxt->Draw(controlVertices[1+i], vertexStart);
+ }
+ vertexStart += controlVertices[1+i];
+ }
+ }
+
+ mSwapChain->Present(settings.vsync ? 1 : 0, 0);
+}
+
+void Asteroids::GetPerfCounters(float &UpdateTime, float &RenderTime)
+{
+ UpdateTime = (float)mTotalUpdateTicks/(float)mPerfCounterFreq;
+ RenderTime = (float)mTotalRenderTicks/(float)mPerfCounterFreq;
+}
+
+} // namespace AsteroidsD3D11