Image Synthesis Transparency
Inter-Object realism Covers different kinds of interactions between objects Increasing realism in the scene Relationships between objects easier to understand Shadows, Reflections, Transparency
Transparency How to handle non-opaque (semi-transparent) objects Multiple fragments contribute to a pixel Visibility order of fragments is important Depth buffer can be used for hidden surface removal but not for semi-transparent objects
Transparency See-through objects Depth test discards objects Object order affects final color Blending non commutative 1 C 1 + (1-1 ) 0 C 0 0 C 0 + (1-0 ) 1 C 1
Transparency General solution Visibility sort all semi-transparent objects in the scene (back to front) Render opaque objects first and update the depth values Render semi-transparent objects in visibility order Apply depth test but do not alter depth values Use alpha-blending in order to obtain linear combination of src and dst color C Dst = (1 - Src ) C Dst + Src C Src
Transparency Opaque Semi-transparent
Transparency without visibility sorting with visibility sorting
Transparency Correct transparency by sorting and alpha-blending
Transparency
Depth peeling Recall: standard depth test gives nearest fragment at each pixel without imposing any order But: there is also a second, third, fragment. Depth test does not provide a means to render the n th nearest surface. Depth peeling solves this problem (in a pixel shader): With n passes over a scene, n layers deeper into the scene are generated E.g. with 2 passes, the nearest and second nearest surfaces are extracted Both the depth and RGBA information is obtained for each layer
Depth peeling The method peels different depth layers in frontto-back order Drawback: as many rendering passes as objects depth complexity: maximum number of surface points (fragments) mapping to one pixel
Depth peeling Reduce/Readback How to determine the depth complexity? Render the scene without depth test and increment the stencil bit (or entries in a texture render target using additive blend) whenever a fragment is generated Reduce the buffer to obtain the maximum In each pass, maximum of 4 texels is computed and stored into 1 texel of output texture Reduce m x m region in fragment shader 1 pass: render quad that covers 1/4 pixels 2 pass: render quad that covers 1/16 pixels
Depth peeling - Queries How to determine the depth complexity while peeling? Employ GPU occlusion query to obtain information (i.e. ask GPU if fragments were rasterized into pixels in the last draw call) Pseudocode bool bkeeppeeling = true while(bkeeppeeling) { } Initialize/Issue occlusion query (to the GPU) Depth peel the next layer (as described in the following) bkeeppeeling = GetQueryResult(); Peels one empty layer, but avoids reduce/readback pass Application has to wait for query result after each peel pass
Depth peeling: Algorithm
Depth peeling issues
Depth peeling Example
Depth peeling back to front Back to front order: Use standard depth test (with op: greater) Discard fragments with depth greater or equal last pass (initialize ping pong depth buffers with depth = 0) (optionally) test with less equal against depth buffer storing opaque geometry (rendered before transparent objects) Blend result onto frame buffer Pro: does not need to store RGBA values for each peel layer
Depth Peeling: Drawbacks As many rendering passes as objects depth complexity Solution Multisampling render target Create up to 8 samples per fragment Each sample has individual stencil value Stencil-routed k-buffer (requires #depth layers / 8 rendering passes) Ideal for complex geometry, much faster than depth peeling
Stencil Routed A-Buffer What we need: A fragment list per pixel MSAA (multi-sampled anti-aliasing) List of samples per pixel Samples store coverage Fragments are rasterized at higher frame buffer resolution 8xMSAA = 8 x aliased resolution Pixel shader is run once per-pixel Frame buffer storage is at sample resolution
K-buffer But: Need to write only 1 sample at once Need all MSAA samples at pixel center MSAA sample patterns don t help Solution: Turn off multisampling but still render to MSAA render target Pixel shader output stored in all sub-samples now writing 8 samples per pixel (but all samples contain the same value)
Stencil Routing and MSAA 5 8 2 3 7 4 6 9 4 7 1 2 6 3 5 8 3 6 0 1 5 2 4 7 2 5 0 0 4 1 3 6 stencil always decrements (stencil pass and fail op = decrement) stencil passes when 2 (stencil reference value)
Stencil buffer initialization Clear stencil buffer to pass value (2) initializes sample 0 to 2 Use sample mask to selectively set other subsamples (to reference value) 5 samples filled Why start at 2? When all n subsamples are filled: (n-1) stencil values will be 0 and one stencil value 1 Overflow occured if all stencil values are 0! 8 samples filled overflow occured
K-buffer Now 8 samples per pixel If we need more: multipass rendering (or render to texture array) Start with different initial stencil mask to skip first 8n fragments Up to 254 layers (due to 8 bit stencil values) Sort these samples in depth order and blend them Can be done in one fragment shader pass