skia / external / github.com / KhronosGroup / OpenGL-Registry / 108-cleanup-xml / . / extensions / NV / NV_vertex_program.txt

Name | |

NV_vertex_program | |

Name Strings | |

GL_NV_vertex_program | |

Contact | |

Mark J. Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com) | |

Notice | |

Copyright NVIDIA Corporation, 2000, 2001, 2002, 2003, 2004. | |

IP Status | |

NVIDIA Proprietary. | |

Status | |

Shipping, spec at version 1.10. | |

Version | |

NVIDIA Date: March 31, 2009 | |

Revision: 1.10 | |

Number | |

233 | |

Dependencies | |

Written based on the wording of the OpenGL 1.2.1 specification and | |

requires OpenGL 1.2.1. | |

Requires support for the ARB_multitexture extension with at least | |

two texture units. | |

EXT_point_parameters affects the definition of this extension. | |

EXT_secondary_color affects the definition of this extension. | |

EXT_fog_coord affects the definition of this extension. | |

EXT_vertex_weighting affects the definition of this extension. | |

ARB_imaging affects the definition of this extension. | |

Overview | |

Unextended OpenGL mandates a certain set of configurable per-vertex | |

computations defining vertex transformation, texture coordinate | |

generation and transformation, and lighting. Several extensions | |

have added further per-vertex computations to OpenGL. For example, | |

extensions have defined new texture coordinate generation modes | |

(ARB_texture_cube_map, NV_texgen_reflection, NV_texgen_emboss), new | |

vertex transformation modes (EXT_vertex_weighting), new lighting modes | |

(OpenGL 1.2's separate specular and rescale normal functionality), | |

several modes for fog distance generation (NV_fog_distance), and | |

eye-distance point size attenuation (EXT_point_parameters). | |

Each such extension adds a small set of relatively inflexible | |

per-vertex computations. | |

This inflexibility is in contrast to the typical flexibility provided | |

by the underlying programmable floating point engines (whether | |

micro-coded vertex engines, DSPs, or CPUs) that are traditionally used | |

to implement OpenGL's per-vertex computations. The purpose of this | |

extension is to expose to the OpenGL application writer a significant | |

degree of per-vertex programmability for computing vertex parameters. | |

For the purposes of discussing this extension, a vertex program is | |

a sequence of floating-point 4-component vector operations that | |

determines how a set of program parameters (defined outside of | |

OpenGL's begin/end pair) and an input set of per-vertex parameters | |

are transformed to a set of per-vertex output parameters. | |

The per-vertex computations for standard OpenGL given a particular | |

set of lighting and texture coordinate generation modes (along with | |

any state for extensions defining per-vertex computations) is, in | |

essence, a vertex 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 vertex | |

program instruction sequences for application-defined vertex programs. | |

In order to define such vertex programs, this extension defines | |

a vertex 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 vertex programming model is designed for efficient | |

hardware implementation and to support a wide variety of vertex | |

programs. By design, the entire set of existing vertex programs | |

defined by existing OpenGL per-vertex computation extensions can be | |

implemented using the extension's vertex programming model. | |

Issues | |

What should this extension be called? | |

RESOLUTION: NV_vertex_program. DirectX 8 refers to its similar | |

functionality as "vertex shaders". This is a confusing term | |

because shaders are usually assumed to operate at the fragment or | |

pixel level, not the vertex level. | |

Conceptually, what the extension defines is an application-defined | |

program (admittedly limited by its sequential execution model) for | |

processing vertices so the "vertex program" term is more accurate. | |

Additionally, some of the API machinery in this extension for | |

describing programs could be useful for extending other OpenGL | |

operations with programs (though other types of programs would | |

likely look very different from vertex programs). | |

What terms are important to this specification? | |

vertex program mode - when vertex program mode is enabled, vertices | |

are transformed by an application-defined vertex program. | |

conventional GL vertex transform mode - when vertex program mode | |

is disabled (or the extension is not supported), vertices are | |

transformed by GL's conventional texgen, lighting, and transform | |

state. | |

provoke - the verb that denotes the beginning of vertex | |

transformation by either vertex program mode or conventional GL | |

vertex transform mode. Vertices are provoked when either glVertex | |

or glVertexAttribNV(0, ...) is called. | |

program target - a type or class of program. This extension | |

supports two program targets: the vertex program and the vertex | |

state program. Future extensions could add other program targets. | |

vertex program - an application-defined vertex program used to | |

transform vertices when vertex program mode is enabled. | |

vertex state program - a program similar to a vertex program. | |

Unlike a vertex program, a vertex state program runs outside of | |

a glBegin/glEnd pair. Vertex state programs do not transform | |

a vertex. They just update program parameters. | |

vertex attribute - one of 16 4-component per-vertex parameters | |

defined by this extension. These attributes alias with the | |

conventional per-vertex parameters. | |

per-vertex parameter - a vertex attribute or a conventional | |

per-vertex parameter such as set by glNormal3f or glColor3f. | |

program parameter - one of 96 4-component registers available | |

to vertex programs. The state of these registers is shared | |

among all vertex programs. | |

What part of OpenGL do vertex programs specifically bypass? | |

Vertex programs bypass the following OpenGL functionality: | |

o Normal transformation and normalization | |

o Color material | |

o Per-vertex lighting | |

o Texture coordinate generation | |

o The texture matrix | |

o The normalization of AUTO_NORMAL evaluated normals | |

o The modelview and projection matrix transforms | |

o The per-vertex processing in EXT_point_parameters | |

o The per-vertex processing in NV_fog_distance | |

o Raster position transformation | |

o Client-defined clip planes | |

Operations not subsumed by vertex programs | |

o The view frustum clip | |

o Perspective divide (division by w) | |

o The viewport transformation | |

o The depth range transformation | |

o Clamping the primary and secondary color to [0,1] | |

o Primitive assembly and subsequent operations | |

o Evaluator (except the AUTO_NORMAL normalization) | |

How specific should this specification be about precision? | |

RESOLUTION: Reasonable precision requirements are incorporated | |

into the specification beyond the often vague requirements of the | |

core OpenGL specification. | |

This extension essentially defines an instruction set and its | |

corresponding execution environment. The instruction set specified | |

may find applications beyond the traditional purposes of 3D vertex | |

transformation, lighting, and texture coordinate generation that | |

have fairly lax precision requirements. To facilitate such | |

possibly unexpected applications of this functionality, minimum | |

precision requirements are specified. | |

The minimum precision requirements in the specification are meant | |

to serve as a baseline so that application developers can write | |

vertex programs with minimal worries about precision issues. | |

What about when the "execution environment" involves support for | |

other extensions? | |

This extension assumes support for functionality that includes | |

a fog distance, secondary color, point parameters, and multiple | |

texture coordinates. | |

There is a trade-off between requiring support for these extensions | |

to guarantee a particular extended execution environment and | |

requiring lots of functionality that everyone might not support. | |

Application developers will desire a high baseline of functionality | |

so that OpenGL applications using vertex programs can work in | |

the full context of OpenGL. But if too much is required, the | |

implementation burden mandated by the extension may limit the | |

number of available implementations. | |

Clearly we do not want to require support for 8 texture units | |

even if the machinery is there for it. Still multitexture is a | |

common and important feature for using vertex programs effectively. | |

Requiring at least two texture units seems reasonable. | |

What do we say about the alpha component of the secondary color? | |

RESOLUTION: When vertex program mode is enabled, the alpha | |

component of csec used for the color sum state is assumed always | |

zero. Another downstream extension may actually make the alpha | |

component written into the COL1 (or BFC1) vertex result register | |

available. | |

Should client-defined clip planes operate when vertex program mode is | |

enabled? | |

RESOLUTION. No. | |

OpenGL's client-defined clip planes are specified in eye-space. | |

Vertex programs generate homogeneous clip space positions. | |

Unlike the conventional OpenGL vertex transformation mode, vertex | |

program mode requires no semantic equivalent to eye-space. | |

Applications that require client-defined clip planes can simulate | |

OpenGL-style client-defined clip planes by generating texture | |

coordinates and using alpha testing or other per-fragment tests | |

such as NV_texture_shader's CULL_FRAGMENT_NV program to discard | |

fragments. In many ways, these schemes provide a more flexible | |

mechanism for clipping than client-defined clip planes. | |

Unfortunately, vertex programs used in conjunction with selection | |

or feedback will not have a means to support client-defined clip | |

planes because the per-fragment culling mechanisms described in the | |

previous paragraph are not available in the selection or feedback | |

render modes. Oh well. | |

Finally, as a practical concern, client-defined clip planes | |

greatly complicate clipping for various hardware rasterization | |

architectures. | |

How are edge flags handled? | |

RESOLUTION: Passed through without the ability to be modified by | |

a vertex program. Applications are free to send edge flags when | |

vertex program mode is enabled. | |

Should vertex attributes alias with conventional per-vertex | |

parameters? | |

RESOLUTION. YES. | |

This aliasing should make it easy to use vertex programs with | |

existing OpenGL code that transfers per-vertex parameters using | |

conventional OpenGL per-vertex calls. | |

It also minimizes the number of per-vertex parameters that the | |

hardware must maintain. | |

See Table X.2 for the aliasing of vertex attributes and conventional | |

per-vertex parameters. | |

How should vertex attribute arrays interact with conventional vertex | |

arrays? | |

RESOLUTION: When vertex program mode is enabled, a particular | |

vertex attribute array will be used if enabled, but if disabled, | |

and the corresponding aliased conventional vertex array is enabled | |

(assuming that there is a corresponding aliased conventional vertex | |

array for the particular vertex array), the conventional vertex | |

array will be used. | |

This matches the way immediate mode per-vertex parameter aliasing | |

works. | |

This does slightly complicate vertex array validation in program | |

mode, but programmers using vertex arrays can simply enable vertex | |

program mode without reconfiguring their conventional vertex arrays | |

and get what they expect. | |

Note that this does create an asymmetry between immediate mode | |

and vertex arrays depending on whether vertex program mode is | |

enabled or not. The immediate mode vertex attribute commands | |

operate unchanged whether vertex program mode is enabled or not. | |

However the vertex attribute vertex arrays are used only when | |

vertex program mode is enabled. | |

Supporting vertex attribute vertex arrays when vertex program mode | |

is disabled would create a large implementation burden for existing | |

OpenGL implementations that have heavily optimized conventional | |

vertex arrays. For example, the normal array can be assumed to | |

always contain 3 and only 3 components in conventional OpenGL | |

vertex transform mode, but may contain 1, 2, 3, or 4 components | |

in vertex program mode. | |

There is not any additional functionality gained by supporting | |

vertex attribute arrays when vertex program mode is disabled, but | |

there is lots of implementation overhead. In any case, it does not | |

seem something worth encouraging so it is simply not supported. | |

So vertex attribute arrays are IGNORED when vertex program mode | |

is not enabled. | |

Ignoring VertexAttribute commands or treating VertexAttribute | |

commands as an error when vertex program mode is enabled | |

would likely add overhead for such a conditional check. The | |

implementation overhead for supporting VertexAttribute commands | |

when vertex program mode is disabled is not that significant. | |

Additionally, it is likely that setting persistent vertex attribute | |

state while vertex program mode is disabled may be useful to | |

applications. So vertex attribute immediate mode commands are | |

PERMITTED when vertex program mode is not enabled. | |

Colors and normals specified as ints, uints, shorts, ushorts, bytes, | |

and ubytes are converted to floating-point ranges when supplied to | |

core OpenGL as described in Table 2.6. Other per-vertex attributes | |

such as texture coordinates and positions are not converted. | |

How does this mix with vertex programs where all vertex attributes | |

are supposedly treated identically? | |

RESOLUTION: Vertex attributes specified as bytes and ubytes are | |

always converted as described in Table 2.6. All other formats are | |

not converted according to Table 2.6 but simply converted directly | |

to floating-point. | |

The ubyte type is converted because those types seem more useful | |

for passing colors in the [0,1] range. | |

If an application desires a conversion, the conversion can be | |

incorporated into the vertex program itself. | |

This also applies to vertex attribute arrays. However, by enabling | |

a color or normal vertex array and not enabling the corresponding | |

aliased vertex attribute array, programmers can get the conventional | |

conversions for color and normal arrays (but only for the vertex | |

attribute arrays that alias to the conventional color and normal | |

arrays and only with the sizes/types supported by these color and | |

normal arrays). | |

Should programs be C-style null-terminated strings? | |

RESOLUTION: No. Programs should be specified as an array of | |

GLubyte with an explicit length parameter. OpenGL has no precedent | |

for passing null-terminated strings into the API (though glGetString | |

returns null-terminated strings). Null-terminated strings are | |

problematic for some languages. | |

Should all existing OpenGL transform functionality and extensions | |

be implementable as vertex programs? | |

RESOLUTION: Yes. Vertex programs should be a complete superset | |

of what you can do with OpenGL 1.2 and existing vertex transform | |

extensions. | |

To implement EXT_point_parameters, the | |

GL_VERTEX_PROGRAM_POINT_SIZE_NV enable is introduced. | |

To implement two-sided lighting, the GL_VERTEX_PROGRAM_TWO_SIDE_NV | |

enable is introduced. | |

How does glPointSize work with vertex programs? | |

RESOLUTION: If GL_VERTEX_PROGRAM_POINT_SIZE_NV is disabled, the size | |

of points is determine by the glPointSize state. If enabled, | |

the point size is determined per-vertex by the clamped value of | |

the vertex result PSIZ register. | |

Can the currently bound vertex program object name be deleted or | |

reloaded? | |

RESOLUTION. Yes. When a vertex program object name is deleted | |

or reloaded when it is the currently bound vertex program object, | |

it is as if a rebind occurs after the deletion or reload. | |

In the case of a reload, the new vertex program object will be | |

used from then on. In the case of a deletion, the current vertex | |

program object will be treated as if it is nonexistent. | |

Should program objects have a mechanism for managing program | |

residency? | |

RESOLUTION: Yes. Vertex program instruction memory is a limited | |

hardware resource. glBindProgramNV will be faster if binding to | |

a resident program. Applications are likely to want to quickly | |

switch between a small collection of programs. | |

glAreProgramsResidentNV allows the residency status of a | |

group of programs to be queried. This mimics | |

glAreTexturesResident. | |

Instead of adopting the glPrioritizeTextures mechanism, a new | |

glRequestResidentProgramsNV command is specified instead. | |

Assigning priorities to textures has always been a problematic | |

endeavor and few OpenGL implementations implemented it effectively. | |

For the priority mechanism to work well, it requires the client | |

to routinely update the priorities of textures. | |

The glRequestResidentProgramsNV indicates to the GL that a | |

set of programs are intended for use together. Because all | |

the programs are requesting residency as a group, drivers | |

should be able to attempt to load all the requested programs | |

at once (and remove from residency programs not in the group if | |

necessary). Clients can use glAreProgramsResidentNV to query the | |

relative success of the request. | |

glRequestResidentProgramsNV should be superior to loading programs | |

on-demand because fragmentation can be avoided. | |

What happens when you execute a nonexistent or invalid program? | |

RESOLUTION: glBegin will fail with a GL_INVALID_OPERATION if the | |

currently bound vertex program is nonexistent or invalid. The same | |

applies to glRasterPos and any command that implies a glBegin. | |

Because the glVertex and glVertexAttribNV(0, ...) are ignored | |

outside of a glBegin/glEnd pair (without generating an error) it | |

is impossible to provoke a vertex program if the current vertex | |

program is nonexistent or invalid. Other per-vertex parameters | |

(for examples those set by glColor, glNormal, and glVertexAttribNV | |

when the attribute number is not zero) are recorded since they | |

are legal outside of a glBegin/glEnd. | |

For vertex state programs, the problem is simpler because | |

glExecuteProgramNV can immediately fail with a GL_INVALID_OPERATION | |

when the named vertex state program is nonexistent or invalid. | |

What happens when a matrix has been tracked into a set of program | |

parameters, but then glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, addr, | |

GL_NONE, GL_IDENTITY_NV) is performed? | |

RESOLUTION: The specified program parameters stop tracking a | |

matrix, but they retain the values of the matrix they were last | |

tracking. | |

Can rows of tracked matrices be queried by querying the program | |

parameters that track them? | |

RESOLUTION: Yes. | |

Discussing matrices is confusing because of row-major versus | |

column-major issues. Can you give an example of how a matrix is | |

tracked? | |

// When loaded, the first row is "1, 2, 3, 4", because of column-major | |

// (OpenGL spec) vs. row-major (C) differences. | |

GLfloat matrix[16] = { 1, 5, 9, 13, | |

2, 6, 10, 14, | |

3, 7, 11, 15, | |

4, 8, 12, 16 }; | |

GLfloat row1[4], row2[4]; | |

glMatrixMode(GL_MATRIX0_NV); | |

glLoadMatrixf(matrix); | |

glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 4, GL_MATRIX0_NV, GL_IDENTITY_NV); | |

glTrackMatrixNV(GL_VERTEX_PROGRAM_NV, 8, GL_MATRIX0_NV, GL_TRANSPOSE_NV); | |

