Back to the OpenGL extension cross reference

GL_ARB_fragment_program


Name


    ARB_fragment_program

Name Strings


    GL_ARB_fragment_program

Contributors


    Bob Beretta
Pat Brown
Matt Craighead
Cass Everitt
Evan Hart
Jon Leech
Bill Licea-Kane
Bimal Poddar
Jeremy Sandmel
Jon Paul Schelter
Avinash Seetharamaiah
Nick Triantos

and contributors to the ARB_vertex_program working group,
the product of which provided the basis for this spec

Contact


    Benj Lipchak, ATI Research (blipchak 'at' ati.com)

IP Status


    Microsoft claims to own intellectual property related to this 
extension.

Status


    Complete.  Approved by ARB on September 18, 2002

Version


    Last Modified Date: August 22, 2003
Revision: 26

Number


    ARB Extension #27

Dependencies


    The extension is written against the OpenGL 1.3 Specification.

OpenGL 1.3 is required.

EXT_texture_lod_bias or OpenGL 1.4 is required.

OpenGL 1.4 affects the definition of this extension.

ARB_vertex_blend and EXT_vertex_weighting affect the definition of
this extension.

ARB_matrix_palette affects the definition of this extension.

ARB_transpose_matrix affects the definition of this extension.

EXT_fog_coord affects the definition of this extension.

EXT_texture_rectangle affects the definition of this extension.

ARB_shadow interacts with this extension.

ARB_vertex_program interacts with this extension.

ATI_fragment_shader interacts with this extension.

NV_fragment_program interacts with this extension.


Overview


    Unextended OpenGL mandates a certain set of configurable per-
fragment computations defining texture application, texture
environment, color sum, and fog operations. Several extensions have
added further per-fragment computations to OpenGL. For example,
extensions have defined new texture environment capabilities
(ARB_texture_env_add, ARB_texture_env_combine, ARB_texture_env_dot3,
ARB_texture_env_crossbar), per-fragment depth comparisons
(ARB_depth_texture, ARB_shadow, ARB_shadow_ambient,
EXT_shadow_funcs), per-fragment lighting (EXT_fragment_lighting,
EXT_light_texture), and environment mapped bump mapping
(ATI_envmap_bumpmap).

Each such extension adds a small set of relatively inflexible per-
fragment computations.

This inflexibility is in contrast to the typical flexibility
provided by the underlying programmable floating point engines
(whether micro-coded fragment engines, DSPs, or CPUs) that are
traditionally used to implement OpenGL's texturing computations.
The purpose of this extension is to expose to the OpenGL application
writer a significant degree of per-fragment programmability for
computing fragment parameters.

For the purposes of discussing this extension, a fragment program is
a sequence of floating-point 4-component vector operations that
determines how a set of program parameters (not specific to an
individual fragment) and an input set of per-fragment parameters are
transformed to a set of per-fragment result parameters.

The per-fragment computations for standard OpenGL given a particular
set of texture and fog application modes (along with any state for
extensions defining per-fragment computations) is, in essence, a
fragment program. However, the sequence of operations is defined
implicitly by the current OpenGL state settings rather than defined
explicitly as a sequence of instructions.

This extension provides an explicit mechanism for defining fragment
program instruction sequences for application-defined fragment
programs. In order to define such fragment programs, this extension
defines a fragment programming model including a floating-point
4-component vector instruction set and a relatively large set of
floating-point 4-component registers.

The extension's fragment programming model is designed for efficient
hardware implementation and to support a wide variety of fragment
programs. By design, the entire set of existing fragment programs
defined by existing OpenGL per-fragment computation extensions can
be implemented using the extension's fragment programming model.

Issues


    This extension is closely related to ARB_vertex_program, and is in 
sync with revision 36 of that spec. ARB_fragment_program will
continue to track changes made to ARB_vertex_program.

(1) Should we provide precision queries?

RESOLVED: We've decided not to include precision queries.
Implementations are expected to meet or exceed the precision
guidelines set forth in the core GL spec, section 2.1.1, p. 6,
as ammended by this extension.

To summarize section 2.1.1, the maximum representable magnitude of
colors must be at least 2^10, while the maximum representable
magnitude of other floating-point values must be at least 2^32.
The individual results of floating-point operations must be
accurate to about 1 part in 10^5.

Here are the reasons why precision queries were not included:
1. It is unclear what the queries should be:
a) min, max, [0,1) granularity
b) min +, max +, min -, max -, [0,1) granularity
c) IEEE mantissa bits, IEEE exponent bits
2. Due to instruction emulation, there is no way to query the
actual precision that can be expected. Should the query
return the best-case or worst-case precision?
3. Implementations may support multiple precisions, on a per-
instruction basis or across the board. How would this be
exposed?
4. Current implementations are able to meet the minimum
requirements specified in the core GL, thanks to its
sufficiently loose wording "... so that the individual
results of floating-point operations are accurate to ABOUT
1 part in 10^5." (Emphasis added.)
5. A conformance test can act as watchdog to ensure
implementations are not cutting corners on precision.
6. Adding precision queries would require a new entrypoint.

See issue 22 regarding reduced-precision modes.

(2) Should the LOD biased texture sample be optional?

RESOLVED: TXB support is mandatory. This exposes useful
functionality which enables blurring and sharpening effects. It
will be more useful to entirely override derivatives (scale
factor) rather than just biasing the level-of-detail. This would
be a future extension to fragment programs.

It should be noted here that the bias introduced per-fragment by
TXB is added to any per-object or per-stage LOD bias. If per-
fragment LOD bias is not necessary, using the per-object and/or
per-stage LOD biases may perform better.

(3) Should we include the ability to bind to the color matrix? How
about others? Program matrices?

RESOLVED: We will not specifically add anything that depends on
the ARB_imaging subset. So we have not included matrix bindings
to the color matrix (or parameter bindings to the color biases,
etc.). However, we have included matrix binding support and
support for all of the matrices present in ARB_vertex_program.

(4) Should we include the ability to bind to just a texcoord
attribute's S,T components? (Or just S, or S,T,P for that matter?)

RESOLVED: No. Issue #15 below obviates this issue by making the
texture coordinate usage within a program explicit, thereby making
optimizations to reduce the number of interpolated texture
coordinates something an implementation can do at compile time
instead of having to do it during every texture target change.

(5) What other instructions should be added? Should any be removed?

RESOLVED: The differences between the ARB_vertex_program
instruction set and the ARB_fragment_program instruction set are
minimal. ARB_fragment_program removes the LOG and EXP rough
approximation instructions and the ARL address register load
instruction. ARB_fragment_program adds the SIN/COS/SCS
trigonometric instructions, the LRP linear interpolation
instruction, the CMP compare instruction, and the TEX/TXP/TXB/KIL
texture instructions.

(6) Should depth output be a program option or a mandatory feature?

RESOLVED: Depth output capability should be mandatory.

(6a) How should per-vertex geometric depth clipping be handled when
replacing depth in a fragment program?

RESOLVED: Per-vertex geometric depth clipping should be performed
by the GL as usual, so no spec change is required. The ideal
behavior would be to disable near and far clipping planes when
replacing depth, but not all implementations can natively support
disabling individual clip planes.

(6b) How should depth output from the fragment program be further
processed before being handed to the per-fragment operations?

RESOLVED: Depth gets clamped by GL to [0,1]. App has access to
depth range as a bindable parameter if it wants to either scale
and bias its depth to fall within the depth range, or to kill
fragments outside the depth range.

(7) If a fragment program does not write a color value, what should
be the final color of the fragment?

RESOLVED: The final fragment color is undefined. Note that it may
be perfectly reasonable to have a program that computes depth
values but not colors. Fragment colors are often irrelevant if
color writes are disabled (via ColorMask).

(7a) If a fragment program does not write a depth value, what should
be the final depth value of the fragment?

RESOLVED: "Depth fly-over" (using the conventional depth produced
by rasterization) should happen whenever a depth-replacing program
is not in use. A depth-replacing program is defined as a program
that writes to result.depth in at least one instruction. The
presence of a depth declaration alone DOES NOT designate a depth-
replacing program. The intention is that a future extension
introducing conditional execution will still consider a program to
be depth-replacing even if the instruction(s) writing to
result.depth do(es) not execute.

Other considered definitions of depth-replacing program:
1. The presence of a depth declaration -OR- the use of
result.depth as an instruction destination anywhere in the
program designates a depth-replacing program.
2. Every program is a depth-replacing program, but the GL
initializes the depth output to be the depth produced by
rasterization. The app may then overwrite the depth output.
3. Every program is a depth-replacing program, and the app is
solely responsible for copying the depth input to depth
output if desired.

(8) Should relative addressing, like that defined in
ARB_vertex_program, be supported in this spec?

RESOLVED: No, relative addressing won't be included in this spec.

(9) Should full-featured operand component swizzling, like that
defined in ARB_vertex_program, be supported in this spec?

RESOLVED: Yes, full swizzling is mandatory.

(10) Should texture instructions contain specific limitations on
operations that can be performed? For example, should write masks
or operand component swizzling be disallowed?

RESOLVED: Texture instructions are specified to be very similar to
ALU instructions. They have been given 3-letter names, they allow
writemasking and saturation (which would be useful for floating-
point texture formats), source swizzles and negates, and the
ability to use parameters as sources.

(11) Should we standardize options for stencil or aux data buffer
outputs?

RESOLVED: Stencil and aux data buffers will be saved for a
possible future extension to fragment programs.

(12) Should depth output be pulled from the 3rd or 4th component?

RESOLVED: 3rd component, as the 3rd component is also used for
depth input from the "fragment.position" attribute.

(13) Which stages are subsumed by fragment programs?

RESOLVED: Texturing, color sum, and fog.

(14) What should the minimum resource limits be?

RESOLVED: 10 attributes, 24 parameters, 4 texture indirections,
48 ALU instructions, 24 texture instructions, and 16 temporaries.

(15) OpenGL provides a hierarchy of texture enables (cube map, 3D,
2D, 1D). Should the texture sampling instructions here override
that hierarchy and select specific texture targets?

RESOLVED: Yes. This removes a potential pitfall for developers:
leaving the hierarchy of enables in an undesired state. It makes
programs more readable as the intent of the sample is more
obvious. Finally, it allows compilers to be more aggressive as
to which texcoord components are "don't cares" without having to
recompile programs when fixed-function texenables change. One
drawback is that programs cannot be reused for both 2D and 3D
texturing, for example, by simply changing the texture enables.

Texture sampling can be specified by instructions like

TEX myTexel, fragment.texcoord[1], texture[2], 3D;

which would indicate to use texture coordinate set number 1 to
sample from the texture object bound to the TEXTURE_3D target on
texture image unit 2.

Each texture unit can have only one "active" target. Programs are
not allowed to reference different texture targets in the same
texture image unit. In the example above, any other texture
instructions using texture image unit 2 must specify the 3D
texture target.

Note that every texture image unit always has a texture bound to
every texture target, whether it is a named texture object or a
default texture. However, the texture may not be complete as
defined in section 3.8.9 of the core GL spec. See issue 23.

(16) Should aux texture units be additional units on top of existing
full-featured texture units, or should this spec fully deprecate
"legacy" texture units and only expose texture coordinate sets and
texture image units?

Background: Some implementations are able to expose more
"texture image units" (texture maps and associated parameters)
than "texture coordinate sets" (current texcoords, texgen, and
texture matrices). A conventional GL "texture unit" encompasses
both a texture image unit and a texture coordinate set as well as
texture environment state.

RESOLVED: Yes, deprecate "legacy" texture units. This is a more
flexible model.

(17) Should fragment programs affect all fragments, or just those
produced by the rasterization of points, lines, and triangles?

RESOLVED: Every fragment generated by the GL is subject to
fragment program mode. This includes point, line, and polygon
primitives as well as pixel rectangles and bitmaps.

(18) Should per-fragment position and fogcoord be bindable as
fragment attributes?

RESOLVED: Yes, interpolated fogcoord will make per-fragment
fog application possible, in addition to full fog stage
subsummation. Interpolated window position, especially depth,
enables interesting depth-replacing algorithms.

(19) What characters should be used to identify individual
components in swizzle selectors and write masks?

RESOLVED: ARB_vertex_program provides "xyzw". This extension
supports "xyzw" and also provides "rgba" for better readability
when dealing with RGBA color values. Adding support for special
identifiers for dealing with texture coordinates was considered
and rejected. "strq" could be used to identify texture coordinate
components, but the "r" would conflict with the "r" from "rgba".
"stpq" would be another possibility, but could be a source of
confusion.

(20) Should implementations be required to support all programs that
fit within the exported limits on the number of resources (e.g.,
instructions, temporaries) that can be present in a program, even if
it means falling back to software? Should implementations be
required to reject programs that could never be accelerated?

RESOLVED: No and no. An implementation is allowed to fail
ProgramStringARB due to the program exceeding native resources.
Note that this failure must be invariant with respect to all other
OpenGL state. In other words, a program cannot succeed to load
with default state, but then fail to load when certain GL state
is altered. However, an implementation is not required to fail
when a program would exceed native resources, and is in fact
encouraged to fallback to a software path. See issue 21 for a way
of determining if this has happened.

This notable departure from ARB_vertex_program was made as an
accommodation to vendors who could not justify implementing a
software fallback path which would be relatively slow even
compared to an ARB_vertex_program software fallback path.

Two issues with this decision:
1. The API limits become hints, and one can no longer tell by
visual inspection whether or not a program will load on
every implementation.
2. Program loading will now depend on the optimizer, which may
vary from release to release of an implementation. A
program that succeeded to load when an ISV first wrote it
may fail to load in a future driver version, and vice versa.

(21) How can applications determine if their programs are too large
to run on the native (likely hardware) implementation, and therefore may
run with reduced performance?

RESOLVED: The following code snippet uses a native resource
query to guarantee a program is loaded natively (or not at all):

GLboolean ProgramStringIsNative(GLenum target, GLenum format,
GLsizei len, const GLvoid *string)
{
GLint errorPos, isNative;
glProgramStringARB(target, format, len, string);
glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);
glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,
GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative);
if ((errorPos == -1) && (isNative == 1))
return GL_TRUE;
else
return GL_FALSE;
}

Note that a program that successfully loads, and falls under the
native limits, is still not guaranteed to execute in hardware.
Lack of other resources (e.g., texture memory) or the use of other
OpenGL features not natively supported by the implementation
(e.g., textures with borders) may also prevent the program from
executing in hardware.

(22) Should we provide applications with a method to control the
level of precision used to carry out fragment program computations?

RESOLVED: Yes. The GL implementation ultimately has control over
the level of precision used for fragment program computations.
However, the "ARB_precision_hint_fastest" and
"ARB_precision_hint_nicest" program options allow applications to
guide the GL implementation in its precision selection. The
"fastest" option encourages the GL to minimize execution time,
with possibly reduced precision. The "nicest" option encourages
the GL to maximize precision, with possibly increased execution
time.

If the precision hint is not "fastest", GL implementations should
perform low-precision operations only if they could not
appreciably affect the final results of the program. Regardless
of the precision hint, GL implementations are discouraged from
reducing the precision of computations so aggressively that final
rendering results could be seriously compromised due to overflow
of intermediate values or insufficient number of mantissa bits.

Some implementations may provide only a single level of precision,
in which case these hints may have no effect. However, all
implementations will accept these options, even if they are
silently ignored.

More explicit control of precision, such as provided in "C" with
data types such as "short", "int", "float", "double", may also be
a desirable feature, but this level of detail is left to a
separate extension.

(23) What is the result of a sample from an incomplete texture?
The definition of texture completeness can be found in section 3.8.9
of the core GL spec.

RESOLVED: The result of a sample from an incomplete texture is the
constant vector (0,0,0,1). The benefit of defining the result to
be a constant is that broken apps are guaranteed to generate
unexpected (black) results from their bad samples. If we were to
leave the result undefined, some implementations may generate
expected results some of the time, for example when magfiltering,
giving app developers a false sense of correctness in their apps.

(24) What is a texture indirection, and how is it counted?

RESOLVED: On some implementations, fragment programs that have
complex texture dependency chains may not be supported, even if
the instruction counts fit within the exported limits. A texture
dependency occurs when a texture instruction depends on the
result of a previous instruction (ALU or texture) for use as its
texture coordinate.

A texture indirection can be considered a node in the texture
dependency chain. Each node contains a set of texture
instructions which execute in parallel, followed by a sequence of
ALU instructions. A dependent texture instruction is one that
uses a temporary as an input coordinate rather than an attribute
or a parameter. A program with no dependent texture instructions
(or no texture instructions at all) will have a single node in
its texture dependency chain, and thus a single indirection.

API-level texture indirections are counted by keeping track of
which temporaries are read and written within the current node in
the texture dependency chain. When a texture instruction is
encountered, an indirection may be added and a new node started
if either of the following two conditions is true:

1. the source coordinate of the texture instruction is a
temporary that has already been written in the current node,
either by a previous texture instruction or ALU instruction;

2. the result of the texture instruction is a temporary that
has already been read or written in the current node by an
ALU instruction.

The texture instruction provoking a new indirection and all
subsequent instructions are added to the new node. This process
is repeated until the end of the program is encountered. Below
is some pseudo-code to describe this:

indirections = 1;
tempsOutput = 0;
aluTemps = 0;
while (i = getInst())
{
if (i.type == TEX)
{
if (((i.input.type == TEMP) &&
(tempsOutput & (1 << i.input.index))) ||
((i.op != KILL) && (i.output.type == TEMP) &&
(aluTemps & (1 << i.output.index))))
{
indirections++;
tempsOutput = 0;
aluTemps = 0;
}
} else {
if (i.input1.type == TEMP)
aluTemps |= (1 << i.input1.index);
if (i.input2 && i.input2.type == TEMP)
aluTemps |= (1 << i.input2.index);
if (i.input3 && i.input3.type == TEMP)
aluTemps |= (1 << i.input3.index);
if (i.output.type == TEMP)
aluTemps |= (1 << i.output.index);
}
if ((i.op != KILL) && (i.output.type == TEMP))
tempsOutput |= (1 << i.output.index);
}

For example, the following programs would have 1, 2, and 3
texture indirections, respectively:

!!ARBfp1.0
# No texture instructions, but always 1 indirection
MOV result.color, fragment.color;
END

!!ARBfp1.0
# A simple dependent texture instruction, 2 indirections
TEMP myColor;
MUL myColor, fragment.texcoord[0], fragment.texcoord[1];
TEX result.color, myColor, texture[0], 2D;
END

!!ARBfp1.0
# A more complex example with 3 indirections
TEMP myColor1, myColor2;
TEX myColor1, fragment.texcoord[0], texture[0], 2D;
MUL myColor1, myColor1, myColor1;
TEX myColor2, fragment.texcoord[1], texture[1], 2D;
# so far we still only have 1 indirection
TEX myColor2, myColor1, texture[2], 2D; # This is #2
TEX result.color, myColor2, texture[3], 2D; # And #3
END

Note that writemasks for the temporaries written and swizzles
for the temporaries read are not taken into consideration when
counting indirections. This makes hand-counting of indirections
by a developer an easier task.

Native texture indirections may be counted differently by an
implementation to reflect its exact restrictions, to reflect the
true dependencies taking into account writemasks and swizzles,
and to reflect optimizations such as instruction reordering.

For implementations with no restrictions on the number of
indirections, the maximum indirection count will equal the
maximum texture instruction count.

(25) How can a program reduce SCS's scalar operand to the
fundamental period [-PI,PI]?

RESOLVED: Unlike the individual SIN and COS instructions, SCS
requires that its argument be reduced ahead of time to the
fundamental period. The reason SCS doesn't perform this
operation automatically is that it may make unnecessary redundant
work for programs that already have their operand in the correct
range. Other programs that do need to reduce their operand
simply need to add a block of code before the SCS instruction:

PARAM myParams = { 0.5, -3.14159, 6.28319, 0.15915 };
MAD myOperand.x, myOperand.x, myParams.w, myParams.x; # a = (a/(2*PI))+0.5
FRC myOperand.x, myOperand.x; # a = frac(a)
MAD myOperand.x, myOperand.x, myParams.z, myParams.y # a = (a*2*PI)-PI
...
SCS myResult, myOperand.x;

(26) Is depth output from a fragment program guaranteed to be
invariant with respect to depth produced via conventional
rasterization?

RESOLVED: No. The floating-point representation of depth values
output from a fragment program may lead to the output of depth
with less precision than the depth output by convention GL
rasterization. For example, a floating-point representation with
16 bits of mantissa will certainly produce depth with lesser
precision than that of conventional rasterization used in
conjunction with a 24-bit depth buffer, where all values are
maintained as integers. Be aware of this when mixing conventional
GL rendering with fragment program rendering.

(27) How can conventional GL fog application be achieved within a
fragment program?

RESOLVED: Program options have been introduced that allow a
program to request fog to be applied to the final clamped fragment
color before being passed along to the antialiasing application
stage. This makes it easy for:
1. developers to request conventional fog behavior
2. implementations with dedicated fog hardware to use it
3. implementations without dedicated fog hardware, so they need
not track fog state after compilation, and constantly
recompile when fog state changes.

The three mandatory options are ARB_fog_exp, ARB_fog_exp2, and
ARB_fog_linear. As these options are mutually exclusive by
nature, specifying more than one is not useful. If more than one
is specified, the last one encountered in the <optionSequence>
will be the one to actually modify the execution environment.

