Yakiimo3D

Mostly DirectX 11 Programming

DX11 Order Independent Transparency

Introduction

This is my implementation of the ATI DX11 linked list OIT algorithm. The DirectX11 SDK OIT sample is pretty slow (a compute shader usage sample), but have read from numerous sources that the ATI OIT algorithm is pretty fast (it is), so I decided to try implementing it. Lots of people have already implemented ATI’s linked list OIT and have made public their implementations so I had a lot of good references for my simple implementation.

CodePlex link for my program’s source code and binary are provided at the end of the article.

Relevant Links

1) http://developer.amd.com/documentation/presentations/Pages/default.aspx
ATI’s conference presentation list contains a link to their “GDC 2010: OIT and GI using DX11 linked lists” presentation ppt. This demo is an implementation of the algorithm described in this presentation.

2) http://www4.atword.jp/cathy39/category/direct3d11/oit-direct3d11/
GPU Pro contributor Kaori Kubota-san’s linked list OIT implementation. She walks through the linked list OIT implementation pretty carefully and her explanations are interspersed with source code. Couldn’t find sample code for stuff like D3D11_BUFFER_UAV_FLAG_COUNTER, so her explanations were very helpful. My implementation is based on the ATI presentation ppt and her blog posts.

3) http://orenk2k.blogspot.com/2010/03/oit-order-independent-transparency.html
A blog post about a linked-list OIT implementation. Good explanations.

4) http://sites.google.com/site/monshonosuana/directxno-hanashi-1/directx-110
A Japanese graphics programming website recently posted a linked list OIT implementation. Good explanations (in Japanese) with source code and binary.

5) http://www.uraldev.ru/articles/id/36
Another linked list OIT implementation. Article is in Russian, so I used google translate to read it. Nice article with source code and binary provided. Learned about the implementation from the author’s blog post comment here http://www.wolfgang-engel.info/blogs/?p=116

6) http://joescg.blogspot.com/2010/01/oita-buffer-demo.html
Another Russian OIT implementation. Good explanations read using google translate again. Learned about the implementation from here http://www.geeks3d.com/forums/index.php/topic,861.0.html

7) http://www.yakiimo3d.com/2010/06/19/dx11-high-quality-global-illumination-rendering-using-rasterization/
The DX11 linked list technique can be used to speed up algorithms besides alpha blending. Toshiya Hachisuka-san’s “High-Quality Global Illumination Rendering Using Rasterization” algorithm can be sped up using ATI’s StructuredBuffer linked list technique.

A Screen Captures From My OIT Demo



Regular alpha blending using ID3D11BlendState. Notice that the far section of the blue quad is incorrectly rendered over the red quad. Since each colored quad is drawn in a single draw call, it’s not possible to sort the geometry to get correct alpha blending.



Rendered with the OIT algorithm. In the first pass, all pixel fragments are stored into a large StructuredBuffer. In the 2nd pass, the stored pixel fragments are read and sorted per-pixel inside a pixel shader program and everything is correctly rendered.

Implementation Details

Other websites already explain the linked list OIT algorithm, so not going to do that in this blog post. On my ATI HD5750, with the DirectX SDK OIT sample, I get a fps of around 10 fps at a screen size of 320×240. With my ATI OIT implementation, I get a fps of around 700 fps at a screen size of 640×480. With regular ID3D11BlendState alpha blending, I get a fps around 3000 fps at a screen size of 640×480.

OIT Demo

Source Code & Binary
http://yakiimo3d.codeplex.com/releases/view/49213

Comments

It’s been over 3 months since my last demo. For the past month, I had been feeling somewhat down, but now I feel much better, so maybe I will be more productive. Not sure what I want to implement next. Maybe a translucent material demo based on this OIT demo. Or maybe experiment with DX11 tesselation and implement a DX11 Phong Tesselation demo.

. This entry was posted on Monday, July 19th, 2010 at 12:44 PM and is filed under Demo, DirectX11. You can follow any responses to this entry through the RSS 2.0 feed. You can leave a response, or trackback from your own site.

5 Responses to “DX11 Order Independent Transparency”

  1. DX11 Order Independent Transparency with MSAA | Yakiimo3D Says:

    [...] DX11 Order Independent Transparency [...]

  2. Dave Says:

    Very nice presentation. You gave your references which helps lend huge credibility to the article.

    Have you done any more work on OIT with a bigger model? If I understand the Mecha sample correctly, only certain parts are drawn with OIT.

    Is this technique applicable to Ray Tracing as well?

    Thanks,

    dave

  3. yakiimo02 Says:

    Hi Dave,

    Glad u enjoyed this small article. Yes, I think it’s important to cite references to give proper credit, and plus like you says, it gives my article more credibility.

    Haven’t really continued with OIT. My simple implementation is still a bit too slow and requires too much memory for the benefits it brings I think (at least for games). Much better than using the DX SDK compute shader sample technique though.

    Ray tracing handles transparency naturally as part of its algorithm, so I don’t think it’s useful there.

  4. Dave Says:

    Keep up the excellent DX 11 work :-)

    One question on the OIT sample which I do not understand.

    In rendering the scene, you break up the drawing into 3 different draws (one per quad).

    pd3dImmediateContext->Draw( 4, 0 );

    uOffsets = 4*sizeof( SCENE_VERTEX );
    pd3dImmediateContext->IASetVertexBuffers( 0, 1, &m_pVB, &uStrides, &uOffsets );
    pd3dImmediateContext->Draw( 4, 0 );

    uOffsets = 8*sizeof( SCENE_VERTEX );
    pd3dImmediateContext->IASetVertexBuffers( 0, 1, &m_pVB, &uStrides, &uOffsets );
    pd3dImmediateContext->Draw( 4, 0 );

    In theory this should have been able to be done in one call:

    pd3dImmediateContext->Draw( 12, 0 );

    However, as you probably noticed there are some extra faces produced. Do you know why this happens? Is it a bug in DX11?

    Thanks

    dave

  5. yakiimo02 Says:

    Hi Dave, sorry for the slow reply.

    pd3dImmediateContext->Draw( 12, 0 );

    results in extra geometry because I’m drawing a D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP and not a D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST.

    You’re right that theoretically the OIT algorithm should work with a single draw call and if you change the vertex buffer into a 3*2*3 element triangle list, it draws correctly the alpha sorted quads just fine. Did a quick check locally (for the test kept the vertex buffer, but added a 3*2*3 element indexbuffer and changed the draw call to pd3dImmediateContext->DrawIndexed, but should be the same) and the OIT algorithm worked.

Leave a Reply



XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

It may take some time for your comment to appear, it is not necessary to submit it again.