glGetProgramParameterfvNV(GL_VERTEX_PROGRAM_NV, 5, | |

GL_PROGRAM_PARAMETER_NV, row1); | |

/* row1 is now [ 5 6 7 8 ] */ | |

glGetProgramParameterfvNV(GL_VERTEX_PROGRAM_NV, 9, | |

GL_PROGRAM_PARAMETER_NV, row2); | |

/* row2 is now [ 2 6 10 14 ] because the tracked matrix is transposed */ | |

Should evaluators be extended to evaluate arbitrary vertex | |

attributes? | |

RESOLUTION: Yes. We'll support 32 new maps (16 for MAP1 and 16 | |

for MAP2) that take priority over the conventional maps that they | |

might alias to (only when vertex program mode is enabled). | |

These new maps always evaluate all four components. The rationale | |

for this is that if we supported 1, 2, 3, or 4 components, that | |

would add 128 (16*4*2) enumerants which is too many. In addition, | |

if you wanted to evaluate two 2-component vertex attributes, you | |

could instead generate one 4-component vertex attribute and use | |

the vertex program with swizzling to treat this as two-components. | |

Moreover, we are assuming 4-component vector instructions so less | |

than 4-component evaluations might not be any more efficient | |

than 4-component evaluations. Implementations that use vector | |

instructions such as Intel's SSE instructions will be easier to | |

implement since they can focus on optimizing just the 4-component | |

case. | |

How should GL_AUTO_NORMAL work with vertex programs? | |

RESOLUTION: GL_AUTO_NORMAL should NOT guarantee that the generated | |

analytical normal be normalized. In vertex program mode, the | |

current vertex program can easily normalize the normal if required. | |

This can lead to greater efficiency if the vertex program transforms | |

the normal to another coordinate system such as eye-space with a | |

transform that preserves vector length. Then a single normalize | |

after transform is more efficient than normalizing after evaluation | |

and also normalizing after transform. | |

Conceptually, the normalize mandated for AUTO_NORMAL in section | |

5.1 is just one of the many transformation operations subsumed by | |

vertex programs. | |

Should the new vertex program related enables push/pop with | |

GL_ENABLE_BIT? | |

RESOLUTION: Yes. Pushing and popping enable bits is easy. | |

This includes the 32 new evaluator map enable bits. These evaluator | |

enable bits are also pushed and popped using GL_EVAL_BIT. | |

Should all the vertex attribute state push/pop with GL_CURRENT_BIT? | |

RESOLUTION: Yes. The state is aliased with the conventional | |

per-vertex parameter state so it really should push/pop. | |

Should all the vertex attrib vertex array state push/pop with | |

GL_CLIENT_VERTEX_ARRAY_BIT? | |

RESOLUTION: Yes. | |

Should all the other vertex program-related state push/pop somehow? | |

RESOLUTION: No. | |

The other vertex program doesn't fit well with the existing bits. | |

To be clear, GL_ALL_ATTRIB_BITS does not push/pop vertex program | |

state other than enables. | |

Should we generate a GL_INVALID_OPERATION operation if updating | |

a vertex attribute greater than 15? | |

RESOLUTION: Yes. | |

The other option would be to mask or modulo the vertex attribute | |

index with 16. This is cheap, but it would make it difficult to | |

increase the number of vertex attributes in the future. | |

If we check for the error, it should be a well predicted branch | |

for immediate mode calls. For vertex arrays, the check is only | |

required at vertex array specification time. | |

Hopefully this will encourage people to use vertex arrays over | |

immediate mode. | |

Should writes to program parameter registers during a vertex program | |

be supported? | |

RESOLUTION. No. | |

Writes to program parameter registers from within a vertex program | |

would require the execution of vertex programs to be serialized | |

with respect to each other. This would create an unwarranted | |

implementation penalty for parallel vertex program execution | |

implementations. | |

However vertex state programs may write to program parameter | |

registers (that is the whole point of vertex state programs). | |

Should we support variously sized immediate mode byte and ubyte | |

commands? How about for vertex arrays? | |

RESOLUTION. Only support the 4ub mode. | |

There are simply too many glVertexAttribNV routines. Passing less | |

than 4 bytes at a time is inefficient. We expect the main use | |

for bytes to be for colors where these will be unsigned bytes. | |

So let's just support 4ub mode for bytes. This applies to | |

vertex arrays too. | |

Should we support integer, unsigned integer, and unsigned short | |

formats for vertex attributes? | |

RESOLUTION: No. It's just too many immediate mode entry points, | |

most of which are not that useful. Signed shorts are supported | |

however. We expect signed shorts to be useful for passing compact | |

texture coordinates. | |

Should we support doubles for vertex attributes? | |

RESOLUTION: Yes. Some implementation of the extension might | |

support double precision. Lots of math routines output double | |

precision. | |

Should there be a way to determine where in a loaded program | |

string the first parse error occurs? | |

RESOLUTION: Yes. You can query PROGRAM_ERROR_POSITION_NV. | |

Should program objects be shared among rendering contexts in the | |

same manner as display lists and texture objects? | |

RESOLUTION: Yes. | |

How should this extension interact with color material? | |

RESOLUTION: It should not. Color material is a conventional | |

OpenGL vertex transform mode. It does not have a place for vertex | |

programs. If you want to emulate color material with vertex | |

programs, you would simply write a program where the material | |

parameters feed from the color vertex attribute. | |

Should there be a glMatrixMode or glActiveTextureARB style selector | |

for vertex attributes? | |

RESOLUTION: No. While this would let us reduce a lot of | |

enumerants down, it would make programming a hassle in lots | |

of cases. Consider having to change the vertex attribute | |

mode to enable a set of vertex arrays. | |

How should gets for vertex attribute array pointers? | |

RESOLUTION: Add new get commands. Using the existing calls | |

would require adding 4 sets of 16 enumerants stride, type, size, | |

and pointer. That's too many gets. | |

Instead add glGetVertexAttribNV and glGetVertexAttribPointervNV. | |

glGetVertexAttribNV is also useful for querying the current vertex | |

attribute. | |

glGet and glGetPointerv will not return vertex attribute array | |

pointers. | |

Why is the address register numbered and why is it a vector | |

register? | |

In the future, A0.y and A0.z and A0.w may exist. For this | |

extension, only A0.x is useful. Also in the future, there may be | |

more than one address register. | |

There's a nice consistency in thinking about all the registers | |

as 4-component vectors even if the address register has only one | |

usable component. | |

Should vertex programs and vertex state programs be required to | |

have a header token and an end token? | |

RESOLUTION: Yes. | |

The "!!VP1.0" and "!!VSP1.0" tokens start vertex programs and | |

vertex state programs respectively. Both types of programs must | |

end with the "END" token. | |

The initial header token reminds the programmer what type of program | |

they are writing. If vertex programs and vertex state programs are | |

ever read from disk files, the header token can serve as a magic | |

number for identifying vertex programs and vertex state programs. | |

The target type for vertex programs and vertex state programs can be | |

distinguished based on their respective grammars independent of the | |

initial header tokens, but the initial header tokens will make it | |

easier for programmers to distinguish the two program target types. | |

We expect programs to often be generated by concatenation of | |

program fragments. The "END" token will hopefully reduce bugs | |

due to specifying an incorrectly concatenated program. | |

It's tempting to make these additional header and end tokens | |

optional, but if there is a sanity check value in header and end | |

tokens, that value is undermined if the tokens are optional. | |

What should be said about rendering invariances? | |

RESOLUTION: See the Appendix A additions below. | |

The justification for the two rules cited is to support multi-pass | |

rendering when using vertex programs. Different rendering passes | |

will likely use different programs so there must be some means of | |

guaranteeing that two different programs can generate particular | |

identical vertex results between different passes. | |

In practice, this does limit the type of vertex program | |

implementations that are possible. | |

For example, consider a limited hardware implementation of vertex | |

programs that uses a different floating-point implementation | |

than the CPU's floating-point implementation. If the limited | |

hardware implementation can only run small vertex programs (say | |

the hardware provides on 4 temporary registers instead of the | |

required 12), the implementation is incorrect and non-conformant | |

if programs that only require 4 temporary registers use the vertex | |

program hardware, but programs that require more than 4 temporary | |

registers are implemented by the CPU. | |

This is a very important practical requirement. Consider a | |

multi-pass rendering algorithm where one pass uses a vertex program | |

that uses only 4 temporary registers, but a different pass uses a | |

vertex program that uses 5 temporary registers. If two programs | |

have instruction sequences that given the same input state compute | |

identical resulting vertex positions, the multi-pass algorithm | |

should generate identically positioned primitives for each pass. | |

But given the non-conformant vertex program implementation described | |

above, this could not be guaranteed. | |

This does not mean that schemes for splitting vertex program | |

implementations between dedicated hardware and CPUs are impossible. | |

If the CPU and dedicated vertex program hardware used IDENTICAL | |

floating-point implementations and therefore generated exactly | |

identical results, the above described could work. | |

While these invariance rules are vital for vertex programs operating | |

correctly for multi-pass algorithms, there is no requirement that | |

conventional OpenGL vertex transform mode will be invariant with | |

vertex program mode. A multi-pass algorithm should not assume | |

that one pass using vertex program mode and another pass using | |

conventional GL vertex transform mode will generate identically | |

positioned primitives. | |

Consider that while the conventional OpenGL vertex program mode | |

is repeatable with itself, the exact procedure used to transform | |

vertices is not specified nor is the procedure's precision | |

specified. The GL specification indicates that vertex coordinates | |

are transformed by the modelview matrix and then transformed by the | |

projection matrix. Some implementations may perform this sequence | |

of transformations exactly, but other implementations may transform | |

vertex coordinates by the composite of the modelview and projection | |

matrices (one matrix transform instead of two matrix transforms | |

in sequence). Given this implementation flexibility, there is no | |

way for a vertex program author to exactly duplicate the precise | |

computations used by the conventional OpenGL vertex transform mode. | |

The guidance to OpenGL application programs is clear. If you are | |

going to implement multi-pass rendering algorithms that require | |

certain invariances between the multiple passes, choose either | |

vertex program mode or the conventional OpenGL vertex transform | |

mode for your rendering passes, but do not mix the two modes. | |

What range of relative addressing offsets should be allowed? | |

RESOLUTION: -64 to 63. | |

Negative offsets are useful for accessing a table centered at zero | |

without extra bias instructions. Having the offsets support much | |

larger magnitudes just seems to increase the required instruction | |

widths. The -64 to 63 range seems like a reasonable compromise. | |

When EXT_secondary_color is supported, how does the GL_COLOR_SUM_EXT | |

enable affect vertex program mode? | |

RESOLUTION: The GL_COLOR_SUM_EXT enable has no affect when vertex | |

program mode is enabled. | |

When vertex program mode is enabled, the color sum operation is | |

always in operation. A program can "avoid" the color sum operation | |

by not writing the COL1 (or BFC1 when GL_VERTEX_PROGRAM_TWO_SIDE_NV) | |

vertex result registers because the default values of all vertex | |

result registers is (0,0,0,1). For the color sum operation, | |

the alpha value is always assumed zero. So by not writing the | |

secondary color vertex result registers, the program assures that | |

zero is added as part of the color sum operation. | |

If there is a cost to the color sum operation, OpenGL | |

implementations may be smart enough to determine at program bind | |

time whether a secondary color vertex result is generated and | |

implicitly disable the color sum operation. | |

Why must RCP of 1.0 always be 1.0? | |

This is important for 3D graphics so that non-projective textures | |

and orthogonal projections work as expected. Basically when q or | |

w is 1.0, things should work as expected. | |

Stronger requirements such as "RCP of -1.0 must always be -1.0" | |

are encouraged, but there is no compelling reason to state such | |

requirements explicitly as is the case for "RCP of 1.0 must always | |

be 1.0". | |

What happens when the source scalar value for the ARL instruction | |

is an extremely positive or extremely negative floating-point value? | |

Is there a problem mapping the value to a constrained integer range? | |

RESOLUTION: It is not a problem. Relative addressing can by offset | |

by a limited range of offsets (-64 to 63). Relative addressing | |

that falls outside of the 0 to 95 range of program parameter | |

registers is automatically mapped to (0,0,0,0). | |

Clamping the source scalar value for ARL to the range -64 to 160 | |

inclusive is sufficient to ensure that relative addressing is out | |

of range. | |

How do you perform a 3-component normalize in three instructions? | |

# | |

# R1 = (nx,ny,nz) | |

# | |

# R0.xyz = normalize(R1) | |

# R0.w = 1/sqrt(nx*nx + ny*ny + nz*nz) | |

# | |

DP3 R0.w, R1, R1; | |

RSQ R0.w, R0.w; | |

MUL R0.xyz, R1, R0.w; | |

How do you perform a 3-component cross product in two instructions? | |

# | |

# Cross product | i j k | into R2. | |

# | R0.x R0.y R0.z | | |

# | R1.x R1.y R1.z | | |

# | |

MUL R2, R0.zxyw, R1.yzxw; | |

MAD R2, R0.yzxw, R1.zxyw, -R2; | |

How do you perform a 4-component vector absolute value in one | |

instruction? | |

# | |

# Absolute value is the maximum of the negative and positive | |

# components of a vector. | |

# | |

# R1 = abs(R0) | |

# | |

MAX R1, R0, -R0; | |

How do you compute the determinant of a 3x3 matrix in three | |

instructions? | |

# | |

# Determinant of | R0.x R0.y R0.z | into R3 | |

# | R1.x R1.y R1.z | | |

# | R2.x R2.y R2.z | | |

# | |

MUL R3, R1.zxyw, R2.yzxw; | |

MAD R3, R1.yzxw, R2.zxyw, -R3; | |

DP3 R3, R0, R3; | |

How do you transform a vertex position by a 4x4 matrix and then | |

perform a homogeneous divide? | |

# | |

# c[20] = modelview row 0 | |

# c[21] = modelview row 1 | |

# c[22] = modelview row 2 | |

# c[23] = modelview row 3 | |

# | |

# result = R5 | |

# | |

DP4 R5.w, v[OPOS], c[23]; | |

DP4 R5.x, v[OPOS], c[20]; | |

DP4 R5.y, v[OPOS], c[21]; | |

DP4 R5.z, v[OPOS], c[22]; | |

RCP R11, R5.w; | |

MUL R5,R5,R11; | |

How do you perform a vector weighting of two vectors using a single | |

weight? | |

# | |

# R2 = vector 0 | |

# R3 = vector 1 | |

# v[WGHT].x = scalar weight to blend vectors 0 and 1 | |

# result = R2 * v[WGHT].x + R3 * (1-v[WGHT]) | |

# | |

# this is because A*B + (1-A)*C = A*(B-C) + C | |

# | |

ADD R4, R2, -R3; | |

MAD R4, v[WGHT].x, R4, R3; | |

How do you reduce a value to some fundamental period such as 2*PI? | |

# | |

# c[36] = (1.0/(2*PI), 2*PI, 0.0, 0.0) | |

# | |

# R1.x = input value | |

# R2 = result | |

# | |

MUL R0, R1, c[36].x; | |

EXP R4, R0.x; | |

MUL R2, R4.y, c[36].y; | |

How do you implement a simple specular and diffuse lighting | |

computation with an eye-space normal? | |

!!VP1.0 | |

# | |

# c[0-3] = modelview projection (composite) matrix | |

# c[4-7] = modelview inverse transpose | |

# c[32] = normalized eye-space light direction (infinite light) | |

# c[33] = normalized constant eye-space half-angle vector (infinite viewer) | |

# c[35].x = pre-multiplied monochromatic diffuse light color & diffuse material | |

# c[35].y = pre-multiplied monochromatic ambient light color & diffuse material | |

# c[36] = specular color | |

# c[38].x = specular power | |

# | |

# outputs homogenous position and color | |

# | |

DP4 o[HPOS].x, c[0], v[OPOS]; | |

DP4 o[HPOS].y, c[1], v[OPOS]; | |

DP4 o[HPOS].z, c[2], v[OPOS]; | |

DP4 o[HPOS].w, c[3], v[OPOS]; | |

DP3 R0.x, c[4], v[NRML]; | |

DP3 R0.y, c[5], v[NRML]; | |

DP3 R0.z, c[6], v[NRML]; # R0 = n' = transformed normal | |

DP3 R1.x, c[32], R0; # R1.x = Lpos DOT n' | |

DP3 R1.y, c[33], R0; # R1.y = hHat DOT n' | |

MOV R1.w, c[38].x; # R1.w = specular power | |

LIT R2, R1; # Compute lighting values | |

MAD R3, c[35].x, R2.y, c[35].y; # diffuse + emissive | |

MAD o[COL0].xyz, c[36], R2.z, R3; # + specular | |

END | |

Can you perturb transformed vertex positions with a vertex program? | |

Yes. Here is an example that performs an object-space diffuse | |

lighting computations and perturbs the vertex position based on | |

this lighting result. Do not take this example too seriously. | |

!!VP1.0 | |

# | |