(28) Why have all of the enums, entrypoints, GLX protocol, and spec
language shared with ARB_vertex_program been reproduced here?

RESOLVED: The two extensions are independent of one another, in
so far as an implementation need not support both of them in order
to support one of them. Everything needed to implement or make
use of ARB_fragment_program is present in this spec without the
need to refer to the ARB_vertex_program spec. When and if these
two extensions are incorporated into the core OpenGL, the
significant overlap of the two will be collapsed into a single
instance of the shared parts.

(29) How might an implementation implement the fog options? To What
does the extra resource consumption described in 3.11.4.5.1
correspond?

RESOLVED: The following code snippets reflect possible
implementations of the fog options. While an implementation may
use other instruction sequences to achieve the same result, or may
use external fog hardware if available, all implementations must
enforce the API-level resource consumption as described: 2 params,
1 temp, 1 attribute, and 3, 4, or 2 instructions. "finalColor" in
the examples below is the color that would otherwise be
"result.color", with components clamped to the range [0,1].
"result.color.a" is assumed to have already been written, as fog
blending does not affect the alpha component.

EXP:
# Exponential fog
# f = exp(-d*z)
#
PARAM p = {DENSITY/LN(2), NOT USED, NOT USED, NOT USED};
PARAM fogColor = state.fog.color;
TEMP fogFactor;
ATTRIB fogCoord = fragment.fogcoord.x;
MUL fogFactor.x, p.x, fogCoord.x;
EX2_SAT fogFactor.x, -fogFactor.x;
LRP result.color.rgb, fogFactor.x, finalColor, fogColor;

EXP2:
#
# 2nd-order Exponential fog
# f = exp(-(d*z)^2)
#
PARAM p = {DENSITY/SQRT(LN(2)), NOT USED, NOT USED, NOT USED};
PARAM fogColor = state.fog.color;
TEMP fogFactor;
ATTRIB fogCoord = fragment.fogcoord.x;
MUL fogFactor.x, p.x, fogCoord.x;
MUL fogFactor.x, fogFactor.x, fogFactor.x;
EX2_SAT fogFactor.x, -fogFactor.x;
LRP result.color.rgb, fogFactor.x, finalColor, fogColor;

LINEAR:
#
# Linear fog
# f = (end-z)/(end-start)
#
PARAM p = {-1/(END-START), END/(END-START), NOT USED, NOT USED};
PARAM fogColor = state.fog.color;
TEMP fogFactor;
ATTRIB fogCoord = fragment.fogcoord.x;
MAD_SAT fogFactor.x, p.x, fogCoord.x, p.y;
LRP result.color.rgb, fogFactor.x, finalColor, fogColor;

(30) Why is the order of operands for the CMP instruction different
than the order used by another popular graphics API?

RESOLVED: No other graphics API was used as a basis for the
design of ARB_fragment_program except ARB_vertex_program, which
did not have a CMP instruction. This independent evolution
naturally led to differences in minor details such as order of
operands. This discrepancy is noted here to help developers
familiar with the other API to avoid this potential pitfall.

(31) Is depth offset applied to the window z value before it enters
the fragment program?

RESOLVED: As in the base OpenGL specification, the depth offset
generated by polygon offset is added during polygon rasterization.
The depth value provided to shaders in the fragment.position.z
attribute already includes polygon offset, if enabled. If the
depth value is replaced by a fragment program, the polygon offset
value will NOT be recomputed and added back after fragment program
execution.

NOTE: This is probably not desirable for fragment programs that
modify depth values since the partials used to generate the offset
may not match the partials of the computed depth value.


New Procedures and Functions


    void ProgramStringARB(enum target, enum format, sizei len, 
const void *string);

void BindProgramARB(enum target, uint program);

void DeleteProgramsARB(sizei n, const uint *programs);

void GenProgramsARB(sizei n, uint *programs);

void ProgramEnvParameter4dARB(enum target, uint index,
double x, double y, double z, double w);
void ProgramEnvParameter4dvARB(enum target, uint index,
const double *params);
void ProgramEnvParameter4fARB(enum target, uint index,
float x, float y, float z, float w);
void ProgramEnvParameter4fvARB(enum target, uint index,
const float *params);

void ProgramLocalParameter4dARB(enum target, uint index,
double x, double y, double z, double w);
void ProgramLocalParameter4dvARB(enum target, uint index,
const double *params);
void ProgramLocalParameter4fARB(enum target, uint index,
float x, float y, float z, float w);
void ProgramLocalParameter4fvARB(enum target, uint index,
const float *params);

void GetProgramEnvParameterdvARB(enum target, uint index,
double *params);
void GetProgramEnvParameterfvARB(enum target, uint index,
float *params);

void GetProgramLocalParameterdvARB(enum target, uint index,
double *params);
void GetProgramLocalParameterfvARB(enum target, uint index,
float *params);

void GetProgramivARB(enum target, enum pname, int *params);

void GetProgramStringARB(enum target, enum pname, void *string);

boolean IsProgramARB(uint program);


New Tokens


    Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, 
by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
and GetDoublev, and by the <target> parameter of ProgramStringARB,
BindProgramARB, ProgramEnvParameter4[df][v]ARB,
ProgramLocalParameter4[df][v]ARB, GetProgramEnvParameter[df]vARB,
GetProgramLocalParameter[df]vARB, GetProgramivARB and
GetProgramStringARB.

FRAGMENT_PROGRAM_ARB 0x8804

Accepted by the <format> parameter of ProgramStringARB:

PROGRAM_FORMAT_ASCII_ARB 0x8875

Accepted by the <pname> parameter of GetProgramivARB:

PROGRAM_LENGTH_ARB 0x8627
PROGRAM_FORMAT_ARB 0x8876
PROGRAM_BINDING_ARB 0x8677
PROGRAM_INSTRUCTIONS_ARB 0x88A0
MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1
PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2
MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3
PROGRAM_TEMPORARIES_ARB 0x88A4
MAX_PROGRAM_TEMPORARIES_ARB 0x88A5
PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6
MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7
PROGRAM_PARAMETERS_ARB 0x88A8
MAX_PROGRAM_PARAMETERS_ARB 0x88A9
PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA
MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB
PROGRAM_ATTRIBS_ARB 0x88AC
MAX_PROGRAM_ATTRIBS_ARB 0x88AD
PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE
MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF
MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4
MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5
PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6

PROGRAM_ALU_INSTRUCTIONS_ARB 0x8805
PROGRAM_TEX_INSTRUCTIONS_ARB 0x8806
PROGRAM_TEX_INDIRECTIONS_ARB 0x8807
PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x8808
PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x8809
PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x880A
MAX_PROGRAM_ALU_INSTRUCTIONS_ARB 0x880B
MAX_PROGRAM_TEX_INSTRUCTIONS_ARB 0x880C
MAX_PROGRAM_TEX_INDIRECTIONS_ARB 0x880D
MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB 0x880E
MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB 0x880F
MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB 0x8810

Accepted by the <pname> parameter of GetProgramStringARB:

PROGRAM_STRING_ARB 0x8628

Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,
GetFloatv, and GetDoublev:

PROGRAM_ERROR_POSITION_ARB 0x864B
CURRENT_MATRIX_ARB 0x8641
TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7
CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640
MAX_PROGRAM_MATRICES_ARB 0x862F
MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E

MAX_TEXTURE_COORDS_ARB 0x8871
MAX_TEXTURE_IMAGE_UNITS_ARB 0x8872

Accepted by the <name> parameter of GetString:

PROGRAM_ERROR_STRING_ARB 0x8874

Accepted by the <mode> parameter of MatrixMode:

MATRIX0_ARB 0x88C0
MATRIX1_ARB 0x88C1
MATRIX2_ARB 0x88C2
MATRIX3_ARB 0x88C3
MATRIX4_ARB 0x88C4
MATRIX5_ARB 0x88C5
MATRIX6_ARB 0x88C6
MATRIX7_ARB 0x88C7
MATRIX8_ARB 0x88C8
MATRIX9_ARB 0x88C9
MATRIX10_ARB 0x88CA
MATRIX11_ARB 0x88CB
MATRIX12_ARB 0x88CC
MATRIX13_ARB 0x88CD
MATRIX14_ARB 0x88CE
MATRIX15_ARB 0x88CF
MATRIX16_ARB 0x88D0
MATRIX17_ARB 0x88D1
MATRIX18_ARB 0x88D2
MATRIX19_ARB 0x88D3
MATRIX20_ARB 0x88D4
MATRIX21_ARB 0x88D5
MATRIX22_ARB 0x88D6
MATRIX23_ARB 0x88D7
MATRIX24_ARB 0x88D8
MATRIX25_ARB 0x88D9
MATRIX26_ARB 0x88DA
MATRIX27_ARB 0x88DB
MATRIX28_ARB 0x88DC
MATRIX29_ARB 0x88DD
MATRIX30_ARB 0x88DE
MATRIX31_ARB 0x88DF


Additions to Chapter 2 of the OpenGL 1.3 Specification (OpenGL Operation)


    Modify Section 2.1.1, Floating-Point Computation (p. 6)

(modify first paragraph, p. 6) ... The maximum representable
magnitude of a floating-point number used to represent position,
normal, or texture coordinates must be at least 2^32; the maximum
representable magnitude for colors must be at least 2^10. ...


Modify Section 2.7, Vertex Specification (p. 19)

(modify second paragraph, p. 20) Implementations support more than
one set of texture coordinates. The commands

void MultiTexCoord{1234}{sifd}(enum texture, T coords);
void MultiTexCoord{1234}{sifd}v(enum texture, T coords);

take the coordinate set to be modified as the <texture> parameter.
<texture> is a symbolic constant of the form TEXTUREi, indicating
that texture coordinate set i is to be modified. The constants obey
TEXTUREi = TEXTURE0 + i (i is in the range 0 to k-1, where k is the
implementation-dependent number of texture units defined by
MAX_TEXTURE_COORDS_ARB).


Modify Section 2.8, Vertex Arrays (p. 21)

(modify first paragraph, p. 21) ... The client may specify up to 5
plus the value of MAX_TEXTURE_COORDS_ARB arrays: one each to store
vertex coordinates...


(modify first paragraph, p. 23) The command

void ClientActiveTexture(enum texture);

is used to select the vertex array client state parameters to be
modified by the TexCoordPointer command and the array affected by
EnableClientState and DisableClientState with parameter
TEXTURE_COORD_ARRAY. This command sets the client state variable
CLIENT_ACTIVE_TEXTURE. Each texture coordinate set has a client
state vector which is selected when this command is invoked. This
state vector includes the vertex array state. This call also
selects the texture coordinate set state used for queries of client
state.


(modify first paragraph, p. 28) If the number of supported texture
coordinate sets (the value of MAX_TEXTURE_COORDS_ARB) is k, ...


Modify Section 2.10.2, Matrices (p. 31)

(modify first paragraph, p. 31) The projection matrix and model-view
matrix are set and modified with a variety of commands. The
affected matrix is determined by the current matrix mode. The
current matrix mode is set with

void MatrixMode(enum mode);

which takes one of the pre-defined constants TEXTURE, MODELVIEW,
COLOR, PROJECTION, or MATRIX<i>_ARB as the argument. In the case of
MATRIX<i>_ARB, <i> is an integer between 0 and <n>-1 indicating one
of <n> program matrices where <n> is the value of the implementation
defined constant MAX_PROGRAM_MATRICES_ARB. Such program matrices
are described in section 3.11.7. TEXTURE is described later in
section 2.10.2, and COLOR is described in section 3.6.3. If the
current matrix mode is MODELVIEW, then matrix operations apply to
the model-view matrix; if PROJECTION, then they apply to the
projection matrix.


(modify first paragraph, p. 34) For each texture coordinate set, a
4x4 matrix is applied to the corresponding texture coordinates...


(modify first and second paragraphs, p. 35) The command

void ActiveTexture(enum texture);

specifies the active texture unit selector, ACTIVE_TEXTURE. Each
texture unit contains up to two distinct sub-units: a texture
coordinate processing unit (consisting of a texture matrix stack and
texture coordinate generation state) and a texture image unit
(consisting of all the texture state defined in Section 3.8). In
implementations with a different number of supported texture
coordinate sets and texture image units, some texture units may
consist of only one of the two sub-units.

The active texture unit selector specifies the texture coordinate
set accessed by commands involving texture coordinate processing.
Such commands include those accessing the current matrix stack (if
MATRIX_MODE is TEXTURE), TexGen (section 2.10.4), Enable/Disable (if
any texture coordinate generation enum is selected), as well as
queries of the current texture coordinates and current raster
texture coordinates. If the texture coordinate set number
corresponding to the current value of ACTIVE_TEXTURE is greater than
or equal to the implementation-dependent constant
MAX_TEXTURE_COORDS_ARB, the error INVALID_OPERATION is generated by
any such command.

The active texture unit selector also selects the texture image unit
accessed by commands involving texture image processing (section
3.8). Such commands include all variants of TexEnv, TexParameter,
and TexImage commands, BindTexture, Enable/Disable for any texture
target (e.g., TEXTURE_2D), and queries of all such state. If the
texture image unit number corresponding to the current value of
ACTIVE_TEXTURE is greater than or equal to the implementation-
dependent constant MAX_TEXTURE_IMAGE_UNITS_ARB, the error
INVALID_OPERATION is generated by any such command.

ActiveTexture generates the error INVALID_ENUM if an invalid
<texture> is specified. <texture> is a symbolic constant of the
form TEXTUREi, indicating that texture unit i is to be modified.
The constants obey TEXTUREi = TEXTURE0 + i (i is in the range 0 to
k-1, where k is the larger of the MAX_TEXTURE_COORDS_ARB and
MAX_TEXTURE_IMAGE_UNITS_ARB). For compatibility with old OpenGL
specifications, the implementation-dependent constant
MAX_TEXTURE_UNITS specifies the number of conventional texture units
supported by the implementation. Its value must be no larger than
the minimum of MAX_TEXTURE_COORDS_ARB and
MAX_TEXTURE_IMAGE_UNITS_ARB.


(modify last paragraph, p. 35) The state required to implement
transformations consists of a <n>-value integer indicating the
current matrix mode (where <n> is 4 + the number of supported
texture and program matrices), a stack of at least two 4x4 matrices
for each of COLOR, PROJECTION, and TEXTURE with associated stack
pointers, <n> stacks (where <n> is at least 8) of at least one 4x4
matrix for each MATRIX<i>_ARB with associated stack pointers, and a
stack of at least 32 4x4 matrices with an associated stack pointer
for MODELVIEW. Initially, there is only one matrix on each stack,
and all matrices are set to the identity. The initial matrix mode
is MODELVIEW. The initial value of ACTIVE_TEXTURE is TEXTURE0.


Additions to Chapter 3 of the OpenGL 1.3 Specification (Rasterization)


    Modify Chapter 3, Introduction (p. 58)

(modify first paragraph, p. 58) ... Figure 3.1 diagrams the
rasterization process. The color value assigned to a fragment is
initially determined by the rasterization operations (sections 3.3
through 3.7) and modified by either the execution of the texturing,
color sum, and fog operations as defined in sections 3.8, 3.9, and
3.10, or of a fragment program defined in section 3.11. The final
depth value is initially determined by the rasterization operations
and may be modified or replaced by a fragment program.

(modify Figure 3.1)

_ +---------------+ FRAGMENT_PROGRAM_ARB
/|| Point | enable
/ | Rasterization |\ |
/ +---------------+ \ V o-------------+
From / +---------------+ \ |
Primitive ---> | Line |---+++--->o o |
Assembly \ | Rasterization | / || | |
\ +---------------+ / || | |
\ +---------------+/ || +-----+-----+ +----+-----+
\|| Polygon | || | Texturing | | Fragment |
- | Rasterization | / | +-----+-----+ | Program |
+---------------+ / | | +----+-----+
+---------------+ / | +-----+-----+ |
| Pixel |/ | | Color Sum | |
DrawPixels --> | Rectangle | / +-----+-----+ |
| Rasterization | / | V
+---------------+ / +-----+-----+
+---------------+ / | Fog |---> Fragments
Bitmap ----> | Bitmap |/ +-----------+
| Rasterization |
+---------------+


Modify Section 3.3, Points (p. 63)

(modify first and second paragraphs, p. 64) All fragments produced
in rasterizing a non-antialiased point are assigned the same
associated data, which are those of the vertex corresponding to the
point. (delete reference to divide by q)

If antialiasing is enabled, then ... The data associated with each
fragment are otherwise the data associated with the point being
rasterized. (delete reference to divide by q)


Modify Section 3.4.1, Basic Line Segment Rasterization (p. 66)

(modify first paragraph, p. 68) ... (Note that t=0 at p_a and t=1 at
p_b). The value of an associated datum f from the fragment center,
whether it be R, G, B, or A (in RGBA mode) or a color index (in
color index mode) or the s, t, r, or q texture coordinate or the
clip w coordinate (the depth value, window z, must be found using
equation 3.3, below), is found as

f = (1-t)*(f_a/w_a) + t*(f_b/w_b) (3.2)
-----------------------------
(1-t)*(1/w_a) + t*(1/w_b)

where f_a and f_b are the data associated with the starting and
ending endpoints of the segment, respectively; w_a and w_b are the
clip w coordinates of the starting and ending endpoints of the
segments, respectively. Note that linear interpolation would use

f = (1-t)*f_a + t*f_b. (3.3)

... A GL implementation may choose to approximate equation 3.2 with
3.3, but this will normally lead to inacceptable distortion effects
when interpolating texture coordinates or clip w coordinates.


Modify Section 3.5.1, Basic Polygon Rasterization (p. 73)

(modify third and fourth paragraphs, p. 74) Denote a datum at p_a,
p_b, or p_c as f_a, f_b, or f_c, respectively. Then the value f of
a datum at a fragment produced by rasterizing a triangle is given by

f = a*(f_a/w_a) + b*(f_b/w_b) + c*(f_c/w_c) (3.4)
---------------------------------------
a*(1/w_a) + b*(1/w_b) + c*(1/w_c)

where w_a, w_b, and w_c are the clip w coordinates of p_a, p_b, and
p_c, respectively. a, b, and c are the barycentric coordinates of
the fragment for which the data are produced. a, b, and c must
correspond precisely to the ... at the fragment's center.

Just as with line segment rasterization, equation 3.4 may be
approximated by

f = a*f_a + b*f_b + c*f_c;

this may yield ... for texture coordinates or clip w coordinates.


Modify Section 3.6.4, Rasterization of Pixel Rectangles (p. 91)

(modify third paragraph, p. 103) A fragment arising from a group ...
the color and texture coordinates are given by those associated with
the current raster position. (delete reference to divide by q)
Groups arising from DrawPixels...


Modify Section 3.7, Bitmaps (p. 113)

(modify third paragraph, p. 114) Otherwise, a rectangular array ...
The associated data for each fragment are those associated with the
current raster position. (delete reference to divide by q) Once
the fragments have been produced ...


Modify Section 3.8, Texturing (p. 115)

(add new paragraphs before first paragraph, p. 115) Texture
coordinate sets are mapped to RGBA colors for application to
primitives in one of two modes. The first mode, described in this
and subsequent sections, is GL's conventional multitexture pipeline,
describing texture environment and texture application. The second
mode, referred to as fragment program mode and described in section
3.11, applies textures, color sum, and fog as specified in an
application-supplied fragment program.

The fragment program mode is enabled and disabled using the generic
Enable and Disable commands, respectively, with the symbolic
constant FRAGMENT_PROGRAM_ARB. The required state is one bit
indicating whether the fragment program mode is enabled or disabled.
In the initial state, the fragment program mode is disabled. When
fragment program mode is enabled, texturing, color sum, and fog
application stages are ignored and a general purpose program is
executed instead.

(modify first and second paragraph, p. 115) Conventional texturing
is employed when fragment program mode is disabled. Texturing maps
... color of an image at the location indicated by a fragment's
texture coordinates to modify the fragment's primary RGBA color.
Texturing does not affect the secondary color.

An implementation may support texturing using more than one image at
a time. In this case the fragment carries multiple sets of texture
coordinates which are used to index ...

(add paragraph before 1st paragraph, p. 116) Except when in fragment
program mode (section 3.11), the (s,t,r) texture coordinates used
for texturing are the values s/q, t/q, and r/q, respectively, where
s, t, r, and q are the texture coordinates associated with the
fragment. When in fragment program mode, the (s,t,r) texture
coordinates are specified by the program. If q is less than or
equal to zero, the results of texturing are undefined.


Modify Section 3.8.7, Texture Minification (p. 135)

(add new paragraph after first paragraph, p. 137) When fragment
program mode is enabled, the derivatives of the coordinates may be
ill-defined or non-existent. As a result, the implementation is
free to approximate these derivatives with such techniques as
differencing. The only requirement is that texture samples be
equivalent across the two modes. In other words, the texture sample
chosen for a fragment of a primitive must be invariant between
fragment program mode and conventional mode subject to the rules
set forth in Appendix A, Invariance.


Modify Section 3.8.13, Texture Application (p. 149)

(modify fourth paragraph, p. 152) Texturing is enabled and disabled
individually for each texture unit. If texturing is disabled for
one of the units, then the fragment resulting from the previous unit
is passed unaltered to the following unit. Individual texture units
beyond those specified by MAX_TEXTURE_UNITS may be incomplete and
are always treated as disabled.


