11. Texture Processing

The 3DS system can perform texture processing operations equivalent to those in OpenGL ES 2.0, but there are several CTR-specific restrictions.

11.1. Texture Unit

Four texture units (TEXTURE0 through TEXTURE3) are installed on the 3DS system, but each one can handle different types of textures. A rasterizer can independently output up to three sets of texture coordinates to the texture units. To output texture coordinates to all four texture units, TEXTURE2 or TEXTURE3 must share the same texture coordinates with other texture units.

Table 11-1. Textures Supported by the Texture Units

Texture
Unit

2D
Textures

Cube Map
Textures

Shadow
Textures

Projection
Textures

Procedural
Textures

TEXTURE0

 

TEXTURE1

 

 

 

 

TEXTURE2

 

 

 

 

TEXTURE3

 

 

 

 

One- and three-dimensional textures are not supported. Cube map textures, shadow textures, projection textures, and other textures that require the w component can only be processed by TEXTURE0. TEXTURE3 is a unit used exclusively for procedural textures. GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS defines the number of installed texture units to be 4.

11.1.1. Texture Coordinate Input

Only texture unit 0 can accept the w component as input; the other texture units only allow two input components, u and v. A projection texture is simply a 2D texture with its w component enabled, but care must be taken with the coordinates output by the vertex shader because the generated UV coordinates are divided by the w component.

To send texture coordinates from the vertex shader, map output registers to the attribute names texture0, texture0w, texture1, and texture2. texture0w must be output for cube map textures, shadow textures, projection textures, and anything else that requires the w component. If it is not output, texture coordinate 0's output is undefined. texture0w output is ignored for textures that do not require the w component.

Table 11-2. Attribute Names and Corresponding Texture Coordinates

Attribute Name

Attributes Sent From the Vertex Shader

texture0

UV components of texture coordinate 0.

texture0w

W component of texture coordinate 0.

texture1

UV components of texture coordinate 1.

texture2

UV components of texture coordinate 2.

11.1.1.1. Texture Coordinate Precision

Within a texture unit, texture coordinates are represented as 16-bit values combining an integer and decimal component. The number of decimal bits decreases as the absolute value of the integer component increases.

The accuracy of texture sampling depends on the decimal bit precision. A texture can be sampled, optimally, if there are enough decimal bits to represent its width and height in texels. Allocate another six decimal bits for bilinear filtering.

11.1.2. How to Use

To enable or disable a texture unit in OpenGL, specify an argument such as TEXTURE_2D to parameters glEnable and glDisable. On the 3DS system, however, set the reserved uniform dmp_Texture[i].samplerType (where i is the texture unit number). Behavior is undefined if you call glEnable or glDisable using the GL_TEXTURE_2D argument.

To disable a texture unit, call glUniform1i, and pass GL_FALSE to set a reserved uniform value. Each texture unit is enabled by different reserved uniform settings.

Table 11-3. Settings for the Reserved Uniforms dmp_Texture[i].samplerType

Reserved Uniform

Value to Set

Supported Textures

dmp_Texture[0].samplerType

GL_FALSE

Disabled (default).

GL_TEXTURE_2D

2D textures

GL_TEXTURE_CUBE_MAP

Cube-map texture.

GL_TEXTURE_SHADOW_2D_DMP

Shadow textures.

GL_TEXTURE_SHADOW_CUBE_DMP

Cube map shadow textures.

GL_TEXTURE_PROJECTION_DMP

Projection textures

dmp_Texture[1].samplerType

GL_FALSE

Disabled (default).

GL_TEXTURE_2D

2D textures

dmp_Texture[2].samplerType

GL_FALSE

Disabled (default).

GL_TEXTURE_2D

2D textures

dmp_Texture[3].samplerType

GL_FALSE

Disabled (default).

GL_TEXTURE_PROCEDURAL_DMP

Procedural textures

Texture units 0 and 1 both have fixed texture coordinate input: texture coordinates 0 and 1, respectively. Texture units 2 and 3 must have their texture coordinate input specified by the reserved uniform dmp_Texture[i].texcoord (where i is the texture unit number 2 or 3). Each texture unit allows different reserved uniform settings. When all four texture units are used, texture unit 2 or 3 must share its input texture coordinates with another texture unit.

Color values input to the texture combiner are undefined when the texture combiner accesses a disabled texture unit.

Table 11-4.Settings for the Reserved Uniforms dmp_Texture[i].texcoord

Reserved Uniform

Value to Set

Texture Coordinate Used as Input

dmp_Texture[2].texcoord

GL_TEXTURE1

Texture coordinate 1

GL_TEXTURE2

Texture coordinate 2 (default).

dmp_Texture[3].texcoord

GL_TEXTURE0

Texture coordinate 0 (default).

GL_TEXTURE1

Texture coordinate 1

GL_TEXTURE2

Texture coordinate 2

Unless they are configured using reserved uniforms, texture unit settings apply to the texture unit specified by the glActiveTexture() function.

Code 11-1. Definition of the glActiveTexture Function
void glActiveTexture(GLenum texture); 

For texture you can specify GL_TEXTURE0, GL_TEXTURE1, or GL_TEXTURE2. A GL_INVALID_ENUM error is generated when some other value, or GL_TEXTURE3 (texture unit 3), is specified.

Reserved uniforms are used for all procedural texture settings.

11.1.3. Specifying Textures to Use

To specify the texture to use with a texture unit, first specify the texture unit using the glActiveTexture() function, and then specify the texture object using the glBindTexture() function.

If you want to use a different texture for each texture unit, call the glActiveTexture and glBindTexture() functions, as shown in the following sample code.

Code 11-2. Specifying a Texture for Each Texture Unit
// Texture Unit0
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, imageTexID);
// Texture Unit1
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, bumpTexID); 

11.1.4. Texture Parameters

Use the glTexParameter*() functions to add parameters to a texture, such as the texture wrapping mode and filters.

Code 11-3. Definition of the glTexParameter* Functions
void glTexParameterf(GLenum target, GLenum pname, GLfloat param);
void glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
void glTexParameteri(GLenum target, GLenum pname, GLint param);
void glTexParameteriv(GLenum target, GLenum pname, const GLint* params); 

The glTexParameteri() function adds parameters passed in as integers and the glTexParameterf() function adds parameters passed in as floating-point numbers. Functions with names that end in v are used to add parameters that must be passed as vectors (arrays).

For target specify the same value specified in the glTexImage2D() function (Table 7-2). pname is the name of the parameter to add and param is the parameter value. Unique parameters have been added for 3DS.

The 3DS system gets up to eight texels for a single fragment when filtering.

Table 11-5. Parameters Added for pname

pname

int / float / vector

Added Parameter

GL_TEXTURE_WRAP_S

int

Wrapping mode in the S direction (Table 11-6).

GL_TEXTURE_WRAP_T

int

Wrapping mode in the S direction (Table 11-6).

GL_TEXTURE_MIN_FILTER

int

Minification filter (Table 11-7).

GL_TEXTURE_MAG_FILTER

int

Magnification filter (Table 11-8).

GL_TEXTURE_BORDER_COLOR

vec4(float)

The border color to use when the wrapping mode is GL_CLAMP_TO_BORDER (each component is between 0.0 and 1.0).

GL_TEXTURE_LOD_BIAS

float

LOD bias (-16.0 through 16.0. The default is 0.0.) Default value: 0.0

GL_TEXTURE_MIN_LOD

int

Minimum LOD (-1000 by default.)

GL_GENERATE_MIPMAP

int(bool)

Automatic mipmap texture generation (GL_FALSE by default). For more information, see 11.1.4.1. Automatic Generation of Mipmap Textures.

