DX11 Order Independent Transparency with MSAA
I extended my DX11 OIT demo (http://www.yakiimo3d.com/2010/07/19/dx11-order-independent-transparency/) to support MSAA.
CodePlex link for my program’s source code and binary are provided at the end of the article.
Blog article for my original DX11 OIT demo. My original demo has no support for MSAA, so jaggies are very noticeable along the edges of the colored quads.
ATI’s conference presentation list contains a link to their “GDC 2010: OIT and GI using DX11 linked lists” presentation ppt. My original demo and this MSAA supported version are both based on this presentation.
From top to bottom. MSAA none. MSAA 2x. MSAA 4x. MSAA 8x. I notice big quality improvements between none, 2x and 4x, but not too much between 4x and 8x. I think the anti-aliasing starts to look pretty nice around 4x. Notice that with increased sampling, the image quality improves, but the fps also drops.
Not too many changes were necessary to the original demo in order to add MSAA support. The main change was adding the SV_COVERAGE and SV_SAMPLEINDEX semantic parameters to my pixel shader input structures and using their information.
Changes to StoreFragments.hlsl
float4 pos : SV_POSITION;
float4 color : COLOR0;
uint nCoverage : SV_COVERAGE; // Bit set according to which samples are covered.
I added a nCoverage SV_COVERAGE parameter to give me information about which samples are covered by the current fragment. For example, bit 1, 4 of nCoverage are set if samples 1 and 4 are covered. Now, in addition to storing each fragment’s color and depth, I also store the fragment’s sample coverage information.
Changes to SortFragmentsAndRender.hlsl
float4 pos : SV_POSITION;
uint nSampleIndex : SV_SAMPLEINDEX; // specify to run pixel shader per sample instead of per pixel
// Read and store linked list data to the temporary buffer.
while( nNext != 0xFFFFFFFF )
FragmentLink element = FragmentLinkSRV[nNext];
aData[ nNumFragment ] = element.fragmentData;
// Use sample only if the fragment covered it.
if( aData[ nNumFragment ].nDepthAndCoverage & (1<<input.nSampleIndex) )
anIndex[ nNumFragment ] = nNumFragment;
nNext = element.nNext;
The SV_SAMPLEINDEX semantic was added to DX10.1 and can be used in DX11. By adding a pixel shader input parameter with the SV_SAMPLEINDEX semantic, it’s possible to make the pixel shader run once per sample instead of once per pixel. By running the sorting & blending pixel shader per sample and discarding the samples not covered by the fragment, it’s possible to get MSAA anti-aliasing even with the StructuredBuffer input fragment data.
OIT with MSAA Demo
Source Code & Binary
The demo starts with a default setting of 4x MSAA. Open the Change Device menu and change the MSAA setting using the Multisample Count combobox.
This demo was my first time using the SV_SAMPLEINDEX pixel shader semantic and processing pixel per sample instead of per pixel. It’s apparently useful for other stuff such as deferred rendering MSAA, so I’ll probably find myself using it again some time in the future. Also, I bought the XBOX Live Arcade game Limbo and played it while taking a break from writing this blog post. From what I’ve played so far, it’s a dark, but very artistic and beautiful game. So far, I’m glad I bought it.