# c[0-3] = modelview projection (composite) matrix | |

# c[32] = normalized light direction in object-space | |

# c[35] = yellow diffuse material, (1.0, 1.0, 0.0, 1.0) | |

# c[64].x = 0.0 | |

# c[64].z = 0.125, a scaling factor | |

# | |

# outputs diffuse illumination for color and perturbed position | |

# | |

DP3 R0, c[32], v[NRML]; # light direction DOT normal | |

MUL o[COL0].xyz, R0, c[35]; | |

MAX R0, c[64].x, R0; | |

MUL R0, R0, v[NRML]; | |

MUL R0, R0, c[64].z; | |

ADD R1, v[OPOS], -R0; # perturb object space position | |

DP4 o[HPOS].x, c[0], R1; | |

DP4 o[HPOS].y, c[1], R1; | |

DP4 o[HPOS].z, c[2], R1; | |

DP4 o[HPOS].w, c[3], R1; | |

END | |

What if more exponential precision is needed than provided by the | |

builtin EXP instruction? | |

A sequence of vertex program instructions can be used refine | |

the initial EXP approximation. The pseudo-macro below shows an | |

example of how to refine the EXP approximation. | |

The psuedo-macro requires 10 instructions, 1 temp register, | |

and 2 constant locations. | |

CE0 = { 9.61597636e-03, -1.32823968e-03, 1.47491097e-04, -1.08635004e-05 }; | |

CE1 = { 1.00000000e+00, -6.93147182e-01, 2.40226462e-01, -5.55036440e-02 }; | |

/* Rt != Ro && Rt != Ri */ | |

EXP_MACRO(Ro:vector, Ri:scalar, Rt:vector) { | |

EXP Rt, Ri.x; /* Use appropriate component of Ri */ | |

MAD Rt.w, c[CE0].w, Rt.y, c[CE0].z; | |

MAD Rt.w, Rt.w,Rt.y, c[CE0].y; | |

MAD Rt.w, Rt.w,Rt.y, c[CE0].x; | |

MAD Rt.w, Rt.w,Rt.y, c[CE1].w; | |

MAD Rt.w, Rt.w,Rt.y, c[CE1].z; | |

MAD Rt.w, Rt.w,Rt.y, c[CE1].y; | |

MAD Rt.w, Rt.w,Rt.y, c[CE1].x; | |

RCP Rt.w, Rt.w; | |

MUL Ro, Rt.w, Rt.x; /* Apply user write mask to Ro */ | |

} | |

Simulation gives |max abs error| < 3.77e-07 over the range (0.0 | |

<= x < 1.0). Actual vertex program precision may be slightly | |

less accurate than this. | |

What if more exponential precision is needed than provided by the | |

builtin LOG instruction? | |

The pseudo-macro requires 10 instructions, 1 temp register, | |

and 3 constant locations. | |

CL0 = { 2.41873696e-01, -1.37531206e-01, 5.20646796e-02, -9.31049418e-03 }; | |

CL1 = { 1.44268966e+00, -7.21165776e-01, 4.78684813e-01, -3.47305417e-01 }; | |

CL2 = { 1.0, NA, NA, NA }; | |

/* Rt != Ro && Rt != Ri */ | |

LOG_MACRO(Ro:vector, Ri:scalar, Rt:vector) { | |

LOG Rt, Ri.x; /* Use appropriate component of Ri */ | |

ADD Rt.y, Rt.y, -c[CL2].x; | |

MAD Rt.w, c[CL0].w, Rt.y, c[CL0].z; | |

MAD Rt.w, Rt.w, Rt.y,c[CL0].y; | |

MAD Rt.w, Rt.w, Rt.y,c[CL0].x; | |

MAD Rt.w, Rt.w, Rt.y,c[CL1].w; | |

MAD Rt.w, Rt.w, Rt.y,c[CL1].z; | |

MAD Rt.w, Rt.w, Rt.y,c[CL1].y; | |

MAD Rt.w, Rt.w, Rt.y,c[CL1].x; | |

MAD Ro, Rt.w, Rt.y, Rt.x; /* Apply user write mask to Ro */ | |

} | |

Simulation gives |max abs error| < 1.79e-07 over the range (1.0 | |

<= x < 2.0). Actual vertex program precision may be slightly | |

less accurate than this. | |

New Procedures and Functions | |

void BindProgramNV(enum target, uint id); | |

void DeleteProgramsNV(sizei n, const uint *ids); | |

void ExecuteProgramNV(enum target, uint id, const float *params); | |

void GenProgramsNV(sizei n, uint *ids); | |

boolean AreProgramsResidentNV(sizei n, const uint *ids, | |

boolean *residences); | |

void RequestResidentProgramsNV(sizei n, uint *ids); | |

void GetProgramParameterfvNV(enum target, uint index, | |

enum pname, float *params); | |

void GetProgramParameterdvNV(enum target, uint index, | |

enum pname, double *params); | |

void GetProgramivNV(uint id, enum pname, int *params); | |

void GetProgramStringNV(uint id, enum pname, ubyte *program); | |

void GetTrackMatrixivNV(enum target, uint address, | |

enum pname, int *params); | |

void GetVertexAttribdvNV(uint index, enum pname, double *params); | |

void GetVertexAttribfvNV(uint index, enum pname, float *params); | |

void GetVertexAttribivNV(uint index, enum pname, int *params); | |

void GetVertexAttribPointervNV(uint index, enum pname, void **pointer); | |

boolean IsProgramNV(uint id); | |

void LoadProgramNV(enum target, uint id, sizei len, | |

const ubyte *program); | |

void ProgramParameter4fNV(enum target, uint index, | |

float x, float y, float z, float w) | |

void ProgramParameter4dNV(enum target, uint index, | |

double x, double y, double z, double w) | |

void ProgramParameter4dvNV(enum target, uint index, | |

const double *params); | |

void ProgramParameter4fvNV(enum target, uint index, | |

const float *params); | |

void ProgramParameters4dvNV(enum target, uint index, | |

sizei num, const double *params); | |

void ProgramParameters4fvNV(enum target, uint index, | |

sizei num, const float *params); | |

void TrackMatrixNV(enum target, uint address, | |

enum matrix, enum transform); | |

void VertexAttribPointerNV(uint index, int size, enum type, sizei stride, | |

const void *pointer); | |

void VertexAttrib1sNV(uint index, short x); | |

void VertexAttrib1fNV(uint index, float x); | |

void VertexAttrib1dNV(uint index, double x); | |

void VertexAttrib2sNV(uint index, short x, short y); | |

void VertexAttrib2fNV(uint index, float x, float y); | |

void VertexAttrib2dNV(uint index, double x, double y); | |

void VertexAttrib3sNV(uint index, short x, short y, short z); | |

void VertexAttrib3fNV(uint index, float x, float y, float z); | |

void VertexAttrib3dNV(uint index, double x, double y, double z); | |

void VertexAttrib4sNV(uint index, short x, short y, short z, short w); | |

void VertexAttrib4fNV(uint index, float x, float y, float z, float w); | |

void VertexAttrib4dNV(uint index, double x, double y, double z, double w); | |

void VertexAttrib4ubNV(uint index, ubyte x, ubyte y, ubyte z, ubyte w); | |

void VertexAttrib1svNV(uint index, const short *v); | |

void VertexAttrib1fvNV(uint index, const float *v); | |

void VertexAttrib1dvNV(uint index, const double *v); | |

void VertexAttrib2svNV(uint index, const short *v); | |

void VertexAttrib2fvNV(uint index, const float *v); | |

void VertexAttrib2dvNV(uint index, const double *v); | |

void VertexAttrib3svNV(uint index, const short *v); | |

void VertexAttrib3fvNV(uint index, const float *v); | |

void VertexAttrib3dvNV(uint index, const double *v); | |

void VertexAttrib4svNV(uint index, const short *v); | |

void VertexAttrib4fvNV(uint index, const float *v); | |

void VertexAttrib4dvNV(uint index, const double *v); | |

void VertexAttrib4ubvNV(uint index, const ubyte *v); | |

void VertexAttribs1svNV(uint index, sizei n, const short *v); | |

void VertexAttribs1fvNV(uint index, sizei n, const float *v); | |

void VertexAttribs1dvNV(uint index, sizei n, const double *v); | |

void VertexAttribs2svNV(uint index, sizei n, const short *v); | |

void VertexAttribs2fvNV(uint index, sizei n, const float *v); | |

void VertexAttribs2dvNV(uint index, sizei n, const double *v); | |

void VertexAttribs3svNV(uint index, sizei n, const short *v); | |

void VertexAttribs3fvNV(uint index, sizei n, const float *v); | |

void VertexAttribs3dvNV(uint index, sizei n, const double *v); | |

void VertexAttribs4svNV(uint index, sizei n, const short *v); | |

void VertexAttribs4fvNV(uint index, sizei n, const float *v); | |

void VertexAttribs4dvNV(uint index, sizei n, const double *v); | |

void VertexAttribs4ubvNV(uint index, sizei n, const ubyte *v); | |

New Tokens | |

Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, | |

and by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, | |

and GetDoublev, and by the <target> parameter of BindProgramNV, | |

ExecuteProgramNV, GetProgramParameter[df]vNV, GetTrackMatrixivNV, | |

LoadProgramNV, ProgramParameter[s]4[df][v]NV, and TrackMatrixNV: | |

VERTEX_PROGRAM_NV 0x8620 | |

Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, | |

and by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, | |

and GetDoublev: | |

VERTEX_PROGRAM_POINT_SIZE_NV 0x8642 | |

VERTEX_PROGRAM_TWO_SIDE_NV 0x8643 | |

Accepted by the <target> parameter of ExecuteProgramNV and | |

LoadProgramNV: | |

VERTEX_STATE_PROGRAM_NV 0x8621 | |

Accepted by the <pname> parameter of GetVertexAttrib[dfi]vNV: | |

ATTRIB_ARRAY_SIZE_NV 0x8623 | |

ATTRIB_ARRAY_STRIDE_NV 0x8624 | |

ATTRIB_ARRAY_TYPE_NV 0x8625 | |

CURRENT_ATTRIB_NV 0x8626 | |

Accepted by the <pname> parameter of GetProgramParameterfvNV | |

and GetProgramParameterdvNV: | |

PROGRAM_PARAMETER_NV 0x8644 | |

Accepted by the <pname> parameter of GetVertexAttribPointervNV: | |

ATTRIB_ARRAY_POINTER_NV 0x8645 | |

Accepted by the <pname> parameter of GetProgramivNV: | |

PROGRAM_TARGET_NV 0x8646 | |

PROGRAM_LENGTH_NV 0x8627 | |

PROGRAM_RESIDENT_NV 0x8647 | |

Accepted by the <pname> parameter of GetProgramStringNV: | |

PROGRAM_STRING_NV 0x8628 | |

Accepted by the <pname> parameter of GetTrackMatrixivNV: | |

TRACK_MATRIX_NV 0x8648 | |

TRACK_MATRIX_TRANSFORM_NV 0x8649 | |

Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, | |

GetFloatv, and GetDoublev: | |

MAX_TRACK_MATRIX_STACK_DEPTH_NV 0x862E | |

MAX_TRACK_MATRICES_NV 0x862F | |

CURRENT_MATRIX_STACK_DEPTH_NV 0x8640 | |

CURRENT_MATRIX_NV 0x8641 | |

VERTEX_PROGRAM_BINDING_NV 0x864A | |

PROGRAM_ERROR_POSITION_NV 0x864B | |

Accepted by the <matrix> parameter of TrackMatrixNV: | |

NONE | |

MODELVIEW | |

PROJECTION | |

TEXTURE | |

COLOR (if ARB_imaging is supported) | |

MODELVIEW_PROJECTION_NV 0x8629 | |

TEXTUREi_ARB | |

where i is between 0 and n-1 where n is the number of texture units | |

supported. | |

Accepted by the <matrix> parameter of TrackMatrixNV and by the | |

<mode> parameter of MatrixMode: | |

MATRIX0_NV 0x8630 | |

MATRIX1_NV 0x8631 | |

MATRIX2_NV 0x8632 | |

MATRIX3_NV 0x8633 | |

MATRIX4_NV 0x8634 | |

MATRIX5_NV 0x8635 | |

MATRIX6_NV 0x8636 | |

MATRIX7_NV 0x8637 | |

(Enumerants 0x8638 through 0x863F are reserved for further matrix | |

enumerants 8 through 15.) | |

Accepted by the <transform> parameter of TrackMatrixNV: | |

IDENTITY_NV 0x862A | |

INVERSE_NV 0x862B | |

TRANSPOSE_NV 0x862C | |

INVERSE_TRANSPOSE_NV 0x862D | |

Accepted by the <array> parameter of EnableClientState and | |

DisableClientState, by the <cap> parameter of IsEnabled, and by | |

the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, and | |

GetDoublev: | |

VERTEX_ATTRIB_ARRAY0_NV 0x8650 | |

VERTEX_ATTRIB_ARRAY1_NV 0x8651 | |

VERTEX_ATTRIB_ARRAY2_NV 0x8652 | |

VERTEX_ATTRIB_ARRAY3_NV 0x8653 | |

VERTEX_ATTRIB_ARRAY4_NV 0x8654 | |

VERTEX_ATTRIB_ARRAY5_NV 0x8655 | |

VERTEX_ATTRIB_ARRAY6_NV 0x8656 | |

VERTEX_ATTRIB_ARRAY7_NV 0x8657 | |

VERTEX_ATTRIB_ARRAY8_NV 0x8658 | |

VERTEX_ATTRIB_ARRAY9_NV 0x8659 | |

VERTEX_ATTRIB_ARRAY10_NV 0x865A | |

VERTEX_ATTRIB_ARRAY11_NV 0x865B | |

VERTEX_ATTRIB_ARRAY12_NV 0x865C | |

VERTEX_ATTRIB_ARRAY13_NV 0x865D | |

VERTEX_ATTRIB_ARRAY14_NV 0x865E | |

VERTEX_ATTRIB_ARRAY15_NV 0x865F | |

Accepted by the <target> parameter of GetMapdv, GetMapfv, GetMapiv, | |

Map1d and Map1f and by the <cap> parameter of Enable, Disable, and | |

IsEnabled, and by the <pname> parameter of GetBooleanv, GetIntegerv, | |

GetFloatv, and GetDoublev: | |

MAP1_VERTEX_ATTRIB0_4_NV 0x8660 | |

MAP1_VERTEX_ATTRIB1_4_NV 0x8661 | |

MAP1_VERTEX_ATTRIB2_4_NV 0x8662 | |

MAP1_VERTEX_ATTRIB3_4_NV 0x8663 | |

MAP1_VERTEX_ATTRIB4_4_NV 0x8664 | |

MAP1_VERTEX_ATTRIB5_4_NV 0x8665 | |

MAP1_VERTEX_ATTRIB6_4_NV 0x8666 | |

MAP1_VERTEX_ATTRIB7_4_NV 0x8667 | |

MAP1_VERTEX_ATTRIB8_4_NV 0x8668 | |

MAP1_VERTEX_ATTRIB9_4_NV 0x8669 | |

MAP1_VERTEX_ATTRIB10_4_NV 0x866A | |

MAP1_VERTEX_ATTRIB11_4_NV 0x866B | |

MAP1_VERTEX_ATTRIB12_4_NV 0x866C | |

MAP1_VERTEX_ATTRIB13_4_NV 0x866D | |

MAP1_VERTEX_ATTRIB14_4_NV 0x866E | |

MAP1_VERTEX_ATTRIB15_4_NV 0x866F | |

Accepted by the <target> parameter of GetMapdv, GetMapfv, GetMapiv, | |

Map2d and Map2f and by the <cap> parameter of Enable, Disable, and | |

IsEnabled, and by the <pname> parameter of GetBooleanv, GetIntegerv, | |

GetFloatv, and GetDoublev: | |

MAP2_VERTEX_ATTRIB0_4_NV 0x8670 | |

MAP2_VERTEX_ATTRIB1_4_NV 0x8671 | |

MAP2_VERTEX_ATTRIB2_4_NV 0x8672 | |

MAP2_VERTEX_ATTRIB3_4_NV 0x8673 | |

MAP2_VERTEX_ATTRIB4_4_NV 0x8674 | |

MAP2_VERTEX_ATTRIB5_4_NV 0x8675 | |

MAP2_VERTEX_ATTRIB6_4_NV 0x8676 | |

MAP2_VERTEX_ATTRIB7_4_NV 0x8677 | |

MAP2_VERTEX_ATTRIB8_4_NV 0x8678 | |

MAP2_VERTEX_ATTRIB9_4_NV 0x8679 | |

MAP2_VERTEX_ATTRIB10_4_NV 0x867A | |

MAP2_VERTEX_ATTRIB11_4_NV 0x867B | |

MAP2_VERTEX_ATTRIB12_4_NV 0x867C | |

MAP2_VERTEX_ATTRIB13_4_NV 0x867D | |

MAP2_VERTEX_ATTRIB14_4_NV 0x867E | |