The following values specify the wrapping mode in the S and T directions.

Table 11-6. Specifying the Wrapping Mode in the S and T Directions

param

Description

GL_REPEAT

Repeat (default).

GL_MIRRORED_REPEAT

Flip and repeat.

GL_CLAMP_TO_EDGE

Use the color at the edge of the texture image for texture coordinates that are not in the range from 0.0 through 1.0.

GL_CLAMP_TO_BORDER

Use the border color for texture coordinates that are not in the range from 0.0 through 1.0.

The following values specify the filters to use when rendering texture images that have been scaled down.

Table 11-7. Specifying Minification Filters

param

Description

GL_NEAREST

Use the color of the nearest texel (default).

GL_LINEAR

Use bilinear sampling (the average of four samples) to determine the color.

GL_NEAREST_MIPMAP_NEAREST

Select the nearest mipmap texture, and then use the color of the nearest texel.

GL_NEAREST_MIPMAP_LINEAR

Select two mipmap texture levels, and then interpolate between the nearest colors at each level.

GL_LINEAR_MIPMAP_NEAREST

Select the nearest mipmap texture, and then use bilinear sampling to determine the color.

GL_LINEAR_MIPMAP_LINEAR

Select two mipmap texture levels, and then interpolate between the bilinearly sampled colors at each level.

The following values specify the filters to use when rendering texture images that have been scaled up.

Table 11-8. Specifying Magnification Filters

param

Description

GL_NEAREST

Use the color of the nearest texel (default).

GL_LINEAR

Use bilinear sampling (the average of four samples) to determine the color.

11.1.4.1. Automatic Generation of Mipmap Textures

When the texture parameter GL_GENERATE_MIPMAP is GL_TRUE and a value of -2 or less is passed to level in the glTexImage2D(), glCopyTexImage2D(), or glCopyTexSubImage2D() function, mipmap textures are automatically generated for all but the lowest mipmap level. However, texture formats (combinations of the format and type parameters) apply the following restrictions to the minimum width and height of mipmap textures that are automatically generated.

Table 11-9. Minimum Width and Height of Automatically Generated Mipmap Textures

Format

format

type

Minimum Width and Height

RGBA4

GL_RGBA
GL_RGBA_NATIVE_DMP

GL_UNSIGNED_SHORT_4_4_4_4

64

RGBA5551

GL_RGBA
GL_RGBA_NATIVE_DMP

GL_UNSIGNED_SHORT_5_5_5_1

64

RGBA8

GL_RGBA
GL_RGBA_NATIVE_DMP

GL_UNSIGNED_BYTE

32

RGB565

GL_RGB
GL_RGB_NATIVE_DMP

GL_UNSIGNED_SHORT_5_6_5

64

RGB8

GL_RGB
GL_RGB_NATIVE_DMP

GL_UNSIGNED_BYTE

32

Even if two textures have the same width and height, the range of values that can be specified for level differ, if the texture formats have different minimum values. A GL_INVALID_OPERATION error is generated when you specify the automatic generation of a mipmap texture smaller than the minimum size. For a texture that is 128×128 texels, for example, you can specify a level of -2 or -3 when the format is RGB8, but you can only specify -2 for level when the format is RGB565.

When enabled, automatically generated mipmap textures take priority. The mipmap texture data loaded with a texture image is ignored.

With automatic generation enabled, level for the glCopyTexImage2D() and glCopyTexSubImage2D() functions must have the same value as was passed to level for the glTexImage2D() function when the texture was loaded. A GL_INVALID_OPERATION error is generated if these values differ. However, even if a nonzero value is passed to level, data is copied to the texture with the lowest level, and the mipmap texture is not replaced.

With automatic generation disabled, level for the glCopyTexImage2D() and glCopyTexSubImage2D() functions must be 0, regardless of the value that was passed to level for the glTexImage2D() function when the texture was loaded. A GL_INVALID_OPERATION error is generated if a nonzero value is specified.

11.1.4.2. Cautions for Specifying GL_NEAREST as the Filter

If you set the GL_TEXTURE_MIN_FILTER and GL_TEXTURE_MAG_FILTER texture parameters to GL_NEAREST and use a texture image with vertical or horizontal lines (including color boundaries that form straight lines), when the texture is applied to polygons that place those stripes horizontally or perpendicular to the screen's scan lines, the straight lines may appear as broken lines.

This phenomenon is caused by the computational precision of texture coordinate interpolation within polygons. Consider a row of fragments that is horizontal or perpendicular to the scan lines. If each fragment samples texels in a single vertical or horizontal line, the straight lines on the texture image are rendered unchanged on the polygons. If each of these fragments sample around the boundary between two adjacent rows of texels, however, each fragment will sample a different texel row due to texture coordinate errors. As a result, the straight line on the texture image is rendered as a broken line on the polygons. You can work around this by adjusting the texture coordinates and rendering area so that each fragment samples the texel centers, just as when a rectangular polygon with texture coordinates of 0 and 1 at its edges is rendered using the same size as a texture.

11.1.4.3. Cautions for Specifying GL_XXX_MIPMAP_LINEAR as a Minification Filter

Trilinear filtering is enabled when GL_XXX_MIPMAP_LINEAR is set for the texture parameter GL_TEXTURE_MIN_FILTER. This interpolates colors from two mipmap texture levels and then renders with the resulting color. However, this interpolation is subject to errors caused by computational precision. For example, even if two colors with the same component values are processed, a different color could be rendered due to these minor errors.

Colors are interpolated when, as a result of LOD calculations, they must be obtained from two mipmap texture levels. Colors are not interpolated when they are obtained from only one mipmap texture level. A texture is slightly darker where colors are interpolated than where colors are not. This causes differences in hue to be rendered as edges along mipmap level boundaries.

You can mitigate this effect by using fixed component values in a texel color. For example, a texture in the GL_RGB format has a fixed alpha component of 1.0, but even this fixed component value decreases slightly for texels that have been interpolated by trilinear filtering. Nonetheless, this component retains its value of 1.0 in texels that have not been interpolated. To correct a texture color, multiply it by the change in alpha value caused by interpolation, and then add this product to the texture color.

Texture combiners can make this correction, as shown in the following sample code. The following code shows an example of the setting.

Code 11-4. Compensating for Trilinear Filtering
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[0].combineRgb"), 
        GL_MULT_ADD_DMP);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].operandRgb"), 
        GL_SRC_COLOR, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].srcRgb"), 
        GL_TEXTURE0, GL_TEXTURE0, GL_TEXTURE0); 

Wherever colors are not interpolated, these settings result in a product of 0 and output the original texture color. Wherever colors are interpolated, these settings multiply the texture color and the difference in the alpha component, add this product to the texture color, and finally output the corrected color. You can only apply these settings to the first texture combiner (combiner 0) because they specify a texture color for every input source.

If you are using a texture format without fixed component values, such as GL_RGBA, prepare a separate texture with fixed component values and use that as a multitexture to perform the correction. This texture must have the same size, number of mipmap levels, and UV input values as the original texture. We recommend using an ETC1-compressed texture for data size and cache efficiency reasons.

11.1.4.4. Getting Texture Level (Mipmap) Parameters

You can use the following functions to get parameters for each mipmap level of textures bound to texture units that are currently active. However, you cannot get information about procedural textures because the texture unit for procedural textures (GL_TEXTURE3) cannot be specified to the glActiveTexture() function.

Code 11-5. Getting Texture Level Parameters
void glGetTexLevelParameterfv(GLenum target, GLint level, GLenum pname,
                              GLfloat *params);