Insert a new Section 3.11, (p. 154), between existing sections 3.10
and 3.11. Renumber 3.11, Antialiasing Application, to 3.12.

3.11 Fragment Programs

The conventional GL texturing model described in section 3.8 is a
configurable but essentially hard-wired sequence of per-fragment
computations based on a canonical set of per-fragment parameters
and texturing-related state such as texture images, texture
parameters, and texture environment parameters. The general success
and utility of the conventional GL texturing model reflects its
basic correspondence to the typical texturing requirements of 3D
applications.

However when the conventional GL texturing model is not sufficient,
the fragment program mode provides a substantially more flexible
model for generating fragment colors. The fragment program mode
permits applications to define their own fragment programs.

A fragment program is a character string that specifies a sequence
of operations to perform. Fragment program instructions are
typically 4-component vector operations that operate on per-fragment
attributes and program parameters. Fragment programs execute on a
per-fragment basis and operate on each fragment completely
independently from any other fragments. Fragment programs execute a
finite fixed sequence of instructions with no branching or looping.
Fragment programs execute without data hazards so results computed
in one instruction can be used immediately afterwards. The result
of a fragment program is a set of fragment result registers that
becomes the color used by antialiasing application and/or a depth
value used in place of the interpolated depth value generated by
conventional rasterization.

In fragment program mode, the color sum is subsumed by the fragment
program. An application desiring the primary and secondary colors
to be summed must explicitly include this operation in its program.

Fragment programs are defined to operate only in RGBA mode. The
results of fragment program execution are undefined if the GL is in
color index mode.


3.11.1 Program Objects

The GL provides one or more program targets, each identifying a
portion of the GL that can be controlled through application-
specified programs. The program target for fragment programs is
FRAGMENT_PROGRAM_ARB. Each program target has an associated program
object, called the current program object. Each program target also
has a default program object, which is initially the current program
object.

Each program object has an associated program string. The command

ProgramStringARB(enum target, enum format, sizei len,
const void *string);

updates the program string for the current program object for
<target>. <format> describes the format of the program string,
which must currently be PROGRAM_FORMAT_ASCII_ARB. <string> is a
pointer to the array of bytes representing the program string being
loaded, which need not be null-terminated. The length of the array
is given by <len>. If <string> is null-terminated, <len> should not
include the terminator.

When a program string is loaded, it is interpreted according to
syntactic and semantic rules corresponding to the program target
specified by <target>. If a program violates the syntactic or
semantic restrictions of the program target, ProgramStringARB
generates the error INVALID_OPERATION. An implementation may also
generate the error INVALID_OPERATION if the program would exceed
the native resource limits defined in section 6.1.12. A program
which fails to load due to exceeding native resource limits must
always fail, regardless of any other GL state.

Additionally, ProgramString will update the program error position
(PROGRAM_ERROR_POSITION_ARB) and error string
(PROGRAM_ERROR_STRING_ARB). If a program fails to load, the value
of the program error position is set to the ubyte offset into the
specified program string indicating where the first program error
was detected. If the program fails to load because of a semantic
restriction that is not detected until the program is fully
scanned, the error position is set to the value of <len>. If a
program loads successfully, the error position is set to the value
negative one. The implementation-dependent program error string
contains one or more error or warning messages. If a program loads
succesfully, the error string may either contain warning messages or
be empty.

Each program object has an associated array of program local
parameters. The number and type of program local parameters is
target- and implementation-dependent. For fragment programs,
program local parameters are four-component floating-point vectors.
The number of vectors is given by the implementation-dependent
constant MAX_PROGRAM_LOCAL_PARAMETERS_ARB, which must be at least
24. The commands

void ProgramLocalParameter4fARB(enum target, uint index,
float x, float y, float z, float w);
void ProgramLocalParameter4fvARB(enum target, uint index,
const float *params);
void ProgramLocalParameter4dARB(enum target, uint index,
double x, double y, double z, double w);
void ProgramLocalParameter4dvARB(enum target, uint index,
const double *params);

update the values of the program local parameter numbered <index>
belonging to the program object currently bound to <target>. For
ProgramLocalParameter4fARB and ProgramLocalParameter4dARB, the four
components of the parameter are updated with the values of <x>, <y>,
<z>, and <w>, respectively. For ProgramLocalParameter4fvARB and
ProgramLocalParameter4dvARB, the four components of the parameter
are updated with the array of four values pointed to by <params>.
The error INVALID_VALUE is generated if <index> is greater than or
equal to the number of program local parameters supported by
<target>.

Additionally, each program target has an associated array of program
environment parameters. Unlike program local parameters, program
environment parameters are shared by all program objects of a given
target. The number and type of program environment parameters is
target- and implementation-dependent. For fragment programs,
program environment parameters are four-component floating-point
vectors. The number of vectors is given by the implementation-
dependent constant MAX_PROGRAM_ENV_PARAMETERS_ARB, which must be at
least 24. The commands

void ProgramEnvParameter4fARB(enum target, uint index,
float x, float y, float z, float w);
void ProgramEnvParameter4fvARB(enum target, uint index,
const float *params);
void ProgramEnvParameter4dARB(enum target, uint index,
double x, double y, double z, double w);
void ProgramEnvParameter4dvARB(enum target, uint index,
const double *params);

update the values of the program environment parameter numbered
<index> for the given program target <target>. For
ProgramEnvParameter4fARB and ProgramEnvParameter4dARB, the four
components of the parameter are updated with the values of <x>, <y>,
<z>, and <w>, respectively. For ProgramEnvParameter4fvARB and
ProgramEnvParameter4dvARB, the four components of the parameter are
updated with the array of four values pointed to by <params>. The
error INVALID_VALUE is generated if <index> is greater than or equal
to the number of program environment parameters supported by
<target>.

Each program target has a default program object. Additionally,
named program objects can be created and operated upon. The name
space for program objects is the positive integers and is shared by
programs of all targets. The name zero is reserved by the GL.

A named program object is created by binding an unused program
object name to a valid program target. The binding is effected by
calling

BindProgramARB(enum target, uint program);

with <target> set to the desired program target and <program> set to
the unused program name. The resulting program object has a program
target given by <target> and is assigned target-specific default
values (see section 3.11.8 for fragment programs). BindProgramARB
may also be used to bind an existing program object to a program
target. If <program> is zero, the default program object for
<target> is bound. If <program> is the name of an existing program
object whose associated program target is <target>, the named
program object is bound. The error INVALID_OPERATION is generated
if <program> names an existing program object whose associated
program target is anything other than <target>.

Programs objects are deleted by calling

void DeleteProgramsARB(sizei n, const uint *programs);

<programs> contains <n> names of programs to be deleted. After a
program object is deleted, its name is again unused. If a program
object that is bound to any target is deleted, it is as though
BindProgramARB is first executed with same target and a <program> of
zero. Unused names in <programs> are silently ignored, as is the
value zero.

The command

void GenProgramsARB(sizei n, uint *programs);

returns <n> currently unused program names in <programs>. These
names are marked as used, for the purposes of GenProgramsARB only,
but objects are created only when they are first bound using
BindProgramARB.


3.11.2 Fragment Program Grammar and Semantic Restrictions

Fragment program strings are specified as an array of ASCII
characters containing the program text. When a fragment program is
loaded by a call to ProgramStringARB, the program string is parsed
into a set of tokens possibly separated by whitespace. Spaces,
tabs, newlines, carriage returns, and comments are considered
whitespace. Comments begin with the character "#" and are
terminated by a newline, a carriage return, or the end of the
program array.

The Backus-Naur Form (BNF) grammar below specifies the syntactically
valid sequences for fragment programs. The set of valid tokens can
be inferred from the grammar. The token "" represents an empty
string and is used to indicate optional rules. A program is invalid
if it contains any undefined tokens or characters.

A fragment program is required to begin with the header string
"!!ARBfp1.0", without any preceding whitespace. This string
identifies the subsequent program text as a fragment program
(version 1.0) that should be parsed according to the following
grammar and semantic rules. Program string parsing begins with the
character immediately following the header string.

<program> ::= <optionSequence> <statementSequence> "END"

<optionSequence> ::= <optionSequence> <option>
| ""

<option> ::= "OPTION" <identifier> ";"

<statementSequence> ::= <statementSequence> <statement>
| ""

<statement> ::= <instruction> ";"
| <namingStatement> ";"

<instruction> ::= <ALUInstruction>
| <TexInstruction>

<ALUInstruction> ::= <VECTORop_instruction>
| <SCALARop_instruction>
| <BINSCop_instruction>
| <BINop_instruction>
| <TRIop_instruction>
| <SWZ_instruction>

<TexInstruction> ::= <SAMPLE_instruction>
| <KIL_instruction>

<VECTORop_instruction> ::= <VECTORop> <maskedDstReg> ","
<vectorSrcReg>

<VECTORop> ::= "ABS" | "ABS_SAT"
| "FLR" | "FLR_SAT"
| "FRC" | "FRC_SAT"
| "LIT" | "LIT_SAT"
| "MOV" | "MOV_SAT"

<SCALARop_instruction> ::= <SCALARop> <maskedDstReg> ","
<scalarSrcReg>

<SCALARop> ::= "COS" | "COS_SAT"
| "EX2" | "EX2_SAT"
| "LG2" | "LG2_SAT"
| "RCP" | "RCP_SAT"
| "RSQ" | "RSQ_SAT"
| "SIN" | "SIN_SAT"
| "SCS" | "SCS_SAT"

<BINSCop_instruction> ::= <BINSCop> <maskedDstReg> ","
<scalarSrcReg> "," <scalarSrcReg>

<BINSCop> ::= "POW" | "POW_SAT"

<BINop_instruction> ::= <BINop> <maskedDstReg> ","
<vectorSrcReg> "," <vectorSrcReg>

<BINop> ::= "ADD" | "ADD_SAT"
| "DP3" | "DP3_SAT"
| "DP4" | "DP4_SAT"
| "DPH" | "DPH_SAT"
| "DST" | "DST_SAT"
| "MAX" | "MAX_SAT"
| "MIN" | "MIN_SAT"
| "MUL" | "MUL_SAT"
| "SGE" | "SGE_SAT"
| "SLT" | "SLT_SAT"
| "SUB" | "SUB_SAT"
| "XPD" | "XPD_SAT"

<TRIop_instruction> ::= <TRIop> <maskedDstReg> ","
<vectorSrcReg> "," <vectorSrcReg> ","
<vectorSrcReg>

<TRIop> ::= "CMP" | "CMP_SAT"
| "LRP" | "LRP_SAT"
| "MAD" | "MAD_SAT"

<SWZ_instruction> ::= <SWZop> <maskedDstReg> ","
<srcReg> "," <extendedSwizzle>

<SWZop> ::= "SWZ" | "SWZ_SAT"

<SAMPLE_instruction> ::= <SAMPLEop> <maskedDstReg> ","
<vectorSrcReg> "," <texImageUnit> ","
<texTarget>

<SAMPLEop> ::= "TEX" | "TEX_SAT"
| "TXP" | "TXP_SAT"
| "TXB" | "TXB_SAT"

<KIL_instruction> ::= "KIL" <vectorSrcReg>

<texImageUnit> ::= "texture" <optTexImageUnitNum>

<texTarget> ::= "1D"
| "2D"
| "3D"
| "CUBE"
| "RECT"

<optTexImageUnitNum> ::= ""
| "[" <texImageUnitNum> "]"

<texImageUnitNum> ::= <integer> from 0 to
MAX_TEXTURE_IMAGE_UNITS_ARB-1

<scalarSrcReg> ::= <optionalSign> <srcReg> <scalarSuffix>

<vectorSrcReg> ::= <optionalSign> <srcReg> <optionalSuffix>

<maskedDstReg> ::= <dstReg> <optionalMask>

<extendedSwizzle> ::= <xyzwExtendedSwizzle>
| <rgbaExtendedSwizzle>

<xyzwExtendedSwizzle> ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> ","
<xyzwExtSwizComp> "," <xyzwExtSwizComp>

<rgbaExtendedSwizzle> ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> ","
<rgbaExtSwizComp> "," <rgbaExtSwizComp>

<xyzwExtSwizComp> ::= <optionalSign> <xyzwExtSwizSel>

<rgbaExtSwizComp> ::= <optionalSign> <rgbaExtSwizSel>

<xyzwExtSwizSel> ::= "0"
| "1"
| <xyzwComponent>

<rgbaExtSwizSel> ::= "0"
| "1"
| <rgbaComponent>

<srcReg> ::= <fragmentAttribReg>
| <temporaryReg>
| <progParamReg>

<dstReg> ::= <temporaryReg>
| <fragmentResultReg>

<fragmentAttribReg> ::= <establishedName>
| <fragAttribBinding>

<temporaryReg> ::= <establishedName>

<progParamReg> ::= <progParamSingle>
| <progParamArray> "[" <progParamArrayAbs> "]"
| <paramSingleItemUse>

<progParamSingle> ::= <establishedName>

<progParamArray> ::= <establishedName>

<progParamArrayAbs> ::= <integer>

<fragmentResultReg> ::= <establishedName>
| <resultBinding>

<scalarSuffix> ::= "." <component>

<optionalSuffix> ::= ""
| "." <component>
| "." <xyzwComponent> <xyzwComponent>
<xyzwComponent> <xyzwComponent>
| "." <rgbaComponent> <rgbaComponent>
<rgbaComponent> <rgbaComponent>

<component> ::= <xyzwComponent>
| <rgbaComponent>

<xyzwComponent> ::= "x" | "y" | "z" | "w"

<rgbaComponent> ::= "r" | "g" | "b" | "a"

<optionalMask> ::= ""
| <xyzwMask>
| <rgbaMask>

<xyzwMask> ::= "." "x"
| "." "y"
| "." "xy"
| "." "z"
| "." "xz"
| "." "yz"
| "." "xyz"
| "." "w"
| "." "xw"
| "." "yw"
| "." "xyw"
| "." "zw"
| "." "xzw"
| "." "yzw"
| "." "xyzw"

<rgbaMask> ::= "." "r"
| "." "g"
| "." "rg"
| "." "b"
| "." "rb"
| "." "gb"
| "." "rgb"
| "." "a"
| "." "ra"
| "." "ga"
| "." "rga"
| "." "ba"
| "." "rba"
| "." "gba"
| "." "rgba"

<namingStatement> ::= <ATTRIB_statement>
| <PARAM_statement>
| <TEMP_statement>
| <OUTPUT_statement>
| <ALIAS_statement>

<ATTRIB_statement> ::= "ATTRIB" <establishName> "="
<fragAttribBinding>

<fragAttribBinding> ::= "fragment" "." <fragAttribItem>

<fragAttribItem> ::= "color" <optColorType>
| "texcoord" <optTexCoordNum>
| "fogcoord"
| "position"

<PARAM_statement> ::= <PARAM_singleStmt>
| <PARAM_multipleStmt>

<PARAM_singleStmt> ::= "PARAM" <establishName> <paramSingleInit>

<PARAM_multipleStmt> ::= "PARAM" <establishName> "[" <optArraySize> "]"
<paramMultipleInit>

<optArraySize> ::= ""
| <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB
(maximum number of allowed program
parameter bindings)

<paramSingleInit> ::= "=" <paramSingleItemDecl>

<paramMultipleInit> ::= "=" "{" <paramMultInitList> "}"

<paramMultInitList> ::= <paramMultipleItem>
| <paramMultipleItem> "," <paramMultInitList>

<paramSingleItemDecl> ::= <stateSingleItem>
| <programSingleItem>
| <paramConstDecl>

<paramSingleItemUse> ::= <stateSingleItem>
| <programSingleItem>
| <paramConstUse>

<paramMultipleItem> ::= <stateMultipleItem>
| <programMultipleItem>
| <paramConstDecl>

<stateMultipleItem> ::= <stateSingleItem>
| "state" "." <stateMatrixRows>

<stateSingleItem> ::= "state" "." <stateMaterialItem>
| "state" "." <stateLightItem>
| "state" "." <stateLightModelItem>
| "state" "." <stateLightProdItem>
| "state" "." <stateTexEnvItem>
| "state" "." <stateFogItem>
| "state" "." <stateDepthItem>
| "state" "." <stateMatrixRow>

<stateMaterialItem> ::= "material" <optFaceType> "." <stateMatProperty>

<stateMatProperty> ::= "ambient"
| "diffuse"
| "specular"
| "emission"
| "shininess"

<stateLightItem> ::= "light" "[" <stateLightNumber> "]" "."
<stateLightProperty>

<stateLightProperty> ::= "ambient"
| "diffuse"
| "specular"
| "position"
| "attenuation"
| "spot" "." <stateSpotProperty>
| "half"

<stateSpotProperty> ::= "direction"

<stateLightModelItem> ::= "lightmodel" <stateLModProperty>

<stateLModProperty> ::= "." "ambient"
| <optFaceType> "." "scenecolor"

<stateLightProdItem> ::= "lightprod" "[" <stateLightNumber> "]"
<optFaceType> "." <stateLProdProperty>

<stateLProdProperty> ::= "ambient"
| "diffuse"
| "specular"

<stateLightNumber> ::= <integer> from 0 to MAX_LIGHTS-1

<stateTexEnvItem> ::= "texenv" <optLegacyTexUnitNum> "."
<stateTexEnvProperty>

<stateTexEnvProperty> ::= "color"

<optLegacyTexUnitNum> ::= ""
| "[" <legacyTexUnitNum> "]"

<legacyTexUnitNum> ::= <integer> from 0 to MAX_TEXTURE_UNITS-1

<stateFogItem> ::= "fog" "." <stateFogProperty>

<stateFogProperty> ::= "color"
| "params"

<stateDepthItem> ::= "depth" "." <stateDepthProperty>

<stateDepthProperty> ::= "range"

<stateMatrixRow> ::= <stateMatrixItem> "." "row" "["
<stateMatrixRowNum> "]"

<stateMatrixRows> ::= <stateMatrixItem> <optMatrixRows>

<optMatrixRows> ::= ""
| "." "row" "[" <stateMatrixRowNum> ".."
<stateMatrixRowNum> "]"

<stateMatrixItem> ::= "matrix" "." <stateMatrixName>
<stateOptMatModifier>

<stateOptMatModifier> ::= ""
| "." <stateMatModifier>

<stateMatModifier> ::= "inverse"
| "transpose"
| "invtrans"

<stateMatrixRowNum> ::= <integer> from 0 to 3

<stateMatrixName> ::= "modelview" <stateOptModMatNum>
| "projection"
| "mvp"
| "texture" <optTexCoordNum>
| "palette" "[" <statePaletteMatNum> "]"
| "program" "[" <stateProgramMatNum> "]"

<stateOptModMatNum> ::= ""
| "[" <stateModMatNum> "]"

<stateModMatNum> ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1

<optTexCoordNum> ::= ""
| "[" <texCoordNum> "]"

<texCoordNum> ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1

<statePaletteMatNum> ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1

<stateProgramMatNum> ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1

<programSingleItem> ::= <progEnvParam>
| <progLocalParam>

<programMultipleItem> ::= <progEnvParams>
| <progLocalParams>

<progEnvParams> ::= "program" "." "env"
"[" <progEnvParamNums> "]"

<progEnvParamNums> ::= <progEnvParamNum>
| <progEnvParamNum> ".." <progEnvParamNum>

<progEnvParam> ::= "program" "." "env"
"[" <progEnvParamNum> "]"

<progLocalParams> ::= "program" "." "local"
"[" <progLocalParamNums> "]"

<progLocalParamNums> ::= <progLocalParamNum>
| <progLocalParamNum> ".." <progLocalParamNum>

<progLocalParam> ::= "program" "." "local"
"[" <progLocalParamNum> "]"

<progEnvParamNum> ::= <integer> from 0 to
MAX_PROGRAM_ENV_PARAMETERS_ARB - 1

<progLocalParamNum> ::= <integer> from 0 to
MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1

<paramConstDecl> ::= <paramConstScalarDecl>
| <paramConstVector>

<paramConstUse> ::= <paramConstScalarUse>
| <paramConstVector>

<paramConstScalarDecl> ::= <signedFloatConstant>

<paramConstScalarUse> ::= <floatConstant>

<paramConstVector> ::= "{" <signedFloatConstant> "}"
| "{" <signedFloatConstant> ","
<signedFloatConstant> "}"
| "{" <signedFloatConstant> ","
<signedFloatConstant> ","
<signedFloatConstant> "}"
| "{" <signedFloatConstant> ","
<signedFloatConstant> ","
<signedFloatConstant> ","
<signedFloatConstant> "}"

<signedFloatConstant> ::= <optionalSign> <floatConstant>

<floatConstant> ::= see text

<optionalSign> ::= ""
| "-"
| "+"

<TEMP_statement> ::= "TEMP" <varNameList>

<varNameList> ::= <establishName>
| <establishName> "," <varNameList>

<OUTPUT_statement> ::= "OUTPUT" <establishName> "="
<resultBinding>

<resultBinding> ::= "result" "." "color"
| "result" "." "depth"

<optFaceType> ::= ""
| "." "front"
| "." "back"

<optColorType> ::= ""
| "." "primary"
| "." "secondary"

<ALIAS_statement> ::= "ALIAS" <establishName> "="
<establishedName>

<establishName> ::= <identifier>

<establishedName> ::= <identifier>

<identifier> ::= see text

The <integer> rule matches an integer constant. The integer
consists of a sequence of one or more digits ("0" through "9").

