Per-Sample Processing

From OpenGL.org
Jump to: navigation, search

Per-Sample Processing is a stage of the OpenGL rendering pipeline, where Fragments output from a Fragment Shader are processed, and their resulting data are written to various buffers.

Early operations

The specification states that all of these tests and such happen after the Fragment Shader. However, it is possible for these to be performed before the fragment shader. The following operations are able to be performed before the fragment shader, under certain circumstances:

There are two circumstances when these operations can be performed before the fragment shader. It can happen as an implicit optimization, if OpenGL detects that the fragment shader's execution will not interfere with these tests. Or it can happen if the fragment shader explicitly requests it.

If it happens by explicit request of the fragment shader, then all of these operations will happen first. Also, all writes to these buffers will happen first. Therefore, operations done in the fragment shader that affect such writes will be effectively ignored. For example, executing a discard​ in an early-test fragment shader will not stop the depth or stencil values from being updated (the update is considered part of the test, write masks notwithstanding, nor will it stop the occlusion query counter from being bumped.

OpenGL 4.2 or ARB_shader_image_load_store explicitly requires the pixel ownership test and scissor test to always be performed early, no matter what. Granted, earlier hardware probably did them early anyway, but without Image Load Store functionality, you would never be able to tell the difference (outside of improved performance).

Pixel ownership test

Because the Default Framebuffer is owned by a resource external to OpenGL, it is possible that particular pixels of the default framebuffer are not owned by OpenGL. And therefore, OpenGL cannot write to those pixels. Fragments aimed at such pixels are therefore discarded at this stage of the pipeline.

Generally speaking, if the window you are rendering to is partially obscured by another window, the pixels covered by the other window are no longer owned by OpenGL and thus fail the ownership test.

Note that this test only affects rendering to the default framebuffer. When rendering to a Framebuffer Object, all fragments pass this test.

Scissor test

A rectangular area of the destination framebuffer can be designated as the only valid area for rendering to. All fragments aimed at pixels outside of this rectangle will be discarded at this stage.

Multisample operations

Stencil test

Depth test

Occlusion query updating

If the fragment passed the depth test (and only passing the depth test is checked), then at this point, an active occlusion query will be considered to have had a fragment pass. Therefore, if the query is a GL_SAMPLES_PASSED​ query, the counter will be incremented. If it is one of the boolean queries, the boolean value will be set to true.

Note that reaching this point does not guarantee that any particular value will actually be written to any particular buffer. The write masks below can turn off writing to particular buffers. The framebuffer's draw buffer settings can effectively ignore one or more fragment values. Indeed, a framebuffer object may be empty entirely, with no images attached at all.

Blending

Each of the colors in the fragment can be combined with the corresponding pixel color in the buffer that the fragment will be written to. The result of this blending operation is what will be written.

If the image being read from is in the sRGB colorspace and GL_FRAMEBUFFER_SRGB​ is currently enabled, then the color read for the blending operation will be converted to linear RGB before blending with the fragment color.

sRGB conversion

If the image that a particular fragment color is being written to is in the sRGB colorspace and GL_FRAMEBUFFER_SRGB​ is currently enabled, then the color being written will be converted to sRGB from linear RGB at this point.

Dithering

Logic operations

Write mask

Writes to particular buffers can be masked off. This also allows masking off of particular components of those writes, such that you can only update the red color component if you want. Each output buffer can have its own mask.