void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname,
                              GLint *params); 

Both functions get the same values, even though they are saved as different types.

Specify the type of texture in target. You can specify the following values.

Table 11-10. Specifying the Types of Textures to Get Texture Level Parameters For

target Value

Type of Texture

GL_TEXTURE_2D

2D texture (including shadow and gas textures).

GL_TEXTURE_CUBE_MAP_POSITIVE_X

Cube-map texture (in the positive X direction).

GL_TEXTURE_CUBE_MAP_NEGATIVE_X

Cube-map texture (in the negative X direction).

GL_TEXTURE_CUBE_MAP_POSITIVE_Y

Cube-map texture (in the positive Y direction).

GL_TEXTURE_CUBE_MAP_NEGATIVE_Y

Cube-map texture (in the negative Y direction).

GL_TEXTURE_CUBE_MAP_POSITIVE_Z

Cube-map texture (in the positive Z direction).

GL_TEXTURE_CUBE_MAP_NEGATIVE_Z

Cube-map texture (in the negative Z direction).

Specify the mipmap level to get in level. When level is 0, you get the parameter for the texture at the lowest mipmap level (the largest texture). You can get the next level and the one after that by specifying 1 and 2, respectively, for level.

Specify the type of parameter to get in pname. The following table shows how the value of pname corresponds to the parameter stored in params.

Table 11-11. Specifying Texture Level Parameters to Get

pname Value

Parameters

GL_TEXTURE_WIDTH

Texture width (in texels).

GL_TEXTURE_HEIGHT

Texture height (in texels).

GL_TEXTURE_DEPTH

Unsupported; has a fixed value of 0.

GL_TEXTURE_INTERNAL_FORMAT

A texture’s internal format.

GL_TEXTURE_BORDER

Unsupported; has a fixed value of 0.

GL_TEXTURE_RED_SIZE

Number of bits in the red component (per texel).

GL_TEXTURE_GREEN_SIZE

Number of bits in the green component (per texel).

GL_TEXTURE_BLUE_SIZE

Number of bits in the blue component (per texel).

GL_TEXTURE_ALPHA_SIZE

Number of bits in the alpha component (per texel).

GL_TEXTURE_LUMINANCE_SIZE

Number of bits in the luminance component (per texel).

GL_TEXTURE_INTENSITY_SIZE

Number of bits in the intensity component (per texel). Only for shadow textures.

GL_TEXTURE_DEPTH_SIZE

Number of bits in the depth component (per texel). Only for shadow textures.

GL_TEXTURE_DENSITY1_SIZE_DMP

Number of bits (per texel) of density information (density value 1) that does not account for intersections. Only for gas textures.

GL_TEXTURE_DENSITY2_SIZE_DMP

Number of bits (per texel) of density information (density value 2) that does account for intersections. Only for gas textures.

GL_TEXTURE_COMPRESSED

Whether a texture is compressed.

GL_TRUE: Compressed texture
GL_FALSE: Uncompressed texture

GL_TEXTURE_COMPRESSED_IMAGE_SIZE

Number of bytes in the texture at the mipmap level specified by level. Only for compressed textures. Specifying an uncompressed texture results in a GL_INVALID_OPERATION error.

The following table shows how the number of bits in each component for a single texel corresponds to the internal format of textures obtained when GL_TEXTURE_INTERNAL_FORMAT is specified for pname.

Table 11-12. Internal Formats and the Number of Bits in Components Making Up Each Texel

Internal Format

Red

Green

Blue

Alpha

Luminance

Intensity

Depth

Density 1

Density 2

GL_RGBA4

4

4

4

4

 

 

 

 

 

GL_RGB5_A1

5

5

5

1

 

 

 

 

 

GL_RGBA

8

8

8

8

 

 

 

 

 

GL_RGB565

5

6

5

 

 

 

 

 

 

GL_RGB

8

8

8

 

 

 

 

 

 

GL_ALPHA

 

 

 

8

 

 

 

 

 

GL_ALPHA4_EXT

 

 

 

4

 

 

 

 

 

GL_LUMINANCE

 

 

 

 

8

 

 

 

 

GL_LUMINANCE4_ EXT

 

 

 

 

4

 

 

 

 

GL_LUMINANCE_ALPHA

 

 

 

8

8

 

 

 

 

GL_LUMINANCE4_ALPHA4_EXT

 

 

 

4

4

 

 

 

 

GL_SHADOW_DMP

 

 

 

 

 

8

24

 

 

GL_GAS_DMP

 

 

 

 

 

 

 

16

16

GL_HILO8_DMP

8

8

 

 

 

 

 

 

 

GL_ETC1_RGB8_NATIVE_DMP

8

8

8

 

 

 

 

 

 

GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP

8

8

8

4

 

 

 

 

 

A GL_INVALID_ENUM error is generated when an invalid value is specified for target and pname. A GL_INVALID_VALUE error is generated when the mipmap level specified for level has not been loaded.

11.1.5. Effects of Texture Settings on Performance

Graphics performance is affected by texture format and size, and by various settings. The following is a list of common tendencies.

  • Compressed textures are processed the fastest, followed by formats that use a small number of bytes per texel.
  • Processing speed increases as the size decreases.
  • Contention for memory access causes processing to slow as the number of textures used simultaneously increases.
  • The following pairs of minification filter settings are each processed at the same speed:GL_NEAREST and GL_LINEARGL_NEAREST_MIPMAP_NEAREST and GL_LINEAR_MIPMAP_NEARESTGL_NEAREST_MIPMAP_LINEAR and GL_LINEAR_MIPMAP_LINEAR. However, because GL_NEAREST(_XXX) fetches 1 texel per pixel and GL_LINEAR(_XXX) fetches 4 texels per pixel, GL_NEAREST(_XXX) uses less memory.
  • It is faster to apply scaled-down textures using mipmaps. Even when mipmaps are used, however, the processing load depends on the filter settings. GL_*_MIPMAP_LINEAR may entail approximately twice the processing load of GL_*_MIPMAP_NEAREST.
  • Although the GL_NEAREST and GL_LINEAR magnification filters have nearly the same performance, GL_NEAREST is slightly faster in some cases.
  • Gas and shadow textures cannot use mipmaps and are processed more slowly than normal textures.
  • Shadow textures make use of special filters for shadows, so there is a processing load comparable to trilinear filtering (when GL_*_MIPMAP_LINEAR is set as the minification filter for normal textures). The processing load is around twice that for a normal texture (excluding trilinear filtering).
  • There are no differences caused by conditions for setting procedural textures. They are faster to process than normal 2D textures.
  • When multiple textures are used, they are processed more quickly if they are all placed in VRAM-A or VRAM-B, rather than split between the two.
  • Textures created to match the upward direction of the framebuffer can sometimes process faster than textures created to match the upward direction of the rendering results. This is because the direction in which fragments are generated matches the direction in which textures are loaded, improving the texture cache hit rate. Flipping a texture vertically has no effect on performance. Fragments are processed horizontally in 8×8-pixel units, whereas textures are loaded in 8×4-texel units. Note also that the short sides of the 3DS's LCD screen are used as the top and bottom.

 

11.1.6. Texture Cache

There is a 256-byte L1 texture cache and an 8-KB L2 texture cache. Within a cache, only compressed textures (in the ETC format) are handled unchanged. All other textures (including those in the alpha ETC format) are converted into a 32-bit format.

There is a separate L1 cache for each texture unit, but the L2 cache is shared by all texture units.

There is a 5-cycle penalty for missing the L1 cache and, instead, getting data from the L2 cache. There is an additional penalty of approximately 30 cycles for missing the L2 cache and instead getting data from VRAM. However, the hardware is implemented to prefetch texels to hide these delays.

