Я использую класс DirectXTK SpriteBatch для рендеринга спрайтов. Проблема в том, что спрайт мерцает. Я полагаю, это связано с переключением переднего / заднего буфера.
Можно ли избежать этого эффекта мерцания?
Мой код рендеринга выглядит так:
void Render(float elapsedTime)
{
ID2D1DeviceContext* d2dContext = g_devResources->GetD2dDeviceContext();
// Draw sprite
g_SpriteBatch->Begin(SpriteSortMode_Deferred);
{
g_SpriteBatch->Draw(g_texture, XMFLOAT2(10, 75), nullptr, Colors::White);
}
g_SpriteBatch->End();
}
И размер окна зависит от кода инициализации следующим образом:
void DeviceResources::InitWindowSizeDependentResources(HWND hWnd)
{
HRESULT hr;
// Identify the physical adapter (GPU or card) this device is runs on.
ComPtr<IDXGIAdapter> dxgiAdapter;
hr = m_dxgiDevice->GetAdapter(&dxgiAdapter);
if (FAILED(hr))
{
throw std::exception("Identification of IDXGIAdapter failed");
}
// Get the factory object that created the DXGI device.
ComPtr<IDXGIFactory2> dxgiFactory;
hr = dxgiAdapter->GetParent(IID_PPV_ARGS(&dxgiFactory));
if (FAILED(hr))
{
throw std::exception("Get IDXGIFactory2 failed");
}
// Allocate a swap chain descriptor.
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = { 0 };
swapChainDesc.Width = 0; // use automatic sizing
swapChainDesc.Height = 0;
swapChainDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; // this is the most common swapchain format
swapChainDesc.Stereo = false;
swapChainDesc.SampleDesc.Count = 1; // don't use multi-sampling
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 2; // use double buffering to enable flip
swapChainDesc.Scaling = DXGI_SCALING_NONE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; // all apps must use this SwapEffect
swapChainDesc.Flags = 0;
// Get the final swap chain for this window from the DXGI factory.
hr = dxgiFactory->CreateSwapChainForHwnd(
m_d3dDevice.Get(),
hWnd,
&swapChainDesc,
NULL,
NULL,
&m_dxgiSwapChain
);
if (FAILED(hr))
{
throw std::exception("Creation of IDXGISwapChain failed");
}
// Ensure that DXGI doesn't queue more than one frame at a time (minimize power consumption).
hr = m_dxgiDevice->SetMaximumFrameLatency(1);
if (FAILED(hr))
{
throw std::exception("Set MaximumFrameLatency failed");
}
// Get the backbuffer for this window which is be the final 3D render target.
ComPtr<ID3D11Texture2D> backBuffer;
hr = m_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&backBuffer));
if (FAILED(hr))
{
throw std::exception("Get BackBuffer failed");
}
hr = m_d3dDevice->CreateRenderTargetView(backBuffer.Get(), nullptr, &m_d3dRenderTargetView);
// Now we set up the Direct2D render target bitmap linked to the swapchain.
// Whenever we render to this bitmap, it is directly rendered to the
// swap chain associated with the window.
D2D1_BITMAP_PROPERTIES1 bitmapProperties =
D2D1::BitmapProperties1(
D2D1_BITMAP_OPTIONS_TARGET | D2D1_BITMAP_OPTIONS_CANNOT_DRAW,
D2D1::PixelFormat(DXGI_FORMAT_B8G8R8A8_UNORM, D2D1_ALPHA_MODE_IGNORE),
96.0f, // dpi x
96.0f // dpi y
);
// Direct2D needs the dxgi version of the backbuffer surface pointer.
ComPtr<IDXGISurface> dxgiBackBuffer;
hr = m_dxgiSwapChain->GetBuffer(0, IID_PPV_ARGS(&dxgiBackBuffer));
if (FAILED(hr))
{
throw std::exception("Get BackBuffer failed");
}
// Get a D2D surface from the DXGI back buffer to use as the D2D render target.
hr = m_d2dContext->CreateBitmapFromDxgiSurface(
dxgiBackBuffer.Get(),
bitmapProperties,
m_d2dRenderTargetBitmap.GetAddressOf());
if (FAILED(hr))
{
throw std::exception("CreateBitmapFromDxgiSurface failed");
}
// Now we can set the Direct2D render target.
m_d2dContext->SetTarget(m_d2dRenderTargetBitmap.Get());
// tell DirectX how to scale its logical coordinate system to physical display
float dpiX, dpiY;
m_d2dFactory1->GetDesktopDpi(&dpiX, &dpiY);
m_d2dContext->SetDpi(dpiX, dpiY);
// Create depth stencil texture
D3D11_TEXTURE2D_DESC descDepth;
ZeroMemory(&descDepth, sizeof(descDepth));
descDepth.Width = 640;
descDepth.Height = 480;
descDepth.MipLevels = 1;
descDepth.ArraySize = 1;
descDepth.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
descDepth.SampleDesc.Count = 1;
descDepth.SampleDesc.Quality = 0;
descDepth.Usage = D3D11_USAGE_DEFAULT;
descDepth.BindFlags = D3D11_BIND_DEPTH_STENCIL;
descDepth.CPUAccessFlags = 0;
descDepth.MiscFlags = 0;
hr = m_d3dDevice->CreateTexture2D(&descDepth, nullptr, &m_d3dDepthStencil);
if (FAILED(hr))
{
throw std::exception("CreateTexture2D failed");
}
// Create the depth stencil view
D3D11_DEPTH_STENCIL_VIEW_DESC descDSV;
ZeroMemory(&descDSV, sizeof(descDSV));
descDSV.Format = descDepth.Format;
descDSV.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D;
descDSV.Texture2D.MipSlice = 0;
hr = m_d3dDevice->CreateDepthStencilView(m_d3dDepthStencil.Get(), &descDSV, &m_d3dDepthStencilView);
if (FAILED(hr))
{
throw std::exception("CreateDepthStencilView failed");
}
m_d3dContext->OMSetRenderTargets(1, m_d3dRenderTargetView.GetAddressOf(), m_d3dDepthStencilView.Get());
// Setup the viewport
// todo: wozu genau? (eingebaut, damit es in SpriteBatch.End() nicht knallt...)
D3D11_VIEWPORT vp;
vp.Width = 640.0f;
vp.Height = 480.0f;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
m_d3dContext->RSSetViewports(1, &vp);
}
Заранее спасибо!
Задача ещё не решена.