Name NV_vertex_program2 Name Strings GL_NV_vertex_program2 Contact Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com) Mark Kilgard, NVIDIA Corporation (mjk 'at' nvidia.com) Notice Copyright NVIDIA Corporation, 2000-2002. IP Status NVIDIA Proprietary. Status Implemented in CineFX (NV30) Emulation driver, August 2002. Shipping in Release 40 NVIDIA driver for CineFX hardware, January 2003. Version Last Modified Date: 03/18/2008 NVIDIA Revision: 33 Number 287 Dependencies Written based on the wording of the OpenGL 1.3 Specification and requires OpenGL 1.3. Written based on the wording of the NV_vertex_program extension specification, version 1.0. NV_vertex_program is required. Overview This extension further enhances the concept of vertex programmability introduced by the NV_vertex_program extension, and extended by NV_vertex_program1_1. These extensions create a separate vertex program mode where the configurable vertex transformation operations in unextended OpenGL are replaced by a user-defined program. This extension introduces the VP2 execution environment, which extends the VP1 execution environment introduced in NV_vertex_program. The VP2 environment provides several language features not present in previous vertex programming execution environments: * Branch instructions allow a program to jump to another instruction specified in the program. * Branching support allows for up to four levels of subroutine calls/returns. * A four-component condition code register allows an application to compute a component-wise write mask at run time and apply that mask to register writes. * Conditional branches are supported, where the condition code register is used to determine if a branch should be taken. * Programmable user clipping is supported support (via the CLP0-CLP5 clip distance registers). Primitives are clipped to the area where the interpolated clip distances are greater than or equal to zero. * Instructions can perform a component-wise absolute value operation on any operand load. The VP2 execution environment provides a number of new instructions, and extends the semantics of several instructions already defined in NV_vertex_program. * ARR: Operates like ARL, except that float-to-int conversion is done by rounding. Equivalent results could be achieved (less efficiently) in NV_vertex program using an ADD/ARL sequence and a program parameter holding the value 0.5. * BRA, CAL, RET: Branch, subroutine call, and subroutine return instructions. * COS, SIN: Adds support for high-precision sine and cosine computations. * FLR, FRC: Adds support for computing the floor and fractional portion of floating-point vector components. Equivalent results could be achieved (less efficiently) in NV_vertex_program using the EXP instruction to compute the fractional portion of one component at a time. * EX2, LG2: Adds support for high-precision exponentiation and logarithm computations. * ARA: Adds pairs of components of an address register; useful for looping and other operations. * SEQ, SFL, SGT, SLE, SNE, STR: Add six new "set on" instructions, similar to the SLT and SGE instructions defined in NV_vertex_program. Equivalent results could be achieved (less efficiently) in NV_vertex_program with multiple SLT, SGE, and arithmetic instructions. * SSG: Adds a new "set sign" operation, which produces a vector holding negative one for negative components, zero for components with a value of zero, and positive one for positive components. Equivalent results could be achieved (less efficiently) in NV_vertex_program with multiple SLT, SGE, and arithmetic instructions. * The ARL instruction is extended to operate on four components instead of a single component. * All instructions that produce integer or floating-point result vectors have variants that update the condition code register based on the result vector. This extension also raises some of the resource limitations in the NV_vertex_program extension. * 256 program parameter registers (versus 96 in NV_vertex_program). * 16 temporary registers (versus 12 in NV_vertex_program). * Two four-component integer address registers (versus one single-component register in NV_vertex_program). * 256 total vertex program instructions (versus 128 in NV_vertex_program). * Including loops, programs can execute up to 64K instructions. Issues This extension builds upon the NV_vertex_program extension. Should this specification contain selected edits to the NV_vertex_program specification or should the specs be unified? RESOLVED: Since NV_vertex_program and NV_vertex_program2 programs share many features, the main section of this specification is unified and describes both types of programs. Other sections containing NV_vertex_program features that are unchanged by this extension will not be edited. How can a program use condition codes to avoid extra computations? Consider the example of evaluating the OpenGL lighting model for a given light. If the diffuse dot product is negative (roughly 1/2 the time for random geometry), the only contribution to the light is ambient. In this case, condition codes and branching can skip over a number of unneeded instructions. # R0 holds accumulated light color # R2 holds normal # R3 holds computed light vector # R4 holds computed half vector # c[0] holds ambient light/material product # c[1] holds diffuse light/material product # c[2].xyz holds specular light/material product # c[2].w holds specular exponent DP3C R1.x, R2, R3; # diffuse dot product ADD R0, R0, c[0]; # accumulate ambient BRA pointsAway (LT.x) # skip rest if diffuse dot < 0 MOV R1.w, c[2].w; DP3 R1.y, R2, R4; # specular dot product LIT R1, R1; # compute expontiated specular MAD R4, c[1], R0.y; # accumulate diffuse MAD R4, c[2], R0.z; # accumulate specular pointsAway: ... # continue execution How can a program use subroutines? With subroutines, a program can encapsulate a small piece of functionality into a subroutine and call it multiple times, as in CPU code. Applications will need to identify the registers used to pass data to and from the subroutine. Subroutines could be used for applications like evaluating lighting equations for a single light. With conditional branching and subroutines, a variable number of lights (which could even vary per-vertex) can be easily supported. accumulate: # R0 holds the accumulated result # R1 holds the value to add ADD R0, R1; RET; # Compute floor(A)*B by repeated addition using a subroutine. Yes, # this is a stupid example. # # c[0] holds (A,B,0,1). # R0 holds the accumulated result # R1 holds B, the value to accumulate. # R2 holds the number of iterations remaining. MOV R0, c[0].z; # start with zero MOV R1, c[0].y; FLRC R2.x, c[0].x; BRA done (LE.x); top: CAL accumulate; ADDC R2.x, R2.x, -c[0].w; # decrement count BRA top (GT.x); done: ... How can conventional OpenGL clip planes be supported in vertex programs? The clip distance in the OpenGL specification can be evaluated with a simple DP4 instruction that writes to one of the six clip distance registers. Primitives will automatically be clipped to the half-space where o[CLPx] >= 0, which matches the definition in the spec. # R0 holds eye coordinates # c[0] holds eye-space clip plane coefficients DP4 o[CLP0].x, R0, c[0]; Note that the clip plane or clip distance volume corresponding to the o[CLPn] register used must be enabled, or no clipping will be performed. The clip distance registers allow for clip distance volumes to be computed more-or-less arbitrarily. To approximate clipping to a sphere of radius , the following code can be used. # R0 holds eye coordinates # c[0].xyz holds sphere center # c[0].w holds the square of the sphere radius SUB R1.xyz, R0, c[0]; # distance vector DP3 R1.w, R1, R1; # compute distance squared SUB o[CLP0].x, c[0].w, R1.w; # compute r^2 - d^2 Since the clip distance is interpolated linearly over a primitive, the clip distance evaluated at a point will represent a piecewise-linear approximation of the true distance. The approximation will become increasingly more accurate as the primitive is tesselated more finely. How can looping be achieved in vertex programs? Simple loops can be achieved using a general purpose floating-point register component as a counter. The following code calls a function named "function" times, where is specified in a program parameter register component. # c[0].x holds the number of iterations to execute. # c[1].x holds the constant 1.0. MOVC R15.x, c[0].x; startLoop: CAL function (GT.x); # if (counter > 0) function(); SUBC R15.x, R15.x, c[1].x; # counter = counter - 1; BRA startLoop (GT.x); # if (counter > 0) goto start; endLoop: ... More complex loops (where a separate index may be needed for indexed addressing into the program parameter array) can be achieved using the ARA instruction, which will add the x/z and y/w components of an address register. # c[0].x holds the number of iterations to execute # c[0].y holds the initial index value # c[0].z holds the constant -1.0 (used for the iteration count) # c[0].w holds the index step value ARLC A1, c[0]; startLoop: CAL function (GT.x); # if (counter > 0) function(); # Note: A1.y can be used for # indexing in function(). ARAC A1.xy, A1; # counter = counter - 1; # index += loopStep; BRA startLoop (GT.x); # if (counter > 0) goto start; endLoop: ... Should this specification add support for vertex state programs beyond the VP1 execution environment? No. Vertex state programs are a little-used feature of NV_vertex_program and don't perform particularly well. They are still supported for compatibility with the original NV_vertex_program spec, but they will not be extended to support new features. How are NaN's be handled in the "set on" instructions (SEQ, SGE, SGT, SLE, SLT, SNE)? What about MIN, MAX? SSG? When doing condition code tests? Any of these instructions involving a NaN operand will produce a NaN result. This behavior differs from the NV_fragment_program extension. There, SEQ, SGE, SGT, SLE, and SLT will produce 0.0 if either operand is a NaN, and SNE will produce 1.0 if either operand is a NaN. For condition code updates, NaN values will result in "UN" condition codes. All conditionals using a "UN" condition code, except "TR" and "NE" will evaluate to false. This behavior is identical to the functionality in NV_fragment_program. How can the various features of this extension be used to provide skinning functionality similar to that in ARB_vertex_blend and ARB_matrix_palette? And how can that functionality be extended? Assume an implementation that allows application of up to 8 matrices at once. Further assume that v[12].xyzw and v[13].xyzw hold the set of 8 weights, and v[14].xyzw and v[15].xyzw hold the set of 8 matrix indices. Furthermore, assume that the palette of matrices are stored/tracked at c[0], c[4], c[8], and so on. As an additional optimization, an application can specify that fewer than 8 matrices should be applied by storing a negative palette index immediately after the last index is applied. Skinning support in this example can be provided by the following code: ARLC A0, v[14]; # load 4 palette indices at once DP4 R1.x, c[A0.x+0], v[0]; # 1st matrix transform DP4 R1.y, c[A0.x+1], v[0]; DP4 R1.z, c[A0.x+2], v[0]; DP4 R1.w, c[A0.x+3], v[0]; MUL R0, R1, v[12].x; # accumulate weighted sum in R0 BRA end (LT.y); # stop on a negative matrix index DP4 R1.x, c[A0.y+0], v[0]; # 2nd matrix transform DP4 R1.y, c[A0.y+1], v[0]; DP4 R1.z, c[A0.y+2], v[0]; DP4 R1.w, c[A0.y+3], v[0]; MAD R0, R1, v[12].y, R0; # accumulate weighted sum in R0 BRA end (LT.z); # stop on a negative matrix index ... # 3rd and 4th matrix transform ARLC A0, v[15]; # load next four palette indices BRA end (LT.x); DP4 R1.x, c[A0.x+0], v[0]; # 5th matrix transform DP4 R1.y, c[A0.x+1], v[0]; DP4 R1.z, c[A0.x+2], v[0]; DP4 R1.w, c[A0.x+3], v[0]; MAD R0, R1, v[13].x, R0; # accumulate weighted sum in R0 BRA end (LT.y); # stop on a negative matrix index ... # 6th, 7th, and 8th matrix transform end: ... # any additional instructions The amount of code used by this example could further be reduced using a subroutine performing four transformations at a time: ARLC A0, v[14]; # load first four indices CAL skin4; # do first four transformations BRA end (LT); # end if any of the first 4 indices was < 0 ARLC A0, v[15]; # load second four indices CAL skin4; # do second four transformations end: ... # any additional instructions Why does the RCC instruction exist? RESOLVED: To perform numeric operations that will avoid overflow and underflow issues. Should the specification provide more examples? RESOLVED: It would be nice. New Procedures and Functions None. New Tokens None. Additions to Chapter 2 of the OpenGL 1.3 Specification (OpenGL Operation) Modify Section 2.11, Clipping (p. 39) (modify last paragraph, p. 39) When the GL is not in vertex program mode (section 2.14), this view volume may be further restricted by as many as n client-defined clip planes to generate the clip volume. ... (add before next-to-last paragraph, p. 40) When the GL is in vertex program mode, the view volume may be restricted to the individual clip distance volumes derived from the per-vertex clip distances (o[CLP0] - o[CLP5]). Clip distance volumes are applied if and only if per-vertex clip distances are not supported in the vertex program execution environment. A point P belonging to the primitive under consideration is in the clip distance volume numbered n if and only if c_n(P) >= 0, where c_n(P) is the interpolated value of the clip distance CLPn at the point P. For point primitives, c_n(P) is simply the clip distance for the vertex in question. For line and triangle primitives, per-vertex clip distances are interpolated using a weighted mean, with weights derived according to the algorithms described in sections 3.4 and 3.5. (modify next-to-last paragraph, p.40) Client-defined clip planes or clip distance volumes are enabled with the generic Enable command and disabled with the Disable command. The value of the argument to either command is CLIP PLANEi where i is an integer between 0 and n; specifying a value of i enables or disables the plane equation with index i. The constants obey CLIP PLANEi = CLIP PLANE0 + i. Add Section 2.14, Vertex Programs (p. 57). This section supersedes the similar section added in the NV_vertex_program extension and extended in the NV_vertex_program1_1 extension. 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. Section 2.14.1, Vertex Program Execution Environment The vertex program execution environment is an operational model that defines how a program is executed. The execution environment includes a set of instructions, a set of registers, and semantic rules defining how operations are performed. There are three vertex program execution environments, VP1, VP1.1, and VP2. The environment names are taken from the mandatory program prefix strings found at the beginning of all vertex programs. The VP1.1 execution environment is a minor addition to the VP1 execution environment, so references to the VP1 execution environment below apply to both VP1 and VP1.1 execution environments except where otherwise noted. The vertex program instruction set consists primarily of floating-point 4-component vector operations operating 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 without data hazards so results computed in one operation can be used immediately afterwards. Vertex programs produce a set of vertex result vectors that becomes the set of transformed vertex parameters used by primitive assembly. In the VP1 environment, vertex programs execute a finite fixed sequence of instructions with no branching or looping. In the VP2 environment, vertex programs support conditional and unconditional branches and four levels of subroutine calls. The vertex program register set consists of six types of registers described in the following sections. Section 2.14.1.1, 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. The set and operation of vertex attribute registers are identical for both VP1 and VP2 execution environment. Section 2.14.1.2, Program Parameter Registers The Program Parameter Registers are a set of 4-component floating-point vector registers containing the vertex program parameters. In the VP1 execution environment, there are 96 registers, numbered 0 through 95. In the VP2 execution environment, there are 256 registers, numbered 0 through 255. 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 error INVALID_VALUE is generated if the specified index is greater than or equal to the number of program parameters in the execution environment (96 for VP1, 256 for VP2). 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. The effect is the same (assuming no errors) as for (i=index; i and is greater than the number of program parameters in the execution environment (96 for VP1, 256 for VP2). 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 initial value of all 96 (VP1) or 256 (VP2) program parameter registers is (0,0,0,0). Section 2.14.1.3, Address Registers The Address Registers are 4-component vector registers with signed 10-bit integer components. In the VP1 execution environment, there is only a single address register (A0) and only the x component of the register is accessible. In the VP2 execution environment, there are two address registers (A0 and A1), of which all four components are accessible. The address registers are private to each vertex program invocation and are initialized to (0,0,0,0) at every vertex program invocation. These registers can be written during vertex program execution (but not read) and their values 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.2.1 and the discussion of the ARL instruction in section 2.14.3.4. Section 2.14.1.4, Temporary Registers The Temporary Registers are 4-component floating-point vector registers used to hold temporary results during vertex program execution. In the VP1 execution environment, there are 12 temporary registers, numbered 0 through 11. In the VP2 execution environment, there are 16 temporary registers, numbered 0 through 15. 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. In the VP2 execution environment, there is one additional temporary pseudo-register, "CC". CC is treated as unnumbered, write-only temporary register, whose sole purpose is to allow instructions to modify the condition code register (section 2.14.1.6) without overwriting the contents of any temporary register. Section 2.14.1.5, Vertex Result Registers The Vertex Result Registers are 4-component floating-point vector registers used to write the results of a vertex program. There are 15 result registers in the VP1 execution environment, and 21 in the VP2 execution environment. 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) CLP0(*) Clip distance 0 (d,*,*,*) CLP1(*) Clip distance 1 (d,*,*,*) CLP2(*) Clip distance 2 (d,*,*,*) CLP3(*) Clip distance 3 (d,*,*,*) CLP4(*) Clip distance 4 (d,*,*,*) CLP5(*) Clip distance 5 (d,*,*,*) Table X.1: Vertex Result Registers. (*) Registers CLP0 through CLP5, are available only in the VP2 execution environment. 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. CLP0 through CLP5, available only in the VP2 execution environment, are the transformed vertex's clip distances. These floating-point coordinates are used by post-vertex program clipping process (see section 2.11). Section 2.14.1.6, The Condition Code Register The VP2 execution environment provides a single four-component vector called the condition code register. Each component of this register is one of four enumerated values: GT (greater than), EQ (equal), LT (less than), or UN (unordered). The condition code register can be used to mask writes to registers and to evaluate conditional branches. Most vertex program instructions can optionally update the condition code register. When a vertex program instruction updates the condition code register, a condition code component is set to LT if the corresponding component of the result is less than zero, EQ if it is equal to zero, GT if it is greater than zero, and UN if it is NaN (not a number). The condition code register is initialized to a vector of EQ values each time a vertex program executes. There is no condition code register available in the VP1 execution environment. Section 2.14.1.7, 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 the VP1 execution environment. Clip planes are supported indirectly via the clip distance (o[CLPx]) registers in the VP2 execution environment. Section 2.14.1.8, 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 several types of 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. The grammar provides for three different vertex program types, corresponding to the three vertex program execution environments. VP1, VP1.1, and VP2 programs match the grammar rules , , and , respectively. Some grammar rules correspond to features or instruction forms available only in certain execution environments. Rules beginning with the prefix "vp1-" are available only to VP1 and VP1.1 programs. Rules beginning with the prefixes "vp11-" and "vp2-" are available only to VP1.1 and VP2 programs, respectively. ::= | | ::= "!!VP1.0" "END" ::= "!!VP1.1" "END" ::= "!!VP2.0" "END" ::= ::=