13. Per-Fragment Operations

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.

Figure 13-1. Per-Fragment Operations Process in Standard Mode

Alpha Test	Stencil Test	Depth Test	Blending	Logical Calculations	Masking the Framebuffer	Framebuffer

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 the glBlendFunc* 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.

Table 13-1. Comparison Functions for the Alpha Test

Setting Value

Comparison

GL_NEVER

Always rejected (never passes).

GL_ALWAYS (default)

Always passes.

GL_LESS

Passes if the alpha value is less than the reference value.

GL_LEQUAL

Passes if the alpha value is less than, or equal to, the reference value.

GL_EQUAL

Passes if the alpha value is equal to the reference value.

GL_GEQUAL

Passes if the alpha value is greater than, or equal to, the reference value.

GL_GREATER

Passes if the alpha value is greater than the reference value.

GL_NOTEQUAL

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.

Table 13-2. Reserved Uniforms Used for the Alpha Test

Reserved Uniform

Type

Setting Value

dmp_FragOperation.enableAlphaTest

bool

Specifies whether to enable or disable the alpha test.

GL_TRUE
GL_FALSE (default)

dmp_FragOperation.alphaRefValue

float

Specifies the reference value to use with the alpha test.

0.0–1.0

0.0 by default.

dmp_FragOperation.alphaTestFunc

int

Specifies the comparison function for the alpha test.

GL_NEVER
GL_ALWAYS (default)
GL_LESS
GL_LEQUAL
GL_EQUAL
GL_GEQUAL
GL_GREATER
GL_NOTEQUAL

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.

Code 13-1. Definition of 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.

Table 13-3. Comparison Functions for the Stencil Test

Setting Value

Comparison

GL_NEVER

Always rejected (never passes).

GL_ALWAYS (default)

Always passes.

GL_LESS

Passes if the reference value is less than the value in the stencil buffer.

GL_LEQUAL

Passes if the reference value is less than, or equal to, the value in the stencil buffer.

GL_EQUAL

Passes if the reference value is equal to the value in the stencil buffer.

GL_GEQUAL

Passes if the reference value is greater than, or equal to, the value in the stencil buffer.

GL_GREATER

Passes if the reference value is greater than the value in the stencil buffer.

GL_NOTEQUAL

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.

Code 13-2. Definition of the glStencilOp Function
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.

Table 13-4. Modifying Stencil Buffer Contents

Setting Value

Stencil Buffer Content

GL_KEEP (default)

Keep the current value.

GL_ZERO

Set the value equal to 0.

GL_REPLACE

Replace the value with the reference value.

GL_INCR

Increment the value by 1. This is never greater than 255.

GL_DECR

Decrement the value by 1. This is never less than 0.

GL_INVERT

Bitwise invert the value.

GL_INCR_WRAP

Increment the value by 1. This wraps to 0 after 255.

GL_DECR_WRAP

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.

Code 13-3. Definition of the glDepthFunc Function
void glDepthFunc(GLenum func); 

For func, specify one of the following eight values.

Table 13-5. Comparison Functions for the Depth Test

Setting Value

Comparison

GL_NEVER

Always rejected (never passes).

GL_ALWAYS

Always passes.

GL_LESS (default)

Passes if the depth value is less than the value in the depth buffer.

GL_LEQUAL

Passes if the depth value is less than, or equal to, the value in the depth buffer.

GL_EQUAL

Passes if the depth value is equal to the value in the depth buffer.

GL_GEQUAL

Passes if the depth value is greater than, or equal to, the value in the depth buffer.

GL_GREATER

Passes if the depth value is greater than the value in the depth buffer.

GL_NOTEQUAL

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).

Code 13-4. Definitions of the glBlendEquation* Functions
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.

Table 13-6. Blending Equations

Setting Value

RGB Components

Alpha Component

GL_FUNC_ADD (default)

R = Rs * Sr + Rd * Dr
G = Gs * Sg + Gd * Dg
B = Bs * Sb + Bd * Db

A = As * Sa + Ad * Da

GL_FUNC_SUBTRACT

R = Rs * Sr + Rd * Dr
G = Gs * Sg + Gd * Dg
B = Bs * Sb + Bd * Db

A = As * Sa - Ad * Da

GL_FUNC_REVERSE_SUBTRACT

R = Rd * Sr - Rs * Dr
G = Gd * Sg - Gs * Dg
B = Bd * Sb - Bs * Db

A = Ad * Sa - As * Da

GL_MIN

R = min( Rs, Rd )
G = min( Gs, Gd )
B = min( Bs, Bd )

A = min( As, Ad )

GL_MAX

R = max( Rs, Rd )
G = max( Gs, Gd )
B = max( Bs, Bd )

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.

Code 13-5. Definitions of the glBlendFunc* Functions
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.

Table 13-7. Source and Destination Blend Factors

Setting Value

Color Blend Factor
(Sr, Sg, Sb) or (Dr, Dg, Db)

Alpha Blend Factor (Sa or Da)

GL_ZERO (default for dstRGB and dstAlpha)

(0, 0, 0)

0

GL_ONE (default for srcRGB and srcAlpha)

(1, 1, 1)

1

GL_SRC_COLOR

(Rs, Gs, Bs)

As

GL_ONE_MINUS_SRC_COLOR

(1, 1, 1) - (Rs, Gs, Bs)

1 - As

GL_DST_COLOR

(Rd, Gd, Bd)

Ad

GL_ONE_MINUS_DST_COLOR

(1, 1, 1) - (Rd, Gd, Bd)

1 - Ad

GL_SRC_ALPHA

(As, As, As)

As

GL_ONE_MINUS_SRC_ALPHA

(1, 1, 1) - (As, As, As)

1 - As

GL_DST_ALPHA

(Ad, Ad, Ad)

Ad

GL_ONE_MINUS_DST_ALPHA

(1, 1, 1) - (Ad, Ad, Ad)

1 - Ad

GL_CONSTANT_COLOR

(Rc, Gc, Bc)

Ac

GL_ONE_MINUS_CONSTANT_COLOR

(1, 1, 1) - (Rc, Gc, Bc)

1 - Ac

GL_CONSTANT_ALPHA

(Ac, Ac, Ac)

Ac

GL_ONE_MINUS_CONSTANT_ALPHA

(1, 1, 1) - (Ac, Ac, Ac)

1 - Ac

GL_SRC_ALPHA_SATURATE

(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.

Code 13-6. Definition of 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.

Code 13-7. Definition of the glLogicOp Function
void glLogicOp(GLenum opcode); 

Specify the logical operation for both the RGB and alpha components, by using the opcode parameter.

Table 13-8. Logical Operations

Setting Value

Operation

C Notation

GL_CLEAR

0

0

GL_AND

s ∧ d

s & d

GL_AND_REVERSE

s ∧ ¬ d

s & ~d

GL_COPY (default)

s

s

GL_AND_INVERTED

¬ s ∧ d

~s & d

GL_NOOP

d

d

GL_XOR

s xor d

s ^ d

GL_OR

s ∨ d

s | d

GL_NOR

¬ (s ∨ d)

~(s | d)

GL_EQUIV

¬ (s xor d)

~(s ^ d)

GL_INVERT

¬ d

~d

GL_OR_REVERSE

s ∨ ¬ d

s | ~d

GL_COPY_INVERTED

¬ s

~s

GL_OR_INVERTED

¬ s ∨ d

~s | d

GL_NAND

¬ (s ∧ d)

~(s & d)

GL_SET

all 1

pow(2, n) - 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.

Code 13-8. Framebuffer Masking Functions
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.


CONFIDENTIAL