4
$\begingroup$

Transparency can be achieved (or actually approximated) by using alpha-to-coverage (in case of MSAA) or basic alpha/transparency blending using the following approach:

  1. Bind a rasterizer state with a Less-Equal comparison function.
  2. Bind no blend state.
  3. Render opaque geometry.
  4. Bind alpha-to-coverage or alpha/transparency blend state.
  5. Render transparent geometry.

Here, the sets of opaque and transparent geometry are mutually exclusive. The benefit of this approach is that geometry is only drawn once and the rasterization state does not need to change. Unfortunately, it could be possible to observe, through the semi-transparent holes of some double-sided object, that object itself. In this case there is no guarantee that fragments of this object would be blended with other fragments of this object, since the order in which the fragments are resolved is and should not be known.

Another approach:

  1. Bind a rasterizer state with a Less-Equal comparison function.
  2. Bind no blend state.
  3. Render all geometry and clip transparent fragments
  4. Bind a rasterizer state with a Less comparison function.
  5. Bind alpha-to-coverage or alpha/transparency blend state.
  6. Render transparent geometry.

Here, all transparent geometry is drawn twice. First, opaque fragments are processed by the pixel shader whereas transparent fragments are clipped inside the pixel shader. Second, opaque fragments will be discarded by the early-z-test of the rasterizer whereas transparent fragments are processed by the pixel shader (and blended afterwards).

Both approaches have some differences, but the difference that concerns me the most is the latter approach having two variants of the pixel shader: one that clips transparent fragments and one that does not clip transparent fragments. In case of multiple pixel shaders, this approach will always result in a doubling of the number of pixel shaders. Is it possible to have the benefits of the second approach while having only one variant of the pixel shader?

$\endgroup$
3
$\begingroup$

You can use a threshold set through a constant buffer to clip pixels (ie an alpha test):

float threshold; // in constant buffer

float4 color = myTexture.Sample(...);
if (color.a < threshold)
    discard;

Set threshold to 1.0 to discard all transparent fragments; set it to 0.0 to discard nothing. There will be some minor inefficency in the latter case compared to having a separate pixel shader with the alpha test removed entirely, but it shouldn't be a big deal on most GPUs nowadays.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.