Texture caches have a 4-way set-associative format. There are 16 cache lines. The L2 cache is 8 KB, with 512 bytes per cache line.

A cache line is the lower 4 bits of a 8x4 block address (a 4x4 texel unit address divided by 2) calculated from the texture coordinate values. In ETC1, this is the value of the [5:2] bit of the address of the block unit in which 2x2 of the 4x4 texel blocks are arranged. Cache thrashing occurs when the same cache line is continuously accessed.

11.2. Combiners

There are six (texture) combiners installed on the 3DS system. They can combine the primary and secondary colors for fragment lighting, in addition to the colors output by texture units, such as the texture color, vertex color, and constant color. If you have experience developing applications for the Nintendo GameCube and Wii, you can more easily understand this effect if you imagine it as combining color and alpha values by using the TEV.

OpenGL ES 1.1 uses TexEnv for combiner settings, but the 3DS system uses reserved uniforms. The following table shows the reserved uniforms that correspond to TexEnv parameters.

Table 11-13. Reserved Uniforms Corresponding to TexEnv Parameters in OpenGL ES 1.1

TexEnv

Reserved Uniform

Setting

COMBINE_RGB

dmp_TexEnv[i].combineRgb

Color combiner function.

COMBINE_ALPHA

dmp_TexEnv[i].combineAlpha

Alpha combiner function.

SRCn_RGB

dmp_TexEnv[i].srcRgb

Color source.

SRCn_ALPHA

dmp_TexEnv[i].srcAlpha

Alpha source.

OPERANDn_RGB

dmp_TexEnv[i].operandRgb

Color operands.

OPERANDn_ALPHA

dmp_TexEnv[i].operandAlpha

Alpha operands.

RGB_SCALE

dmp_TexEnv[i].scaleRgb

Color scaling value.

ALPHA_SCALE

dmp_TexEnv[i].scaleAlpha

Alpha scaling value.

TEXTURE_ENV_COLOR

dmp_TexEnv[i].constRgba

Constant color (with an alpha component).

Where n is the source (from 0 through 2) and i is the combiner number (from 0 through 5).

Each combiner processes its three source inputs as operands in its combiner function, multiplies the calculated result by a scaling value, and clamps the value between 0.0 and 1.0 before outputting it. Also, 0.0 to 1.0 are clamped before input is computed in the combiner, and the clamped value is a result of a rasterized absolute value for the vertex color (primary color).

Color operations are performed on all components (red, green, and blue) using a single setting, and alpha operations are performed on the alpha component using a separate setting. Color values input to the texture combiner are undefined when the texture combiner accesses a disabled texture unit.

Figure 11-1. Combiner Options

srcRgb0 srcRgb1 srcRgb2 operandRgb0 operandRgb1 operandRgb2 CombineRgb srcAlpha0 srcAlpha1 srcAlpha2 operandAlpha0 operandAlpha1 operandAlpha2 CombineAlpha scaleRgb scaleAlpha Input Output

A combiner accepts three input sources. Each input source must be one of the following types (a single type can be used for more than one input).

  • Texture color output by a texture unit.
  • Constant color.
  • Primary color.
  • Primary color for fragment lighting.
  • Secondary color for fragment lighting.
  • Output from the previous combiner stage (except for combiner 0).
  • Output from the previous combiner buffer stage (except for combiner 0).
Figure 11-2. Combiner Input Sources

Combiner0 CombinerBuffer0 Combiner1 CombinerBuffer1 Combiner2 CombinerBuffer2 Combiner3 CombinerBuffer3 Combiner4 CombinerBuffer4 Combiner5 TextureUnit0 TextureUnit1 TextureUnit2 TextureUnit3 Primary Color Fragment Lighting Primary Color Fragment Lighting Secondary Color ConstantRGBA

11.2.1. Reserved Uniforms for Combiner Functions

There are two reserved uniforms for combiner functions: dmp_TexEnv[i].combineRgb and dmp_TexEnv[i].combineAlpha. Use the glUniform1i() function to set a value at the reserved uniform location obtained by glGetUniformLocation.

The following values are used to set the reserved uniforms for combiner functions. The same values can be set for both dmp_TexEnv[i].combineRgb and dmp_TexEnv[i].combineAlpha.

If GL_DOT3_RGBA is set for the combiner, it must have the same combiner function (GL_DOT3_RGBA) for both the color (combineRgb) and alpha (combineAlpha) components.

Table 11-14. Reserved Uniform Values That Can Be Set for Combiner Functions

Setting Value

Combiner Function

GL_REPLACE

Src0 (default)

GL_MODULATE

Src0 * Src1

GL_ADD

Src0 + Src1

GL_ADD_SIGNED

Src0 + Src1 - 0.5

GL_INTERPOLATE

Src0 * Src2 + Src1 * (1 - Src2)

GL_SUBTRACT

Src0 - Src1

GL_DOT3_RGB

4 * ((Src0_Red - 0.5) * (Src1_Red - 0.5) + (Src0_Green - 0.5) * (Src1_Green - 0.5) + (Src0_Blue - 0.5) * (Src1_Blue - 0.5))

GL_DOT3_RGBA

4 * ((Src0_Red - 0.5) * (Src1_Red - 0.5) + (Src0_Green - 0.5) * (Src1_Green - 0.5) + (Src0_Blue - 0.5) * (Src1_Blue - 0.5))

GL_ADD_MULT_DMP

(Src0 + Src1) * Src2 Note: The sum is clamped between 0.0 and 1.0 before it is multiplied.

GL_MULT_ADD_DMP

(Src0 * Src1) + Src2

11.2.2. Reserved Uniforms for the Input Sources

There are two reserved uniforms for the input sources: dmp_TexEnv[i].srcRgb and dmp_TexEnv[i].srcAlpha.

Use the glUniform3i() function to set values at the reserved uniform location obtained by the glGetUniformLocation() function. Source 0 is first, followed by source 1 and source 2, respectively.

The following values are used to set the reserved uniforms for the input sources. The same values can be set for dmp_TexEnv[0].srcRgb and dmp_TexEnv[0].srcAlpha, and for dmp_TexEnv[i].srcRgb and dmp_TexEnv[i].srcAlpha.

Warning:

Every combiner except for combiner 0 must have GL_CONSTANT, GL_PREVIOUS, or GL_PREVIOUS_BUFFER_DMP specified as one of its three input sources.

Table 11-15. Reserved Uniform Values That Can Be Set for Input Sources

Setting Value

Input Source

GL_TEXTURE0

Texture color from texture unit 0.

GL_TEXTURE1

Texture color from texture unit 1.

GL_TEXTURE2

Texture color from texture unit 2.

GL_TEXTURE3

Texture color from texture unit 3.

GL_CONSTANT

Constant color. (This is the default for combiner 0 and is set by dmp_TexEnv[i].constRgba.)

GL_PRIMARY_COLOR

Primary color (vertex color).

GL_PREVIOUS

Output from the previous combiner stage. (Cannot be set for combiner 0. Default for combiners other than 0.)

GL_PREVIOUS_BUFFER_DMP

Output from the previous combiner buffer stage. (Cannot be set for combiner 0.)

GL_FRAGMENT_PRIMARY_COLOR_DMP

Primary color for fragment lighting.

GL_FRAGMENT_SECONDARY_COLOR_DMP

Secondary color for fragment lighting.

11.2.3. Reserved Uniforms for Operands

There are two reserved uniforms for operands: dmp_TexEnv[i].operandRgb and dmp_TexEnv[i].operandAlpha.