MAP2_VERTEX_ATTRIB15_4_NV 0x867F | |

Additions to Chapter 2 of the OpenGL 1.2.1 Specification (OpenGL Operation) | |

-- Section 2.10 "Coordinate Transformations" | |

Add this initial discussion: | |

"Per-vertex parameters are transformed before the transformation | |

results are used to generate primitives for rasterization, establish | |

a raster position, or generate vertices for selection or feedback. | |

Each vertex's per-vertex parameters are transformed by one of | |

two vertex transformation modes. The first vertex transformation mode | |

is GL's conventional vertex transformation model. The second mode, | |

known as 'vertex program' mode, transforms the vertex's per-vertex | |

parameters by an application-supplied vertex program. | |

Vertex program mode is enabled and disabled, respectively, by | |

void Enable(enum target); | |

and | |

void Disable(enum target); | |

with target equal to VERTEX_PROGRAM_NV. When vertex program mode | |

is enabled, vertices are transformed by the currently bound vertex | |

program as discussed in section 2.14." | |

Update the original initial paragraph in the section to read: | |

"When vertex program mode is disabled, vertices, normals, and texture | |

coordinates are transformed before their coordinates are used to | |

produce an image in the framebuffer. We begin with a description | |

of how vertex coordinates are transformed and how the transformation | |

is controlled in the case when vertex program mode is disabled. The | |

discussion that continues through section 2.13 applies when vertex | |

program mode is disabled." | |

-- Section 2.10.2 "Matrices" | |

Change the first paragraph to read: | |

"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 MATRIXi_NV as the argument. In the case | |

of MATRIXi_NV, i is an integer between 0 and n-1 indicating one | |

of n tracking matrices where n is the value of the implementation | |

defined constant MAX_TRACK_MATRICES_NV. TEXTURE is described | |

later in section 2.10.2, and COLOR is described in section 3.6.3. | |

The tracking matrices of the form MATRIXi_NV are described in | |

section 2.14.5. 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." | |

Change the last paragraph to read: | |

"The state required to implement transformations consists of a n-value | |

integer indicating the current matrix mode (where n is 4 + the number | |

of tracking matrices supported), 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 MATRIXi_NV 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." | |

-- NEW Section 2.14 "Vertex Programs" | |

"The conventional GL vertex transformation model described | |

in sections 2.10 through 2.13 is a configurable but essentially | |

hard-wired sequence of per-vertex computations based on a canonical | |

set of per-vertex parameters and vertex transformation related | |

state such as transformation matrices, lighting parameters, and | |

texture coordinate generation parameters. | |

The general success and utility of the conventional GL vertex | |

transformation model reflects its basic correspondence to the | |

typical vertex transformation requirements of 3D applications. | |

However when the conventional GL vertex transformation model | |

is not sufficient, the vertex program mode provides a substantially | |

more flexible model for vertex transformation. The vertex program | |

mode permits applications to define their own vertex programs. | |

2.14.1 The Vertex Program Execution Model | |

A vertex program is a sequence of floating-point 4-component vector | |

operations that operate on per-vertex attributes and program | |

parameters. Vertex programs execute on a per-vertex basis and | |

operate on each vertex completely independently from the processing | |

of other vertices. Vertex programs execute a finite fixed sequence | |

of instructions with no branching or looping. Vertex programs | |

execute without data hazards so results computed in one operation can | |

be used immediately afterwards. The result of a vertex program is | |

a set of vertex result vectors that becomes the transformed vertex | |

parameters used by primitive assembly. | |

Vertex programs use a specific well-defined instruction set, register | |

set, and operational model defined in the following sections. | |

The vertex program register set consists of five types of registers | |

described in the following five sections. | |

2.14.1.1 The Vertex Attribute Registers | |

The Vertex Attribute Registers are sixteen 4-component | |

vector floating-point registers containing the current vertex's | |

per-vertex attributes. These registers are numbered 0 through 15. | |

These registers are private to each vertex program invocation and are | |

initialized at each vertex program invocation by the current vertex | |

attribute state specified with VertexAttribNV commands. These registers | |

are read-only during vertex program execution. The VertexAttribNV | |

commands used to update the vertex attribute registers can be issued | |

both outside and inside of Begin/End pairs. Vertex program execution | |

is provoked by updating vertex attribute zero. Updating vertex | |

attribute zero outside of a Begin/End pair is ignored without | |

generating any error (identical to the Vertex command operation). | |

The commands | |

void VertexAttrib{1234}{sfd}NV(uint index, T coords); | |

void VertexAttrib{1234}{sfd}vNV(uint index, T coords); | |

void VertexAttrib4ubNV(uint index, T coords); | |

void VertexAttrib4ubvNV(uint index, T coords); | |

specify the particular current vertex attribute indicated by index. | |

The coordinates for each vertex attribute are named x, y, z, and w. | |

The VertexAttrib1NV family of commands sets the x coordinate to the | |

provided single argument while setting y and z to 0 and w to 1. | |

Similarly, VertexAttrib2NV sets x and y to the specified values, | |

z to 0 and w to 1; VertexAttrib3NV sets x, y, and z, with w set | |

to 1, and VertexAttrib4NV sets all four coordinates. The error | |

INVALID_VALUE is generated if index is greater than 15. | |

No conversions are applied to the vertex attributes specified as | |

type short, float, or double. However, vertex attributes specified | |

as type ubyte are converted as described by Table 2.6. | |

The commands | |

void VertexAttribs{1234}{sfd}vNV(uint index, sizei n, T coords[]); | |

void VertexAttribs4ubvNV(uint index, sizei n, GLubyte coords[]); | |

specify a contiguous set of n vertex attributes. The effect of | |

VertexAttribs{1234}{sfd}vNV(index, n, coords) | |

is the same (assuming no errors) as the command sequence | |

#define NUM k /* where k is 1, 2, 3, or 4 components */ | |

int i; | |

for (i=n-1; i>=0; i--) { | |

VertexAttrib{NUM}{sfd}vNV(i+index, &coords[i*NUM]); | |

} | |

VertexAttribs4ubvNV behaves similarly. | |

The VertexAttribNV calls equivalent to VertexAttribsNV are issued in | |

reverse order so that vertex program execution is provoked when index | |

is zero only after all the other vertex attributes have first been | |

specified. | |

2.14.1.2 The Program Parameter Registers | |

The Program Parameter Registers are ninety-six 4-component | |

floating-point vector registers containing the vertex program | |

parameters. These registers are numbered 0 through 95. This | |

relatively large set of registers is intended to hold parameters | |

such as matrices, lighting parameters, and constants required by | |

vertex programs. Vertex program parameter registers can be updated | |

in one of two ways: by the ProgramParameterNV commands outside | |

of a Begin/End pair or by a vertex state program executed outside | |

of a Begin/End pair (vertex state programs are discussed in section | |

2.14.3). | |

The commands | |

void ProgramParameter4fNV(enum target, uint index, | |

float x, float y, float z, float w) | |

void ProgramParameter4dNV(enum target, uint index, | |

double x, double y, double z, double w) | |

specify the particular program parameter indicated by index. | |

The coordinates values x, y, z, and w are assigned to the respective | |

components of the particular program parameter. target must be | |

VERTEX_PROGRAM_NV. | |

The commands | |

void ProgramParameter4dvNV(enum target, uint index, double *params); | |

void ProgramParameter4fvNV(enum target, uint index, float *params); | |

operate identically to ProgramParameter4fNV and ProgramParameter4dNV | |

respectively except that the program parameters are passed as an | |

array of four components. | |

The commands | |

void ProgramParameters4dvNV(enum target, uint index, | |

uint num, double *params); | |

void ProgramParameters4fvNV(enum target, uint index, | |

uint num, float *params); | |

specify a contiguous set of num program parameters. target must | |

be VERTEX_PROGRAM_NV. The effect is the same (assuming no errors) as | |

for (i=index; i<index+num; i++) { | |

ProgramParameter4{fd}vNV(target, i, ¶ms[i*4]); | |

} | |

The program parameter registers are shared to all vertex program | |

invocations within a rendering context. ProgramParameterNV command | |

updates and vertex state program executions are serialized with | |

respect to vertex program invocations and other vertex state program | |

executions. | |

Writes to the program parameter registers during vertex state program | |

execution can be maskable on a per-component basis. | |

The error INVALID_VALUE is generated if any ProgramParameterNV has | |

an index is greater than 95. | |

The initial value of all ninety-six program parameter registers is | |

(0,0,0,0). | |

2.14.1.3 The Address Register | |

The Address Register is a single 4-component vector signed 32-bit | |

integer register though only the x component of the vector is | |

accessible. The register is private to each vertex program invocation | |

and is initialized to (0,0,0,0) at every vertex program invocation. | |

This register can be written during vertex program execution (but | |

not read) and its value can be used for as a relative offset for | |

reading vertex program parameter registers. Only the vertex program | |

parameter registers can be read using relative addressing (writes | |

using relative addressing are not supported). | |

See the discussion of relative addressing of program parameters | |

in section 2.14.1.9 and the discussion of the ARL instruction in | |

section 2.14.1.10.1. | |

2.14.1.4 The Temporary Registers | |

The Temporary Registers are twelve 4-component floating-point vector | |

registers used to hold temporary results during vertex program | |

execution. These registers are numbered 0 through 11. These | |

registers are private to each vertex program invocation and | |

initialized to (0,0,0,0) at every vertex program invocation. These | |

registers can be read and written during vertex program execution. | |

Writes to these registers can be maskable on a per-component basis. | |

2.14.1.5 The Vertex Result Register Set | |

The Vertex Result Registers are fifteen 4-component floating-point | |

vector registers used to write the results of a vertex program. | |

Each register value is initialized to (0,0,0,1) at the invocation | |

of each vertex program. Writes to the vertex result registers can | |

be maskable on a per-component basis. These registers are named in | |

Table X.1 and further discussed below. | |

Vertex Result Component | |

Register Name Description Interpretation | |

-------------- --------------------------------- -------------- | |

HPOS Homogeneous clip space position (x,y,z,w) | |

COL0 Primary color (front-facing) (r,g,b,a) | |

COL1 Secondary color (front-facing) (r,g,b,a) | |

BFC0 Back-facing primary color (r,g,b,a) | |

BFC1 Back-facing secondary color (r,g,b,a) | |

FOGC Fog coordinate (f,*,*,*) | |

PSIZ Point size (p,*,*,*) | |

TEX0 Texture coordinate set 0 (s,t,r,q) | |

TEX1 Texture coordinate set 1 (s,t,r,q) | |

TEX2 Texture coordinate set 2 (s,t,r,q) | |

TEX3 Texture coordinate set 3 (s,t,r,q) | |

TEX4 Texture coordinate set 4 (s,t,r,q) | |

TEX5 Texture coordinate set 5 (s,t,r,q) | |

TEX6 Texture coordinate set 6 (s,t,r,q) | |

TEX7 Texture coordinate set 7 (s,t,r,q) | |

Table X.1: Vertex Result Registers. | |

HPOS is the transformed vertex's homogeneous clip space position. | |

The vertex's homogeneous clip space position is converted to | |

normalized device coordinates and transformed to window coordinates | |

as described at the end of section 2.10 and in section 2.11. | |

Further processing (subsequent to vertex program termination) | |

is responsible for clipping primitives assembled from vertex | |

program-generated vertices as described in section 2.10 but all | |

client-defined clip planes are treated as if they are disabled when | |

vertex program mode is enabled. | |

Four distinct color results can be generated for each vertex. | |

COL0 is the transformed vertex's front-facing primary color. | |

COL1 is the transformed vertex's front-facing secondary color. | |

BFC0 is the transformed vertex's back-facing primary color. BFC1 is | |

the transformed vertex's back-facing secondary color. | |

Primitive coloring may operate in two-sided color mode. This behavior | |

is enabled and disabled by calling Enable or Disable with the | |

symbolic value VERTEX_PROGRAM_TWO_SIDE_NV. The selection between | |

the back-facing colors and the front-facing colors depends on the | |

primitive of which the vertex is a part. If the primitive is a | |

point or a line segment, the front-facing colors are always selected. | |

If the primitive is a polygon and two-sided color mode is disabled, | |

the front-facing colors are selected. If it is a polygon and | |

two-sided color mode is enabled, then the selection is based on the | |

sign of the (clipped or unclipped) polygon's signed area computed in | |

window coordinates. This facingness determination is identical to | |

the two-sided lighting facingness determination described in section | |

2.13.1. | |

The selected primary and secondary colors for each primitive are | |

clamped to the range [0,1] and then interpolated across the assembled | |

primitive during rasterization with at least 8-bit accuracy for each | |

color component. | |

FOGC is the transformed vertex's fog coordinate. The register's | |

first floating-point component is interpolated across the assembled | |

primitive during rasterization and used as the fog distance to | |

compute per-fragment the fog factor when fog is enabled. However, | |

if both fog and vertex program mode are enabled, but the FOGC vertex | |

result register is not written, the fog factor is overridden to 1.0. | |

The register's other three components are ignored. | |

Point size determination may operate in program-specified point | |

size mode. This behavior is enabled and disabled by calling Enable | |

or Disable with the symbolic value VERTEX_PROGRAM_POINT_SIZE_NV. | |

If the vertex is for a point primitive and the mode is enabled | |

and the PSIZ vertex result is written, the point primitive's size | |

is determined by the clamped x component of the PSIZ register. | |

Otherwise (because vertex program mode is disabled, program-specified | |

point size mode is disabled, or because the vertex program did not | |

write PSIZ), the point primitive's size is determined by the point | |

size state (the state specified using the PointSize command). | |

The PSIZ register's x component is clamped to the range zero through | |

either the hi value of ALIASED_POINT_SIZE_RANGE if point smoothing | |

is disabled or the hi value of the SMOOTH_POINT_SIZE_RANGE if | |

point smoothing is enabled. The register's other three components | |

are ignored. | |

If the vertex is not for a point primitive, the value of the | |

PSIZ vertex result register is ignored. | |

TEX0 through TEX7 are the transformed vertex's texture coordinate | |

sets for texture units 0 through 7. These floating-point coordinates | |

are interpolated across the assembled primitive during rasterization | |

and used for accessing textures. If the number of texture units | |

supported is less than eight, the values of vertex result registers | |

that do not correspond to existent texture units are ignored. | |

2.14.1.6 Semantic Meaning for Vertex Attributes and Program Parameters | |

One important distinction between the conventional GL vertex | |

transformation mode and the vertex program mode is that per-vertex | |

parameters and other state parameters in vertex program mode do | |

not have dedicated semantic interpretations the way that they do | |

with the conventional GL vertex transformation mode. | |

For example, in the conventional GL vertex transformation mode, | |

the Normal command specifies a per-vertex normal. The semantic that | |

the Normal command supplies a normal for lighting is established because | |

that is how the per-vertex attribute supplied by the Normal command | |

is used by the conventional GL vertex transformation mode. | |

Similarly, other state parameters such as a light source position have | |

semantic interpretations based on how the conventional GL vertex | |

transformation model uses each particular parameter. | |

In contrast, vertex attributes and program parameters for vertex | |

programs have no pre-defined semantic meanings. The meaning of | |

a vertex attribute or program parameter in vertex program mode is | |

defined by how the vertex attribute or program parameter is used by | |

the current vertex program to compute and write values to the Vertex | |

Result Registers. This is the reason that per-vertex attributes and | |

program parameters for vertex programs are numbered instead of named. | |

For convenience however, the existing per-vertex parameters for the | |

conventional GL vertex transformation mode (vertices, normals, | |

colors, fog coordinates, vertex weights, and texture coordinates) are | |

aliased to numbered vertex attributes. This aliasing is specified in | |

Table X.2. The table includes how the various conventional components | |

map to the 4-component vertex attribute components. | |

Vertex | |

Attribute Conventional Conventional | |

Register Per-vertex Conventional Component | |

Number Parameter Per-vertex Parameter Command Mapping | |

--------- --------------- ----------------------------------- ------------ | |

0 vertex position Vertex x,y,z,w | |

1 vertex weights VertexWeightEXT w,0,0,1 | |

2 normal Normal x,y,z,1 | |

3 primary color Color r,g,b,a | |

4 secondary color SecondaryColorEXT r,g,b,1 | |

5 fog coordinate FogCoordEXT fc,0,0,1 | |

6 - - - | |

7 - - - | |

8 texture coord 0 MultiTexCoord(GL_TEXTURE0_ARB, ...) s,t,r,q | |

9 texture coord 1 MultiTexCoord(GL_TEXTURE1_ARB, ...) s,t,r,q | |

10 texture coord 2 MultiTexCoord(GL_TEXTURE2_ARB, ...) s,t,r,q | |

11 texture coord 3 MultiTexCoord(GL_TEXTURE3_ARB, ...) s,t,r,q | |

12 texture coord 4 MultiTexCoord(GL_TEXTURE4_ARB, ...) s,t,r,q | |

13 texture coord 5 MultiTexCoord(GL_TEXTURE5_ARB, ...) s,t,r,q | |