The <floatConstant> rule matches a floating-point constant
consisting of an integer part, a decimal point, a fraction part, an
"e" or "E", and an optionally signed integer exponent. The integer
and fraction parts both consist of a sequence of one or more digits
("0" through "9"). Either the integer part or the fraction parts
(not both) may be missing; either the decimal point or the "e" (or
"E") and the exponent (not both) may be missing.

The <identifier> rule matches a sequence of one or more letters ("A"
through "Z", "a" through "z"), digits ("0" through "9), underscores
("_"), or dollar signs ("$"); the first character must not be a
number. Upper and lower case letters are considered different
(names are case-sensitive). The following strings are reserved
keywords and may not be used as identifiers:

ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,
COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT,
END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2,
LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT,
MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM,
POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS,
SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT,
TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT,
fragment, program, result, state, and texture.

The error INVALID_OPERATION is generated if a fragment program fails
to load because it is not syntactically correct or for one of the
semantic restrictions described in the following sections.

A successfully loaded fragment program is parsed into a sequence of
instructions. Each instruction is identified by its tokenized name.
The operation of these instructions when executed is defined in
section 3.11.5.

A successfully loaded program string replaces the program string
previously loaded into the specified program object. If the
OUT_OF_MEMORY error is generated by ProgramStringARB, no change is
made to the previous contents of the current program object.


3.11.3 Fragment Program Variables

Fragment programs may access a number of different variables during
their execution. The following sections define the variables that
can be declared and used by a fragment program.

Explicit variable declarations allow a fragment program to establish
a variable name that can be used to refer to a specified resource in
subsequent instructions. A fragment program will fail to load if it
declares the same variable name more than once or if it refers to a
variable name that has not been previously declared in the program
string.

Implicit variable declarations allow a fragment program to use the
name of certain available resources by name.


3.11.3.1 Fragment Attributes

Fragment program attribute variables are a set of four-component
floating-point vectors holding the attributes of the fragment being
processed. Fragment attribute variables are read-only during
fragment program execution.

Fragment attribute variables can be declared explicitly using the
<ATTRIB_statement> grammar rule, or implicitly using the
<fragAttribBinding> grammar rule in an executable instruction.

Each fragment attribute variable is bound to a single item of
fragment state according to the <fragAttrBinding> grammar rule. The
set of GL state that can be bound to a fragment attribute variable
is given in Table X.1. Fragment attribute variables are initialized
at each fragment program invocation with the current values of the
bound state.

Fragment Attribute Binding Components Underlying State
-------------------------- ---------- ----------------------------
fragment.color (r,g,b,a) primary color
fragment.color.primary (r,g,b,a) primary color
fragment.color.secondary (r,g,b,a) secondary color
fragment.texcoord (s,t,r,q) texture coordinate, unit 0
fragment.texcoord[n] (s,t,r,q) texture coordinate, unit n
fragment.fogcoord (f,0,0,1) fog distance/coordinate
fragment.position (x,y,z,1/w) window position

Table X.1: Fragment Attribute Bindings. The "Components" column
indicates the mapping of the state in the "Underlying State"
column. Bindings containing "[n]" require an integer value of <n>
to select an individual item.

If a fragment attribute binding matches "fragment.color" or
"fragment.color.primary", the "x", "y", "z", and "w" components of
the fragment attribute variable are filled with the "r", "g", "b",
and "a" components, respectively, of the fragment color. Each
fixed-point color component undergoes an implied conversion to
floating point. This conversion must leave the values 0 and 1
invariant.

If a fragment attribute binding matches "fragment.color.secondary",
the "x", "y", "z", and "w" components of the fragment attribute
variable are filled with the "r", "g", "b", and "a" components,
respectively, of the fragment secondary color. Each fixed-point
color component undergoes an implied conversion to floating point.
This conversion must leave the values 0 and 1 invariant.

If a fragment attribute binding matches "fragment.texcoord" or
"fragment.texcoord[n]", the "x", "y", "z", and "w" components of the
fragment attribute variable are filled with the "s", "t", "r", and
"q" components, respectively, of the fragment texture coordinates
for texture unit <n>. If "[n]" is omitted, texture unit zero is
used.

If a fragment attribute binding matches "fragment.fogcoord", the "x"
component of the fragment attribute variable is filled with either
the fragment eye distance or the fog coordinate, depending on
whether the fog source is set to FRAGMENT_DEPTH_EXT or
FOG_COORDINATE_EXT, respectively. The "y", "z", and "w" coordinates
are filled with 0, 0, and 1, respectively.

If a fragment attribute binding matches "fragment.position", the "x"
and "y" components of the fragment attribute variable are filled
with the (x,y) window coordinates of the fragment center, relative
to the lower left corner of the window. The "z" component is filled
with the fragment's z window coordinate. This z window coordinate
undergoes an implied conversion to floating point. This conversion
must leave the values 0 and 1 invariant. The "w" component is
filled with the reciprocal of the fragment's clip w coordinate.

On some implementations, the components of fragment.position may be
generated by interpolating per-vertex position values. This may
produce x and y window coordinates that don't exactly match those of
the fragment center and z window coordinates that do not exactly
match those generated by fixed-function rasterization. Therefore,
there is no guaranteed invariance between the final z window
coordinates of fragments processed by fragment programs that write
depth values and fragments processed by any other means, even if the
fragment programs in question simply copy the z value from the
fragment.position binding.


3.11.3.2 Fragment Program Parameters

Fragment program parameter variables are a set of four-component
floating-point vectors used as constants during fragment program
execution. Fragment program parameters retain their values across
fragment program invocations, although their values can change
between invocations due to GL state changes.

Single program parameter variables and arrays of program parameter
variables can be declared explicitly using the <PARAM_statement>
grammar rule. Single program parameter variables can also be
declared implicitly using the <paramSingleItemUse> grammar rule in
an executable instruction.

Each single program parameter variable is bound to a constant vector
or to a GL state vector according to the <paramSingleInit> grammar
rule. Individual items of a program parameter array are bound to
constant vectors or GL state vectors according to the
<programMultipleInit> grammar rule. The set of GL state that can be
bound to program parameter variables are given in Tables X.2.1
through X.2.4.


Constant Bindings

A program parameter variable can be bound to a scalar or vector
constant using the <paramConstDecl> grammar rule (explicit
declarations) or the <paramConstUse> grammar rule (implicit
declarations).

If a program parameter binding matches the <paramConstScalarDecl> or
<paramConstScalarUse> grammar rules, the corresponding program
parameter variable is bound to the vector (X,X,X,X), where X is the
value of the specified constant. Note that the
<paramConstScalarUse> grammar rule, used only in implicit
declarations, allows only non-negative constants. This
disambiguates cases like "-2", which could conceivably be taken to
mean either the vector "(2,2,2,2)" with all components negated or
"(-2,-2,-2,-2)" without negation. Only the former interpretation is
allowed by the grammar.

If a program parameter binding matches <paramConstVector>, the
corresponding program parameter variable is bound to the vector
(X,Y,Z,W), where X, Y, Z, and W are the values corresponding to the
first, second, third, and fourth match of <signedFloatConstant>. If
fewer than four constants are specified, Y, Z, and W assume the
values 0.0, 0.0, and 1.0, if their respective constants are not
specified.

Program parameter variables initialized to constant values can never
be modified.


Program Environment/Local Parameter Bindings

Binding Components Underlying State
----------------------------- ---------- ----------------------------
program.env[a] (x,y,z,w) program environment
parameter a
program.local[a] (x,y,z,w) program local parameter a
program.env[a..b] (x,y,z,w) program environment
parameters a through b
program.local[a..b] (x,y,z,w) program local parameters
a through b

Table X.2.1: Program Environment/Local Parameter Bindings. <a>
and <b> indicate parameter numbers, where <a> must be less than or
equal to <b>.

If a program parameter binding matches "program.env[a]" or
"program.local[a]", the four components of the program parameter
variable are filled with the four components of program environment
parameter <a> or program local parameter <a>, respectively.

Additionally, for program parameter array bindings,
"program.env[a..b]" and "program.local[a..b]" are equivalent to
specifying program environment parameters <a> through <b> in order
or program local parameters <a> through <b> in order, respectively.
In either case, a program will fail to load if <a> is greater than
<b>.


Material Property Bindings

Binding Components Underlying State
----------------------------- ---------- ----------------------------
state.material.ambient (r,g,b,a) front ambient material color
state.material.diffuse (r,g,b,a) front diffuse material color
state.material.specular (r,g,b,a) front specular material color
state.material.emission (r,g,b,a) front emissive material color
state.material.shininess (s,0,0,1) front material shininess
state.material.front.ambient (r,g,b,a) front ambient material color
state.material.front.diffuse (r,g,b,a) front diffuse material color
state.material.front.specular (r,g,b,a) front specular material color
state.material.front.emission (r,g,b,a) front emissive material color
state.material.front.shininess (s,0,0,1) front material shininess
state.material.back.ambient (r,g,b,a) back ambient material color
state.material.back.diffuse (r,g,b,a) back diffuse material color
state.material.back.specular (r,g,b,a) back specular material color
state.material.back.emission (r,g,b,a) back emissive material color
state.material.back.shininess (s,0,0,1) back material shininess

Table X.2.2: Material Property Bindings. If a material face is
not specified in the binding, the front property is used.

If a program parameter binding matches any of the material
properties listed in Table X.2.2, the program parameter variable is
filled according to the table. For ambient, diffuse, specular, or
emissive colors, the "x", "y", "z", and "w" components are filled
with the "r", "g", "b", and "a" components, respectively, of the
corresponding material color. For material shininess, the "x"
component is filled with the material's specular exponent, and the
"y", "z", and "w" components are filled with 0, 0, and 1,
respectively. Bindings containing ".back" refer to the back
material; all other bindings refer to the front material.

Material properties can be changed inside a Begin/End pair, either
directly by calling Material, or indirectly through color material.
However, such property changes are not guaranteed to update program
parameter bindings until the following End command. Program
parameter variables bound to material properties changed inside a
Begin/End pair are undefined until the following End command.


Light Property Bindings

Binding Components Underlying State
----------------------------- ---------- ----------------------------
state.light[n].ambient (r,g,b,a) light n ambient color
state.light[n].diffuse (r,g,b,a) light n diffuse color
state.light[n].specular (r,g,b,a) light n specular color
state.light[n].position (x,y,z,w) light n position
state.light[n].attenuation (a,b,c,e) light n attenuation constants
and spot light exponent
state.light[n].spot.direction (x,y,z,c) light n spot direction and
cutoff angle cosine
state.light[n].half (x,y,z,1) light n infinite half-angle
state.lightmodel.ambient (r,g,b,a) light model ambient color
state.lightmodel.scenecolor (r,g,b,a) light model front scene color
state.lightmodel . (r,g,b,a) light model front scene color
front.scenecolor
state.lightmodel . (r,g,b,a) light model back scene color
back.scenecolor
state.lightprod[n].ambient (r,g,b,a) light n / front material
ambient color product
state.lightprod[n].diffuse (r,g,b,a) light n / front material
diffuse color product
state.lightprod[n].specular (r,g,b,a) light n / front material
specular color product
state.lightprod[n]. (r,g,b,a) light n / front material
front.ambient ambient color product
state.lightprod[n]. (r,g,b,a) light n / front material
front.diffuse diffuse color product
state.lightprod[n]. (r,g,b,a) light n / front material
front.specular specular color product
state.lightprod[n]. (r,g,b,a) light n / back material
back.ambient ambient color product
state.lightprod[n]. (r,g,b,a) light n / back material
back.diffuse diffuse color product
state.lightprod[n]. (r,g,b,a) light n / back material
back.specular specular color product

Table X.2.3: Light Property Bindings. <n> indicates a light
number.

If a program parameter binding matches "state.light[n].ambient",
"state.light[n].diffuse", or "state.light[n].specular", the "x",
"y", "z", and "w" components of the program parameter variable are
filled with the "r", "g", "b", and "a" components, respectively, of
the corresponding light color.

If a program parameter binding matches "state.light[n].position",
the "x", "y", "z", and "w" components of the program parameter
variable are filled with the "x", "y", "z", and "w" components,
respectively, of the light position.

If a program parameter binding matches "state.light[n].attenuation",
the "x", "y", and "z" components of the program parameter variable
are filled with the constant, linear, and quadratic attenuation
parameters of the specified light, respectively (section 2.13.1).
The "w" component of the program parameter variable is filled with
the spot light exponent of the specified light.

If a program parameter binding matches
"state.light[n].spot.direction", the "x", "y", and "z" components of
the program parameter variable are filled with the "x", "y", and "z"
components of the spot light direction of the specified light,
respectively (section 2.13.1). The "w" component of the program
parameter variable is filled with the cosine of the spot light
cutoff angle of the specified light.

If a program parameter binding matches "state.light[n].half", the
"x", "y", and "z" components of the program parameter variable are
filled with the x, y, and z components, respectively, of the
normalized infinite half-angle vector

h_inf = || P + (0, 0, 1) ||.

The "w" component is filled with 1. In the computation of h_inf, P
consists of the x, y, and z coordinates of the normalized vector
from the eye position P_e to the eye-space light position P_pli
(section 2.13.1). h_inf is defined to correspond to the normalized
half-angle vector when using an infinite light (w coordinate of the
position is zero) and an infinite viewer (v_bs is FALSE). For local
lights or a local viewer, h_inf is well-defined but does not match
the normalized half-angle vector, which will vary depending on the
vertex position.

If a program parameter binding matches "state.lightmodel.ambient",
the "x", "y", "z", and "w" components of the program parameter
variable are filled with the "r", "g", "b", and "a" components of
the light model ambient color, respectively.

If a program parameter binding matches "state.lightmodel.scenecolor"
or "state.lightmodel.front.scenecolor", the "x", "y", and "z"
components of the program parameter variable are filled with the
"r", "g", and "b" components respectively of the "front scene color"

c_scene = a_cs * a_cm + e_cm,

where a_cs is the light model ambient color, a_cm is the front
ambient material color, and e_cm is the front emissive material
color. The "w" component of the program parameter variable is
filled with the alpha component of the front diffuse material color.
If a program parameter binding matches
"state.lightmodel.back.scenecolor", a similar back scene color,
computed using back-facing material properties, is used. The front
and back scene colors match the values that would be assigned to
vertices using conventional lighting if all lights were disabled.

If a program parameter binding matches anything beginning with
"state.lightprod[n]", the "x", "y", and "z" components of the
program parameter variable are filled with the "r", "g", and "b"
components, respectively, of the corresponding light product. The
three light product components are the products of the corresponding
color components of the specified material property and the light
color of the specified light (see Table X.2.3). The "w" component
of the program parameter variable is filled with the alpha component
of the specified material property.

Light products depend on material properties, which can be changed
inside a Begin/End pair. Such property changes are not guaranteed
to take effect until the following End command. Program parameter
variables bound to light products whose corresponding material
property changes inside a Begin/End pair are undefined until the
following End command.


Texture Environment Property Bindings

Binding Components Underlying State
------------------------- ---------- ----------------------------
state.texenv[n].color (r,g,b,a) texture environment n color

Table X.2.4: Texture Environment Property Bindings. "[n]" is
optional -- texture unit <n> is used if specified; texture unit 0
is used otherwise.

If a program parameter binding matches "state.texenv[n].color", the
"x", "y", "z", and "w" components of the program parameter variable
are filled with the "r", "g", "b", and "a" components, respectively,
of the corresponding texture environment color. Note that only
"legacy" texture units, as queried by MAX_TEXTURE_UNITS, include
texture environment state. Texture image units and texture
coordinate sets do not have associated texture environment state.


Fog Property Bindings

Binding Components Underlying State
--------------------------- ---------- ----------------------------
state.fog.color (r,g,b,a) RGB fog color (section 3.11)
state.fog.params (d,s,e,r) fog density, linear start
and end, and 1/(end-start)
(section 3.11)

Table X.2.5: Fog Property Bindings

If a program parameter binding matches "state.fog.color", the "x",
"y", "z", and "w" components of the program parameter variable are
filled with the "r", "g", "b", and "a" components, respectively, of
the fog color (section 3.11).

If a program parameter binding matches "state.fog.params", the "x",
"y", and "z" components of the program parameter variable are filled
with the fog density, linear fog start, and linear fog end
parameters (section 3.11), respectively. The "w" component is
filled with 1/(end-start), where end and start are the linear fog
end and start parameters, respectively.


Depth Property Bindings

Binding Components Underlying State
--------------------------- ---------- ----------------------------
state.depth.range (n,f,d,1) Depth range near, far, and
(far-near) (section 2.10.1)

Table X.2.6: Depth Property Bindings

If a program parameter binding matches "state.depth.range", the "x"
and "y" components of the program parameter variable are filled with
the mappings of near and far clipping planes to window coordinates,
respectively. The "z" component is filled with the difference of
the mappings of near and far clipping planes, far minus near. The
"w" component is filled with 1.


Matrix Property Bindings

Binding Underlying State
------------------------------------ ---------------------------
* state.matrix.modelview[n] modelview matrix n
state.matrix.projection projection matrix
state.matrix.mvp modelview-projection matrix
* state.matrix.texture[n] texture matrix n
state.matrix.palette[n] modelview palette matrix n
state.matrix.program[n] program matrix n

Table X.2.7: Base Matrix Property Bindings. The "[n]" syntax
indicates a specific matrix number. For modelview and texture
matrices, a matrix number is optional, and matrix zero will be
used if the matrix number is omitted. These base bindings may
further be modified by a inverse/transpose selector and a row
selector.

If the beginning of a program parameter binding matches any of the
matrix binding names listed in Table X.2.7, the binding corresponds
to a 4x4 matrix. If the parameter binding is followed by
".inverse", ".transpose", or ".invtrans" (<stateMatModifier> grammar
rule), the inverse, transpose, or transpose of the inverse,
respectively, of the matrix specified in Table X.2.7 is selected.
Otherwise, the matrix specified in Table X.2.7 is selected. If the
specified matrix is poorly-conditioned (singular or nearly so), its
inverse matrix is undefined. The binding name "state.matrix.mvp"
refers to the product of modelview matrix zero and the projection
matrix, defined as

MVP = P * M0,

where P is the projection matrix and M0 is modelview matrix zero.

If the selected matrix is followed by ".row[<a>]" (matching the
<stateMatrixRow> grammar rule), the "x", "y", "z", and "w"
components of the program parameter variable are filled with the
four entries of row <a> of the selected matrix. In the example,

PARAM m0 = state.matrix.modelview[1].row[0];
PARAM m1 = state.matrix.projection.transpose.row[3];

the variable "m0" is set to the first row (row 0) of modelview
matrix 1 and "m1" is set to the last row (row 3) of the transpose of
the projection matrix.

For program parameter array bindings, multiple rows of the selected
matrix can be bound via the <stateMatrixRows> grammar rule. If the
selected matrix binding is followed by ".row[<a>..<b>]", the result
is equivalent to specifying matrix rows <a> through <b>, in order.
A program will fail to load if <a> is greater than <b>. If no row
selection is specified (<optMatrixRows> matches ""), matrix rows 0
through 3 are bound in order. In the example,

PARAM m2[] = { state.matrix.program[0].row[1..2] };
PARAM m3[] = { state.matrix.program[0].transpose };

the array "m2" has two entries, containing rows 1 and 2 of program
matrix zero, and "m3" has four entries, containing all four rows of
the transpose of program matrix zero.


Program Parameter Arrays

A program parameter array variable can be declared explicitly by
matching the <PARAM_multipleStmt> grammar rule. Programs can
optionally specify the number of individual program parameters in
the array, using the <optArraySize> grammar rule. Program parameter
arrays may not be declared implicity.

Individual parameter variables in a program parameter array are
bound to GL state vectors or constant vectors as specified by the
grammar rule <paramMultInitList>. Each individual parameter in the
array is bound in turn as described above.

The total number of entries in the array is equal to the number of
parameters bound in the initializer list. A fragment program that
specifies an array size (<optArraySize> matches <integer>) that does
not match the number of parameter bindings in the initialization
list will fail to load.

Program parameter array variables may only be accessed using
absolute addressing by matching the <progParamArrayAbs> grammar
rule. Array accesses are checked against the limits of the array.
If any fragment program instruction accesses a program parameter
array with an out-of-range index (greater than or equal to the size
of the array), the fragment program will fail to load.

Individual state vectors can have no more than one unique binding in
any given program. The GL will automatically combine multiple
bindings of the same state vector into a single unique binding.


3.11.3.3 Fragment Program Temporaries

Fragment program temporary variables are a set of four-component
floating-point vectors used to hold temporary results during
fragment program execution. Temporaries do not persist between
program invocations, and are undefined at the beginning of each
fragment program invocation.

Fragment program temporary variables can be declared explicitly
using the <TEMP_statement> grammar rule. Each such statement can
declare one or more temporaries. Fragment program temporary
variables can not be declared implicitly.


3.11.3.4 Fragment Program Results

Fragment program result variables are a set of four component
floating-point vectors used to hold the final results of a fragment
program. Fragment program result variables are write-only during
fragment program execution.

Fragment program result variables can be declared explicitly using
the <OUTPUT_statement> grammar rule, or implicitly using the
<resultBinding> grammar rule in an executable instruction. Each
fragment program result variable is bound to a fragment attribute
used in subsequent back-end processing. The set of fragment program
result variable bindings is given in Table X.3.

Binding Components Description
----------------------------- ---------- ----------------------------
result.color (r,g,b,a) color
result.depth (*,*,d,*) depth coordinate

Table X.3: Fragment Result Variable Bindings. Components labeled
"*" are unused.

If a result variable binding matches "result.color", updates to the
"x", "y", "z", and "w" components of the result variable modify the
"r", "g", "b", and "a" components, respectively, of the fragment's
output color. If "result.color" is not both bound by the fragment
program and written by some instruction of the program, the output
color of the fragment program is undefined.

If a result variable binding matches "result.depth", updates to the
"z" component of the result variable modify the fragment's output
depth value. If "result.depth" is not both bound by the fragment
program and written by some instruction of the program, the
interpolated depth value produced by rasterization is used as if
fragment program mode is not enabled. Writes to any component of
depth other than the "z" component have no effect.


3.11.3.5 Fragment Program Aliases

Fragment programs can create aliases by matching the
<ALIAS_statement> grammar rule. Aliases allow programs to use
multiple variable names to refer to a single underlying variable.
For example, the statement

ALIAS var1 = var0

establishes a variable name named "var1". Subsequent references to
"var1" in the program text are treated as references to "var0". The
left hand side of an ALIAS statement must be a new variable name,
and the right hand side must be an established variable name.

Aliases are not considered variable declarations, so do not count
against the limits on the number of variable declarations allowed in
the program text.


3.11.3.6 Fragment Program Resource Limits

The fragment program execution environment provides implementation-
dependent resource limits on the number of ALU instructions, texture
instructions, total instructions (ALU or texture), temporary
variable declarations, program parameter bindings, or texture
indirections. A program that exceeds any of these resource limits
will fail to load. The resource limits for fragment programs can be
queried by calling GetProgramiv (section 6.1.12) with a target of
FRAGMENT_PROGRAM_ARB.

The limit on fragment program ALU instructions can be queried with
a <pname> of MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, and must be at least
48. Each ALU instruction in the program (matches of the
<ALUInstruction> grammar rule) counts against this limit.

The limit on fragment program texture instructions can be queried
with a <pname> of MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, and must be at
least 24. Each texture instruction in the program (matches of the
<TexInstruction> grammar rule) counts against this limit.

The limit on fragment program total instructions can be queried with
a <pname> of MAX_PROGRAM_INSTRUCTIONS_ARB, and must be at least 72.
Each instruction in the program (matching the <instruction> grammar
rule) counts against this limit. Note that the limit on total
instructions is not necessarily equal to the sum of the limits on
ALU instructions and texture instructions.

The limit on fragment program texture indirections can be queried
with a <pname> of MAX_PROGRAM_TEX_INDIRECTIONS_ARB, and must be at
least 4. Texture indirections are described in 3.11.6. If an
implementation has no limit on texture indirections, the limit will
be equal to the limit on texture instructions.

The limit on fragment program temporary variable declarations can be
queried with a <pname> of MAX_PROGRAM_TEMPORARIES_ARB, and must be at
least 16. Each temporary declared in the program, using the
<TEMP_statement> grammar rule, counts against this limit. Aliases
of declared temporaries do not.

The limit on fragment program attribute bindings can be queried with
a <pname> of MAX_PROGRAM_ATTRIBS_ARB and must be at least 10. Each
distinct vertex attribute bound explicitly or implicitly in the
program counts against this limit; vertex attributes bound multiple
times count only once.

The limit on fragment program parameter bindings can be queried with
a <pname> of MAX_PROGRAM_PARAMETERS_ARB, and must be at least 24.
Each distinct GL state vector bound explicitly or implicitly in the
program counts against this limit; GL state vectors bound multiple
times count only once. Every other constant vector bound in the
program is counted if and only if an identical constant vector has
not already been counted. Two constant vectors are considered
identical if the four component values are numerically equivalent.
Recall that scalar constants bound in a program are treated as
vector constants with the scalar value replicated.

In addition to the limits described above, the GL provides a similar
set of implementation-dependent native resource limits. These
limits, specified in Section 6.1.12, provide guidance as to whether
the program is small enough to use a "native" mode where fragment
programs may be executed with higher performance. The native
resource limits and usage counts are implementation-dependent and
may not exactly correspond to limits and counts described above.
A program's native resource consumption may be reduced by program
optimizations performed by the GL. Native resource consumption may
be increased due to emulation of instructions or any other program
features not natively supported by an implementation. Notably, an
additional texture indirection may be consumed due to an
implementation's lack of native support for texture instructions
with source coordinate swizzles or parameter source coordinates,
which may require emulation by prepending ALU instructions. An
implementation may also fail to natively support all combinations of
attributes described in Table X.1, even if the total number of
bound attributes is fewer than the native attribute limit. In this
case the program is still considered to exceed the native resource
limits, as queried by PROGRAM_UNDER_NATIVE_LIMITS_ARB (section
6.1.12).

To assist in resource counting, the GL additionally provides
GetProgram queries to determine the resource usage and native
resource usage of the currently bound program, and to determine
whether the bound program exceeds any native resource limit.

Programs that exceed any native resource limit may or may not load
depending on the implementation.


3.11.4 Fragment Program Execution Environment

If fragment program mode is enabled, the currently bound fragment
program is executed when any fragment is produced by rasterization.

If fragment program mode is enabled and the currently bound program
object does not contain a valid fragment program, the error
INVALID_OPERATION will be generated by Begin, RasterPos, and any
command that implicitly calls Begin (e.g., DrawArrays).

Fragment programs execute a sequence of instructions without
branching. Fragment programs begin by executing the first
instruction in the program, and execute instructions in the order
specified in the program until the last instruction is completed.

There are 33 fragment program instructions. The instructions and
their respective input and output parameters are summarized in
Table X.5.

Instruction Inputs Output Description
----------- ------ ------ --------------------------------
ABS v v absolute value
ADD v,v v add
CMP v,v,v v compare
COS s ssss cosine with reduction to [-PI,PI]
DP3 v,v ssss 3-component dot product
DP4 v,v ssss 4-component dot product
DPH v,v ssss homogeneous dot product
DST v,v v distance vector
EX2 s ssss exponential base 2
FLR v v floor
FRC v v fraction
KIL v v kill fragment
LG2 s ssss logarithm base 2
LIT v v compute light coefficients
LRP v,v,v v linear interpolation
MAD v,v,v v multiply and add
MAX v,v v maximum
MIN v,v v minimum
MOV v v move
MUL v,v v multiply
POW s,s ssss exponentiate
RCP s ssss reciprocal
RSQ s ssss reciprocal square root
SCS s ss-- sine/cosine without reduction
SGE v,v v set on greater than or equal
SIN s ssss sine with reduction to [-PI,PI]
SLT v,v v set on less than
SUB v,v v subtract
SWZ v v extended swizzle
TEX v,u,t v texture sample
TXB v,u,t v texture sample with bias
TXP v,u,t v texture sample with projection
XPD v,v v cross product

Table X.5: Summary of fragment program instructions. "v"
indicates a floating-point vector input or output, "s" indicates a
floating-point scalar input, "ssss" indicates a scalar output
replicated across a 4-component result vector, "ss--" indicates
two scalar outputs in the first two components, "u" indicates a
texture image unit identifier, and "t" indicates a texture target.


3.11.4.1 Fragment Program Operands

Most fragment program instructions operate on floating-point vectors
or scalars, as indicated by the grammar rules <vectorSrcReg> and
<scalarSrcReg>, respectively.

Vector and scalar operands can be obtained from fragment attribute,
program parameter, or temporary registers, as indicated by the
<srcReg> rule. For scalar operands, a single vector component is
selected by the <scalarSuffix> rule, where the characters "x", "y",
"z", and "w", or "r", "g", "b", and "a" select the first, second,
third, and fourth components, respectively, of the vector.

Vector operands can be swizzled according to the <optionalSuffix>
rule. In its most general form, the <optionalSuffix> rule matches
the pattern ".????" where each question mark is replaced with one of
"x", "y", "z", "w", "r", "g", "b", or "a". For such patterns, the
first, second, third, and fourth components of the operand are taken
from the vector components named by the first, second, third, and
fourth character of the pattern, respectively. For example, if the
swizzle suffix is ".yzzx" or ".gbbr" and the specified source
contains {2,8,9,0}, the swizzled operand used by the instruction is
{8,9,9,2}.

If the <optionalSuffix> rule matches "", it is treated as though it
were ".xyzw". If the <optionalSuffix> rule matches (ignoring
whitespace) ".x", ".y", ".z", or ".w", these are treated the same as
".xxxx", ".yyyy", ".zzzz", and ".wwww" respectively. Likewise, if
the <optionalSuffix> rule matches ".r", ".g", ".b", or ".a", these
are treated the same as ".rrrr", ".gggg", ".bbbb", and ".aaaa"
respectively.

Floating-point scalar or vector operands can optionally be negated
according to the <optionalSign> rule in <scalarSrcReg> and
<vectorSrcReg>. If the <optionalSign> matches "-", each operand or
operand component is negated.

The following pseudo-code spells out the operand generation process.
In the example, "float" is a floating-point scalar type, while
"floatVec" is a four-component vector. "source" refers to the
register used for the operand, matching the <srcReg> rule. "negate"
is TRUE if the <optionalSign> rule in <scalarSrcReg> or
<vectorSrcReg> matches "-" and FALSE otherwise. The ".c***",
".*c**", ".**c*", ".***c" modifiers refer to the x, y, z, and w
components obtained by the swizzle operation; the ".c" modifier
refers to the single component selected for a scalar load.

floatVec VectorLoad(floatVec source)
{
floatVec operand;

operand.x = source.c***;
operand.y = source.*c**;
operand.z = source.**c*;
operand.w = source.***c;
if (negate) {
operand.x = -operand.x;
operand.y = -operand.y;
operand.z = -operand.z;
operand.w = -operand.w;
}

return operand;
}

float ScalarLoad(floatVec source)
{
float operand;

operand = source.c;
if (negate) {
operand = -operand;
}

return operand;
}


3.11.4.2 Fragment Program Parameter Arrays

A fragment program can load a single element of a program parameter
array using only absolute addressing. Program parameter arrays are
accessed when the <progParamArrayAbs> rule is matched. The offset
of the selected entry in the array is given by the number matching
<progParamRegNum>. If the offset exceeds the size of the
array, the results of the access are undefined, but may not lead to
program or GL termination.


3.11.4.3 Fragment Program Destination Register Update

Fragment program instructions write a 4-component result vector to a
single temporary or fragment result register. Writes to individual
components of the destination register are controlled by individual
component write masks specified as part of the instruction.
Optional clamping of each component of the destination register to
the range [0,1] is controlled by an opcode modifier.

The component write mask is specified by the <optionalMask> rule
found in the <maskedDstReg> rule. If the optional mask is "", all
components are enabled. Otherwise, the optional mask names the
individual components to enable. The characters "x", "y", "z", and
"w", or "r", "g", "b", and "a" match the first, second, third, and
fourth components, respectively. For example, an optional mask of
".xzw" indicates that the x, z, and w components should be enabled
for writing but the y component should not. The grammar requires
that the destination register mask components must be listed in
"xyzw", or "rgba" order. Component names from one set (xyzw or
rgba) cannot be mixed with component names from another set. For
example, ".rgw" is not a valid writemask.

Each component of the destination register is updated with the
result of the fragment program instruction if and only if the
component is enabled for writes by the component write mask.
Otherwise, the component of the destination register remains
unchanged.

If the instruction opcode has the "_SAT" suffix, requesting
saturated result vectors, each component of the result vector
enabled in the writemask is clamped to the range [0,1] before being
updated in the destination register.

The following pseudocode illustrates the process of writing a result
vector to the destination register. In the pseudocode, "instrmask"
refers to the component write mask given by the <optionalMask> rule.
"clamp" is TRUE if the instruction specifies that the result should
be clamped. "result" and "destination" refer to the result vector
and the register selected by <dstReg>, respectively.

void UpdateDestination(floatVec destination, floatVec result)
{
floatVec merged;

// Clamp the result vector components to [0,1], if requested.
if (instrClamp) {
if (result.x < 0) result.x = 0;
else if (result.x > 1) result.x = 1;
if (result.y < 0) result.y = 0;
else if (result.y > 1) result.y = 1;
if (result.z < 0) result.z = 0;
else if (result.z > 1) result.z = 1;
if (result.w < 0) result.w = 0;
else if (result.w > 1) result.w = 1;
}

// Merge the converted result into the destination register,
// under control of the compile-time write mask.
merged = destination;
if (instrMask.x) {
merged.x = result.x;
}
if (instrMask.y) {
merged.y = result.y;
}
if (instrMask.z) {
merged.z = result.z;
}
if (instrMask.w) {
merged.w = result.w;
}

// Write out the new destination register.
destination = merged;
}


3.11.4.4 Fragment Program Result Processing

As a fragment program executes, it will write to either one or two
result registers that are mapped to the fragment's color and depth.

The fragment's color components are first clamped to the range [0,1]
then converted to fixed point as in section 2.13.9. If the fragment
program does not write result.color, the color will be undefined in
subsequent stages.

If the fragment program contains an instruction to write to
result.depth, the fragment's depth is replaced by the value of the
"z" component of result.depth. This z value is first clamped to the
range [0,1] then converted to fixed-point as if it were a window z
value (section 2.10.1). If the fragment program does not write
result.depth, the fragment's original depth is unmodified.


3.11.4.5 Fragment Program Options

The <optionSequence> grammar rule provides a mechanism for programs
to indicate that one or more extended language features are used by
the program. All program options used by the program must be
declared at the beginning of the program string. Each program
option specified in a program string will modify the syntactic or
semantic rules used to interpet the program and the execution
environment used to execute the program. Program options not
present in the program string are ignored, even if they are
supported by the GL.

The <identifier> token in the <option> rule must match the name of a
program option supported by the implementation. To avoid option
name conflicts, option identifiers are required to begin with a
vendor prefix. A program will fail to load if it specifies a
program option not supported by the GL.

Fragment program options should confine their semantic changes to
the domain of fragment programs. Support for a fragment program
option should not change the specification and behavior of fragment
programs not requesting use of that option.


3.11.4.5.1 Fog Application Fragment Program Options

If a fragment program specifies one of the options "ARB_fog_exp",
"ARB_fog_exp2", or "ARB_fog_linear", the program will apply fog to
the program's final clamped color using a fog mode of EXP, EXP2, or
LINEAR, respectively, as described in section 3.10.

When a fog option is specified in a fragment program, semantic
restrictions are added to indicate that a fragment program
will fail to load if the number of temporaries it contains exceeds
the implementation-dependent limit minus 1, if the number of
attributes it contains exceeds the implementation-dependent limit
minus 1, or if the number of parameters it contains exceeds the
implementation-dependent limit minus 2.

Additionally, when the ARB_fog_exp option is specified in a fragment
program, a semantic restriction is added to indicate that a fragment
program will fail to load if the number of instructions or ALU
instructions it contains exceeds the implementation-dependent limit
minus 3. When the ARB_fog_exp2 option is specified in a fragment
program, a semantic restriction is added to indicate that a fragment
program will fail to load if the number of instructions or ALU
instructions it contains exceeds the implementation-dependent limit
minus 4. When the ARB_fog_linear option is specified in a fragment
program, a semantic restriction is added to indicate that a fragment
program will fail to load if the number of instructions or ALU
instructions it contains exceeds the implementation-dependent limit
minus 2.

Only one fog application option may be specified by any given
fragment program. A fragment program that specifies more than one
of the program options "ARB_fog_exp", "ARB_fog_exp2", and
"ARB_fog_linear", will fail to load.


3.11.4.5.2 Precision Hint Options

Fragment program computations are carried out at an implementation-
dependent precision. However, some implementations may be able to
perform fragment program computations at more than one precision,
and may be able to trade off computation precision for performance.

If a fragment program specifies the "ARB_precision_hint_fastest"
program option, implementations should select precision to minimize
program execution time, with possibly reduced precision. If a
fragment program specifies the "ARB_precision_hint_nicest" program
option, implementations should maximize the precision, with possibly
increased execution time.

Only one precision control option may be specified by any given
fragment program. A fragment program that specifies both the
"ARB_precision_hint_fastest" and "ARB_precision_hint_nicest" program
options will fail to load.


3.11.5 Fragment Program ALU Instruction Set

The following sections describe the set of supported fragment
program instructions. Each section contains pseudocode describing
the instruction. Instructions will have up to three operands,
referred to as "op0", "op1", and "op2". The operands are loaded
using the mechanisms specified in section 3.11.4.1. The variables
"tmp", "tmp0", "tmp1", and "tmp2" describe scalars or vectors used
to hold intermediate results in the instruction. Instructions will
generate a result vector called "result". The result vector is then
written to the destination register specified in the instruction as
described in section 3.11.4.3.


3.11.5.1 ABS: Absolute Value

The ABS instruction performs a component-wise absolute value
operation on the single operand to yield a result vector.

tmp = VectorLoad(op0);
result.x = fabs(tmp.x);
result.y = fabs(tmp.y);
result.z = fabs(tmp.z);
result.w = fabs(tmp.w);


3.11.5.2 ADD: Add

The ADD instruction performs a component-wise add of the two
operands to yield a result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = tmp0.x + tmp1.x;
result.y = tmp0.y + tmp1.y;
result.z = tmp0.z + tmp1.z;
result.w = tmp0.w + tmp1.w;

The following rules apply to addition:

1. <x> + <y> == <y> + <x>, for all <x> and <y>.
2. <x> + 0.0 == <x>, for all <x>.


3.11.5.3 CMP: Compare

The CMP instructions performs a component-wise comparison of the
first operand against zero, and copies the values of the second or
third operands based on the results of the compare.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
tmp2 = VectorLoad(op2);
result.x = (tmp0.x < 0.0) ? tmp1.x : tmp2.x;
result.y = (tmp0.y < 0.0) ? tmp1.y : tmp2.y;
result.z = (tmp0.z < 0.0) ? tmp1.z : tmp2.z;
result.w = (tmp0.w < 0.0) ? tmp1.w : tmp2.w;


3.11.5.4 COS: Cosine

The COS instruction approximates the trigonometric cosine of the
angle specified by the scalar operand and replicates it to all four
components of the result vector. The angle is specified in radians
and does not have to be in the range [-PI,PI].

tmp = ScalarLoad(op0);
result.x = ApproxCosine(tmp);
result.y = ApproxCosine(tmp);
result.z = ApproxCosine(tmp);
result.w = ApproxCosine(tmp);


3.11.5.5 DP3: Three-Component Dot Product

The DP3 instruction computes a three-component dot product of the
two operands (using the first three components) and replicates the
dot product to all four components of the result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) + (tmp0.z * tmp1.z);
result.x = dot;
result.y = dot;
result.z = dot;
result.w = dot;


