Я пытаюсь выучить Directx. В настоящее время я использую визуальный шаблон студии для игр DirectX. У этого есть две функции, названные CreateResources () и CreateDevice (). В CreateResources () свопчейн сделан, и вы должны поместить весь код рендеринга, который требует доступа к измерениям окна. В CreateDevice () вы помещаете код, который инициализирует переменные рендеринга. Мои вопросы: есть ли способ организовать код так, чтобы весь код рендеринга был вместе, а не разделен между несколькими. Моя идея создания ресурсов состояла в том, чтобы иметь глобальные переменные для высоты и ширины, которые обновляются в каждом кадре функцией CreateResources (). Вот код для обеих функций:
void Game::CreateDevice()
{
UINT creationFlags = 0;
#ifdef _DEBUG
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
static const D3D_FEATURE_LEVEL featureLevels [] =
{
// TODO: Modify for supported Direct3D feature levels
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_3,
D3D_FEATURE_LEVEL_9_2,
D3D_FEATURE_LEVEL_9_1,
};
// Create the DX11 API device object, and get a corresponding context.
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
DX::ThrowIfFailed(D3D11CreateDevice(
nullptr, // specify nullptr to use the default adapter
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
creationFlags,
featureLevels,
_countof(featureLevels),
D3D11_SDK_VERSION,
device.ReleaseAndGetAddressOf(), // returns the Direct3D device created
&m_featureLevel, // returns feature level of device created
context.ReleaseAndGetAddressOf() // returns the device immediate context
));
#ifndef NDEBUG
ComPtr<ID3D11Debug> d3dDebug;
if (SUCCEEDED(device.As(&d3dDebug)))
{
ComPtr<ID3D11InfoQueue> d3dInfoQueue;
if (SUCCEEDED(d3dDebug.As(&d3dInfoQueue)))
{
#ifdef _DEBUG
d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_CORRUPTION, true);
d3dInfoQueue->SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY_ERROR, true);
#endif
D3D11_MESSAGE_ID hide [] =
{
D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
// TODO: Add more message IDs here as needed.
};
D3D11_INFO_QUEUE_FILTER filter = {};
filter.DenyList.NumIDs = _countof(hide);
filter.DenyList.pIDList = hide;
d3dInfoQueue->AddStorageFilterEntries(&filter);
}
}
#endif
DX::ThrowIfFailed(device.As(&m_d3dDevice));
DX::ThrowIfFailed(context.As(&m_d3dContext));
// TODO: Initialize device dependent objects here (independent of window size).
m_states = std::make_unique<CommonStates>(m_d3dDevice.Get());
m_effect = std::make_unique<BasicEffect>(m_d3dDevice.Get());
m_effect->SetVertexColorEnabled(true);
void const* shaderByteCode;
size_t byteCodeLength;
m_effect->GetVertexShaderBytecode(&shaderByteCode, &byteCodeLength);
DX::ThrowIfFailed(
m_d3dDevice->CreateInputLayout(VertexType::InputElements,
VertexType::InputElementCount,
shaderByteCode, byteCodeLength,
m_inputLayout.ReleaseAndGetAddressOf()));
m_batch = std::make_unique<PrimitiveBatch<VertexType>>(m_d3dContext.Get());
}
// Allocate all memory resources that change on a window SizeChanged event.
void Game::CreateResources()
{
// Clear the previous window size specific context.
ID3D11RenderTargetView* nullViews [] = { nullptr };
m_d3dContext->OMSetRenderTargets(_countof(nullViews), nullViews, nullptr);
m_renderTargetView.Reset();
m_depthStencilView.Reset();
m_d3dContext->Flush();
const UINT backBufferWidth = static_cast<UINT>(m_outputWidth);
const UINT backBufferHeight = static_cast<UINT>(m_outputHeight);
const DXGI_FORMAT backBufferFormat = DXGI_FORMAT_B8G8R8A8_UNORM;
const DXGI_FORMAT depthBufferFormat = DXGI_FORMAT_D24_UNORM_S8_UINT;
constexpr UINT backBufferCount = 2;
// If the swap chain already exists, resize it, otherwise create one.
if (m_swapChain)
{
HRESULT hr = m_swapChain->ResizeBuffers(backBufferCount, backBufferWidth, backBufferHeight, backBufferFormat, 0);
if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET)
{
// If the device was removed for any reason, a new device and swap chain will need to be created.
OnDeviceLost();
// Everything is set up now. Do not continue execution of this method. OnDeviceLost will reenter this method
// and correctly set up the new device.
return;
}
else
{
DX::ThrowIfFailed(hr);
}
}
else
{
// First, retrieve the underlying DXGI Device from the D3D Device.
ComPtr<IDXGIDevice1> dxgiDevice;
DX::ThrowIfFailed(m_d3dDevice.As(&dxgiDevice));
// Identify the physical adapter (GPU or card) this device is running on.
ComPtr<IDXGIAdapter> dxgiAdapter;
DX::ThrowIfFailed(dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()));
// And obtain the factory object that created it.
ComPtr<IDXGIFactory2> dxgiFactory;
DX::ThrowIfFailed(dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.GetAddressOf())));
// Create a descriptor for the swap chain.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {};
swapChainDesc.Width = backBufferWidth;
swapChainDesc.Height = backBufferHeight;
swapChainDesc.Format = backBufferFormat;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = backBufferCount;
DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsSwapChainDesc = {};
fsSwapChainDesc.Windowed = TRUE;
// Create a SwapChain from a Win32 window.
DX::ThrowIfFailed(dxgiFactory->CreateSwapChainForHwnd(
m_d3dDevice.Get(),
m_window,
&swapChainDesc,
&fsSwapChainDesc,
nullptr,
m_swapChain.ReleaseAndGetAddressOf()
));
// This template does not support exclusive fullscreen mode and prevents DXGI from responding to the ALT+ENTER shortcut.
DX::ThrowIfFailed(dxgiFactory->MakeWindowAssociation(m_window, DXGI_MWA_NO_ALT_ENTER));
}
// Obtain the backbuffer for this window which will be the final 3D rendertarget.
ComPtr<ID3D11Texture2D> backBuffer;
DX::ThrowIfFailed(m_swapChain->GetBuffer(0, IID_PPV_ARGS(backBuffer.GetAddressOf())));
// Create a view interface on the rendertarget to use on bind.
DX::ThrowIfFailed(m_d3dDevice->CreateRenderTargetView(backBuffer.Get(), nullptr, m_renderTargetView.ReleaseAndGetAddressOf()));
// Allocate a 2-D surface as the depth/stencil buffer and
// create a DepthStencil view on this surface to use on bind.
CD3D11_TEXTURE2D_DESC depthStencilDesc(depthBufferFormat, backBufferWidth, backBufferHeight, 1, 1, D3D11_BIND_DEPTH_STENCIL);
ComPtr<ID3D11Texture2D> depthStencil;
DX::ThrowIfFailed(m_d3dDevice->CreateTexture2D(&depthStencilDesc, nullptr, depthStencil.GetAddressOf()));
CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2D);
DX::ThrowIfFailed(m_d3dDevice->CreateDepthStencilView(depthStencil.Get(), &depthStencilViewDesc, m_depthStencilView.ReleaseAndGetAddressOf()));
// TODO: Initialize windows-size dependent objects here.
}