14 texture coord 6 MultiTexCoord(GL_TEXTURE6_ARB, ...) s,t,r,q | |

15 texture coord 7 MultiTexCoord(GL_TEXTURE7_ARB, ...) s,t,r,q | |

Table X.2: Aliasing of vertex attributes with conventional per-vertex | |

parameters. | |

Only vertex attribute zero is treated specially because it is | |

the attribute that provokes the execution of the vertex program; | |

this is the attribute that aliases to the Vertex command's vertex | |

coordinates. | |

The result of a vertex program is the set of post-transformation | |

vertex parameters written to the Vertex Result Registers. | |

All vertex programs must write a homogeneous clip space position, but | |

the other Vertex Result Registers can be optionally written. | |

Clipping and culling are not the responsibility of vertex programs | |

because these operations assume the assembly of multiple vertices | |

into a primitive. View frustum clipping is performed subsequent to | |

vertex program execution. Clip planes are not supported in vertex | |

program mode. | |

2.14.1.7 Vertex Program Specification | |

Vertex programs are specified as an array of ubytes. The array is | |

a string of ASCII characters encoding the program. | |

The command | |

LoadProgramNV(enum target, uint id, sizei len, | |

const ubyte *program); | |

loads a vertex program when the target parameter is VERTEX_PROGRAM_NV. | |

Multiple programs can be loaded with different names. id names the | |

program to load. The name space for programs is the positive integers | |

(zero is reserved). The error INVALID_VALUE occurs if a program is | |

loaded with an id of zero. The error INVALID_OPERATION is generated | |

if a program is loaded for an id that is currently loaded with a | |

program of a different program target. Managing the program name | |

space and binding to vertex programs is discussed later in section | |

2.14.1.8. | |

program is a pointer to an array of ubytes that represents the | |

program being loaded. The length of the array is indicated by len. | |

A second program target type known as vertex state programs is | |

discussed in 2.14.4. | |

At program load time, the program is parsed into a set of tokens | |

possibly separated by white space. 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 vertex 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. | |

<program> ::= "!!VP1.0" <instructionSequence> "END" | |

<instructionSequence> ::= <instructionSequence> <instructionLine> | |

| <instructionLine> | |

<instructionLine> ::= <instruction> ";" | |

<instruction> ::= <ARL-instruction> | |

| <VECTORop-instruction> | |

| <SCALARop-instruction> | |

| <BINop-instruction> | |

| <TRIop-instruction> | |

<ARL-instruction> ::= "ARL" <addrReg> "," <scalarSrcReg> | |

<VECTORop-instruction> ::= <VECTORop> <maskedDstReg> "," <swizzleSrcReg> | |

<SCALARop-instruction> ::= <SCALARop> <maskedDstReg> "," <scalarSrcReg> | |

<BINop-instruction> ::= <BINop> <maskedDstReg> "," | |

<swizzleSrcReg> "," <swizzleSrcReg> | |

<TRIop-instruction> ::= <TRIop> <maskedDstReg> "," | |

<swizzleSrcReg> "," <swizzleSrcReg> "," | |

<swizzleSrcReg> | |

<VECTORop> ::= "MOV" | |

| "LIT" | |

<SCALARop> ::= "RCP" | |

| "RSQ" | |

| "EXP" | |

| "LOG" | |

<BINop> ::= "MUL" | |

| "ADD" | |

| "DP3" | |

| "DP4" | |

| "DST" | |

| "MIN" | |

| "MAX" | |

| "SLT" | |

| "SGE" | |

<TRIop> ::= "MAD" | |

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

<swizzleSrcReg> ::= <optionalSign> <srcReg> <swizzleSuffix> | |

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

<optionalMask> ::= "" | |

| "." "x" | |

| "." "y" | |

| "." "x" "y" | |

| "." "z" | |

| "." "x" "z" | |

| "." "y" "z" | |

| "." "x" "y" "z" | |

| "." "w" | |

| "." "x" "w" | |

| "." "y" "w" | |

| "." "x" "y" "w" | |

| "." "z" "w" | |

| "." "x" "z" "w" | |

| "." "y" "z" "w" | |

| "." "x" "y" "z" "w" | |

<optionalSign> ::= "-" | |

| "" | |

<srcReg> ::= <vertexAttribReg> | |

| <progParamReg> | |

| <temporaryReg> | |

<dstReg> ::= <temporaryReg> | |

| <vertexResultReg> | |

<vertexAttribReg> ::= "v" "[" vertexAttribRegNum "]" | |

<vertexAttribRegNum> ::= decimal integer from 0 to 15 inclusive | |

| "OPOS" | |

| "WGHT" | |

| "NRML" | |

| "COL0" | |

| "COL1" | |

| "FOGC" | |

| "TEX0" | |

| "TEX1" | |

| "TEX2" | |

| "TEX3" | |

| "TEX4" | |

| "TEX5" | |

| "TEX6" | |

| "TEX7" | |

<progParamReg> ::= <absProgParamReg> | |

| <relProgParamReg> | |

<absProgParamReg> ::= "c" "[" <progParamRegNum> "]" | |

<progParamRegNum> ::= decimal integer from 0 to 95 inclusive | |

<relProgParamReg> ::= "c" "[" <addrReg> "]" | |

| "c" "[" <addrReg> "+" <progParamPosOffset> "]" | |

| "c" "[" <addrReg> "-" <progParamNegOffset> "]" | |

<progParamPosOffset> ::= decimal integer from 0 to 63 inclusive | |

<progParamNegOffset> ::= decimal integer from 0 to 64 inclusive | |

<addrReg> ::= "A0" "." "x" | |

<temporaryReg> ::= "R0" | |

| "R1" | |

| "R2" | |

| "R3" | |

| "R4" | |

| "R5" | |

| "R6" | |

| "R7" | |

| "R8" | |

| "R9" | |

| "R10" | |

| "R11" | |

<vertexResultReg> ::= "o" "[" vertexResultRegName "]" | |

<vertexResultRegName> ::= "HPOS" | |

| "COL0" | |

| "COL1" | |

| "BFC0" | |

| "BFC1" | |

| "FOGC" | |

| "PSIZ" | |

| "TEX0" | |

| "TEX1" | |

| "TEX2" | |

| "TEX3" | |

| "TEX4" | |

| "TEX5" | |

| "TEX6" | |

| "TEX7" | |

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

<swizzleSuffix> ::= "" | |

| "." <component> | |

| "." <component> <component> | |

<component> <component> | |

<component> ::= "x" | |

| "y" | |

| "z" | |

| "w" | |

The <vertexAttribRegNum> rule matches both register numbers 0 through | |

15 and a set of mnemonics that abbreviate the aliasing of conventional | |

the per-vertex parameters to vertex attribute register numbers. | |

Table X.3 shows the mapping from mnemonic to vertex attribute register | |

number and what the mnemonic abbreviates. | |

Vertex Attribute | |

Mnemonic Register Number Meaning | |

-------- ---------------- -------------------- | |

"OPOS" 0 object position | |

"WGHT" 1 vertex weight | |

"NRML" 2 normal | |

"COL0" 3 primary color | |

"COL1" 4 secondary color | |

"FOGC" 5 fog coordinate | |

"TEX0" 8 texture coordinate 0 | |

"TEX1" 9 texture coordinate 1 | |

"TEX2" 10 texture coordinate 2 | |

"TEX3" 11 texture coordinate 3 | |

"TEX4" 12 texture coordinate 4 | |

"TEX5" 13 texture coordinate 5 | |

"TEX6" 14 texture coordinate 6 | |

"TEX7" 15 texture coordinate 7 | |

Table X.3: The mapping between vertex attribute register numbers, | |

mnemonics, and meanings. | |

A vertex programs fails to load if it does not write at least one | |

component of the HPOS register. | |

A vertex program fails to load if it contains more than 128 | |

instructions. | |

A vertex program fails to load if any instruction sources more than | |

one unique program parameter register. | |

A vertex program fails to load if any instruction sources more than | |

one unique vertex attribute register. | |

The error INVALID_OPERATION is generated if a vertex program fails | |

to load because it is not syntactically correct or for one of the | |

semantic restrictions listed above. | |

The error INVALID_OPERATION is generated if a program is loaded for | |

id when id is currently loaded with a program of a different target. | |

A successfully loaded vertex 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 2.14.1.10. | |

A successfully loaded program replaces the program previously assigned | |

to the name specified by id. If the OUT_OF_MEMORY error is generated | |

by LoadProgramNV, no change is made to the previous contents of the | |

named program. | |

Querying the value of PROGRAM_ERROR_POSITION_NV returns a ubyte | |

offset into the last loaded program string indicating where the first | |

error in the program. If the program fails to load because of a | |

semantic restriction that cannot be determined until the program | |

is fully scanned, the error position will be len, the length of | |

the program. If the program loads successfully, the value of | |

PROGRAM_ERROR_POSITION_NV is assigned the value negative one. | |

2.14.1.8 Vertex Program Binding and Program Management | |

The current vertex program is invoked whenever vertex attribute | |

zero is updated (whether by a VertexAttributeNV or Vertex command). | |

The current vertex program is updated by | |

BindProgramNV(enum target, uint id); | |

where target must be VERTEX_PROGRAM_NV. This binds the vertex program | |

named by id as the current vertex program. The error INVALID_OPERATION | |

is generated if id names a program that is not a vertex program | |

(for example, if id names a vertex state program as described in | |

section 2.14.4). | |

Binding to a nonexistent program id does not generate an error. | |

In particular, binding to program id zero does not generate an error. | |

However, because program zero cannot be loaded, program zero is | |

always nonexistent. If a program id is successfully loaded with a | |

new vertex program and id is also the currently bound vertex program, | |

the new program is considered the currently bound vertex program. | |

The INVALID_OPERATION error is generated when both vertex program | |

mode is enabled and Begin is called (or when a command that performs | |

an implicit Begin is called) if the current vertex program is | |

nonexistent or not valid. A vertex program may not be valid for | |

reasons explained in section 2.14.5. | |

Programs are deleted by calling | |

void DeleteProgramsNV(sizei n, const uint *ids); | |

ids contains n names of programs to be deleted. After a program | |

is deleted, it becomes nonexistent, and its name is again unused. | |

If a program that is currently bound is deleted, it is as though | |

BindProgramNV has been executed with the same target as the deleted | |

program and program zero. Unused names in ids are silently ignored, | |

as is the value zero. | |

The command | |

void GenProgramsNV(sizei n, uint *ids); | |

returns n previously unused program names in ids. These names | |

are marked as used, for the purposes of GenProgramsNV only, | |

but they become existent programs only when the are first loaded | |

using LoadProgramNV. The error INVALID_VALUE is generated if n | |

is negative. | |

An implementation may choose to establish a working set of programs on | |

which binding and ExecuteProgramNV operations (execute programs are | |

explained in section 2.14.4) are performed with higher performance. | |

A program that is currently part of this working set is said to | |

be resident. | |

The command | |

boolean AreProgramsResidentNV(sizei n, const uint *ids, | |

boolean *residences); | |

returns TRUE if all of the n programs named in ids are resident, | |

or if the implementation does not distinguish a working set. If at | |

least one of the programs named in ids is not resident, then FALSE is | |

returned, and the residence of each program is returned in residences. | |

Otherwise the contents of residences are not changed. If any of | |

the names in ids are nonexistent or zero, FALSE is returned, the | |

error INVALID_VALUE is generated, and the contents of residences | |

are indeterminate. The residence status of a single named program | |

can also be queried by calling GetProgramivNV with id set to the | |

name of the program and pname set to PROGRAM_RESIDENT_NV. | |

AreProgramsResidentNV indicates only whether a program is | |

currently resident, not whether it could not be made resident. | |

An implementation may choose to make a program resident only on | |

first use, for example. The client may guide the GL implementation | |

in determining which programs should be resident by requesting a | |

set of programs to make resident. | |

The command | |

void RequestResidentProgramsNV(sizei n, const uint *ids); | |

requests that the n programs named in ids should be made resident. | |

While all the programs are not guaranteed to become resident, | |

the implementation should make a best effort to make as many of | |

the programs resident as possible. As a result of making the | |

requested programs resident, program names not among the requested | |

programs may become non-resident. Higher priority for residency | |

should be given to programs listed earlier in the ids array. | |

RequestResidentProgramsNV silently ignores attempts to make resident | |

nonexistent program names or zero. AreProgramsResidentNV can be | |

called after RequestResidentProgramsNV to determine which programs | |

actually became resident. | |

2.14.1.9 Vertex Program Register Accesses | |

There are 17 vertex program instructions. The instructions and their | |

respective input and output parameters are summarized in Table X.4. | |

Output | |

Inputs (vector or | |

Opcode (scalar or vector) replicated scalar) Operation | |

------ ------------------ ------------------ -------------------------- | |

ARL s address register address register load | |

MOV v v move | |

MUL v,v v multiply | |

ADD v,v v add | |

MAD v,v,v v multiply and add | |

RCP s ssss reciprocal | |

RSQ s ssss reciprocal square root | |

DP3 v,v ssss 3-component dot product | |

DP4 v,v ssss 4-component dot product | |

DST v,v v distance vector | |

MIN v,v v minimum | |

MAX v,v v maximum | |

SLT v,v v set on less than | |

SGE v,v v set on greater equal than | |

EXP s v exponential base 2 | |

LOG s v logarithm base 2 | |

LIT v v light coefficients | |

Table X.4: Summary of vertex program instructions. "v" indicates a | |

vector input or output, "s" indicates a scalar input, and "ssss" indicates | |

a scalar output replicated across a 4-component vector. | |

Instructions use either scalar source values or swizzled source | |

values, indicated in the grammar (see section 2.14.1.7) by the rules | |

<scalarSrcReg> and <swizzleSrcReg> respectively. Either type of | |

source value is negated when the <optionalSign> rule matches "-". | |

Scalar source register values select one of the source register's | |

four components based on the <component> of the <scalarSuffix> rule. | |

The characters "x", "y", "z", and "w" match the x, y, z, and | |

w components respectively. The indicated component is used as a | |

scalar for the particular source value. | |

Swizzled source register values may arbitrarily swizzle the source | |

register's components based on the <swizzleSuffix> rule. In the case | |

where the <swizzleSuffix> matches (ignoring whitespace) the pattern | |

".????" where each question mark is one of "x", "y", "z", or "w", | |

this indicates the ith component of the source register value should | |

come from the component named by the ith component in the sequence. | |

For example, if the swizzle suffix is ".yzzx" and the source register | |

contains [ 2.0, 8.0, 9.0, 0.0 ] the swizzled source register value | |

used by the instruction is [ 8.0, 9.0, 9.0, 2.0 ]. | |

If the <swizzleSuffix> rule matches "", this is treated the same as | |

".xyzw". If the <swizzleSuffix> rule matches (ignoring whitespace) | |

".x", ".y", ".z", or ".w", these are treated the same as ".xxxx", | |

".yyyy", ".zzzz", and ".wwww" respectively. | |

The register sourced for either a scalar source register value or a | |

swizzled source register value is indicated in the grammar by the rule | |

<srcReg>. The <vertexAttribReg>, <progParamReg>, and <temporaryReg> | |

sub-rules correspond to one of the vertex attribute registers, | |

program parameter registers, or temporary register respectively. | |

The vertex attribute and temporary registers are accessed absolutely | |

based on the numbered register. In the case of vertex attribute | |

registers, if the <vertexAttribRegNum> corresponds to a mnemonic, | |

the corresponding register number from Table X.3 is used. | |

Either absolute or relative addressing can be used to access the | |

program parameter registers. Absolute addressing is indicated by | |

the grammar by the <absProgParamReg> rule. Absolute addressing | |

accesses the numbered program parameter register indicated by the | |

<progParamRegNum> rule. Relative addressing accesses the numbered | |

program parameter register plus an offset. The offset is the positive | |

value of <progParamPosOffset> if the <progParamPosOffset> rule is | |

matched, or the offset is the negative value of <progParamNegOffset> | |

if the <progParamNegOffset> rule is matched, or otherwise the offset | |

is zero. Relative addressing is available only for program parameter | |

registers and only for reads (not writes). Relative addressing | |

reads outside of the 0 to 95 inclusive range always read the value | |

(0,0,0,0). | |

The result of all instructions except ARL is written back to a | |

masked destination register, indicated in the grammar by the rule | |

<maskedDstReg>. | |

Writes to each component of the destination register can be masked, | |

indicated in the grammar by the <optionalMask> rule. If the optional | |

mask is "", all components are written. Otherwise, the optional | |

mask names particular components to write. The characters "x", | |

"y", "z", and "w" match the x, y, z, and w components respectively. | |

For example, an optional mask of ".xzw" indicates that the x, z, | |

and w components should be written but not the y component. | |

The grammar requires that the destination register mask components | |

must be listed in "xyzw" order. | |

The actual destination register is indicated in the grammar by | |

the rule <dstReg>. The <temporaryReg> and <vertexResultReg> | |

sub-rules correspond to either the temporary registers or vertex | |

result registers. The temporary registers are determined and accessed | |