3.11.5.6 DP4: Four-Component Dot Product

The DP4 instruction computes a four-component dot product of the two
operands and replicates the dot product to all four components of
the result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1):
dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) +
(tmp0.z * tmp1.z) + (tmp0.w * tmp1.w);
result.x = dot;
result.y = dot;
result.z = dot;
result.w = dot;


3.11.5.7 DPH: Homogeneous Dot Product

The DPH instruction computes a three-component dot product of the
two operands (using the x, y, and z components), adds the w
component of the second operand, and replicates the sum to all four
components of the result vector. This is equivalent to a four-
component dot product where the w component of the first operand is
forced to 1.0.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1):
dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) +
(tmp0.z * tmp1.z) + tmp1.w;
result.x = dot;
result.y = dot;
result.z = dot;
result.w = dot;


3.11.5.8 DST: Distance Vector

The DST instruction computes a distance vector from two specially-
formatted operands. The first operand should be of the form [NA,
d^2, d^2, NA] and the second operand should be of the form [NA, 1/d,
NA, 1/d], where NA values are not relevant to the calculation and d
is a vector length. If both vectors satisfy these conditions, the
result vector will be of the form [1.0, d, d^2, 1/d].

The exact behavior is specified in the following pseudo-code:

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = 1.0;
result.y = tmp0.y * tmp1.y;
result.z = tmp0.z;
result.w = tmp1.w;

Given an arbitrary vector, d^2 can be obtained using the DP3
instruction (using the same vector for both operands) and 1/d can be
obtained from d^2 using the RSQ instruction.

This distance vector is useful for per-fragment light attenuation
calculations: a DP3 operation using the distance vector and an
attenuation constants vector as operands will yield the attenuation
factor.


3.11.5.9 EX2: Exponential Base 2

The EX2 instruction approximates 2 raised to the power of the scalar
operand and replicates the approximation to all four components of
the result vector.

tmp = ScalarLoad(op0);
result.x = Approx2ToX(tmp);
result.y = Approx2ToX(tmp);
result.z = Approx2ToX(tmp);
result.w = Approx2ToX(tmp);


3.11.5.10 FLR: Floor

The FLR instruction performs a component-wise floor operation on the
operand to generate a result vector. The floor of a value is
defined as the largest integer less than or equal to the value. The
floor of 2.3 is 2.0; the floor of -3.6 is -4.0.

tmp = VectorLoad(op0);
result.x = floor(tmp.x);
result.y = floor(tmp.y);
result.z = floor(tmp.z);
result.w = floor(tmp.w);


3.11.5.11 FRC: Fraction