Use the glUniform3i() function to set values at the reserved uniform location obtained by the glGetUniformLocation() function. Source 0 is first, followed by source 1 and source 2, respectively.

The following values are used to set the reserved uniforms for operands.

Table 11-16. Reserved Uniform Values That Can Be Set for Operands

Setting Value

Operands

GL_SRC_COLOR

Color. (Cannot be set for operandAlpha. operandAlpha is the default.)

GL_ONE_MINUS_SRC_COLOR

1 - Color. (Cannot be set for operandAlpha.)

GL_SRC_ALPHA

Alpha. (operandAlpha is the default.)

GL_ONE_MINUS_SRC_ALPHA

1 - Alpha

GL_SRC_R_DMP

Color_Red

GL_ONE_MINUS_SRC_R_DMP

1 - Color_Red

GL_SRC_G_DMP

Color_Green

GL_ONE_MINUS_SRC_G_DMP

1 - Color_Green

GL_SRC_B_DMP

Color_Blue

GL_ONE_MINUS_SRC_B_DMP

1 - Color_Blue

11.2.4. Reserved Uniforms for Scaling Values

There are two reserved uniforms for scaling values: dmp_TexEnv[i].scaleRgb and dmp_TexEnv[i].scaleAlpha.

Use the glUniform1f() function to set a value at the reserved uniform location obtained by the glGetUniformLocation() function

The following values are used to set the reserved uniforms for scaling.

Table 11-17. Reserved Uniform Values That Can Be Set for Scaling

Setting Value

Scaling

1.0

Unchanged combiner output (default).

2.0

Double the combiner output (clamp between 0.0 and 1.0).

4.0

Quadruple the combiner output (clamp between 0.0 and 1.0).

11.2.5. Reserved Uniforms for Constant Colors

There is one uniform for constant colors: dmp_TexEnv[i].constRgba. Use the glUniform4f() function to set values at the reserved uniform location obtained by the glGetUniformLocation() function. The first value is R, followed by G, B, and A, respectively.

By default, 0.0 is set for the R, G, B, and A values in the reserved uniforms for constant colors.

11.2.6. Sample Combiner Settings

In the following example, combiner 2 references the primary color and outputs (renders) it unchanged.

To output only the primary color from the combiners without being affected by anything else, combiner 2's input source 0 is set to the primary color (GL_PRIMARY_COLOR), operand 0 is set to the unchanged input source color (GL_SRC_COLOR), the combiner function is configured to output input source 0 unchanged (GL_REPLACE), and the scale is set to 1.0. With these settings, the combiner outputs only the primary color and combiners 0 and 1 do not affect the output results.

This is illustrated by the following connection diagram.

Figure 11-3. Sample Combiner Settings 1

TextureUnit0 TextureUnit1 TextureUnit2 TextureUnit3 Primary Color Fragment Lighting Primary Color Fragment Lighting Secondary Color ConstantRGBA Combiner0 GL_REPLACE Combiner1 GL_REPLACE Combiner2 GL_REPLACE GL_PRIMARY_COLOR

The following sample code shows how to make these settings in a program.

Code 11-6. Code for Sample Combiner Settings 1
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcRgb"), 
        GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcAlpha"), 
        GL_PRIMARY_COLOR, GL_PREVIOUS, GL_PREVIOUS);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineRgb"), 
        GL_REPLACE);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineAlpha"), 
        GL_REPLACE);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandRgb"), 
        GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandAlpha"), 
        GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
glUniform1f(glGetUniformLocation(program, "dmp_TexEnv[2].scaleRgb"), 1.0);
glUniform1f(glGetUniformLocation(program, "dmp_TexEnv[2].scaleAlpha"), 1.0); 

In a more complex example, combiner 1 is configured to add output from texture 0 and texture 1, and combiner 2 is configured to multiply the result by the primary color.

Figure 11-4. Sample Combiner Settings 2

TextureUnit0 TextureUnit1 TextureUnit2 TextureUnit3 Primary Color Fragment Lighting Primary Color Fragment Lighting Secondary Color ConstantRGBA Combiner0 GL_REPLACE Combiner1 GL_ADD Combiner2 GL_MODULATE GL_PRIMARY_COLOR GL_TEXTURE0 GL_TEXTURE1

Code 11-7. Code for Sample Combiner Settings 2
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcRgb"), 
        GL_TEXTURE0, GL_TEXTURE1, GL_PREVIOUS);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcAlpha"), 
        GL_TEXTURE0, GL_TEXTURE1, GL_PREVIOUS);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineRgb"), 
        GL_ADD);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineAlpha"), 
        GL_ADD);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandRgb"), 
        GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandAlpha"), 
        GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcRgb"), 
        GL_PREVIOUS, GL_PRIMARY_COLOR, GL_PREVIOUS);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcAlpha"), 
        GL_PREVIOUS, GL_PRIMARY_COLOR, GL_PREVIOUS);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineRgb"), 
        GL_MODULATE);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineAlpha"), 
        GL_MODULATE);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandRgb"), 
        GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandAlpha"), 
        GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); 

11.3. Combiner Buffers

In the CTR system, each combiner, except for the last one (combiner 5), has a combiner buffer configured in parallel to it. A combiner buffer can select the output of the previous combiner stage or combiner buffer stage as its input source. By preserving the output of a previous combiner buffer stage, a combiner buffer can allow a later combiner stage's input to come from the output of a combiner stage earlier than the previous one.

11.3.1. Reserved Uniforms for Combiner Buffers

Because combiner buffer 0 has no input, its initial value is a constant color set by the reserved uniform dmp_TexEnv[0].bufferColor. Use the glUniform4f() function to set the constant color at the reserved uniform location obtained by the glGetUniformLocation() function. The first value is R, followed by G, B, and A, respectively.

By default, 0.0 is set as the R, G, B, and A values of combiner buffer 0's constant color.

You can choose output from either the previous combiner stage or the previous combiner buffer stage as the input source to combiner buffers 1 through 4. Input from the color and alpha components can be selected separately through the reserved uniforms dmp_TexEnv[i].bufferInput (where i is 1 through 4). Use the glUniform2i() function to set a value at the reserved uniform location obtained by glGetUniformLocation. The color components are first, followed by the alpha component.

The following reserved uniform values are used to configure the combiner buffer input sources.

Table 11-18. Reserved Uniform Values That Can Be Set for Combiner Buffer Input Sources

Setting Value

Input Source

GL_PREVIOUS

Output from the previous combiner stage (default).

GL_PREVIOUS_BUFFER_DMP

Output from the previous combiner buffer stage.

11.3.2. Sample Combiner Buffer Settings

The following sample settings demonstrate how to connect combiner buffers so that texture 0 is multiplied with the primary color for fragment lighting, texture 1 is multiplied with the secondary color for fragment lighting, and then these results are added together and output.

Figure 11-5. Sample Combiner Buffer Settings

TextureUnit0 TextureUnit1 TextureUnit2 TextureUnit3 Primary Color Fragment Lighting Primary Color Fragment Lighting Secondary Color ConstantRGBA Combiner0 GL_MODULATE Combiner1 GL_MODULATE Combiner2 GL_ADD GL_TEXTURE0 CombinerBuffer1 GL_PREVIOUS CombinerBuffer0 GL_FRAGMENT_PRIMARY_COLOR_DMP GL_TEXTURE1 GL_FRAGMENT_SECONDARY_COLOR_DMP CombinerBuffer2

The following sample code shows how to make these settings in a program.