as described earlier. | |

The vertex result registers are accessed absolutely based on the | |

named register. The <vertexResultRegName> rule corresponds to | |

registers named in Table X.1. | |

2.14.1.10 Vertex Program Instruction Set Operations | |

The operation of the 17 vertex program instructions are described in | |

this section. After the textual description of each instruction's | |

operation, a register transfer level description is also presented. | |

The following conventions are used in each instruction's register | |

transfer level description. The 4-component vector variables "t", | |

"u", and "v" are assigned intermediate results. The destination | |

register is called "destination". The three possible source registers | |

are called "source0", "source1", and "source2" respectively. | |

The x, y, z, and w vector components are referred to with the suffixes | |

".x", ".y", ".z", and ".w" respectively. The suffix ".c" is used for | |

scalar source register values and c represents the particular source | |

register's selected scalar component. Swizzling of components is | |

indicated with the suffixes ".c***", ".*c**", ".**c*", and ".***c" | |

where c is meant to indicate the x, y, z, or w component selected for | |

the particular source operand swizzle configuration. For example: | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

This example indicates that t should be assigned the swizzled | |

version of the source0 operand based on the source0 operand's swizzle | |

configuration. | |

The variables "negate0", "negate1", and "negate2" are booleans | |

that are true when the respective source value should be negated. | |

The variables "xmask", "ymask", "zmask", and "wmask" are booleans | |

that are true when the destination write mask for the respective | |

component is enabled for writing. | |

Otherwise, the register transfer level descriptions mimic ANSI C | |

syntax. | |

The idiom "IEEE(expression)" represents the s23e8 single-precision | |

result of the expression if evaluated using IEEE single-precision | |

floating point operations. The IEEE idiom is used to specify the | |

maximum allowed deviation from IEEE single-precision floating-point | |

arithmetic results. | |

The following abbreviations are also used: | |

+Inf floating-point representation of positive infinity | |

-Inf floating-point representation of negative infinity | |

+NaN floating-point representation of positive not a number | |

-NaN floating-point representation of negative not a number | |

NA not applicable or not used | |

2.14.1.10.1 ARL: Address Register Load | |

The ARL instruction moves value of the source scalar into the address | |

register. Conceptually, the address register load instruction is | |

a 4-component vector signed integer register, but the only valid | |

address register component for writing and indexing is the x | |

component. The only use for A0.x is as a base address for program | |

parameter reads. The source value is a float that is truncated | |

towards negative infinity into a signed integer. | |

t.x = source0.c; | |

if (negate0) t.x = -t.x; | |

A0.x = floor(t.x); | |

2.14.1.10.2 MOV: Move | |

The MOV instruction moves the value of the source vector into the | |

destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

if (xmask) destination.x = t.x; | |

if (ymask) destination.y = t.y; | |

if (zmask) destination.z = t.z; | |

if (wmask) destination.w = t.w; | |

2.14.1.10.3 MUL: Multiply | |

The MUL instruction multiplies the values of the two source vectors | |

into the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = t.x * u.x; | |

if (ymask) destination.y = t.y * u.y; | |

if (zmask) destination.z = t.z * u.z; | |

if (wmask) destination.w = t.w * u.w; | |

2.14.1.10.4 ADD: Add | |

The ADD instruction adds the values of the two source vectors into | |

the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = t.x + u.x; | |

if (ymask) destination.y = t.y + u.y; | |

if (zmask) destination.z = t.z + u.z; | |

if (wmask) destination.w = t.w + u.w; | |

2.14.1.10.5 MAD: Multiply and Add | |

The MAD instruction adds the value of the third source vector to the | |

product of the values of the first and second two source vectors, | |

writing the result to the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

v.x = source2.c***; | |

v.y = source2.*c**; | |

v.z = source2.**c*; | |

v.w = source2.***c; | |

if (negate2) { | |

v.x = -v.x; | |

v.y = -v.y; | |

v.z = -v.z; | |

v.w = -v.w; | |

} | |

if (xmask) destination.x = t.x * u.x + v.x; | |

if (ymask) destination.y = t.y * u.y + v.y; | |

if (zmask) destination.z = t.z * u.z + v.z; | |

if (wmask) destination.w = t.w * u.w + v.w; | |

2.14.1.10.6 RCP: Reciprocal | |

The RCP instruction inverts the value of the source scalar into | |

the destination register. The reciprocal of exactly 1.0 must be | |

exactly 1.0. | |

Additionally the reciprocal of negative infinity gives [-0.0, -0.0, | |

-0.0, -0.0]; the reciprocal of negative zero gives [-Inf, -Inf, -Inf, | |

-Inf]; the reciprocal of positive zero gives [+Inf, +Inf, +Inf, +Inf]; | |

and the reciprocal of positive infinity gives [0.0, 0.0, 0.0, 0.0]. | |

t.x = source0.c; | |

if (negate0) { | |

t.x = -t.x; | |

} | |

if (t.x == 1.0f) { | |

u.x = 1.0f; | |

} else { | |

u.x = 1.0f / t.x; | |

} | |

if (xmask) destination.x = u.x; | |

if (ymask) destination.y = u.x; | |

if (zmask) destination.z = u.x; | |

if (wmask) destination.w = u.x; | |

where | |

| u.x - IEEE(1.0f/t.x) | < 1.0f/(2^22) | |

for 1.0f <= t.x <= 2.0f. The intent of this precision requirement is | |

that this amount of relative precision apply over all values of t.x. | |

2.14.1.10.7 RSQ: Reciprocal Square Root | |

The RSQ instruction assigns the inverse square root of the | |

absolute value of the source scalar into the destination register. | |

Additionally, RSQ(0.0) gives [+Inf, +Inf, +Inf, +Inf]; and both | |

RSQ(+Inf) and RSQ(-Inf) give [0.0, 0.0, 0.0, 0.0]; | |

t.x = source0.c; | |

if (negate0) { | |

t.x = -t.x; | |

} | |

u.x = 1.0f / sqrt(fabs(t.x)); | |

if (xmask) destination.x = u.x; | |

if (ymask) destination.y = u.x; | |

if (zmask) destination.z = u.x; | |

if (wmask) destination.w = u.x; | |

where | |

| u.x - IEEE(1.0f/sqrt(fabs(t.x))) | < 1.0f/(2^22) | |

for 1.0f <= t.x <= 4.0f. The intent of this precision requirement is | |

that this amount of relative precision apply over all values of t.x. | |

2.14.1.10.8 DP3: Three-Component Dot Product | |

The DP3 instruction assigns the three-component dot product of the | |

two source vectors into the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

} | |

v.x = t.x * u.x + t.y * u.y + t.z * u.z; | |

if (xmask) destination.x = v.x; | |

if (ymask) destination.y = v.x; | |

if (zmask) destination.z = v.x; | |

if (wmask) destination.w = v.x; | |

2.14.1.10.9 DP4: Four-Component Dot Product | |

The DP4 instruction assigns the four-component dot product of the | |

two source vectors into the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

v.x = t.x * u.x + t.y * u.y + t.z * u.z + t.w * u.w; | |

if (xmask) destination.x = v.x; | |

if (ymask) destination.y = v.x; | |

if (zmask) destination.z = v.x; | |

if (wmask) destination.w = v.x; | |

2.14.1.10.10 DST: Distance Vector | |

The DST instructions calculates a distance vector for the values | |

of two source vectors. The first vector is assumed to be [NA, d*d, | |

d*d, NA] and the second source vector is assumed to be [NA, 1.0/d, | |

NA, 1.0/d], where the value of a component labeled NA is undefined. | |

The destination vector is then assigned [1,d,d*d,1.0/d]. | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

if (negate0) { | |

t.y = -t.y; | |

t.z = -t.z; | |

} | |

u.y = source1.*c**; | |

u.w = source1.***c; | |

if (negate1) { | |

u.y = -u.y; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = 1.0; | |

if (ymask) destination.y = t.y*u.y; | |

if (zmask) destination.z = t.z; | |

if (wmask) destination.w = u.w; | |

2.14.1.10.11 MIN: Minimum | |

The MIN instruction assigns the component-wise minimum of the two | |

source vectors into the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = (t.x < u.x) ? t.x : u.x; | |

if (ymask) destination.y = (t.y < u.y) ? t.y : u.y; | |

if (zmask) destination.z = (t.z < u.z) ? t.z : u.z; | |

if (wmask) destination.w = (t.w < u.w) ? t.w : u.w; | |

2.14.1.10.12 MAX: Maximum | |

The MAX instruction assigns the component-wise maximum of the two | |

source vectors into the destination register. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = (t.x >= u.x) ? t.x : u.x; | |

if (ymask) destination.y = (t.y >= u.y) ? t.y : u.y; | |

if (zmask) destination.z = (t.z >= u.z) ? t.z : u.z; | |

if (wmask) destination.w = (t.w >= u.w) ? t.w : u.w; | |

2.14.1.10.13 SLT: Set On Less Than | |

The SLT instruction performs a component-wise assignment of either | |

1.0 or 0.0 into the destination register. 1.0 is assigned if the | |

value of the first source vector is less than the value of the second | |

source vector; otherwise, 0.0 is assigned. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = (t.x < u.x) ? 1.0 : 0.0; | |

if (ymask) destination.y = (t.y < u.y) ? 1.0 : 0.0; | |

if (zmask) destination.z = (t.z < u.z) ? 1.0 : 0.0; | |

if (wmask) destination.w = (t.w < u.w) ? 1.0 : 0.0; | |

2.14.1.10.14 SGE: Set On Greater or Equal Than | |

The SGE instruction performs a component-wise assignment of either | |

1.0 or 0.0 into the destination register. 1.0 is assigned if the | |

value of the first source vector is greater than or equal the value | |

of the second source vector; otherwise, 0.0 is assigned. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.z = source0.**c*; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.z = -t.z; | |

t.w = -t.w; | |

} | |

u.x = source1.c***; | |

u.y = source1.*c**; | |

u.z = source1.**c*; | |

u.w = source1.***c; | |

if (negate1) { | |

u.x = -u.x; | |

u.y = -u.y; | |

u.z = -u.z; | |

u.w = -u.w; | |

} | |

if (xmask) destination.x = (t.x >= u.x) ? 1.0 : 0.0; | |

if (ymask) destination.y = (t.y >= u.y) ? 1.0 : 0.0; | |

if (zmask) destination.z = (t.z >= u.z) ? 1.0 : 0.0; | |

if (wmask) destination.w = (t.w >= u.w) ? 1.0 : 0.0; | |

2.14.1.10.15 EXP: Exponential Base 2 | |

The EXP instruction generates an approximation of the exponential base | |

2 for the value of a source scalar. This approximation is assigned | |

to the z component of the destination register. Additionally, | |

the x and y components of the destination register are assigned | |

values useful for determining a more accurate approximation. The | |

exponential base 2 of the source scalar can be better approximated | |

by destination.x*FUNC(destination.y) where FUNC is some user | |

approximation (presumably implemented by subsequent instructions in | |

the vertex program) to 2^destination.y where 0.0 <= destination.y < | |

1.0. | |

Additionally, EXP(-Inf) or if the exponential result underflows | |

gives [0.0, 0.0, 0.0, 1.0]; and EXP(+Inf) or if the exponential result | |

overflows gives [+Inf, 0.0, +Inf, 1.0]. | |

t.x = source0.c; | |

if (negate0) { | |

t.x = -t.x; | |

} | |

q.x = 2^floor(t.x); | |

q.y = t.x - floor(t.x); | |

q.z = q.x * APPX(q.y); | |

if (xmask) destination.x = q.x; | |

if (ymask) destination.y = q.y; | |

if (zmask) destination.z = q.z; | |

if (wmask) destination.w = 1.0; | |

where APPX is an implementation dependent approximation of exponential | |

base 2 such that | |

| exp(q.y*log(2.0))-APPX(q.y) | < 1/(2^11) | |

for all 0 <= q.y < 1.0. | |

The expression "2^floor(t.x)" should overflow to +Inf and underflow | |

to zero. | |

2.14.1.10.16 LOG: Logarithm Base 2 | |

The LOG instruction generates an approximation of the logarithm base | |

2 for the absolute value of a source scalar. This approximation | |

is assigned to the z component of the destination register. | |

Additionally, the x and y components of the destination register are | |

assigned values useful for determining a more accurate approximation. | |

The logarithm base 2 of the absolute value of the source scalar | |

can be better approximated by destination.x+FUNC(destination.y) | |

where FUNC is some user approximation (presumably implemented by | |

subsequent instructions in the vertex program) of log2(destination.y) | |

where 1.0 <= destination.y < 2.0. | |

Additionally, LOG(0.0) gives [-Inf, 1.0, -Inf, 1.0]; and both | |

LOG(+Inf) and LOG(-Inf) give [+Inf, 1.0, +Inf, 1.0]. | |

t.x = source0.c; | |

if (negate0) { | |

t.x = -t.x; | |

} | |

if (fabs(t.x) != 0.0f) { | |

if (fabs(t.x) == +Inf) { | |

q.x = +Inf; | |

q.y = 1.0; | |

q.z = +Inf; | |

} else { | |

q.x = Exponent(t.x); | |

q.y = Mantissa(t.x); | |

q.z = q.x + APPX(q.y); | |

} | |

} else { | |

q.x = -Inf; | |

q.y = 1.0; | |

q.z = -Inf; | |

} | |

if (xmask) destination.x = q.x; | |

if (ymask) destination.y = q.y; | |

if (zmask) destination.z = q.z; | |

if (wmask) destination.w = 1.0; | |

where APPX is an implementation dependent approximation of logarithm | |

base 2 such that | |

| log(q.y)/log(2.0) - APPX(q.y) | < 1/(2^11) | |

for all 1.0 <= q.y < 2.0. | |

The "Exponent(t.x)" function returns the unbiased exponent between | |

-126 and 127. For example, "Exponent(1.0)" equals 0.0. (Note that | |

the IEEE floating-point representation maintains the exponent as a | |

biased value.) Larger or smaller exponents should generate +Inf or | |

-Inf respectively. The "Mantissa(t.x)" function returns a value | |

in the range [1.0f, 2.0). The intent of these functions is that | |

fabs(t.x) is approximately "Mantissa(t.x)*2^Exponent(t.x)". | |

2.14.1.10.17 LIT: Light Coefficients | |

The LIT instruction is intended to compute ambient, diffuse, | |

and specular lighting coefficients from a diffuse dot product, | |

a specular dot product, and a specular power that is clamped to | |

(-128,128) exclusive. The x component of the source vector is | |

assumed to contain a diffuse dot product (unit normal vector dotted | |

with a unit light vector). The y component of the source vector is | |

assumed to contain a Blinn specular dot product (unit normal vector | |

dotted with a unit half-angle vector). The w component is assumed | |

to contain a specular power. | |

An implementation must support at least 8 fraction bits in the | |

specular power. Note that because 0.0 times anything must be 0.0, | |

taking any base to the power of 0.0 will yield 1.0. | |

t.x = source0.c***; | |

t.y = source0.*c**; | |

t.w = source0.***c; | |

if (negate0) { | |

t.x = -t.x; | |

t.y = -t.y; | |

t.w = -t.w; | |

} | |

if (t.w < -(128.0-epsilon)) t.w = -(128.0-epsilon); | |

else if (t.w > 128-epsilon) t.w = 128-epsilon; | |

if (t.x < 0.0) t.x = 0.0; | |

if (t.y < 0.0) t.y = 0.0; | |

if (xmask) destination.x = 1.0; | |

if (ymask) destination.y = t.x; | |

if (zmask) destination.z = (t.x > 0.0) ? EXP(t.w*LOG(t.y)) : 0.0; | |

if (wmask) destination.w = 1.0; | |

where EXP and LOG are functions that approximate the exponential base | |

2 and logarithm base 2 with the identical accuracy and special case | |

requirements of the EXP and LOG instructions. epsilon is 1.0/256.0 | |

or approximately 0.0039 which would correspond to representing the | |

specular power with a s8.8 representation. | |

2.14.1.11 Vertex Program Floating Point Requirements | |

All vertex program calculations are assumed to use IEEE single | |

precision floating-point math with a format of s1e8m23 (one signed | |

bit, 8 bits of exponent, 23 bits of magnitude) or better and the | |

round-to-zero rounding mode. The only exceptions to this are the RCP, | |

RSQ, LOG, EXP, and LIT instructions. | |

Note that (positive or negative) 0.0 times anything is (positive) | |

0.0. | |

The RCP and RSQ instructions deliver results accurate to 1.0/(2^22) | |

and the approximate output (the z component) of the EXP and LOG | |

instructions only has to be accurate to 1.0/(2^11). The LIT | |

instruction specular output (the z component) is allowed an error | |

equivalent to the combination of the EXP and LOG combination to | |

implement a power function. | |

The floor operations used by the ARL and EXP instructions must | |

operate identically. Specifically, the EXP instruction's floor(t.x) | |

intermediate result must exactly match the integer stored in the | |

address register by the ARL instruction. | |

