DirectX11 初期化
はじめに
DirectX11を使用して画面の初期化を行う.
環境
- Windows10 Home
- Visual Studio 2022
- C++
- AMD Ryzen5 3600
- RAM 24GB
- GeForce GTX1060 6GB
ウィンドウの作成
GPUを列挙して選択
bool DxManager::CreateFactory() { ComPtr<IDXGIOutput> pOutput; DXGI_ADAPTER_DESC adapterDesc = {}; size_t stringLength; uint32_t numModes = 0; uint32_t GPUMaxMem = 0; uint32_t GPUNum = 0; HRESULT hResult = S_OK; //DXGIファクトリーの作成 hResult = CreateDXGIFactory(IID_PPV_ARGS(_pFactory.GetAddressOf())); if (FAILED(hResult)) { return false; } //GPUを列挙 for (uint32_t i = 0; i < 100; i++) { IDXGIAdapter* adapter; hResult = _pFactory->EnumAdapters(i, &adapter); if (FAILED(hResult)) { break; } //GPUの情報を取得 hResult = adapter->GetDesc(&adapterDesc); if (FAILED(hResult)) { return false; } char videoCardDesc[128]; int error = wcstombs_s(&stringLength, videoCardDesc, 128, adapterDesc.Description, 128); if (error != 0) { break; } uint32_t videoCardMemory = (uint32_t)(adapterDesc.DedicatedVideoMemory / 1028 / 1024); std::cout << "ビデオカード名: " << videoCardDesc << std::endl; std::cout << "ビデオメモリ: " << videoCardMemory << std::endl; hResult = adapter->EnumOutputs(0, pOutput.GetAddressOf()); if (FAILED(hResult)) { continue; } hResult = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, nullptr); if (FAILED(hResult)) { continue; } //一番メモリが多いGPUを探す if (videoCardMemory > GPUMaxMem) { GPUMaxMem = videoCardMemory; GPUNum = i; } } //GPUを選ぶやでー hResult = _pFactory->EnumAdapters(GPUNum, _pAdapter.GetAddressOf()); if (FAILED(hResult)) { return false; } return true; }
デバイスとスワップチェインの作成
bool DxManager::CreateDeviceAndSwapChain() { HRESULT hResult = S_OK; UINT cdev_flags = 0; //デバッグレイヤーを有効にするやでー #ifdef _DEBUG cdev_flags |= D3D11_CREATE_DEVICE_DEBUG; #endif DXGI_MODE_DESC modeDesc = {}; modeDesc.Width = _width; modeDesc.Height = _height; modeDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; modeDesc.RefreshRate.Numerator = 60; modeDesc.RefreshRate.Denominator = 1; modeDesc.Scaling = DXGI_MODE_SCALING_CENTERED; modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); swapChainDesc.BufferCount = 2; swapChainDesc.BufferDesc = modeDesc; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = _hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.Windowed = true; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, }; hResult = D3D11CreateDeviceAndSwapChain( _pAdapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, cdev_flags, featureLevels, 4, D3D11_SDK_VERSION, &swapChainDesc, _pSwapChain.GetAddressOf(), _pDevice.GetAddressOf(), &_featurelevel, _pDeviceContext.GetAddressOf()); if (FAILED(hResult)) { return false; } _pAdapter->Release(); _pFactory->Release(); hResult = _pSwapChain->GetBuffer(0, IID_PPV_ARGS(_pRenderTarget.GetAddressOf())); if (FAILED(hResult)) { return false; } hResult = _pDevice->CreateRenderTargetView(_pRenderTarget.Get(), nullptr, _pRenderTargetView.GetAddressOf()); if (FAILED(hResult)) { return false; } _viewport.Width = static_cast<float>(_width); _viewport.Height = static_cast<float>(_height); _viewport.MinDepth = 0.0f; _viewport.MaxDepth = 1.0f; _viewport.TopLeftX = 0; _viewport.TopLeftY = 0; return true; }
デプスステンシルバッファの作成
bool DxManager::CreateDepthStencilBuffer() { D3D11_DEPTH_STENCIL_DESC desc = {}; desc.DepthEnable = true; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_LESS; desc.StencilEnable = false; desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; HRESULT hResult = _pDevice->CreateDepthStencilState(&desc, _pDepthStencilState.GetAddressOf()); if (FAILED(hResult)) { return false; } D3D11_TEXTURE2D_DESC Tex2Desc = {}; Tex2Desc.Format = DXGI_FORMAT_R24G8_TYPELESS; Tex2Desc.Width = _width; Tex2Desc.Height = _height; Tex2Desc.ArraySize = 1; Tex2Desc.MipLevels = 1; Tex2Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; Tex2Desc.Usage = D3D11_USAGE_DEFAULT; Tex2Desc.CPUAccessFlags = 0; Tex2Desc.SampleDesc.Count = 1; Tex2Desc.SampleDesc.Quality = 0; Tex2Desc.MiscFlags = 0; hResult = _pDevice->CreateTexture2D(&Tex2Desc, nullptr, _pDepthStencilTex.GetAddressOf()); if (FAILED(hResult)) { return false; } D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc = {}; DSVDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; DSVDesc.Texture2D.MipSlice = 0; DSVDesc.Flags = 0; hResult = _pDevice->CreateDepthStencilView(_pDepthStencilTex.Get(), &DSVDesc, _pDepthStencilView.GetAddressOf()); if (FAILED(hResult)) { return false; } return true; }
ブレンドステートの作成
bool DxManager::CreateBlendState() { D3D11_RENDER_TARGET_BLEND_DESC descRTBS = {}; descRTBS.BlendEnable = true; descRTBS.SrcBlend = D3D11_BLEND_SRC_ALPHA; descRTBS.DestBlend = D3D11_BLEND_INV_SRC_ALPHA; descRTBS.BlendOp = D3D11_BLEND_OP_ADD; descRTBS.SrcBlendAlpha = D3D11_BLEND_ONE; descRTBS.DestBlendAlpha = D3D11_BLEND_ZERO; descRTBS.BlendOpAlpha = D3D11_BLEND_OP_ADD; descRTBS.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; D3D11_BLEND_DESC descBS = {}; descBS.AlphaToCoverageEnable = true; descBS.IndependentBlendEnable = true; for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { descBS.RenderTarget[i] = descRTBS; } HRESULT hResult = _pDevice->CreateBlendState(&descBS, _pBlendState.GetAddressOf()); if (FAILED(hResult)) { return false; } return true; }
画面の初期化
void DxManager::BeginRender() { _pDeviceContext->OMSetRenderTargets(1, _pRenderTargetView.GetAddressOf(), _pDepthStencilView.Get()); _pDeviceContext->RSSetViewports(1, &_viewport); float clearColor[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; _pDeviceContext->ClearRenderTargetView(_pRenderTargetView.Get(), clearColor); _pDeviceContext->ClearDepthStencilView(_pDepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } void DxManager::EndRender() { _pSwapChain->Present(1, 0); }
ソースコード
main.cpp
#include "App.h" int main() { App app = App(); app.Run(); }
App.h
#pragma once #include <Windows.h> #include <cstdint> #include <string> #include <iostream> #include "DxManager.h" class App { public: App(); void Run(); private: bool InitApp(); bool InitWindow(); void MainLoop(); static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); private: const std::wstring WindowClassName = L"MainWindow"; uint32_t _width; uint32_t _height; HWND _hwnd; HINSTANCE _hInstance; };
App.cpp
#include "App.h" App::App() { _width = 1080; _height = 720; _hwnd = nullptr; _hInstance = nullptr; } void App::Run() { if (!InitApp()) { return; } MainLoop(); } //初期化 bool App::InitApp() { dx = new DxManager(); if (!InitWindow()) { return false; } if (!dx->Init(_width, _height, _hwnd)) { return false; } return true; } //ウィンドウの初期化 bool App::InitWindow() { _hInstance = GetModuleHandle(nullptr); if (_hInstance == nullptr) { return false; } //ウィンドウの設定 WNDCLASSEX wc = {}; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; //水平方向と垂直方向のサイズ変更で再描画 wc.lpfnWndProc = WndProc; //ウィンドウプロシージャの登録 wc.hIcon = LoadIcon(_hInstance, IDI_APPLICATION); //アイコン wc.hCursor = LoadCursor(_hInstance, IDC_ARROW); //マウスカーソル wc.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH); //背景色は黒 wc.hInstance = _hInstance; //インスタンスハンドル wc.lpszMenuName = nullptr; //メニュー wc.lpszClassName = WindowClassName.c_str(); //ウィンドウクラスの名前 wc.hIconSm = LoadIcon(_hInstance, IDI_APPLICATION); //小さいアイコン RegisterClassEx(&wc); //ウィンドウクラスの登録 _hwnd = CreateWindowEx( 0, WindowClassName.c_str(), L"Title", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, _width, _height, nullptr, nullptr, _hInstance, nullptr ); ShowWindow(_hwnd, SW_SHOWNORMAL); UpdateWindow(_hwnd); SetFocus(_hwnd); return true; } //メインループ void App::MainLoop() { MSG msg = {}; while (WM_QUIT != msg.message) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE == true)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { dx->BeginRender(); dx->EndRender(); UpdateWindow(_hwnd); } } } //ウィンドウプロシージャ LRESULT CALLBACK App::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch (msg) { case WM_DESTROY: PostQuitMessage(0); break; default: break; } return DefWindowProc(hwnd, msg, wParam, lParam); }
DxManager.h
#pragma once #include <iostream> #include <cstdint> #include <d3d11.h> #include <dxgi.h> #include <Windows.h> #include <windef.h> #include <wrl/client.h> #pragma comment(lib, "d3d11.lib") #pragma comment(lib, "dxgi.lib") using Microsoft::WRL::ComPtr; class DxManager { private: D3D_FEATURE_LEVEL _featurelevel; ComPtr<IDXGIFactory> _pFactory = nullptr; ComPtr<IDXGIAdapter> _pAdapter = nullptr; ComPtr<ID3D11Device> _pDevice = nullptr; ComPtr<ID3D11DeviceContext> _pDeviceContext = nullptr; ComPtr<IDXGISwapChain> _pSwapChain = nullptr; ComPtr<ID3D11Texture2D> _pRenderTarget = nullptr; ComPtr<ID3D11RenderTargetView> _pRenderTargetView = nullptr; ComPtr<ID3D11DepthStencilState> _pDepthStencilState = nullptr; ComPtr<ID3D11Texture2D> _pDepthStencilTex = nullptr; ComPtr<ID3D11DepthStencilView> _pDepthStencilView = nullptr; ComPtr<ID3D11BlendState> _pBlendState; D3D11_VIEWPORT _viewport; uint32_t _width; uint32_t _height; HWND _hwnd; public: bool Init(uint32_t width, uint32_t height, HWND hwnd); void BeginRender(); void EndRender(); private: bool CreateFactory(); bool CreateDeviceAndSwapChain(); bool CreateDepthStencilBuffer(); bool CreateBlendState(); };
DxManager.cpp
#include "DxManager.h" bool DxManager::Init(uint32_t width, uint32_t height, HWND hwnd) { _width = width; _height = height; _hwnd = hwnd; if (!CreateFactory()) { return false; } if (!CreateDeviceAndSwapChain()) { return false; } if (!CreateDepthStencilBuffer()) { return false; } if (!CreateBlendState()) { return false; } return true; } bool DxManager::CreateFactory() { ComPtr<IDXGIOutput> pOutput; DXGI_ADAPTER_DESC adapterDesc = {}; size_t stringLength; uint32_t numModes = 0; uint32_t GPUMaxMem = 0; uint32_t GPUNum = 0; HRESULT hResult = S_OK; //DXGIファクトリーの作成 hResult = CreateDXGIFactory(IID_PPV_ARGS(_pFactory.GetAddressOf())); if (FAILED(hResult)) { return false; } //GPUを列挙 for (uint32_t i = 0; i < 100; i++) { IDXGIAdapter* adapter; hResult = _pFactory->EnumAdapters(i, &adapter); if (FAILED(hResult)) { break; } //GPUの情報を取得 hResult = adapter->GetDesc(&adapterDesc); if (FAILED(hResult)) { return false; } char videoCardDesc[128]; int error = wcstombs_s(&stringLength, videoCardDesc, 128, adapterDesc.Description, 128); if (error != 0) { break; } uint32_t videoCardMemory = (uint32_t)(adapterDesc.DedicatedVideoMemory / 1028 / 1024); std::cout << "ビデオカード名: " << videoCardDesc << std::endl; std::cout << "ビデオメモリ: " << videoCardMemory << std::endl; hResult = adapter->EnumOutputs(0, pOutput.GetAddressOf()); if (FAILED(hResult)) { continue; } hResult = pOutput->GetDisplayModeList(DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_ENUM_MODES_INTERLACED, &numModes, nullptr); if (FAILED(hResult)) { continue; } //一番メモリが多いGPUを探す if (videoCardMemory > GPUMaxMem) { GPUMaxMem = videoCardMemory; GPUNum = i; } } //GPUを選ぶやでー hResult = _pFactory->EnumAdapters(GPUNum, _pAdapter.GetAddressOf()); if (FAILED(hResult)) { return false; } return true; } bool DxManager::CreateDeviceAndSwapChain() { HRESULT hResult = S_OK; UINT cdev_flags = 0; //デバッグレイヤーを有効にするやでー #ifdef _DEBUG cdev_flags |= D3D11_CREATE_DEVICE_DEBUG; #endif DXGI_MODE_DESC modeDesc = {}; modeDesc.Width = _width; modeDesc.Height = _height; modeDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; modeDesc.RefreshRate.Numerator = 60; modeDesc.RefreshRate.Denominator = 1; modeDesc.Scaling = DXGI_MODE_SCALING_CENTERED; modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); swapChainDesc.BufferCount = 2; swapChainDesc.BufferDesc = modeDesc; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = _hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.Windowed = true; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, }; hResult = D3D11CreateDeviceAndSwapChain( _pAdapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, nullptr, cdev_flags, featureLevels, 4, D3D11_SDK_VERSION, &swapChainDesc, _pSwapChain.GetAddressOf(), _pDevice.GetAddressOf(), &_featurelevel, _pDeviceContext.GetAddressOf()); if (FAILED(hResult)) { return false; } _pAdapter->Release(); _pFactory->Release(); hResult = _pSwapChain->GetBuffer(0, IID_PPV_ARGS(_pRenderTarget.GetAddressOf())); if (FAILED(hResult)) { return false; } hResult = _pDevice->CreateRenderTargetView(_pRenderTarget.Get(), nullptr, _pRenderTargetView.GetAddressOf()); if (FAILED(hResult)) { return false; } _viewport.Width = static_cast<float>(_width); _viewport.Height = static_cast<float>(_height); _viewport.MinDepth = 0.0f; _viewport.MaxDepth = 1.0f; _viewport.TopLeftX = 0; _viewport.TopLeftY = 0; return true; } bool DxManager::CreateDepthStencilBuffer() { D3D11_DEPTH_STENCIL_DESC desc = {}; desc.DepthEnable = true; desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; desc.DepthFunc = D3D11_COMPARISON_LESS; desc.StencilEnable = false; desc.StencilReadMask = D3D11_DEFAULT_STENCIL_READ_MASK; desc.StencilWriteMask = D3D11_DEFAULT_STENCIL_WRITE_MASK; desc.FrontFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; desc.BackFace.StencilFailOp = D3D11_STENCIL_OP_KEEP; HRESULT hResult = _pDevice->CreateDepthStencilState(&desc, _pDepthStencilState.GetAddressOf()); if (FAILED(hResult)) { return false; } D3D11_TEXTURE2D_DESC Tex2Desc = {}; Tex2Desc.Format = DXGI_FORMAT_R24G8_TYPELESS; Tex2Desc.Width = _width; Tex2Desc.Height = _height; Tex2Desc.ArraySize = 1; Tex2Desc.MipLevels = 1; Tex2Desc.BindFlags = D3D11_BIND_DEPTH_STENCIL; Tex2Desc.Usage = D3D11_USAGE_DEFAULT; Tex2Desc.CPUAccessFlags = 0; Tex2Desc.SampleDesc.Count = 1; Tex2Desc.SampleDesc.Quality = 0; Tex2Desc.MiscFlags = 0; hResult = _pDevice->CreateTexture2D(&Tex2Desc, nullptr, _pDepthStencilTex.GetAddressOf()); if (FAILED(hResult)) { return false; } D3D11_DEPTH_STENCIL_VIEW_DESC DSVDesc = {}; DSVDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; DSVDesc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; DSVDesc.Texture2D.MipSlice = 0; DSVDesc.Flags = 0; hResult = _pDevice->CreateDepthStencilView(_pDepthStencilTex.Get(), &DSVDesc, _pDepthStencilView.GetAddressOf()); if (FAILED(hResult)) { return false; } return true; } bool DxManager::CreateBlendState() { D3D11_RENDER_TARGET_BLEND_DESC descRTBS = {}; descRTBS.BlendEnable = true; descRTBS.SrcBlend = D3D11_BLEND_SRC_ALPHA; descRTBS.DestBlend = D3D11_BLEND_INV_SRC_ALPHA; descRTBS.BlendOp = D3D11_BLEND_OP_ADD; descRTBS.SrcBlendAlpha = D3D11_BLEND_ONE; descRTBS.DestBlendAlpha = D3D11_BLEND_ZERO; descRTBS.BlendOpAlpha = D3D11_BLEND_OP_ADD; descRTBS.RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; D3D11_BLEND_DESC descBS = {}; descBS.AlphaToCoverageEnable = true; descBS.IndependentBlendEnable = true; for (uint32_t i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++) { descBS.RenderTarget[i] = descRTBS; } HRESULT hResult = _pDevice->CreateBlendState(&descBS, _pBlendState.GetAddressOf()); if (FAILED(hResult)) { return false; } return true; } void DxManager::BeginRender() { _pDeviceContext->OMSetRenderTargets(1, _pRenderTargetView.GetAddressOf(), _pDepthStencilView.Get()); _pDeviceContext->RSSetViewports(1, &_viewport); float clearColor[4] = { 1.0f, 0.0f, 0.0f, 0.0f }; _pDeviceContext->ClearRenderTargetView(_pRenderTargetView.Get(), clearColor); _pDeviceContext->ClearDepthStencilView(_pDepthStencilView.Get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0); } void DxManager::EndRender() { _pSwapChain->Present(1, 0); }
おまけ(デバイスとスワップチェインを別に作成)
bool DxManager::CreateSwapChain() { HRESULT hResult = S_OK; DXGI_MODE_DESC modeDesc = {}; modeDesc.Width = _width; modeDesc.Height = _height; modeDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB; modeDesc.RefreshRate.Numerator = 60; modeDesc.RefreshRate.Denominator = 1; modeDesc.Scaling = DXGI_MODE_SCALING_CENTERED; modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED; DXGI_SWAP_CHAIN_DESC swapChainDesc = {}; ZeroMemory(&swapChainDesc, sizeof(swapChainDesc)); swapChainDesc.BufferCount = 2; swapChainDesc.BufferDesc = modeDesc; swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; swapChainDesc.OutputWindow = _hwnd; swapChainDesc.SampleDesc.Count = 1; swapChainDesc.SampleDesc.Quality = 0; swapChainDesc.Windowed = true; swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; hResult = _pFactory->CreateSwapChain(_pDevice.Get(), &swapChainDesc, _pSwapChain.GetAddressOf()); if (FAILED(hResult)) { return false; } _pAdapter->Release(); _pFactory->Release(); hResult = _pSwapChain->GetBuffer(0, IID_PPV_ARGS(_pRenderTarget.GetAddressOf())); if (FAILED(hResult)) { return false; } hResult = _pDevice->CreateRenderTargetView(_pRenderTarget.Get(), nullptr, _pRenderTargetView.GetAddressOf()); if (FAILED(hResult)) { return false; } _viewport.Width = static_cast<float>(_width); _viewport.Height = static_cast<float>(_height); _viewport.MinDepth = 0.0f; _viewport.MaxDepth = 1.0f; _viewport.TopLeftX = 0; _viewport.TopLeftY = 0; return true; }