Name ARB_vertex_program Name Strings GL_ARB_vertex_program Contributors Kurt Akeley Allen Akin Ben Ashbaugh Bob Beretta John Carmack Matt Craighead Ken Dyke Steve Glanville Michael Gold Evan Hart Mark Kilgard Bill Licea-Kane Barthold Lichtenbelt Erik Lindholm Benj Lipchak Bill Mark James McCombe Jeremy Morris Brian Paul Bimal Poddar Thomas Roell Jeremy Sandmel Jon Paul Schelter Geoff Stahl John Stauffer Nick Triantos Contact Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com) Notice Copyright (c) 2002-2013 The Khronos Group Inc. Copyright terms at http://www.khronos.org/registry/speccopyright.html Specification Update Policy Khronos-approved extension specifications are updated in response to issues and bugs prioritized by the Khronos OpenGL Working Group. For extensions which have been promoted to a core Specification, fixes will first appear in the latest version of that core Specification, and will eventually be backported to the extension document. This policy is described in more detail at https://www.khronos.org/registry/OpenGL/docs/update_policy.php IP Status NVIDIA claims to own intellectual property related to this extension, and has signed an ARB Contributor License agreement licensing this intellectual property. Microsoft claims to own intellectual property related to this extension. Status Complete. Approved by ARB on June 18, 2002 Version Last Modified Date: 07/25/07 Revision: 46 Number ARB Extension #26 Dependencies Written based on the wording of the OpenGL 1.3 specification and requires OpenGL 1.3. ARB_vertex_blend and EXT_vertex_weighting affect the definition of this extension. ARB_matrix_palette affects the definition of this extension. ARB_point_parameters and EXT_point_parameters affect the definition of this extension. EXT_secondary_color affects the definition of this extension. EXT_fog_coord affects the definition of this extension. ARB_transpose_matrix affects the definition of this extension. NV_vertex_program interacts with this extension. EXT_vertex_shader interacts with 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 (ARB_vertex_blend, 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/ARB_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 result 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 (1) What should this extension be called? RESOLVED: ARB_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. Some of the API machinery in this extension for describing programs should be useful for extending other OpenGL operations with programs (though other types of programs may look very different from vertex programs). (2) 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. vertex program - An application-defined program used to transform vertices when vertex program mode is enabled. program target - A type or class of program. This extension supports the VERTEX_PROGRAM_ARB target. Future extensions may add other program targets. program object - An object maintained internal to OpenGL that encapsulates a program and a set of associated state. Operations performed on program objects include loading a program, binding, generating program object names, querying state, and deleting. program name - Each program object has an associated unsigned integer, called the program name. Applications refer to a program object using the program name. current program - Each program target may have a current program object. For vertex programs, the current program is executed whenever a vertex is specified when vertex program mode is enabled. default program - Each program target has a default program object, referred to using a program name of zero. The current program for each program target is initially the default program for that target. program execution environment - A set of resources, instructions, and semantic rules used to execute a program. Each program target may support one or more execution environment -- new execution environments may provide new instructions, resources, or execution rules. Program strings must specify the execution environment that should be used to execute the program. program options - An optional feature that modifies the rules of the execution environment. Vertex programs specify the options that they require at the beginning of the program. vertex attribute - GL state associated with vertices that can vary per vertex. conventional vertex attributes - Per-vertex attributes used in conventional GL vertex transform mode, including colors, normals, texture coordinate sets. generic vertex attributes - An array of 16+ 4-component vectors added by this extension. Generic vertex attributes can be used by vertex programs but are unused in conventional GL vertex transform mode. program parameter - A set of constants that are available for vertex programs to use during their execution. Program parameters include program environment parameters, program local parameters, conventional GL state, and program constants. program environment parameter - A set of 96+ 4-component vectors belonging to the GL context that can be used as constants during the execution of any vertex program. program local parameter - A set of 96+ 4-component vectors belonging to a vertex program object that can be used as constants during the execution of the corresponding vertex program. Program local parameters can not be used by any other vertex programs. program constants - Constants declared in the text of a program may be used during the execution of that program. program temporaries - A set of 12+ 4-component vectors to hold temporary results that can be read or written during the execution of a vertex program. program address registers - A set of 1+ 1-component integer vectors that can be used to perform variable indirect accesses to program parameter arrays during the execution of a vertex program. Address registers are specified as vectors to allow for future extensions supporting multiple address register components. program results - A set of 4-component vectors to hold the final results of a vertex program. The program results correspond closely to the set of vertex attributes used during primitive assembly and rasterization. program variables - Variable names used to identify a specific vertex attribute, program parameter, temporary, address register, or result. program binding - A program statement that declares a variable and associates it with a specific vertex attribute, program parameter, or program result. implicit binding - When an executable instruction refers to a specific vertex attribute, program parameter, program result, or constant by name, without using an explicit program binding statement. When such values are encountered, an implicit binding to an anonymous variable name is created. program invocation - The act of implicitly or explicitly kicking off program execution. Vertex programs are invoked automatically when vertex program mode is enabled and vertices are received. Vertex programs are also invoked automatically when the current raster position is specified. (3) What part of OpenGL do vertex programs specifically bypass? Vertex programs bypass the following OpenGL functionality: - The modelview and projection matrix vertex transformations. - Vertex weighting/blending (ARB_vertex_blend). - Normal transformation, rescaling, and normalization. - Color material. - Per-vertex lighting. - Texture coordinate generation and texture matrix transformations. - Per-vertex point size computations in ARB/EXT_point_parameters - Per-vertex fog coordinate computations in EXT_fog_coord and NV_fog_distance. - Client-defined clip planes. - The normalization of AUTO_NORMAL evaluated normals - All of the above, when computing the current raster position. Operations not subsumed by vertex programs - Clipping to the view frustum. - Perspective divide (division by w). - The viewport transformation. - The depth range transformation. - Front and back color selection (for two-sided lighting and coloring). - Clamping the primary and secondary colors to [0,1]. - Primitive assembly and subsequent operations. - Evaluators (except the AUTO_NORMAL normalization). (5) This extension adds a set of generic vertex attributes to the existing conventional attributes. The sum of the number of generic and conventional attributes supported on a given platform may exceed the total number of per-vertex attributes supported in hardware. How should this situation be handled? RESOLVED: Implementations may alias conventional and generic vertex attributes, where pairs of conventional and generic vertex attributes share the same storage. Such aliasing will effectively reduce the number of vertex attributes a hardware platforms. While implementations may alias attributes, that behavior is not required. To accommodate both behaviors, changing a generic vertex attribute leaves the corresponding conventional attribute undefined, and vice versa. This undefined behavior is a compromise between the existing EXT_vertex_shader extension (which does not permit aliasing) and the NV_vertex_program extension (which requires aliasing). The mapping between generic and conventional vertex attributes is found in Table X.1 below. This mapping is taken from the NV_vertex_program specification and generalized to define behavior for >8 texture coordinate sets. Applications that mix conventional and generic vertex attributes in a single rendering pass should be careful to avoid using attributes that may alias. To limit inadvertent use of such attributes, loading a vertex program that used a pair of attributes that may alias is guaranteed to fail. Applications requiring a small number of generic vertex attributes can always safely use generic attributes 6 and 7, and any supported attributes corresponding to unused or unsupported texture units. For example, if an implementation supports only four texture units, generic attributes 12 through 15 can always be used safely. (6) Should there be a "VertexAttribs" entry point to specify multiple vertex attributes in one immediate mode call. RESOLVED: No. Not providing such functionality serves to reduce the already large number of required immediate mode entry points. A "VertexAttribs" command would improve the efficiency of vertex attribute transfer, but vertex arrays or display lists should still be better. (7) Should a full complement of data types (signed and unsigned bytes, shorts, and ints, as well as floats and doubles) be supported for vertex attributes? Should fixed-point data types be supported in both normalized (map the range to [0,1] or [-1,1]) and unnormalized form? RESOLVED: For vertex arrays, all data type combinations are supported. For immediate mode, a smaller subset is supported, to limit the number of immediate-mode entry points added by this extension. In fully general form, 112 immediate-mode entry points (4 sizes x 2 vector/non-vector x 14 data types) would be required. Immediate mode support is available for non-normalized shorts, floats, and doubles for all component counts. Additionally, immediate mode support is available for 4-component vectors of all data types (normalized and unnormalized). Note also that in immediate mode, the "N" qualifier in function names like VertexAttrib4Nub will be used to indicate that fixed-point data should be normalized. (8) How should applications indicate that fixed-point generic vertex attribute array components should be converted to [-1,+1] or [0,1] ranges? RESOLVED: The function VertexAttribPointerARB takes a boolean argument that indicates whether fixed-point array data should be normalized to [-1,+1] or [0,1]. One alternate approach would have been to extend to set of enumerants to include values such as NORMALIZED_UNSIGNED_BYTE_ARB. Adding such enumerants in some sense implies that UNSIGNED_BYTE is not normalized, even though it usually is. (9) In unextended OpenGL, calling Vertex() specifies a vertex and causes vertex transformation operations to be performed on the vertex. Should there be an equivalent method to specify a vertex using generic vertex attributes? If so, how should this be accomplished? RESOLVED: Setting generic vertex attribute zero will always specify a vertex. Vertex*(...) and VertexAttrib*(0,...) are specified to be equivalent, whether or not vertex program mode is enabled. Allowing generic vertex attribute zero to specify a vertex allows applications to write vertex programs that use only generic attributes; otherwise, applications would have had to use Vertex() to provoke vertex processing. (10) How is this extension different from previous vertex program extensions, such as EXT_vertex_shader or NV_vertex_program? What pitfalls are there in porting vertex programs to/from this extension? RESOLVED: See "Interactions with NV_vertex_program" and "Interactions with EXT_vertex_shader" sections near the end of this specification. (11) Should program parameter variables bound to GL state be updated automatically after the bound state changes? If so, when? RESOLVED: Yes. Such variables are updated automatically prior to the next vertex program invocation with no application intervention required. A proposal to reduce the burden by requiring a manual "update state" step was considered and rejected. (12) How should this specification handle variable bindings to Material state? Material is allowed inside a Begin/End, so material properties are technically per-vertex state. RESOLVED: Materials can be bound only as program parameters. Changes to material properties inside a Begin/End will leave the bindings undefined until the subsequent End command. At that point, all material property bindings are guaranteed to be updated, and any material property changes up to the next Begin command are guaranteed to take effect immediately. Supporting per-vertex material properties places additional pressure on the number of per-vertex bindings an implementation can support, which was already a problem. See issue (5). In practice, material properties are usually not changed in this manner. Applications needing to change material properties inside a Begin/End in vertex program mode can work around this limitation by storing the color in a conventional or generic vertex attribute and modifying the vertex program accordingly. (13) What semantic restrictions, if any, should be imposed on binding the same GL state to multiple variables? The grammar permits such bindings, but allowing this behavior means that single state updates must update multiple variables. RESOLVED: Cases where a single state update necessarily requires updating multiple variables are disallowed. The only restriction resulting from this decision is that a single state variable can not be bound more than once in the collection of arrays that are accessed using relative addressing (at run time). The driver can and will coalesce all other bindings accessed only at fixed offsets into a single binding. This restriction and a little driver work allows the same state variable to be used multiple times without requiring that a single state change update multiple variables. (14) What semantic restrictions, if any, should be imposed on using multiple vertex attributes or program parameters in the same instruction? RESOLVED: None. If the underlying hardware implementation does not support reads of multiple attributes or program parameters, the driver may need to transparently insert additional instructions and/or consume temporaries to perform the operation. (15) How and when should related state be combined into a single program parameter binding? Additionally, should any values derived from core GL state be exposed, too? RESOLVED: Related state should be combined when possible, as long as the binding name remains somewhat sensible. Additionally, certain pre-computed state items useful for performance reasons are also exposed. In particular, the following GL state combinations are supported: * Light attenuation constants and the spot light exponent are combined into a single vector called "state.light[n].attenuation" (spot lights can attenuate the lit result). * Spot light direction and cutoff angle cosine are called "state.light[n].spot.direction" (cutoff is directional information). Binding the cutoff angle itself is pretty useless, so the cosine is used. * A pre-computed half angle for lighting with infinite lights and an infinite viewer is provided and called "state.light[n].half". * Pre-computed products of ambient, diffuse, and specular light colors with the corresponding front or back material colors are supported, and are called "state.lightprod[n]..". * Exponential fog density, linear fog start and end parameters, as well as the pre-computed reciprocal of (end-start) are combined into one vector called "state.fog.params". * The core point size, minimum and maximum size clamps (ARB_point_parameters), and multisample fade size threshold (ARB_point_parameters) are combined into a single vector called "state.point.size". * Precomputed transpose, inverse, and inverse transpose matrices are supported for each base matrix type. (16) Should the initial values of temporaries and results be undefined? RESOLVED: Since the underlying hardware differs, it was decided to leave these values uninitalized. There are a few issues related to this behavior that programs should keep in mind: * Since any results not written by the program are undefined, programs should write to all result registers that are needed during rasterization. * In particular, the initial vertex position result is undefined, and will remain undefined if not written by a program. To achieve proper results, vertex programs should be careful to write to all four components of the vertex position. Otherwise, primitives may be completely clipped or produce undefined results during rasterization. There is no semantic requirement that programs must write a transformed vertex position, so erroneous programs will load succesfully, but will produce undefined (and probably useless) results. Such a semantic requirement may be impossible to enforce in future language versions that support run-time branching. * Since vertex programs may be executed when the raster position is set, any attributes not written by the program will result in undefined state in the current raster position. Programs should write to all result registers that would be used when rasterizing pixel primitives using the current raster position. * If conventional OpenGL texture mapping operations are performed, a program should always write to the "w" coordinate of any texture coordinates result registers it needs to use. Conventional OpenGL texture accesses always use projective texture coordinates (e.g., s/q, t/q, r/q), even though q is almost always 1.0. An undefined q coordinate (coming from the "w" component of the result register) may produce undefined coordinates on the texture lookup. (17) Should vertex programs be required to have a header token and an end token? RESOLVED: Yes. The header token for this extension is named "!!ARBvp1.0". The ARB may standardize future language versions which would be expected to have tokens like "!!ARBvp2.0". Vertex programs must end with the "END" token. The initial header token reminds the programmer what type of program they are writing. If vertex programs are ever read from disk files, the header token can be used to specifically identify vertex programs. The initial header tokens will also make it easier for programmers to distinguish between multiple types of vertex programs and between vertex programs and another future type of programs. We expect that programs may be generated by concatenation of program fragments. The "END" token will hopefully reduce bugs due to specifying an incorrectly concatenated program. (18) Should ProgramStringARB take a specifier? Should ProgramLocalParameterARB and GetProgramLocalParameterARB take a specifier? How about GetProgramivARB and GetProgramStringARB? RESOLVED: No to all. Instead, these calls are specified to always query or modify the currently bound program object. Using bound objects allows GL implementations to avoid locking and name lookup overhead on each such call. This behavior does imply that applications loading a sequence of program objects must bind each in turn. (19) Should relative addressing be performed using an address register (load up an integer register) or by taking a floating-point scalar? RESOLVED: Address register. It would not be a good idea to support both syntaxes simultaneously, since using a floating-point scalar may consume the only available address register in the process. The current address register syntax can be easily extended to allow for multiple integer registers and/or enable other integer operations in a later extension. Using a floating-point index may require an extra instruction on some architectures, and would require optimization work to eliminate redundant loads. Using a floating-point index may consume one of a small number of temporary registers. On the other hand, for implementations without a dedicated address register, it may be necessary to dedicate a general-purpose register (or register component) to hold the address register contents. (20) How should user-defined clipping be supported in this specification? RESOLVED: User-defined clipping is not supported in standard vertex program mode. User-defined clipping support will be provided for programs that use the "position invariant" option, where all vertex transformation operations are performed by the fixed-function pipeline. It is expected that future vertex program extensions or a future language standard may provide more powerful user clipping functionality. The options considered were: (1) Not at all. Does not work for applications requiring user clipping. User clipping could be supported through a language extension. (2) Support only through the "position_invariant" option, where vertex transformation is performed by the fixed-function pipeline. (3) Support by using the fixed-function pipeline to generate eye coordinates and perform user clipping as specified for conventional transformation. May not work properly if the vertex transformation doesn't match the standard "multiply by modelview and projection matrices" model. (4) Project existing fixed-function clip planes into clip coordinates and perform the clip test in clip space. The clip planes would be transformed by the inverse of the projection matrix, which will not work if the projection matrix is singular. (5) Provide a 4-component "user clip coordinate" result that can be bound by a vertex program. User clipping is performed as in unextended OpenGL, using the "user clip coordinate" in place of the non-existant eye coordinates. This approach allows an application to do user clipping in any coordinate system. Clipping would not be independent of primitive tesselation as in the conventional pipeline. Additionally, the implicit transformation of specified clip planes by the modelview matrix may be undesirable (e.g., clipping in object coordinates). (6) Provide one or more "clip plane distance" results that can be bound by a vertex program. For conventional clipping applications, vertex programs would compute the dot products normally computed by fixed-function hardware. Additionally, this method would enable additional unconventional clipping effects. Primitives would be clipped to the portion whose interpolated clip distances are greater than or equal to zero. This approach has the same issues as (5). (21) How should future vertex program opcodes be named? RESOLVED: Three-character names are recommended for brevity. Three character names are not a hard-and-fast requirement; extra characters may be needed for clarity or to disambiguate instructions. (22) Should anything be said about the precision used for carrying out the instructions? RESOLVED: Not much; precision will vary across platforms. The minimum precision requirements (1 part in 10^5 or roughly 17 bits) are spelled out in section 2.1.1. In practice, implementations will generally provide precision comparable to that obtained using single precision floats. Documenting exact precision across implementations is difficult. Additionally, it is difficult to spell out precision requirements for "compound" operations such as DP4. (23) Should this extension support evaluator maps for generic vertex attributes? If so, what attribute sizes should be supported? Note that such maps are not supported at all for texture units except zero. RESOLVED: No. Evaluator support has not been consistently extended in previous extensions. For example, neither ARB_multitexture nor OpenGL 1.3 provide support for evaluators for texture units other than unit zero. Adding evaluators for generic attributes involves a large amount of new state and complexity, particularly if evaluators should be supported in general form (1, 2, 3, and 4 components, all supported data type). (25) The number of generic vertex attributes is implementation-dependent and is at least 16. Each generic vertex attribute has a vertex array enable. Should two new entry points be provided to accept an arbitrary attribute number, or should we reserve a range of enumerants that is "large enough"? RESOLVED: Yes. EnableVertexAttribArrayARB and DisableVertexAttribArrayARB. This allows the number of vertex attributes to be unbounded, instead of using a limited range. (26) What limits should be imposed on the constants that can be added to or subtracted from the address register for relative addressing? Negative offsets are sometimes useful for shifting down in an array. RESOLVED: -64 to +63 should be sufficient for the time being. Offset sizes are limited to allow offsets to be baked into device-dependent instruction encodings. (28) What level of precision should be guaranteed for the EXP and LOG instructions? And for the EX2 and LG2 instructions? RESOLVED: The low precision EXP and LOG instructions should give at least 10 bits (2^-11 maximum relative error). No specific treatment will be added for EX2/LG2, implying that the computations should at least meet the minimal floating-point precision required by the spec. (29) Should incremental program compilation be supported? RESOLVED: No. Applications can compile programs just as easily using string concatenation. (30) Should the execution environment be identified by the program itself or as an additional "language" parameter to ProgramStringARB? RESOLVED: Programs should identify their execution environment in the header. The header (plus any specified options) make it clear what kind of program is being defined. (31) Should this extension provide support for character sets other than 7-bit ASCII? RESOLVED: Provide a argument to ProgramStringARB to allow for future extensions. Only ASCII will be supported by this extension; additional character sets or encodings could be supported using separate extensions. (32) Support for "program object" functionality may be applicable to future program targets. Should this functionality be factored out into a separate extension? RESOLVED: No, such separation is not necessary. This extension was designed to allow to easily accommodate future program target types. It would be straightforward to put program object functionality into a separate extension, but the functionality provided by that extension would be of no value by itself. (33) Should program residency management be supported? RESOLVED: No. This functionality can be supported in a separate extension if desired. If may be desirable to address residency management in a more general form, where an application may desire a diverse set of objects (textures, programs) to be resident at once. (34) Should program object management APIs (GenProgramsARB, DeleteProgramsARB) work like texture objects or display lists? RESOLVED: Texture objects. Both approaches have their merits. Pluses for the display list model include: no need to keep around multiple indices if you want to allocate a group of object, contiguous indices may fall out on implementations that share one block allocator for textures and display lists. Pluses for the texture object model: non-contiguous indices may be more optimizable -- new objects can be mapped to empty blocks in a hash table to avoid collisions with existing objects, separate indices are more compatible with a future handle-based object paradigm, and a larger base of extensions using this model. Note that display list allocations needed to be contiguous to support CallLists, but no such requirement for texture or program objects exists for programs. (35) Should there be support for a program object zero? With texture objects, texture object zero is "special" because it is the default texture object for each target type. Is there something like this for program objects? RESOLVED: Yes. Like texture objects, there should be a separate program object zero for each program type. This allows applications to use vertex programs without needing to generate and manage program objects. With texture objects, an object zero was needed for backward compatibility with pre-OpenGL 1.1 applications. There is no such requirement here, but providing an object zero nicely matches the familiar texture object model. (36) How should this extension provide feedback on why a program failed to load? RESOLVED: Two queries are provided. Calling GetIntegerv() with PROGRAM_ERROR_POSITION_ARB provides the offset of an offending instruction in the program string. An error position of -1 indicates that a program loaded successfully. Calling GetString() with PROGRAM_ERROR_STRING_ARB returns an implementation-dependent error string explaining the reason for the failure. The error string can be queried even on successful program loads to check for warning messages. The error string may be kept in a static buffer managed by the GL implementation. Implementations may reuse the same buffer on subsequent calls to ProgramStringARB, so returned error strings are guaranteed to be valid only until the next such call. (37) How does ARB_vertex_blend's WEIGHT_SUM_UNITY_ARB mode interact with this extension? This mode allows an application to specify N-1 weights, and have the Nth weight computed by the GL. RESOLVED: The ARB_vertex_blend spec (as of May, 2002) specifies that the nth weight is automatically computed by the GL and is effectively current state. In practice, ARB_vertex_blend implementations compute the nth weight on the fly in the fixed-function transformation pipeline, implying that the ARB_vertex_blend spec may require a fix. For the purposes of this extension, the WEIGHT_SUM_UNITY_ARB enable is ignored in vertex program mode. Applications performing a vertex weighting operation in a vertex program are free to compute the extra weight in the program. (38) Should program environment parameters be pushed and popped? RESOLVED: No. There is no need to push and pop this large set of state, much like pixel maps. Adding a new attribute bit would have complicated logistics (would the bit be included in ALL_ATTRIB_BITS?). Having program local parameters provides a method for making localized changes to certain state simply by switching programs. (39) How should this extension interact with color material? RESOLVED: When color material is enabled, any bindings of material colors that track the current color should be updated when the current color is updated. In this specification, material properties can be bound only as program parameters, and any changes to the material properties inside a Begin/End leave the bindings undefined until the next End command. Similarly, any indirect changes to the material properties (through ColorMaterial) will have a similar effect. Several other options were considered here. One option was to support per-vertex material property bindings and have programs that reference tracked material properties should get the current color. This could be handled either by broadcasting the current color to multiple vertex attributes, or recompiling the vertex program so that references to a tracked material property are redirected to the vertex color. Both such solutions are somewhat complex. A second option would be to ignore the COLOR_MATERIAL enable and instead use an "old" material color. This breaks the standard color material model. Implementations can and often do defer such updates (making an "old" color available), some conditions may cause an implementation to update of material state at odd times. (41) What about when the execution environment involves support for other extensions? In particular, the execution environment subsumes some functionality from EXT/ARB_point_parameters, EXT_fog_coord, EXT_secondary_color, and ARB_multitexture. RESOLVED: This extension assumes support for functionality that includes a fog coordinate, secondary color, per-vertex point sizes, and multiple texture coordinates (at least to the extent that it exposes >1 texture coordinate). All of these extensions are supported fairly widely. On some platforms, some of this functionality may require software fallbacks. (42) How does PointSize work with vertex programs? RESOLVED: If VERTEX_PROGRAM_POINT_SIZE_ARB is disabled, the size of points is determined by the PointSize state and is not attenuated, even if EXT_point_parameters is supported. If enabled, the point size is the point size result value, and is clamped to implementation-dependent point size limits during point rasterization. (43) What do we say about the alpha component of the secondary color? RESOLVED: The alpha component of the secondary color has generally been treated as zero. This extension specifies that only the R, G, and B components are added in the color sum operation, making the alpha component of the secondary color irrelevant. Other downstream extensions may allow applications to make use of this component. (44) How are edge flags handled? RESOLVED: Edge flags are 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. (45) Should programs be C-style null-terminated strings? RESOLVED: 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 GetString returns null-terminated strings). Null-terminated strings may be problematic for some programming languages. (46) Should all existing OpenGL transform functionality and extensions be implementable as vertex programs? RESOLVED: 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 VERTEX_PROGRAM_POINT_SIZE_ARB enable is introduced. To implement two-sided lighting, the VERTEX_PROGRAM_TWO_SIDE_ARB enable is introduced. To implement color material, applications should refer to the per-vertex color attribute in their vertex programs. (47) Should there be a plural version of ProgramEnvParameter and ProgramLocalParameter, which would set multiple parameters in a single call? RESOLVED: No; not necessary. (48) Can the currently bound vertex program object be deleted or reloaded? RESOLVED: Yes. When ProgramStringARB is called to reload a program object, subsequent program executions will use the new program. When DeleteProgramsARB deletes a currently bound program object, object zero becomes the new current program object. (49) What happens if you transform vertices in vertex program mode, but the current program object does not contain a valid vertex program? RESOLVED: Begin will fail with an INVALID_OPERATION error if the currently bound vertex program object does not have a valid program. The same applies to RasterPos and any command (Rect, DrawArrays, DrawElements) that implies a Begin. Because Vertex is ignored outside of a Begin/End pair (without generating an error) it is impossible to provoke a vertex program if the current vertex program object is nonexistent or invalid. Other per-vertex parameters (for examples those set by Color, Normal, and VertexAttrib*ARB when the attribute number is not zero) are allowed since they are legal outside of a Begin/End. (50) Discussing matrices is confusing because of row-major versus column-major issues. Can you give an example of how a matrix is bound? RESOLVED: Assume program matrix zero were loaded with the following code: // 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 }; glMatrixMode(GL_MATRIX0_ARB); glLoadMatrixf(matrix); Then in the program !!ARBvp1.0 PARAM mat1[4] = { state.matrix.program[0] }; PARAM mat2[4] = { state.matrix.program[0].transpose }; mat1[0] would have (1,2,3,4), mat1[3] would have (13,14,15,16), mat2[0] would have (1,5,9,13), and mat2[3] would have (4,8,12,16). (51) Should the new vertex program-related enables push/pop with ENABLE_BIT? RESOLVED: Yes. Pushing and popping enable bits is easy. (52) Should all the vertex attribute state push/pop with CURRENT_BIT? RESOLVED: Yes. (53) Should all the vertex attrib vertex array state push/pop with CLIENT_VERTEX_ARRAY_BIT? RESOLVED: Yes. (55) Should we generate an INVALID_VALUE operation if updating a vertex attribute greater than MAX_VERTEX_ATTRIBS_ARB? RESOLVED: Yes. The other option would be to leave the behavior undefined, as with MultiTexCoord() functions. An implementation could mask or modulo the vertex attribute index with MAX_VERTEX_ATTRIB_ARB if it were a power of two. This error check will be a minor performance issue with VertexAttrib*ARB() and VertexAttribArrayARB() calls. There will be no per-vertex overhead when using vertex arrays or display lists. (56) Should writes to program environment or local parameters during a vertex program be supported? RESOLVED. 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 a severe implementation penalty for pipelined or parallel vertex program execution implementations. (58) Should program objects be shared among rendering contexts in the same manner as display lists and texture objects? RESOLVED: Yes. (60) Should there be a MatrixMode or ActiveTexture-style selector for vertex attributes? RESOLVED: No. While this would reduce the number of enumerants used by this extensions, it would create programming a hassle in lots of cases. Consider having to change the vertex attribute mode to enable a set of vertex arrays. (61) How should queries of vertex attribute arrays work? RESOLVED: Add new get commands. Using the existing calls would require adding 6 sets of 16+ enumerants for current state and vertex attribute array state. That's too many new enumerants. Instead, add GetVertexAttribARB and GetVertexAttribPointervARB. GetVertexAttribARB will be used to query vertex attribute array state and the current values of the generic vertex attributes. Get and GetPointerv will not return vertex attribute array state and pointers. (63) What should be said about rendering invariances? RESOLVED: 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. (64) Should there be a way to guarantee position invariance with respect to conventional vertex transformation? RESOLVED: Yes. The "OPTION ARB_position_invariant" program option addresses this issue. This program option will be available on all implementations of this extension. John Carmack advocated the need for this. (65) Why must RCP of 1.0 always be 1.0? RESOLVED: 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". (66) What happens when the source scalar value for the ARL instruction is an extremely large positive or negative floating-point value? Is there a problem mapping the value to a constrained integer range? RESOLVED: In this extension, address registers are only useful for relative addressing. The range of offsets that can be added to an address register is limited (-64 to +63) and the set of valid array indices is also limited to MAX_PROGRAM_PARAMETERS_ARB. So, the set of floating-point values that needs to be handled properly is well-constrained. (67) How do you perform a 3-component normalize in three instructions? RESOLVED: As follows. DP3 result.w, vector, vector; # result.w = nx^2+ny^2+nz^2 RSQ result.w, result.w; # result.w = 1/sqrt(nx^2+ny^2+nz^2) MUL result.xyz, result.w, vector; (69) How do you compute the determinant of a 3x3 matrix in three instructions? RESOLVED: As follows. # # Determinant of | vec0.x vec0.y vec0.z | into result. # | vec1.x vec1.y vec1.z | # | vec2.x vec2.y vec2.z | # MUL result, vec1.zxyw, vec2.yzxw; MAD result, vec1.yzxw, vec2.zxyw, -result; DP3 result, vec0, result; (70) How do you transform a vertex position by a 4x4 matrix and then perform a homogeneous divide? RESOLVED: As follows. ATTRIB pos = vertex.position; TEMP result, temp; PARAM mat[4] = { state.matrix.modelview }; DP4 result.w, pos, mat[3]; DP4 result.x, pos, mat[0]; DP4 result.y, pos, mat[1]; DP4 result.z, pos, mat[2]; RCP temp.w, result.w; MUL result, result, temp.w; (71) How do you perform a vector weighting of two vectors using a single weight? RESOLVED: As follows. # result = a * vec0 + (1-a) * vec1 # = vec1 + a * (vec0 - vec1) SUB result, vec0, vec1; MAD result, a, result, vec1; (72) How do you reduce a value to some fundamental period such as 2*PI? RESOLVED: As follows. # result = 2*PI * fraction(in/(2*PI)) # piVec = (1/(2*PI), 2*PI, 0, 0) PARAM piVec = { 0.159154943, 6.283185307, 0, 0 }; MUL result, in, piVec.x; EXP result, result.x; MUL result, result.y, piVec.y; (73) How do you implement a simple ambient, specular, and diffuse infinite lighting computation with a single light and an eye-space normal? RESOLVED: As follows. !!ARBvp1.0 ATTRIB iPos = vertex.position; ATTRIB iNormal = vertex.normal; PARAM mvinv[4] = { state.matrix.modelview.invtrans }; PARAM mvp[4] = { state.matrix.mvp }; PARAM lightDir = state.light[0].position; PARAM halfDir = state.light[0].half; PARAM specExp = state.material.shininess; PARAM ambientCol = state.lightprod[0].ambient; PARAM diffuseCol = state.lightprod[0].diffuse; PARAM specularCol = state.lightprod[0].specular; TEMP xfNormal, temp, dots; OUTPUT oPos = result.position; OUTPUT oColor = result.color; # Transform the vertex to clip coordinates. DP4 oPos.x, mvp[0], iPos; DP4 oPos.y, mvp[1], iPos; DP4 oPos.z, mvp[2], iPos; DP4 oPos.w, mvp[3], iPos; # Transform the normal to eye coordinates. DP3 xfNormal.x, mvinv[0], iNormal; DP3 xfNormal.y, mvinv[1], iNormal; DP3 xfNormal.z, mvinv[2], iNormal; # Compute diffuse and specular dot products and use LIT to compute # lighting coefficients. DP3 dots.x, xfNormal, lightDir; DP3 dots.y, xfNormal, halfDir; MOV dots.w, specExp.x; LIT dots, dots; # Accumulate color contributions. MAD temp, dots.y, diffuseCol, ambientCol; MAD oColor.xyz, dots.z, specularCol, temp; MOV oColor.w, diffuseCol.w; END (75) Can you perturb transformed vertex positions with a vertex program? RESOLVED: 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. !!ARBvp1.0 # # Program environment parameters: # c[0].xyz = normalized light direction in object-space # # outputs diffuse illumination for color and perturbed position # ATTRIB iPos = vertex.position; ATTRIB iNormal = vertex.normal; PARAM mvp[4] = { state.matrix.mvp }; PARAM lightDir = program.env[0]; PARAM diffuseCol = { 1, 1, 0, 1 }; TEMP temp; OUTPUT oPos = result.position; OUTPUT oColor = result.color; DP3 temp, lightDir, iNormal; MUL oColor.xyz, temp, diffuseCol; MAX temp, temp, 0; # clamp dot product to zero MUL temp, temp, iNormal; # align in direction of normal MUL temp, temp, 0.125; # scale displacement by 1/8 SUB temp, temp, iPos; # perturb DP4 oPos.x, mvp[0], temp; # xform using perturbed position DP4 oPos.y, mvp[1], temp; DP4 oPos.z, mvp[2], temp; DP4 oPos.w, mvp[3], temp; END (76) Should this extension provide any method for updating program parameters in a program itself? RESOLVED: No. NV_vertex_program provided a special mechanism to do this using a "vertex state program" manually executed by calling ExecuteProgramNV. This capability has not proven itself particularly useful to date. (78) Should there be a different ProgramStringARB call for every distinct program target? Arguably, 1D, 2D, and 3D textures each have their own TexImage command for specifying their image data. RESOLVED: No. All program objects can/should be loaded with ProgramStringARB. We expect the string to be a sufficient to express any kind of programmability. Moreover, the 1D, 2D, and 3D TexImage commands describe the image being specified as opposed to the texture target being updated. With cube map textures, there are six face texture targets that use the TexImage2D command but not with the TEXTURE_2D target. (79) This extension introduces a collection of new matrices for use by vertex programs (and possibly other programs as well). What should these matrices be called? RESOLVED: Program matrices. These matrices are referred to as "tracking matrices" in NV_vertex_program, but the functionality is equivalent. (80) With ARB_vertex_blend and EXT_vertex_weighting, there are multiple modelview matrices. This extension provides a single "MVP" matrix, defined to be the product of modelview matrix 0 and the projection matrices. Should this extension instead provide one MVP matrix per modelview matrix? RESOLVED: No. Providing multiple MVP matrices allows applications to do N transformations into clip space and then one weighting operation, instead of N transformations into eye space, a weighting operation, and then a single transformation into clip space. This would potentially save instructions, but this optimization would be of no value if the program did any other operations that required eye coordinates. Note also that the MVP transformations are likely general 4x4 matrix multiplies (4 DP4 instructions per transform). On the other hand, object and eye coordinates are often 3D coordinates with a constant W of 1.0. So each transformation to eye coordinates may require only 3 DP4 instructions, in which case the comparison may be 4N instructions (clip weighting) vs. 3N+4 (eye weighting). (81) Should variable declarations be allowed to be anywhere within the program body, or should they instead be required to be done at the beginning of the program? Should the possibility of branching in a future standard affect this resolution? RESOLVED: Declarations will be allowed anywhere in the program text; the only ordering requirement is that the declaration of a variable must precede its use in the program text. Requiring up-front variable declarations may require multiple passes for applications that build programs on the fly. While declarations can appear anywhere in the program body, they are not executable statements. Any corresponding bindings (including constant initializations) are resolved before the program executes. The bindings will be resolved even if a program were to "branch around" a declaration. (82) Should address register variables be treated as vectors? If so, should a variable number of components (up to four) be supported by this extension? RESOLVED: In the future, four-component address vectors may be supported, and vector notation is used for forward compatibility. Using this notation makes address registers consistent with all the other vector data types in this extension. However, support for more than one usable component will be left for future extensions, but could be added via a program option or in a new language revision (e.g., !!ARBvp2.0). (83) Should program local parameters be logically connected to the program string or the program object? RESOLVED: Program local parameters are properties of a program object. Their values persist even after a new program is loaded into the object. This model does allow applications to recompile the program in a given object based on certain rendering settings without having to re-initialize any state stored in the object. (84) Should this extension provide a method to specify "anonymous" program local parameters and query an index into the program parameter array. RESOLVED: No. It would be nice to declare a variable in a program such as PARAM foo = program.local; # note no index in the array after which an application could query the location of "foo" in the program local parameter array. However, given that local parameters persist even across program loads, it would be difficult to specify what program local parameter "foo" would be assigned to. (85) EXT_vertex_weighting provides a single vertex blend weight. ARB_vertex_blend generalizes this concept to a weight vector. Both pieces of state are specified separately, and could be thought of as distinct. Should distinct bindings be provided in this extension? RESOLVED: No. No current implementation supports both extensions, but the vendors involved in this standardization process agree that the state should not be considered distinct. If an implementation supported both extensions, the APIs would modify the same state. (86) Should this extension provide functionality for variable aliasing? If so, how should it be specified and what types of variables can be aliasesed? RESOLVED: Yes, for all variable types. The syntax is a simple text replacement: ALIAS a = b; This functionality allows applications to "share" variables, and thereby exceed implementation-dependent limits on the number of variable declarations. This may be particularly significant for temporaries, where the limit on the number of variables may be fairly low. (87) How do you determine whether a given program option is supported by the GL implementation? RESOLVED: Program options may be introduced in OpenGL extensions and may be added to future OpenGL specifications. An option will be supported if and only if (1) the corresponding OpenGL extension appears in the implementation-dependent EXTENSIONS string or (2) the option is documented in the OpenGL specification version corresponding to the implementation's VERSION string. The ARB_position_invariant option is provided by this extension, and will always be available (provided this extension is supported). (88) What's the deal with binding the alpha component of light colors, fog colors, and material colors (other than diffuse)? They don't do anything, right? RESOLVED: The GL state for these different colors includes alpha components, which will be returned by queries. However, in the conventional OpenGL pipeline, most of these alpha components are effectively ignored. However, since they are present in the GL state, they will be exposed in bindings. What is done with these alpha values in program mode is completely up to the vertex program. Vertex programs need to be careful to ensure that the alpha component is computed correctly when evaluating lighting equations. When accumulating light contributions, it may be necessary to use write masks to disable writes to the alpha component. (89) The LOG instruction takes the logarithm of the absolute value of its operand while the LG2 instruction takes the logarithm of the operand itself. In LG2, the logarithm of negative numbers is undefined. RESOLVED: The LOG instruction is present for (1) compatibility with NV_vertex_program and DirectX 8 languages and (2) because it may outperform LG2 on some platforms. For compatibility, it is defined to behave identically to existing languages. (90) With vertex programs, fog coordinates and point sizes can be computed on a per-vertex basis. How are the fog coordinates and point sizes associated with vertices introduced by clipping computed? RESOLVED: Fog coordinates and point sizes for clipped vertices are computed by interpolating the computed values at the original vertices in exactly the same manner as colors and texture coordinates are interpolated in section 2.13.8 of the OpenGL 1.3 specification. (91) Vertex programs support only RGBA colors, but do not support color index inputs or results. What happens if an application uses vertex programs in color index mode. RESOLVED: The results of vertex program execution are undefined if the GL is in color index mode. (92) Should automatic normalization of evaluated normals (AUTO_NORMAL) be supported when the GL is in vertex program mode? RESOLVED: Automatic normalization of normals will be disabled 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 normalizing again 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. (93) This extension allows applications to name their own variables. What keywords should be reserved? RESOLVED: Instruction names and declaration keywords (e.g., PARAM) will be reserved. Additionally, since attribute, parameter, and result bindings are allowed in the program text, the binding prefix keywords "vertex", "state", "program", and "result" are reserved to simplify parsing. This prevents the need to distinguish between "vertex.position" ("vertex" as a binding) and "vertex.xyzw" ("vertex" as a variable). (94) When counting the number of program parameter bindings, multiple constant vectors with the same components are counted only once. How is this determined? RESOLVED: The implementation does a numerical comparison after the specified constants are converted to an internal floating-point representation. Due to floating-point representation limits, such conversions are not always precise. Constants specified with different text that are "equivalent" (e.g., "12" and "1.2E+01") are not guaranteed to resolve to the same value. Additionally, constants that are not "equivalent" but have only small relative differences (e.g., "200000000" and "200000001") may end up resolving to the same value. Constants specified with the same text should always be identical. (95) What characters are allowed in identifier names? RESOLVED: Letters ("A"-"Z", "a"-"z"), numbers ("0"-"9"), underscores ("_"), and dollar signs ("$"). (96) How should future programmability extensions interact with this one? RESOLVED: Future programmability extensions are expected to fall in one of two classes: (1) extensions that bring programmability to new sections and (2) extensions the extend existing programmability models. The former class should introduce a new program target; the latter class would extend the functionality of an existing target. Recommendations for extensions introducing new program targets include: * Re-use and reference the functionality specified in this extension (or in a future OpenGL specification incorporating this extension) as much as possible, to maintain a consistent model. * Provide a program header allowing for easy identification and versioning of programs for the new target. Recommendations for extensions modifying existing program targets include: * The option mechanism (section 2.14.4.5) should be used to provide minor modifications to the program language. * The program header/version string (section 2.14.2) should be used to provide major modifications to the language, or potentially to provide a commonly used collection of options. Program header string changes should be multi-vendor extensions as much as possible. * For portability, programs should not be allowed to use extended language features without specifying the corresponding program options or program header. New Procedures and Functions void VertexAttrib1sARB(uint index, short x); void VertexAttrib1fARB(uint index, float x); void VertexAttrib1dARB(uint index, double x); void VertexAttrib2sARB(uint index, short x, short y); void VertexAttrib2fARB(uint index, float x, float y); void VertexAttrib2dARB(uint index, double x, double y); void VertexAttrib3sARB(uint index, short x, short y, short z); void VertexAttrib3fARB(uint index, float x, float y, float z); void VertexAttrib3dARB(uint index, double x, double y, double z); void VertexAttrib4sARB(uint index, short x, short y, short z, short w); void VertexAttrib4fARB(uint index, float x, float y, float z, float w); void VertexAttrib4dARB(uint index, double x, double y, double z, double w); void VertexAttrib4NubARB(uint index, ubyte x, ubyte y, ubyte z, ubyte w); void VertexAttrib1svARB(uint index, const short *v); void VertexAttrib1fvARB(uint index, const float *v); void VertexAttrib1dvARB(uint index, const double *v); void VertexAttrib2svARB(uint index, const short *v); void VertexAttrib2fvARB(uint index, const float *v); void VertexAttrib2dvARB(uint index, const double *v); void VertexAttrib3svARB(uint index, const short *v); void VertexAttrib3fvARB(uint index, const float *v); void VertexAttrib3dvARB(uint index, const double *v); void VertexAttrib4bvARB(uint index, const byte *v); void VertexAttrib4svARB(uint index, const short *v); void VertexAttrib4ivARB(uint index, const int *v); void VertexAttrib4ubvARB(uint index, const ubyte *v); void VertexAttrib4usvARB(uint index, const ushort *v); void VertexAttrib4uivARB(uint index, const uint *v); void VertexAttrib4fvARB(uint index, const float *v); void VertexAttrib4dvARB(uint index, const double *v); void VertexAttrib4NbvARB(uint index, const byte *v); void VertexAttrib4NsvARB(uint index, const short *v); void VertexAttrib4NivARB(uint index, const int *v); void VertexAttrib4NubvARB(uint index, const ubyte *v); void VertexAttrib4NusvARB(uint index, const ushort *v); void VertexAttrib4NuivARB(uint index, const uint *v); void VertexAttribPointerARB(uint index, int size, enum type, boolean normalized, sizei stride, const void *pointer); void EnableVertexAttribArrayARB(uint index); void DisableVertexAttribArrayARB(uint index); void ProgramStringARB(enum target, enum format, sizei len, const void *string); void BindProgramARB(enum target, uint program); void DeleteProgramsARB(sizei n, const uint *programs); void GenProgramsARB(sizei n, uint *programs); void ProgramEnvParameter4dARB(enum target, uint index, double x, double y, double z, double w); void ProgramEnvParameter4dvARB(enum target, uint index, const double *params); void ProgramEnvParameter4fARB(enum target, uint index, float x, float y, float z, float w); void ProgramEnvParameter4fvARB(enum target, uint index, const float *params); void ProgramLocalParameter4dARB(enum target, uint index, double x, double y, double z, double w); void ProgramLocalParameter4dvARB(enum target, uint index, const double *params); void ProgramLocalParameter4fARB(enum target, uint index, float x, float y, float z, float w); void ProgramLocalParameter4fvARB(enum target, uint index, const float *params); void GetProgramEnvParameterdvARB(enum target, uint index, double *params); void GetProgramEnvParameterfvARB(enum target, uint index, float *params); void GetProgramLocalParameterdvARB(enum target, uint index, double *params); void GetProgramLocalParameterfvARB(enum target, uint index, float *params); void GetProgramivARB(enum target, enum pname, int *params); void GetProgramStringARB(enum target, enum pname, void *string); void GetVertexAttribdvARB(uint index, enum pname, double *params); void GetVertexAttribfvARB(uint index, enum pname, float *params); void GetVertexAttribivARB(uint index, enum pname, int *params); void GetVertexAttribPointervARB(uint index, enum pname, void **pointer); boolean IsProgramARB(uint program); New Tokens Accepted by the parameter of Disable, Enable, and IsEnabled, by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev, and by the parameter of ProgramStringARB, BindProgramARB, ProgramEnvParameter4[df][v]ARB, ProgramLocalParameter4[df][v]ARB, GetProgramEnvParameter[df]vARB, GetProgramLocalParameter[df]vARB, GetProgramivARB, and GetProgramStringARB. VERTEX_PROGRAM_ARB 0x8620 Accepted by the parameter of Disable, Enable, and IsEnabled, and by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: VERTEX_PROGRAM_POINT_SIZE_ARB 0x8642 VERTEX_PROGRAM_TWO_SIDE_ARB 0x8643 COLOR_SUM_ARB 0x8458 Accepted by the parameter of ProgramStringARB: PROGRAM_FORMAT_ASCII_ARB 0x8875 Accepted by the parameter of GetVertexAttrib[dfi]vARB: VERTEX_ATTRIB_ARRAY_ENABLED_ARB 0x8622 VERTEX_ATTRIB_ARRAY_SIZE_ARB 0x8623 VERTEX_ATTRIB_ARRAY_STRIDE_ARB 0x8624 VERTEX_ATTRIB_ARRAY_TYPE_ARB 0x8625 VERTEX_ATTRIB_ARRAY_NORMALIZED_ARB 0x886A CURRENT_VERTEX_ATTRIB_ARB 0x8626 Accepted by the parameter of GetVertexAttribPointervARB: VERTEX_ATTRIB_ARRAY_POINTER_ARB 0x8645 Accepted by the parameter of GetProgramivARB: PROGRAM_LENGTH_ARB 0x8627 PROGRAM_FORMAT_ARB 0x8876 PROGRAM_BINDING_ARB 0x8677 PROGRAM_INSTRUCTIONS_ARB 0x88A0 MAX_PROGRAM_INSTRUCTIONS_ARB 0x88A1 PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A2 MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB 0x88A3 PROGRAM_TEMPORARIES_ARB 0x88A4 MAX_PROGRAM_TEMPORARIES_ARB 0x88A5 PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A6 MAX_PROGRAM_NATIVE_TEMPORARIES_ARB 0x88A7 PROGRAM_PARAMETERS_ARB 0x88A8 MAX_PROGRAM_PARAMETERS_ARB 0x88A9 PROGRAM_NATIVE_PARAMETERS_ARB 0x88AA MAX_PROGRAM_NATIVE_PARAMETERS_ARB 0x88AB PROGRAM_ATTRIBS_ARB 0x88AC MAX_PROGRAM_ATTRIBS_ARB 0x88AD PROGRAM_NATIVE_ATTRIBS_ARB 0x88AE MAX_PROGRAM_NATIVE_ATTRIBS_ARB 0x88AF PROGRAM_ADDRESS_REGISTERS_ARB 0x88B0 MAX_PROGRAM_ADDRESS_REGISTERS_ARB 0x88B1 PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B2 MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB 0x88B3 MAX_PROGRAM_LOCAL_PARAMETERS_ARB 0x88B4 MAX_PROGRAM_ENV_PARAMETERS_ARB 0x88B5 PROGRAM_UNDER_NATIVE_LIMITS_ARB 0x88B6 Accepted by the parameter of GetProgramStringARB: PROGRAM_STRING_ARB 0x8628 Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: PROGRAM_ERROR_POSITION_ARB 0x864B CURRENT_MATRIX_ARB 0x8641 TRANSPOSE_CURRENT_MATRIX_ARB 0x88B7 CURRENT_MATRIX_STACK_DEPTH_ARB 0x8640 MAX_VERTEX_ATTRIBS_ARB 0x8869 MAX_PROGRAM_MATRICES_ARB 0x862F MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB 0x862E Accepted by the parameter of GetString: PROGRAM_ERROR_STRING_ARB 0x8874 Accepted by the parameter of MatrixMode: MATRIX0_ARB 0x88C0 MATRIX1_ARB 0x88C1 MATRIX2_ARB 0x88C2 MATRIX3_ARB 0x88C3 MATRIX4_ARB 0x88C4 MATRIX5_ARB 0x88C5 MATRIX6_ARB 0x88C6 MATRIX7_ARB 0x88C7 MATRIX8_ARB 0x88C8 MATRIX9_ARB 0x88C9 MATRIX10_ARB 0x88CA MATRIX11_ARB 0x88CB MATRIX12_ARB 0x88CC MATRIX13_ARB 0x88CD MATRIX14_ARB 0x88CE MATRIX15_ARB 0x88CF MATRIX16_ARB 0x88D0 MATRIX17_ARB 0x88D1 MATRIX18_ARB 0x88D2 MATRIX19_ARB 0x88D3 MATRIX20_ARB 0x88D4 MATRIX21_ARB 0x88D5 MATRIX22_ARB 0x88D6 MATRIX23_ARB 0x88D7 MATRIX24_ARB 0x88D8 MATRIX25_ARB 0x88D9 MATRIX26_ARB 0x88DA MATRIX27_ARB 0x88DB MATRIX28_ARB 0x88DC MATRIX29_ARB 0x88DD MATRIX30_ARB 0x88DE MATRIX31_ARB 0x88DF Additions to Chapter 2 of the OpenGL 1.3 Specification (OpenGL Operation) Modify Section 2.6, Begin/End Paradigm (p. 12) (modify last paragraph, p. 12) ... In addition, a current normal, a current color, multiple current texture coordinate sets, and multiple generic vertex attributes may be used in processing each vertex. Normals are used by the GL in lighting calculations; the current normal is a three-dimensional vector that may be set by sending three coordinates that specify it. Texture coordinates determine how a texture image is mapped onto a primitive. Multiple sets of texture coordinates may be used to specify how multiple texture images are mapped onto a primitive. Generic vertex attributes do not have any specific function but can be used in vertex program mode (section 2.14) to compute final values for any data associated with a vertex. Modify Section 2.6.3, GL Commands within Begin/End (p. 19) (modify first paragraph of section, p. 19) The only GL commands that are allowed within any Begin/End pairs are the commands for specifying vertex coordinates, vertex color, normal coordinates, texture coordinates, and generic vertex attributes (Vertex, Color, Index, Normal, TexCoord, VertexAttrib*ARB), ... Modify Section 2.7, Vertex Specification (p. 19) (remove the "Finally" from the next-to-last paragraph, p. 20) There are several ways to set the current color. The GL stores both a current single-valued color index, and a current four-valued RGBA color. One (add new paragraph before last paragraph of section, p. 21) Vertex programs (section 2.14) can access an array of four-component generic current vertex attributes. The first entry of this array is numbered zero, and the number of entries in the array is given by the implementation-dependent constant MAX_VERTEX_ATTRIBS_ARB. The commands void VertexAttrib{1234}{sfd}ARB(uint index, T coords); void VertexAttrib{123}{sfd}vARB(uint index, T coords); void VertexAttrib4{bsifd ubusui}vARB(uint index, T coords); specify the current vertex attribute numbered , whose components are named , , , and . The VertexAttrib1ARB family of commands sets the coordinate to the provided single argument while setting and to 0 and to 1. Similarly, VertexAttrib2ARB commands set and to the specified values, to 0 and to 1; VertexAttrib3ARB commands set , , and , with set to 1, and VertexAttrib4ARB commands set all four coordinates. The error INVALID_VALUE is generated if is greater than or equal to MAX_VERTEX_ATTRIBS_ARB. The commands void VertexAttrib4NubARB(uint index, T coords); void VertexAttrib4N{bsi ubusui}vARB(uint index, T coords); also specify vertex attributes with fixed-point coordinates that are scaled to the range [0,1] or [-1,1], according to Table 2.6. Setting generic vertex attribute zero specifies a vertex; the four vertex coordinates are taken from the values of attribute zero. A Vertex2, Vertex3, or Vertex4 command is completely equivalent to the corresponding VertexAttrib command with an index of zero. Setting any other generic vertex attribute updates the current values of the attribute. There are no current values for vertex attribute zero. Implementations may, but do not necessarily, use the same storage for the current values of generic and certain conventional vertex attributes. When any generic vertex attribute other than zero is specified, the current values for the corresponding conventional attribute in Table X.1 become undefined. Additionally, when a conventional vertex attribute is specified, the current values for the corresponding generic vertex attribute in Table X.1 become undefined. For example, setting the current normal will leave generic vertex attribute 2 undefined, and vice versa. Generic Attribute Conventional Attribute Conventional Attribute Command --------- ------------------------ ------------------------------ 0 vertex position Vertex 1 vertex weights 0-3 WeightARB, VertexWeightEXT 2 normal Normal 3 primary color Color 4 secondary color SecondaryColorEXT 5 fog coordinate FogCoordEXT 6 - - 7 - - 8 texture coordinate set 0 MultiTexCoord(TEXTURE0, ...) 9 texture coordinate set 1 MultiTexCoord(TEXTURE1, ...) 10 texture coordinate set 2 MultiTexCoord(TEXTURE2, ...) 11 texture coordinate set 3 MultiTexCoord(TEXTURE3, ...) 12 texture coordinate set 4 MultiTexCoord(TEXTURE4, ...) 13 texture coordinate set 5 MultiTexCoord(TEXTURE5, ...) 14 texture coordinate set 6 MultiTexCoord(TEXTURE6, ...) 15 texture coordinate set 7 MultiTexCoord(TEXTURE7, ...) 8+n texture coordinate set n MultiTexCoord(TEXTURE0+n, ...) Table X.1, Generic and Conventional Vertex Attribute Mappings. For each row, the current value of the conventional attribute becomes undefined when the corresponding generic attribute is set, and vice versa. Attribute zero corresponds to the vertex position and has no current state. Setting any conventional vertex attribute not listed in Table X.1 (including vertex weights 4 and above, if supported) will not cause any generic vertex attribute to become undefined, and such attributes will not become undefined when any generic vertex attribute is set. (modify the last paragraph in the section, p.21) The state required to support vertex specification consists of four floating-point numbers per texture unit to store the current texture coordinates s, t, r, and q, three floating-point numbers to store the three coordinates of the current normal, four floating-point values to store the current RGBA color, one floating-point value to store the current color index, and MAX_VERTEX_ATTRIBS_ARB-1 four-component floating-point vectors for generic vertex attributes. There is no notion of a current vertex, so no state is devoted to vertex coordinates or vertex attribute zero. The initial texture coordinates are (S,T,R,Q) = (0,0,0,1) for each texture unit. The initial current normal has coordinates (0,0,1). The initial RGBA color is (R,G,B,A) = (1,1,1,1). The initial color index is 1. The initial values for all generic vertex attributes are undefined. Modify Section 2.8, Vertex Arrays (p. 21) (modify first paragraph of section, p.21) The vertex specification commands described in section 2.7 accept data in almost any format, but their use requires many command executions to specify even simple geometry. Vertex data may also be placed into arrays that are stored in the client's address space. Blocks of data in these arrays may then be used to specify multiple geometric primitives through the execution of a single GL command. The client may specify up to 5 plus the values of MAX_TEXTURE_UNITS and MAX_VERTEX_ATTRIBS_ARB arrays: one each to store vertex coordinates, edge flags, colors, color indices, normals, one or more texture coordinate sets, and one or more generic vertex attributes. The commands ... void VertexAttribPointerARB(uint index, int size, enum type, boolean normalized, sizei stride, const void *pointer); describe the locations and organizations... (add after the first paragraph, p.22) The parameter in the VertexAttribPointer command identifies the generic vertex attribute array being described. The error INVALID_VALUE is generated if is greater than or equal to MAX_VERTEX_ATTRIBS_ARB. The parameter in the VertexAttribPointer command identifies whether fixed-point types should be normalized when converted to floating-point. If is TRUE, fixed-point data are converted as specified in Table 2.6; otherwise, the fixed-point values are converted directly. (add after first paragraph, p.23) An individual generic vertex attribute array is enabled or disabled by calling one of void EnableVertexAttribArrayARB(uint index); void DisableVertexAttribArrayARB(uint index); where identifies the generic vertex attribute array to enable or disable. The error INVALID_VALUE is generated if is greater than or equal to MAX_VERTEX_ATTRIBS_ARB. (modify Table 2.4, p.23) Normal Command Sizes ized? Types ---------------------- ------- ------ -------------------------------- VertexPointer 2,3,4 no short, int, float, double NormalPointer 3 yes byte, short, int, float, double ColorPointer 3,4 yes byte, ubyte, short, ushort, int, uint, float, double IndexPointer 1 no ubyte, short, int, float, double TexCoordPointer 1,2,3,4 no short, int, float, double EdgeFlagPointer 1 no boolean VertexAttribPointerARB 1,2,3,4 flag byte, ubyte, short, ushort, int, uint, float, double WeightPointerARB >=1 yes byte, ubyte, short, ushort, int, uint, float, double VertexWeightPointerEXT 1 n/a float SecondaryColor- 3 yes byte, ubyte, short, ushort, PointerEXT int, uint, float, double FogCoordPointerEXT 1 n/a float, double MatrixIndexPointerARB >=1 no ubyte, ushort, uint Table 2.4: Vertex array sizes (values per vertex) and data types. The "normalized" column indicates whether fixed-point types are accepted directly or normalized to [0,1] (for unsigned types) or [-1,1] (for singed types). For generic vertex attributes, fixed-point data are normalized if and only if the flag is set. (modify last paragraph, p.23) The command void ArrayElement(int i); transfers the ith element of every enabled array to the GL. The effect of ArrayElement(i) is the same as the effect of the command sequence if (ARB_vertex_blend vertex weight array enabled) { Weight[type]vARB(vertex weight array size, vertex weight array element i); } if (EXT_vertex_weighting vertex weight array enabled) { VertexWeight[type]vARB(vertex weight array element i); } if (normal array enabled) { Normal3[type]v(normal array element i); } if (color array enabled) { Color[size][type]v(color array element i); } if (secondary color array enabled) { SecondaryColor3[type]vEXT(secondary color array element i); } if (fog coordinate array enabled) { FogCoord[type]vEXT(fog coordinate array element i); } if (matrix index array enabled) { MatrixIndex[type]vARB(matrix index array size, matrix index array element i); } for (j = 0; j < textureUnits; j++) { if (texture coordinate set j array enabled) { MultiTexCoord[size][type]v(TEXTURE0 + j, texture coordinate set j array element i); } if (color index array enabled) { Index[type]v(color index array element i); } if (edge flag array enabled) { EdgeFlagv(edge flag array element i); } for (j = 1; j < genericAttributes; j++) { if (generic vertex attribute j array enabled) { if (generic vertex attribute j array normalization flag is set, and type is not FLOAT or DOUBLE) { VertexAttrib[size]N[type]vARB(j, generic vertex attribute j array element i); } else { VertexAttrib[size][type]vARB(j, generic vertex attribute j array element i); } } } if (generic attribute array 0 enabled) { if (generic vertex attribute j array normalization flag is set, and type is not FLOAT or DOUBLE) { VertexAttrib[size]N[type]vARB(0, generic vertex attribute 0 array element i); } else { VertexAttrib[size][type]vARB(0, generic vertex attribute 0 array element i); } } else if (vertex array enabled) { Vertex[size][type]vARB(vertex array element i); } where and give the number of texture units and generic vertex attributes supported by the implementation, respectively. "[size]" and "[type]" correspond to the size and type of the corresponding array. For generic vertex attributes, it is assumed that a complete set of vertex attribute commands exists, even though not all such functions are provided by the GL. Both generic attribute array zero and the vertex array can specify a vertex if enabled, but only one such array is used. As described in section 2.7, setting a generic vertex attributes listed in Table X.1 will leave the corresponding conventional vertex attribute undefined, and vice versa. (modify last paragraph of section, p.28) If the number of supported texture units (the value of MAX TEXTURE UNITS) is m and the number of supported generic vertex attributes (MAX_VERTEX_ATTRIBS_ARB) is n, then the client state required to implement vertex arrays consists of 5+m+n boolean enables, 5+m+n memory pointers, 5+m+n integer stride values, 4+m+n symbolic constants representing array types, 2+m+n integers representing values per element, and n boolean normalization flags. In the initial state, the enable values are each disabled, the memory pointers are each null, the strides are each zero, the array types are each FLOAT, the integers representing values per element are each four, and the normalization flags are disabled.. Modify Section 2.10, Coordinate Transformations (p. 29) (add new paragraphs) Vertex attributes are transformed before the vertex is used to generate primitives for rasterization, establish a raster position, or generate vertices for selection or feedback. The attributes of each vertex are transformed using one of two vertex transformation modes. The first mode, described in this and subsequent sections, is GL's conventional vertex transformation model. The second mode, known as vertex program mode and described in section 2.14, transforms vertex attributes as specified in an application-supplied vertex program. Vertex program mode is enabled and disabled, respectively, by void Enable(enum target); and void Disable(enum target); with equal to VERTEX_PROGRAM_ARB. When vertex program mode is enabled, vertices are transformed by the currently bound vertex program as discussed in section 2.14. 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 this case. The discussion that continues through section 2.13 applies when vertex program mode is disabled. Modify Section 2.10.2, Matrices (p. 31) (modify 1st paragraph) The projection matrix and model-view matrix are set and modified with a variety of commands. The affected matrix is determined by the current matrix mode. The current matrix mode is set with void MatrixMode(enum mode); which takes one of the pre-defined constants TEXTURE, MODELVIEW, COLOR, PROJECTION, or MATRIX_ARB as the argument. In the case of MATRIX_ARB, is an integer between 0 and -1 indicating one of program matrices where is the value of the implementation defined constant MAX_PROGRAM_MATRICES_ARB. Such program matrices are described in section 2.14.6. TEXTURE is described later in section 2.10.2, and COLOR is described in section 3.6.3. If the current matrix mode is MODELVIEW, then matrix operations apply to the model-view matrix; if PROJECTION, then they apply to the projection matrix. (modify last paragraph of section) The state required to implement transformations consists of a -value integer indicating the current matrix mode (where is 4 + the number of supported texture and program matrices), a stack of at least two 4x4 matrices for each of COLOR, PROJECTION, and TEXTURE with associated stack pointers, stacks (where is at least 8) of at least one 4x4 matrix for each MATRIX_ARB with associated stack pointers, and a stack of at least 32 4x4 matrices with an associated stack pointer for MODELVIEW. Initially, there is only one matrix on each stack, and all matrices are set to the identity. The initial matrix mode is MODELVIEW. The initial value of ACTIVE_TEXTURE is TEXTURE0. Modify Section 2.11, Clipping (p. 39) (add to end of next-to-last paragraph, p. 40) ... User clipping is not supported in vertex program mode if the current program is not position-invariant (section 2.14.4.5.1). In this case, client-defined clip planes are always treated as disabled. Modify Section 2.12, Current Raster Position (p. 42) (modify fourth paragraph, p.42) The coordinates are treated as if they were specified in a Vertex command. If vertex program mode is enabled, the currently bound vertex program is executed, using the x, y, z, and w coordinates as the object coordinates of the vertex. Otherwise, the x, y, z, and w coordinates are transformed by the current model-view and projection matrices. These coordinates, along with current values, are used to generate a color and texture coordinates just as is done for a vertex. The color and texture coordinates produced using either method replace the color and texture coordinates stored in the current raster position's associated data. When in vertex program mode, the "x" component of the fog coordinate result replaces the current raster distance; otherwise, the distance from the origin of the eye coordinate system to the vertex as transformed by only the current model-view matrix replaces the current raster distance. The latter distance can be approximated (see section 3.10). Rename and Modify Section 2.13.8, Color and Vertex Data Clipping (p.56) (modify second paragraph, p.57) Texture coordinates, as well as fog coordinates and point sizes computed on a per-vertex basis, must also be clipped when a primitive is clipped. The method is exactly analogous to that used for color clipping. Add New Section 2.14 and subsections (p. 57). 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. A vertex program is a character string that specifies a sequence of operations to perform. Vertex program instructions are typically 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 any 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 instruction can be used immediately afterwards. The result of a vertex program is a set of vertex result registers that becomes the set of transformed vertex attributes used during clipping and primitive assembly. Vertex programs are defined to operate only in RGBA mode. The results of vertex program execution are undefined if the GL is in color index mode. Section 2.14.1, Program Objects The GL provides one or more program targets, each identifying a portion of the GL that can be controlled through application-specified programs. The program target for vertex programs is VERTEX_PROGRAM_ARB. Each program target has an associated program object, called the current program object. Each program target also has a default program object, which is initially the current program object. Each program object has an associated program string. The command ProgramStringARB(enum target, enum format, sizei len, const void *string); updates the program string for the current program object for . describes the format of the program string, which must currently be PROGRAM_FORMAT_ASCII_ARB. is a pointer to the array of bytes representing the program string being loaded, which need not be null-terminated. The length of the array is given by . If is null-terminated, should not include the terminator. When a program string is loaded, it is interpreted according to syntactic and semantic rules corresponding to the program target specified by . If a program violates the syntactic or semantic restrictions of the program target, ProgramStringARB generates the error INVALID_OPERATION. Additionally, ProgramString will update the program error position (PROGRAM_ERROR_POSITION_ARB) and error string (PROGRAM_ERROR_STRING_ARB). If a program fails to load, the value of the program error position is set to the ubyte offset into the specified program string indicating where the first program error was detected. If the program fails to load because of a semantic restriction that is not detected until the program is fully scanned, the error position is set to the value of . If a program loads successfully, the error position is set to the value negative one. The implementation-dependent program error string contains one or more error or warning messages. If a program loads succesfully, the error string may either contain warning messages or be empty. Each program object has an associated array of program local parameters. The number and type of program local parameters is target- and implementation-dependent. For vertex programs, program local parameters are four-component floating-point vectors. The number of vectors is given by the implementation-dependent constant MAX_PROGRAM_LOCAL_PARAMETERS_ARB, which must be at least 96. The commands void ProgramLocalParameter4fARB(enum target, uint index, float x, float y, float z, float w); void ProgramLocalParameter4fvARB(enum target, uint index, const float *params); void ProgramLocalParameter4dARB(enum target, uint index, double x, double y, double z, double w); void ProgramLocalParameter4dvARB(enum target, uint index, const double *params); update the values of the program local parameter numbered belonging to the program object currently bound to . For ProgramLocalParameter4fARB and ProgramLocalParameter4dARB, the four components of the parameter are updated with the values of , , , and , respectively. For ProgramLocalParameter4fvARB and ProgramLocalParameter4dvARB, the four components of the parameter are updated with the array of four values pointed to by . The error INVALID_VALUE is generated if is greater than or equal to the number of program local parameters supported by . Additionally, each program target has an associated array of program environment parameters. Unlike program local parameters, program environment parameters are shared by all program objects of a given target. The number and type of program environment parameters is target- and implementation-dependent. For vertex programs, program environment parameters are four-component floating-point vectors. The number of vectors is given by the implementation-dependent constant MAX_PROGRAM_ENV_PARAMETERS_ARB, which must be at least 96. The commands void ProgramEnvParameter4fARB(enum target, uint index, float x, float y, float z, float w); void ProgramEnvParameter4fvARB(enum target, uint index, const float *params); void ProgramEnvParameter4dARB(enum target, uint index, double x, double y, double z, double w); void ProgramEnvParameter4dvARB(enum target, uint index, const double *params); update the values of the program environment parameter numbered for the given program target . For ProgramEnvParameter4fARB and ProgramEnvParameter4dARB, the four components of the parameter are updated with the values of , , , and , respectively. For ProgramEnvParameter4fvARB and ProgramEnvParameter4dvARB, the four components of the parameter are updated with the array of four values pointed to by . The error INVALID_VALUE is generated if is greater than or equal to the number of program environment parameters supported by . Each program target has a default program object. Additionally, named program objects can be created and operated upon. The name space for program objects is the positive integers and is shared by programs of all targets. The name zero is reserved by the GL. A named program object is created by binding an unused program object name to a valid program target. The binding is effected by calling BindProgramARB(enum target, uint program); with set to the desired program target and set to the unused program name. The resulting program object has a program target given by and is assigned target-specific default values (see section 2.14.7 for vertex programs). BindProgramARB may also be used to bind an existing program object to a program target. If is zero, the default program object for is bound. If is the name of an existing program object whose associated program target is , the named program object is bound. The error INVALID_OPERATION is generated if names an existing program object whose associated program target is anything other than . Programs objects are deleted by calling void DeleteProgramsARB(sizei n, const uint *programs); contains names of programs to be deleted. After a program object is deleted, its name is again unused. If a program object that is bound to any target is deleted, it is as though BindProgramARB is first executed with same target and a of zero. Unused names in are silently ignored, as is the value zero. The command void GenProgramsARB(sizei n, uint *programs); returns currently unused program names in . These names are marked as used, for the purposes of GenProgramsARB only, but objects are created only when they are first bound using BindProgramARB. Section 2.14.2, Vertex Program Grammar and Semantic Restrictions Vertex program strings are specified as an array of ASCII characters containing the program text. When a vertex program is loaded by a call to ProgramStringARB, the program string is parsed into a set of tokens possibly separated by whitespace. Spaces, tabs, newlines, carriage returns, and comments are considered whitespace. Comments begin with the character "#" and are terminated by a newline, a carriage return, or the end of the program array. The Backus-Naur Form (BNF) grammar below specifies the syntactically valid sequences for 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. A vertex program is required to begin with the header string "!!ARBvp1.0", without any preceding whitespace. This string identifies the subsequent program text as a vertex program (version 1.0) that should be parsed according to the following grammar and semantic rules. Program string parsing begins with the character immediately following the header string. ::= "END" ::=