Code 11-8. Sample Code for Setting Up the Combiner Buffers
// Combiner 0
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].srcRgb"), 
        GL_TEXTURE0, GL_FRAGMENT_PRIMARY_COLOR_DMP, GL_PREVIOUS);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].srcAlpha"), 
        GL_TEXTURE0, GL_PREVIOUS, GL_PREVIOUS);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[0].combineRgb"), 
        GL_MODULATE);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[0].combineAlpha"), 
        GL_REPLACE);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].operandRgb"), 
        GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[0].operandAlpha"), 
        GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
// CombinerBuffer 1
glUniform2i(glGetUniformLocation(program, "dmp_TexEnv[1].bufferInput"), 
        GL_PREVIOUS, GL_PREVIOUS);
// Combiner 1
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcRgb"), 
        GL_TEXTURE1, GL_FRAGMENT_SECONDARY_COLOR_DMP, GL_PREVIOUS);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].srcAlpha"), 
        GL_TEXTURE1, GL_PREVIOUS, GL_PREVIOUS);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineRgb"), 
        GL_MODULATE);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[1].combineAlpha"), 
        GL_REPLACE);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandRgb"), 
        GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[1].operandAlpha"), 
        GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA);
// Combiner 2
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcRgb"), 
        GL_PREVIOUS_BUFFER_DMP, GL_PREVIOUS, GL_PREVIOUS);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].srcAlpha"), 
        GL_PREVIOUS_BUFFER_DMP, GL_PREVIOUS, GL_PREVIOUS);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineRgb"), 
        GL_ADD);
glUniform1i(glGetUniformLocation(program, "dmp_TexEnv[2].combineAlpha"), 
        GL_REPLACE);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandRgb"), 
        GL_SRC_COLOR, GL_SRC_COLOR, GL_SRC_COLOR);
glUniform3i(glGetUniformLocation(program, "dmp_TexEnv[2].operandAlpha"), 
        GL_SRC_ALPHA, GL_SRC_ALPHA, GL_SRC_ALPHA); 

11.4. Procedural Textures

Procedural textures are unlike conventional textures, in that they determine texel colors procedurally rather than by referencing images. Procedural textures are most effective when used for perfectly regular patterns and patterns that are regular, but have some randomness. Because they do not access texture images, they avoid memory access conflicts and reduce data (content) sizes.

Texture unit 3 is exclusively used for procedural textures, and is also the only texture unit that can handle procedural textures. Even though procedural textures calculate texel colors, they are similar to normal textures, in that they still determine which texel colors correspond to UV texture coordinates.

As a part of the reserved fragment shaders, procedural textures have parameters that are configured through reserved uniforms by the glUniform*() functions.

11.4.1. Procedural Texture Unit

The procedural texture unit comprises three computational components. In order of process flow, these are random number generation, clamping, and mapping. Random number generation adds noise to UV texture coordinates; clamping determines wrapping and mirror symmetry for patterns; and mapping calculates texel colors from UV coordinates.

Figure 11-6. Structure of the Procedural Texture Unit

Random Numbers Clamp G(u, v) F(g) Color(f) Random Number Generation Clamping Mapping color

Input texture coordinates are processed as shown in the figure above. Use the following procedure to set parameters to get the desired image.

  1. Enable Procedural Textures
  2. Set shared RGBA mode or independent alpha mode.
    This corresponds to settings for G(u, v) and F(g).
  3. Select a basic shape.
    This corresponds to the selection in G(u, v).
  4. Colors are set in color lookup tables. This corresponds to settings for Color(f).
  5. Set the relationship between the basic shape and color lookup table.
    This determines how the basic shape in step 3 corresponds to the color lookup table in step 4. This corresponds to settings for F(g).
  6. Select random number parameters.
    If necessary, enable random numbers and determine the size of their effect. If not necessary, disable them. This corresponds to random number generation. The UV coordinates are made into absolute values and output to the clamp portion, regardless of whether they are enabled or disabled.
  7. Configure wrapping and symmetry.
    This corresponds to clamp settings.

11.4.2. Enable Procedural Textures

To enable or disable texture unit 3, which is used by procedural textures, set a value for the dmp_Texture[3].samplerType reserved uniform. Note that using glActiveTexture to select a unit or glEnable to select a texture type results in an error.

Using glUniform1i, set the value to GL_TEXTURE_PROCEDURAL_DMP to enable texture unit 3 or to GL_FALSE to disable it. The only supported texture type is GL_TEXTURE_PROCEDURAL_DMP.

Code 11-9. Enabling Procedural Textures
glUniform1i(
    glGetUniformLocation(s_PgID, "dmp_Texture[3].samplerType"), 
    GL_TEXTURE_PROCEDURAL_DMP); 

11.4.3. Setting Shared RGBA Mode or Independent Alpha Mode

Choose whether the alpha component is mapped using the same functions as the RGB components (shared RGBA mode) or using functions that are set separately for the alpha component (independent alpha mode). If independent alpha mode is selected, two G functions and two F functions must be set for mapping. Shared RGBA mode is easier to set if you just want to output an image to see what it looks like.

Using the glUniform1i() function, set the reserved uniform dmp_Texture[3].ptAlphaSeparate to GL_FALSE to select shared RGBA mode or to GL_TRUE to select independent alpha mode. Shared RGBA mode is the default.

Figure 11-7. Mapping in Independent Alpha Mode

Grgb(u, v) Frgb(grgb) Color(frgb) Mapping color Ga(u, v) Fa(ga) fa alpha

11.4.4. Selecting a Basic Shape

A procedural texture's basic shape is determined by the G function during mapping.

The basic shapes in Table 11-19 use the following color assignments.

Table 11-19. G Function Settings, Selected Functions, and Basic Shapes

Setting Value

Selected Function

Basic Shape

GL_PROCTEX_U_DMP (default)

u

GL_PROCTEX_V_DMP

v

GL_PROCTEX_U2_DMP

u2

GL_PROCTEX_V2_DMP

v2

GL_PROCTEX_ADD_DMP

(u + v) / 2

GL_PROCTEX_ADD2_DMP

(u2 + v2) / 2

GL_PROCTEX_ADDSQRT2_DMP

sqrt(u2 + v2)

GL_PROCTEX_MIN_DMP

min(u, v)

GL_PROCTEX_MAX_DMP

max(u, v)

GL_PROCTEX_RMAX_DMP

((u + v) / 2 + sqrt(u2 + v2)) / 2

The basic shape is rendered using texture coordinates between -1.0 and 1.0 (with 0.0 at the center) and GL_MIRRORED_REPEAT specified for wrapping.

The reserved uniforms used for selection with the G function are dmp_Texture[3].ptRgbMap for RGB components and dmp_Texture[3].ptAlphaMap for the alpha component. Use the glUniform1i() function to set each of these reserved uniforms.

dmp_Texture[3].ptAlphaMap settings are only valid in independent alpha mode. Choose the shape that is closest to the desired texture image.

For example, choose GL_PROCTEX_U_DMP and GL_PROCTEX_V_DMP for wood grain or GL_PROCTEX_ADDSQRT2_DMP for the annual rings in a tree.

11.4.5. Color Lookup Table Settings

Color lookup tables are used to convert values calculated by the G and F functions into actual texel colors, and can set each of the RGBA components separately.

The content of the color lookup table depends on whether LOD is used.

Figure 11-8. Color Lookup Table Differences Caused by the Use of LOD

ptTexOffset ColorTable1 ptTexWidth ColorTable2 ColorTable1 ColorTable2 width T ΔT ptTexWidth 256 + ptTexOffset ptTexOffset = 0 ColorTable Level 0 ptTexWidth = 128 width = 512 T ΔT With LOD Without LOD ColorTable Level 1 Level 2 Level 6 ColorTable Level 0 ColorTable Level 1 Level 2 Level 6 ptTexWidth = 128

