Thanks for the reply.
I'm not really sure about the correct method to apply msaa when dealing with textures etc.
So basically, what I'd like to do is this:
1. Render the main scene to a full-resolution DXGI_FORMAT_R16G16B16A16_FLOAT-texture (with msaa enabled).
2. Render the volumetric light (that you see in my first post) to a small-resolution texture. MSAA is not really needed here.
3. Render the main scene to the backbuffer (maybe using a HDR/bloom effect later on), by rendering a full-screen quad and texture from step 1.
4. Render the small-resolution texture from step 2 to the backbuffer with a full-screen quad
I've tried to extract what I think is the most relevant code here.
Setting up the swap chain:
// Get data on GPU's support of multisampling
UINT qual_levels[ D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT ] = {0};
for(int i = 1; i < D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; i++) {
hr = dev->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, i, &qual_levels[i]);
if(!FAILED(hr) && qual_levels[i] > 0) {
settings.msaa_count = i;
settings.msaa_quality = qual_levels[i]-1;
}
}
settings.msaa_count = 4;
settings.msaa_quality = qual_levels[settings.msaa_count]-1;
// create a struct to hold information about the swap chain
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd, sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount = 1; // one back buffer
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferDesc.Width = sys.screen_width; // set the back buffer width
scd.BufferDesc.Height = sys.screen_height; // set the back buffer height
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = settings.msaa_count; // how many multisamples
scd.SampleDesc.Quality = settings.msaa_quality;
scd.Windowed = TRUE; // windowed/full-screen mode
scd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH; // allow full-screen switching
Setting up a rasterizer:
// Apply custom rasterizer so we can be sure to get anti-aliasing
D3D11_RASTERIZER_DESC rd;
ZeroMemory(&rd, sizeof(D3D11_RASTERIZER_DESC));
rd.MultisampleEnable = ( settings.msaa_count > 1 );
rd.AntialiasedLineEnable = ( settings.msaa_count > 1 );
rd.FillMode = D3D11_FILL_SOLID;
rd.CullMode = D3D11_CULL_BACK;
rd.DepthClipEnable = true;
hr = dev->CreateRasterizerState(&rd, &pRS);
if( SUCCEEDED(hr)) devcon->RSSetState(pRS);
Depth stencil texture:
// create the depth stencil texture
D3D11_TEXTURE2D_DESC texd;
ZeroMemory(&texd, sizeof(texd));
texd.Width = sys.screen_width;
texd.Height = sys.screen_height;
texd.ArraySize = 1;
texd.MipLevels = 1;
texd.SampleDesc.Count = settings.msaa_count;
texd.SampleDesc.Quality = settings.msaa_quality;
texd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
texd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D *pDepthBuffer;
hr = dev->CreateTexture2D(&texd, NULL, &pDepthBuffer);
if(FAILED(hr)) return false;
// create the depth stencil buffer
D3D11_DEPTH_STENCIL_VIEW_DESC dsvd;
ZeroMemory(&dsvd, sizeof(dsvd));
dsvd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
dsvd.ViewDimension = settings.msaa_count == 1 ? D3D11_DSV_DIMENSION_TEXTURE2D : D3D11_DSV_DIMENSION_TEXTURE2DMS; //D3D11_DSV_DIMENSION_TEXTURE2DMS;
dsvd.Texture2D.MipSlice = 0;
dev->CreateDepthStencilView(pDepthBuffer, &dsvd, &zbuffer);
pDepthBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, zbuffer);
Here is the code used to setup all my render textures:
I've tried turning off multi-sampling here, but then my game crashes on startup. So I guess there is something I should be doing differently to turn off msaa on individual textures.
D3D11_TEXTURE2D_DESC textureDesc;
HRESULT result;
D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc;
D3D11_SHADER_RESOURCE_VIEW_DESC shaderResourceViewDesc;
// Initialize the render target texture description.
ZeroMemory(&textureDesc, sizeof(textureDesc));
// Setup the render target texture description.
textureDesc.Width = textureWidth;
textureDesc.Height = textureHeight;
textureDesc.MipLevels = 1;
textureDesc.ArraySize = 1;
textureDesc.Format = format;
textureDesc.SampleDesc.Count = sys.device->settings.msaa_count;
textureDesc.SampleDesc.Quality = sys.device->settings.msaa_quality;
textureDesc.Usage = D3D11_USAGE_DEFAULT;
textureDesc.BindFlags = D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE;
textureDesc.CPUAccessFlags = 0;
textureDesc.MiscFlags = 0;
// Create the render target texture.
result = sys.device->dev->CreateTexture2D(&textureDesc, NULL, &pRenderTargetTexture);
if(FAILED(result))
{
return false;
}
// Setup the description of the render target view.
renderTargetViewDesc.Format = textureDesc.Format;
renderTargetViewDesc.ViewDimension = sys.device->settings.msaa_count == 1 ? D3D11_RTV_DIMENSION_TEXTURE2D : D3D11_RTV_DIMENSION_TEXTURE2DMS; //D3D11_RTV_DIMENSION_TEXTURE2DMS;
renderTargetViewDesc.Texture2D.MipSlice = 0;
// Create the render target view.
result = sys.device->dev->CreateRenderTargetView(pRenderTargetTexture, &renderTargetViewDesc, &pRenderTargetView);
if(FAILED(result))
{
return false;
}
// Setup the description of the shader resource view.
shaderResourceViewDesc.Format = textureDesc.Format;
shaderResourceViewDesc.ViewDimension = sys.device->settings.msaa_count == 1 ? D3D11_SRV_DIMENSION_TEXTURE2D : D3D11_SRV_DIMENSION_TEXTURE2DMS;// D3D11_SRV_DIMENSION_TEXTURE2DMS;
shaderResourceViewDesc.Texture2D.MostDetailedMip = 0;
shaderResourceViewDesc.Texture2D.MipLevels = 1;
// Create the shader resource view.
result = sys.device->dev->CreateShaderResourceView(pRenderTargetTexture, &shaderResourceViewDesc, &pShaderResourceView);
if(FAILED(result))
{
return false;
}
Here is an extract of my main graphics-draw loop.
rt_xxxx are my render textures.
// Render main 3d scene to texture
rt_scene->SetRenderTarget();
rt_scene->ClearRenderTarget(0,0,0,0);
setShader( SHADER_TYPE_MAIN );
shader_main->updateCbLightSource( matView, matProj );
ID3D11ShaderResourceView *srv = rt_light_shadowmap->GetShaderResourceView();
sys.device->devcon->PSSetShaderResources(1, 1, &srv);
sys.renderScene(true);
// Render volumetric light to small-resolution render texture
rt_small_2->SetRenderTarget();
rt_small_2->ClearRenderTarget(0,0,0,0);
setShader( SHADER_TYPE_VOL_LIGHTING );
sprite_light->Render(0, 0, 0 ); // The model of the light frustum
shader_vol_lighting->render( 18, rt_light_shadowmap->GetShaderResourceView(), rt_depth_map->GetShaderResourceView()); // The shadow-map and depth-map are also just render textures, previously generated
// Render full-screen quads to backbuffer
sys.device->setBackBufferRenderTarget();
sys.device->turnOffAlphaBlending();
sys.device->changeZbufferState(false);
setShader( SHADER_TYPE_TEXTURE );
updateTextureCB( sys.screen_width , sys.screen_height );
full_window->Render(0, 0, rt_scene->GetShaderResourceView() );
shader_texture->render( sizeof(WORD)*6);
// Vol. light
sys.device->turnOffAlphaBlending();
full_window->Render(0, 0, rt_small_2->GetShaderResourceView() );
shader_texture->render( sizeof(WORD)*6);
// Present
swapchain->Present(0, 0);
If I understand it correctly, I should define my rt_scene render texture with msaa and just draw it like I do currently.
On the other hand, my volumetric light render texture (here called rt_small2) should be defined
without msaa. Then, I can resize it and hopefully not get the pixelation.
Is it generally bad to resize textures with msaa?