In addition to cube map textures and 2D textures that are pasted onto polygon models, the 3DS system can handle shadow textures used for shadows, gas textures used for rendering gases, and lookup tables used by the reserved fragment shader (these lookup tables cannot be used as textures).
This chapter explains the necessary procedures for using these textures and describes how the native PICA format differs from the OpenGL specifications.
7.1. Creating Texture Objects
Use the glGenTextures()
function to create texture objects to bind as textures.
void glGenTextures(GLsizei n, GLuint* textures);
7.2. Specifying Texture Objects
Use the glBindTexture()
function to specify a texture object to bind as a texture. After this function is called, the various texture processes are performed using the specified texture object. Texture images loaded for (and the results of processing performed on) a texture object are preserved until the texture object is deleted. Consequently, you can switch texture objects to change textures without reloading texture images.
void glBindTexture(GLenum target, GLuint texture);
Specify the texture type for target
, and the texture object to bind for texture
. A GL_INVALID_ENUM
error is generated if you set target
to a value that is not in the following table.
target Value |
Type of Texture |
---|---|
|
2D textures, shadow textures, and gas textures. |
|
Cube-map texture. |
|
Cube-map texture. |
|
Cube-map texture. |
|
Cube-map texture. |
|
Cube-map texture. |
|
Cube-map texture. |
|
Lookup tables (used by the reserved fragment shader). |
|
Texture collections (see 7.9. Texture Collections). |
7.3. Loading Texture Images
In addition to normal texture images (2D textures), the glTexImage2D()
function loads the following special textures: cube map textures, shadow textures, and gas textures. Partial texture loading with the glTexSubImage2D()
function is not supported.
void glTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
Set target
to one of the following values.
target Value |
Texture Usage |
---|---|
|
2D textures, shadow textures, and gas textures. |
|
Cube map +X plane textures. |
|
Cube map -X plane textures. |
|
Cube map +Y plane textures. |
|
Cube map −Y plane textures. |
|
Cube map +Z plane textures. |
|
Cube map −Z plane textures. |
Combinations of format
and type
specify the format of texture images stored in the region specified by pixels
. The following table lists the formats that can be handled by the 3DS system. The Bytes column indicates the number of bytes per texel. An asterisk (*) that follows the byte count indicates a native PICA format, which has a different byte order than the standard OpenGL format. For more information about the native PICA format, see 7.10. Native PICA Format.
format |
type |
Format |
Bytes |
---|---|---|---|
|
|
RGBA4 |
2 |
|
|
RGBA5551 |
2 |
|
|
RGBA8 |
4 |
|
|
RGB565 |
2 |
|
|
RGB8 |
3 |
|
|
A8 |
1 |
|
|
A4 |
0.5 |
|
|
L8 |
1 |
|
|
L4 |
0.5 |
|
|
LA8 |
2 |
|
|
LA4 |
1 |
|
|
- |
4 |
|
|
- |
4 |
|
|
- |
2 |
|
|
RGBA4 |
2 |
|
|
RGBA5551 |
2 |
|
|
RGBA8 |
4* |
|
|
RGB565 |
2 |
|
|
RGB8 |
3* |
|
|
A8 |
1 |
|
|
A4 |
0.5 |
|
|
L8 |
1 |
|
|
L4 |
0.5 |
|
|
LA8 |
2* |
|
|
LA4 |
1 |
|
|
- |
4* |
|
|
- |
4* |
|
|
- |
2* |
R, G, and B represent colors (red, green, and blue, respectively).
A represents the alpha value.
L represents the luminance value.
As set forth in the OpenGL ES 1.1 specifications, a value of 1 is output for the alpha component if the texture combiner references a texture without an alpha component. This is also true for compressed textures.
You can only set format
to GL_RGB
or GL_RGB_NATIVE_DMP
and type
to GL_UNSIGNED_BYTE
when target
is GL_TEXTURE_2D
. When format
is GL_*_NATIVE_DMP
, pixels
must specify data in the native PICA format. When GL_GAS_DMP
is specified, pixels
must be 0
(NULL
).
For width
and height
, specify the width and height of the texture image. Both numbers must be powers of 2, from 8 through 1024.
If target
is GL_TEXTURE_CUBE_MAP_*
, width
and height
must have the same value. Every surface must have the same settings, except for pixels
(and target
).
If pixels
is set to 0
(NULL
), a region is allocated but image data is not loaded.
For internalformat
specify the basic internal format. A GL_INVALID_OPERATION
error is generated when internalformat
and format
are not the same value. The following table shows how an image's RGBA components correspond to the components in the basic internal format.
Basic Internal Format |
RGBA |
Internal Format |
---|---|---|
|
A |
A |
|
R |
L |
|
R, A |
L, A |
|
R, G, B |
R, G, B |
|
R, G, B, A |
R, G, B, A |
|
R, G |
Nx, Ny |
The GL_HILO8_DMP
format outputs 0.0
for the B component and 1.0
for the A component.
Unlike in the OpenGL specifications, level
specifies the number of mipmap levels as a negative value. For example, -2
indicates two mipmap levels, and both -1
and 0
indicate one mipmap level. You cannot separately specify which textures to use for each mipmap level. Instead, set pixels
to a series of textures, starting with the texture to use as the largest mipmap and ending with the texture to use as the smallest mipmap.
You must set border
to 0
.
To configure the GPU access targets and processing to use when allocating the buffer region, pass a bitwise OR of certain specific flag values for target
for the glTexImage2D()
function. For more information, see 3. Using Data Located in Main Memory in 3DS Programming Manual: Advanced Graphics.
7.3.1. Formats With 4-Bit Components
Texture formats with a type
of GL_UNSIGNED_BYTE_4_4_DMP
or GL_UNSIGNED_4BITS_DMP
use 4 bits for a single component, and require a special data ordering.
In a format with a type
of GL_UNSIGNED_BYTE_4_4_DMP
, two components are stored in a single byte. You can combine this with a format
of GL_LUMINANCE_ALPHA
or GL_LUMINANCE_ALPHA_NATIVE_DMP
. The luminance is stored in the most-significant 4 bits and the alpha component is stored in the least-significant 4 bits.
In a format with a type
of GL_UNSIGNED_4BITS_DMP
, two texels are stored in a single byte. You can combine this with a format
of GL_LUMINANCE
, GL_LUMINANCE_NATIVE_DMP
, GL_ALPHA
, or GL_ALPHA_NATIVE_DMP
. Viewed as a row of texels, the first component is stored in the least-significant 4 bits, the second component is stored in the most-significant 4 bits, and so on.
If you enable a texture format with a type
of GL_UNSIGNED_4BITS_DMP
(a 4-bit format) at the same time as another texture format (a non-4-bit format that includes ETC1 compressed textures) and then use them as a multitexture, there are restrictions on the placements of the texture. and then use them as a multitexture, there are restrictions on the placements of the texture.
If you are placing 4-bit textures in VRAM, you must place 4-bit textures and non-4-bit textures in separate memory. In such cases, VRAM-A and VRAM-B are treated as separate memory. Behavior is undefined when textures having different bit formats are placed in the same memory.
There is no restriction on texture arrays when 4-bit textures are placed in main memory.
7.4. Loading Compressed Textures
You can load compressed image data as texture images. Partial texture loading, with the glCompressedTexSubImage2D()
function, is not supported.
void glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const void* data);
For target
specify the same value specified in the glTexImage2D()
function (Table 7-2). However, shadow textures and gas textures cannot use the regions allocated by this function.
For width
and height
, specify the width and height of the texture image. Both numbers must be powers of 2, from 16 through 1024.
The values specified for level
and border
, and the restrictions on cube map textures and mipmap textures, are the same as in the glTexImage2D()
function. For more information, see 7.3. Loading Texture Images.
The hardware supports only one compressed texture format: ETC1 (Ericsson Texture Compression). You can set internalformat
to either GL_ETC1_RGB8_NATIVE_DMP
or GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP
.
The ETC1 format takes blocks of 4×4 texels in the 24-bit RGB format and compresses them each into 64 bits. An alpha channel is not supported by GL_ETC1_RGB8_NATIVE_DMP
, but it is supported by GL_ETC1_ALPHA_RGB8_A4_NATIVE_DMP
, which adds 4 bits of alpha component data for each of the 16 texels.
A value of 1
is output for the alpha component when the texture combiner references a compressed texture with a format that does not include an alpha channel.
For imageSize
specify the number of bytes in the image data. If the original texture image has a width of w
and a height of h
, imageSize
can be found using the following equation. The value of blockSize
is either 8
when there is no alpha channel or 16
when there is.
imageSize
= (w / 4) * (h / 4) * blockSize
The ETC1 format handled by the 3DS system is different from the standard OpenGL specifications. 7.10. Native PICA Format explains the differences between this format and the standard specifications. For more information about formats, see the 3DS Programming Manual: Advanced Graphics.
To configure the GPU access targets and processing to use when allocating the buffer region, pass a bitwise OR of certain specific flag values for target
for the glCompressedTexImage2D()
function. For more information, see 3. Using Data Located in Main Memory in 3DS Programming Manual: Advanced Graphics.
7.5. Copying From the Framebuffer
You can get (copy) an image of the color buffer and depth buffer, which are bound to a framebuffer object as a texture.
7.5.1. Copying From the Color Buffer
You can get (copy) an image of the color buffer as a texture.
void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
For target
specify the same value specified in the glTexImage2D()
function (Table 7-2). All other argument values are also the same, except for the following differences.
- For
internalformat
specify eitherGL_RGB
orGL_RGBA
, but data cannot be converted from the color buffer format during the copy (only formats with the same pixel sizes are allowed). - The values of
x
andy
specify the starting point of the data region to copy from the color buffer (with the origin at the lower-left corner and the positive axes pointing up and right). The values ofwidth
andheight
specify the width and height of the region to copy. The values ofx
andy
must be multiples of 8. - Only
0
can be specified forlevel
.
To configure the GPU access targets and processing to use when allocating the buffer region, pass a bitwise OR of certain specific flag values for target
for the glCopyTexImage2D()
function. For more information, see 3. Using Data Located in Main Memory in 3DS Programming Manual: Advanced Graphics.
7.5.2. Copying From the Color Buffer
You can also copy a partial texture image region from the color buffer.
void glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
Data must be copied to a texture image region that was allocated in advance by the glTexImage2D()
function.
This function is the same as glCopyTexImage2D
except that xoffset
and yoffset
specify the coordinates of the region to be copied to (where the origin is the lower-left corner and the positive axes point up and toward the right), and width
and height
specify a multiple of 8 (not necessarily a power of two). For more information, see 7.5.1. Copying From the Color Buffer.
7.5.3. Copying From the Depth Buffer
If you call the glEnable()
function with GL_DEPTH_STENCIL_COPY_DMP
passed as an argument, the glCopyTexImage2D()
and glCopyTexSubImage2D()
functions copy the content of the depth (and stencil) buffer, rather than the color buffer, to a texture as long as depth/stencil copy operations are enabled.
The format of the current depth buffer determines the format of the texture to specify as the copy target. Because the format is not converted during the copy operation, a GL_INVALID_OPERATION
error occurs if you attempt to copy data to a texture with an unsupported format. The copied data is identical for both native and non-native texture formats.
Depth Buffer Format |
Texture Format |
Texture Type |
Components |
---|---|---|---|
|
|
|
R: Stencil |
|
|
|
R: D [23:16] |
|
|
|
R: D [15:8] |
Note: The Components column shows which bits of the depth value are set in each component. (For example, Depth [15:8] indicates that bits 8 through 15 of the depth value are set for that component.)
You can call the glEnable
, glDisable
, and glIsEnabled()
functions and pass GL_DEPTH_STENCIL_COPY_DMP
as an argument to respectively enable, disable, and determine the current status of depth and stencil copy operations.
You cannot use the glCopyTexImage2D()
and glCopyTexSubImage2D()
functions in block 32 mode. No errors are generated, but images are not transferred properly. For information about block mode settings, see the 3DS Programming Manual: Advanced Graphics.
7.6. Specifying a Texture as the Render Target
To write rendering results directly to a texture ("render to texture"), take a texture image allocated by glTexImage2D()
and bind it to a framebuffer object using the glFramebufferTexture2D()
function. Because rendering results are written directly to each of the special textures used by shadows and gases, you do not need to use this function to specify the special textures as rendering targets.
void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
For target
, you can only specify GL_FRAMEBUFFER
.
For attachment
, specify the data to write to the texture. Specify GL_COLOR_ATTACHMENT0
if a color buffer and GL_DEPTH_ATTACHMENT
if a depth buffer.
For textarget
specify the same value specified in the glTexImage2D()
function (Table 7-2).
For texture
, specify the texture object to bind to the framebuffer object.
Only 0
can be specified for level
.
When a texture is specified as the render target for the depth (and stencil) buffer, the texture format to specify for each depth buffer format is set. The corresponding format is the same as that indicating in 7.5.3. Copying From the Depth Buffer (Table 7-5). When the format of the depth buffer is GL_DEPTH24_STENCIL8_EXT
, you can set GL_DEPTH_STENCIL_ATTACHMENT
to attachment
, but it is the same as setting GL_DEPTH_ATTACHMENT
.
7.7. Loading Lookup Tables
The glTexImage1D()
function loads one-dimensional textures in OpenGL, but it is used to load lookup tables on the 3DS system. A lookup table is a one-dimensional table accessed by procedural textures, fragment lighting, fog, and gases. It cannot be used as a texture.
void glTexImage1D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
For target
, specify GL_LUT_TEXTUREi_DMP
to specify the lookup table to load. The lookup table number is specified in i
as a number between 0
and one less than the value obtained by passing GL_MAX_LUT_TEXTURES_DMP
to pname
in the glGetIntegerv()
function. In other words, you can specify a lookup table number in the range from 0 through 31. GL_LUT_TEXTUREi_DMP
is defined as GL_LUT_TEXTURE0_DMP
+ i
.
You can only specify 0
for level
, GL_FLOAT
for type
, and GL_LUMINANCEF_DMP
for format
and internalformat
. A GL_INVALID_VALUE
error is generated if level
is nonzero. A GL_INVALID_ENUM
error is generated if type
, format
, or internalformat
is not one of these values.
For width
, specify the number of table elements, and for pixels
, specify the table elements. The maximum value that can be specified for width
is 512
, which is the same value obtained from the glGetIntegerv()
function when GL_MAX_LUT_ENTRIES_DMP
is passed into pname
. However, the various reserved fragment processes have unique restrictions on the number of table elements and on the table elements.
To get the ID of the texture object bound to GL_LUT_TEXTUREi_DMP
, call glGetIntegerv()
and specify GL_TEXTURE_BINDING_LUTi_DMP
for the pname
parameter (where i
is a value from 0
through 31
).
Use the glTexSubImage1D()
function to rewrite a subset of the lookup table data that has been loaded.
void glTexSubImage1D(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
Data must be copied to a lookup table region that was allocated in advance by the glTexImage1D()
function.
This function is identical to glTexImage1D
except for xoffset
and width
, which specify the starting element number and the number of elements, respectively. A GL_INVALID_VALUE
error is generated if the sum of width
and xoffset
exceeds the number of table elements.
The glCopyTexImage1D()
and glCopyTexSubImage1D()
functions have not been implemented. Texture parameter settings are also unsupported.
7.8. Destroying Texture Objects
You can use the glDeleteTextures()
function to destroy texture objects that are no longer necessary.
void glDeleteTextures(GLsizei n, const GLuint* textures);
7.9. Texture Collections
Texture collections are new to the Nintendo 3DS. You can bind texture objects to textures and record them. Using texture collections, you can bind a group of texture objects to a recorded texture type in one operation. Texture collections share their namespace with texture objects and can be created, specified, and destroyed using glGenTextures
, glBindTexture
, and glDeleteTextures
, respectively.
7.9.1. Creating Texture Collections
A texture collection operates as a special texture object. Consequently, use the glGenTextures()
function to generate objects that can be used as texture collections, just as you would for texture objects.
7.9.2. Specifying Texture Collections
Use the glBindTexture()
function to specify a texture object to use as a texture collection. Call this function, and for the target
parameter, specify GL_TEXTURE_COLLECTION_DMP
. By default, the object with a name of 0 (with a value of 0 passed into texture
) is a texture collection.
After this function is called, the texture collection records the texture objects bound by glBindTexture
to each texture type (2D texture, cube map texture, and lookup table). The function overwrites any other existing binding to the same texture. Settings recorded in the texture collection remain until the collection is switched.
When the texture collection is switched, all texture objects recorded in the new texture collection are bound as the new textures.
7.9.3. Destroying Texture Collections
Texture collections can be destroyed with the glDeleteTextures()
function, just like texture objects. Even if a texture collection is destroyed, it does not affect texture bindings to the texture objects recorded in that vertex state collection.
The glDeleteTextures()
function does not immediately destroy a texture collection that is in use. A texture collection remains in use until it is switched with another one. You cannot destroy the default texture collection. Calls to glDeleteTextures
on the default texture collection are ignored.
7.10. Native PICA Format
The GPU's texture unit supports a different texture format than the OpenGL specifications. The format that is actually supported by the texture unit is called the native PICA format. Because libraries do not convert textures loaded in native PICA format, it is more efficient than the standard format.
There are three major differences between this format and the OpenGL specifications.
- Byte order
Bytes are written in a different order because of the way internal addresses are processed.
- V-Flip
The two formats use v-axes that run in opposite directions, when placing texels using UV coordinates.
- Addressing
Texels and compressed data blocks are written in different orders, because of differences between linear addressing (OpenGL) and block addressing (native PICA format).
In the CTR system, v-flip, addressing, and byte-order conversions are run, in that order, on an uncompressed texture (loaded by glTexImage2D
), to convert it from the OpenGL format into the native PICA format. The system converts a compressed texture (loaded by glCompressedTexImage2D
) by running V-flip, ETC compression, addressing, and finally, byte-order conversions. Note that v-flip conversion must precede ETC compression.
7.10.1. Byte Order Swapping
When the format uses more than one byte to represent a single texel and the texture was defined by calling glTexImage2D()
and passing GL_UNSIGNED_BYTE
for type
, the number of bytes swapped (replaced) is the same as the number of bytes that represent a texel.
Data in a compressed format is swapped one block (8 bytes for 4×4 texels) at a time. However, if the format has an alpha channel (the first 8 bytes), the alpha portion is not byte-swapped.
7.10.2. V-Flip Differences
In the OpenGL specifications, images are converted into data starting with the texel at UV coordinates (0.0, 0.0). In the native PICA format, images are converted into data, starting with the texel at UV coordinates (0.0, 1.0). This is the same for both uncompressed and compressed textures.
7.10.3. Differences in Addressing
In the OpenGL specifications, texels are stored consecutively in the U direction (linear addressing). In the native PICA format, blocks of texels are stored, consecutively, in the U direction, but texels within those blocks are stored in a zigzag pattern (block addressing).
7.10.3.1. Uncompressed Textures
Texels are stored in a zigzag pattern within each block of 8×8 texels (as shown by the red lines in the figure), but the blocks are stored consecutively in the U direction.
7.10.3.2. Compressed Textures
A compressed texture compresses each block of 4×4 texels. In the OpenGL specifications, blocks are stored consecutively in the U direction (shown by the blue line in the figure). In the native PICA format, blocks are stored in a zigzag pattern in meta-blocks of 2×2 blocks. The meta-blocks themselves are stored consecutively in the U direction (shown by the red line in the figure).
For more information about compressed textures, see the 3DS Programming Manual: Advanced Graphics.