When LOD is not used, multiple color tables can be stored as partial arrays in a color lookup table. By changing the offset and table width, you can also render textures with different coloring from the same calculation results.

A color lookup table can hold up to 512 elements. You can store the color table in the first 256 elements and the differences between the color table values in the last 256 elements. Because the delta values must start at the 257th element, the number of color lookup table entries is defined as the sum of 256, the number of color lookup table elements that are actually referenced, and the starting offset to the color tables. The number of elements is calculated for the last color table.

Use the glUniform1i() function to set the color table width that is actually referenced (dmp_Texture[3].ptTexWidth). Set this value to a power of 2 that is no greater than 128. Use the glUniform1i() function to set the color table's starting offset (dmp_Texture[3].ptTexOffset) to an integer between 0 and 128.

When LOD is used, the color table width and offset must be 128 and 0 respectively. The level of detail determines which color table is actually referenced. The maximum number of elements in a color lookup table is fixed at 512.

Table 11-20. Level of Detail and Corresponding Color Tables

Level of Detail

Starting Position

Width

0

0

128

1

128

64

2

192

32

3

224

16

4

240

8

5

248

4

6

252

2

As explained in 7.7. Loading Lookup Tables, lookup tables are loaded from arrays by calls to the glTexImage1D() function. Prepare an array of floating-point numbers with as many elements as the color lookup table, storing values 0.0 through 1.0 for the color table elements (T) in the first half of the array and the differences between the first half’s 256 elements (ΔT) in the last half of the array. The following equations calculate the elements and delta values, given size as the number of elements in the color table, offset as the starting offset, Ci as each element, and func as the conversion function.

Ci offset size func

Set the last difference value to either 0.0 or the difference between the color table's last element and the convergence value.

You can use the following code to call the glTexImage1D() function and configure 512 as the maximum number of elements in a color lookup table, data as the array storing the color lookup table, and 0 as the number of the lookup table to set.

Code 11-10. Loading a Color Lookup Table
glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 512, 0, 
             GL_LUMINANCEF_DMP, GL_FLOAT, data); 

The color lookup table used by each RGBA component uses the glUniform1i() function to specify the lookup table number as the following reserved uniform. Note that the lookup table number specified here, GL_LUT_TEXTUREi_DMP, where i represents a number from 0 to 31, does not specify the name (ID) of the texture nor GL_LUT_TEXTUREi_DMP directly.

Table 11-21. Reserved Uniforms That Specify Color Lookup Tables

Reserved Uniform

Value to Set

dmp_Texture[3].ptSamplerR

Specifies the lookup table number to use as the color lookup table for the red component.

dmp_Texture[3].ptSamplerG

Specifies the lookup table number to use as the color lookup table for the green component.

dmp_Texture[3].ptSamplerB

Specifies the lookup table number to use as the color lookup table for the blue component.

dmp_Texture[3].ptSamplerA

Specifies the lookup table number to use as the color lookup table for the alpha component.

Each reserved uniform specifies a value between 0 and 31.

The value set for dmp_Texture[3].ptSamplerA is ignored in independent alpha mode.

You can apply the same minification filters to a procedural texture's color lookup tables as you can to a normal texture. Choose a value from the following table to set the reserved uniform dmp_Texture[3].ptMinFilter with the glUniform1i() function.

Table 11-22. Color Lookup Table Filters

Value to Set

Filter to Apply

GL_NEAREST

Nearest in the UV directions without LOD.

GL_LINEAR

Linear in the UV directions without LOD (default).

GL_NEAREST_MIPMAP_NEAREST

Nearest in the UV directions with the nearest LOD.

GL_NEAREST_MIPMAP_LINEAR

Nearest in the UV directions with a linear LOD.

GL_LINEAR_MIPMAP_NEAREST

Linear in the UV directions with the nearest LOD.

GL_LINEAR_MIPMAP_LINEAR

Linear in the UV directions with a linear LOD.

You can apply an LOD bias when referencing the color lookup table. Use the glUniform1f() function to set the reserved uniform dmp_Texture[3].ptTexBias to a value from 0.0 through 6.0. This is disabled with a value of 0.0, and has a default value of 0.5.

11.4.6. Setting the Relationship Between the Basic Shape and Color Lookup Table

The F function configures how the G function, which selects the basic shape, corresponds to the color lookup table, which sets the basic color. The F function uses a lookup table to map output from the G function (0.0 through 1.0) into lookup values for the color lookup table (0.0 through 1.0). The lookup table has 256 elements. A mapping table is stored in the first 128 elements and the differences between the mapping table values are stored in the last 128 elements. Because the mapping table configures the relationship between shapes and colors, by changing the mapping table you can render textures that have different appearances even though they use the same shape and color lookup table. By modifying the F function, a wide variety of outputs is possible. For example, you could use a simple F function to calculate results, such as F(x)=x or F(x)=x2, or you could have the F function use discontinuous values and operate like an index.

Like color lookup tables, the mapping table for the F function is loaded from an array into a lookup table by a call to the glTexImage1D() function. Prepare an array of floating-point numbers with as many elements (256) as the mapping table, storing the mapping table elements (0.0 through 1.0) in the first half of the array and the differences between those elements in the last half of the array. The following equations calculate the mapping table elements and delta values, assuming Fi is a mapping table element and func is the conversion function.

You can use the following code to call the glTexImage1D() function and configure 256 as the number of mapping table elements, data as the array storing the mapping table, and 0 as the number of the lookup table to set.

Code 11-11. Loading a Mapping Table
glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 256, 0, 
             GL_LUMINANCEF_DMP, GL_FLOAT, data); 

The mapping table used as the F functions uses the glUniform1i() function to specify the lookup table number as the following reserved uniform. Note that the specified lookup table number GL_LUT_TEXTUREi_DMP, where i represents a number from 0 to 31, does not specify the name (ID) of the texture nor GL_LUT_TEXTUREi_DMP directly.

Table 11-23. Reserved Uniforms That Specify Mapping Tables

Reserved Uniform

Value to Set

dmp_Texture[3].ptSamplerRgbMap

Specifies the lookup table number to use as the F function for RGB values.

dmp_Texture[3].ptSamplerAlphaMap

Specifies the lookup table number to use as the F function for alpha values.

Each reserved uniform specifies a value between 0 and 31.
dmp_Texture[3].ptSamplerAlphaMap is only valid in independent alpha mode.

11.4.7. Selecting Random Number Parameters

As a random element in a procedural texture, noise can be added to the UV texture coordinates that are input to the G function. Noise affects the basic shape. When the G function is GL_PROCTEX_U_DMP and noise affects U texture coordinates, for example, it becomes possible to render wood grain with natural warping. Ordinarily, wood grain can only be rendered in a straight line.

To enable or disable noise, set a value in the reserved uniform dmp_Texture[3].ptNoiseEnable. Using glUniform1i, specify GL_TRUE to enable it, and GL_FALSE to disable it.

Code 11-12. Enabling Noise
glUniform1i(
    glGetUniformLocation(s_PgID, "dmp_Texture[3].ptNoiseEnable"), GL_TRUE); 

The function that adds noise is a black box, but it can be controlled through three parameters from the application: the frequency (F), the phase (P), and the amplitude (A). The F parameter adjusts the speed of the fluctuations (noise) so that large values create jagged waves and small values create gentle undulations. The P parameter changes the starting location of the noise. When rendering a texture of the ocean surface, for example, you can represent changing waves by modifying only the P parameter. When increased, the A parameter magnifies the effect of the noise and further destroys the basic shape.