Since distance is calculated as (d^2)*(1/sqrt(d^2)), 0.0 multiplied | |

by anything must be 0.0. This affects the MUL, MAD, DP3, DP4, DST, | |

and LIT instructions. | |

Because if/then/else conditional evaluation is done by multiplying | |

by 1.0 or 0.0 and adding, the floating point computations require: | |

0.0 * x = 0.0 for all x (including +Inf, -Inf, +NaN, and -NaN) | |

1.0 * x = x for all x (including +Inf and -Inf) | |

0.0 + x = x for all x (including +Inf and -Inf) | |

Including +Inf, -Inf, +NaN, and -NaN when applying the above three | |

rules is recommended but not required. (The recommended inclusion | |

of +Inf, -Inf, +NaN, and -NaN when applying the first rule is | |

inconsistent with IEEE floating-point requirements.) | |

For the purpose of comparisons performed by the SGE and SLT | |

instructions, -0.0 is less than +0.0, -NaN is less than -Inf, | |

and +NaN is greater than +Inf. (This is inconsistent with IEEE | |

floating-point requirements). | |

No floating-point exceptions or interrupts are generated. Denorms | |

are not supported; if a denorm is input, it is treated as 0.0 (ie, | |

denorms are flushed to zero). | |

Computations involving +NaN or -NaN generate +NaN, except for the | |

requirement that zero times +NaN or -NaN must always be zero. (This | |

exception is inconsistent with IEEE floating-point requirements). | |

2.14.2 Vertex Program Update for the Current Raster Position | |

When vertex programs are enabled, the raster position is determined | |

by the current vertex program. The raster position specified by | |

RasterPos is treated as if they were specified in a Vertex command. | |

The contents of vertex result register set is used to update respective | |

raster position state. | |

Assuming an existent program, the homogeneous clip-space coordinates | |

are passed to clipping as if they represented a point and assuming no | |

client-defined clip planes are enabled. If the point is not culled, | |

then the projection to window coordinates is computed (section 2.10) | |

and saved as the current raster position and the valid bit is set. | |

If the current vertex program is nonexistent or the "point" is | |

culled, the current raster position and its associated data become | |

indeterminate and the raster position valid bit is cleared. | |

2.14.3 Vertex Arrays for Vertex Attributes | |

Data for vertex attributes in vertex program mode may be specified | |

using vertex array commands. The client may specify and enable any | |

of sixteen vertex attribute arrays. | |

The vertex attribute arrays are ignored when vertex program mode | |

is disabled. When vertex program mode is enabled, vertex attribute | |

arrays are used. | |

The command | |

void VertexAttribPointerNV(uint index, int size, enum type, | |

sizei stride, const void *pointer); | |

describes the locations and organizations of the sixteen vertex | |

attribute arrays. index specifies the particular vertex attribute | |

to be described. size indicates the number of values per vertex | |

that are stored in the array; size must be one of 1, 2, 3, or 4. | |

type specifies the data type of the values stored in the array. | |

type must be one of SHORT, FLOAT, DOUBLE, or UNSIGNED_BYTE and these | |

values correspond to the array types short, int, float, double, and | |

ubyte respectively. The INVALID_OPERATION error is generated if | |

type is UNSIGNED_BYTE and size is not 4. The INVALID_VALUE error | |

is generated if index is greater than 15. The INVALID_VALUE error | |

is generated if stride is negative. | |

The one, two, three, or four values in an array that correspond to a | |

single vertex attribute comprise an array element. The values within | |

each array element at stored sequentially in memory. If the stride | |

is specified as zero, then array elements are stored sequentially | |

as well. Otherwise points to the ith and (i+1)st elements of an array | |

differ by stride basic machine units (typically unsigned bytes), | |

the pointer to the (i+1)st element being greater. pointer specifies | |

the location in memory of the first value of the first element of | |

the array being specified. | |

Vertex attribute arrays are enabled with the EnableClientState command | |

and disabled with the DisableClientState command. The value of the | |

argument to either command is VERTEX_ATTRIB_ARRAYi_NV where i is an | |

integer between 0 and 15; specifying a value of i enables or | |

disables the vertex attribute array with index i. The constants | |

obey VERTEX_ATTRIB_ARRAYi_NV = VERTEX_ATTRIB_ARRAY0_NV + i. | |

When vertex program mode is enabled, the ArrayElement command operates | |

as described in this section in contrast to the behavior described | |

in section 2.8. Likewise, any vertex array transfer commands that | |

are defined in terms of ArrayElement (DrawArrays, DrawElements, and | |

DrawRangeElements) assume the operation of ArrayElement described | |

in this section when vertex program mode is enabled. | |

When vertex program mode is enabled, the ArrayElement command | |

transfers the ith element of particular enabled vertex arrays as | |

described below. For each enabled vertex attribute array, it is | |

as though the corresponding command from section 2.14.1.1 were | |

called with a pointer to element i. For each vertex attribute, | |

the corresponding command is VertexAttrib[size][type]v, where size | |

is one of [1,2,3,4], and type is one of [s,f,d,ub], corresponding | |

to the array types short, int, float, double, and ubyte respectively. | |

However, if a given vertex attribute array is disabled, but its | |

corresponding aliased conventional per-vertex parameter's vertex | |

array (as described in section 2.14.1.6) is enabled, then it is | |

as though the corresponding command from section 2.7 or section | |

2.6.2 were called with a pointer to element i. In this case, the | |

corresponding command is determined as described in section 2.8's | |

description of ArrayElement. | |

If the vertex attribute array 0 is enabled, it is as though | |

VertexAttrib[size][type]v(0, ...) is executed last, after the | |

executions of other corresponding commands. If the vertex attribute | |

array 0 is disabled but the vertex array is enabled, it is as though | |

Vertex[size][type]v is executed last, after the executions of other | |

corresponding commands. | |

2.14.4 Vertex State Programs | |

Vertex state programs share the same instruction set as and a similar | |

execution model to vertex programs. While vertex program are executed | |

implicitly when a vertex transformation is provoked, vertex state | |

programs are executed explicitly, independently of any vertices. | |

Vertex state programs can write program parameter registers, but | |

may not write vertex result registers. | |

The purpose of a vertex state program is to update program parameter | |

registers by means of an application-defined program. Typically, | |

an application will load a set of program parameters and then execute | |

a vertex state program that reads and updates the program parameter | |

registers. For example, a vertex state program might normalize a | |

set of unnormalized vectors previously loaded as program parameters. | |

The expectation is that subsequently executed vertex programs would | |

use the normalized program parameters. | |

Vertex state programs are loaded with the same LoadProgramNV command | |

(see section 2.14.1.7) used to load vertex programs except that the | |

target must be VERTEX_STATE_PROGRAM_NV when loading a vertex state | |

program. | |

Vertex state programs must conform to a more limited grammar than | |

the grammar for vertex programs. The vertex state program grammar | |

for syntactically valid sequences is the same as the grammar defined | |

in section 2.14.1.7 with the following modified rules: | |

<program> ::= "!!VSP1.0" <instructionSequence> "END" | |

<dstReg> ::= <absProgParamReg> | |

| <temporaryReg> | |

<vertexAttribReg> ::= "v" "[" "0" "]" | |

A vertex state program fails to load if it does not write at least | |

one program parameter register. | |

A vertex state program fails to load if it contains more than 128 | |

instructions. | |

A vertex state program fails to load if any instruction sources more | |

than one unique program parameter register. | |

A vertex state program fails to load if any instruction sources | |

more than one unique vertex attribute register (this is necessarily | |

true because only vertex attribute 0 is available in vertex state | |

programs). | |

The error INVALID_OPERATION is generated if a vertex state program | |

fails to load because it is not syntactically correct or for one | |

of the other reasons listed above. | |

A successfully loaded vertex state 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 2.14.1.10. | |

Executing vertex state programs is legal only outside a Begin/End | |

pair. A vertex state program may not read any vertex attribute | |

register other than register zero. A vertex state program may not | |

write any vertex result register. | |

The command | |

ExecuteProgramNV(enum target, uint id, const float *params); | |

executes the vertex state program named by id. The target must be | |

VERTEX_STATE_PROGRAM_NV and the id must be the name of program loaded | |

with a target type of VERTEX_STATE_PROGRAM_NV. params points to | |

an array of four floating-point values that are loaded into vertex | |

attribute register zero (the only vertex attribute readable from a | |

vertex state program). | |

The INVALID_OPERATION error is generated if the named program is | |

nonexistent, is invalid, or the program is not a vertex state | |

program. A vertex state program may not be valid for reasons | |

explained in section 2.14.5. | |

2.14.5 Tracking Matrices | |

As a convenience to applications, standard GL matrix state can be | |

tracked into program parameter vectors. This permits vertex programs | |

to access matrices specified through GL matrix commands. | |

In addition to GL's conventional matrices, several additional matrices | |

are available for tracking. These matrices have names of the form | |

MATRIXi_NV where i is between zero and n-1 where n is the value | |

of the MAX_TRACK_MATRICES_NV implementation dependent constant. | |

The MATRIXi_NV constants obey MATRIXi_NV = MATRIX0_NV + i. The value | |

of MAX_TRACK_MATRICES_NV must be at least eight. The maximum | |

stack depth for tracking matrices is defined by the | |

MAX_TRACK_MATRIX_STACK_DEPTH_NV and must be at least 1. | |

The command | |

TrackMatrixNV(enum target, uint address, enum matrix, enum transform); | |

tracks a given transformed version of a particular matrix into | |

a contiguous sequence of four vertex program parameter registers | |

beginning at address. target must be VERTEX_PROGRAM_NV (though | |

tracked matrices apply to vertex state programs as well because both | |

vertex state programs and vertex programs shared the same program | |

parameter registers). matrix must be one of NONE, MODELVIEW, | |

PROJECTION, TEXTURE, TEXTUREi_ARB (where i is between 0 and n-1 | |

where n is the number of texture units supported), COLOR (if | |

the ARB_imaging subset is supported), MODELVIEW_PROJECTION_NV, | |

or MATRIXi_NV. transform must be one of IDENTITY_NV, INVERSE_NV, | |

TRANSPOSE_NV, or INVERSE_TRANSPOSE_NV. The INVALID_VALUE error is | |

generated if address is not a multiple of four. | |

The MODELVIEW_PROJECTION_NV matrix represents the concatenation of | |

the current modelview and projection matrices. If M is the current | |

modelview matrix and P is the current projection matrix, then the | |

MODELVIEW_PROJECTION_NV matrix is C and computed as | |

C = P M | |

Matrix tracking for the specified program parameter register and the | |

next consecutive three registers is disabled when NONE is supplied | |

for matrix. When tracking is disabled the previously tracked program | |

parameter registers retain the state of their last tracked values. | |

Otherwise, the specified transformed version of matrix is tracked into | |

the specified program parameter register and the next three registers. | |

Whenever the matrix changes, the transformed version of the matrix | |

is updated in the specified range of program parameter registers. | |

If TEXTURE is specified for matrix, the texture matrix for the current | |

active texture unit is tracked. If TEXTUREi_ARB is specified for | |

matrix, the <i>th texture matrix is tracked. | |

Matrices are tracked row-wise meaning that the top row of the | |

transformed matrix is loaded into the program parameter address, | |

the second from the top row of the transformed matrix is loaded into | |

the program parameter address+1, the third from the top row of the | |

transformed matrix is loaded into the program parameter address+2, | |

and the bottom row of the transformed matrix is loaded into the | |

program parameter address+3. The transformed matrix may be identical | |

to the specified matrix, the inverse of the specified matrix, the | |

transpose of the specified matrix, or the inverse transpose of the | |

specified matrix, depending on the value of transform. | |

When matrix tracking is enabled for a particular program parameter | |

register sequence, updates to the program parameter using | |

ProgramParameterNV commands, a vertex program, or a vertex state | |

program are not possible. The INVALID_OPERATION error is generated | |

if a ProgramParameterNV command is used to update a program parameter | |

register currently tracking a matrix. | |

The INVALID_OPERATION error is generated by ExecuteProgramNV when | |

the vertex state program requested for execution writes to a program | |

parameter register that is currently tracking a matrix because the | |

program is considered invalid. | |

2.14.6 Required Vertex Program State | |

The state required for vertex programs consists of: | |

a bit indicating whether or not program mode is enabled; | |

a bit indicating whether or not two-sided color mode is enabled; | |

a bit indicating whether or not program-specified point size mode | |

is enabled; | |

96 4-component floating-point program parameter registers; | |

16 4-component vertex attribute registers (though this state is | |

aliased with the current normal, primary color, secondary color, | |

fog coordinate, weights, and texture coordinate sets); | |

24 sets of matrix tracking state for each set of four sequential | |

program parameter registers, consisting of a n-valued integer | |

indicated the tracked matrix or GL_NONE (where n is 5 + the number | |

of texture units supported + the number of tracking matrices | |

supported) and a four-valued integer indicating the transformation | |

of the tracked matrix; | |

an unsigned integer naming the currently bound vertex program | |

and the state must be maintained to indicate which integers | |

are currently in use as program names. | |

Each existent program object consists of a target, a boolean indicating | |

whether the program is resident, an array of type ubyte containing the | |

program string, and the length of the program string array. Initially, | |

no program objects exist. | |

Program mode, two-sided color mode, and program-specified point size | |

mode are all initially disabled. | |

The initial state of all 96 program parameter registers is (0,0,0,0). | |

The initial state of the 16 vertex attribute registers is (0,0,0,1) | |

except in cases where a vertex attribute register aliases to a | |

conventional GL transform mode vertex parameter in which case | |

the initial state is the initial state of the respective aliased | |

conventional vertex parameter. | |

The initial state of the 24 sets of matrix tracking state is NONE | |

for the tracked matrix and IDENTITY_NV for the transformation of the | |

tracked matrix. | |

The initial currently bound program is zero. | |

The client state required to implement the 16 vertex attribute | |

arrays consists of 16 boolean values, 16 memory pointers, 16 integer | |

stride values, 16 symbolic constants representing array types, | |

and 16 integers representing values per element. Initially, the | |

boolean values are each disabled, the memory pointers are each null, | |

the strides are each zero, the array types are each FLOAT, and the | |

integers representing values per element are each four." | |

Additions to Chapter 3 of the OpenGL 1.2.1 Specification (Rasterization) | |

-- Section 3.3 "Points" | |

Change the first paragraph to read: | |

"When program vertex mode is disabled, the point size for rasterizing | |

points is controlled with | |

void PointSize(float size); | |

size specifies the width or diameter of a point. The initial point size | |

value is 1.0. A value less than or equal to zero results in the error | |

INVALID_VALUE. When vertex program mode is enabled, the point size for | |

rasterizing points is determined as described in section 2.14.1.5." | |

-- Section 3.9 "Color Sum" | |

Change the first paragraph to read: | |

"At the beginning of color sum, a fragment has two RGBA colors: a | |

primary color cpri (which texturing, if enabled, may have modified) | |

and a secondary color csec. If vertex program mode is disabled, csec | |

is defined by the lighting equations in section 2.13.1. If vertex | |

program mode is enabled, csec is the fragment's secondary color, | |

obtained by interpolating the COL1 (or BFC1 if the primitive is a | |

polygon, the vertex program two-sided color mode is enabled, and the | |

polygon is back-facing) vertex result register RGB components for the | |

vertices making up the primitive; the alpha component of csec when | |

program mode is enabled is always zero. The components of these two | |

colors are summed to produce a single post-texturing RGBA color c. | |

The components of c are then clamped to the range [0,1]." | |

-- Section 3.10 "Fog" | |

Change the initial sentences in the second paragraph to read: | |

"This factor f may be computed according to one of three equations: | |

f = exp(-d*c) (3.24) | |

f = exp(-(d*c)^2) (3.25) | |

f = (e-c)/(e-s) (3.26) | |

If vertex program mode is enabled, then c is the fragment's fog | |

coordinate, obtained by interpolating the FOGC vertex result register | |

values for the vertices making up the primitive. When vertex program | |

mode is disabled, the c is the eye-coordinate distance from the eye, | |

(0,0,0,1) in eye-coordinates, to the fragment center." ... | |

Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment | |

Operations and the Framebuffer) | |

None | |

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

-- Section 5.1 "Evaluators" | |

Add the following lines to the end of table 5.1 (page 165): | |

target k values | |

------------------------- --- ------------------------------ | |

MAP1_VERTEX_ATTRIB0_4_NV 4 x, y, z, w vertex attribute 0 | |

MAP1_VERTEX_ATTRIB1_4_NV 4 x, y, z, w vertex attribute 1 | |

MAP1_VERTEX_ATTRIB2_4_NV 4 x, y, z, w vertex attribute 2 | |

MAP1_VERTEX_ATTRIB3_4_NV 4 x, y, z, w vertex attribute 3 | |

MAP1_VERTEX_ATTRIB4_4_NV 4 x, y, z, w vertex attribute 4 | |

MAP1_VERTEX_ATTRIB5_4_NV 4 x, y, z, w vertex attribute 5 | |