The FRC instruction extracts the fractional portion of each
component of the operand to generate a result vector. The
fractional portion of a component is defined as the result after
subtracting off the floor of the component (see FLR), and is always
in the range [0.0, 1.0).

For negative values, the fractional portion is NOT the number
written to the right of the decimal point -- the fractional portion
of -1.7 is not 0.7 -- it is 0.3. 0.3 is produced by subtracting the
floor of -1.7 (-2.0) from -1.7.

tmp = VectorLoad(op0);
result.x = fraction(tmp.x);
result.y = fraction(tmp.y);
result.z = fraction(tmp.z);
result.w = fraction(tmp.w);


3.11.5.12 LG2: Logarithm Base 2

The LG2 instruction approximates the base 2 logarithm of the scalar
operand and replicates it to all four components of the result
vector.

tmp = ScalarLoad(op0);
result.x = ApproxLog2(tmp);
result.y = ApproxLog2(tmp);
result.z = ApproxLog2(tmp);
result.w = ApproxLog2(tmp);

If the scalar operand is zero or negative, the result is undefined.


3.11.5.13 LIT: Light Coefficients

The LIT instruction accelerates per-fragment lighting by computing
lighting coefficients for ambient, diffuse, and specular light
contributions. The "x" component of the single operand is assumed
to hold a diffuse dot product (n dot VP_pli, as in the vertex
lighting equations in Section 2.13.1). The "y" component of the
operand is assumed to hold a specular dot product (n dot h_i). The
"w" component of the operand is assumed to hold the specular
exponent of the material (s_rm), and is clamped to the range (-128,
+128) exclusive.

The "x" component of the result vector receives the value that
should be multiplied by the ambient light/material product (always
1.0). The "y" component of the result vector receives the value
that should be multiplied by the diffuse light/material product
(n dot VP_pli). The "z" component of the result vector receives the
value that should be multiplied by the specular light/material
product (f_i * (n dot h_i) ^ s_rm). The "w" component of the result
is the constant 1.0.

Negative diffuse and specular dot products are clamped to 0.0, as is
done in the standard per-vertex lighting operations. In addition,
if the diffuse dot product is zero or negative, the specular
coefficient is forced to zero.

tmp = VectorLoad(op0);
if (tmp.x < 0) tmp.x = 0;
if (tmp.y < 0) tmp.y = 0;
if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);
else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;
result.x = 1.0;
result.y = tmp.x;
result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;
result.w = 1.0;

The exponentiation approximation function may be defined in terms of
the base 2 exponentiation and logarithm approximation operations in
the EX2 and LG2 instructions, where

ApproxPower(a,b) = ApproxExp2(b * ApproxLog2(a)).

In particular, the approximation may not be any more accurate than
the underlying EX2 and LG2 operations.

Also, since 0^0 is defined to be 1, RoughApproxPower(0.0, 0.0) will
produce 1.0.


3.11.5.14 LRP: Linear Interpolation

The LRP instruction performs a component-wise linear interpolation
between the second and third operands using the first operand as the
blend factor.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
tmp2 = VectorLoad(op2);
result.x = tmp0.x * tmp1.x + (1 - tmp0.x) * tmp2.x;
result.y = tmp0.y * tmp1.y + (1 - tmp0.y) * tmp2.y;
result.z = tmp0.z * tmp1.z + (1 - tmp0.z) * tmp2.z;
result.w = tmp0.w * tmp1.w + (1 - tmp0.w) * tmp2.w;


3.11.5.15 MAD: Multiply and Add

The MAD instruction performs a component-wise multiply of the first two
operands, and then does a component-wise add of the product to the
third operand to yield a result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
tmp2 = VectorLoad(op2);
result.x = tmp0.x * tmp1.x + tmp2.x;
result.y = tmp0.y * tmp1.y + tmp2.y;
result.z = tmp0.z * tmp1.z + tmp2.z;
result.w = tmp0.w * tmp1.w + tmp2.w;

The multiplication and addition operations in this instruction are
subject to the same rules as described for the MUL and ADD
instructions.


3.11.5.16 MAX: Maximum

The MAX instruction computes component-wise maximums of the values
in the two operands to yield a result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = (tmp0.x > tmp1.x) ? tmp0.x : tmp1.x;
result.y = (tmp0.y > tmp1.y) ? tmp0.y : tmp1.y;
result.z = (tmp0.z > tmp1.z) ? tmp0.z : tmp1.z;
result.w = (tmp0.w > tmp1.w) ? tmp0.w : tmp1.w;


3.11.5.17 MIN: Minimum

The MIN instruction computes component-wise minimums of the values
in the two operands to yield a result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = (tmp0.x > tmp1.x) ? tmp1.x : tmp0.x;
result.y = (tmp0.y > tmp1.y) ? tmp1.y : tmp0.y;
result.z = (tmp0.z > tmp1.z) ? tmp1.z : tmp0.z;
result.w = (tmp0.w > tmp1.w) ? tmp1.w : tmp0.w;


3.11.5.18 MOV: Move

The MOV instruction copies the value of the operand to yield a
result vector.

result = VectorLoad(op0);


3.11.5.19 MUL: Multiply

The MUL instruction performs a component-wise multiply of the two
operands to yield a result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = tmp0.x * tmp1.x;
result.y = tmp0.y * tmp1.y;
result.z = tmp0.z * tmp1.z;
result.w = tmp0.w * tmp1.w;

The following rules apply to multiplication:

1. <x> * <y> == <y> * <x>, for all <x> and <y>.
2. +/-0.0 * <x> = +/-0.0, at least for all <x> that correspond to
representable numbers (IEEE "not a number" and "infinity"
encodings may be exceptions).
3. +1.0 * <x> = <x>, for all <x>.

Multiplication by zero and one should be invariant, as it may be
used to evaluate conditional expressions without branching.


3.11.5.20 POW: Exponentiate

The POW instruction approximates the value of the first scalar
operand raised to the power of the second scalar operand and
replicates it to all four components of the result vector.

tmp0 = ScalarLoad(op0);
tmp1 = ScalarLoad(op1);
result.x = ApproxPower(tmp0, tmp1);
result.y = ApproxPower(tmp0, tmp1);
result.z = ApproxPower(tmp0, tmp1);
result.w = ApproxPower(tmp0, tmp1);

The exponentiation approximation function may be implemented using
the base 2 exponentiation and logarithm approximation operations in
the EX2 and LG2 instructions. In particular,

ApproxPower(a,b) = ApproxExp2(b * ApproxLog2(a)).

Note that a logarithm may be involved even for cases where the
exponent is an integer. This means that it may not be possible to
exponentiate correctly with a negative base. In constrast, it is
possible in a "normal" mathematical formulation to raise negative
numbers to integral powers (e.g., (-3)^2== 9, and (-0.5)^-2==4).


3.11.5.21 RCP: Reciprocal

The RCP instruction approximates the reciprocal of the scalar
operand and replicates it to all four components of the result
vector.

tmp = ScalarLoad(op0);
result.x = ApproxReciprocal(tmp);
result.y = ApproxReciprocal(tmp);
result.z = ApproxReciprocal(tmp);
result.w = ApproxReciprocal(tmp);

The following rule applies to reciprocation:

1. ApproxReciprocal(+1.0) = +1.0.


3.11.5.22 RSQ: Reciprocal Square Root

The RSQ instruction approximates the reciprocal of the square root
of the absolute value of the scalar operand and replicates it to all
four components of the result vector.

tmp = fabs(ScalarLoad(op0));
result.x = ApproxRSQRT(tmp);
result.y = ApproxRSQRT(tmp);
result.z = ApproxRSQRT(tmp);
result.w = ApproxRSQRT(tmp);


3.11.5.23 SCS: Sine/Cosine

The SCS instruction approximates the trigonometric sine and cosine
of the angle specified by the scalar operand and places the cosine
in the x component and the sine in the y component of the result
vector. The z and w components of the result vector are undefined.
The angle is specified in radians and must be in the range [-PI,PI].

tmp = ScalarLoad(op0);
result.x = ApproxCosine(tmp);
result.y = ApproxSine(tmp);

If the scalar operand is not in the range [-PI,PI], the result
vector is undefined.


3.11.5.24 SGE: Set On Greater or Equal Than

The SGE instruction performs a component-wise comparison of the two
operands. Each component of the result vector is 1.0 if the
corresponding component of the first operands is greater than or
equal that of the second, and 0.0 otherwise.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = (tmp0.x >= tmp1.x) ? 1.0 : 0.0;
result.y = (tmp0.y >= tmp1.y) ? 1.0 : 0.0;
result.z = (tmp0.z >= tmp1.z) ? 1.0 : 0.0;
result.w = (tmp0.w >= tmp1.w) ? 1.0 : 0.0;


3.11.5.25 SIN: Sine

The SIN instruction approximates the trigonometric sine of the angle
specified by the scalar operand and replicates it to all four
components of the result vector. The angle is specified in radians
and does not have to be in the range [-PI,PI].

tmp = ScalarLoad(op0);
result.x = ApproxSine(tmp);
result.y = ApproxSine(tmp);
result.z = ApproxSine(tmp);
result.w = ApproxSine(tmp);


3.11.5.26 SLT: Set On Less Than

The SLT instruction performs a component-wise comparison of the two
operands. Each component of the result vector is 1.0 if the
corresponding component of the first operand is less than that of
the second, and 0.0 otherwise.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = (tmp0.x < tmp1.x) ? 1.0 : 0.0;
result.y = (tmp0.y < tmp1.y) ? 1.0 : 0.0;
result.z = (tmp0.z < tmp1.z) ? 1.0 : 0.0;
result.w = (tmp0.w < tmp1.w) ? 1.0 : 0.0;


3.11.5.27 SUB: Subtract

The SUB instruction performs a component-wise subtraction of the
second operand from the first to yield a result vector.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = tmp0.x - tmp1.x;
result.y = tmp0.y - tmp1.y;
result.z = tmp0.z - tmp1.z;
result.w = tmp0.w - tmp1.w;


3.11.5.28 SWZ: Extended Swizzle

The SWZ instruction loads the single vector operand, and performs a
swizzle operation more powerful than that provided for loading
normal vector operands to yield an instruction vector.

After the operand is loaded, the "x", "y", "z", and "w" components
of the result vector are selected by the first, second, third, and
fourth matches of the <xyzwExtSwizComp> or <rgbaExtSwizComp> pattern
in the <extendedSwizzle> rule.

A result component can be selected from any of the four components
of the operand or the constants 0.0 and 1.0. The result component
can also be optionally negated. The following pseudocode describes
the component selection method. "operand" refers to the vector
operand. "select" is an enumerant where the values ZERO, ONE, X, Y,
Z, and W correspond to the <xyzwExtSwizSel> rule matching "0", "1", "x",
"y", "z", and "w", respectively, or the <rgbaExtSwizSel> rule
matching "0", 1", "r", "g", "b", and "a", respectively. "negate" is
TRUE if and only if the <optionalSign> rule in <xyzwExtSwizComp>
or <rgbaExtSwizComp> matches "-".

float ExtSwizComponent(floatVec operand, enum select, boolean negate)
{
float result;
switch (select) {
case ZERO: result = 0.0; break;
case ONE: result = 1.0; break;
case X: result = operand.x; break;
case Y: result = operand.y; break;
case Z: result = operand.z; break;
case W: result = operand.w; break;
}
if (negate) {
result = -result;
}
return result;
}

The entire extended swizzle operation is then defined using the
following pseudocode:

tmp = VectorLoad(op0);
result.x = ExtSwizComponent(tmp, xSelect, xNegate);
result.y = ExtSwizComponent(tmp, ySelect, yNegate);
result.z = ExtSwizComponent(tmp, zSelect, zNegate);
result.w = ExtSwizComponent(tmp, wSelect, wNegate);

"xSelect", "xNegate", "ySelect", "yNegate", "zSelect", "zNegate",
"wSelect", and "wNegate" correspond to the "select" and "negate"
values above for the four <xyzwExtSwizComp> or <rgbaExtSwizComp>
matches.

Since this instruction allows for component selection and negation
for each individual component, the grammar does not allow the use of
the normal swizzle and negation operations allowed for vector
operands in other instructions.


3.11.5.29 XPD: Cross Product

The XPD instruction computes the cross product using the first three
components of its two vector operands to generate the x, y, and z
components of the result vector. The w component of the result
vector is undefined.

tmp0 = VectorLoad(op0);
tmp1 = VectorLoad(op1);
result.x = tmp0.y * tmp1.z - tmp0.z * tmp1.y;
result.y = tmp0.z * tmp1.x - tmp0.x * tmp1.z;
result.z = tmp0.x * tmp1.y - tmp0.y * tmp1.x;


3.11.6 Fragment Program Texture Instruction Set

The first three texture instructions described below specify the
mapping of 4-tuple vectors to colors of an image. The sampling of
the texture works as described in section 3.8, except that texture
environments and texture functions are not applicable, and the
texture enables hierarchy is replaced by explicit references to
the desired texture target (i.e., 1D, 2D, 3D, cube map, rectangle).
These texture instructions specify how the 4-tuple is mapped into
the coordinates used for sampling. The following function is used
to describe the texture sampling in the descriptions below:

vec4 TextureSample(float s, float t, float r, float lodBias,
int texImageUnit, enum texTarget);

Note that not all three texture coordinates, s, t, and r, are
used by all texture targets. In particular, 1D texture targets only
use the s component, and 2D and rectangle (non-power-of-two) texture
targets only use the s and t components. The descriptions of the
texture instructions below supply all three components, as would be
the case with 3D or cube map targets.

If a fragment program samples from a texture target on a texture
image unit where the bound texture object is not complete, as
defined in section 3.8.9, the result will be the vector
(R, G, B, A) = (0, 0, 0, 1).

A fragment program will fail to load if it attempts to sample from
multiple texture targets on the same texture image unit. For
example, the following program would fail to load:

!!ARBfp1.0
TEX result.color, fragment.texcoord[0], texture[0], 2D;
TEX result.depth, fragment.texcoord[1], texture[0], 3D;
END

The fourth texture instruction described below, KIL, does not sample
from a texture, but rather prevents further processing of the
current fragment if any component of its 4-tuple vector is less than
zero.

A dependent texture instruction is one that samples using a texture
coordinate residing in a temporary, rather than in an attribute or
a parameter. A program may have a chain of dependent texture
instructions, where the result of the first texture instruction is
used as the coordinate for a second texture instruction, which is in
turn used as the coordinate for a third texture instruction, and so
on. Each node in this chain is termed an indirection, and can be
thought of as a set of texture samples that execute in parallel
followed by a sequence of ALU instructions.

Some implementations may have limitations on how long the dependency
chain may be, and so indirections are counted as a resource just
like instructions or temporaries are counted. All programs have at
least one indirection, or one node in this chain, even if the
program performs no texture operation. Each instruction encountered
is included in this node until a texture instruction is encountered

- whose texture coordinate is a temporary that has been previously
written in the current node; or

- whose result vector is a temporary that is also the operand or
result vector of a previous ALU instruction in the current node.

A new node is then started, including the texture instruction and
all subsequent instructions, and the process repeats for all
instructions in the program. Note that for simplicity in counting,
result writemasks and operand suffixes are not taken into
consideration when counting indirections.


3.11.6.1 TEX: Map coordinate to color

The TEX instruction takes the first three components of
its source vector, and maps them to s, t, and r. These coordinates
are used to sample from the specified texture target on the
specified texture image unit in a manner consistent with its
parameters. The resulting sample is mapped to RGBA as described in
table 3.21 and written to the result vector.

tmp = VectorLoad(op0);
result = TextureSample(tmp.x, tmp.y, tmp.z, 0.0, op1, op2);


3.11.6.2 TXP: Project coordinate and map to color

The TXP instruction divides the first three components of its source
vector by the fourth component and maps the results to s, t, and r.
These coordinates are used to sample from the specified texture
target on the specified texture image unit in a manner consistent
with its parameters. The resulting sample is mapped to RGBA as
described in table 3.21 and written to the result vector. If the
value of the fourth component of the source vector is less than or
equal to zero, the result vector is undefined.

tmp = VectorLoad(op0);
tmp.x = tmp.x / tmp.w;
tmp.y = tmp.y / tmp.w;
tmp.z = tmp.z / tmp.w;
result = TextureSample(tmp.x, tmp.y, tmp.z, 0.0, op1, op2);


3.11.6.3 TXB: Map coordinate to color while biasing its LOD

The TXB instruction takes the first three components of its source
vector and maps them to s, t, and r. These coordinates are used to
sample from the specified texture target on the specified texture
image unit in a manner consistent with its parameters.
Additionally, the fourth component of the source vector is applied
to equation 3.14 as fragment_bias below to further bias the level of
detail.

lambda'(x,y) = log2[p(x,y)] +
clamp(texobj_bias + texunit_bias + fragment_bias)

The resulting sample is mapped to RGBA as described in table 3.21
and written to the result vector.

tmp = VectorLoad(op0);
result = TextureSample(tmp.x, tmp.y, tmp.z, tmp.w, op1, op2);


3.11.6.4 KIL: Kill fragment

Rather than mapping a coordinate set to a color, this function
prevents a fragment from receiving any future processing. If any
component of its source vector is negative, the processing of this
fragment will be discontinued and no further outputs to this
fragment will occur. Subsequent stages of the GL pipeline will be
skipped for this fragment.

tmp = VectorLoad(op0);
if ((tmp.x < 0) || (tmp.y < 0) ||
(tmp.z < 0) || (tmp.w < 0))
{
exit;
}


3.11.7 Program Matrices

In addition to GL's conventional matrices, several additional
program matrices are available for use as program parameters. These
matrices have names of the form MATRIX<i>_ARB where <i> is between
zero and <n>-1 where <n> is the value of the implementation-
dependent constant MAX_PROGRAM_MATRICES_ARB. The MATRIX<i>_ARB
constants obey MATRIX<i>_ARB = MATRIX0_ARB + <i>. The value of
MAX_PROGRAM_MATRICES_ARB must be at least eight. The maximum stack
depth for program matrices is defined by the
MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB and must be at least 1.


3.11.8 Required Fragment Program State

The state required to support program objects of all targets
consists of:

an integer for the program error position, initially -1;

an array of ubytes for the program error string, initially empty;

and the state that must be maintained to indicate which integers
are currently in use as program object names.

The state required to support the fragment program target consists
of:

a bit indicating whether or not fragment program mode is enabled,
initially disabled;

a set of MAX_PROGRAM_ENV_PARAMETERS_ARB four-component floating-
point program environment parameters, initially set to (0,0,0,0);

an unsigned integer naming the currently bound fragment program,
initially zero;

The state required for each fragment program object consists of:

an unsigned integer indicating the program object name;

an array of type ubyte containing the program string, initially
empty;

an unsigned integer holding the length of the program string,
initially zero;

an enum indicating the program string format, initially
PROGRAM_FORMAT_ASCII_ARB;

a bit indicating whether or not the program exceeds the native
limits;

six unsigned integers holding the number of instruction (ALU,
texture, and total), texture indirection, temporary variable, and
program parameter binding resources used by the program, initially
all zero;

six unsigned integers holding the number of native instruction
(ALU, texture, and total), texture indirection, temporary
variable, and program parameter binding resources used by the
program, initially all zero;

and a set of MAX_PROGRAM_LOCAL_PARAMETERS_ARB four-component
floating-point program local parameters, initially set to
(0,0,0,0).

Initially, no fragment program objects exist.


Additions to Chapter 4 of the OpenGL 1.3 Specification (Per-Fragment Operations and the Frame Buffer)


    None


Additions to Chapter 5 of the OpenGL 1.3 Specification (Special Functions)


    Modify Section 5.4, Display Lists (p. 191)

(modify third paragraph, p. 195) ... These are IsList, GenLists,
..., IsProgramARB, GenProgramsARB, and DeleteProgramsARB, as well as
IsEnabled and all the Get commands (chapter 6).


Additions to Chapter 6 of the OpenGL 1.3 Specification (State and State Requests)


    Modify Section 6.1.2, Data Conversions (p. 198)

(add before last paragraph, p. 198) The matrix selected by the
current matrix mode can be queried by calling GetBooleanv,
GetIntegerv, GetFloatv, and GetDoublev with <pname> set to
CURRENT_MATRIX_ARB; the matrix will be returned in transposed form
with <pname> set to TRANSPOSE_CURRENT_MATRIX_ARB. The depth of the
selected matrix stack can be queried with <pname> set to
CURRENT_MATRIX_STACK_DEPTH_ARB. Querying CURRENT_MATRIX_ARB and
CURRENT_MATRIX_STACK_DEPTH_ARB is the only means for querying the
matrix and matrix stack depth of the program matrices described in
section 3.11.7.


(add to end of last paragraph, p. 199) Queries of texture state
variables corresponding to texture coordinate processing unit
(namely, TexGen state and enables, and matrices) will produce an
INVALID_OPERATION error if the value of ACTIVE_TEXTURE is greater
than or equal to MAX_TEXTURE_COORDS_ARB. All other texture state
queries will result in an INVALID_OPERATION error if the value of
ACTIVE_TEXTURE is greater than or equal to
MAX_TEXTURE_IMAGE_UNITS_ARB.


Modify Section 6.1.11, Pointer and String Queries (p. 206)

(modify last paragraph, p. 206) ... The possible values for <name>
are VENDOR, RENDERER, VERSION, EXTENSIONS, and
PROGRAM_ERROR_STRING_ARB.


