blob: 268534a75906171cdb8b2f9fb8117724cfe8c46e [file] [log] [blame]
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, AMD (benj.lipchak 'at' amd.com)
Notice
Copyright (c) 2002-2013 The Khronos Group Inc. Copyright terms at
http://www.khronos.org/registry/speccopyright.html
Specification Update Policy
Khronos-approved extension specifications are updated in response to
issues and bugs prioritized by the Khronos OpenGL Working Group. For
extensions which have been promoted to a core Specification, fixes will
first appear in the latest version of that core Specification, and will
eventually be backported to the extension document. This policy is
described in more detail at
https://www.khronos.org/registry/OpenGL/docs/update_policy.php
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: October 8, 2013
Revision: 28
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 void *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