OIT using Linked Lists - 2
[Previous post]
I show my implementation here. Refer to the slide and OIT11 sample code for details of each technique. The slide is very useful to understand how linked lists works and it also contains code. You can implement easily after you read the slide.
1. Modify Rendering Flow
In usual rendering, pixels which pass depth test are drawn to a frame buffer directly. In OIT, transparent primitives are not rendered to the frame buffer directly. Instead, all fragments are stored to a large buffer. Each fragment has a color and depth value and belongs to a pixel in the screen. There are multiple fragments per pixel where multiple transparent polygons overlaps. After rendering all transparent primitives, all fragments at a pixel are sorted by its depth and then the blended color is drawn to the frame buffer.
The OIT11 sample stores the fragments to a large buffer in order of pixel address.
For instance, the fragments are stored as follows.
Fragment 1, 2, 3, .... of the pixel[0]
Fragment 1, 2, ... of the pixel[1]
To store fragments like this, before storing fragments, it is necessary to know how many fragments each pixel has and where the fragment should be stored in the large buffer.
The OIT11 sample has 4 phases. You can see the entire phases in OIT::Render.
// Create a count of the number of fragments at each pixel location
CreateFragmentCount( pD3DContext, pScene, mWorldViewProjection, pRTV, pDSV );
// Create a prefix sum of the fragment counts. Each pixel location will hold
// a count of the total number of fragments of every preceding pixel location.
CreatePrefixSum( pD3DContext );
// Fill in the deep frame buffer with depth and color values. Use the prefix
// sum to determine where in the deep buffer to place the current fragment.
FillDeepBuffer( pD3DContext, pRTV, pDSV, pScene, mWorldViewProjection );
// Sort and render the fragments. Use the prefix sum to determine where the
// fragments for each pixel reside.
SortAndRenderFragments( pD3DContext, pDevice, pRTV );
The first and third phases are implemented by pixel shaders and the others by compute shaders.
On the other hand, Linked List OIT stores fragments in order of being drawn. So it requires only 2 passes. Instead of count the number of fragments, it stores fragments as linked lists. All fragments which belong to a certain pixel are in a linked list.
OIT::Render can be rewritten as follows:
// Linked List creation.
CreateFragmentLink( pD3DContext, pRTV, pDSV, pScene, mWorldViewProjection );
// Sort and render the fragments.
SortAndRenderFragments( pD3DContext, pDevice, pRTV );
Both passes are implemented by a pixel shader. The primitives are drawn in the first pass and the second pass is performed by rendering a screen quad.
Linked List OIT does not use Compute shader.
[To be continued...]
