Per-fragment operations update the pixel data stored at a fragment's window coordinates in the framebuffer, based on the lighting results and other related data.
This does not mean that all fragments are taken into account. Unnecessary fragments are rejected by tests, such as the alpha test, and then existing pixel data and colors are combined through blending and logical operations.
When the fragment operation mode (mp_FragOperation.mode
) is in standard mode (GL_FRAGOP_MODE_GL_DMP
), per-fragment operations occur as in the process in Figure 13-1.
The 3DS specifications differ from the OpenGL ES 2.0 specifications in the following ways.
- The scissor test is run during rasterization on a CTR system.
- The
glSampleCoverage()
function has not been implemented because multisampling is not supported. - The alpha test provides features equivalent to those in OpenGL ES 1.1, but it is controlled entirely through reserved uniforms.
- The
glStencil*Separate()
functions have not been implemented because the stencil test does not distinguish between front-facing polygons and back-facing polygons. - Logical operators (
GL_LOGIC_OP
) cannot be selected for blending. GL_SRC_ALPHA_SATURATE
can be selected for the destination in theglBlendFunc*
blending functions, even though this is not allowed by the OpenGL ES specifications.- Dithering is not applied.
- Logical operations are implemented to correspond with the OpenGL ES 1.1 specifications.
13.1. Alpha Test
The alpha test compares a fragment's alpha value with a reference value, to determine whether to pass the fragment to the next process or reject it.
The 3DS alpha test has features that correspond to the alpha test in OpenGL ES 1.1, but they are all controlled by reserved uniforms.
13.1.1. Reserved Uniform
The following reserved uniforms are used for the alpha test.
Enabling or Disabling the Alpha Test
To enable the alpha test, set the reserved uniform dmp_FragOperation.enableAlphaTest
to GL_TRUE
, using the glUniform1i()
function. Disabled (set to GL_FALSE
) by default.
Comparison Function
Use the glUniform1i()
function to set the comparison function in the reserved uniform dmp_FragOperation.alphaTestFunc
. You can specify one of the following eight values.
Setting Value |
Comparison |
---|---|
|
Always rejected (never passes). |
|
Always passes. |
|
Passes if the alpha value is less than the reference value. |
|
Passes if the alpha value is less than, or equal to, the reference value. |
|
Passes if the alpha value is equal to the reference value. |
|
Passes if the alpha value is greater than, or equal to, the reference value. |
|
Passes if the alpha value is greater than the reference value. |
|
Passes if the alpha value is not equal to the reference value. |
Reference Value
Use the glUniform1f()
function to set the reference value for the alpha test in the reserved uniform dmp_FragOperation.alphaRefValue
. The reference value is clamped between 0.0 and 1.0 when it is used for comparisons.
The following table lists the reserved uniforms used for the alpha test.
Reserved Uniform |
Type |
Setting Value |
---|---|---|
|
|
Specifies whether to enable or disable the alpha test.
|
|
|
Specifies the reference value to use with the alpha test. 0.0–1.0 0.0 by default. |
|
|
Specifies the comparison function for the alpha test.
|
13.2. Stencil Test
The stencil test compares a reference value with the value stored at a fragment's window coordinates in the stencil buffer to determine whether to pass the fragment to the next process or reject it.
The glStencilFuncSeparate
and glStencilOpSeparate()
functions have not been implemented because the 3DS system does not distinguish between front-facing polygons and back-facing polygons.
13.2.1. How to Use
The stencil test is used in the same way it is used in OpenGL.
Enabling or Disabling the Stencil Test
To enable or disable the stencil test, call the glEnable()
or glDisable()
function, passing GL_STENCIL_TEST
for cap
. To get the current setting, call the glIsEnabled()
function, specifying GL_STENCIL_TEST
for cap
. The stencil test is disabled by default. When it is disabled, the stencil buffer is not changed and fragments are not rejected. If a stencil buffer has not been bound to the framebuffer, the stencil test is treated as if it were disabled. There is no performance difference between when both the stencil test and the depth test are enabled and when only one of the two is enabled.
Comparison Function, Reference Value, and Mask
The stencil test has three elements: the comparison function, reference value, and mask, which are specified by the glStencilFunc()
function.
void glStencilFunc(GLenum func, GLint ref, GLuint mask);
For the ref
parameter, specify an integer to use as the reference value during comparisons. The reference value is handled as an unsigned number when it is compared by the stencil test, and it is clamped between 0 and 255 because the 3DS stencil buffer is always 8-bit. A value of 0 is used by default.
For the mask
parameter, specify the mask. Bitwise AND operations apply the mask to both the reference value and the value in the stencil buffer to get the values to use during comparisons. A value of 0xFFFFFFFF
(all 1s) is used by default.
For the func
parameter, specify the comparison function. You can specify one of the following eight values.
Setting Value |
Comparison |
---|---|
|
Always rejected (never passes). |
|
Always passes. |
|
Passes if the reference value is less than the value in the stencil buffer. |
|
Passes if the reference value is less than, or equal to, the value in the stencil buffer. |
|
Passes if the reference value is equal to the value in the stencil buffer. |
|
Passes if the reference value is greater than, or equal to, the value in the stencil buffer. |
|
Passes if the reference value is greater than the value in the stencil buffer. |
|
Passes if the reference value is not equal to the value in the stencil buffer. |
Handling Test Results
Using the glStencilOp()
function, you can specify how the contents of the stencil buffer are modified as a result of both the stencil test (which compares the reference value with the stencil buffer) and the depth test, which will be described later.
void glStencilOp(GLenum fail, GLenum zfail, GLenum zpass);
The fail
parameter specifies how the contents of the stencil buffer are modified when a fragment is rejected by the stencil test. You can specify one of the following eight values.
Setting Value |
Stencil Buffer Content |
---|---|
|
Keep the current value. |
|
Set the value equal to 0. |
|
Replace the value with the reference value. |
|
Increment the value by 1. This is never greater than 255. |
|
Decrement the value by 1. This is never less than 0. |
|
Bitwise invert the value. |
|
Increment the value by 1. This wraps to 0 after 255. |
|
Decrement the value by 1. This wraps to 255 after 0. |
The zfail
parameter configures how the contents of the stencil buffer are modified when a fragment is rejected by the depth test, and the zpass
parameter configures how the contents of the stencil buffer are modified when a fragment passes the depth test. For these parameters, specify one of the eight values that is valid for the fail
parameter, earlier.
13.3. Early Depth Test
The depth test compares a fragment's depth value with the value stored at the fragment's window coordinates in the depth buffer to determine whether to pass the fragment to the next process or reject it. As explained for the stencil buffer, the results of the depth test can also change the content of the stencil buffer.
13.3.1. How to Use
The depth test is used in the same way it is used in OpenGL.
Enabling or Disabling the Depth Test
To enable or disable the depth test, call the glEnable
or glDisable()
function, specifying GL_DEPTH_TEST
for the cap
parameter. To get the current setting, call the glIsEnabled()
function, specifying GL_DEPTH_TEST
for the cap
parameter. The depth test is disabled by default. When it is disabled, the depth buffer is not modified, and fragments are not rejected. If a depth buffer has not been bound to the framebuffer, the depth test is treated as if it were disabled. There is no performance difference between when both the stencil test and the depth test are enabled and when only one of the two is enabled.
Comparison Function
Use the glDepthFunc()
function to set the comparison function.
void glDepthFunc(GLenum func);
For func
, specify one of the following eight values.
Setting Value |
Comparison |
---|---|
|
Always rejected (never passes). |
|
Always passes. |
|
Passes if the depth value is less than the value in the depth buffer. |
|
Passes if the depth value is less than, or equal to, the value in the depth buffer. |
|
Passes if the depth value is equal to the value in the depth buffer. |
|
Passes if the depth value is greater than, or equal to, the value in the depth buffer. |
|
Passes if the depth value is greater than the value in the depth buffer. |
|
Passes if the depth value is not equal to the value in the depth buffer. |
If a fragment is rejected as a result of the comparison, the depth buffer is not modified. If a fragment passes, its depth value overwrites the value in the depth buffer.
13.4. Blending
Blending combines a fragment's color (the source color) with the color stored at the fragment's window coordinates in the framebuffer (the destination color). The blended result is passed to the next process as the fragment's color.
13.4.1. How to Use
Blending is used in the same way it is used in OpenGL.
Enabling or Disabling Blending
To enable or disable blending, call the glEnable
or glDisable()
function, specifying GL_BLEND
for cap
. To get the current setting, call the glIsEnabled()
function, specifying GL_BLEND
for cap
. Blending is disabled by default. When it is disabled, blending is skipped.
Blending is considered to be disabled, either when a color buffer has not been bound to the framebuffer or when logical operations (described later) are enabled.
Blend Equations
You can use the glBlendEquation
or glBlendEquationSeparate()
function to specify how a fragment's color (the source color) is combined with a framebuffer color (the destination color).
void glBlendEquation(GLenum mode); void glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
The glBlendEquation()
function allows you to specify equations for both the RGB and alpha components by using the mode
parameter.
The glBlendEquationSeparate()
function allows you to specify equations for the RGB and alpha components, separately, using the modeRGB
and modeAlpha
parameters, respectively. All of these parameters accept the following five values.
Setting Value |
RGB Components |
Alpha Component |
---|---|---|
|
R = Rs * Sr + Rd * Dr |
A = As * Sa + Ad * Da |
|
R = Rs * Sr + Rd * Dr |
A = As * Sa - Ad * Da |
|
R = Rd * Sr - Rs * Dr |
A = Ad * Sa - As * Da |
|
R = min( Rs, Rd ) |
A = min( As, Ad ) |
|
R = max( Rs, Rd ) |
A = max( As, Ad ) |
Rs, Gs, Bs, and As represent the source color components.
Rd, Gd, Bd, and Ad represent the destination color components.
Sr, Sg, Sb, and Sa represent the source blend factors.
Dr, Dg, Db, and Da represent the destination blend factors.
GL_LOGIC_OP
, which can be specified in OpenGL ES 2.0, is not supported.
Source and Destination Blend Factors
You can use the glBlendFunc
or glBlendFuncSeparate()
function to specify the blend factors to apply to the source and destination.
void glBlendFunc(GLenum sfactor, GLenum dfactor); void glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
The glBlendFunc()
function allows you to specify both source and destination blend factors using sfactor
and dfactor
. The glBlendFuncSeparate()
function allows you to specify the blend factors for the source RGB and alpha components using srcRGB
and srcAlpha
, and the blend factors for the destination RGB and alpha components using dstRGB
and dstAlpha
. All of these parameters accept the following 15 values.
Setting Value |
Color Blend Factor |
Alpha Blend Factor (Sa or Da) |
---|---|---|
|
(0, 0, 0) |
0 |
|
(1, 1, 1) |
1 |
|
(Rs, Gs, Bs) |
As |
|
(1, 1, 1) - (Rs, Gs, Bs) |
1 - As |
|
(Rd, Gd, Bd) |
Ad |
|
(1, 1, 1) - (Rd, Gd, Bd) |
1 - Ad |
|
(As, As, As) |
As |
|
(1, 1, 1) - (As, As, As) |
1 - As |
|
(Ad, Ad, Ad) |
Ad |
|
(1, 1, 1) - (Ad, Ad, Ad) |
1 - Ad |
|
(Rc, Gc, Bc) |
Ac |
|
(1, 1, 1) - (Rc, Gc, Bc) |
1 - Ac |
|
(Ac, Ac, Ac) |
Ac |
|
(1, 1, 1) - (Ac, Ac, Ac) |
1 - Ac |
|
(f, f, f) |
1 |
Rs, Gs, Bs, and As represent the source color.
Rd, Gd, Bd, and Ad represent the destination color.
Rc, Gc, Bc, and Ac represent the constant color.
f = min(As, 1 - Ad).
The 3DS system also allows you to specify GL_SRC_ALPHA_SATURATE
for the destination.
Constant Color
You can specify the constant color using the glBlendColor()
function.
void glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
Specify each of the RGB and alpha components using the red
, green
, blue
, and alpha
parameters. Specify a floating-point number between 0.0 and 1.0 for each component. By default, they are all 0.0 (0.0, 0.0, 0.0, 0.0).
13.5. Logical Operations
The final per-fragment operation is the logical operation, which is applied to fragment colors and framebuffer colors for an image. The result of the logical operation is written at the fragment's window coordinates in the framebuffer.
13.5.1. How to Use
Logical operations are used in the same way they are used in OpenGL ES 1.1.
Enabling or Disabling Logical Operations
To enable or disable logical operations, call the glEnable
or glDisable()
function, specifying GL_COLOR_LOGIC_OP
for the cap
parameter. To get the current setting, call the glIsEnabled()
function, specifying GL_COLOR_LOGIC_OP
for the cap
parameter. Logical operations are disabled by default. When disabled, logical operations are skipped, but fragment colors are written to the framebuffer. Blending is disabled when logical operations are enabled.
Operation
Use the glLogicOp()
function to specify the logical operation to be performed on the fragment color (the source) and the framebuffer color (the destination). To get the current setting, call the glGetIntegerv()
function, specifying GL_LOGIC_OP_MODE
as the pname
parameter. The default setting is GL_COPY
.
void glLogicOp(GLenum opcode);
Specify the logical operation for both the RGB and alpha components, by using the opcode
parameter.
Setting Value |
Operation |
C Notation |
---|---|---|
|
0 |
0 |
|
s ∧ d |
|
|
s ∧ ¬ d |
|
|
s |
|
|
¬ s ∧ d |
|
|
d |
|
|
s xor d |
|
|
s ∨ d |
|
|
¬ (s ∨ d) |
|
|
¬ (s xor d) |
|
|
¬ d |
|
|
s ∨ ¬ d |
|
|
¬ s |
|
|
¬ s ∨ d |
|
|
¬ (s ∧ d) |
|
|
all 1 |
|
n
is the number of bits in each component.
13.6. Masking the Framebuffer
You can apply a masking operation to the color (RGBA), stencil, and depth values that are written to the framebuffer by per-fragment operations. These values can be configured by the glColorMask
, glStencilMask
, and glDepthMask()
functions, respectively.
void glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha); void glStencilMask(GLuint mask); void glDepthMask(GLboolean flag);
You can specify whether to allow (GL_TRUE
) or deny (GL_FALSE
) the writing of each RGBA color value and depth value. These values are all set to GL_TRUE
by default.
You can modify the stencil masking value. This masking value is independent of the masking value for the stencil test. It is 0xFFFFFFFF
(all 1s) by default.