The three parameters F, P, and A can each be set separately for the U and V components.

Table 11-24. Reserved Uniforms for Noise

Reserved Uniform

Value to Set

dmp_Texture[3].ptNoiseU

Specifies the F, P, and A parameters for the u-component. The range from -8.0 to 8.0 is clamped only for parameter A.

(F-parameter, P-parameter, A-parameter)

These are (0.0, 0.0, 0.0) by default.

dmp_Texture[3].ptNoiseV

Specifies the F, P, and A parameters for the v component. The range from -8.0 to 8.0 is clamped only for parameter A.

(F-parameter, P-parameter, A-parameter)

These are (0.0, 0.0, 0.0) by default.

Apart from the noise parameters, you can control changes in the continuity of random numbers (called noise modulation) in the function that adds noise. Noise modulation (a continuous noise function) is specified by a lookup table called the noise modulation table. The noise function takes a noise modulation table and uses it to create natural noise values from the discrete values that arise from calculations alone. A suitable continuous noise function, such as 3x2 - 2x3, generates values that change gradually when x is near 0.0 and 1.0.

Like the color lookup table, the noise modulation table is loaded from an array by a call to the glTexImage1D() function. The noise function takes a noise modulation table and uses it to create natural noise values from the discrete values that arise from calculations alone. The following equations calculate the noise modulation table elements and delta values, assuming Ni is a table element and func is the conversion function.

You can use the following code to call the glTexImage1D() function and configure 256 as the number of noise modulation table elements, data as the array storing the noise modulation table, and 0 as the number of the lookup table to set.

Code 11-13 Loading a Noise Modulation Table
glTexImage1D(GL_LUT_TEXTURE0_DMP, 0, GL_LUMINANCEF_DMP, 256, 0, 
                 GL_LUMINANCEF_DMP, GL_FLOAT, data); 

The noise modulation table to use as continuous noise functions use the glUniform1i() function to specify the lookup table number as the following reserved uniform. Note that the specified lookup table number GL_LUT_TEXTUREi_DMP, where i represents a number from 0 to 31, does not specify the name (ID) of the texture nor GL_LUT_TEXTUREi_DMP directly.

Table 11-25. Reserved Uniforms That Specify Noise Modulation Tables

Reserved Uniform

Value to Set

dmp_Texture[3].ptSamplerNoiseMap

Specifies the lookup table number to use as the continuous noise function.

0 through 31

To illustrate the effects of the three noise parameters F, P, and A on the output results, consider the difference between a procedural texture that is rendered as a concentric circle when it is unaffected by noise, and the same texture when its parameters are changed in both the U and V directions. These are rendered with F(x)=x as the continuous noise function.

Figure 11-9 shows the effect of changing only the A parameter. The other parameters, F and P, are set to 0.3 and 0.0 respectively. Although the waves become more prominent as A gets larger, note that most points along the circumference of the circle are unaffected.

Figure 11-9. Effect of the A Parameter

Figure 11-10 shows the effect of changing only the F parameter. The other parameters, A and P, are set to 0.3 and 0.0 respectively. Note that as F gets larger, the frequency of the noise (fluctuations) increases, and the affected locations along the circumference of the circle get closer to each other. Also note that the absolute value is used for the F parameter when calculating noise, so reversing the sign does not change the result.

Figure 11-10. Effect of the F Parameter

Figure 11-11 shows the effect of changing only the P parameter. The other parameters, A and F, are both set to 0.3. Note that when P changes, only the shape of the noise changes. By modifying the P parameter, you can change a procedural texture so that it appears animated.

If you set the P parameter equal to a large value while using it to animate a texture, small changes to the P parameter will affect the shape of the noise. This is caused by the accuracy of calculations in the hardware. For example, if you animate a texture by adding a constant value to the P parameter every frame (which changes the noise), you must restore the P parameter to a small value before it gets too large. One characteristic of the F and P parameters is that when they are both positive and have a product that is a multiple of 16, they have the same effect as when the P parameter is 0.0. In other words, by changing the P parameter back to 0 when the product of the P and F parameters is 16, you can maintain the animation’s continuity. However, you may not get the same shape when the P parameter is 0.0 and when the product of the F and P parameters is 16, if the F parameter is large.

If the values for the F and A parameters are fixed, and the P parameter varies in a range where the sign does not change for the phase |u| + u (or for the phase |v| + v), you can get the same noise result for X + 16 when F×P is some arbitrary value X. However, depending on the accuracy of the noise calculation process, you may not be able to get the same random value this way if you set a large value for the F parameter. Also, if you set a large value for the P parameter, changes in small values may not be applied to the noise result.

Figure 11-11. Effect of the P Parameter

11.4.8. Wrapping and Symmetry Settings

Procedural textures have a feature equivalent to the wrapping mode that can be set for normal textures. This feature is called clamp calculation, and can be configured with dedicated modes such as pulse and zero-clamp. There are also shift calculations that shift blocks of texture coordinates that have the same integer values during wrapping.

Clamp calculations use the clamp mode to determine how to convert texture coordinates that are less than 0.0 or greater than 1.0 into values between 0.0 and 1.0.

Table 11-26. Clamp Modes

Clamp Mode

Coordinate Clamping

GL_SYMMETRICAL_REPEAT_DMP

GL_MIRRORED_REPEAT

GL_PULSE_DMP

GL_CLAMP_TO_EDGE (default)

GL_CLAMP_TO_ZERO_DMP

You can set different clamp modes for the U and V texture coordinates. To set these modes, call the glUniform1i() function on the reserved uniform dmp_Texture[3].ptClampU or dmp_Texture[3].ptClampV.

GL_SYMMETRICAL_REPEAT_DMP lines up the same image on a grid. GL_MIRRORED_REPEAT uses a mirror reflection at even-numbered values. GL_PULSE_DMP uses the pixel closest to the edge of the texture for each pixel that is used for rendering. GL_CLAMP_TO_EDGE uses a texture's internal image for values between -1.0 and 1.0. Outside of that range, it uses pixels at the edge of the texture. GL_CLAMP_TO_ZERO_DMP uses the texture image for values between –1.0 and 1.0 (excluding these two values). Outside of that range, it uses the image at coordinate 0 (including the values –1.0 and 1.0).

Shift calculations determine the shift coordinates based on the shift mode. The shift width depends on the clamp mode. This process is applied before clamp calculations, allowing you to avoid rendering the same image over and over.

Table 11-27. Shift Modes

Shift Mode

Shift Calculation

Shift Width

GL_NONE_DMP (default)

No shift calculation.

None.

GL_ODD_DMP

Shifts coordinates when their integer value changes from an odd number to an even number.

1.0 for GL_MIRRORED_REPEAT only; 0.5 otherwise.

GL_EVEN_DMP

Shifts coordinates when their integer value changes from an even number to an odd number.

1.0 for GL_MIRRORED_REPEAT only; 0.5 otherwise.

You can set different shift modes for the U and V texture coordinates. To set these modes, call the glUniform1i() function on the reserved uniform dmp_Texture[3].ptShiftU or dmp_Texture[3].ptShiftV.

Figure 11-12. How Shift Modes and Clamping Modes Affect Shift Widths

1.0 0.0 2.0 3.0 4.0 1.0 0.0 2.0 3.0 4.0 GL_NONE_DMP GL_EVEN_DMP GL_ODD_DMP GL_NONE_DMP GL_EVEN_DMP GL_ODD_DMP GL_SYMMETRICAL_REPEAT_DMP GL_MIRRORED_REPEAT 0.5 0.5 1.0 1.0


CONFIDENTIAL