Difference between revisions of "Per-Sample Processing"

From OpenGL.org
Jump to: navigation, search
(Pipeline page link.)
(Adding lots more info.)
Line 1: Line 1:
 
{{pipeline float}}
 
{{pipeline float}}
'''Per-Sample Processing''' is a stage of the [[Rendering Pipeline Overview|OpenGL rendering pipeline]], where fragment data output from a [[Fragment Shader]] is processed and written to various buffers. There are a number of operations that are performed in the order below.
+
'''Per-Sample Processing''' is a stage of the [[Rendering Pipeline Overview|OpenGL rendering pipeline]], where [[Fragment]]s 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 [[Early Fragment Test|before the fragment shader]]. The following operations are able to be performed before the fragment shader, under certain circumstances:
 +
 
 +
* [[#Pixel ownership test|The pixel ownership test]]
 +
* [[#Scissor test|The scissor test]]
 +
* [[#Stencil test|The stencil test]]
 +
* [[#Depth test|The depth test]]
 +
* [[#Occlusion query updating|Occlusion query updating]]
 +
 
 +
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 [[Early Fragment Test#Limitations|fragment shader's execution will not interfere with these tests]]. Or it can happen if the [[Early Fragment Test#Explicit specification|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 {{code|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 mask|write masks notwithstanding]], nor will it stop the occlusion query counter from being bumped.
 +
 
 +
{{require|4.2|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 ==
 
== 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 ==
 
== Scissor test ==
 
{{main|Scissor Test}}
 
{{main|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 ==
 
== Multisample operations ==
 +
{{main|Multisampling}}
  
 
== Stencil test ==
 
== Stencil test ==
Line 16: Line 41:
  
 
== Occlusion query updating ==
 
== Occlusion query updating ==
 +
{{main|Query Object#Occlusion queries}}
  
Fragments at this point are considered to have passed any conditional tests. Thus, their outputs will be written to one or more buffers ([[Write Mask]]s not withstanding). As such, this is the point where the fragment is counted for [[Occlusion Query]] counters. If an occlusion query of type {{enum|GL_SAMPLES_PASSED}} is active, then the query will be incremented every time a fragment hits this stage.
+
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 {{enum|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|write masks below]] can turn off writing to particular buffers. The [[Framebuffer#Draw color buffers|framebuffer's draw buffer]] settings can effectively ignore one or more fragment values. Indeed, a [[Framebuffer Object#Empty framebuffers|framebuffer object may be empty entirely]], with no images attached at all.
  
 
== Blending ==
 
== Blending ==
 
{{main|Blending}}
 
{{main|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'' [[Framebuffer#Colorspace|{{enum|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 ==
 
== sRGB conversion ==
 +
 +
If the image that a particular fragment color is being written to is in the sRGB colorspace ''and'' [[Framebuffer#Colorspace|{{enum|GL_FRAMEBUFFER_SRGB}} is currently enabled]], then the color being written will be converted to sRGB from linear RGB at this point.
  
 
== Dithering ==
 
== Dithering ==
Line 32: Line 66:
 
{{main|Write Mask}}
 
{{main|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.
  
 
{{stub}}
 
{{stub}}
  
 
[[Category:General OpenGL]]
 
[[Category:General OpenGL]]

Revision as of 20:03, 18 August 2013

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.