MAP1_VERTEX_ATTRIB6_4_NV 4 x, y, z, w vertex attribute 6 | |

MAP1_VERTEX_ATTRIB7_4_NV 4 x, y, z, w vertex attribute 7 | |

MAP1_VERTEX_ATTRIB8_4_NV 4 x, y, z, w vertex attribute 8 | |

MAP1_VERTEX_ATTRIB9_4_NV 4 x, y, z, w vertex attribute 9 | |

MAP1_VERTEX_ATTRIB10_4_NV 4 x, y, z, w vertex attribute 10 | |

MAP1_VERTEX_ATTRIB11_4_NV 4 x, y, z, w vertex attribute 11 | |

MAP1_VERTEX_ATTRIB12_4_NV 4 x, y, z, w vertex attribute 12 | |

MAP1_VERTEX_ATTRIB13_4_NV 4 x, y, z, w vertex attribute 13 | |

MAP1_VERTEX_ATTRIB14_4_NV 4 x, y, z, w vertex attribute 14 | |

MAP1_VERTEX_ATTRIB15_4_NV 4 x, y, z, w vertex attribute 15 | |

Replace the four paragraphs on pages 167-168 that explain the | |

operation of EvalCoord: | |

"EvalCoord operates differently depending on whether vertex program | |

mode is enabled or not. We first discuss how EvalCoord operates when | |

vertex program mode is disabled. | |

When one of the EvalCoord commands is issued and vertex program | |

mode is disabled, all currently enabled maps (excluding the | |

maps that correspond to vertex attributes, i.e. maps of the form | |

MAPx_VERTEX_ATTRIBn_4_NV). ..." | |

Add a paragraph before the initial paragraph discussing AUTO_NORMAL: | |

"When one of the EvalCoord commands is issued and vertex program mode | |

is enabled, the evaluation and the issuing of per-vertex parameter commands | |

matches the discussion above, except that if any vertex attribute | |

maps are enabled, the corresponding VertexAttribNV call for each enabled | |

vertex attribute map is issued with the map's evaluated coordinates | |

and the corresponding aliased per-vertex parameter map is ignored | |

if it is also enabled, with one important difference. As is the case when | |

vertex program mode is disabled, the GL uses evaluated values | |

instead of current values for those evaluations that are enabled | |

(otherwise the current values are used). The order of the effective | |

commands is immaterial, except that Vertex or VertexAttribNV(0, | |

...) (the commands that issue provoke vertex program execution) | |

must be issued last. Use of evaluators has no effect on the current | |

vertex attributes or conventional per-vertex parameters. If a | |

vertex attribute map is disabled, but its corresponding conventional | |

per-vertex parameter map is enabled, the conventional per-vertex | |

parameter map is evaluated and issued as when vertex program mode | |

is not enabled." | |

Replace the two paragraphs discussing AUTO_NORMAL with: | |

"Finally, if either MAP2_VERTEX_3 or MAP2_VERTEX_4 is enabled or if | |

both MAP2_VERTEX_ATTRIB0_4_NV and vertex program mode are enabled, | |

then the normal to the surface is computed. Analytic computation, | |

which sometimes yields normals of length zero, is one method which | |

may be used. If automatic normal generation is enabled, then this | |

computed normal is used as the normal associated with a generated | |

vertex (when program mode is disabled) or as vertex attribute 2 | |

(when vertex program mode is enabled). Automatic normal generation | |

is controlled with Enable and Disable with the symbolic constant | |

AUTO_NORMAL. If automatic normal generation is disabled and vertex | |

program mode is enabled, then vertex attribute 2 is evaluated | |

as usual. If automatic normal generation and vertex program mode | |

are disabled, then a corresponding normal map, if enabled, is used | |

to produce a normal. If neither automatic normal generation nor | |

a map corresponding to the normal per-vertex parameter (or vertex | |

attribute 2 in program mode) are enabled, then no normal is sent with | |

a vertex resulting from an evaluation (the effect is that the current | |

normal is used). For MAP_VERTEX3, let q=p. For MAP_VERTEX_4 or | |

MAP2_VERTEX_ATTRBI0_4_NV, let q = (x/w, y/w, z/w) where (x,y,z,w)=p. | |

Then let | |

m = (partial q / partial u) cross (partial q / partial v) | |

Then when vertex program mode is disabled, the generated analytic | |

normal, n, is given by n=m/||m||. However, when vertex program mode | |

is enabled, the generated analytic normal used for vertex attribute | |

2 is simply (mx,my,mz,1). In vertex program mode, the normalization | |

of the generated analytic normal can be performed by the current | |

vertex program." | |

Change the respective sentences of the last paragraph discussing | |

required evaluator state to read: | |

"The state required for evaluators potentially consists of 9 | |

conventional one-dimensional map specifications, 16 vertex attribute | |

one-dimensional map specifications, 9 conventional two-dimensional | |

map specifications, and 16 vertex attribute two-dimensional map | |

specifications indicating which are enabled. ... All vertex | |

coordinate maps produce the coordinates (0,0,0,1) (or the appropriate | |

subset); all normal coordinate maps produce (0,0,1); RGBA maps produce | |

(1,1,1,1); color index maps produce 1.0; texture coordinate maps | |

produce (0,0,0,1); and vertex attribute maps produce (0,0,0,1). ... | |

If any evaluation command is issued when none of MAPn_VERTEX_3, | |

MAPn_VERTEX_4, or MAPn_VERTEX_ATTRIB0_NV (where n is the map dimension | |

being evaluated) are enabled, nothing happens." | |

-- Section 5.4 "Display Lists" | |

Add to the list of commands not compiled into display lists in the | |

third to the last paragraph: | |

"AreProgramsResidentNV, IsProgramNV, GenProgramsNV, DeleteProgramsNV, | |

VertexAttribPointerNV" | |

Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and | |

State Requests) | |

-- Section 6.1.12 "Saving and Restoring State" | |

Only the enables and vertex array state introduced by this extension | |

can be pushed and popped. | |

See the attribute column in table X.5 for determining what vertex | |

program state can be pushed and popped with PushAttrib, PopAttrib, | |

PushClientAttrib, and PopClientAttrib. | |

The new evaluator enables in table 6.22 can also be pushed and | |

popped. | |

-- NEW Section 6.1.13 "Vertex Program Queries" | |

"The commands | |

void GetProgramParameterfvNV(enum target, uint index, | |

enum pname, float *params); | |

void GetProgramParameterdvNV(enum target, uint index, | |

enum pname, double *params); | |

obtain the current program parameters for the given program | |

target and parameter index into the array params. target must | |

be VERTEX_PROGRAM_NV. pname must be PROGRAM_PARAMETER_NV. | |

The INVALID_VALUE error is generated if index is greater than 95. | |

Each program parameter is an array of four values. | |

The command | |

void GetProgramivNV(uint id, enum pname, int *params); | |

obtains program state named by pname for the program named id | |

in the array params. pname must be one of PROGRAM_TARGET_NV, | |

PROGRAM_LENGTH_NV, or PROGRAM_RESIDENT_NV. The INVALID_OPERATION | |

error is generated if the program named id does not exist. | |

The command | |

void GetProgramStringNV(uint id, enum pname, | |

ubyte *program); | |

obtains the program string for program id. pname must be | |

PROGRAM_STRING_NV. n ubytes are returned into the array program | |

where n is the length of the program in ubytes. GetProgramivNV with | |

PROGRAM_LENGTH_NV can be used to query the length of a program's | |

string. The INVALID_OPERATION error is generated if the program | |

named id does not exist. | |

The command | |

void GetTrackMatrixivNV(enum target, uint address, | |

enum pname, int *params); | |

obtains the matrix tracking state named by pname for the specified | |

address in the array params. target must be VERTEX_PROGRAM_NV. pname | |

must be either TRACK_MATRIX_NV or TRACK_MATRIX_TRANSFORM_NV. If the | |

matrix tracked is a texture matrix, TEXTUREi_ARB is returned (never | |

TEXTURE) where i indicates the texture unit of the particular tracked | |

texture matrix. The INVALID_VALUE error is generated if address is | |

not divisible by four and is not less than 96. | |

The commands | |

void GetVertexAttribdvNV(uint index, enum pname, double *params); | |

void GetVertexAttribfvNV(uint index, enum pname, float *params); | |

void GetVertexAttribivNV(uint index, enum pname, int *params); | |

obtain the vertex attribute state named by pname for the vertex | |

attribute numbered index. pname must be one of ATTRIB_ARRAY_SIZE_NV, | |

ATTRIB_ARRAY_STRIDE_NV, ATTRIB_ARRAY_TYPE_NV, or CURRENT_ATTRIB_NV. | |

Note that all the queries except CURRENT_ATTRIB_NV return client | |

state. The INVALID_VALUE error is generated if index is greater than | |

15, or if index is zero and pname is CURRENT_ATTRIB_NV. | |

The command | |

void GetVertexAttribPointervNV(uint index, | |

enum pname, void **pointer); | |

obtains the pointer named pname in the array params for vertex | |

attribute numbered index. pname must be ATTRIB_ARRAY_POINTER_NV. | |

The INVALID_VALUE error is generated if index greater than 15. | |

The command | |

boolean IsProgramNV(uint id); | |

returns TRUE if program is the name of a program object. If program | |

is zero or is a non-zero value that is not the name of a program | |

object, or if an error condition occurs, IsProgramNV returns FALSE. | |

A name returned by GenProgramsNV but not yet loaded with a program | |

is not the name of a program object." | |

-- NEW Section 6.1.14 "Querying Current Matrix State" | |

"Instead of providing distinct symbolic tokens for querying each | |

matrix and matrix stack depth, the symbolic tokens CURRENT_MATRIX_NV | |

and CURRENT_MATRIX_STACK_DEPTH_NV in conjunction with the GetBooleanv, | |

GetIntegerv, GetFloatv, and GetDoublev return the respective state | |

of the current matrix given the current matrix mode. | |

Querying CURRENT_MATRIX_NV and CURRENT_MATRIX_STACK_DEPTH_NV is | |

the only means for querying the matrix and matrix stack depth of | |

the tracking matrices described in section 2.14.5." | |

Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance) | |

Add the following rule: | |

"Rule X Vertex program and vertex state program instructions not | |

relevant to the calculation of any result must have no effect on | |

that result. | |

Rules X+1 Vertex program and vertex state program instructions | |

relevant to the calculation of any result must always produce the | |

identical result. In particular, the same instruction with the same | |

source inputs must produce the identical result whether executed by | |

a vertex program or a vertex state program. | |

Instructions relevant to the calculation of a result are any | |

instructions in a sequence of instructions that eventually determine | |

the source values for the calculation under consideration. | |

There is no guaranteed invariance between vertices transformed by | |

conventional GL vertex transform mode and vertices transformed by | |

vertex program mode. Multi-pass rendering algorithms that require | |

rendering invariances to operate correctly should not mix conventional | |

GL vertex transform mode with vertex program mode for different | |

rendering passes. However such algorithms will operate correctly | |

if the algorithms limit themselves to a single mode of vertex | |

transformation." | |

Additions to the AGL/GLX/WGL Specifications | |

Program objects are shared between AGL/GLX/WGL rendering contexts if | |

and only if the rendering contexts share display lists. No change | |

is made to the AGL/GLX/WGL API. | |

Dependencies on EXT_vertex_weighting | |

If the EXT_vertex_weighting extension is not supported, there is no | |

aliasing between vertex attribute 1 and the current vertex weight. | |

Replace the contents of the last three columns in row 5 of table | |

X.2 with dashes. | |

Dependencies on EXT_point_parameters | |

When EXT_point_parameters is supported, the amended discussion | |

of point size determination should be further amended with the | |

language from the EXT_point_parameters specification though the point | |

parameters functionality only applies when vertex program mode is | |

disabled. | |

Even if the EXT_point_parameters extension is not supported, the | |

PSIZ vertex result register must operate as specified. | |

Dependencies on ARB_multitexture | |

ARB_multitexture is required to support NV_vertex_program and the | |

value of MAX_TEXTURE_UNITS_ARB must be at least 2. If more than 8 | |

texture units are supported, only the first 8 texture units can be | |

assigned texture coordinates when vertex program mode is enabled. | |

Texture units beyond 8 are implicitly disabled when vertex program | |

mode is enabled. | |

Dependencies on EXT_fog_coord | |

If the EXT_fog_coord extension is not supported, there is no | |

aliasing between vertex attribute 5 and the current fog coordinate. | |

Replace the contents of the last three columns in row 5 of table | |

X.2 with dashes. | |

Even if the EXT_fog_coord extension is not supported, the FOGC | |

vertex result register must operate as specified. Note that the | |

FOGC vertex result register behaves identically to the EXT_fog_coord | |

extension's FOG_COORDINATE_SOURCE_EXT being FOG_COORDINATE_EXT. | |

This means that the functionality of EXT_fog_coord is required to | |

implement NV_vertex_program even if the EXT_fog_coord extension is | |

not supported. | |

If the EXT_fog_coord extension is supported, the state of | |

FOG_COORDINATE_SOURCE_EXT only applies when vertex program mode is | |

disabled and the discussion in section 3.10 is further amended by | |

the discussion of FOG_COORDINATE_SOURCE_EXT in the EXT_fog_coord | |

specification. | |

Dependencies on EXT_secondary_color | |

If the EXT_secondary_color extension is not supported, there is no | |

aliasing between vertex attribute 4 and the current secondary color. | |

Replace the contents of the last three columns in row 4 of table | |

X.2 with dashes. | |

Even if the EXT_secondary_color extension is not supported, the COL1 | |

and BFC1 vertex result registers must operate as specified. | |

These vertex result registers are required to implement OpenGL 1.2's | |

separate specular mode within a vertex program. | |

GLX Protocol | |

Forty-five new GL commands are added. | |

The following thirty-five rendering commands are sent to the sever | |

as part of a glXRender request: | |

BindProgramNV | |

2 12 rendering command length | |

2 4180 rendering command opcode | |

4 ENUM target | |

4 CARD32 id | |

ExecuteProgramNV | |

2 12+4*n rendering command length | |

2 4181 rendering command opcode | |

4 ENUM target | |

0x8621 n=4 GL_VERTEX_STATE_PROGRAM_NV | |

else n=0 command is erroneous | |

4 CARD32 id | |

4*n LISTofFLOAT32 params | |

RequestResidentProgramsNV | |

2 8+4*n rendering command length | |

2 4182 rendering command opcode | |

4 INT32 n | |

n*4 CARD32 programs | |

LoadProgramNV | |

2 16+n+p rendering command length | |

2 4183 rendering command opcode | |

4 ENUM target | |

4 CARD32 id | |

4 INT32 len | |

n LISTofCARD8 n | |

p unused, p=pad(n) | |

ProgramParameter4fvNV | |

2 32 rendering command length | |

2 4184 rendering command opcode | |

4 ENUM target | |

4 CARD32 index | |

4 FLOAT32 params[0] | |

4 FLOAT32 params[1] | |

4 FLOAT32 params[2] | |

4 FLOAT32 params[3] | |

ProgramParameter4dvNV | |

2 44 rendering command length | |

2 4185 rendering command opcode | |

4 ENUM target | |

4 CARD32 index | |

8 FLOAT64 params[0] | |

8 FLOAT64 params[1] | |

8 FLOAT64 params[2] | |

8 FLOAT64 params[3] | |

ProgramParameters4fvNV | |

2 16+16*n rendering command length | |

2 4186 rendering command opcode | |

4 ENUM target | |

4 CARD32 index | |

4 CARD32 n | |

16*n FLOAT32 params | |

ProgramParameters4dvNV | |

2 16+32*n rendering command length | |

2 4187 rendering command opcode | |

4 ENUM target | |

4 CARD32 index | |

4 CARD32 n | |

32*n FLOAT64 params | |

TrackMatrixNV | |

2 20 rendering command length | |

2 4188 rendering command opcode | |

4 ENUM target | |

4 CARD32 address | |

4 ENUM matrix | |

4 ENUM transform | |

VertexAttribPointerNV is an entirely client-side command | |

VertexAttrib1svNV | |

2 12 rendering command length | |

2 4265 rendering command opcode | |

4 CARD32 index | |

2 INT16 v[0] | |

2 unused | |

VertexAttrib2svNV | |

2 12 rendering command length | |

2 4266 rendering command opcode | |

4 CARD32 index | |

2 INT16 v[0] | |

2 INT16 v[1] | |

VertexAttrib3svNV | |

2 12 rendering command length | |

2 4267 rendering command opcode | |

4 CARD32 index | |

2 INT16 v[0] | |

2 INT16 v[1] | |

2 INT16 v[2] | |

2 unused | |

VertexAttrib4svNV | |

2 12 rendering command length | |

2 4268 rendering command opcode | |

4 CARD32 index | |

2 INT16 v[0] | |

2 INT16 v[1] | |

2 INT16 v[2] | |

2 INT16 v[3] | |

VertexAttrib1fvNV | |

2 12 rendering command length | |

2 4269 rendering command opcode | |

4 CARD32 index | |

4 FLOAT32 v[0] | |