(add after last paragraph of section, p. 207) Queries of
PROGRAM_ERROR_STRING_ARB return a pointer to an implementation-
dependent program load error string. If the last call to
ProgramStringARB failed to load a program, the returned string
describes at least one reason why the program failed to load. If
the last call to ProgramStringARB successfully loaded a program, the
returned string may be empty (containing only a zero terminator) or
may contain one or more implementation-dependent warning messages.
The contents of the error string are guaranteed to remain constant
only until the next ProgramStringARB command, which may overwrite
the error string.


Insert a new Section 6.1.12, Program Queries (p. 207), between
existing sections 6.1.11 and 6.1.12.

6.1.12 Program Queries

The commands

void GetProgramEnvParameterdvARB(enum target, uint index,
double *params);
void GetProgramEnvParameterfvARB(enum target, uint index,
float *params);

obtain the current value for the program environment parameter
numbered <index> for the given program target <target>, and places
the information in the array <params>. The error INVALID_ENUM is
generated if <target> specifies a nonexistent program target or a
program target that does not support program environment parameters.
The error INVALID_VALUE is generated if <index> is greater than or
equal to the implementation-dependent number of supported program
environment parameters for the program target.

When <target> is FRAGMENT_PROGRAM_ARB, each program parameter
returned is an array of four values.

The commands

void GetProgramLocalParameterdvARB(enum target, uint index,
double *params);
void GetProgramLocalParameterfvARB(enum target, uint index,
float *params);

obtain the current value for the program local parameter numbered
<index> belonging to the program object currently bound to <target>,
and places the information in the array <params>. The error
INVALID_ENUM is generated if <target> specifies a nonexistent
program target or a program target that does not support program
local parameters. The error INVALID_VALUE is generated if <index>
is greater than or equal to the implementation-dependent number of
supported program local parameters for the program target.

When the program target type is FRAGMENT_PROGRAM_ARB, each program
local parameter returned is an array of four values.

The command

void GetProgramivARB(enum target, enum pname, int *params);

obtains program state for the program target <target>, writing the
state into the array given by <params>. GetProgramivARB can be used
to determine the properties of the currently bound program object or
implementation limits for <target>.

If <pname> is PROGRAM_LENGTH_ARB, PROGRAM_FORMAT_ARB, or
PROGRAM_BINDING_ARB, GetProgramivARB returns one integer holding the
program string length (in bytes), program string format, and program
name, respectively, for the program object currently bound to
<target>.

If <pname> is MAX_PROGRAM_LOCAL_PARAMETERS_ARB or
MAX_PROGRAM_ENV_PARAMETERS_ARB, GetProgramivARB returns one integer
holding the maximum number of program local parameters or program
environment parameters, respectively, supported for the program
target <target>.

If <pname> is MAX_PROGRAM_INSTRUCTIONS_ARB,
MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, MAX_PROGRAM_TEX_INSTRUCTIONS_ARB,
MAX_PROGRAM_TEX_INDIRECTIONS_ARB, MAX_PROGRAM_TEMPORARIES_ARB,
MAX_PROGRAM_PARAMETERS_ARB, or MAX_PROGRAM_ATTRIBS_ARB,
GetProgramivARB returns a single integer giving the maximum number
of total instructions, ALU instructions, texture instructions,
texture indirections, temporaries, parameters, and attributes that
can be used by a program of type <target>. If <pname> is
PROGRAM_INSTRUCTIONS_ARB, PROGRAM_ALU_INSTRUCTIONS_ARB,
PROGRAM_TEX_INSTRUCTIONS_ARB, PROGRAM_TEX_INDIRECTIONS_ARB,
PROGRAM_TEMPORARIES_ARB, PROGRAM_PARAMETERS_ARB, or
PROGRAM_ATTRIBS_ARB, GetProgramivARB returns a single integer giving
the number of total instructions, ALU instructions, texture
instructions, texture indirections, temporaries, parameters, and
attributes used by the current program for <target>.

If <pname> is MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,
MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,
MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,
MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,
MAX_PROGRAM_NATIVE_PARAMETERS_ARB, or
MAX_PROGRAM_NATIVE_ATTRIBS_ARB, GetProgramivARB returns a single
integer giving the maximum number of native instruction, ALU
instruction, texture instruction, texture indirection, temporary,
parameter, and attribute resources available to a program of type
<target>. If <pname> is PROGRAM_NATIVE_INSTRUCTIONS_ARB,
PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,
PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,
PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,
PROGRAM_NATIVE_TEMPORARIES_ARB, PROGRAM_NATIVE_PARAMETERS_ARB, or
PROGRAM_NATIVE_ATTRIBS_ARB, GetProgramivARB returns a single integer
giving the number of native instruction, ALU instruction, texture
instruction, texture indirection, temporary, parameter, and
attribute resources consumed by the program currently bound to
<target>. Native resource counts will reflect the results of
implementation-dependent scheduling and optimization algorithms
applied by the GL, as well as emulation of non-native features. If
<pname> is PROGRAM_UNDER_NATIVE_LIMITS_ARB, GetProgramivARB returns
0 if the native resource consumption of the program currently bound
to <target> exceeds the number of available resources for any
resource type, and 1 otherwise.

The command

void GetProgramStringARB(enum target, enum pname, void *string);

obtains the program string for the program object bound to <target>
and places the information in the array <string>. <pname> must be
PROGRAM_STRING_ARB. <n> ubytes are returned into the array program
where <n> is the length of the program in ubytes, as returned by
GetProgramivARB when <pname> is PROGRAM_LENGTH_ARB. The program
string is always returned using the format given when the program
string was specified.

The command

boolean IsProgramARB(uint program);

returns TRUE if <program> is the name of a program object. If
<program> is zero or is a non-zero value that is not the name of a
program object, or if an error condition occurs, IsProgramARB
returns FALSE. A name returned by GenProgramsARB, but not yet
bound, is not the name of a program object.


Modify Section 6.2, State Tables (p. 216)

(add to caption of Table 6.5) When accessing the current texture
coordinates (CURRENT_TEXTURE_COORDS) or the texture coordinates
associated with raster position (CURRENT_RASTER_TEXTURE_COORDS), the
active texture unit selector (ACTIVE_TEXTURE) must be less than the
implementation dependent maximum number of texture coordinate sets
(MAX_TEXTURE_COORDS_ARB).

(add to caption of Table 6.8) When accessing the texture matrix
stack (TEXTURE_MATRIX, TRANSPOSE_TEXTURE_MATRIX) or the texture
matrix stack pointer (TEXTURE_STACK_DEPTH), the active texture unit
selector (ACTIVE_TEXTURE) must be less than the implementation
dependent maximum number of texture coordinate sets
(MAX_TEXTURE_COORDS_ARB).

(split Table 6.17 into two tables, Texture Environment and Texture
Coordinate Generation; move active texture unit selector and texture
coordinate generation state to table 6.18; renumber subsequent
tables)

(add to captions of Tables 6.14, 6.15, 6.16) The active texture unit
selector (ACTIVE_TEXTURE) identifies which texture object is
accessed, and must be less than the implementation dependent maximum
number of texture image units (MAX_TEXTURE_IMAGE_UNITS_ARB).

(add to caption of Table 6.18) With the exception of ACTIVE_TEXTURE,
the active texture unit selector (ACTIVE_TEXTURE) identifies which
texture coordinate set is accessed, and must be less than the
implementation dependent maximum number of texture coordinate sets
(MAX_TEXTURE_COORDS_ARB).

Additions to Appendix A of the OpenGL 1.3 Specification (Invariance)


    Add to end of Section A.3 (p. 242):

Rule 4. Fragment program instructions not relevant to the
calculation of any result must have no effect on that result.

Rule 5. Fragment program instructions relevant to the calculation
of any result must always produce the identical result.

Instructions relevant to the calculation of a result are any
instructions in a sequence of instructions that eventually determine
the source values for the calculation under consideration.

There is no guaranteed invariance between fragment colors generated
by conventional GL texturing mode and fragment colors generated by
fragment program mode. Multi-pass rendering algorithms that require
rendering invariances to operate correctly should not mix
conventional GL fragment texturing mode with fragment program mode
for different rendering passes. However, such algorithms will
operate correctly if the algorithms limit themselves to a single
mode of fragment color generation.

There is no guaranteed invariance between the final z window
coordinates of fragments processed by fragment programs that write
depth values and fragments processed by any other means, even if the
fragment programs in question simply copy the z value from the
"fragment.position" binding. Multi-pass rendering algorithms that
use depth-replacing fragment programs should use depth-replacing
fragment programs on each pass to guarantee identical z values.

The texture sample chosen for a fragment of a primitive must be
invariant between fragment program mode and conventional texture
application mode subject to these conditions:

1. All state with the exception of fragment program state is
identical

2. The primitives generating the fragments are identical

3. The sample in the fragment program mode is the result of a
'TEX' instruction (or a 'TXP' instruction with a unity q)

4. The texture coordinate operand for the texture instruction uses
the same texture coordinate set as the conventional mode sample

5. The texture coordinate operand for the texture instruction has
not been the result of any other operations in the fragment
program


Additions to the AGL/GLX/WGL Specifications


    Program objects are shared between AGL/GLX/WGL rendering contexts if
and only if the rendering contexts share display lists. No change
is made to the AGL/GLX/WGL API.

Changes to program objects shared between multiple rendering
contexts will be serialized (i.e., the changes will occur in a
specific order).

Changes to a program object made by one rendering context are not
guaranteed to take effect in another rendering context until the
other calls BindProgram to bind the program object.

When a program object is deleted by one rendering context, the
object itself is not destroyed until it is no longer the current
program object in any context. However, the name of the deleted
object is removed from the program object name space, so the next
attempt to bind a program using the same name will create a new
program object. Recall that destroying a program object bound in
the current rendering context effectively unbinds the object being
destroyed.


Dependencies on OpenGL 1.4


    If OpenGL 1.4 is not supported, the modified equation for the 
calculation of level of detail by the TXB instruction in 3.11.6.3
should read

lambda'(x,y) = log2[p(x,y)] +
clamp(texunit_bias + fragment_bias)

Dependencies on EXT_vertex_weighting and ARB_vertex_blend


    If EXT_vertex_weighting and ARB_vertex_blend are both not supported,
all discussions of multiple modelview matrices should be removed.

In particular, the line in the grammar

<stateMatrixName> ::= "modelview" <stateOptModMatNum>

should be changed to

<stateMatrixName> ::= "modelview"

and the rules <stateOptModMatNum> and <stateModMatNum> should be
deleted. The first line of Table X.2.7 should be modified to read:

Binding Underlying State
------------------------------------ ---------------------------
state.matrix.modelview modelview matrix

The caption for Table X.2.7 should be modified to exclude optional
modelview matrix number. Subsequent references to "modelview matrix
zero" and "modelview matrix 1" should be changed to "modelview
matrix" and the example "state.matrix.modelview[1].row[0]" should be
changed to "state.matrix.modelview.row[0]".


Dependencies on ARB_matrix_palette:


    If ARB_matrix_palette is not supported, all discussions of the 
matrix palette should be removed.

In particular, the line

"palette" "[" <statePaletteMatNum> "]"

should be removed from the <stateMatrixName> grammar rule, and the
<statePaletteMatNum> grammar rule should be removed entirely.
"state.matrix.palette[n]" should be removed from Table X.2.7.


Dependencies on ARB_transpose_matrix


    If ARB_transpose_matrix is not supported, the discussion of
TRANSPOSE_CURRENT_MATRIX_ARB in the edits to section 6.1.2 should be
removed.


Dependencies on EXT_fog_coord


    If EXT_fog_coord is not supported, references to "fog coordinate"
in the definition of the "fragment.fogcoord" attribute should be
removed.

Dependencies on EXT_texture_rectangle


    If NV_texture_rectangle is not supported, the discussion of the
rectangle (non-power-of-two) texture target in section 3.11.6 should
be removed, and the line

"RECT"

should be removed from the <texTarget> grammar rule.


Interactions with ARB_shadow


    The texture comparison introduced by ARB_shadow can be expressed in 
terms of a fragment program, and in fact use the same internal
resources on some implementations. Therefore, if fragment program
mode is enabled, the GL behaves as if TEXTURE_COMPARE_MODE_ARB is
NONE.


Interactions with ARB_vertex_program


    The program object management entrypoints described in sections
2.14.1 (for vertex programs) and 3.11.1 (for fragment programs)
are shared by both program targets. The PROGRAM_ERROR_STRING_ARB
and program queries in sections 6.1.11 and 6.1.12 are also shared,
as are all common tokens.

The Errors section should be modified to generate INVALID_OPERATION
from the Get command with argument CURRENT_MATRIX_ARB,
TRANSPOSE_CURRENT_MATRIX_ARB, and CURRENT_MATRIX_STACK_DEPTH_ARB
when the current matrix mode is TEXTURE.

In the presence of ARB_vertex_program, ARB_fragment_program must
recognize and return appropriate values for the GetProgram <pname>
tokens introduced in that spec but not otherwise shared by
ARB_fragment_program:

PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0
MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1
PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2
MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3

The following tables list new program object state and
implementation-dependent state:

Get Value Type Get Command Initial Value Description Sec Attrib
-------------------- ----- ------------------- --------------- ---------------------- -------- ------
PROGRAM_ADDRESS_REGISTERS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
address registers
PROGRAM_NATIVE_ADDRESS_ Z+ GetProgramivARB 0 bound program native 6.1.12 -
REGISTERS_ARB address registers

Table X.7. Program Object State. Program object queries return attributes of
the program object currently bound to the program target <target>.


Minimum
Get Value Type Get Command Value Description Sec. Attrib
--------- ---- ----------- ------- ----------- ---- ------
MAX_PROGRAM_ADDRESS_REGISTERS_ARB Z+ GetProgramivARB 0 maximum program 6.1.12 -
address registers
MAX_PROGRAM_NATIVE_ADDRESS_ Z+ GetProgramivARB 0 maximum program native 6.1.12 -
REGISTERS_ARB address registers

Table X.10. New Implementation-Dependent Values Introduced by
ARB_vertex_program.


In the presence of ARB_fragment_program, ARB_vertex_program must
recognize and return appropriate values for the GetProgram <pname>
tokens introduced in this spec. The following tables list new
program object state and implementation-dependent state:

Get Value Type Get Command Initial Value Description Sec Attrib
-------------------- ----- ------------------- --------------- ---------------------- -------- ------
PROGRAM_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 maximum program 6.1.12 -
ALU instructions
PROGRAM_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 maximum program 6.1.12 -
texture instructions
PROGRAM_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 0 maximum program 6.1.12 -
texture indirections
PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 maximum program native 6.1.12 -
ALU instructions
PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 maximum program native 6.1.12 -
texture instructions
PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 0 maximum program native 6.1.12 -
texture indirections

Table X.7. Program Object State. Program object queries return attributes of
the program object currently bound to the program target <target>.


Minimum
Get Value Type Get Command Value Description Sec. Attrib
--------- ---- ----------- ------- ----------- ---- ------
MAX_PROGRAM_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 Number of frag. prg. 6.1.12 -
ALU instructions
MAX_PROGRAM_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 Number of frag. prg. 6.1.12 -
texture instructions
MAX_PROGRAM_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 0 Number of frag. prg. 6.1.12 -
texture indirections
MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 maximum program native 6.1.12 -
ALU instructions
MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 maximum program native 6.1.12 -
texture instructions
MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 0 maximum program native 6.1.12 -
texture indirections

Table X.10. New Implementation-Dependent Values Introduced by
ARB_fragment_program.


Interactions with ATI_fragment_shader


    The existing ATI_fragment_shader extension, if supported, also
provides a similar fragment programming model. Mixing the two
models in a single application is possible but not recommended.
FRAGMENT_PROGRAM_ARB has priority over FRAGMENT_SHADER_ATI if
both are enabled.


Interactions with NV_fragment_program


    The NV_fragment_program extension, if supported, also provides a 
similar programming model. This extension is incompatible with
NV_fragment_program in a number of different ways. Mixing the two
models in a single application is possible but not recommended. The
interactions between the extensions are defined below.

Functions, enumerants, and programs defined in NV_fragment_program
are called "NV functions", "NV enumerants", and "NV programs,"
respectively. Functions, enumerants, and programs defined in
ARB_fragment_program are called "ARB functions", "ARB enumerants",
and "ARB programs," respectively.

The following GL state is identical in the two extensions:

- Fragment program mode enable. The NV and ARB enumerants have
different values, but the same effect.

- Program error position.

- Program error string.

- NV_fragment_program and ARB_fragment_program "program local
parameters."

- Fragment program names, targets, formats, program string,
program string lengths, and residency information. The ARB and
NV query functions operate differently. The ARB query function
does not allow queries of target (passed in to the query) and
residency information. The NV query function does not allow
queries of program name (passed in to the query) or format. The
format of NV programs is always PROGRAM_FORMAT_ASCII_ARB.

- Program object name space. Program objects are created
differently in the NV and ARB specs. Under the NV spec, program
objects are created by calling LoadProgramNV. Under the ARB
spec, program objects are created by calling BindProgramARB with
an unused program name.

The following state is provided only by ARB_fragment_program:

- Program environment parameters.

- Implementation-dependent limits on the number of instructions,
ALU instructions, texture instructions, texture indirections,
program parameters, fragment attributes, resource counts, and
native resource counts. The instruction limit is baked into the
NV spec. Implementations supporting NV_fragment_program have no
specific restrictions on the number of ALU instructions, texture
instructions, texture indirections, or fragment attributes used.
Such implementations also have no limit on program parameters
used, except that no more than one may be used by any single
program instruction.

The following state is provided only by NV_fragment_program:

- Named program parameters (variables defined in the program text
and updated by name).

The following are additional functional differences between
ARB_fragment_program and NV_fragment_program:

- NV programs use a set of register names, with no support for
user-defined variables (other than parameters in the program).
ARB programs provide no support for fixed variable names; all
variables must be declared, explicitly or implicitly, in the
program.

- ARB programs support parameter variables that can be bound to
selected GL state variables, and are updated automatically when
the underlying state changes. NV programs provide no such
support; applications must set program parameters themselves.

- ARB_fragment_program doesn't provide explicit support for
multiple data types (fx12, fp16, fp32) described in
NV_fragment_program, and provides no mechanism for controlling
the precision used to carry out arithmetic operations.

- ARB_fragment_program doesn't support condition codes,
conditional writemasks, or the "C" instruction suffix that
specifies a condition code update.

- ARB_fragment_program doesn't support an absolute value operator
that can be applied to a source vector as it is loaded.

- ARB_fragment_program doesn't define behavior for many floating-
point special cases. On platforms where NV_fragment_program is
supported, ARB programs will have the same special-case
behavior.

- Language to declare program parameters is slightly different
(NV_fragment_program has "DECLARE" and "DEFINE";
ARB_fragment_program has "PARAM").

- NV_fragment_program provides a number of instructions not found
in ARB_fragment_program:

* DDX, DDY: partial derivatives relative to x and y.

* "PK*" and "UP*": packing and unpacking instructions.

* RFL: reflection vector.

* SEQ, SFL, SGT, SLE, SNE, STR: set on equal, false, greater
than, less than or equal, not equal, and true, respectively.

* TXD: texture lookup w/partials.

* X2D: 2D coordinate transformation.

- ARB_fragment_program provides several instructions not found in
NV_fragment_program, and there are a few instruction set
differences:

* ABS: absolute value. ABS instructions are unnecessary in
NV_fragment_program because of the free absolute value on
input operator. Equivalent to:

MOV dst, |src|;

* CMP: compare. Roughly equivalent to the following
sequence, but may be optimized further:

SLT tmp, src0;
LRP dst, tmp, src1, src2;

* DPH: homogenous dot product. Equivalent to:

DP3 tmp, src0, src1;
ADD dst, tmp, src0.w;

* KIL: kill fragment. Both extensions support this
instruction, but the ARB instruction takes a vector
operand rather than a condition code.

* SCS: sine/cosine. Emulated using the separate SIN and COS
instructions in NV_fragment_program, which also have no
restriction on the input values.

* SWZ: extended swizzle. On NV_fragment_program platforms,
this instruction will be emulated using a single MAD
instruction and a program parameter constant.

* TXB: texture sample with bias. Not exposed in the
NV_fragment_program API.

* XPD: cross product. Emulated using a MUL and a MAD
instruction.


GLX Protocol


     The following rendering commands are sent to the server as part of
a glXRender request:

BindProgramARB
2 12 rendering command length
2 4180 rendering command opcode
4 ENUM target
4 CARD32 program

ProgramEnvParameter4fvARB
2 32 rendering command length
2 4184 rendering command opcode
4 ENUM target
4 CARD32 index
4 FLOAT32 params[0]
4 FLOAT32 params[1]
4 FLOAT32 params[2]
4 FLOAT32 params[3]

ProgramEnvParameter4dvARB
2 44 rendering command length
2 4185 rendering command opcode
4 ENUM target
4 CARD32 index
8 FLOAT64 params[0]
8 FLOAT64 params[1]
8 FLOAT64 params[2]
8 FLOAT64 params[3]

ProgramLocalParameter4fvARB
2 32 rendering command length
2 4215 rendering command opcode
4 ENUM target
4 CARD32 index
4 FLOAT32 params[0]
4 FLOAT32 params[1]
4 FLOAT32 params[2]
4 FLOAT32 params[3]

