Полный код для платформы DirectX
В этом разделе приведен полный пример кода, используемый в руководстве Начало работы с DirectX для Windows.
В этом коде предполагается, что вы используете microsoft Visual Studio 2013 и создали пустой проект Win32.
Эта статья содержит следующие разделы.
Расположение для скачивания
Этот пример недоступен для загрузки.
Технологии
Требование | Значение |
---|---|
Языки программирования | C++ |
Модели программирования | Windows/C++ |
Требования
Требование | Значение |
---|---|
Минимальная версия клиента | Windows 8.1 |
Минимальная версия сервера | Windows Server 2012 R2 |
Минимальный обязательный пакет SDK | Visual Studio 2013 |
Просмотреть код (C++)
Cube.cpp
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
// File: Cube.cpp
//
// Desktop app that renders a spinning, colorful cube.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "dxstdafx.h"
#include "resource.h"
#include <string>
#include <memory>
#include "DeviceResources.h"
#include "Renderer.h"
#include "MainClass.h"
//-----------------------------------------------------------------------------
// Main function: Creates window, calls initialization functions, and hosts
// the render loop.
//-----------------------------------------------------------------------------
INT WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
HRESULT hr = S_OK;
// Enable run-time memory check for debug builds.
#if defined(DEBUG) | defined(_DEBUG)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
// Begin initialization.
// Instantiate the window manager class.
std::shared_ptr<MainClass> winMain = std::shared_ptr<MainClass>(new MainClass());
// Create a window.
hr = winMain->CreateDesktopWindow();
if (SUCCEEDED(hr))
{
// Instantiate the device manager class.
std::shared_ptr<DeviceResources> deviceResources = std::shared_ptr<DeviceResources>(new DeviceResources());
// Create device resources.
deviceResources->CreateDeviceResources();
// Instantiate the renderer.
std::shared_ptr<Renderer> renderer = std::shared_ptr<Renderer>(new Renderer(deviceResources));
renderer->CreateDeviceDependentResources();
// We have a window, so initialize window size-dependent resources.
deviceResources->CreateWindowResources(winMain->GetWindowHandle());
renderer->CreateWindowSizeDependentResources();
// Go full-screen.
deviceResources->GoFullScreen();
// Whoops! We resized the "window" when we went full-screen. Better
// tell the renderer.
renderer->CreateWindowSizeDependentResources();
// Run the program.
hr = winMain->Run(deviceResources, renderer);
}
// Cleanup is handled in destructors.
return hr;
}
MainClass.h
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
#pragma once
//-----------------------------------------------------------------------------
// File: Cube.cpp
//
// Desktop app that renders a spinning, colorful cube.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "DeviceResources.h"
#include "Renderer.h"
//-----------------------------------------------------------------------------
// Class declarations
//-----------------------------------------------------------------------------
class MainClass
{
public:
MainClass();
~MainClass();
HRESULT CreateDesktopWindow();
HWND GetWindowHandle() { return m_hWnd; };
static LRESULT CALLBACK StaticWindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
);
HRESULT Run(
std::shared_ptr<DeviceResources> deviceResources,
std::shared_ptr<Renderer> renderer
);
private:
//-----------------------------------------------------------------------------
// Desktop window resources
//-----------------------------------------------------------------------------
HMENU m_hMenu;
RECT m_rc;
HWND m_hWnd;
};
// These are STATIC because this sample only creates one window.
// If your app can have multiple windows, MAKE SURE this is dealt with
// differently.
static HINSTANCE m_hInstance;
static std::wstring m_windowClassName;
MainClass.cpp
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
// File: MainClass.cpp
//
// Creates and owns a desktop window resource.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "dxstdafx.h"
#include "resource.h"
#include <string>
#include <memory>
#include "MainClass.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
MainClass::MainClass()
{
m_windowClassName = L"Direct3DWindowClass";
m_hInstance = NULL;
}
//-----------------------------------------------------------------------------
// Create a window for our Direct3D viewport.
//-----------------------------------------------------------------------------
HRESULT MainClass::CreateDesktopWindow()
{
// Window resources are dealt with here.
if(m_hInstance == NULL)
m_hInstance = (HINSTANCE)GetModuleHandle(NULL);
HICON hIcon = NULL;
WCHAR szExePath[MAX_PATH];
GetModuleFileName(NULL, szExePath, MAX_PATH);
// If the icon is NULL, then use the first one found in the exe
if(hIcon == NULL)
hIcon = ExtractIcon(m_hInstance, szExePath, 0);
// Register the windows class
WNDCLASS wndClass;
wndClass.style = CS_DBLCLKS;
wndClass.lpfnWndProc = MainClass::StaticWindowProc;
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hInstance = m_hInstance;
wndClass.hIcon = hIcon;
wndClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndClass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
wndClass.lpszMenuName = NULL;
wndClass.lpszClassName = m_windowClassName.c_str();
if(!RegisterClass(&wndClass))
{
DWORD dwError = GetLastError();
if(dwError != ERROR_CLASS_ALREADY_EXISTS)
return HRESULT_FROM_WIN32(dwError);
}
m_rc;
int x = CW_USEDEFAULT;
int y = CW_USEDEFAULT;
// No menu in this example.
m_hMenu = NULL;
// This example uses a non-resizable 640 by 480 viewport for simplicity.
int nDefaultWidth = 640;
int nDefaultHeight = 480;
SetRect(&m_rc, 0, 0, nDefaultWidth, nDefaultHeight);
AdjustWindowRect(
&m_rc,
WS_OVERLAPPEDWINDOW,
(m_hMenu != NULL) ? true : false
);
// Create the window for our viewport.
m_hWnd = CreateWindow(
m_windowClassName.c_str(),
L"Cube11",
WS_OVERLAPPEDWINDOW,
x, y,
(m_rc.right-m_rc.left), (m_rc.bottom-m_rc.top),
0,
m_hMenu,
m_hInstance,
0
);
if(m_hWnd == NULL)
{
DWORD dwError = GetLastError();
return HRESULT_FROM_WIN32(dwError);
}
return S_OK;
}
HRESULT MainClass::Run(
std::shared_ptr<DeviceResources> deviceResources,
std::shared_ptr<Renderer> renderer
)
{
HRESULT hr = S_OK;
if (!IsWindowVisible(m_hWnd))
ShowWindow(m_hWnd, SW_SHOW);
// The render loop is controlled here.
bool bGotMsg;
MSG msg;
msg.message = WM_NULL;
PeekMessage(&msg, NULL, 0U, 0U, PM_NOREMOVE);
while (WM_QUIT != msg.message)
{
// Process window events.
// Use PeekMessage() so we can use idle time to render the scene.
bGotMsg = (PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE) != 0);
if (bGotMsg)
{
// Translate and dispatch the message
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Update the scene.
renderer->Update();
// Render frames during idle time (when no messages are waiting).
renderer->Render();
// Present the frame to the screen.
deviceResources->Present();
}
}
return hr;
}
//-----------------------------------------------------------------------------
// Destructor.
//-----------------------------------------------------------------------------
MainClass::~MainClass()
{
}
//-----------------------------------------------------------------------------
// Process windows messages. This looks for window close events, letting us
// exit out of the sample.
//-----------------------------------------------------------------------------
LRESULT CALLBACK MainClass::StaticWindowProc(
HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam
)
{
switch(uMsg)
{
case WM_CLOSE:
{
HMENU hMenu;
hMenu = GetMenu(hWnd);
if (hMenu != NULL)
{
DestroyMenu(hMenu);
}
DestroyWindow(hWnd);
UnregisterClass(
m_windowClassName.c_str(),
m_hInstance
);
return 0;
}
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
DeviceResources.h
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
#pragma once
//-----------------------------------------------------------------------------
// File: Cube.cpp
//
// Desktop app that renders a spinning, colorful cube.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Class declarations
//-----------------------------------------------------------------------------
class DeviceResources
{
public:
DeviceResources();
~DeviceResources();
HRESULT CreateDeviceResources( HWND hWnd );
HRESULT CreateDeviceResources( );
HRESULT CreateWindowResources( HWND hWnd );
HRESULT ConfigureBackBuffer();
HRESULT ReleaseBackBuffer();
HRESULT GoFullScreen();
HRESULT GoWindowed();
float GetAspectRatio();
ID3D11Device* GetDevice() { return m_pd3dDevice.Get(); };
ID3D11DeviceContext* GetDeviceContext() { return m_pd3dDeviceContext.Get(); };
ID3D11RenderTargetView* GetRenderTarget() { return m_pRenderTarget.Get(); }
ID3D11DepthStencilView* GetDepthStencil() { return m_pDepthStencilView.Get(); }
void Present();
private:
//-----------------------------------------------------------------------------
// Direct3D device
//-----------------------------------------------------------------------------
Microsoft::WRL::ComPtr<ID3D11Device> m_pd3dDevice;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_pd3dDeviceContext; // immediate context
Microsoft::WRL::ComPtr<IDXGISwapChain> m_pDXGISwapChain;
//-----------------------------------------------------------------------------
// DXGI swap chain device resources
//-----------------------------------------------------------------------------
Microsoft::WRL::ComPtr < ID3D11Texture2D> m_pBackBuffer;
Microsoft::WRL::ComPtr < ID3D11RenderTargetView> m_pRenderTarget;
//-----------------------------------------------------------------------------
// Direct3D device resources for the depth stencil
//-----------------------------------------------------------------------------
Microsoft::WRL::ComPtr<ID3D11Texture2D> m_pDepthStencil;
Microsoft::WRL::ComPtr<ID3D11DepthStencilView> m_pDepthStencilView;
//-----------------------------------------------------------------------------
// Direct3D device metadata and device resource metadata
//-----------------------------------------------------------------------------
D3D_FEATURE_LEVEL m_featureLevel;
D3D11_TEXTURE2D_DESC m_bbDesc;
D3D11_VIEWPORT m_viewport;
};
DeviceResources.cpp
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
// File: Cube.cpp
//
// Creates and owns a DirectX virtual device, along with accompanying DXGI swap
// chain and Direct3D device resources.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "dxstdafx.h"
#include "resource.h"
#include <string>
#include <memory>
#include "DeviceResources.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
DeviceResources::DeviceResources()
{
};
//-----------------------------------------------------------------------------
//
// Method 1: Create device and swap chain at the same time.
//
// Benefit: It's easy.
// Drawback: You have to create a new device, and therefore
// reload all DirectX device resources, every time
// you recreate the swap chain.
//
//-----------------------------------------------------------------------------
HRESULT DeviceResources::CreateDeviceResources(HWND hWnd)
{
HRESULT hr = S_OK;
D3D_FEATURE_LEVEL levels [] = {
D3D_FEATURE_LEVEL_9_1,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_11_1
};
// This flag adds support for surfaces with a color-channel ordering different
// from the API default. It is required for compatibility with Direct2D.
UINT deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(DEBUG) || defined(_DEBUG)
deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(DXGI_SWAP_CHAIN_DESC));
desc.Windowed = TRUE;
desc.BufferCount = 2;
desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.SampleDesc.Count = 1; //multisampling setting
desc.SampleDesc.Quality = 0; //vendor-specific flag
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.OutputWindow = hWnd;
Microsoft::WRL::ComPtr<ID3D11Device> device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
Microsoft::WRL::ComPtr<IDXGISwapChain> swapChain;
hr = D3D11CreateDeviceAndSwapChain(
nullptr,
D3D_DRIVER_TYPE::D3D_DRIVER_TYPE_HARDWARE,
nullptr,
deviceFlags,
levels,
ARRAYSIZE(levels),
D3D11_SDK_VERSION,
&desc,
swapChain.GetAddressOf(),
device.GetAddressOf(),
&m_featureLevel,
context.GetAddressOf()
);
device.As(&m_pd3dDevice);
context.As(&m_pd3dDeviceContext);
swapChain.As(&m_pDXGISwapChain);
// Configure the back buffer and viewport.
hr = m_pDXGISwapChain->GetBuffer(
0,
__uuidof(ID3D11Texture2D),
(void**) &m_pBackBuffer);
m_pBackBuffer->GetDesc(&m_bbDesc);
ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));
m_viewport.Height = (float) m_bbDesc.Height;
m_viewport.Width = (float) m_bbDesc.Width;
m_viewport.MinDepth = 0;
m_viewport.MaxDepth = 1;
m_pd3dDeviceContext->RSSetViewports(
1,
&m_viewport
);
hr = m_pd3dDevice->CreateRenderTargetView(
m_pBackBuffer.Get(),
nullptr,
m_pRenderTarget.GetAddressOf()
);
return hr;
}
//-----------------------------------------------------------------------------
//
// Method 2: Create the device and swap chain separately.
//
// Benefit: You can recreate the swap chain on-the-fly.
// Drawback: Slight increase in your initial investment.
//
//-----------------------------------------------------------------------------
HRESULT DeviceResources::CreateDeviceResources()
{
HRESULT hr = S_OK;
D3D_FEATURE_LEVEL levels[] = {
D3D_FEATURE_LEVEL_9_1,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_11_1
};
// This flag adds support for surfaces with a color-channel ordering different
// from the API default. It is required for compatibility with Direct2D.
UINT deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
#if defined(DEBUG) || defined(_DEBUG)
deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
// Create the Direct3D 11 API device object and a corresponding context.
Microsoft::WRL::ComPtr<ID3D11Device> device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> context;
hr = D3D11CreateDevice(
nullptr, // Specify nullptr to use the default adapter.
D3D_DRIVER_TYPE_HARDWARE, // Create a device using the hardware graphics driver.
0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
deviceFlags, // Set debug and Direct2D compatibility flags.
levels, // List of feature levels this app can support.
ARRAYSIZE(levels), // Size of the list above.
D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows Store apps.
&device, // Returns the Direct3D device created.
&m_featureLevel, // Returns feature level of device created.
&context // Returns the device immediate context.
);
if (FAILED(hr))
{
// Handle device interface creation failure if it occurs.
// For example, reduce the feature level requirement, or fail over
// to WARP rendering.
}
// Store pointers to the Direct3D 11.1 API device and immediate context.
device.As(&m_pd3dDevice);
context.As(&m_pd3dDeviceContext);
return hr;
}
//-----------------------------------------------------------------------------
// Method 2, continued. Creates the swap chain.
//-----------------------------------------------------------------------------
HRESULT DeviceResources::CreateWindowResources(HWND hWnd)
{
HRESULT hr = S_OK;
DXGI_SWAP_CHAIN_DESC desc;
ZeroMemory(&desc, sizeof(DXGI_SWAP_CHAIN_DESC));
desc.Windowed = TRUE; // Sets the initial state of full-screen mode.
desc.BufferCount = 2;
desc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
desc.SampleDesc.Count = 1; //multisampling setting
desc.SampleDesc.Quality = 0; //vendor-specific flag
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
desc.OutputWindow = hWnd;
// Create the DXGI device object to use in other factories, such as Direct2D.
Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice;
m_pd3dDevice.As(&dxgiDevice);
// Create swap chain.
Microsoft::WRL::ComPtr<IDXGIAdapter> adapter;
Microsoft::WRL::ComPtr<IDXGIFactory> factory;
hr = dxgiDevice->GetAdapter(&adapter);
if (SUCCEEDED(hr))
{
adapter->GetParent(IID_PPV_ARGS(&factory));
hr = factory->CreateSwapChain(
m_pd3dDevice.Get(),
&desc,
&m_pDXGISwapChain
);
}
// Configure the back buffer, stencil buffer, and viewport.
hr = ConfigureBackBuffer();
return hr;
}
HRESULT DeviceResources::ConfigureBackBuffer()
{
HRESULT hr = S_OK;
hr = m_pDXGISwapChain->GetBuffer(
0,
__uuidof(ID3D11Texture2D),
(void**) &m_pBackBuffer);
hr = m_pd3dDevice->CreateRenderTargetView(
m_pBackBuffer.Get(),
nullptr,
m_pRenderTarget.GetAddressOf()
);
m_pBackBuffer->GetDesc(&m_bbDesc);
// Create a depth-stencil view for use with 3D rendering if needed.
CD3D11_TEXTURE2D_DESC depthStencilDesc(
DXGI_FORMAT_D24_UNORM_S8_UINT,
static_cast<UINT> (m_bbDesc.Width),
static_cast<UINT> (m_bbDesc.Height),
1, // This depth stencil view has only one texture.
1, // Use a single mipmap level.
D3D11_BIND_DEPTH_STENCIL
);
m_pd3dDevice->CreateTexture2D(
&depthStencilDesc,
nullptr,
&m_pDepthStencil
);
CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
m_pd3dDevice->CreateDepthStencilView(
m_pDepthStencil.Get(),
&depthStencilViewDesc,
&m_pDepthStencilView
);
ZeroMemory(&m_viewport, sizeof(D3D11_VIEWPORT));
m_viewport.Height = (float) m_bbDesc.Height;
m_viewport.Width = (float) m_bbDesc.Width;
m_viewport.MinDepth = 0;
m_viewport.MaxDepth = 1;
m_pd3dDeviceContext->RSSetViewports(
1,
&m_viewport
);
return hr;
}
HRESULT DeviceResources::ReleaseBackBuffer()
{
HRESULT hr = S_OK;
// Release the render target view based on the back buffer:
m_pRenderTarget.Reset();
// Release the back buffer itself:
m_pBackBuffer.Reset();
// The depth stencil will need to be resized, so release it (and view):
m_pDepthStencilView.Reset();
m_pDepthStencil.Reset();
// After releasing references to these resources, we need to call Flush() to
// ensure that Direct3D also releases any references it might still have to
// the same resources - such as pipeline bindings.
m_pd3dDeviceContext->Flush();
return hr;
}
HRESULT DeviceResources::GoFullScreen()
{
HRESULT hr = S_OK;
hr = m_pDXGISwapChain->SetFullscreenState(TRUE, NULL);
// Swap chains created with the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL flag need to
// call ResizeBuffers in order to realize a full-screen mode switch. Otherwise,
// your next call to Present will fail.
// Before calling ResizeBuffers, you have to release all references to the back
// buffer device resource.
ReleaseBackBuffer();
// Now we can call ResizeBuffers.
hr = m_pDXGISwapChain->ResizeBuffers(
0, // Number of buffers. Set this to 0 to preserve the existing setting.
0, 0, // Width and height of the swap chain. Set to 0 to match the screen resolution.
DXGI_FORMAT_UNKNOWN, // This tells DXGI to retain the current back buffer format.
0
);
// Then we can recreate the back buffer, depth buffer, and so on.
hr = ConfigureBackBuffer();
return hr;
}
HRESULT DeviceResources::GoWindowed()
{
HRESULT hr = S_OK;
hr = m_pDXGISwapChain->SetFullscreenState(FALSE, NULL);
// Swap chains created with the DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL flag need to
// call ResizeBuffers in order to realize a change to windowed mode. Otherwise,
// your next call to Present will fail.
// Before calling ResizeBuffers, you have to release all references to the back
// buffer device resource.
ReleaseBackBuffer();
// Now we can call ResizeBuffers.
hr = m_pDXGISwapChain->ResizeBuffers(
0, // Number of buffers. Set this to 0 to preserve the existing setting.
0, 0, // Width and height of the swap chain. MUST be set to a non-zero value. For example, match the window size.
DXGI_FORMAT_UNKNOWN, // This tells DXGI to retain the current back buffer format.
0
);
// Then we can recreate the back buffer, depth buffer, and so on.
hr = ConfigureBackBuffer();
return hr;
}
//-----------------------------------------------------------------------------
// Returns the aspect ratio of the back buffer.
//-----------------------------------------------------------------------------
float DeviceResources::GetAspectRatio()
{
return static_cast<float>(m_bbDesc.Width) / static_cast<float>(m_bbDesc.Height);
}
//-----------------------------------------------------------------------------
// Present frame:
// Show the frame on the primary surface.
//-----------------------------------------------------------------------------
void DeviceResources::Present()
{
m_pDXGISwapChain->Present(1, 0);
}
//-----------------------------------------------------------------------------
// Destructor.
//-----------------------------------------------------------------------------
DeviceResources::~DeviceResources()
{
}
Renderer.h
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
#pragma once
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "DeviceResources.h"
//-----------------------------------------------------------------------------
// Class declarations
//-----------------------------------------------------------------------------
class Renderer
{
public:
Renderer(std::shared_ptr<DeviceResources> deviceResources);
~Renderer();
void CreateDeviceDependentResources();
void CreateWindowSizeDependentResources();
void Update();
void Render();
private:
HRESULT CreateShaders();
HRESULT CreateCube();
void CreateViewAndPerspective();
//-----------------------------------------------------------------------------
// Pointer to device resource manager
//-----------------------------------------------------------------------------
std::shared_ptr<DeviceResources> m_deviceResources;
//-----------------------------------------------------------------------------
// Variables for rendering the cube
//-----------------------------------------------------------------------------
typedef struct _constantBufferStruct {
DirectX::XMFLOAT4X4 world;
DirectX::XMFLOAT4X4 view;
DirectX::XMFLOAT4X4 projection;
} ConstantBufferStruct;
// Assert that the constant buffer remains 16-byte aligned.
static_assert((sizeof(ConstantBufferStruct) % 16) == 0, "Constant Buffer size must be 16-byte aligned");
//-----------------------------------------------------------------------------
// Per-vertex data
//-----------------------------------------------------------------------------
typedef struct _vertexPositionColor
{
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 color;
} VertexPositionColor;
//-----------------------------------------------------------------------------
// Per-vertex data (extended)
//-----------------------------------------------------------------------------
typedef struct _vertexPositionColorTangent
{
DirectX::XMFLOAT3 pos;
DirectX::XMFLOAT3 normal;
DirectX::XMFLOAT3 tangent;
} VertexPositionColorTangent;
ConstantBufferStruct m_constantBufferData;
unsigned int m_indexCount;
unsigned int m_frameCount;
//-----------------------------------------------------------------------------
// Direct3D device resources
//-----------------------------------------------------------------------------
//ID3DXEffect* m_pEffect;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pVertexBuffer;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pIndexBuffer;
Microsoft::WRL::ComPtr<ID3D11VertexShader> m_pVertexShader;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_pInputLayout;
Microsoft::WRL::ComPtr<ID3D11InputLayout> m_pInputLayoutExtended;
Microsoft::WRL::ComPtr<ID3D11PixelShader> m_pPixelShader;
Microsoft::WRL::ComPtr<ID3D11Buffer> m_pConstantBuffer;
};
Renderer.cpp
//// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
//// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
//// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//// PARTICULAR PURPOSE.
////
//// Copyright (c) Microsoft Corporation. All rights reserved
//-----------------------------------------------------------------------------
// File: Cube.cpp
//
// Renders a spinning, colorful cube.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "dxstdafx.h"
#include "resource.h"
#include <string>
#include <memory>
#include <ppltasks.h>
#include "Renderer.h"
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
Renderer::Renderer(std::shared_ptr<DeviceResources> deviceResources)
:
m_frameCount(0),
m_deviceResources(deviceResources)
{
m_frameCount = 0; // init frame count
}
//-----------------------------------------------------------------------------
// Create Direct3D shader resources by loading the .cso files.
//-----------------------------------------------------------------------------
HRESULT Renderer::CreateShaders()
{
HRESULT hr = S_OK;
// Use the Direct3D device to load resources into graphics memory.
ID3D11Device* device = m_deviceResources->GetDevice();
// You'll need to use a file loader to load the shader bytecode. In this
// example, we just use the standard library.
FILE* vShader, * pShader;
BYTE* bytes;
size_t destSize = 4096;
size_t bytesRead = 0;
bytes = new BYTE[destSize];
fopen_s(&vShader, "CubeVertexShader.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, vShader);
hr = device->CreateVertexShader(
bytes,
bytesRead,
nullptr,
&m_pVertexShader
);
D3D11_INPUT_ELEMENT_DESC iaDesc [] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = device->CreateInputLayout(
iaDesc,
ARRAYSIZE(iaDesc),
bytes,
bytesRead,
&m_pInputLayout
);
delete bytes;
bytes = new BYTE[destSize];
bytesRead = 0;
fopen_s(&pShader, "CubePixelShader.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, pShader);
hr = device->CreatePixelShader(
bytes,
bytesRead,
nullptr,
m_pPixelShader.GetAddressOf()
);
delete bytes;
CD3D11_BUFFER_DESC cbDesc(
sizeof(ConstantBufferStruct),
D3D11_BIND_CONSTANT_BUFFER
);
hr = device->CreateBuffer(
&cbDesc,
nullptr,
m_pConstantBuffer.GetAddressOf()
);
fclose(vShader);
fclose(pShader);
// Load the extended shaders with lighting calculations.
/*
bytes = new BYTE[destSize];
bytesRead = 0;
fopen_s(&vShader, "CubeVertexShaderLighting.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, vShader);
hr = device->CreateVertexShader(
bytes,
bytesRead,
nullptr,
&m_pVertexShader
);
D3D11_INPUT_ELEMENT_DESC iaDescExtended[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT,
0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
hr = device->CreateInputLayout(
iaDesc,
ARRAYSIZE(iaDesc),
bytes,
bytesRead,
&m_pInputLayoutExtended
);
delete bytes;
bytes = new BYTE[destSize];
bytesRead = 0;
fopen_s(&pShader, "CubePixelShaderPhongLighting.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, pShader);
hr = device->CreatePixelShader(
bytes,
bytesRead,
nullptr,
m_pPixelShader.GetAddressOf()
);
delete bytes;
fclose(vShader);
fclose(pShader);
bytes = new BYTE[destSize];
bytesRead = 0;
fopen_s(&pShader, "CubePixelShaderTexelLighting.cso", "rb");
bytesRead = fread_s(bytes, destSize, 1, 4096, pShader);
hr = device->CreatePixelShader(
bytes,
bytesRead,
nullptr,
m_pPixelShader.GetAddressOf()
);
delete bytes;
fclose(pShader);
*/
return hr;
}
//-----------------------------------------------------------------------------
// Create the cube:
// Creates the vertex buffer and index buffer.
//-----------------------------------------------------------------------------
HRESULT Renderer::CreateCube()
{
HRESULT hr = S_OK;
// Use the Direct3D device to load resources into graphics memory.
ID3D11Device* device = m_deviceResources->GetDevice();
// Create cube geometry.
VertexPositionColor CubeVertices[] =
{
{DirectX::XMFLOAT3(-0.5f,-0.5f,-0.5f), DirectX::XMFLOAT3( 0, 0, 0),},
{DirectX::XMFLOAT3(-0.5f,-0.5f, 0.5f), DirectX::XMFLOAT3( 0, 0, 1),},
{DirectX::XMFLOAT3(-0.5f, 0.5f,-0.5f), DirectX::XMFLOAT3( 0, 1, 0),},
{DirectX::XMFLOAT3(-0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3( 0, 1, 1),},
{DirectX::XMFLOAT3( 0.5f,-0.5f,-0.5f), DirectX::XMFLOAT3( 1, 0, 0),},
{DirectX::XMFLOAT3( 0.5f,-0.5f, 0.5f), DirectX::XMFLOAT3( 1, 0, 1),},
{DirectX::XMFLOAT3( 0.5f, 0.5f,-0.5f), DirectX::XMFLOAT3( 1, 1, 0),},
{DirectX::XMFLOAT3( 0.5f, 0.5f, 0.5f), DirectX::XMFLOAT3( 1, 1, 1),},
};
// Create vertex buffer:
CD3D11_BUFFER_DESC vDesc(
sizeof(CubeVertices),
D3D11_BIND_VERTEX_BUFFER
);
D3D11_SUBRESOURCE_DATA vData;
ZeroMemory(&vData, sizeof(D3D11_SUBRESOURCE_DATA));
vData.pSysMem = CubeVertices;
vData.SysMemPitch = 0;
vData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(
&vDesc,
&vData,
&m_pVertexBuffer
);
// Create index buffer:
unsigned short CubeIndices [] =
{
0,2,1, // -x
1,2,3,
4,5,6, // +x
5,7,6,
0,1,5, // -y
0,5,4,
2,6,7, // +y
2,7,3,
0,4,6, // -z
0,6,2,
1,3,7, // +z
1,7,5,
};
m_indexCount = ARRAYSIZE(CubeIndices);
CD3D11_BUFFER_DESC iDesc(
sizeof(CubeIndices),
D3D11_BIND_INDEX_BUFFER
);
D3D11_SUBRESOURCE_DATA iData;
ZeroMemory(&iData, sizeof(D3D11_SUBRESOURCE_DATA));
iData.pSysMem = CubeIndices;
iData.SysMemPitch = 0;
iData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(
&iDesc,
&iData,
&m_pIndexBuffer
);
return hr;
}
//-----------------------------------------------------------------------------
// Create the view matrix and create the perspective matrix.
//-----------------------------------------------------------------------------
void Renderer::CreateViewAndPerspective()
{
// Use DirectXMath to create view and perspective matrices.
DirectX::XMVECTOR eye = DirectX::XMVectorSet(0.0f, 0.7f, 1.5f, 0.f);
DirectX::XMVECTOR at = DirectX::XMVectorSet(0.0f,-0.1f, 0.0f, 0.f);
DirectX::XMVECTOR up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.f);
DirectX::XMStoreFloat4x4(
&m_constantBufferData.view,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixLookAtRH(
eye,
at,
up
)
)
);
float aspectRatioX = m_deviceResources->GetAspectRatio();
float aspectRatioY = aspectRatioX < (16.0f / 9.0f) ? aspectRatioX / (16.0f / 9.0f) : 1.0f;
DirectX::XMStoreFloat4x4(
&m_constantBufferData.projection,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixPerspectiveFovRH(
2.0f * std::atan(std::tan(DirectX::XMConvertToRadians(70) * 0.5f) / aspectRatioY),
aspectRatioX,
0.01f,
100.0f
)
)
);
}
//-----------------------------------------------------------------------------
// Create device-dependent resources for rendering.
//-----------------------------------------------------------------------------
void Renderer::CreateDeviceDependentResources()
{
// Compile shaders using the Effects library.
auto CreateShadersTask = Concurrency::create_task(
[this]( )
{
CreateShaders();
}
);
// Load the geometry for the spinning cube.
auto CreateCubeTask = CreateShadersTask.then(
[this]()
{
CreateCube();
}
);
}
void Renderer::CreateWindowSizeDependentResources()
{
// Create the view matrix and the perspective matrix.
CreateViewAndPerspective();
}
//-----------------------------------------------------------------------------
// Update the scene.
//-----------------------------------------------------------------------------
void Renderer::Update()
{
// Rotate the cube 1 degree per frame.
DirectX::XMStoreFloat4x4(
&m_constantBufferData.world,
DirectX::XMMatrixTranspose(
DirectX::XMMatrixRotationY(
DirectX::XMConvertToRadians(
(float) m_frameCount++
)
)
)
);
if (m_frameCount == MAXUINT) m_frameCount = 0;
}
//-----------------------------------------------------------------------------
// Render the cube.
//-----------------------------------------------------------------------------
void Renderer::Render()
{
// Use the Direct3D device context to draw.
ID3D11DeviceContext* context = m_deviceResources->GetDeviceContext();
ID3D11RenderTargetView* renderTarget = m_deviceResources->GetRenderTarget();
ID3D11DepthStencilView* depthStencil = m_deviceResources->GetDepthStencil();
context->UpdateSubresource(
m_pConstantBuffer.Get(),
0,
nullptr,
&m_constantBufferData,
0,
0
);
// Clear the render target and the z-buffer.
const float teal [] = { 0.098f, 0.439f, 0.439f, 1.000f };
context->ClearRenderTargetView(
renderTarget,
teal
);
context->ClearDepthStencilView(
depthStencil,
D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL,
1.0f,
0);
// Set the render target.
context->OMSetRenderTargets(
1,
&renderTarget,
depthStencil
);
// Set up the IA stage by setting the input topology and layout.
UINT stride = sizeof(VertexPositionColor);
UINT offset = 0;
context->IASetVertexBuffers(
0,
1,
m_pVertexBuffer.GetAddressOf(),
&stride,
&offset
);
context->IASetIndexBuffer(
m_pIndexBuffer.Get(),
DXGI_FORMAT_R16_UINT,
0
);
context->IASetPrimitiveTopology(
D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
);
context->IASetInputLayout(m_pInputLayout.Get());
// Set up the vertex shader stage.
context->VSSetShader(
m_pVertexShader.Get(),
nullptr,
0
);
context->VSSetConstantBuffers(
0,
1,
m_pConstantBuffer.GetAddressOf()
);
// Set up the pixel shader stage.
context->PSSetShader(
m_pPixelShader.Get(),
nullptr,
0
);
// Calling Draw tells Direct3D to start sending commands to the graphics device.
context->DrawIndexed(
m_indexCount,
0,
0
);
}
//-----------------------------------------------------------------------------
// Clean up cube resources when the Direct3D device is lost or destroyed.
//-----------------------------------------------------------------------------
Renderer::~Renderer()
{
// ComPtr will clean up references for us. But be careful to release
// references to anything you don't need whenever you call Flush or Trim.
// As always, clean up your system (CPU) memory resources before exit.
}