Shader programs can customize the 3D graphics pipeline and control various graphics effects on the 3DS system.
There are three types of 3DS shader programs: one processes vertices, one creates geometry, and one processes fragments.
The shader program that processes vertices (the vertex shader) can be a unique shader programmed by developers.
The shader program that creates geometry (the geometry shader) is provided by the SDK. Geometry shaders and vertex shaders can be used in conjunction with each other.
The shader program that processes fragments (the fragment shader) is not programmable. Fragment processing is implemented as a fixed pipeline, but it can be controlled through reserved uniforms. This document uses the terms reserved fragment processing and reserved fragment shader to refer to the fragment pipeline and shader program, respectively.
5.1. Creating Shaders
Vertex shaders are the only shader programs that can be created by developers. The series of procedures related to vertex processing follow the OpenGL ES 2.0 specifications, but some features are not supported.
Shader programs are written in an assembly language that is unique to the PICA graphics core. For an application to use a shader program, it must load and then attach a binary generated by a special-purpose assembler and linker. The glShaderSource
and glCompileShader()
functions in the OpenGL ES 2.0 specifications are not implemented.
For more information about how to create a vertex shader, see 8. Vertex Shader and the Vertex Shader Reference.
5.2. Loading Shaders
As explained in 5.1. Creating Shaders, you must load and then attach a shader program's binary data. Use the glCreateShader()
function first to create a shader object.
GLuint glCreateShader(GLenum type);
The value to pass as type
depends on the shader program being loaded. The reserved fragment shader uses a fixed implementation and does not need to be loaded.
Type |
Generated Object |
---|---|
|
A developer-created vertex shader object. |
|
A geometry shader object provided by the SDK. |
Load the shader program binary into memory and then bind it to the GPU with the glShaderBinary()
function.
void glShaderBinary(GLint n, const GLuint* shaders, GLenum binaryformat, const void* binary, GLint length);
For shaders
, specify an array of shader objects, and for n
, specify the number of array elements. Because you can only load a binary that was created by the assembler and linker, set binaryformat
to GL_PLATFORM_BINARY_DMP
. Set binary
to the address at which the shader program binary was loaded and set length
to the binary's size (in bytes).
The loaded shader programs are bound to the array in the order that they were passed to the linker. You can use the map file output by the linker to check the number of elements in the array and the type of shader objects to set. For more information, see the Vertex Shader Reference.
5.3. Attaching Shaders
To use a loaded shader program, an application must attach the shader program to a program object created by glCreateProgram
, and then link that program object.
GLuint glCreateProgram(void);
Unlike in OpenGL ES 2.0, program objects have a 13-bit namespace that is independent of shader objects. Consequently, up to 8191 objects can be created simultaneously. If any of these objects are deleted by glDeleteProgram
, they can be re-created.
Use the glAttachShader()
function to attach a shader program to a program object.
void glAttachShader(GLuint program, GLuint shader);
Set program
to the return value from glCreateProgram
and set shader
to the shader object.
Both the vertex shader and geometry shader are attached from loaded binaries. The reserved fragment shader, on the other hand, does not need to be loaded and is attached by setting shader
to GL_DMP_FRAGMENT_SHADER_DMP
.
You can attach one vertex shader, one geometry shader, and one reserved fragment shader to a single program object. In other words, if a point shader and line shader (both geometry shaders) are attached one after the other, only the line shader is activated.
Use the glLinkProgram()
function to link a program object.
void glLinkProgram(GLuint program);
You can link more than one program object. However, if you use glAttachShader
to attach a different shader program to a linked program object, you must use glLinkProgram
to relink the program object. The program object fails to be linked when the vertex shader and geometry shader use a total of more than 2048 uniforms.
5.4. Using Shaders
Call the glUseProgram()
function to apply a linked shader program to the 3D processing pipeline.
void glUseProgram(GLuint program);
This function allows you to switch between several linked shader programs.
OpenGL allowed you to call the glValidateProgram()
function to validate a shader program, but this function does nothing when it is called on a 3DS system.
void glValidateProgram(GLuint program);
5.5. Detaching Shaders
You can use the glDetachShader()
function to detach shader programs that are no longer necessary.
void glDetachShader(GLuint program, GLuint shader);
5.6. Destroying Shaders
You can use the glDeleteShader()
function to destroy shader objects that are no longer necessary.
void glDeleteShader(GLuint shader);
5.7. Querying Shaders
You can query program objects and shader objects to determine whether they are valid or invalid, and to get parameters and other shader-related information.
5.7.1. Validation
You can use the glIsProgram
and glIsShader()
functions to determine whether program objects and shader objects are valid.
GLboolean glIsProgram(GLuint program); GLboolean glIsShader(GLuint shader);
These functions return a value of GL_TRUE
if the program object or shader object passed as an argument is valid and GL_FALSE
if it is not.
5.7.2. Getting Attached Shader Objects
You can use the glGetAttachedShaders()
function to get the shader objects attached to a program object.
void glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
A list of shader objects attached to the program object specified by program
is stored in the array specified by shaders
. For maxcount
, specify the size of the array specified in shaders
. A GL_INVALID_VALUE
error is generated if program
is invalid or maxcount
is negative.
The count
parameter holds the number of shader objects that were saved. This value is not saved if NULL
is specified, but you can get the number of attached shader objects by calling the glGetProgramiv()
function (described later) with GL_ATTACHED_SHADERS
passed as an argument.
5.7.3. Getting Command List Parameters
You can use the glGetProgramiv
and glGetShaderiv()
functions to get parameters for program objects and shader objects.
void glGetProgramiv(GLuint program, GLenum pname, GLint* params); void glGetShaderiv(GLuint shader, GLenum pname, GLint* params);
These functions store parameter values in params
that correspond to the parameter name specified by pname
. A GL_INVALID_ENUM
error is generated if an invalid value is specified for pname
. A GL_INVALID_VALUE
error is generated if an invalid value is specified for program
or shader
.
The following table shows the parameter names that can be specified for pname
and the parameters that are stored in params
for the glGetProgramiv()
function.
pname |
Values Saved in params |
---|---|
|
|
|
|
|
The same value as when |
|
Always |
|
The number of shader objects attached to the program object. |
|
The number of vertex attributes in the active state. |
|
The number of characters in the longest name of the active vertex attributes. The character count includes the terminating character ( |
|
The number of uniforms in the active state. |
|
The number of characters in the longest name of the active uniforms. The character count includes the terminating character ( |
The following table shows the parameter names that can be specified for pname
, and the parameters that are stored in params
for the glGetShaderiv()
function.
pname |
Values Saved in params |
---|---|
|
The shader type. |
|
|
|
Always |
|
Always |
|
Always |