ProgramLocalParameter4dvARB
2 44 rendering command length
2 4216 rendering command opcode
4 ENUM target
4 CARD32 index
8 FLOAT64 params[0]
8 FLOAT64 params[1]
8 FLOAT64 params[2]
8 FLOAT64 params[3]

The ProgramStringARB is potentially large, and hence can be sent in
a glXRender or glXRenderLarge request.

ProgramStringARB
2 16+len+p rendering command length
2 4217 rendering command opcode
4 ENUM target
4 ENUM format
4 sizei len
len LISTofBYTE program
p unused, p=pad(len)

If the command is encoded in a glxRenderLarge request, the
command opcode and command length fields above are expanded to
4 bytes each:

4 16+len+p rendering command length
4 4217 rendering command opcode

The remaining commands are non-rendering commands. These commands
are sent separately (i.e., not as part of a glXRender or
glXRenderLarge request), using the glXVendorPrivateWithReply
request:

DeleteProgramsARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4+n request length
4 1294 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 n
n*4 LISTofCARD32 programs

GenProgramsARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4 request length
4 1295 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 n
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 n reply length
24 unused
n*4 LISTofCARD322 programs

GetProgramEnvParameterfvARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 6 request length
4 1296 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 CARD32 index
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m=(n==1?0:n)
4 unused
4 CARD32 n (number of parameter components)

if (n=1) this follows:

4 FLOAT32 params
12 unused

otherwise this follows:

16 unused
n*4 LISTofFLOAT32 params

GetProgramEnvParameterdvARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 6 request length
4 1297 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 CARD32 index
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m=(n==1?0:n*2)
4 unused
4 CARD32 n (number of parameter components)

if (n=1) this follows:

8 FLOAT64 params
8 unused

otherwise this follows:

16 unused
n*8 LISTofFLOAT64 params

GetProgramLocalParameterfvARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 6 request length
4 1305 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 CARD32 index
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m=(n==1?0:n)
4 unused
4 CARD32 n (number of parameter components)

if (n=1) this follows:

4 FLOAT32 params
12 unused

otherwise this follows:

16 unused
n*4 LISTofFLOAT32 params

GetProgramLocalParameterdvARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 6 request length
4 1306 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 CARD32 index
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m=(n==1?0:n*2)
4 unused
4 CARD32 n (number of parameter components)

if (n=1) this follows:

8 FLOAT64 params
8 unused

otherwise this follows:

16 unused
n*8 LISTofFLOAT64 params

GetProgramivARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 5 request length
4 1307 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 m reply length, m=(n==1?0:n)
4 unused
4 CARD32 n

if (n=1) this follows:

4 INT32 params
12 unused

otherwise this follows:

16 unused
n*4 LISTofINT32 params

GetProgramStringARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 5 request length
4 1308 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 ENUM target
4 ENUM pname
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 (n+p)/4 reply length
4 unused
4 CARD32 n
16 unused
n STRING program
p unused, p=pad(n)

IsProgramARB
1 CARD8 opcode (X assigned)
1 17 GLX opcode (glXVendorPrivateWithReply)
2 4 request length
4 1304 vendor specific opcode
4 GLX_CONTEXT_TAG context tag
4 INT32 n
=>
1 1 reply
1 unused
2 CARD16 sequence number
4 0 reply length
4 BOOL32 return value
20 unused


Errors


    The error INVALID_OPERATION is generated by ProgramStringARB if the
program string <string> is syntactically incorrect or violates any
semantic restriction of the execution environment of the specified
program target <target>. The error INVALID_OPERATION may also be
generated by ProgramStringARB if the specified program would exceed
native resource limits of the implementation.

The error INVALID_OPERATION is generated by BindProgramARB if
<program> is the name of a program whose target does not match
<target>.

The error INVALID_VALUE is generated by commands
ProgramEnvParameter{fd}ARB, ProgramEnvParameter{fd}vARB, and
GetProgramEnvParameter{fd}vARB if <index> is greater than or equal
to the value of MAX_PROGRAM_ENV_PARAMETERS_ARB corresponding to the
program target <target>.

The error INVALID_VALUE is generated by commands
ProgramLocalParameter4{fd}ARB, ProgramLocalParameter4{fd}vARB, and
GetProgramLocalParameter{fd}vARB if <index> is greater than or equal
to the value of MAX_PROGRAM_LOCAL_PARAMETERS_ARB corresponding to
the program target <target>.

The error INVALID_OPERATION is generated if Begin, RasterPos, or any
command that performs an explicit Begin is called when fragment
program mode is enabled and the currently bound fragment program
object does not contain a valid fragment program.

The error INVALID_OPERATION is generated by any command accessing
texture coordinate processing state if the texture unit number
corresponding to the current value of ACTIVE_TEXTURE is greater than
or equal to the implementation-dependent constant
MAX_TEXTURE_COORDS_ARB. Such commands include: GetTexGen{if}v;
TexGen{ifd}, TexGen{ifd}v; Disable, Enable, IsEnabled with argument
TEXTURE_GEN_{STRQ}; Get with argument CURRENT_TEXTURE_COORDS,
CURRENT_RASTER_TEXTURE_COORDS, TEXTURE_STACK_DEPTH, TEXTURE_MATRIX,
TRANSPOSE_TEXTURE_MATRIX; when the current matrix mode is TEXTURE,
Frustum, LoadIdentity, LoadMatrix{fd}, LoadTransposeMatrix{fd},
MultMatrix{fd}, MultTransposeMatrix{fd}, Ortho, PopMatrix,
PushMatrix, Rotate{fd}, Scale{fd}, Translate{fd}.

The error INVALID_OPERATION is generated by any command accessing
texture image processing state if the texture unit number
corresponding to the current value of ACTIVE_TEXTURE is greater than
or equal to the implementation-dependent constant
MAX_TEXTURE_IMAGE_UNITS_ARB. Such commands include: BindTexture;
GetCompressedTexImage, GetTexEnv{if}v, GetTexImage,
GetTexLevelParameter{if}v, GetTexParameter{if}v; TexEnv{if},
TexEnv{if}v, TexParameter{if}, TexParameter{if}v; Disable, Enable,
IsEnabled with argument TEXTURE_{123}D, TEXTURE_CUBE_MAP; Get with
argument TEXTURE_BINDING_{123}D, TEXTURE_BINDING_CUBE_MAP;
CompressedTexImage{123}D, CompressedTexSubImage{123}D,
CopyTexImage{12}D, CopyTexSubImage{123}D, TexImage{123}D,
TexSubImage{123}D.


New State



Get Value Type Get Command Initial Value Description Section Attribute
------------------------------- ------ ------------- ------------- ------------------ ------------ ------------
FRAGMENT_PROGRAM_ARB B IsEnabled False fragment program 3.8 enable
enable
- 24+xR4 GetProgramEnv- (0,0,0,0) program environment 3.11.1 -
ParameterARB parameters
PROGRAM_ERROR_POSITION_ARB Z GetIntegerv -1 last program error 3.11.1 -
position
PROGRAM_ERROR_STRING_ARB 0+xub GetString "" last program error 3.11.1 -
string

Table X.6. New Accessible State Introduced by ARB_fragment_program.


Get Value Type Get Command Initial Value Description Sec Attrib
-------------------- ----- ------------------- --------------- ---------------------- -------- ------
PROGRAM_BINDING_ARB Z+ GetProgramivARB object-specific bound program name 6.1.12 -
PROGRAM_LENGTH_ARB Z+ GetProgramivARB 0 bound program length 6.1.12 -
PROGRAM_FORMAT_ARB Z1 GetProgramivARB PROGRAM_FORMAT_ bound program format 6.1.12 -
ASCII_ARB
PROGRAM_STRING_ARB ubxn GetProgramStringARB (empty) bound program string 6.1.12 -
PROGRAM_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
total instructions
PROGRAM_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
ALU instructions
PROGRAM_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
texture instructions
PROGRAM_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
texture indirections
PROGRAM_TEMPORARIES_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
temporaries
PROGRAM_PARAMETERS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
parameter bindings
PROGRAM_ATTRIBS_ARB Z+ GetProgramivARB 0 bound program 6.1.12 -
attribute bindings
PROGRAM_NATIVE_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
instructions
PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
ALU instructions
PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
texture instructions
PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
texture indirections
PROGRAM_NATIVE_TEMPORARIES_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
temporaries
PROGRAM_NATIVE_PARAMETERS_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
parameter bindings
PROGRAM_NATIVE_ATTRIBS_ARB Z+ GetProgramivARB 0 bound program native 6.1.12 -
attribute bindings
PROGRAM_UNDER_NATIVE_LIMITS_ARB B GetProgramivARB 0 bound program under 6.1.12 -
native resource limits
- 24+xR4 GetProgramLocal- (0,0,0,0) bound program local 3.11.1 -
ParameterARB parameter value

Table X.7. Program Object State. Program object queries return attributes of
the program object currently bound to the program target <target>.


Get Value Type Get Command Initial Value Description Sec Attribute
--------- ------ ----------- ------------- ------------------------- -------- ---------
- 16+xR4 - undefined temporary registers 3.11.3.3 -
- 2xR4 - undefined fragment result registers 3.11.3.4 -

Table X.8. Fragment Program Per-fragment Execution State. All per-fragment
execution state registers are uninitialized at the beginning of program
execution.


Get Value Type Get Command Initial Value Description Sec Attribute
------------------------------ -------- -------------- ------------- ------------------- ------- ---------
CURRENT_MATRIX_ARB m*n*xM^4 GetFloatv Identity current matrix 6.1.2 -
CURRENT_MATRIX_STACK_DEPTH_ARB m*Z+ GetIntegerv 1 current stack depth 6.1.2 -

Table X.9. Current matrix state where m is the total number of matrices
including texture matrices and program matrices and n is the number of
matrices on each particular matrix stack. Note that this state is aliased
with existing matrix state.


New Implementation Dependent State
Minimum
Get Value Type Get Command Value Description Sec. Attrib
--------- ---- ----------- ------- ----------- ---- ------
MAX_TEXTURE_COORDS_ARB Z+ GetIntegerv 2 number of texture 2.7 -
coordinate sets
MAX_TEXTURE_IMAGE_UNITS_ARB Z+ GetIntegerv 2 number of texture 2.10.2 -
image units
MAX_PROGRAM_ENV_PARAMETERS_ARB Z+ GetProgramivARB 24 maximum program 3.11.1 -
env parameters
MAX_PROGRAM_LOCAL_PARAMETERS_ARB Z+ GetProgramivARB 24 maximum program 3.11.1 -
local parameters
MAX_PROGRAM_MATRICES_ARB Z+ GetIntegerv 8 (not to maximum number of 3.11.7 -
exceed 32) program matrices
MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB Z+ GetIntegerv 1 maximum program 3.11.7 -
matrix stack depth
MAX_PROGRAM_INSTRUCTIONS_ARB Z+ GetProgramivARB 72 maximum program 6.1.12 -
total instructions
MAX_PROGRAM_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB 48 number of frag. prg. 6.1.12 -
ALU instructions
MAX_PROGRAM_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB 24 number of frag. prg. 6.1.12 -
texture instructions
MAX_PROGRAM_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB 4 number of frag. prg. 6.1.12 -
texture indirections
MAX_PROGRAM_TEMPORARIES_ARB Z+ GetProgramivARB 16 maximum program 6.1.12 -
temporaries
MAX_PROGRAM_PARAMETERS_ARB Z+ GetProgramivARB 24 maximum program 6.1.12 -
parameter bindings
MAX_PROGRAM_ATTRIBS_ARB Z+ GetProgramivARB 10 maximum program 6.1.12 -
attribute bindings
MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
total instructions
MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
ALU instructions
MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
texture instructions
MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
texture indirections
MAX_PROGRAM_NATIVE_TEMPORARIES_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
temporaries
MAX_PROGRAM_NATIVE_PARAMETERS_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
parameter bindings
MAX_PROGRAM_NATIVE_ATTRIBS_ARB Z+ GetProgramivARB - maximum program native 6.1.12 -
attribute bindings

Table X.10. New Implementation-Dependent Values Introduced by
ARB_fragment_program. Values queried by GetProgram require a <pname> of
FRAGMENT_PROGRAM_ARB.


Sample Usage


    The following program shows how to perform a simple modulation 
between the interpolated color and a single texture:

!!ARBfp1.0
# Simple program to show how to code up the default texture environment

ATTRIB tex = fragment.texcoord; #first set of texture coordinates
ATTRIB col = fragment.color.primary; #diffuse interpolated color

OUTPUT outColor = result.color;

TEMP tmp;

TXP tmp, tex, texture, 2D; #sample the texture

MUL outColor, tmp, col; #perform the modulation

END

The following is an example the simulates a chrome surface:

!!ARBfp1.0

########################
# Input Textures:
#-----------------------
# Texture 0 contains the default 2D texture used for general mapping
# Texture 2 contains a 1D pointlight falloff map
# Texture 3 contains a 2D map for calculating specular lighting
# Texture 4 contains normalizer cube map
#
# Input Texture Coordinates:
#-----------------------
# TexCoord1 contains the calculated normal
# TexCoord2 contains the light to vertex vector
# TexCoord3 contains the half-vector in tangent space
# TexCoord4 contains the light vector in tangent space
# TexCoord5 contains the eye vector in tangent space
########################

TEMP NdotH, lV, L;

ALIAS diffuse = L;
PARAM half = { 0.5, 0.5, 0.5, 0.5 };
ATTRIB norm_tc = fragment.texcoord[1];
ATTRIB lv_tc = fragment.texcoord[2];
ATTRIB half_tc = fragment.texcoord[3];
ATTRIB light_tc = fragment.texcoord[4];
ATTRIB eye_tc = fragment.texcoord[5];
OUTPUT oCol = result.color;

TEX L, light_tc, texture[4], CUBE; # Sample cube map normalizer

# Calculate diffuse lighting (N.L)
SUB L, L, half; # Bias L and then multiply by 2
ADD L, L, L;
DP3 diffuse, norm_tc, L; # N.L

# Calculate specular lighting component { (N.H), |H|^2 }
DP3 NdotH.x, norm_tc, half_tc;
DP3 NdotH.y, half_tc, half_tc;

DP3 lV.x, lv_tc, lv_tc; # lV = (|light to vertex|)^2


#############
# Pass 2
#############

TEMP base, specular;
ALIAS atten = lV;

TEX base, eye_tc, texture[0], 2D; # sample enviroment map using eye vector
TEX atten, lV, texture[2], 1D; # Sample attenuation map
TEX specular, NdotH, texture[3], 2D; # Sample specular NHHH map= (N.H)^256

# specular = (N.H)^256 * (N.L)
# this ensures a pixel is only lit if facing the light (since the specular
# exponent makes negative N.H positive we must do this)
MUL specular, specular, diffuse;

# specular = specular * environment map
MUL specular, base, specular;

# diffuse = diffuse * environment map
MUL diffuse, base, diffuse;

# outColor = (specular * environment map) + (diffuse * environment map)
ADD base, specular, diffuse;

# Apply point light attenutaion
MUL oCol, base, atten.r;

END


Revision History


   Date: 8/22/2003
Revision: 26
- Added list of commands generating errors when active texture
unit selector is out of range.
- Fixed typo in <stateMatrixItem> rule.
- Clarified behavior of fragment.position.z with respect to depth
offset.

Date: 2/26/2003
Revision: 25
- Fixed description of KIL instruction to reflect less than zero
test, not less than or equal to zero.
- Clarified the processing of incoming and outgoing depths and
colors to reflect the conversion to floating-point on input and
the conversion to fixed-point on output.

Date: 1/10/2003
Revision: 24
- Fixed bug where "state.matrix.mvp" was specified incorrectly.
It should be P*M0 rather than M0*P.
- Added issue warning about CMP opcode's order of operands.

Date: 10/22/2002
Revision: 23
- Fixed reference to <extSwizComp> rule in 3.11.5.28. Instead
reference both <xyzwExtSwizComp> and <rgbaExtSwizComp> rules.

Date: 10/02/2002
Revision: 22
- Fixed typo in section 3.11.1, where 8 program environment and
8 program local parameters are listed as the minimums instead
of 24 of each. Table X.10 had the correct values.
- Fixed <stateTexEnvItem> to refer to legacy texture units.
- Fixed typos in issue 29 pseudo-code, added some clarification.

Date: 9/19/2002
Revision: 21
- Added clarifying paragraph for native texture indirection
counting, offering examples of possible cases where texture
indirections may be increased.
- Fixed typos in issues 25 and 29.

Date: 9/16/2002
Revision: 20
- Added precision hint program options.
- Fixed various typos, reworded some parts for consistency.
- Updated issues list.

Date: 9/13/2002
Revision: 19
- Promoted minimum precision of texture coordinates in 2.1.1.
- Added ARB_fog_* program options.
- Removed modification to 3.9, put clamps in 3.11.4.4.
- Made 'texture' a reserved keyword in the grammar.
- Fixed various typos.
- Updated section 3.11.6.
- Updated issues list.

Date: 9/11/2002
Revision: 18
- Updated for consistency with ARB_vertex_program revision 36.
- Depth output moved to 3rd component of result.depth.
- Fixed various typos, reworded things in many places.
- Added NV_fragment_program interactions.
- Updated issues list.

Date: 9/09/2002
Revision: 17
- Added fogcoord and position attributes.
- Moved fragment program section to 3.11, after fog.
- Changed MAX_TEXTURE_UNITS/MAX_AUX_TEXTURE_UNITS to
MAX_TEXTURE_COORDS/MAX_TEXTURE_IMAGE_UNITS.
- Removed TRC and MOD instructions.
- Added SIN and COS instructions.
- Added more clarity to resource consumption wording.
- Added invariance wording concerning depth-replacement.
- Added rule that a program that fails to load must always fail to
load, regardless of GL state.
- Updated issues list.

Date: 8/30/2002
Revision: 16
- Improved texture indirection description.
- Defined result of sample from incomplete texture as (0,0,0,1).
- Removed PROGRAMS_LOAD_OVER_NATIVE_LIMITS_ARB per-target query.
- Allowed ProgramStringARB to fail on non-native programs.
- Updated issues list.

Date: 8/28/2002
Revision: 15
- Updated for consistency with ARB_vertex_program revision 35.
- Added PROGRAMS_LOAD_OVER_NATIVE_LIMITS_ARB per-target query.
- Changed MAX_AUX_TEXTURE_UNITS_ARB enum value.
- Updated issues list.

Date: 8/22/2002
Revision: 14
- Added sine/cosine instruction (SCS).
- Updated texture sample grammar, replaced texenables hierarchy.
- Added EXT_vertex_weighting and ARB_vertex_blend dependency.
- Updated issues list.

Date: 8/14/2002
Revision: 13
- Fixed <paramConstant> grammar rule.
- Updated issues list.

Date: 8/06/2002
Revision: 12
- Fixed various typos.
- Updated issues list.
- Added wording to 3.10.3.6 to reflect that native resource
consumption may increase due to emulated instructions.

Date: 7/29/2002
Revision: 11
- Updated for consistency with ARB_vertex_program revision 34.
- Added support for matrix binding.
- Removed precision queries.
- Updated issues list.

Date: 7/16/2002
Revision: 10
- Updated for consistency with ARB_vertex_program revision 31.
- Added fog params and depth range bindings to grammar.
- Removed stpq writemasks and swizzles from grammar.
- Required swizzle components to come from same set, xyzw or rgba.

Date: 7/10/2002
Revision: 9
- Made fog params and depth range bindable.
- Changed texture instruction names to match 3-letter format.
- Made texture instructions more consistent with ALU instructions.
- Increased minimums for implementation-dependent values.
- Re-introduced 4-components swizzles and the SWZ instruction.
- Updated issues list.

Date: 7/03/2002
Revision: 8
- Fixed typos.
- Added DST, LIT, SGE, SLT instructions.
- Changed FRC definition to match ARB_vertex_program, added MOD
instruction to expose fmod(arg, 1.0) behavior.

Date: 6/25/2002
Revision: 7
- Updated for consistency with ARB_vertex_program revision 29.

Date: 6/19/2002
Revision: 6
- Updated for consistency with ARB_vertex_program revision 28.
- Changed from ATI to ARB prefix/suffix.
- Started using single integer revision number.
- Added a few more issues to the list.

Date: 6/14/2002
Revision: 1.4
- Updated for consistency with ARB_vertex_program revision 27.
- Added a few more issues to the list.

Date: 6/05/2002
Revision: 1.3
- Updated for consistency with ARB_vertex_program revision 26.
- Incorporated program object management, removing dependency on
ARB_vertex_program.
- Added interaction with ARB_shadow.

Date: 6/03/2002
Revision: 1.2
- Updated for consistency with ARB_vertex_program revision 25.
- Fixed TexInstructions to use <texSrcReg>, i.e. no parameters.
- Added TRC, POW, DPH instructions, updated FRC and LRP.
- Added fog color parameter binding.

Date: 5/23/2002
Revision: 1.1
- Updated for consistency with ARB_vertex_program revision 24.
- Added GetProgramfvATI entrypoint for querying precision values.

Date: 5/10/2002
Revision: 1.0
- First draft for circulation.

Implementation Support


   List of OpenGL implementations supporting the GL_ARB_fragment_program extension

Original File


   Original text file for the GL_ARB_fragment_program extension


Page generated on Sun Nov 20 18:36:34 2005