back  Return to list

GL_ARB_fragment_program
homeprevnext Name
  
    ARB_fragment_program  
  
homeprevnext Name Strings
  
    GL_ARB_fragment_program  
  
homeprevnext Contributors
  
    Bob Beretta  
    Pat Brown  
    Matt Craighead  
    Cass Everitt  
    Evan Hart  
    Jon Leech  
    Bill Licea-Kane  
    Bimal Poddar  
    Jeremy Sandmel  
    Jon Paul Schelter  
    Avinash Seetharamaiah  
    Nick Triantos  
  
    and contributors to the ARB_vertex_program working group,  
    the product of which provided the basis for this spec  
  
homeprevnext Contact
  
    Benj Lipchak, ATI Research (blipchak 'at' ati.com)  
  
homeprevnext IP Status
  
    Microsoft claims to own intellectual property related to this   
    extension.  
  
homeprevnext Status
  
    Complete.  Approved by ARB on September 18, 2002  
  
homeprevnext Version
  
    Last Modified Date: January 10, 2003  
    Revision: 24  
  
homeprevnext Number
  
    ARB Extension #27  
  
homeprevnext Dependencies
  
    The extension is written against the OpenGL 1.3 Specification.  
  
    OpenGL 1.3 is required.  
  
    EXT_texture_lod_bias or OpenGL 1.4 is required.  
  
    OpenGL 1.4 affects the definition of this extension.  
  
    ARB_vertex_blend and EXT_vertex_weighting affect the definition of   
    this extension.  
  
    ARB_matrix_palette affects the definition of this extension.  
  
    ARB_transpose_matrix affects the definition of this extension.  
  
    EXT_fog_coord affects the definition of this extension.  
  
    EXT_texture_rectangle affects the definition of this extension.  
  
    ARB_shadow interacts with this extension.  
  
    ARB_vertex_program interacts with this extension.  
  
    ATI_fragment_shader interacts with this extension.  
  
    NV_fragment_program interacts with this extension.  
  
  
homeprevnext Overview
  
    Unextended OpenGL mandates a certain set of configurable per-  
    fragment computations defining texture application, texture   
    environment, color sum, and fog operations.  Several extensions have   
    added further per-fragment computations to OpenGL.  For example,   
    extensions have defined new texture environment capabilities   
    (ARB_texture_env_add, ARB_texture_env_combine, ARB_texture_env_dot3,  
    ARB_texture_env_crossbar), per-fragment depth comparisons   
    (ARB_depth_texture, ARB_shadow, ARB_shadow_ambient,   
    EXT_shadow_funcs), per-fragment lighting (EXT_fragment_lighting,   
    EXT_light_texture), and environment mapped bump mapping   
    (ATI_envmap_bumpmap).    
  
    Each such extension adds a small set of relatively inflexible per-  
    fragment computations.  
  
    This inflexibility is in contrast to the typical flexibility   
    provided by the underlying programmable floating point engines   
    (whether micro-coded fragment engines, DSPs, or CPUs) that are   
    traditionally used to implement OpenGL's texturing computations.    
    The purpose of this extension is to expose to the OpenGL application   
    writer a significant degree of per-fragment programmability for   
    computing fragment parameters.  
  
    For the purposes of discussing this extension, a fragment program is   
    a sequence of floating-point 4-component vector operations that   
    determines how a set of program parameters (not specific to an  
    individual fragment) and an input set of per-fragment parameters are   
    transformed to a set of per-fragment result parameters.  
  
    The per-fragment computations for standard OpenGL given a particular   
    set of texture and fog application modes (along with any state for   
    extensions defining per-fragment computations) is, in essence, a   
    fragment program.  However, the sequence of operations is defined   
    implicitly by the current OpenGL state settings rather than defined   
    explicitly as a sequence of instructions.  
  
    This extension provides an explicit mechanism for defining fragment   
    program instruction sequences for application-defined fragment   
    programs.  In order to define such fragment programs, this extension   
    defines a fragment programming model including a floating-point  
    4-component vector instruction set and a relatively large set of   
    floating-point 4-component registers.  
  
    The extension's fragment programming model is designed for efficient  
    hardware implementation and to support a wide variety of fragment   
    programs.  By design, the entire set of existing fragment programs   
    defined by existing OpenGL per-fragment computation extensions can   
    be implemented using the extension's fragment programming model.  
  
homeprevnext Issues
  
    This extension is closely related to ARB_vertex_program, and is in   
    sync with revision 36 of that spec.  ARB_fragment_program will   
    continue to track changes made to ARB_vertex_program.  
  
    (1) Should we provide precision queries?  
  
      RESOLVED: We've decided not to include precision queries.  
      Implementations are expected to meet or exceed the precision   
      guidelines set forth in the core GL spec, section 2.1.1, p. 6,  
      as ammended by this extension.  
  
      To summarize section 2.1.1, the maximum representable magnitude of   
      colors must be at least 2^10, while the maximum representable   
      magnitude of other floating-point values must be at least 2^32.    
      The individual results of floating-point operations must be   
      accurate to about 1 part in 10^5.  
  
      Here are the reasons why precision queries were not included:  
        1. It is unclear what the queries should be:  
           a) min, max, [0,1) granularity  
           b) min +, max +, min -, max -, [0,1) granularity  
           c) IEEE mantissa bits, IEEE exponent bits  
        2. Due to instruction emulation, there is no way to query the   
           actual precision that can be expected.  Should the query   
           return the best-case or worst-case precision?  
        3. Implementations may support multiple precisions, on a per-  
           instruction basis or across the board.  How would this be   
           exposed?  
        4. Current implementations are able to meet the minimum   
           requirements specified in the core GL, thanks to its  
           sufficiently loose wording "... so that the individual   
           results of floating-point operations are accurate to ABOUT   
           1 part in 10^5."  (Emphasis added.)  
        5. A conformance test can act as watchdog to ensure   
           implementations are not cutting corners on precision.  
        6. Adding precision queries would require a new entrypoint.  
  
      See issue 22 regarding reduced-precision modes.  
  
    (2) Should the LOD biased texture sample be optional?  
  
      RESOLVED: TXB support is mandatory.  This exposes useful   
      functionality which enables blurring and sharpening effects.  It   
      will be more useful to entirely override derivatives (scale   
      factor) rather than just biasing the level-of-detail.  This would   
      be a future extension to fragment programs.  
  
      It should be noted here that the bias introduced per-fragment by   
      TXB is added to any per-object or per-stage LOD bias.  If per-  
      fragment LOD bias is not necessary, using the per-object and/or   
      per-stage LOD biases may perform better.  
  
    (3) Should we include the ability to bind to the color matrix?  How  
    about others?  Program matrices?  
  
      RESOLVED: We will not specifically add anything that depends on   
      the ARB_imaging subset.  So we have not included matrix bindings   
      to the color matrix (or parameter bindings to the color biases,   
      etc.).  However, we have included matrix binding support and   
      support for all of the matrices present in ARB_vertex_program.  
  
    (4) Should we include the ability to bind to just a texcoord   
    attribute's S,T components?  (Or just S, or S,T,P for that matter?)   
  
      RESOLVED: No.  Issue #15 below obviates this issue by making the  
      texture coordinate usage within a program explicit, thereby making   
      optimizations to reduce the number of interpolated texture   
      coordinates something an implementation can do at compile time   
      instead of having to do it during every texture target change.  
  
    (5) What other instructions should be added?  Should any be removed?  
  
      RESOLVED: The differences between the ARB_vertex_program   
      instruction set and the ARB_fragment_program instruction set are  
      minimal.  ARB_fragment_program removes the LOG and EXP rough  
      approximation instructions and the ARL address register load  
      instruction.  ARB_fragment_program adds the SIN/COS/SCS   
      trigonometric instructions, the LRP linear interpolation   
      instruction, the CMP compare instruction, and the TEX/TXP/TXB/KIL  
      texture instructions.  
  
    (6) Should depth output be a program option or a mandatory feature?  
   
      RESOLVED: Depth output capability should be mandatory.  
  
    (6a) How should per-vertex geometric depth clipping be handled when   
      replacing depth in a fragment program?  
  
      RESOLVED: Per-vertex geometric depth clipping should be performed   
      by the GL as usual, so no spec change is required.  The ideal  
      behavior would be to disable near and far clipping planes when  
      replacing depth, but not all implementations can natively support  
      disabling individual clip planes.  
  
    (6b) How should depth output from the fragment program be further   
    processed before being handed to the per-fragment operations?  
  
      RESOLVED: Depth gets clamped by GL to [0,1].  App has access to   
      depth range as a bindable parameter if it wants to either scale   
      and bias its depth to fall within the depth range, or to kill   
      fragments outside the depth range.  
  
    (7) If a fragment program does not write a color value, what should  
    be the final color of the fragment?  
  
      RESOLVED: The final fragment color is undefined.  Note that it may  
      be perfectly reasonable to have a program that computes depth   
      values but not colors.  Fragment colors are often irrelevant if  
      color writes are disabled (via ColorMask).  
  
    (7a) If a fragment program does not write a depth value, what should   
    be the final depth value of the fragment?  
  
      RESOLVED: "Depth fly-over" (using the conventional depth produced  
      by rasterization) should happen whenever a depth-replacing program   
      is not in use.  A depth-replacing program is defined as a program  
      that writes to result.depth in at least one instruction.  The  
      presence of a depth declaration alone DOES NOT designate a depth-  
      replacing program.  The intention is that a future extension  
      introducing conditional execution will still consider a program to  
      be depth-replacing even if the instruction(s) writing to   
      result.depth do(es) not execute.  
  
      Other considered definitions of depth-replacing program:  
        1. The presence of a depth declaration -OR- the use of   
           result.depth as an instruction destination anywhere in the   
           program designates a depth-replacing program.  
        2. Every program is a depth-replacing program, but the GL   
           initializes the depth output to be the depth produced by   
           rasterization.  The app may then overwrite the depth output.  
        3. Every program is a depth-replacing program, and the app is   
           solely responsible for copying the depth input to depth   
           output if desired.  
  
    (8) Should relative addressing, like that defined in   
    ARB_vertex_program, be supported in this spec?  
  
      RESOLVED: No, relative addressing won't be included in this spec.  
  
    (9) Should full-featured operand component swizzling, like that   
    defined in ARB_vertex_program, be supported in this spec?  
  
      RESOLVED: Yes, full swizzling is mandatory.  
  
    (10) Should texture instructions contain specific limitations on  
    operations that can be performed?  For example, should write masks  
    or operand component swizzling be disallowed?  
  
      RESOLVED: Texture instructions are specified to be very similar to   
      ALU instructions.  They have been given 3-letter names, they allow   
      writemasking and saturation (which would be useful for floating-  
      point texture formats), source swizzles and negates, and the   
      ability to use parameters as sources.  
  
    (11) Should we standardize options for stencil or aux data buffer  
    outputs?  
  
      RESOLVED: Stencil and aux data buffers will be saved for a   
      possible future extension to fragment programs.  
  
    (12) Should depth output be pulled from the 3rd or 4th component?  
  
      RESOLVED: 3rd component, as the 3rd component is also used for  
      depth input from the "fragment.position" attribute.  
  
    (13) Which stages are subsumed by fragment programs?  
  
      RESOLVED: Texturing, color sum, and fog.  
  
    (14) What should the minimum resource limits be?  
  
      RESOLVED: 10 attributes, 24 parameters, 4 texture indirections,  
      48 ALU instructions, 24 texture instructions, and 16 temporaries.  
  
    (15) OpenGL provides a hierarchy of texture enables (cube map, 3D,   
    2D, 1D).  Should the texture sampling instructions here override   
    that hierarchy and select specific texture targets?  
  
      RESOLVED: Yes.  This removes a potential pitfall for developers:   
      leaving the hierarchy of enables in an undesired state.  It makes   
      programs more readable as the intent of the sample is more   
      obvious.  Finally, it allows compilers to be more aggressive as   
      to which texcoord components are "don't cares" without having to   
      recompile programs when fixed-function texenables change.  One   
      drawback is that programs cannot be reused for both 2D and 3D   
      texturing, for example, by simply changing the texture enables.   
  
      Texture sampling can be specified by instructions like   
        
        TEX myTexel, fragment.texcoord[1], texture[2], 3D;  
  
      which would indicate to use texture coordinate set number 1 to  
      sample from the texture object bound to the TEXTURE_3D target on   
      texture image unit 2.  
  
      Each texture unit can have only one "active" target.  Programs are   
      not allowed to reference different texture targets in the same   
      texture image unit.  In the example above, any other texture   
      instructions using texture image unit 2 must specify the 3D   
      texture target.  
  
      Note that every texture image unit always has a texture bound to   
      every texture target, whether it is a named texture object or a   
      default texture.  However, the texture may not be complete as  
      defined in section 3.8.9 of the core GL spec.  See issue 23.  
  
    (16) Should aux texture units be additional units on top of existing   
    full-featured texture units, or should this spec fully deprecate   
    "legacy" texture units and only expose texture coordinate sets and  
    texture image units?  
  
      Background: Some implementations are able to expose more   
      "texture image units" (texture maps and associated parameters)   
      than "texture coordinate sets" (current texcoords, texgen, and   
      texture matrices).  A conventional GL "texture unit" encompasses   
      both a texture image unit and a texture coordinate set as well as   
      texture environment state.  
  
      RESOLVED: Yes, deprecate "legacy" texture units.  This is a more   
      flexible model.  
  
    (17) Should fragment programs affect all fragments, or just those  
    produced by the rasterization of points, lines, and triangles?  
  
      RESOLVED: Every fragment generated by the GL is subject to   
      fragment program mode.  This includes point, line, and polygon   
      primitives as well as pixel rectangles and bitmaps.  
  
    (18) Should per-fragment position and fogcoord be bindable as   
    fragment attributes?  
  
      RESOLVED: Yes, interpolated fogcoord will make per-fragment   
      fog application possible, in addition to full fog stage   
      subsummation.  Interpolated window position, especially depth,  
      enables interesting depth-replacing algorithms.  
  
    (19) What characters should be used to identify individual   
    components in swizzle selectors and write masks?  
  
      RESOLVED: ARB_vertex_program provides "xyzw".  This extension   
      supports "xyzw" and also provides "rgba" for better readability   
      when dealing with RGBA color values.  Adding support for special   
      identifiers for dealing with texture coordinates was considered   
      and rejected.  "strq" could be used to identify texture coordinate   
      components, but the "r" would conflict with the "r" from "rgba".  
      "stpq" would be another possibility, but could be a source of   
      confusion.  
  
    (20) Should implementations be required to support all programs that   
    fit within the exported limits on the number of resources (e.g.,  
    instructions, temporaries) that can be present in a program, even if   
    it means falling back to software?  Should implementations be   
    required to reject programs that could never be accelerated?  
  
      RESOLVED: No and no.  An implementation is allowed to fail   
      ProgramStringARB due to the program exceeding native resources.  
      Note that this failure must be invariant with respect to all other  
      OpenGL state.  In other words, a program cannot succeed to load  
      with default state, but then fail to load when certain GL state  
      is altered.  However, an implementation is not required to fail  
      when a program would exceed native resources, and is in fact  
      encouraged to fallback to a software path.  See issue 21 for a way  
      of determining if this has happened.  
  
      This notable departure from ARB_vertex_program was made as an  
      accommodation to vendors who could not justify implementing a  
      software fallback path which would be relatively slow even   
      compared to an ARB_vertex_program software fallback path.  
  
      Two issues with this decision:  
        1.  The API limits become hints, and one can no longer tell by  
            visual inspection whether or not a program will load on  
            every implementation.  
        2.  Program loading will now depend on the optimizer, which may   
            vary from release to release of an implementation.  A   
            program that succeeded to load when an ISV first wrote it   
            may fail to load in a future driver version, and vice versa.  
  
    (21) How can applications determine if their programs are too large  
    to run on the native (likely hardware) implementation, and therefore may  
    run with reduced performance?  
  
      RESOLVED: The following code snippet uses a native resource  
      query to guarantee a program is loaded natively (or not at all):  
  
      GLboolean ProgramStringIsNative(GLenum target, GLenum format,   
                                     GLsizei len, const GLvoid *string)  
      {  
          GLint errorPos, isNative;  
          glProgramStringARB(target, format, len, string);  
          glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &errorPos);  
          glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB,   
              GL_PROGRAM_UNDER_NATIVE_LIMITS_ARB, &isNative);  
          if ((errorPos == -1) && (isNative == 1))  
              return GL_TRUE;  
          else  
              return GL_FALSE;  
      }  
  
      Note that a program that successfully loads, and falls under the  
      native limits, is still not guaranteed to execute in hardware.  
      Lack of other resources (e.g., texture memory) or the use of other   
      OpenGL features not natively supported by the implementation   
      (e.g., textures with borders) may also prevent the program from  
      executing in hardware.  
  
    (22) Should we provide applications with a method to control the   
    level of precision used to carry out fragment program computations?  
  
      RESOLVED:  Yes.  The GL implementation ultimately has control over   
      the level of precision used for fragment program computations.    
      However, the "ARB_precision_hint_fastest" and   
      "ARB_precision_hint_nicest" program options allow applications to   
      guide the GL implementation in its precision selection.  The   
      "fastest" option encourages the GL to minimize execution time,   
      with possibly reduced precision.  The "nicest" option encourages   
      the GL to maximize precision, with possibly increased execution   
      time.  
  
      If the precision hint is not "fastest", GL implementations should  
      perform low-precision operations only if they could not   
      appreciably affect the final results of the program.  Regardless   
      of the precision hint, GL implementations are discouraged from   
      reducing the precision of computations so aggressively that final   
      rendering results could be seriously compromised due to overflow  
      of intermediate values or insufficient number of mantissa bits.  
  
      Some implementations may provide only a single level of precision,   
      in which case these hints may have no effect.  However, all  
      implementations will accept these options, even if they are   
      silently ignored.  
  
      More explicit control of precision, such as provided in "C" with   
      data types such as "short", "int", "float", "double", may also be   
      a desirable feature, but this level of detail is left to a   
      separate extension.  
  
    (23) What is the result of a sample from an incomplete texture?   
    The definition of texture completeness can be found in section 3.8.9   
    of the core GL spec.   
  
      RESOLVED: The result of a sample from an incomplete texture is the   
      constant vector (0,0,0,1).  The benefit of defining the result to   
      be a constant is that broken apps are guaranteed to generate   
      unexpected (black) results from their bad samples.  If we were to   
      leave the result undefined, some implementations may generate   
      expected results some of the time, for example when magfiltering,   
      giving app developers a false sense of correctness in their apps.   
  
    (24) What is a texture indirection, and how is it counted?  
  
       RESOLVED: On some implementations, fragment programs that have  
       complex texture dependency chains may not be supported, even if   
       the instruction counts fit within the exported limits.  A texture  
       dependency occurs when a texture instruction depends on the   
       result of a previous instruction (ALU or texture) for use as its   
       texture coordinate.  
  
       A texture indirection can be considered a node in the texture   
       dependency chain.  Each node contains a set of texture   
       instructions which execute in parallel, followed by a sequence of   
       ALU instructions.  A dependent texture instruction is one that   
       uses a temporary as an input coordinate rather than an attribute   
       or a parameter.  A program with no dependent texture instructions   
       (or no texture instructions at all) will have a single node in   
       its texture dependency chain, and thus a single indirection.  
  
       API-level texture indirections are counted by keeping track of  
       which temporaries are read and written within the current node in   
       the texture dependency chain.  When a texture instruction is   
       encountered, an indirection may be added and a new node started   
       if either of the following two conditions is true:  
  
         1. the source coordinate of the texture instruction is a  
            temporary that has already been written in the current node,   
            either by a previous texture instruction or ALU instruction;  
  
         2. the result of the texture instruction is a temporary that   
            has already been read or written in the current node by an   
            ALU instruction.  
  
       The texture instruction provoking a new indirection and all  
       subsequent instructions are added to the new node.  This process  
       is repeated until the end of the program is encountered.  Below   
       is some pseudo-code to describe this:  
  
         indirections = 1;  
         tempsOutput = 0;  
         aluTemps = 0;  
         while (i = getInst())   
         {  
           if (i.type == TEX)   
           {  
             if (((i.input.type == TEMP) &&   
                   (tempsOutput & (1 << i.input.index))) ||  
                 ((i.op != KILL) && (i.output.type == TEMP) &&   
                   (aluTemps & (1 << i.output.index))))   
             {  
               indirections++;  
               tempsOutput = 0;  
               aluTemps = 0;  
             }  
           } else {  
             if (i.input1.type == TEMP)  
               aluTemps |= (1 << i.input1.index);  
             if (i.input2 && i.input2.type == TEMP)  
               aluTemps |= (1 << i.input2.index);  
             if (i.input3 && i.input3.type == TEMP)  
               aluTemps |= (1 << i.input3.index);  
             if (i.output.type == TEMP)  
               aluTemps |= (1 << i.output.index);  
           }  
           if ((i.op != KILL) && (i.output.type == TEMP))  
             tempsOutput |= (1 << i.output.index);  
         }  
  
       For example, the following programs would have 1, 2, and 3  
       texture indirections, respectively:  
  
         !!ARBfp1.0  
         # No texture instructions, but always 1 indirection  
         MOV result.color, fragment.color;  
         END  
  
         !!ARBfp1.0  
         # A simple dependent texture instruction, 2 indirections  
         TEMP myColor;  
         MUL myColor, fragment.texcoord[0], fragment.texcoord[1];  
         TEX result.color, myColor, texture[0], 2D;  
         END  
  
         !!ARBfp1.0  
         # A more complex example with 3 indirections  
         TEMP myColor1, myColor2;  
         TEX myColor1, fragment.texcoord[0], texture[0], 2D;  
         MUL myColor1, myColor1, myColor1;  
         TEX myColor2, fragment.texcoord[1], texture[1], 2D;  
         # so far we still only have 1 indirection  
         TEX myColor2, myColor1, texture[2], 2D;      # This is #2  
         TEX result.color, myColor2, texture[3], 2D;  # And #3  
         END  
  
       Note that writemasks for the temporaries written and swizzles   
       for the temporaries read are not taken into consideration when  
       counting indirections.  This makes hand-counting of indirections  
       by a developer an easier task.  
  
       Native texture indirections may be counted differently by an  
       implementation to reflect its exact restrictions, to reflect the   
       true dependencies taking into account writemasks and swizzles,   
       and to reflect optimizations such as instruction reordering.    
  
       For implementations with no restrictions on the number of  
       indirections, the maximum indirection count will equal the  
       maximum texture instruction count.  
  
    (25) How can a program reduce SCS's scalar operand to the   
    fundamental period [-PI,PI]?  
  
       RESOLVED: Unlike the individual SIN and COS instructions, SCS   
       requires that its argument be reduced ahead of time to the   
       fundamental period.  The reason SCS doesn't perform this   
       operation automatically is that it may make unnecessary redundant   
       work for programs that already have their operand in the correct   
       range.  Other programs that do need to reduce their operand   
       simply need to add a block of code before the SCS instruction:  
  
         PARAM myParams = { 0.5, -3.14159, 6.28319, 0.15915 };  
         MAD myOperand.x, myOperand.x, myParams.w, myParams.x; # a = (a/(2*PI))+0.5  
         FRC myOperand.x, myOperand.x;                         # a = frac(a)  
         MAD myOperand.x, myOperand.x, myParams.z, myParams.y  # a = (a*2*PI)-PI  
         ...  
         SCS myResult, myOperand.x;  
  
    (26) Is depth output from a fragment program guaranteed to be  
    invariant with respect to depth produced via conventional   
    rasterization?  
  
      RESOLVED:  No.  The floating-point representation of depth values   
      output from a fragment program may lead to the output of depth   
      with less precision than the depth output by convention GL   
      rasterization.  For example, a floating-point representation with   
      16 bits of mantissa will certainly produce depth with lesser   
      precision than that of conventional rasterization used in   
      conjunction with a 24-bit depth buffer, where all values are  
      maintained as integers.  Be aware of this when mixing conventional   
      GL rendering with fragment program rendering.  
  
    (27) How can conventional GL fog application be achieved within a   
    fragment program?  
  
      RESOLVED: Program options have been introduced that allow a   
      program to request fog to be applied to the final clamped fragment   
      color before being passed along to the antialiasing application   
      stage.  This makes it easy for:  
        1. developers to request conventional fog behavior  
        2. implementations with dedicated fog hardware to use it  
        3. implementations without dedicated fog hardware, so they need   
           not track fog state after compilation, and constantly   
           recompile when fog state changes.  
  
      The three mandatory options are ARB_fog_exp, ARB_fog_exp2, and   
      ARB_fog_linear.  As these options are mutually exclusive by  
      nature, specifying more than one is not useful.  If more than one  
      is specified, the last one encountered in the <optionSequence>   
      will be the one to actually modify the execution environment.  
  
    (28) Why have all of the enums, entrypoints, GLX protocol, and spec   
    language shared with ARB_vertex_program been reproduced here?  
  
      RESOLVED: The two extensions are independent of one another, in  
      so far as an implementation need not support both of them in order   
      to support one of them.  Everything needed to implement or make   
      use of ARB_fragment_program is present in this spec without the  
      need to refer to the ARB_vertex_program spec.  When and if these  
      two extensions are incorporated into the core OpenGL, the  
      significant overlap of the two will be collapsed into a single  
      instance of the shared parts.  
  
    (29) How might an implementation implement the fog options?  To What  
    does the extra resource consumption described in 3.11.4.5.1   
    correspond?  
  
      RESOLVED: The following code snippets reflect possible  
      implementations of the fog options.  While an implementation may  
      use other instruction sequences to achieve the same result, or may   
      use external fog hardware if available, all implementations must   
      enforce the API-level resource consumption as described: 2 params,  
      1 temp, 1 attribute, and 3, 4, or 2 instructions.  "finalColor" in  
      the examples below is the color that would otherwise be   
      "result.color", with components clamped to the range [0,1].  
      "result.color.a" is assumed to have already been written, as fog  
      blending does not affect the alpha component.  
  
      EXP:  
        # Exponential fog  
        # f = exp(-d*z)  
        #  
        PARAM p = {DENSITY/LN(2), NOT USED, NOT USED, NOT USED};  
        PARAM fogColor = state.fog.color;  
        TEMP fogFactor;  
        ATTRIB fogCoord = fragment.fogcoord.x;  
        MUL fogFactor.x, p.x, fogCoord.x;  
        EX2_SAT fogFactor.x, -fogFactor.x;  
        LRP result.color.rgb, fogFactor.x, finalColor, fogColor;  
  
      EXP2:  
        #  
        # 2nd-order Exponential fog  
        # f = exp(-(d*z)^2)  
        #  
        PARAM p = {DENSITY/SQRT(LN(2)), NOT USED, NOT USED, NOT USED};  
        PARAM fogColor = state.fog.color;  
        TEMP fogFactor;  
        ATTRIB fogCoord = fragment.fogcoord.x;  
        MUL fogFactor.x, p.x, fogCoord.x;  
        MUL fogFactor.x, fogFactor.x, fogFactor.x;  
        EX2_SAT fogFactor.x, -fogFactor.x;  
        LRP result.color.rgb, fogFactor.x, finalColor, fogColor;  
  
      LINEAR:  
        #  
        # Linear fog  
        # f = (end-z)/(end-start)  
        #  
        PARAM p = {-1/(END-START), END/(END-START), NOT USED, NOT USED};  
        PARAM fogColor = state.fog.color;  
        TEMP fogFactor;  
        ATTRIB fogCoord = fragment.fogcoord.x;  
        MAD_SAT fogFactor.x, p.x, fogCoord.x, p.y;  
        LRP result.color.rgb, fogFactor.x, finalColor, fogColor;  
  
    (30) Why is the order of operands for the CMP instruction different  
    than the order used by another popular graphics API?  
  
      RESOLVED: No other graphics API was used as a basis for the  
      design of ARB_fragment_program except ARB_vertex_program, which  
      did not have a CMP instruction.  This independent evolution  
      naturally led to differences in minor details such as order of  
      operands.  This discrepancy is noted here to help developers   
      familiar with the other API to avoid this potential pitfall.  
  
  
homeprevnext New Procedures and Functions
  
    void ProgramStringARB(enum target, enum format, sizei len,   
                          const void *string);   
  
    void BindProgramARB(enum target, uint program);  
  
    void DeleteProgramsARB(sizei n, const uint *programs);  
  
    void GenProgramsARB(sizei n, uint *programs);  
  
    void ProgramEnvParameter4dARB(enum target, uint index,  
                                  double x, double y, double z, double w);  
    void ProgramEnvParameter4dvARB(enum target, uint index,  
                                   const double *params);  
    void ProgramEnvParameter4fARB(enum target, uint index,  
                                  float x, float y, float z, float w);  
    void ProgramEnvParameter4fvARB(enum target, uint index,  
                                   const float *params);  
  
    void ProgramLocalParameter4dARB(enum target, uint index,  
                                    double x, double y, double z, double w);  
    void ProgramLocalParameter4dvARB(enum target, uint index,  
                                     const double *params);  
    void ProgramLocalParameter4fARB(enum target, uint index,  
                                    float x, float y, float z, float w);  
    void ProgramLocalParameter4fvARB(enum target, uint index,  
                                     const float *params);  
  
    void GetProgramEnvParameterdvARB(enum target, uint index,  
                                     double *params);  
    void GetProgramEnvParameterfvARB(enum target, uint index,   
                                     float *params);  
  
    void GetProgramLocalParameterdvARB(enum target, uint index,  
                                       double *params);  
    void GetProgramLocalParameterfvARB(enum target, uint index,   
                                       float *params);  
  
    void GetProgramivARB(enum target, enum pname, int *params);  
  
    void GetProgramStringARB(enum target, enum pname, void *string);  
  
    boolean IsProgramARB(uint program);  
  
  
homeprevnext New Tokens
  
    Accepted by the <cap> parameter of Disable, Enable, and IsEnabled,   
    by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,   
    and GetDoublev, and by the <target> parameter of ProgramStringARB,  
    BindProgramARB, ProgramEnvParameter4[df][v]ARB,  
    ProgramLocalParameter4[df][v]ARB, GetProgramEnvParameter[df]vARB,   
    GetProgramLocalParameter[df]vARB, GetProgramivARB and  
    GetProgramStringARB.  
  
        FRAGMENT_PROGRAM_ARB                            0x8804  
  
    Accepted by the <format> parameter of ProgramStringARB:  
  
        PROGRAM_FORMAT_ASCII_ARB                        0x8875  
  
    Accepted by the <pname> parameter of GetProgramivARB:  
  
        PROGRAM_LENGTH_ARB                              0x8627  
        PROGRAM_FORMAT_ARB                              0x8876  
        PROGRAM_BINDING_ARB                             0x8677  
        PROGRAM_INSTRUCTIONS_ARB                        0x88A0  
        MAX_PROGRAM_INSTRUCTIONS_ARB                    0x88A1  
        PROGRAM_NATIVE_INSTRUCTIONS_ARB                 0x88A2  
        MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB             0x88A3  
        PROGRAM_TEMPORARIES_ARB                         0x88A4  
        MAX_PROGRAM_TEMPORARIES_ARB                     0x88A5  
        PROGRAM_NATIVE_TEMPORARIES_ARB                  0x88A6  
        MAX_PROGRAM_NATIVE_TEMPORARIES_ARB              0x88A7  
        PROGRAM_PARAMETERS_ARB                          0x88A8  
        MAX_PROGRAM_PARAMETERS_ARB                      0x88A9  
        PROGRAM_NATIVE_PARAMETERS_ARB                   0x88AA  
        MAX_PROGRAM_NATIVE_PARAMETERS_ARB               0x88AB  
        PROGRAM_ATTRIBS_ARB                             0x88AC  
        MAX_PROGRAM_ATTRIBS_ARB                         0x88AD  
        PROGRAM_NATIVE_ATTRIBS_ARB                      0x88AE  
        MAX_PROGRAM_NATIVE_ATTRIBS_ARB                  0x88AF  
        MAX_PROGRAM_LOCAL_PARAMETERS_ARB                0x88B4  
        MAX_PROGRAM_ENV_PARAMETERS_ARB                  0x88B5  
        PROGRAM_UNDER_NATIVE_LIMITS_ARB                 0x88B6  
  
        PROGRAM_ALU_INSTRUCTIONS_ARB                    0x8805  
        PROGRAM_TEX_INSTRUCTIONS_ARB                    0x8806  
        PROGRAM_TEX_INDIRECTIONS_ARB                    0x8807  
        PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB             0x8808  
        PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB             0x8809  
        PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB             0x880A  
        MAX_PROGRAM_ALU_INSTRUCTIONS_ARB                0x880B  
        MAX_PROGRAM_TEX_INSTRUCTIONS_ARB                0x880C  
        MAX_PROGRAM_TEX_INDIRECTIONS_ARB                0x880D  
        MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB         0x880E  
        MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB         0x880F  
        MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB         0x8810  
  
    Accepted by the <pname> parameter of GetProgramStringARB:  
  
        PROGRAM_STRING_ARB                              0x8628  
  
    Accepted by the <pname> parameter of GetBooleanv, GetIntegerv,  
    GetFloatv, and GetDoublev:  
  
        PROGRAM_ERROR_POSITION_ARB                      0x864B  
        CURRENT_MATRIX_ARB                              0x8641  
        TRANSPOSE_CURRENT_MATRIX_ARB                    0x88B7  
        CURRENT_MATRIX_STACK_DEPTH_ARB                  0x8640  
        MAX_PROGRAM_MATRICES_ARB                        0x862F  
        MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB              0x862E  
  
        MAX_TEXTURE_COORDS_ARB                          0x8871  
        MAX_TEXTURE_IMAGE_UNITS_ARB                     0x8872  
  
    Accepted by the <name> parameter of GetString:  
  
        PROGRAM_ERROR_STRING_ARB                        0x8874  
  
    Accepted by the <mode> parameter of MatrixMode:  
      
        MATRIX0_ARB                                     0x88C0  
        MATRIX1_ARB                                     0x88C1  
        MATRIX2_ARB                                     0x88C2  
        MATRIX3_ARB                                     0x88C3  
        MATRIX4_ARB                                     0x88C4  
        MATRIX5_ARB                                     0x88C5  
        MATRIX6_ARB                                     0x88C6  
        MATRIX7_ARB                                     0x88C7  
        MATRIX8_ARB                                     0x88C8  
        MATRIX9_ARB                                     0x88C9  
        MATRIX10_ARB                                    0x88CA  
        MATRIX11_ARB                                    0x88CB  
        MATRIX12_ARB                                    0x88CC  
        MATRIX13_ARB                                    0x88CD  
        MATRIX14_ARB                                    0x88CE  
        MATRIX15_ARB                                    0x88CF  
        MATRIX16_ARB                                    0x88D0  
        MATRIX17_ARB                                    0x88D1  
        MATRIX18_ARB                                    0x88D2  
        MATRIX19_ARB                                    0x88D3  
        MATRIX20_ARB                                    0x88D4  
        MATRIX21_ARB                                    0x88D5  
        MATRIX22_ARB                                    0x88D6  
        MATRIX23_ARB                                    0x88D7  
        MATRIX24_ARB                                    0x88D8  
        MATRIX25_ARB                                    0x88D9  
        MATRIX26_ARB                                    0x88DA  
        MATRIX27_ARB                                    0x88DB  
        MATRIX28_ARB                                    0x88DC  
        MATRIX29_ARB                                    0x88DD  
        MATRIX30_ARB                                    0x88DE  
        MATRIX31_ARB                                    0x88DF  
  
  
homeprevnext Additions to Chapter 2 of the OpenGL 1.3 Specification (OpenGL Operation)
  
    Modify Section 2.1.1, Floating-Point Computation (p. 6)  
  
    (modify first paragraph, p. 6) ... The maximum representable   
    magnitude of a floating-point number used to represent position,  
    normal, or texture coordinates must be at least 2^32; the maximum  
    representable magnitude for colors must be at least 2^10.  ...  
  
  
    Modify Section 2.7, Vertex Specification (p. 19)  
  
    (modify second paragraph, p. 20) Implementations support more than  
    one set of texture coordinates.  The commands  
  
      void MultiTexCoord{1234}{sifd}(enum texture, T coords);  
      void MultiTexCoord{1234}{sifd}v(enum texture, T coords);  
  
    take the coordinate set to be modified as the <texture> parameter.  
    <texture> is a symbolic constant of the form TEXTUREi, indicating  
    that texture coordinate set i is to be modified.  The constants obey  
    TEXTUREi = TEXTURE0 + i (i is in the range 0 to k-1, where k is the  
    implementation-dependent number of texture units defined by  
    MAX_TEXTURE_COORDS_ARB).  
  
  
    Modify Section 2.8, Vertex Arrays (p. 21)  
  
    (modify first paragraph, p. 21) ... The client may specify up to 5  
    plus the value of MAX_TEXTURE_COORDS_ARB arrays: one each to store  
    vertex coordinates...  
  
  
    (modify first paragraph, p. 23) The command  
  
      void ClientActiveTexture(enum texture);  
  
    is used to select the vertex array client state parameters to be  
    modified by the TexCoordPointer command and the array affected by  
    EnableClientState and DisableClientState with parameter  
    TEXTURE_COORD_ARRAY.  This command sets the client state variable  
    CLIENT_ACTIVE_TEXTURE.  Each texture coordinate set has a client   
    state vector which is selected when this command is invoked.  This  
    state vector includes the vertex array state.  This call also   
    selects the texture coordinate set state used for queries of client  
    state.  
  
  
    (modify first paragraph, p. 28) If the number of supported texture  
    coordinate sets (the value of MAX_TEXTURE_COORDS_ARB) is k, ...  
  
  
    Modify Section 2.10.2, Matrices (p. 31)  
  
    (modify first paragraph, p. 31) The projection matrix and model-view   
    matrix are set and modified with a variety of commands.  The   
    affected matrix is determined by the current matrix mode.  The   
    current matrix mode is set with  
  
      void MatrixMode(enum mode);  
  
    which takes one of the pre-defined constants TEXTURE, MODELVIEW,   
    COLOR, PROJECTION, or MATRIX<i>_ARB as the argument.  In the case of  
    MATRIX<i>_ARB, <i> is an integer between 0 and <n>-1 indicating one   
    of <n> program matrices where <n> is the value of the implementation   
    defined constant MAX_PROGRAM_MATRICES_ARB.  Such program matrices   
    are described in section 3.11.7.  TEXTURE is described later in   
    section 2.10.2, and COLOR is described in section 3.6.3.  If the   
    current matrix mode is MODELVIEW, then matrix operations apply to   
    the model-view matrix; if PROJECTION, then they apply to the   
    projection matrix.  
  
  
    (modify first paragraph, p. 34) For each texture coordinate set, a  
    4x4 matrix is applied to the corresponding texture coordinates...  
  
  
    (modify first and second paragraphs, p. 35) The command  
  
      void ActiveTexture(enum texture);  
  
    specifies the active texture unit selector, ACTIVE_TEXTURE.  Each  
    texture unit contains up to two distinct sub-units: a texture   
    coordinate processing unit (consisting of a texture matrix stack and  
    texture coordinate generation state) and a texture image unit  
    (consisting of all the texture state defined in Section 3.8).  In  
    implementations with a different number of supported texture   
    coordinate sets and texture image units, some texture units may  
    consist of only one of the two sub-units.  
  
    The active texture unit selector specifies the texture coordinate   
    set accessed by commands involving texture coordinate processing.    
    Such commands include those accessing the current matrix stack (if   
    MATRIX_MODE is TEXTURE), TexGen (section 2.10.4), Enable/Disable (if   
    any texture coordinate generation enum is selected), as well as   
    queries of the current texture coordinates and current raster   
    texture coordinates.  If the texture coordinate set number   
    corresponding to the current value of ACTIVE_TEXTURE is greater than   
    or equal to the implementation-dependent constant   
    MAX_TEXTURE_COORDS_ARB, the error INVALID_OPERATION is generated by   
    any such command.  
  
    The active texture unit selector also selects the texture image unit  
    accessed by commands involving texture image processing (section   
    3.8).  Such commands include all variants of TexEnv, TexParameter,  
    and TexImage commands, BindTexture, Enable/Disable for any texture  
    target (e.g., TEXTURE_2D), and queries of all such state.  If the  
    texture image unit number corresponding to the current value of   
    ACTIVE_TEXTURE is greater than or equal to the implementation-  
    dependent constant MAX_TEXTURE_IMAGE_UNITS_ARB, the error  
    INVALID_OPERATION is generated by any such command.  
  
    ActiveTexture generates the error INVALID_ENUM if an invalid   
    <texture> is specified.  <texture> is a symbolic constant of the   
    form TEXTUREi, indicating that texture unit i is to be modified.    
    The constants obey TEXTUREi = TEXTURE0 + i (i is in the range 0 to  
    k-1, where k is the larger of the MAX_TEXTURE_COORDS_ARB and  
    MAX_TEXTURE_IMAGE_UNITS_ARB).  For compatibility with old OpenGL  
    specifications, the implementation-dependent constant   
    MAX_TEXTURE_UNITS specifies the number of conventional texture units   
    supported by the implementation.  Its value must be no larger than   
    the minimum of MAX_TEXTURE_COORDS_ARB and   
    MAX_TEXTURE_IMAGE_UNITS_ARB.  
      
  
    (modify last paragraph, p. 35) The state required to implement  
    transformations consists of a <n>-value integer indicating the   
    current matrix mode (where <n> is 4 + the number of supported   
    texture and program matrices), a stack of at least two 4x4 matrices   
    for each of COLOR, PROJECTION, and TEXTURE with associated stack   
    pointers, <n> stacks (where <n> is at least 8) of at least one 4x4   
    matrix for each MATRIX<i>_ARB with associated stack pointers, and a   
    stack of at least 32 4x4 matrices with an associated stack pointer   
    for MODELVIEW.  Initially, there is only one matrix on each stack,   
    and all matrices are set to the identity.  The initial matrix mode   
    is MODELVIEW.  The initial value of ACTIVE_TEXTURE is TEXTURE0.  
  
  
homeprevnext Additions to Chapter 3 of the OpenGL 1.3 Specification (Rasterization)
  
    Modify Chapter 3, Introduction (p. 58)  
  
    (modify first paragraph, p. 58) ... Figure 3.1 diagrams the   
    rasterization process.  The color value assigned to a fragment is  
    initially determined by the rasterization operations (sections 3.3  
    through 3.7) and modified by either the execution of the texturing,  
    color sum, and fog operations as defined in sections 3.8, 3.9, and  
    3.10, or of a fragment program defined in section 3.11.  The final  
    depth value is initially determined by the rasterization operations  
    and may be modified or replaced by a fragment program.  
  
    (modify Figure 3.1)  
  
                 _ +---------------+   FRAGMENT_PROGRAM_ARB  
                 /||    Point      |          enable  
                /  | Rasterization |\           |  
               /   +---------------+ \          V  o-------------+  
       From   /    +---------------+  \                          |  
    Primitive ---> |     Line      |---+++--->o    o             |  
     Assembly \    | Rasterization |  / ||         |             |  
               \   +---------------+ /  ||         |             |  
                \  +---------------+/   ||   +-----+-----+  +----+-----+  
                 \||    Polygon    |    ||   | Texturing |  | Fragment |  
                 - | Rasterization |   / |   +-----+-----+  | Program  |  
                   +---------------+  /  |         |        +----+-----+  
                   +---------------+ /   |   +-----+-----+       |  
                   |     Pixel     |/    |   | Color Sum |       |  
    DrawPixels --> |   Rectangle   |    /    +-----+-----+       |  
                   | Rasterization |   /           |             V  
                   +---------------+  /      +-----+-----+  
                   +---------------+ /       |    Fog    |---> Fragments  
      Bitmap ----> |    Bitmap     |/        +-----------+  
                   | Rasterization |  
                   +---------------+  
  
  
    Modify Section 3.3, Points (p. 63)  
  
    (modify first and second paragraphs, p. 64) All fragments produced  
    in rasterizing a non-antialiased point are assigned the same  
    associated data, which are those of the vertex corresponding to the  
    point.  (delete reference to divide by q)  
  
    If antialiasing is enabled, then ...  The data associated with each   
    fragment are otherwise the data associated with the point being   
    rasterized.  (delete reference to divide by q)  
      
  
    Modify Section 3.4.1, Basic Line Segment Rasterization (p. 66)  
  
    (modify first paragraph, p. 68) ... (Note that t=0 at p_a and t=1 at  
    p_b).  The value of an associated datum f from the fragment center,  
    whether it be R, G, B, or A (in RGBA mode) or a color index (in   
    color index mode) or the s, t, r, or q texture coordinate or the   
    clip w coordinate (the depth value, window z, must be found using  
    equation 3.3, below), is found as  
  
      f = (1-t)*(f_a/w_a) + t*(f_b/w_b)                     (3.2)  
          -----------------------------  
            (1-t)*(1/w_a) + t*(1/w_b)  
  
    where f_a and f_b are the data associated with the starting and   
    ending endpoints of the segment, respectively; w_a and w_b are the   
    clip w coordinates of the starting and ending endpoints of the   
    segments, respectively.  Note that linear interpolation would use  
  
      f = (1-t)*f_a + t*f_b.                                (3.3)  
  
    ... A GL implementation may choose to approximate equation 3.2 with  
    3.3, but this will normally lead to inacceptable distortion effects  
    when interpolating texture coordinates or clip w coordinates.  
  
  
    Modify Section 3.5.1, Basic Polygon Rasterization (p. 73)  
  
    (modify third and fourth paragraphs, p. 74) Denote a datum at p_a,   
    p_b, or p_c as f_a, f_b, or f_c, respectively.  Then the value f of   
    a datum at a fragment produced by rasterizing a triangle is given by  
  
      f = a*(f_a/w_a) + b*(f_b/w_b) + c*(f_c/w_c)           (3.4)  
          ---------------------------------------  
             a*(1/w_a) + b*(1/w_b) + c*(1/w_c)  
  
    where w_a, w_b, and w_c are the clip w coordinates of p_a, p_b, and  
    p_c, respectively.  a, b, and c are the barycentric coordinates of  
    the fragment for which the data are produced.  a, b, and c must  
    correspond precisely to the ... at the fragment's center.  
  
    Just as with line segment rasterization, equation 3.4 may be  
    approximated by  
  
      f = a*f_a + b*f_b + c*f_c;  
  
    this may yield ... for texture coordinates or clip w coordinates.  
  
  
    Modify Section 3.6.4, Rasterization of Pixel Rectangles (p. 91)  
  
    (modify third paragraph, p. 103) A fragment arising from a group ...  
    the color and texture coordinates are given by those associated with   
    the current raster position.  (delete reference to divide by q)  
    Groups arising from DrawPixels...    
  
  
    Modify Section 3.7, Bitmaps (p. 113)  
  
    (modify third paragraph, p. 114) Otherwise, a rectangular array ...  
    The associated data for each fragment are those associated with the  
    current raster position.  (delete reference to divide by q)  Once  
    the fragments have been produced ...  
  
  
    Modify Section 3.8, Texturing (p. 115)  
  
    (add new paragraphs before first paragraph, p. 115) Texture   
    coordinate sets are mapped to RGBA colors for application to   
    primitives in one of two modes.  The first mode, described in this   
    and subsequent sections, is GL's conventional multitexture pipeline,   
    describing texture environment and texture application.  The second   
    mode, referred to as fragment program mode and described in section   
    3.11, applies textures, color sum, and fog as specified in an   
    application-supplied fragment program.  
  
    The fragment program mode is enabled and disabled using the generic   
    Enable and Disable commands, respectively, with the symbolic   
    constant FRAGMENT_PROGRAM_ARB.  The required state is one bit   
    indicating whether the fragment program mode is enabled or disabled.  
    In the initial state, the fragment program mode is disabled.  When  
    fragment program mode is enabled, texturing, color sum, and fog  
    application stages are ignored and a general purpose program is  
    executed instead.  
  
    (modify first and second paragraph, p. 115) Conventional texturing   
    is employed when fragment program mode is disabled.  Texturing maps   
    ... color of an image at the location indicated by a fragment's   
    texture coordinates to modify the fragment's primary RGBA color.    
    Texturing does not affect the secondary color.  
  
    An implementation may support texturing using more than one image at  
    a time.  In this case the fragment carries multiple sets of texture  
    coordinates which are used to index ...   
  
    (add paragraph before 1st paragraph, p. 116) Except when in fragment  
    program mode (section 3.11), the (s,t,r) texture coordinates used  
    for texturing are the values s/q, t/q, and r/q, respectively, where  
    s, t, r, and q are the texture coordinates associated with the  
    fragment.  When in fragment program mode, the (s,t,r) texture  
    coordinates are specified by the program.  If q is less than or  
    equal to zero, the results of texturing are undefined.  
  
  
    Modify Section 3.8.7, Texture Minification (p. 135)  
  
    (add new paragraph after first paragraph, p. 137) When fragment   
    program mode is enabled, the derivatives of the coordinates may be   
    ill-defined or non-existent.  As a result, the implementation is   
    free to approximate these derivatives with such techniques as   
    differencing.  The only requirement is that texture samples be   
    equivalent across the two modes.  In other words, the texture sample   
    chosen for a fragment of a primitive must be invariant between   
    fragment program mode and conventional mode subject to the rules  
    set forth in Appendix A, Invariance.  
  
  
    Modify Section 3.8.13, Texture Application (p. 149)  
  
    (modify fourth paragraph, p. 152) Texturing is enabled and disabled  
    individually for each texture unit.  If texturing is disabled for  
    one of the units, then the fragment resulting from the previous unit  
    is passed unaltered to the following unit.  Individual texture units  
    beyond those specified by MAX_TEXTURE_UNITS may be incomplete and   
    are always treated as disabled.  
  
  
    Insert a new Section 3.11, (p. 154), between existing sections 3.10   
    and 3.11.  Renumber 3.11, Antialiasing Application, to 3.12.  
  
    3.11  Fragment Programs  
  
    The conventional GL texturing model described in section 3.8 is a  
    configurable but essentially hard-wired sequence of per-fragment  
    computations based on a canonical set of per-fragment parameters  
    and texturing-related state such as texture images, texture   
    parameters, and texture environment parameters.  The general success   
    and utility of the conventional GL texturing model reflects its   
    basic correspondence to the typical texturing requirements of 3D   
    applications.  
  
    However when the conventional GL texturing model is not sufficient,   
    the fragment program mode provides a substantially more flexible  
    model for generating fragment colors.  The fragment program mode   
    permits applications to define their own fragment programs.  
  
    A fragment program is a character string that specifies a sequence   
    of operations to perform.  Fragment program instructions are   
    typically 4-component vector operations that operate on per-fragment   
    attributes and program parameters.  Fragment programs execute on a   
    per-fragment basis and operate on each fragment completely   
    independently from any other fragments.  Fragment programs execute a   
    finite fixed sequence of instructions with no branching or looping.    
    Fragment programs execute without data hazards so results computed   
    in one instruction can be used immediately afterwards.  The result   
    of a fragment program is a set of fragment result registers that   
    becomes the color used by antialiasing application and/or a depth   
    value used in place of the interpolated depth value generated by   
    conventional rasterization.  
  
    In fragment program mode, the color sum is subsumed by the fragment  
    program.  An application desiring the primary and secondary colors  
    to be summed must explicitly include this operation in its program.  
  
    Fragment programs are defined to operate only in RGBA mode.  The   
    results of fragment program execution are undefined if the GL is in   
    color index mode.  
  
  
    3.11.1  Program Objects  
  
    The GL provides one or more program targets, each identifying a   
    portion of the GL that can be controlled through application-  
    specified programs.  The program target for fragment programs is   
    FRAGMENT_PROGRAM_ARB.  Each program target has an associated program   
    object, called the current program object.  Each program target also   
    has a default program object, which is initially the current program   
    object.  
  
    Each program object has an associated program string.  The command  
  
      ProgramStringARB(enum target, enum format, sizei len,   
                       const void *string);  
  
    updates the program string for the current program object for   
    <target>.  <format> describes the format of the program string,   
    which must currently be PROGRAM_FORMAT_ASCII_ARB.  <string> is a   
    pointer to the array of bytes representing the program string being   
    loaded, which need not be null-terminated.  The length of the array   
    is given by <len>.  If <string> is null-terminated, <len> should not   
    include the terminator.  
  
    When a program string is loaded, it is interpreted according to   
    syntactic and semantic rules corresponding to the program target   
    specified by <target>.  If a program violates the syntactic or   
    semantic restrictions of the program target, ProgramStringARB   
    generates the error INVALID_OPERATION.  An implementation may also  
    generate the error INVALID_OPERATION if the program would exceed  
    the native resource limits defined in section 6.1.12.  A program  
    which fails to load due to exceeding native resource limits must  
    always fail, regardless of any other GL state.  
  
    Additionally, ProgramString will update the program error position  
    (PROGRAM_ERROR_POSITION_ARB) and error string   
    (PROGRAM_ERROR_STRING_ARB).  If a program fails to load, the value   
    of the program error position is set to the ubyte offset into the   
    specified program string indicating where the first program error   
    was detected.  If the program fails to load because of a semantic   
    restriction that is not detected until the program is fully   
    scanned, the error position is set to the value of <len>.  If a  
    program loads successfully, the error position is set to the value  
    negative one.  The implementation-dependent program error string   
    contains one or more error or warning messages.  If a program loads   
    succesfully, the error string may either contain warning messages or   
    be empty.  
  
    Each program object has an associated array of program local   
    parameters.  The number and type of program local parameters is   
    target- and implementation-dependent.  For fragment programs,   
    program local parameters are four-component floating-point vectors.    
    The number of vectors is given by the implementation-dependent   
    constant MAX_PROGRAM_LOCAL_PARAMETERS_ARB, which must be at least   
    24.  The commands  
  
      void ProgramLocalParameter4fARB(enum target, uint index,  
                                      float x, float y, float z, float w);  
      void ProgramLocalParameter4fvARB(enum target, uint index,   
                                       const float *params);  
      void ProgramLocalParameter4dARB(enum target, uint index,  
                                      double x, double y, double z, double w);  
      void ProgramLocalParameter4dvARB(enum target, uint index,   
                                       const double *params);  
  
    update the values of the program local parameter numbered <index>  
    belonging to the program object currently bound to <target>.  For  
    ProgramLocalParameter4fARB and ProgramLocalParameter4dARB, the four  
    components of the parameter are updated with the values of <x>, <y>,   
    <z>, and <w>, respectively.  For ProgramLocalParameter4fvARB and  
    ProgramLocalParameter4dvARB, the four components of the parameter   
    are updated with the array of four values pointed to by <params>.    
    The error INVALID_VALUE is generated if <index> is greater than or   
    equal to the number of program local parameters supported by   
    <target>.  
  
    Additionally, each program target has an associated array of program   
    environment parameters.  Unlike program local parameters, program  
    environment parameters are shared by all program objects of a given   
    target.  The number and type of program environment parameters is   
    target- and implementation-dependent.  For fragment programs,   
    program environment parameters are four-component floating-point   
    vectors.  The number of vectors is given by the implementation-  
    dependent constant MAX_PROGRAM_ENV_PARAMETERS_ARB, which must be at   
    least 24.  The commands  
  
      void ProgramEnvParameter4fARB(enum target, uint index,  
                                    float x, float y, float z, float w);  
      void ProgramEnvParameter4fvARB(enum target, uint index,  
                                     const float *params);  
      void ProgramEnvParameter4dARB(enum target, uint index,  
                                    double x, double y, double z, double w);  
      void ProgramEnvParameter4dvARB(enum target, uint index,  
                                     const double *params);  
  
    update the values of the program environment parameter numbered   
    <index> for the given program target <target>.  For   
    ProgramEnvParameter4fARB and ProgramEnvParameter4dARB, the four   
    components of the parameter are updated with the values of <x>, <y>,   
    <z>, and <w>, respectively.  For ProgramEnvParameter4fvARB and   
    ProgramEnvParameter4dvARB, the four components of the parameter are   
    updated with the array of four values pointed to by <params>.  The   
    error INVALID_VALUE is generated if <index> is greater than or equal   
    to the number of program environment parameters supported by   
    <target>.  
  
    Each program target has a default program object.  Additionally,   
    named program objects can be created and operated upon.  The name   
    space for program objects is the positive integers and is shared by   
    programs of all targets.  The name zero is reserved by the GL.  
  
    A named program object is created by binding an unused program   
    object name to a valid program target.  The binding is effected by   
    calling   
  
      BindProgramARB(enum target, uint program);  
  
    with <target> set to the desired program target and <program> set to   
    the unused program name.  The resulting program object has a program   
    target given by <target> and is assigned target-specific default   
    values (see section 3.11.8 for fragment programs).  BindProgramARB   
    may also be used to bind an existing program object to a program   
    target.  If <program> is zero, the default program object for   
    <target> is bound.  If <program> is the name of an existing program  
    object whose associated program target is <target>, the named   
    program object is bound.  The error INVALID_OPERATION is generated   
    if <program> names an existing program object whose associated   
    program target is anything other than <target>.  
  
    Programs objects are deleted by calling  
  
      void DeleteProgramsARB(sizei n, const uint *programs);  
  
    <programs> contains <n> names of programs to be deleted.  After a   
    program object is deleted, its name is again unused.  If a program   
    object that is bound to any target is deleted, it is as though   
    BindProgramARB is first executed with same target and a <program> of   
    zero.  Unused names in <programs> are silently ignored, as is the   
    value zero.  
  
    The command  
  
      void GenProgramsARB(sizei n, uint *programs);  
  
    returns <n> currently unused program names in <programs>.  These   
    names are marked as used, for the purposes of GenProgramsARB only,   
    but objects are created only when they are first bound using   
    BindProgramARB.  
  
  
    3.11.2  Fragment Program Grammar and Semantic Restrictions  
  
    Fragment program strings are specified as an array of ASCII   
    characters containing the program text.  When a fragment program is   
    loaded by a call to ProgramStringARB, the program string is parsed   
    into a set of tokens possibly separated by whitespace.  Spaces,   
    tabs, newlines, carriage returns, and comments are considered   
    whitespace.  Comments begin with the character "#" and are   
    terminated by a newline, a carriage return, or the end of the   
    program array.  
  
    The Backus-Naur Form (BNF) grammar below specifies the syntactically   
    valid sequences for fragment programs.  The set of valid tokens can   
    be inferred from the grammar.  The token "" represents an empty   
    string and is used to indicate optional rules.  A program is invalid   
    if it contains any undefined tokens or characters.  
  
    A fragment program is required to begin with the header string   
    "!!ARBfp1.0", without any preceding whitespace.  This string   
    identifies the subsequent program text as a fragment program   
    (version 1.0) that should be parsed according to the following   
    grammar and semantic rules.  Program string parsing begins with the   
    character immediately following the header string.  
  
    <program>              ::= <optionSequence> <statementSequence> "END"  
  
    <optionSequence>       ::= <optionSequence> <option>  
                             | ""  
  
    <option>               ::= "OPTION" <identifier> ";"  
  
    <statementSequence>    ::= <statementSequence> <statement>  
                             | ""  
  
    <statement>            ::= <instruction> ";"  
                             | <namingStatement> ";"  
  
    <instruction>          ::= <ALUInstruction>  
                             | <TexInstruction>  
  
    <ALUInstruction>       ::= <VECTORop_instruction>  
                             | <SCALARop_instruction>  
                             | <BINSCop_instruction>  
                             | <BINop_instruction>  
                             | <TRIop_instruction>  
                             | <SWZ_instruction>  
  
    <TexInstruction>       ::= <SAMPLE_instruction>  
                             | <KIL_instruction>  
  
    <VECTORop_instruction> ::= <VECTORop> <maskedDstReg> ","   
                               <vectorSrcReg>  
  
    <VECTORop>             ::= "ABS" | "ABS_SAT"  
                             | "FLR" | "FLR_SAT"  
                             | "FRC" | "FRC_SAT"  
                             | "LIT" | "LIT_SAT"  
                             | "MOV" | "MOV_SAT"  
  
    <SCALARop_instruction> ::= <SCALARop> <maskedDstReg> ","    
                               <scalarSrcReg>   
   
    <SCALARop>             ::= "COS" | "COS_SAT"  
                             | "EX2" | "EX2_SAT"  
                             | "LG2" | "LG2_SAT"  
                             | "RCP" | "RCP_SAT"  
                             | "RSQ" | "RSQ_SAT"  
                             | "SIN" | "SIN_SAT"  
                             | "SCS" | "SCS_SAT"  
   
    <BINSCop_instruction>  ::= <BINSCop> <maskedDstReg> ","   
                               <scalarSrcReg> "," <scalarSrcReg>   
  
    <BINSCop>              ::= "POW" | "POW_SAT"  
   
    <BINop_instruction>    ::= <BINop> <maskedDstReg> ","  
                               <vectorSrcReg> "," <vectorSrcReg>  
  
    <BINop>                ::= "ADD" | "ADD_SAT"  
                             | "DP3" | "DP3_SAT"  
                             | "DP4" | "DP4_SAT"  
                             | "DPH" | "DPH_SAT"  
                             | "DST" | "DST_SAT"  
                             | "MAX" | "MAX_SAT"  
                             | "MIN" | "MIN_SAT"  
                             | "MUL" | "MUL_SAT"  
                             | "SGE" | "SGE_SAT"  
                             | "SLT" | "SLT_SAT"  
                             | "SUB" | "SUB_SAT"  
                             | "XPD" | "XPD_SAT"  
  
    <TRIop_instruction>    ::= <TRIop> <maskedDstReg> ","  
                               <vectorSrcReg> "," <vectorSrcReg> ","  
                               <vectorSrcReg>  
  
    <TRIop>                ::= "CMP" | "CMP_SAT"  
                             | "LRP" | "LRP_SAT"  
                             | "MAD" | "MAD_SAT"  
  
    <SWZ_instruction>      ::= <SWZop> <maskedDstReg> ","   
                               <srcReg> "," <extendedSwizzle>  
  
    <SWZop>                ::= "SWZ" | "SWZ_SAT"  
  
    <SAMPLE_instruction>   ::= <SAMPLEop> <maskedDstReg> ","  
                               <vectorSrcReg> "," <texImageUnit> ","   
                               <texTarget>  
  
    <SAMPLEop>             ::= "TEX" | "TEX_SAT"  
                             | "TXP" | "TXP_SAT"  
                             | "TXB" | "TXB_SAT"  
  
    <KIL_instruction>      ::= "KIL" <vectorSrcReg>  
  
    <texImageUnit>         ::= "texture" <optTexImageUnitNum>  
  
    <texTarget>            ::= "1D"  
                             | "2D"  
                             | "3D"  
                             | "CUBE"  
                             | "RECT"  
  
    <optTexImageUnitNum>   ::= ""  
                             | "[" <texImageUnitNum> "]"  
  
    <texImageUnitNum>      ::= <integer> from 0 to   
                               MAX_TEXTURE_IMAGE_UNITS_ARB-1  
  
    <scalarSrcReg>         ::= <optionalSign> <srcReg> <scalarSuffix>  
  
    <vectorSrcReg>         ::= <optionalSign> <srcReg> <optionalSuffix>   
   
    <maskedDstReg>         ::= <dstReg> <optionalMask>  
  
    <extendedSwizzle>      ::= <xyzwExtendedSwizzle>  
                             | <rgbaExtendedSwizzle>  
  
    <xyzwExtendedSwizzle>  ::= <xyzwExtSwizComp> "," <xyzwExtSwizComp> ","   
                               <xyzwExtSwizComp> "," <xyzwExtSwizComp>  
  
    <rgbaExtendedSwizzle>  ::= <rgbaExtSwizComp> "," <rgbaExtSwizComp> ","   
                               <rgbaExtSwizComp> "," <rgbaExtSwizComp>  
  
    <xyzwExtSwizComp>      ::= <optionalSign> <xyzwExtSwizSel>  
  
    <rgbaExtSwizComp>      ::= <optionalSign> <rgbaExtSwizSel>  
  
    <xyzwExtSwizSel>       ::= "0"   
                             | "1"   
                             | <xyzwComponent>  
  
    <rgbaExtSwizSel>       ::= "0"   
                             | "1"   
                             | <rgbaComponent>  
  
    <srcReg>               ::= <fragmentAttribReg>  
                             | <temporaryReg>  
                             | <progParamReg>  
  
    <dstReg>               ::= <temporaryReg>  
                             | <fragmentResultReg>  
  
    <fragmentAttribReg>    ::= <establishedName>  
                             | <fragAttribBinding>  
  
    <temporaryReg>         ::= <establishedName>  
  
    <progParamReg>         ::= <progParamSingle>  
                             | <progParamArray> "[" <progParamArrayAbs> "]"  
                             | <paramSingleItemUse>  
  
    <progParamSingle>      ::= <establishedName>  
  
    <progParamArray>       ::= <establishedName>  
  
    <progParamArrayAbs>    ::= <integer>  
  
    <fragmentResultReg>    ::= <establishedName>  
                             | <resultBinding>  
  
    <scalarSuffix>         ::= "." <component>  
  
    <optionalSuffix>       ::= ""   
                             | "." <component>   
                             | "." <xyzwComponent> <xyzwComponent>  
                                   <xyzwComponent> <xyzwComponent>  
                             | "." <rgbaComponent> <rgbaComponent>  
                                   <rgbaComponent> <rgbaComponent>  
   
    <component>            ::= <xyzwComponent>  
                             | <rgbaComponent>  
  
    <xyzwComponent>        ::= "x" | "y" | "z" | "w"  
  
    <rgbaComponent>        ::= "r" | "g" | "b" | "a"  
  
    <optionalMask>         ::= ""  
                             | <xyzwMask>  
                             | <rgbaMask>  
  
    <xyzwMask>             ::= "." "x"  
                             | "." "y"  
                             | "." "xy"  
                             | "." "z"  
                             | "." "xz"  
                             | "." "yz"  
                             | "." "xyz"  
                             | "." "w"  
                             | "." "xw"  
                             | "." "yw"  
                             | "." "xyw"  
                             | "." "zw"  
                             | "." "xzw"  
                             | "." "yzw"  
                             | "." "xyzw"  
  
    <rgbaMask>             ::= "." "r"  
                             | "." "g"  
                             | "." "rg"  
                             | "." "b"  
                             | "." "rb"  
                             | "." "gb"  
                             | "." "rgb"  
                             | "." "a"  
                             | "." "ra"  
                             | "." "ga"  
                             | "." "rga"  
                             | "." "ba"  
                             | "." "rba"  
                             | "." "gba"  
                             | "." "rgba"  
  
    <namingStatement>      ::= <ATTRIB_statement>  
                             | <PARAM_statement>  
                             | <TEMP_statement>  
                             | <OUTPUT_statement>  
                             | <ALIAS_statement>  
  
    <ATTRIB_statement>     ::= "ATTRIB" <establishName> "="  
                                 <fragAttribBinding>  
  
    <fragAttribBinding>    ::= "fragment" "." <fragAttribItem>  
  
    <fragAttribItem>       ::= "color" <optColorType>  
                             | "texcoord" <optTexCoordNum>  
                             | "fogcoord"  
                             | "position"  
  
    <PARAM_statement>      ::= <PARAM_singleStmt>  
                             | <PARAM_multipleStmt>  
  
    <PARAM_singleStmt>     ::= "PARAM" <establishName> <paramSingleInit>  
  
    <PARAM_multipleStmt>   ::= "PARAM" <establishName> "[" <optArraySize> "]"  
                                   <paramMultipleInit>  
  
    <optArraySize>         ::= ""  
                             | <integer> from 1 to MAX_PROGRAM_PARAMETERS_ARB  
                                 (maximum number of allowed program   
                                  parameter bindings)  
  
    <paramSingleInit>      ::= "=" <paramSingleItemDecl>  
  
    <paramMultipleInit>    ::= "=" "{" <paramMultInitList> "}"  
  
    <paramMultInitList>    ::= <paramMultipleItem>  
                             | <paramMultipleItem> "," <paramMultInitList>  
  
    <paramSingleItemDecl>  ::= <stateSingleItem>  
                             | <programSingleItem>  
                             | <paramConstDecl>  
  
    <paramSingleItemUse>   ::= <stateSingleItem>  
                             | <programSingleItem>  
                             | <paramConstUse>  
  
    <paramMultipleItem>    ::= <stateMultipleItem>  
                             | <programMultipleItem>  
                             | <paramConstDecl>  
  
    <stateMultipleItem>    ::= <stateSingleItem>  
                             | "state" "." <stateMatrixRows>  
  
    <stateSingleItem>      ::= "state" "." <stateMaterialItem>  
                             | "state" "." <stateLightItem>  
                             | "state" "." <stateLightModelItem>  
                             | "state" "." <stateLightProdItem>  
                             | "state" "." <stateTexEnvItem>  
                             | "state" "." <stateFogItem>  
                             | "state" "." <stateDepthItem>  
                             | "state" "." <stateMatrixRow>  
  
    <stateMaterialItem>    ::= "material" <optFaceType> "." <stateMatProperty>  
  
    <stateMatProperty>     ::= "ambient"  
                             | "diffuse"  
                             | "specular"  
                             | "emission"  
                             | "shininess"  
  
    <stateLightItem>       ::= "light" "[" <stateLightNumber> "]" "."   
                                 <stateLightProperty>  
  
    <stateLightProperty>   ::= "ambient"  
                             | "diffuse"   
                             | "specular"  
                             | "position"  
                             | "attenuation"  
                             | "spot" "." <stateSpotProperty>  
                             | "half"  
  
    <stateSpotProperty>    ::= "direction"   
  
    <stateLightModelItem>  ::= "lightmodel" <stateLModProperty>  
  
    <stateLModProperty>    ::= "." "ambient"  
                             | <optFaceType> "." "scenecolor"  
  
    <stateLightProdItem>   ::= "lightprod" "[" <stateLightNumber> "]"  
                                 <optFaceType> "." <stateLProdProperty>  
  
    <stateLProdProperty>   ::= "ambient"  
                             | "diffuse"  
                             | "specular"  
  
    <stateLightNumber>     ::= <integer> from 0 to MAX_LIGHTS-1  
  
    <stateTexEnvItem>      ::= "texenv" <optLegacyTexUnitNum> "."   
                                 <stateTexEnvProperty>  
  
    <stateTexEnvProperty>  ::= "color"  
  
    <optLegacyTexUnitNum>  ::= ""  
                             | "[" <legacyTexUnitNum> "]"  
  
    <legacyTexUnitNum>     ::= <integer> from 0 to MAX_TEXTURE_UNITS-1  
  
    <stateFogItem>         ::= "fog" "." <stateFogProperty>  
  
    <stateFogProperty>     ::= "color"   
                             | "params"   
  
    <stateDepthItem>       ::= "depth" "." <stateDepthProperty>  
  
    <stateDepthProperty>   ::= "range"   
  
    <stateMatrixRow>       ::= <stateMatrixItem> "." "row" "["   
                                  <stateMatrixRowNum> "]"  
  
    <stateMatrixRows>      ::= <stateMatrixItem> <optMatrixRows>  
  
    <optMatrixRows>        ::= ""  
                             | "." "row" "[" <stateMatrixRowNum> ".."   
                                  <stateMatrixRowNum> "]"  
  
    <stateMatrixItem>      ::= "matrix" . <stateMatrixName>   
                               <stateOptMatModifier>  
  
    <stateOptMatModifier>  ::= ""  
                             | "." <stateMatModifier>  
  
    <stateMatModifier>     ::= "inverse"   
                             | "transpose"   
                             | "invtrans"  
  
    <stateMatrixRowNum>    ::= <integer> from 0 to 3  
  
    <stateMatrixName>      ::= "modelview" <stateOptModMatNum>  
                             | "projection"  
                             | "mvp"  
                             | "texture" <optTexCoordNum>  
                             | "palette" "[" <statePaletteMatNum> "]"  
                             | "program" "[" <stateProgramMatNum> "]"  
                               
    <stateOptModMatNum>    ::= ""  
                             | "[" <stateModMatNum> "]"  
  
    <stateModMatNum>       ::= <integer> from 0 to MAX_VERTEX_UNITS_ARB-1  
  
    <optTexCoordNum>       ::= ""  
                             | "[" <texCoordNum> "]"  
  
    <texCoordNum>          ::= <integer> from 0 to MAX_TEXTURE_COORDS_ARB-1  
  
    <statePaletteMatNum>   ::= <integer> from 0 to MAX_PALETTE_MATRICES_ARB-1  
  
    <stateProgramMatNum>   ::= <integer> from 0 to MAX_PROGRAM_MATRICES_ARB-1  
  
    <programSingleItem>    ::= <progEnvParam>  
                             | <progLocalParam>  
  
    <programMultipleItem>  ::= <progEnvParams>  
                             | <progLocalParams>  
  
    <progEnvParams>        ::= "program" "." "env"   
                                 "[" <progEnvParamNums> "]"  
  
    <progEnvParamNums>     ::= <progEnvParamNum>  
                             | <progEnvParamNum> ".." <progEnvParamNum>  
  
    <progEnvParam>         ::= "program" "." "env"   
                                 "[" <progEnvParamNum> "]"  
  
    <progLocalParams>      ::= "program" "." "local"   
                                 "[" <progLocalParamNums> "]"  
  
    <progLocalParamNums>   ::= <progLocalParamNum>  
                             | <progLocalParamNum> ".." <progLocalParamNum>  
  
    <progLocalParam>       ::= "program" "." "local"   
                                 "[" <progLocalParamNum> "]"  
  
    <progEnvParamNum>      ::= <integer> from 0 to  
                               MAX_PROGRAM_ENV_PARAMETERS_ARB - 1   
  
    <progLocalParamNum>    ::= <integer> from 0 to  
                               MAX_PROGRAM_LOCAL_PARAMETERS_ARB - 1   
  
    <paramConstDecl>       ::= <paramConstScalarDecl>  
                             | <paramConstVector>  
  
    <paramConstUse>        ::= <paramConstScalarUse>  
                             | <paramConstVector>  
  
    <paramConstScalarDecl> ::= <signedFloatConstant>  
  
    <paramConstScalarUse>  ::= <floatConstant>  
  
    <paramConstVector>     ::= "{" <signedFloatConstant> "}"  
                             | "{" <signedFloatConstant> ","   
                                   <signedFloatConstant> "}"  
                             | "{" <signedFloatConstant> ","   
                                   <signedFloatConstant> ","  
                                   <signedFloatConstant> "}"  
                             | "{" <signedFloatConstant> ","   
                                   <signedFloatConstant> ","  
                                   <signedFloatConstant> ","   
                                   <signedFloatConstant> "}"  
  
    <signedFloatConstant>  ::= <optionalSign> <floatConstant>  
  
    <floatConstant>        ::= see text  
  
    <optionalSign>         ::= ""  
                             | "-"  
                             | "+"  
  
    <TEMP_statement>       ::= "TEMP" <varNameList>  
  
    <varNameList>          ::= <establishName>  
                             | <establishName> "," <varNameList>  
  
    <OUTPUT_statement>     ::= "OUTPUT" <establishName> "="  
                                 <resultBinding>  
  
    <resultBinding>        ::= "result" "." "color"  
                             | "result" "." "depth"  
  
    <optFaceType>          ::= ""  
                             | "." "front"  
                             | "." "back"  
  
    <optColorType>         ::= ""  
                             | "." "primary"  
                             | "." "secondary"  
  
    <ALIAS_statement>      ::= "ALIAS" <establishName> "="  
                                 <establishedName>  
  
    <establishName>        ::= <identifier>  
  
    <establishedName>      ::= <identifier>  
  
    <identifier>           ::= see text  
  
    The <integer> rule matches an integer constant.  The integer   
    consists of a sequence of one or more digits ("0" through "9").  
  
    The <floatConstant> rule matches a floating-point constant   
    consisting of an integer part, a decimal point, a fraction part, an   
    "e" or "E", and an optionally signed integer exponent.  The integer   
    and fraction parts both consist of a sequence of one or more digits   
    ("0" through "9").  Either the integer part or the fraction parts   
    (not both) may be missing; either the decimal point or the "e" (or   
    "E") and the exponent (not both) may be missing.  
  
    The <identifier> rule matches a sequence of one or more letters ("A"  
    through "Z", "a" through "z"), digits ("0" through "9), underscores   
    ("_"), or dollar signs ("$"); the first character must not be a   
    number.  Upper and lower case letters are considered different   
    (names are case-sensitive).  The following strings are reserved   
    keywords and may not be used as identifiers:  
  
        ABS, ABS_SAT, ADD, ADD_SAT, ALIAS, ATTRIB, CMP, CMP_SAT, COS,  
        COS_SAT, DP3, DP3_SAT, DP4, DP4_SAT, DPH, DPH_SAT, DST, DST_SAT,   
        END, EX2, EX2_SAT, FLR, FLR_SAT, FRC, FRC_SAT, KIL, LG2,   
        LG2_SAT, LIT, LIT_SAT, LRP, LRP_SAT, MAD, MAD_SAT, MAX, MAX_SAT,   
        MIN, MIN_SAT, MOV, MOV_SAT, MUL, MUL_SAT, OPTION, OUTPUT, PARAM,   
        POW, POW_SAT, RCP, RCP_SAT, RSQ, RSQ_SAT, SIN, SIN_SAT, SCS,   
        SCS_SAT, SGE, SGE_SAT, SLT, SLT_SAT, SUB, SUB_SAT, SWZ, SWZ_SAT,   
        TEMP, TEX, TEX_SAT, TXB, TXB_SAT, TXP, TXP_SAT, XPD, XPD_SAT,   
        fragment, program, result, state, and texture.  
  
    The error INVALID_OPERATION is generated if a fragment program fails   
    to load because it is not syntactically correct or for one of the   
    semantic restrictions described in the following sections.  
  
    A successfully loaded fragment program is parsed into a sequence of  
    instructions.  Each instruction is identified by its tokenized name.    
    The operation of these instructions when executed is defined in   
    section 3.11.5.  
  
    A successfully loaded program string replaces the program string  
    previously loaded into the specified program object.  If the   
    OUT_OF_MEMORY error is generated by ProgramStringARB, no change is   
    made to the previous contents of the current program object.  
  
  
    3.11.3  Fragment Program Variables  
  
    Fragment programs may access a number of different variables during   
    their execution.  The following sections define the variables that   
    can be declared and used by a fragment program.  
  
    Explicit variable declarations allow a fragment program to establish   
    a variable name that can be used to refer to a specified resource in   
    subsequent instructions.  A fragment program will fail to load if it   
    declares the same variable name more than once or if it refers to a  
    variable name that has not been previously declared in the program   
    string.  
  
    Implicit variable declarations allow a fragment program to use the   
    name of certain available resources by name.  
  
  
    3.11.3.1  Fragment Attributes  
  
    Fragment program attribute variables are a set of four-component  
    floating-point vectors holding the attributes of the fragment being  
    processed.  Fragment attribute variables are read-only during   
    fragment program execution.  
  
    Fragment attribute variables can be declared explicitly using the  
    <ATTRIB_statement> grammar rule, or implicitly using the  
    <fragAttribBinding> grammar rule in an executable instruction.  
  
    Each fragment attribute variable is bound to a single item of   
    fragment state according to the <fragAttrBinding> grammar rule.  The   
    set of GL state that can be bound to a fragment attribute variable   
    is given in Table X.1.  Fragment attribute variables are initialized   
    at each fragment program invocation with the current values of the   
    bound state.  
  
      Fragment Attribute Binding  Components  Underlying State  
      --------------------------  ----------  ----------------------------  
      fragment.color              (r,g,b,a)   primary color  
      fragment.color.primary      (r,g,b,a)   primary color  
      fragment.color.secondary    (r,g,b,a)   secondary color  
      fragment.texcoord           (s,t,r,q)   texture coordinate, unit 0  
      fragment.texcoord[n]        (s,t,r,q)   texture coordinate, unit n  
      fragment.fogcoord           (f,0,0,1)   fog distance/coordinate  
      fragment.position           (x,y,z,1/w) window position  
  
      Table X.1:  Fragment Attribute Bindings.  The "Components" column  
      indicates the mapping of the state in the "Underlying State"   
      column.  Bindings containing "[n]" require an integer value of <n>   
      to select an individual item.  
  
    If a fragment attribute binding matches "fragment.color" or  
    "fragment.color.primary", the "x", "y", "z", and "w" components of   
    the fragment attribute variable are filled with the "r", "g", "b",   
    and "a" components, respectively, of the fragment color.  
  
    If a fragment attribute binding matches "fragment.color.secondary",   
    the "x", "y", "z", and "w" components of the fragment attribute   
    variable are filled with the "r", "g", "b", and "a" components,   
    respectively, of the fragment secondary color.  
  
    If a fragment attribute binding matches "fragment.texcoord" or  
    "fragment.texcoord[n]", the "x", "y", "z", and "w" components of the   
    fragment attribute variable are filled with the "s", "t", "r", and   
    "q" components, respectively, of the fragment texture coordinates   
    for texture unit <n>.  If "[n]" is omitted, texture unit zero is   
    used.  
  
    If a fragment attribute binding matches "fragment.fogcoord", the "x"   
    component of the fragment attribute variable is filled with either  
    the fragment eye distance or the fog coordinate, depending on   
    whether the fog source is set to FRAGMENT_DEPTH_EXT or   
    FOG_COORDINATE_EXT, respectively.  The "y", "z", and "w" coordinates   
    are filled with 0, 0, and 1, respectively.  
  
    If a fragment attribute binding matches "fragment.position", the "x"  
    and "y" components of the fragment attribute variable are filled   
    with the (x,y) window coordinates of the fragment center, relative   
    to the lower left corner of the window.  The "z" component is filled   
    with the fragment's z window coordinate.  The "W" component is   
    filled with the reciprocal of the fragment's clip w coordinate.  
  
    On some implementations, the components of fragment.position may be  
    generated by interpolating per-vertex position values.  This may  
    produce x and y window coordinates that don't exactly match those of  
    the fragment center and z window coordinates that do not exactly  
    match those generated by fixed-function rasterization.  Therefore,  
    there is no guaranteed invariance between the final z window  
    coordinates of fragments processed by fragment programs that write  
    depth values and fragments processed by any other means, even if the  
    fragment programs in question simply copy the z value from the  
    fragment.position binding.  
  
  
    3.11.3.2  Fragment Program Parameters  
  
    Fragment program parameter variables are a set of four-component  
    floating-point vectors used as constants during fragment program   
    execution.  Fragment program parameters retain their values across   
    fragment program invocations, although their values can change   
    between invocations due to GL state changes.  
  
    Single program parameter variables and arrays of program parameter  
    variables can be declared explicitly using the <PARAM_statement>   
    grammar rule.  Single program parameter variables can also be   
    declared implicitly using the <paramSingleItemUse> grammar rule in   
    an executable instruction.  
  
    Each single program parameter variable is bound to a constant vector   
    or to a GL state vector according to the <paramSingleInit> grammar   
    rule.  Individual items of a program parameter array are bound to   
    constant vectors or GL state vectors according to the   
    <programMultipleInit> grammar rule.  The set of GL state that can be   
    bound to program parameter variables are given in Tables X.2.1   
    through X.2.4.  
  
  
    Constant Bindings  
  
    A program parameter variable can be bound to a scalar or vector   
    constant using the <paramConstDecl> grammar rule (explicit   
    declarations) or the <paramConstUse> grammar rule (implicit   
    declarations).  
  
    If a program parameter binding matches the <paramConstScalarDecl> or  
    <paramConstScalarUse> grammar rules, the corresponding program   
    parameter variable is bound to the vector (X,X,X,X), where X is the   
    value of the specified constant.  Note that the   
    <paramConstScalarUse> grammar rule, used only in implicit   
    declarations, allows only non-negative constants.  This   
    disambiguates cases like "-2", which could conceivably be taken to   
    mean either the vector "(2,2,2,2)" with all components negated or   
    "(-2,-2,-2,-2)" without negation.  Only the former interpretation is   
    allowed by the grammar.  
  
    If a program parameter binding matches <paramConstVector>, the  
    corresponding program parameter variable is bound to the vector  
    (X,Y,Z,W), where X, Y, Z, and W are the values corresponding to the   
    first, second, third, and fourth match of <signedFloatConstant>.  If   
    fewer than four constants are specified, Y, Z, and W assume the   
    values 0.0, 0.0, and 1.0, if their respective constants are not   
    specified.  
  
    Program parameter variables initialized to constant values can never   
    be modified.  
  
  
    Program Environment/Local Parameter Bindings  
  
      Binding                        Components  Underlying State  
      -----------------------------  ----------  ----------------------------  
      program.env[a]                 (x,y,z,w)   program environment   
                                                 parameter a  
      program.local[a]               (x,y,z,w)   program local parameter a  
      program.env[a..b]              (x,y,z,w)   program environment  
                                                 parameters a through b  
      program.local[a..b]            (x,y,z,w)   program local parameters  
                                                 a through b  
  
      Table X.2.1:  Program Environment/Local Parameter Bindings.  <a>   
      and <b> indicate parameter numbers, where <a> must be less than or   
      equal to <b>.  
  
    If a program parameter binding matches "program.env[a]" or  
    "program.local[a]", the four components of the program parameter   
    variable are filled with the four components of program environment   
    parameter <a> or program local parameter <a>, respectively.  
  
    Additionally, for program parameter array bindings,   
    "program.env[a..b]" and "program.local[a..b]" are equivalent to   
    specifying program environment parameters <a> through <b> in order   
    or program local parameters <a> through <b> in order, respectively.    
    In either case, a program will fail to load if <a> is greater than   
    <b>.  
  
  
    Material Property Bindings  
  
      Binding                        Components  Underlying State  
      -----------------------------  ----------  ----------------------------  
      state.material.ambient         (r,g,b,a)   front ambient material color  
      state.material.diffuse         (r,g,b,a)   front diffuse material color  
      state.material.specular        (r,g,b,a)   front specular material color  
      state.material.emission        (r,g,b,a)   front emissive material color  
      state.material.shininess       (s,0,0,1)   front material shininess  
      state.material.front.ambient   (r,g,b,a)   front ambient material color  
      state.material.front.diffuse   (r,g,b,a)   front diffuse material color  
      state.material.front.specular  (r,g,b,a)   front specular material color  
      state.material.front.emission  (r,g,b,a)   front emissive material color  
      state.material.front.shininess (s,0,0,1)   front material shininess  
      state.material.back.ambient    (r,g,b,a)   back ambient material color  
      state.material.back.diffuse    (r,g,b,a)   back diffuse material color  
      state.material.back.specular   (r,g,b,a)   back specular material color  
      state.material.back.emission   (r,g,b,a)   back emissive material color  
      state.material.back.shininess  (s,0,0,1)   back material shininess  
  
      Table X.2.2:  Material Property Bindings.  If a material face is   
      not specified in the binding, the front property is used.  
  
    If a program parameter binding matches any of the material   
    properties listed in Table X.2.2, the program parameter variable is   
    filled according to the table.  For ambient, diffuse, specular, or   
    emissive colors, the "x", "y", "z", and "w" components are filled   
    with the "r", "g", "b", and "a" components, respectively, of the   
    corresponding material color.  For material shininess, the "x"   
    component is filled with the material's specular exponent, and the   
    "y", "z", and "w" components are filled with 0, 0, and 1,   
    respectively.  Bindings containing ".back" refer to the back   
    material; all other bindings refer to the front material.  
  
    Material properties can be changed inside a Begin/End pair, either  
    directly by calling Material, or indirectly through color material.  
    However, such property changes are not guaranteed to update program  
    parameter bindings until the following End command.  Program   
    parameter variables bound to material properties changed inside a   
    Begin/End pair are undefined until the following End command.  
  
  
    Light Property Bindings  
  
      Binding                        Components  Underlying State  
      -----------------------------  ----------  ----------------------------  
      state.light[n].ambient         (r,g,b,a)   light n ambient color  
      state.light[n].diffuse         (r,g,b,a)   light n diffuse color  
      state.light[n].specular        (r,g,b,a)   light n specular color  
      state.light[n].position        (x,y,z,w)   light n position  
      state.light[n].attenuation     (a,b,c,e)   light n attenuation constants  
                                                 and spot light exponent  
      state.light[n].spot.direction  (x,y,z,c)   light n spot direction and  
                                                 cutoff angle cosine  
      state.light[n].half            (x,y,z,1)   light n infinite half-angle  
      state.lightmodel.ambient       (r,g,b,a)   light model ambient color  
      state.lightmodel.scenecolor    (r,g,b,a)   light model front scene color  
      state.lightmodel      .        (r,g,b,a)   light model front scene color  
               front.scenecolor  
      state.lightmodel      .        (r,g,b,a)   light model back scene color  
               back.scenecolor  
      state.lightprod[n].ambient     (r,g,b,a)   light n / front material  
                                                 ambient color product  
      state.lightprod[n].diffuse     (r,g,b,a)   light n / front material  
                                                 diffuse color product  
      state.lightprod[n].specular    (r,g,b,a)   light n / front material  
                                                 specular color product  
      state.lightprod[n].            (r,g,b,a)   light n / front material  
              front.ambient                      ambient color product  
      state.lightprod[n].            (r,g,b,a)   light n / front material  
              front.diffuse                      diffuse color product  
      state.lightprod[n].            (r,g,b,a)   light n / front material  
              front.specular                     specular color product  
      state.lightprod[n].            (r,g,b,a)   light n / back material  
              back.ambient                       ambient color product  
      state.lightprod[n].            (r,g,b,a)   light n / back material  
              back.diffuse                       diffuse color product  
      state.lightprod[n].            (r,g,b,a)   light n / back material  
              back.specular                      specular color product  
  
      Table X.2.3: Light Property Bindings.  <n> indicates a light   
      number.  
  
    If a program parameter binding matches "state.light[n].ambient",  
    "state.light[n].diffuse", or "state.light[n].specular", the "x",   
    "y", "z", and "w" components of the program parameter variable are   
    filled with the "r", "g", "b", and "a" components, respectively, of   
    the corresponding light color.  
  
    If a program parameter binding matches "state.light[n].position",   
    the "x", "y", "z", and "w" components of the program parameter   
    variable are filled with the "x", "y", "z", and "w" components,   
    respectively, of the light position.  
      
    If a program parameter binding matches "state.light[n].attenuation",   
    the "x", "y", and "z" components of the program parameter variable   
    are filled with the constant, linear, and quadratic attenuation   
    parameters of the specified light, respectively (section 2.13.1).    
    The "w" component of the program parameter variable is filled with   
    the spot light exponent of the specified light.  
  
    If a program parameter binding matches   
    "state.light[n].spot.direction", the "x", "y", and "z" components of   
    the program parameter variable are filled with the "x", "y", and "z"   
    components of the spot light direction of the specified light,   
    respectively (section 2.13.1).  The "w" component of the program   
    parameter variable is filled with the cosine of the spot light   
    cutoff angle of the specified light.  
  
    If a program parameter binding matches "state.light[n].half", the   
    "x", "y", and "z" components of the program parameter variable are   
    filled with the x, y, and z components, respectively, of the   
    normalized infinite half-angle vector  
  
      h_inf = || P + (0, 0, 1) ||.  
  
    The "w" component is filled with 1.  In the computation of h_inf, P  
    consists of the x, y, and z coordinates of the normalized vector   
    from the eye position P_e to the eye-space light position P_pli   
    (section 2.13.1).  h_inf is defined to correspond to the normalized   
    half-angle vector when using an infinite light (w coordinate of the   
    position is zero) and an infinite viewer (v_bs is FALSE).  For local   
    lights or a local viewer, h_inf is well-defined but does not match   
    the normalized half-angle vector, which will vary depending on the   
    vertex position.  
  
    If a program parameter binding matches "state.lightmodel.ambient",   
    the "x", "y", "z", and "w" components of the program parameter   
    variable are filled with the "r", "g", "b", and "a" components of   
    the light model ambient color, respectively.  
  
    If a program parameter binding matches "state.lightmodel.scenecolor"   
    or "state.lightmodel.front.scenecolor", the "x", "y", and "z"   
    components of the program parameter variable are filled with the   
    "r", "g", and "b" components respectively of the "front scene color"  
  
      c_scene = a_cs * a_cm + e_cm,  
  
    where a_cs is the light model ambient color, a_cm is the front   
    ambient material color, and e_cm is the front emissive material   
    color.  The "w" component of the program parameter variable is   
    filled with the alpha component of the front diffuse material color.    
    If a program parameter binding matches   
    "state.lightmodel.back.scenecolor", a similar back scene color,   
    computed using back-facing material properties, is used.  The front  
    and back scene colors match the values that would be assigned to   
    vertices using conventional lighting if all lights were disabled.  
  
    If a program parameter binding matches anything beginning with  
    "state.lightprod[n]", the "x", "y", and "z" components of the   
    program parameter variable are filled with the "r", "g", and "b"   
    components, respectively, of the corresponding light product.  The   
    three light product components are the products of the corresponding   
    color components of the specified material property and the light   
    color of the specified light (see Table X.2.3).  The "w" component   
    of the program parameter variable is filled with the alpha component   
    of the specified material property.  
  
    Light products depend on material properties, which can be changed   
    inside a Begin/End pair.  Such property changes are not guaranteed   
    to take effect until the following End command.  Program parameter   
    variables bound to light products whose corresponding material   
    property changes inside a Begin/End pair are undefined until the   
    following End command.  
  
  
    Texture Environment Property Bindings  
  
      Binding                    Components  Underlying State  
      -------------------------  ----------  ----------------------------  
      state.texenv[n].color      (r,g,b,a)   texture environment n color  
  
      Table X.2.4:  Texture Environment Property Bindings.  "[n]" is   
      optional -- texture unit <n> is used if specified; texture unit 0   
      is used otherwise.  
  
    If a program parameter binding matches "state.texenv[n].color", the   
    "x", "y", "z", and "w" components of the program parameter variable   
    are filled with the "r", "g", "b", and "a" components, respectively,   
    of the corresponding texture environment color.  Note that only  
    "legacy" texture units, as queried by MAX_TEXTURE_UNITS, include   
    texture environment state.  Texture image units and texture   
    coordinate sets do not have associated texture environment state.  
  
  
    Fog Property Bindings  
  
      Binding                      Components  Underlying State  
      ---------------------------  ----------  ----------------------------  
      state.fog.color              (r,g,b,a)   RGB fog color (section 3.11)  
      state.fog.params             (d,s,e,r)   fog density, linear start  
                                               and end, and 1/(end-start)  
                                               (section 3.11)   
  
      Table X.2.5:  Fog Property Bindings  
  
    If a program parameter binding matches "state.fog.color", the "x",   
    "y", "z", and "w" components of the program parameter variable are   
    filled with the "r", "g", "b", and "a" components, respectively, of   
    the fog color (section 3.11).  
  
    If a program parameter binding matches "state.fog.params", the "x",   
    "y", and "z" components of the program parameter variable are filled   
    with the fog density, linear fog start, and linear fog end   
    parameters (section 3.11), respectively.  The "w" component is   
    filled with 1/(end-start), where end and start are the linear fog   
    end and start parameters, respectively.  
  
  
    Depth Property Bindings  
  
      Binding                      Components  Underlying State  
      ---------------------------  ----------  ----------------------------  
      state.depth.range            (n,f,d,1)   Depth range near, far, and  
                                               (far-near) (section 2.10.1)  
  
      Table X.2.6:  Depth Property Bindings  
  
    If a program parameter binding matches "state.depth.range", the "x"   
    and "y" components of the program parameter variable are filled with   
    the mappings of near and far clipping planes to window coordinates,  
    respectively.  The "z" component is filled with the difference of  
    the mappings of near and far clipping planes, far minus near.  The   
    "w" component is filled with 1.  
  
  
    Matrix Property Bindings  
  
      Binding                               Underlying State  
      ------------------------------------  ---------------------------  
      * state.matrix.modelview[n]           modelview matrix n  
        state.matrix.projection             projection matrix  
        state.matrix.mvp                    modelview-projection matrix  
      * state.matrix.texture[n]             texture matrix n  
        state.matrix.palette[n]             modelview palette matrix n  
        state.matrix.program[n]             program matrix n  
  
      Table X.2.7:  Base Matrix Property Bindings.  The "[n]" syntax   
      indicates a specific matrix number.  For modelview and texture   
      matrices, a matrix number is optional, and matrix zero will be   
      used if the matrix number is omitted.  These base bindings may   
      further be modified by a inverse/transpose selector and a row   
      selector.  
  
    If the beginning of a program parameter binding matches any of the   
    matrix binding names listed in Table X.2.7, the binding corresponds   
    to a 4x4 matrix.  If the parameter binding is followed by   
    ".inverse", ".transpose", or ".invtrans" (<stateMatModifier> grammar   
    rule), the inverse, transpose, or transpose of the inverse,   
    respectively, of the matrix specified in Table X.2.7 is selected.    
    Otherwise, the matrix specified in Table X.2.7 is selected.  If the   
    specified matrix is poorly-conditioned (singular or nearly so), its   
    inverse matrix is undefined.  The binding name "state.matrix.mvp"   
    refers to the product of modelview matrix zero and the projection   
    matrix, defined as  
  
       MVP = P * M0,  
  
    where P is the projection matrix and M0 is modelview matrix zero.  
  
    If the selected matrix is followed by ".row[<a>]" (matching the  
    <stateMatrixRow> grammar rule), the "x", "y", "z", and "w"   
    components of the program parameter variable are filled with the   
    four entries of row <a> of the selected matrix.  In the example,  
  
      PARAM m0 = state.matrix.modelview[1].row[0];  
      PARAM m1 = state.matrix.projection.transpose.row[3];  
  
    the variable "m0" is set to the first row (row 0) of modelview   
    matrix 1 and "m1" is set to the last row (row 3) of the transpose of   
    the projection matrix.  
  
    For program parameter array bindings, multiple rows of the selected   
    matrix can be bound via the <stateMatrixRows> grammar rule.  If the   
    selected matrix binding is followed by ".row[<a>..<b>]", the result   
    is equivalent to specifying matrix rows <a> through <b>, in order.    
    A program will fail to load if <a> is greater than <b>.  If no row   
    selection is specified (<optMatrixRows> matches ""), matrix rows 0   
    through 3 are bound in order.  In the example,  
  
      PARAM m2[] = { state.matrix.program[0].row[1..2] };  
      PARAM m3[] = { state.matrix.program[0].transpose };  
  
    the array "m2" has two entries, containing rows 1 and 2 of program   
    matrix zero, and "m3" has four entries, containing all four rows of   
    the transpose of program matrix zero.  
  
  
    Program Parameter Arrays  
  
    A program parameter array variable can be declared explicitly by   
    matching the <PARAM_multipleStmt> grammar rule.  Programs can   
    optionally specify the number of individual program parameters in   
    the array, using the <optArraySize> grammar rule.  Program parameter   
    arrays may not be declared implicity.  
  
    Individual parameter variables in a program parameter array are   
    bound to GL state vectors or constant vectors as specified by the   
    grammar rule <paramMultInitList>.  Each individual parameter in the   
    array is bound in turn as described above.    
  
    The total number of entries in the array is equal to the number of  
    parameters bound in the initializer list.  A fragment program that   
    specifies an array size (<optArraySize> matches <integer>) that does   
    not match the number of parameter bindings in the initialization   
    list will fail to load.  
  
    Program parameter array variables may only be accessed using   
    absolute addressing by matching the <progParamArrayAbs> grammar   
    rule.  Array accesses are checked against the limits of the array.    
    If any fragment program instruction accesses a program parameter  
    array with an out-of-range index (greater than or equal to the size   
    of the array), the fragment program will fail to load.  
  
    Individual state vectors can have no more than one unique binding in   
    any given program.  The GL will automatically combine multiple   
    bindings of the same state vector into a single unique binding.  
  
  
    3.11.3.3  Fragment Program Temporaries  
  
    Fragment program temporary variables are a set of four-component  
    floating-point vectors used to hold temporary results during   
    fragment program execution.  Temporaries do not persist between   
    program invocations, and are undefined at the beginning of each   
    fragment program invocation.  
  
    Fragment program temporary variables can be declared explicitly   
    using the <TEMP_statement> grammar rule.  Each such statement can   
    declare one or more temporaries.  Fragment program temporary   
    variables can not be declared implicitly.  
  
  
    3.11.3.4  Fragment Program Results  
  
    Fragment program result variables are a set of four component   
    floating-point vectors used to hold the final results of a fragment   
    program.  Fragment program result variables are write-only during   
    fragment program execution.  
  
    Fragment program result variables can be declared explicitly using   
    the <OUTPUT_statement> grammar rule, or implicitly using the  
    <resultBinding> grammar rule in an executable instruction.  Each   
    fragment program result variable is bound to a fragment attribute   
    used in subsequent back-end processing.  The set of fragment program  
    result variable bindings is given in Table X.3.  
  
      Binding                        Components  Description  
      -----------------------------  ----------  ----------------------------  
      result.color                   (r,g,b,a)   color  
      result.depth                   (*,*,d,*)   depth coordinate  
  
      Table X.3:  Fragment Result Variable Bindings.  Components labeled   
      "*" are unused.  
  
    If a result variable binding matches "result.color", updates to the   
    "x", "y", "z", and "w" components of the result variable modify the  
    "r", "g", "b", and "a" components, respectively, of the fragment's  
    output color.  If "result.color" is not both bound by the fragment   
    program and written by some instruction of the program, the output   
    color of the fragment program is undefined.  
  
    If a result variable binding matches "result.depth", updates to the   
    "z" component of the result variable modify the fragment's output  
    depth value.  If "result.depth" is not both bound by the fragment   
    program and written by some instruction of the program, the   
    interpolated depth value produced by rasterization is used as if   
    fragment program mode is not enabled.  Writes to any component of   
    depth other than the "z" component have no effect.  
  
  
    3.11.3.5  Fragment Program Aliases  
  
    Fragment programs can create aliases by matching the   
    <ALIAS_statement> grammar rule.  Aliases allow programs to use   
    multiple variable names to refer to a single underlying variable.    
    For example, the statement  
  
      ALIAS var1 = var0  
  
    establishes a variable name named "var1".  Subsequent references to   
    "var1" in the program text are treated as references to "var0".  The   
    left hand side of an ALIAS statement must be a new variable name,   
    and the right hand side must be an established variable name.  
  
    Aliases are not considered variable declarations, so do not count   
    against the limits on the number of variable declarations allowed in   
    the program text.  
  
  
    3.11.3.6  Fragment Program Resource Limits  
  
    The fragment program execution environment provides implementation-  
    dependent resource limits on the number of ALU instructions, texture  
    instructions, total instructions (ALU or texture), temporary   
    variable declarations, program parameter bindings, or texture  
    indirections.  A program that exceeds any of these resource limits   
    will fail to load.  The resource limits for fragment programs can be   
    queried by calling GetProgramiv (section 6.1.12) with a target of   
    FRAGMENT_PROGRAM_ARB.  
      
    The limit on fragment program ALU instructions can be queried with   
    a <pname> of MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, and must be at least   
    48.  Each ALU instruction in the program (matches of the   
    <ALUInstruction> grammar rule) counts against this limit.  
  
    The limit on fragment program texture instructions can be queried   
    with a <pname> of MAX_PROGRAM_TEX_INSTRUCTIONS_ARB, and must be at   
    least 24.  Each texture instruction in the program (matches of the   
    <TexInstruction> grammar rule) counts against this limit.  
  
    The limit on fragment program total instructions can be queried with   
    a <pname> of MAX_PROGRAM_INSTRUCTIONS_ARB, and must be at least 72.    
    Each instruction in the program (matching the <instruction> grammar   
    rule) counts against this limit.  Note that the limit on total  
    instructions is not necessarily equal to the sum of the limits on  
    ALU instructions and texture instructions.  
  
    The limit on fragment program texture indirections can be queried   
    with a <pname> of MAX_PROGRAM_TEX_INDIRECTIONS_ARB, and must be at   
    least 4.  Texture indirections are described in 3.11.6.  If an  
    implementation has no limit on texture indirections, the limit will  
    be equal to the limit on texture instructions.  
  
    The limit on fragment program temporary variable declarations can be   
    queried with a <pname> of MAX_PROGRAM_TEMPORARIES_ARB, and must be at   
    least 16.  Each temporary declared in the program, using the   
    <TEMP_statement> grammar rule, counts against this limit.  Aliases   
    of declared temporaries do not.  
      
    The limit on fragment program attribute bindings can be queried with   
    a <pname> of MAX_PROGRAM_ATTRIBS_ARB and must be at least 10.  Each   
    distinct vertex attribute bound explicitly or implicitly in the   
    program counts against this limit; vertex attributes bound multiple   
    times count only once.  
  
    The limit on fragment program parameter bindings can be queried with   
    a <pname> of MAX_PROGRAM_PARAMETERS_ARB, and must be at least 24.    
    Each distinct GL state vector bound explicitly or implicitly in the   
    program counts against this limit; GL state vectors bound multiple   
    times count only once.  Every other constant vector bound in the   
    program is counted if and only if an identical constant vector has   
    not already been counted.  Two constant vectors are considered   
    identical if the four component values are numerically equivalent.  
    Recall that scalar constants bound in a program are treated as   
    vector constants with the scalar value replicated.  
  
    In addition to the limits described above, the GL provides a similar   
    set of implementation-dependent native resource limits.  These   
    limits, specified in Section 6.1.12, provide guidance as to whether   
    the program is small enough to use a "native" mode where fragment   
    programs may be executed with higher performance.  The native   
    resource limits and usage counts are implementation-dependent and   
    may not exactly correspond to limits and counts described above.     
    A program's native resource consumption may be reduced by program   
    optimizations performed by the GL.  Native resource consumption may  
    be increased due to emulation of instructions or any other program  
    features not natively supported by an implementation.  Notably, an  
    additional texture indirection may be consumed due to an   
    implementation's lack of native support for texture instructions   
    with source coordinate swizzles or parameter source coordinates,   
    which may require emulation by prepending ALU instructions.  An   
    implementation may also fail to natively support all combinations of   
    attributes described in Table X.1, even if the total number of  
    bound attributes is fewer than the native attribute limit.  In this  
    case the program is still considered to exceed the native resource  
    limits, as queried by PROGRAM_UNDER_NATIVE_LIMITS_ARB (section   
    6.1.12).  
  
    To assist in resource counting, the GL additionally provides   
    GetProgram queries to determine the resource usage and native   
    resource usage of the currently bound program, and to determine   
    whether the bound program exceeds any native resource limit.  
  
    Programs that exceed any native resource limit may or may not load   
    depending on the implementation.  
  
  
    3.11.4  Fragment Program Execution Environment  
  
    If fragment program mode is enabled, the currently bound fragment   
    program is executed when any fragment is produced by rasterization.  
  
    If fragment program mode is enabled and the currently bound program   
    object does not contain a valid fragment program, the error   
    INVALID_OPERATION will be generated by Begin, RasterPos, and any   
    command that implicitly calls Begin (e.g., DrawArrays).  
  
    Fragment programs execute a sequence of instructions without  
    branching.  Fragment programs begin by executing the first   
    instruction in the program, and execute instructions in the order   
    specified in the program until the last instruction is completed.  
      
    There are 33 fragment program instructions.  The instructions and   
    their respective input and output parameters are summarized in   
    Table X.5.  
  
      Instruction    Inputs  Output   Description  
      -----------    ------  ------   --------------------------------  
      ABS            v       v        absolute value  
      ADD            v,v     v        add  
      CMP            v,v,v   v        compare  
      COS            s       ssss     cosine with reduction to [-PI,PI]  
      DP3            v,v     ssss     3-component dot product  
      DP4            v,v     ssss     4-component dot product  
      DPH            v,v     ssss     homogeneous dot product  
      DST            v,v     v        distance vector  
      EX2            s       ssss     exponential base 2  
      FLR            v       v        floor  
      FRC            v       v        fraction  
      KIL            v       v        kill fragment  
      LG2            s       ssss     logarithm base 2  
      LIT            v       v        compute light coefficients  
      LRP            v,v,v   v        linear interpolation  
      MAD            v,v,v   v        multiply and add  
      MAX            v,v     v        maximum  
      MIN            v,v     v        minimum  
      MOV            v       v        move  
      MUL            v,v     v        multiply  
      POW            s,s     ssss     exponentiate  
      RCP            s       ssss     reciprocal  
      RSQ            s       ssss     reciprocal square root  
      SCS            s       ss--     sine/cosine without reduction  
      SGE            v,v     v        set on greater than or equal  
      SIN            s       ssss     sine with reduction to [-PI,PI]  
      SLT            v,v     v        set on less than  
      SUB            v,v     v        subtract  
      SWZ            v       v        extended swizzle  
      TEX            v,u,t   v        texture sample  
      TXB            v,u,t   v        texture sample with bias  
      TXP            v,u,t   v        texture sample with projection  
      XPD            v,v     v        cross product  
  
      Table X.5:  Summary of fragment program instructions.  "v"   
      indicates a floating-point vector input or output, "s" indicates a   
      floating-point scalar input, "ssss" indicates a scalar output   
      replicated across a 4-component result vector, "ss--" indicates  
      two scalar outputs in the first two components, "u" indicates a   
      texture image unit identifier, and "t" indicates a texture target.  
  
  
    3.11.4.1  Fragment Program Operands  
  
    Most fragment program instructions operate on floating-point vectors   
    or scalars, as indicated by the grammar rules <vectorSrcReg> and  
    <scalarSrcReg>, respectively.  
  
    Vector and scalar operands can be obtained from fragment attribute,   
    program parameter, or temporary registers, as indicated by the   
    <srcReg> rule.  For scalar operands, a single vector component is   
    selected by the <scalarSuffix> rule, where the characters "x", "y",   
    "z", and "w", or "r", "g", "b", and "a" select the first, second,   
    third, and fourth components, respectively, of the vector.  
  
    Vector operands can be swizzled according to the <optionalSuffix>   
    rule.  In its most general form, the <optionalSuffix> rule matches  
    the pattern ".????" where each question mark is replaced with one of  
    "x", "y", "z", "w", "r", "g", "b", or "a".  For such patterns, the   
    first, second, third, and fourth components of the operand are taken   
    from the vector components named by the first, second, third, and   
    fourth character of the pattern, respectively.  For example, if the   
    swizzle suffix is ".yzzx" or ".gbbr" and the specified source   
    contains {2,8,9,0}, the swizzled operand used by the instruction is   
    {8,9,9,2}.  
  
    If the <optionalSuffix> rule matches "", it is treated as though it   
    were ".xyzw".  If the <optionalSuffix> rule matches (ignoring   
    whitespace) ".x", ".y", ".z", or ".w", these are treated the same as   
    ".xxxx", ".yyyy", ".zzzz", and ".wwww" respectively.  Likewise, if  
    the <optionalSuffix> rule matches ".r", ".g", ".b", or ".a", these   
    are treated the same as ".rrrr", ".gggg", ".bbbb", and ".aaaa"   
    respectively.  
  
    Floating-point scalar or vector operands can optionally be negated  
    according to the <optionalSign> rule in <scalarSrcReg> and  
    <vectorSrcReg>.  If the <optionalSign> matches "-", each operand or  
    operand component is negated.  
  
    The following pseudo-code spells out the operand generation process.    
    In the example, "float" is a floating-point scalar type, while   
    "floatVec" is a four-component vector.  "source" refers to the   
    register used for the operand, matching the <srcReg> rule.  "negate"   
    is TRUE if the <optionalSign> rule in <scalarSrcReg> or   
    <vectorSrcReg> matches "-" and FALSE otherwise.  The ".c***",   
    ".*c**", ".**c*", ".***c" modifiers refer to the x, y, z, and w   
    components obtained by the swizzle operation; the ".c" modifier  
    refers to the single component selected for a scalar load.  
  
      floatVec VectorLoad(floatVec source)  
      {  
          floatVec operand;  
  
          operand.x = source.c***;  
          operand.y = source.*c**;  
          operand.z = source.**c*;  
          operand.w = source.***c;  
          if (negate) {  
             operand.x = -operand.x;  
             operand.y = -operand.y;  
             operand.z = -operand.z;  
             operand.w = -operand.w;  
          }  
  
          return operand;  
      }  
  
      float ScalarLoad(floatVec source)   
      {  
          float operand;  
  
          operand = source.c;  
          if (negate) {  
            operand = -operand;  
          }  
  
          return operand;  
      }  
  
  
    3.11.4.2  Fragment Program Parameter Arrays  
  
    A fragment program can load a single element of a program parameter   
    array using only absolute addressing.  Program parameter arrays are   
    accessed when the <progParamArrayAbs> rule is matched.  The offset   
    of the selected entry in the array is given by the number matching   
    <progParamRegNum>.  If the offset exceeds the size of the   
    array, the results of the access are undefined, but may not lead to  
    program or GL termination.  
  
  
    3.11.4.3  Fragment Program Destination Register Update  
  
    Fragment program instructions write a 4-component result vector to a  
    single temporary or fragment result register.  Writes to individual   
    components of the destination register are controlled by individual   
    component write masks specified as part of the instruction.    
    Optional clamping of each component of the destination register to   
    the range [0,1] is controlled by an opcode modifier.  
  
    The component write mask is specified by the <optionalMask> rule   
    found in the <maskedDstReg> rule.  If the optional mask is "", all   
    components are enabled.  Otherwise, the optional mask names the   
    individual components to enable.  The characters "x", "y", "z", and   
    "w", or "r", "g", "b", and "a" match the first, second, third, and   
    fourth components, respectively.  For example, an optional mask of   
    ".xzw" indicates that the x, z, and w components should be enabled   
    for writing but the y component should not.  The grammar requires   
    that the destination register mask components must be listed in   
    "xyzw", or "rgba" order.  Component names from one set (xyzw or   
    rgba) cannot be mixed with component names from another set.  For   
    example, ".rgw" is not a valid writemask.  
  
    Each component of the destination register is updated with the   
    result of the fragment program instruction if and only if the   
    component is enabled for writes by the component write mask.    
    Otherwise, the component of the destination register remains   
    unchanged.  
  
    If the instruction opcode has the "_SAT" suffix, requesting   
    saturated result vectors, each component of the result vector   
    enabled in the writemask is clamped to the range [0,1] before being   
    updated in the destination register.  
  
    The following pseudocode illustrates the process of writing a result  
    vector to the destination register.  In the pseudocode, "instrmask"   
    refers to the component write mask given by the <optionalMask> rule.    
    "clamp" is TRUE if the instruction specifies that the result should  
    be clamped.  "result" and "destination" refer to the result vector   
    and the register selected by <dstReg>, respectively.  
  
      void UpdateDestination(floatVec destination, floatVec result)  
      {  
          floatVec merged;  
  
          // Clamp the result vector components to [0,1], if requested.  
          if (instrClamp) {  
              if (result.x < 0)      result.x = 0;  
              else if (result.x > 1) result.x = 1;  
              if (result.y < 0)      result.y = 0;  
              else if (result.y > 1) result.y = 1;  
              if (result.z < 0)      result.z = 0;  
              else if (result.z > 1) result.z = 1;  
              if (result.w < 0)      result.w = 0;  
              else if (result.w > 1) result.w = 1;  
          }  
  
          // Merge the converted result into the destination register,  
          // under control of the compile-time write mask.  
          merged = destination;  
          if (instrMask.x) {  
              merged.x = result.x;  
          }  
          if (instrMask.y) {  
              merged.y = result.y;  
          }  
          if (instrMask.z) {  
              merged.z = result.z;  
          }  
          if (instrMask.w) {  
              merged.w = result.w;  
          }  
  
          // Write out the new destination register.  
          destination = merged;  
      }  
  
  
    3.11.4.4  Fragment Program Result Processing  
  
    As a fragment program executes, it will write to either one or two   
    result registers that are mapped to the fragment's color and depth.  
  
    The fragment's color components are clamped to the range [0,1], and  
    the color is passed to the antialiasing application stage.  If the   
    color is not written by the fragment program, the color will be   
    undefined in subsequent stages.  
  
    If the fragment program contains an instruction to write to  
    result.depth, the fragment's depth is replaced by the value of the  
    "z" component of result.depth, clamped to the range [0,1].    
    Otherwise, the fragment's original depth is unmodified.  
  
  
    3.11.4.5  Fragment Program Options  
  
    The <optionSequence> grammar rule provides a mechanism for programs   
    to indicate that one or more extended language features are used by   
    the program.  All program options used by the program must be   
    declared at the beginning of the program string.  Each program   
    option specified in a program string will modify the syntactic or   
    semantic rules used to interpet the program and the execution   
    environment used to execute the program.  Program options not   
    present in the program string are ignored, even if they are   
    supported by the GL.  
  
    The <identifier> token in the <option> rule must match the name of a  
    program option supported by the implementation.  To avoid option   
    name conflicts, option identifiers are required to begin with a   
    vendor prefix.  A program will fail to load if it specifies a   
    program option not supported by the GL.  
  
    Fragment program options should confine their semantic changes to   
    the domain of fragment programs.  Support for a fragment program   
    option should not change the specification and behavior of fragment   
    programs not requesting use of that option.  
  
  
    3.11.4.5.1  Fog Application Fragment Program Options  
  
    If a fragment program specifies one of the options "ARB_fog_exp",   
    "ARB_fog_exp2", or "ARB_fog_linear", the program will apply fog to   
    the program's final clamped color using a fog mode of EXP, EXP2, or   
    LINEAR, respectively, as described in section 3.10.  
  
    When a fog option is specified in a fragment program, semantic   
    restrictions are added to indicate that a fragment program   
    will fail to load if the number of temporaries it contains exceeds   
    the implementation-dependent limit minus 1, if the number of   
    attributes it contains exceeds the implementation-dependent limit  
    minus 1, or if the number of parameters it contains exceeds the   
    implementation-dependent limit minus 2.  
  
    Additionally, when the ARB_fog_exp option is specified in a fragment  
    program, a semantic restriction is added to indicate that a fragment  
    program will fail to load if the number of instructions or ALU   
    instructions it contains exceeds the implementation-dependent limit   
    minus 3.  When the ARB_fog_exp2 option is specified in a fragment  
    program, a semantic restriction is added to indicate that a fragment  
    program will fail to load if the number of instructions or ALU   
    instructions it contains exceeds the implementation-dependent limit   
    minus 4.  When the ARB_fog_linear option is specified in a fragment  
    program, a semantic restriction is added to indicate that a fragment  
    program will fail to load if the number of instructions or ALU   
    instructions it contains exceeds the implementation-dependent limit   
    minus 2.  
  
    Only one fog application option may be specified by any given   
    fragment program.  A fragment program that specifies more than one   
    of the program options "ARB_fog_exp", "ARB_fog_exp2", and   
    "ARB_fog_linear", will fail to load.  
  
  
    3.11.4.5.2  Precision Hint Options  
  
    Fragment program computations are carried out at an implementation-  
    dependent precision.  However, some implementations may be able to  
    perform fragment program computations at more than one precision,   
    and may be able to trade off computation precision for performance.    
  
    If a fragment program specifies the "ARB_precision_hint_fastest"   
    program option, implementations should select precision to minimize   
    program execution time, with possibly reduced precision.  If a   
    fragment program specifies the "ARB_precision_hint_nicest" program   
    option, implementations should maximize the precision, with possibly   
    increased execution time.  
  
    Only one precision control option may be specified by any given   
    fragment program.  A fragment program that specifies both the  
    "ARB_precision_hint_fastest" and "ARB_precision_hint_nicest" program  
    options will fail to load.  
  
  
    3.11.5  Fragment Program ALU Instruction Set  
  
    The following sections describe the set of supported fragment   
    program instructions.  Each section contains pseudocode describing  
    the instruction.  Instructions will have up to three operands,  
    referred to as "op0", "op1", and "op2".  The operands are loaded   
    using the mechanisms specified in section 3.11.4.1.  The variables   
    "tmp", "tmp0", "tmp1", and "tmp2" describe scalars or vectors used   
    to hold intermediate results in the instruction.  Instructions will   
    generate a result vector called "result".  The result vector is then   
    written to the destination register specified in the instruction as   
    described in section 3.11.4.3.  
      
  
    3.11.5.1  ABS:  Absolute Value  
  
    The ABS instruction performs a component-wise absolute value   
    operation on the single operand to yield a result vector.  
  
      tmp = VectorLoad(op0);   
      result.x = fabs(tmp.x);  
      result.y = fabs(tmp.y);  
      result.z = fabs(tmp.z);  
      result.w = fabs(tmp.w);  
  
  
    3.11.5.2  ADD:  Add  
  
    The ADD instruction performs a component-wise add of the two   
    operands to yield a result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = tmp0.x + tmp1.x;  
      result.y = tmp0.y + tmp1.y;  
      result.z = tmp0.z + tmp1.z;  
      result.w = tmp0.w + tmp1.w;  
  
    The following rules apply to addition:  
  
      1. <x> + <y> == <y> + <x>, for all <x> and <y>.  
      2. <x> + 0.0 == <x>, for all <x>.  
  
  
    3.11.5.3  CMP: Compare  
  
    The CMP instructions performs a component-wise comparison of the   
    first operand against zero, and copies the values of the second or  
    third operands based on the results of the compare.  
      
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      tmp2 = VectorLoad(op2);  
      result.x = (tmp0.x < 0.0) ? tmp1.x : tmp2.x;  
      result.y = (tmp0.y < 0.0) ? tmp1.y : tmp2.y;  
      result.z = (tmp0.z < 0.0) ? tmp1.z : tmp2.z;  
      result.w = (tmp0.w < 0.0) ? tmp1.w : tmp2.w;  
   
     
    3.11.5.4  COS:  Cosine  
  
    The COS instruction approximates the trigonometric cosine of the   
    angle specified by the scalar operand and replicates it to all four   
    components of the result vector.  The angle is specified in radians  
    and does not have to be in the range [-PI,PI].  
  
      tmp = ScalarLoad(op0);  
      result.x = ApproxCosine(tmp);  
      result.y = ApproxCosine(tmp);  
      result.z = ApproxCosine(tmp);  
      result.w = ApproxCosine(tmp);  
  
  
    3.11.5.5  DP3:  Three-Component Dot Product  
  
    The DP3 instruction computes a three-component dot product of the   
    two operands (using the first three components) and replicates the   
    dot product to all four components of the result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) + (tmp0.z * tmp1.z);  
      result.x = dot;  
      result.y = dot;  
      result.z = dot;  
      result.w = dot;  
  
  
    3.11.5.6  DP4:  Four-Component Dot Product  
  
    The DP4 instruction computes a four-component dot product of the two  
    operands and replicates the dot product to all four components of   
    the result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1):  
      dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) +   
            (tmp0.z * tmp1.z) + (tmp0.w * tmp1.w);  
      result.x = dot;  
      result.y = dot;  
      result.z = dot;  
      result.w = dot;  
  
  
    3.11.5.7  DPH:  Homogeneous Dot Product  
  
    The DPH instruction computes a three-component dot product of the   
    two operands (using the x, y, and z components), adds the w   
    component of the second operand, and replicates the sum to all four   
    components of the result vector.  This is equivalent to a four-  
    component dot product where the w component of the first operand is   
    forced to 1.0.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1):  
      dot = (tmp0.x * tmp1.x) + (tmp0.y * tmp1.y) +   
            (tmp0.z * tmp1.z) + tmp1.w;  
      result.x = dot;  
      result.y = dot;  
      result.z = dot;  
      result.w = dot;  
  
  
    3.11.5.8  DST:  Distance Vector  
  
    The DST instruction computes a distance vector from two specially-  
    formatted operands.  The first operand should be of the form [NA,   
    d^2, d^2, NA] and the second operand should be of the form [NA, 1/d,   
    NA, 1/d], where NA values are not relevant to the calculation and d   
    is a vector length.  If both vectors satisfy these conditions, the   
    result vector will be of the form [1.0, d, d^2, 1/d].  
  
    The exact behavior is specified in the following pseudo-code:  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = 1.0;  
      result.y = tmp0.y * tmp1.y;  
      result.z = tmp0.z;  
      result.w = tmp1.w;  
  
    Given an arbitrary vector, d^2 can be obtained using the DP3   
    instruction (using the same vector for both operands) and 1/d can be   
    obtained from d^2 using the RSQ instruction.  
  
    This distance vector is useful for per-fragment light attenuation  
    calculations:  a DP3 operation using the distance vector and an  
    attenuation constants vector as operands will yield the attenuation  
    factor.  
  
  
    3.11.5.9  EX2:  Exponential Base 2  
  
    The EX2 instruction approximates 2 raised to the power of the scalar  
    operand and replicates the approximation to all four components of   
    the result vector.  
  
      tmp = ScalarLoad(op0);  
      result.x = Approx2ToX(tmp);  
      result.y = Approx2ToX(tmp);  
      result.z = Approx2ToX(tmp);  
      result.w = Approx2ToX(tmp);  
  
  
    3.11.5.10  FLR:  Floor  
  
    The FLR instruction performs a component-wise floor operation on the  
    operand to generate a result vector.  The floor of a value is   
    defined as the largest integer less than or equal to the value.  The   
    floor of 2.3 is 2.0; the floor of -3.6 is -4.0.  
  
      tmp = VectorLoad(op0);  
      result.x = floor(tmp.x);  
      result.y = floor(tmp.y);  
      result.z = floor(tmp.z);  
      result.w = floor(tmp.w);  
  
  
    3.11.5.11  FRC:  Fraction  
  
    The FRC instruction extracts the fractional portion of each   
    component of the operand to generate a result vector.  The   
    fractional portion of a component is defined as the result after   
    subtracting off the floor of the component (see FLR), and is always   
    in the range [0.0, 1.0).  
  
    For negative values, the fractional portion is NOT the number   
    written to the right of the decimal point -- the fractional portion   
    of -1.7 is not 0.7 -- it is 0.3.  0.3 is produced by subtracting the   
    floor of -1.7 (-2.0) from -1.7.  
  
      tmp = VectorLoad(op0);  
      result.x = fraction(tmp.x);  
      result.y = fraction(tmp.y);  
      result.z = fraction(tmp.z);  
      result.w = fraction(tmp.w);  
  
  
    3.11.5.12  LG2:  Logarithm Base 2  
  
    The LG2 instruction approximates the base 2 logarithm of the scalar  
    operand and replicates it to all four components of the result   
    vector.  
  
      tmp = ScalarLoad(op0);  
      result.x = ApproxLog2(tmp);  
      result.y = ApproxLog2(tmp);  
      result.z = ApproxLog2(tmp);  
      result.w = ApproxLog2(tmp);  
  
    If the scalar operand is zero or negative, the result is undefined.  
  
  
    3.11.5.13  LIT:  Light Coefficients  
  
    The LIT instruction accelerates per-fragment lighting by computing   
    lighting coefficients for ambient, diffuse, and specular light   
    contributions.  The "x" component of the single operand is assumed   
    to hold a diffuse dot product (n dot VP_pli, as in the vertex   
    lighting equations in Section 2.13.1).  The "y" component of the   
    operand is assumed to hold a specular dot product (n dot h_i).  The   
    "w" component of the operand is assumed to hold the specular   
    exponent of the material (s_rm), and is clamped to the range (-128,   
    +128) exclusive.  
  
    The "x" component of the result vector receives the value that   
    should be multiplied by the ambient light/material product (always   
    1.0).  The "y" component of the result vector receives the value   
    that should be multiplied by the diffuse light/material product   
    (n dot VP_pli).  The "z" component of the result vector receives the   
    value that should be multiplied by the specular light/material   
    product (f_i * (n dot h_i) ^ s_rm).  The "w" component of the result   
    is the constant 1.0.  
  
    Negative diffuse and specular dot products are clamped to 0.0, as is   
    done in the standard per-vertex lighting operations.  In addition,   
    if the diffuse dot product is zero or negative, the specular   
    coefficient is forced to zero.  
  
      tmp = VectorLoad(op0);  
      if (tmp.x < 0) tmp.x = 0;  
      if (tmp.y < 0) tmp.y = 0;  
      if (tmp.w < -(128.0-epsilon)) tmp.w = -(128.0-epsilon);  
      else if (tmp.w > 128-epsilon) tmp.w = 128-epsilon;  
      result.x = 1.0;  
      result.y = tmp.x;  
      result.z = (tmp.x > 0) ? RoughApproxPower(tmp.y, tmp.w) : 0.0;  
      result.w = 1.0;  
  
    The exponentiation approximation function may be defined in terms of   
    the base 2 exponentiation and logarithm approximation operations in   
    the EX2 and LG2 instructions, where  
  
      ApproxPower(a,b) = ApproxExp2(b * ApproxLog2(a)).  
  
    In particular, the approximation may not be any more accurate than   
    the underlying EX2 and LG2 operations.  
  
    Also, since 0^0 is defined to be 1, RoughApproxPower(0.0, 0.0) will  
    produce 1.0.  
  
  
    3.11.5.14  LRP: Linear Interpolation  
  
    The LRP instruction performs a component-wise linear interpolation   
    between the second and third operands using the first operand as the  
    blend factor.  
      
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      tmp2 = VectorLoad(op2);  
      result.x = tmp0.x * tmp1.x + (1 - tmp0.x) * tmp2.x;  
      result.y = tmp0.y * tmp1.y + (1 - tmp0.y) * tmp2.y;  
      result.z = tmp0.z * tmp1.z + (1 - tmp0.z) * tmp2.z;  
      result.w = tmp0.w * tmp1.w + (1 - tmp0.w) * tmp2.w;  
  
  
    3.11.5.15  MAD:  Multiply and Add  
  
    The MAD instruction performs a component-wise multiply of the first two  
    operands, and then does a component-wise add of the product to the   
    third operand to yield a result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      tmp2 = VectorLoad(op2);  
      result.x = tmp0.x * tmp1.x + tmp2.x;  
      result.y = tmp0.y * tmp1.y + tmp2.y;  
      result.z = tmp0.z * tmp1.z + tmp2.z;  
      result.w = tmp0.w * tmp1.w + tmp2.w;  
  
    The multiplication and addition operations in this instruction are   
    subject to the same rules as described for the MUL and ADD   
    instructions.  
  
  
    3.11.5.16  MAX:  Maximum  
  
    The MAX instruction computes component-wise maximums of the values   
    in the two operands to yield a result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = (tmp0.x > tmp1.x) ? tmp0.x : tmp1.x;  
      result.y = (tmp0.y > tmp1.y) ? tmp0.y : tmp1.y;  
      result.z = (tmp0.z > tmp1.z) ? tmp0.z : tmp1.z;  
      result.w = (tmp0.w > tmp1.w) ? tmp0.w : tmp1.w;  
  
  
    3.11.5.17  MIN:  Minimum  
  
    The MIN instruction computes component-wise minimums of the values   
    in the two operands to yield a result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = (tmp0.x > tmp1.x) ? tmp1.x : tmp0.x;  
      result.y = (tmp0.y > tmp1.y) ? tmp1.y : tmp0.y;  
      result.z = (tmp0.z > tmp1.z) ? tmp1.z : tmp0.z;  
      result.w = (tmp0.w > tmp1.w) ? tmp1.w : tmp0.w;  
  
  
    3.11.5.18  MOV:  Move  
  
    The MOV instruction copies the value of the operand to yield a   
    result vector.  
  
      result = VectorLoad(op0);  
  
  
    3.11.5.19  MUL:  Multiply  
  
    The MUL instruction performs a component-wise multiply of the two   
    operands to yield a result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = tmp0.x * tmp1.x;  
      result.y = tmp0.y * tmp1.y;  
      result.z = tmp0.z * tmp1.z;  
      result.w = tmp0.w * tmp1.w;  
  
    The following rules apply to multiplication:  
  
      1. <x> * <y> == <y> * <x>, for all <x> and <y>.  
      2. +/-0.0 * <x> = +/-0.0, at least for all <x> that correspond to  
         representable numbers (IEEE "not a number" and "infinity"   
         encodings may be exceptions).  
      3. +1.0 * <x> = <x>, for all <x>.  
  
    Multiplication by zero and one should be invariant, as it may be   
    used to evaluate conditional expressions without branching.  
  
  
    3.11.5.20  POW:  Exponentiate  
  
    The POW instruction approximates the value of the first scalar   
    operand raised to the power of the second scalar operand and   
    replicates it to all four components of the result vector.  
  
      tmp0 = ScalarLoad(op0);  
      tmp1 = ScalarLoad(op1);  
      result.x = ApproxPower(tmp0, tmp1);  
      result.y = ApproxPower(tmp0, tmp1);  
      result.z = ApproxPower(tmp0, tmp1);  
      result.w = ApproxPower(tmp0, tmp1);  
  
    The exponentiation approximation function may be implemented using   
    the base 2 exponentiation and logarithm approximation operations in   
    the EX2 and LG2 instructions.  In particular,  
  
      ApproxPower(a,b) = ApproxExp2(b * ApproxLog2(a)).  
  
    Note that a logarithm may be involved even for cases where the   
    exponent is an integer.  This means that it may not be possible to   
    exponentiate correctly with a negative base.  In constrast, it is   
    possible in a "normal" mathematical formulation to raise negative   
    numbers to integral powers (e.g., (-3)^2== 9, and (-0.5)^-2==4).  
  
  
    3.11.5.21  RCP:  Reciprocal  
  
    The RCP instruction approximates the reciprocal of the scalar   
    operand and replicates it to all four components of the result   
    vector.  
  
      tmp = ScalarLoad(op0);  
      result.x = ApproxReciprocal(tmp);  
      result.y = ApproxReciprocal(tmp);  
      result.z = ApproxReciprocal(tmp);  
      result.w = ApproxReciprocal(tmp);  
  
    The following rule applies to reciprocation:  
  
      1. ApproxReciprocal(+1.0) = +1.0.  
  
  
    3.11.5.22  RSQ:  Reciprocal Square Root  
  
    The RSQ instruction approximates the reciprocal of the square root   
    of the absolute value of the scalar operand and replicates it to all   
    four components of the result vector.  
  
      tmp = fabs(ScalarLoad(op0));  
      result.x = ApproxRSQRT(tmp);  
      result.y = ApproxRSQRT(tmp);  
      result.z = ApproxRSQRT(tmp);  
      result.w = ApproxRSQRT(tmp);  
  
  
    3.11.5.23  SCS:  Sine/Cosine  
  
    The SCS instruction approximates the trigonometric sine and cosine  
    of the angle specified by the scalar operand and places the cosine   
    in the x component and the sine in the y component of the result   
    vector.  The z and w components of the result vector are undefined.  
    The angle is specified in radians and must be in the range [-PI,PI].  
  
      tmp = ScalarLoad(op0);  
      result.x = ApproxCosine(tmp);  
      result.y = ApproxSine(tmp);  
  
    If the scalar operand is not in the range [-PI,PI], the result  
    vector is undefined.  
  
  
    3.11.5.24  SGE:  Set On Greater or Equal Than  
  
    The SGE instruction performs a component-wise comparison of the two  
    operands.  Each component of the result vector is 1.0 if the   
    corresponding component of the first operands is greater than or   
    equal that of the second, and 0.0 otherwise.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = (tmp0.x >= tmp1.x) ? 1.0 : 0.0;  
      result.y = (tmp0.y >= tmp1.y) ? 1.0 : 0.0;  
      result.z = (tmp0.z >= tmp1.z) ? 1.0 : 0.0;  
      result.w = (tmp0.w >= tmp1.w) ? 1.0 : 0.0;  
  
  
    3.11.5.25  SIN:  Sine  
  
    The SIN instruction approximates the trigonometric sine of the angle  
    specified by the scalar operand and replicates it to all four   
    components of the result vector.  The angle is specified in radians  
    and does not have to be in the range [-PI,PI].  
  
      tmp = ScalarLoad(op0);  
      result.x = ApproxSine(tmp);  
      result.y = ApproxSine(tmp);  
      result.z = ApproxSine(tmp);  
      result.w = ApproxSine(tmp);  
  
  
    3.11.5.26  SLT:  Set On Less Than  
  
    The SLT instruction performs a component-wise comparison of the two  
    operands.  Each component of the result vector is 1.0 if the   
    corresponding component of the first operand is less than that of   
    the second, and 0.0 otherwise.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = (tmp0.x < tmp1.x) ? 1.0 : 0.0;  
      result.y = (tmp0.y < tmp1.y) ? 1.0 : 0.0;  
      result.z = (tmp0.z < tmp1.z) ? 1.0 : 0.0;  
      result.w = (tmp0.w < tmp1.w) ? 1.0 : 0.0;  
  
  
    3.11.5.27  SUB:  Subtract  
  
    The SUB instruction performs a component-wise subtraction of the   
    second operand from the first to yield a result vector.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = tmp0.x - tmp1.x;  
      result.y = tmp0.y - tmp1.y;  
      result.z = tmp0.z - tmp1.z;  
      result.w = tmp0.w - tmp1.w;  
  
  
    3.11.5.28  SWZ:  Extended Swizzle  
  
    The SWZ instruction loads the single vector operand, and performs a  
    swizzle operation more powerful than that provided for loading   
    normal vector operands to yield an instruction vector.  
  
    After the operand is loaded, the "x", "y", "z", and "w" components   
    of the result vector are selected by the first, second, third, and   
    fourth matches of the <xyzwExtSwizComp> or <rgbaExtSwizComp> pattern   
    in the <extendedSwizzle> rule.  
  
    A result component can be selected from any of the four components   
    of the operand or the constants 0.0 and 1.0.  The result component   
    can also be optionally negated.  The following pseudocode describes   
    the component selection method.  "operand" refers to the vector   
    operand.  "select" is an enumerant where the values ZERO, ONE, X, Y,  
    Z, and W correspond to the <xyzwExtSwizSel> rule matching "0", "1", "x",   
    "y", "z", and "w", respectively, or the <rgbaExtSwizSel> rule  
    matching "0", 1", "r", "g", "b", and "a", respectively.  "negate" is   
    TRUE if and only if the <optionalSign> rule in <xyzwExtSwizComp>   
    or <rgbaExtSwizComp> matches "-".  
  
      float ExtSwizComponent(floatVec operand, enum select, boolean negate)  
      {  
          float result;  
          switch (select) {  
            case ZERO:  result = 0.0; break;  
            case ONE:   result = 1.0; break;  
            case X:     result = operand.x; break;  
            case Y:     result = operand.y; break;  
            case Z:     result = operand.z; break;  
            case W:     result = operand.w; break;  
          }  
          if (negate) {  
            result = -result;  
          }  
          return result;  
      }  
  
    The entire extended swizzle operation is then defined using the   
    following pseudocode:  
  
      tmp = VectorLoad(op0);  
      result.x = ExtSwizComponent(tmp, xSelect, xNegate);  
      result.y = ExtSwizComponent(tmp, ySelect, yNegate);  
      result.z = ExtSwizComponent(tmp, zSelect, zNegate);  
      result.w = ExtSwizComponent(tmp, wSelect, wNegate);  
  
    "xSelect", "xNegate", "ySelect", "yNegate", "zSelect", "zNegate",  
    "wSelect", and "wNegate" correspond to the "select" and "negate"   
    values above for the four <xyzwExtSwizComp> or <rgbaExtSwizComp>  
    matches.    
  
    Since this instruction allows for component selection and negation   
    for each individual component, the grammar does not allow the use of   
    the normal swizzle and negation operations allowed for vector   
    operands in other instructions.  
  
  
    3.11.5.29  XPD:  Cross Product  
  
    The XPD instruction computes the cross product using the first three  
    components of its two vector operands to generate the x, y, and z  
    components of the result vector.  The w component of the result   
    vector is undefined.  
  
      tmp0 = VectorLoad(op0);  
      tmp1 = VectorLoad(op1);  
      result.x = tmp0.y * tmp1.z - tmp0.z * tmp1.y;  
      result.y = tmp0.z * tmp1.x - tmp0.x * tmp1.z;  
      result.z = tmp0.x * tmp1.y - tmp0.y * tmp1.x;  
  
  
    3.11.6  Fragment Program Texture Instruction Set  
  
    The first three texture instructions described below specify the   
    mapping of 4-tuple vectors to colors of an image.  The sampling of   
    the texture works as described in section 3.8, except that texture   
    environments and texture functions are not applicable, and the  
    texture enables hierarchy is replaced by explicit references to  
    the desired texture target (i.e., 1D, 2D, 3D, cube map, rectangle).    
    These texture instructions specify how the 4-tuple is mapped into   
    the coordinates used for sampling.  The following function is used   
    to describe the texture sampling in the descriptions below:  
  
      vec4 TextureSample(float s, float t, float r, float lodBias,  
                         int texImageUnit, enum texTarget);  
  
    Note that not all three texture coordinates, s, t, and r, are  
    used by all texture targets.  In particular, 1D texture targets only  
    use the s component, and 2D and rectangle (non-power-of-two) texture  
    targets only use the s and t components.  The descriptions of the  
    texture instructions below supply all three components, as would be  
    the case with 3D or cube map targets.  
  
    If a fragment program samples from a texture target on a texture  
    image unit where the bound texture object is not complete, as   
    defined in section 3.8.9, the result will be the vector   
    (R, G, B, A) = (0, 0, 0, 1).  
  
    A fragment program will fail to load if it attempts to sample from  
    multiple texture targets on the same texture image unit.  For   
    example, the following program would fail to load:  
  
      !!ARBfp1.0  
      TEX result.color, fragment.texcoord[0], texture[0], 2D;  
      TEX result.depth, fragment.texcoord[1], texture[0], 3D;  
      END  
  
    The fourth texture instruction described below, KIL, does not sample  
    from a texture, but rather prevents further processing of the   
    current fragment if any component of its 4-tuple vector is less than  
    or equal to zero.  
  
    A dependent texture instruction is one that samples using a texture  
    coordinate residing in a temporary, rather than in an attribute or  
    a parameter.  A program may have a chain of dependent texture  
    instructions, where the result of the first texture instruction is   
    used as the coordinate for a second texture instruction, which is in   
    turn used as the coordinate for a third texture instruction, and so   
    on.  Each node in this chain is termed an indirection, and can be   
    thought of as a set of texture samples that execute in parallel  
    followed by a sequence of ALU instructions.  
  
    Some implementations may have limitations on how long the dependency   
    chain may be, and so indirections are counted as a resource just  
    like instructions or temporaries are counted.  All programs have at   
    least one indirection, or one node in this chain, even if the   
    program performs no texture operation.  Each instruction encountered  
    is included in this node until a texture instruction is encountered  
  
      - whose texture coordinate is a temporary that has been previously   
        written in the current node; or  
  
      - whose result vector is a temporary that is also the operand or   
        result vector of a previous ALU instruction in the current node.  
  
    A new node is then started, including the texture instruction and   
    all subsequent instructions, and the process repeats for all   
    instructions in the program.  Note that for simplicity in counting,   
    result writemasks and operand suffixes are not taken into   
    consideration when counting indirections.  
  
  
    3.11.6.1  TEX: Map coordinate to color  
  
    The TEX instruction takes the first three components of   
    its source vector, and maps them to s, t, and r.  These coordinates   
    are used to sample from the specified texture target on the   
    specified texture image unit in a manner consistent with its   
    parameters.  The resulting sample is mapped to RGBA as described in   
    table 3.21 and written to the result vector.  
  
      tmp = VectorLoad(op0);  
      result = TextureSample(tmp.x, tmp.y, tmp.z, 0.0, op1, op2);  
     
  
    3.11.6.2  TXP: Project coordinate and map to color  
  
    The TXP instruction divides the first three components of its source   
    vector by the fourth component and maps the results to s, t, and r.    
    These coordinates are used to sample from the specified texture  
    target on the specified texture image unit in a manner consistent   
    with its parameters.  The resulting sample is mapped to RGBA as   
    described in table 3.21 and written to the result vector.  If the   
    value of the fourth component of the source vector is less than or   
    equal to zero, the result vector is undefined.  
  
      tmp = VectorLoad(op0);  
      tmp.x = tmp.x / tmp.w;  
      tmp.y = tmp.y / tmp.w;  
      tmp.z = tmp.z / tmp.w;  
      result = TextureSample(tmp.x, tmp.y, tmp.z, 0.0, op1, op2);  
  
  
    3.11.6.3  TXB: Map coordinate to color while biasing its LOD  
  
    The TXB instruction takes the first three components of its source   
    vector and maps them to s, t, and r.  These coordinates are used to   
    sample from the specified texture target on the specified texture  
    image unit in a manner consistent with its parameters.    
    Additionally, the fourth component of the source vector is applied   
    to equation 3.14 as fragment_bias below to further bias the level of   
    detail.  
      
     lambda'(x,y) = log2[p(x,y)] +   
                    clamp(texobj_bias + texunit_bias + fragment_bias)  
      
    The resulting sample is mapped to RGBA as described in table 3.21   
    and written to the result vector.  
  
      tmp = VectorLoad(op0);  
      result = TextureSample(tmp.x, tmp.y, tmp.z, tmp.w, op1, op2);  
  
  
    3.11.6.4  KIL: Kill fragment  
  
    Rather than mapping a coordinate set to a color, this function  
    prevents a fragment from receiving any future processing.  If any  
    component of its source vector is negative, the processing of this   
    fragment will be discontinued and no further outputs to this   
    fragment will occur.  Subsequent stages of the GL pipeline will be   
    skipped for this fragment.  
  
      tmp = VectorLoad(op0);  
      if ((tmp.x < 0) || (tmp.y < 0) ||   
          (tmp.z < 0) || (tmp.w < 0))  
      {  
          exit;  
      }  
  
  
    3.11.7  Program Matrices  
  
    In addition to GL's conventional matrices, several additional   
    program matrices are available for use as program parameters.  These   
    matrices have names of the form MATRIX<i>_ARB where <i> is between   
    zero and <n>-1 where <n> is the value of the implementation-  
    dependent constant MAX_PROGRAM_MATRICES_ARB.  The MATRIX<i>_ARB   
    constants obey MATRIX<i>_ARB = MATRIX0_ARB + <i>.  The value of   
    MAX_PROGRAM_MATRICES_ARB must be at least eight.  The maximum stack   
    depth for program matrices is defined by the   
    MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB and must be at least 1.  
  
  
    3.11.8  Required Fragment Program State   
  
    The state required to support program objects of all targets   
    consists of:  
  
      an integer for the program error position, initially -1;  
  
      an array of ubytes for the program error string, initially empty;  
  
      and the state that must be maintained to indicate which integers   
      are currently in use as program object names.  
  
    The state required to support the fragment program target consists   
    of:  
  
      a bit indicating whether or not fragment program mode is enabled,   
      initially disabled;  
  
      a set of MAX_PROGRAM_ENV_PARAMETERS_ARB four-component floating-  
      point program environment parameters, initially set to (0,0,0,0);  
  
      an unsigned integer naming the currently bound fragment program,   
      initially zero;  
  
    The state required for each fragment program object consists of:  
  
      an unsigned integer indicating the program object name;  
  
      an array of type ubyte containing the program string, initially   
      empty;  
  
      an unsigned integer holding the length of the program string,   
      initially zero;  
  
      an enum indicating the program string format, initially  
      PROGRAM_FORMAT_ASCII_ARB;  
  
      a bit indicating whether or not the program exceeds the native   
      limits;  
  
      six unsigned integers holding the number of instruction (ALU,  
      texture, and total), texture indirection, temporary variable, and   
      program parameter binding resources used by the program, initially   
      all zero;  
  
      six unsigned integers holding the number of native instruction   
      (ALU, texture, and total), texture indirection, temporary   
      variable, and program parameter binding resources used by the   
      program, initially all zero;  
  
      and a set of MAX_PROGRAM_LOCAL_PARAMETERS_ARB four-component   
      floating-point program local parameters, initially set to   
      (0,0,0,0).  
  
    Initially, no fragment program objects exist.  
  
  
homeprevnext Additions to Chapter 4 of the OpenGL 1.3 Specification (Per-Fragment Operations and the Frame Buffer)
  
    None  
  
  
homeprevnext Additions to Chapter 5 of the OpenGL 1.3 Specification (Special Functions)
  
    Modify Section 5.4, Display Lists (p. 191)  
  
    (modify third paragraph, p. 195) ... These are IsList, GenLists,   
    ..., IsProgramARB, GenProgramsARB, and DeleteProgramsARB, as well as   
    IsEnabled and all the Get commands (chapter 6).  
  
  
homeprevnext Additions to Chapter 6 of the OpenGL 1.3 Specification (State and State Requests)
  
    Modify Section 6.1.2, Data Conversions (p. 198)  
  
    (add before last paragraph, p. 198) The matrix selected by the   
    current matrix mode can be queried by calling GetBooleanv,   
    GetIntegerv, GetFloatv, and GetDoublev with <pname> set to   
    CURRENT_MATRIX_ARB; the matrix will be returned in transposed form   
    with <pname> set to TRANSPOSE_CURRENT_MATRIX_ARB.  The depth of the   
    selected matrix stack can be queried with <pname> set to   
    CURRENT_MATRIX_STACK_DEPTH_ARB.  Querying CURRENT_MATRIX_ARB and   
    CURRENT_MATRIX_STACK_DEPTH_ARB is the only means for querying the   
    matrix and matrix stack depth of the program matrices described in   
    section 3.11.7.  
  
  
    (add to end of last paragraph, p. 199) Queries of texture state  
    variables corresponding to texture coordinate processing unit  
    (namely, TexGen state and enables, and matrices) will produce an  
    INVALID_OPERATION error if the value of ACTIVE_TEXTURE is greater   
    than or equal to MAX_TEXTURE_COORDS_ARB.  All other texture state   
    queries will result in an INVALID_OPERATION error if the value of   
    ACTIVE_TEXTURE is greater than or equal to   
    MAX_TEXTURE_IMAGE_UNITS_ARB.  
  
  
    Modify Section 6.1.11, Pointer and String Queries (p. 206)  
  
    (modify last paragraph, p. 206) ... The possible values for <name>   
    are VENDOR, RENDERER, VERSION, EXTENSIONS, and   
    PROGRAM_ERROR_STRING_ARB.  
  
  
    (add after last paragraph of section, p. 207) Queries of  
    PROGRAM_ERROR_STRING_ARB return a pointer to an implementation-  
    dependent program load error string.  If the last call to   
    ProgramStringARB failed to load a program, the returned string   
    describes at least one reason why the program failed to load.  If   
    the last call to ProgramStringARB successfully loaded a program, the   
    returned string may be empty (containing only a zero terminator) or   
    may contain one or more implementation-dependent warning messages.    
    The contents of the error string are guaranteed to remain constant   
    only until the next ProgramStringARB command, which may overwrite   
    the error string.  
  
  
    Insert a new Section 6.1.12, Program Queries (p. 207), between   
    existing sections 6.1.11 and 6.1.12.  
  
    6.1.12  Program Queries  
  
    The commands  
  
      void GetProgramEnvParameterdvARB(enum target, uint index,  
                                       double *params);  
      void GetProgramEnvParameterfvARB(enum target, uint index,  
                                       float *params);  
  
    obtain the current value for the program environment parameter   
    numbered <index> for the given program target <target>, and places   
    the information in the array <params>.  The error INVALID_ENUM is   
    generated if <target> specifies a nonexistent program target or a   
    program target that does not support program environment parameters.    
    The error INVALID_VALUE is generated if <index> is greater than or   
    equal to the implementation-dependent number of supported program   
    environment parameters for the program target.  
  
    When <target> is FRAGMENT_PROGRAM_ARB, each program parameter   
    returned is an array of four values.  
  
    The commands  
  
      void GetProgramLocalParameterdvARB(enum target, uint index,  
                                         double *params);  
      void GetProgramLocalParameterfvARB(enum target, uint index,  
                                         float *params);  
  
    obtain the current value for the program local parameter numbered   
    <index> belonging to the program object currently bound to <target>,   
    and places the information in the array <params>.  The error   
    INVALID_ENUM is generated if <target> specifies a nonexistent   
    program target or a program target that does not support program   
    local parameters.  The error INVALID_VALUE is generated if <index>   
    is greater than or equal to the implementation-dependent number of   
    supported program local parameters for the program target.  
  
    When the program target type is FRAGMENT_PROGRAM_ARB, each program  
    local parameter returned is an array of four values.  
  
    The command  
  
      void GetProgramivARB(enum target, enum pname, int *params);  
  
    obtains program state for the program target <target>, writing the   
    state into the array given by <params>.  GetProgramivARB can be used   
    to determine the properties of the currently bound program object or  
    implementation limits for <target>.  
  
    If <pname> is PROGRAM_LENGTH_ARB, PROGRAM_FORMAT_ARB, or  
    PROGRAM_BINDING_ARB, GetProgramivARB returns one integer holding the  
    program string length (in bytes), program string format, and program   
    name, respectively, for the program object currently bound to   
    <target>.  
  
    If <pname> is MAX_PROGRAM_LOCAL_PARAMETERS_ARB or  
    MAX_PROGRAM_ENV_PARAMETERS_ARB, GetProgramivARB returns one integer  
    holding the maximum number of program local parameters or program  
    environment parameters, respectively, supported for the program   
    target <target>.  
  
    If <pname> is MAX_PROGRAM_INSTRUCTIONS_ARB,   
    MAX_PROGRAM_ALU_INSTRUCTIONS_ARB, MAX_PROGRAM_TEX_INSTRUCTIONS_ARB,  
    MAX_PROGRAM_TEX_INDIRECTIONS_ARB, MAX_PROGRAM_TEMPORARIES_ARB,  
    MAX_PROGRAM_PARAMETERS_ARB, or MAX_PROGRAM_ATTRIBS_ARB,   
    GetProgramivARB returns a single integer giving the maximum number   
    of total instructions, ALU instructions, texture instructions,   
    texture indirections, temporaries, parameters, and attributes that   
    can be used by a program of type <target>.  If <pname> is   
    PROGRAM_INSTRUCTIONS_ARB, PROGRAM_ALU_INSTRUCTIONS_ARB,   
    PROGRAM_TEX_INSTRUCTIONS_ARB, PROGRAM_TEX_INDIRECTIONS_ARB,  
    PROGRAM_TEMPORARIES_ARB, PROGRAM_PARAMETERS_ARB, or  
    PROGRAM_ATTRIBS_ARB, GetProgramivARB returns a single integer giving   
    the number of total instructions, ALU instructions, texture   
    instructions, texture indirections, temporaries, parameters, and  
    attributes used by the current program for <target>.      
  
    If <pname> is MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB,   
    MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,   
    MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,   
    MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,   
    MAX_PROGRAM_NATIVE_TEMPORARIES_ARB,   
    MAX_PROGRAM_NATIVE_PARAMETERS_ARB, or   
    MAX_PROGRAM_NATIVE_ATTRIBS_ARB, GetProgramivARB returns a single   
    integer giving the maximum number of native instruction, ALU   
    instruction, texture instruction, texture indirection, temporary,   
    parameter, and attribute resources available to a program of type   
    <target>.  If <pname> is PROGRAM_NATIVE_INSTRUCTIONS_ARB,   
    PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB,   
    PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB,   
    PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB,   
    PROGRAM_NATIVE_TEMPORARIES_ARB, PROGRAM_NATIVE_PARAMETERS_ARB, or  
    PROGRAM_NATIVE_ATTRIBS_ARB, GetProgramivARB returns a single integer   
    giving the number of native instruction, ALU instruction, texture   
    instruction, texture indirection, temporary, parameter, and  
    attribute resources consumed by the program currently bound to   
    <target>.  Native resource counts will reflect the results of   
    implementation-dependent scheduling and optimization algorithms   
    applied by the GL, as well as emulation of non-native features.  If   
    <pname> is PROGRAM_UNDER_NATIVE_LIMITS_ARB, GetProgramivARB returns   
    0 if the native resource consumption of the program currently bound   
    to <target> exceeds the number of available resources for any   
    resource type, and 1 otherwise.  
  
    The command  
  
      void GetProgramStringARB(enum target, enum pname, void *string);  
  
    obtains the program string for the program object bound to <target>   
    and places the information in the array <string>.  <pname> must be  
    PROGRAM_STRING_ARB.  <n> ubytes are returned into the array program   
    where <n> is the length of the program in ubytes, as returned by   
    GetProgramivARB when <pname> is PROGRAM_LENGTH_ARB.  The program   
    string is always returned using the format given when the program   
    string was specified.  
  
    The command  
  
      boolean IsProgramARB(uint program);  
  
    returns TRUE if <program> is the name of a program object.  If   
    <program> is zero or is a non-zero value that is not the name of a   
    program object, or if an error condition occurs, IsProgramARB   
    returns FALSE.  A name returned by GenProgramsARB, but not yet   
    bound, is not the name of a program object.  
  
  
homeprevnext Additions to Appendix A of the OpenGL 1.3 Specification (Invariance)
  
    Add to end of Section A.3 (p. 242):  
  
      Rule 4.  Fragment program instructions not relevant to the   
      calculation of any result must have no effect on that result.  
  
      Rule 5.  Fragment program instructions relevant to the calculation   
      of any result must always produce the identical result.  
  
    Instructions relevant to the calculation of a result are any   
    instructions in a sequence of instructions that eventually determine   
    the source values for the calculation under consideration.  
  
    There is no guaranteed invariance between fragment colors generated   
    by conventional GL texturing mode and fragment colors generated by   
    fragment program mode.  Multi-pass rendering algorithms that require   
    rendering invariances to operate correctly should not mix   
    conventional GL fragment texturing mode with fragment program mode   
    for different rendering passes.  However, such algorithms will   
    operate correctly if the algorithms limit themselves to a single   
    mode of fragment color generation.  
  
    There is no guaranteed invariance between the final z window  
    coordinates of fragments processed by fragment programs that write  
    depth values and fragments processed by any other means, even if the  
    fragment programs in question simply copy the z value from the  
    "fragment.position" binding.  Multi-pass rendering algorithms that  
    use depth-replacing fragment programs should use depth-replacing  
    fragment programs on each pass to guarantee identical z values.  
  
    The texture sample chosen for a fragment of a primitive must be  
    invariant between fragment program mode and conventional texture  
    application mode subject to these conditions:  
  
      1. All state with the exception of fragment program state is  
         identical  
  
      2. The primitives generating the fragments are identical  
  
      3. The sample in the fragment program mode is the result of a  
         'TEX' instruction (or a 'TXP' instruction with a unity q)  
  
      4. The texture coordinate operand for the texture instruction uses   
         the same texture coordinate set as the conventional mode sample  
  
      5. The texture coordinate operand for the texture instruction has   
         not been the result of any other operations in the fragment   
         program  
  
  
homeprevnext Additions to the AGL/GLX/WGL Specifications
  
    Program objects are shared between AGL/GLX/WGL rendering contexts if  
    and only if the rendering contexts share display lists.  No change  
    is made to the AGL/GLX/WGL API.  
  
    Changes to program objects shared between multiple rendering   
    contexts will be serialized (i.e., the changes will occur in a   
    specific order).    
  
    Changes to a program object made by one rendering context are not  
    guaranteed to take effect in another rendering context until the   
    other calls BindProgram to bind the program object.    
  
    When a program object is deleted by one rendering context, the   
    object itself is not destroyed until it is no longer the current   
    program object in any context.  However, the name of the deleted   
    object is removed from the program object name space, so the next   
    attempt to bind a program using the same name will create a new   
    program object.  Recall that destroying a program object bound in   
    the current rendering context effectively unbinds the object being   
    destroyed.  
  
  
homeprevnext Dependencies on OpenGL 1.4
  
    If OpenGL 1.4 is not supported, the modified equation for the   
    calculation of level of detail by the TXB instruction in 3.11.6.3   
    should read  
  
      lambda'(x,y) = log2[p(x,y)] +   
                     clamp(texunit_bias + fragment_bias)  
  
homeprevnext Dependencies on EXT_vertex_weighting and ARB_vertex_blend
  
    If EXT_vertex_weighting and ARB_vertex_blend are both not supported,  
    all discussions of multiple modelview matrices should be removed.    
  
    In particular, the line in the grammar  
  
      <stateMatrixName>      ::= "modelview" <stateOptModMatNum>  
  
    should be changed to  
  
      <stateMatrixName>      ::= "modelview"  
  
    and the rules <stateOptModMatNum> and <stateModMatNum> should be   
    deleted.  The first line of Table X.2.7 should be modified to read:  
  
      Binding                               Underlying State  
      ------------------------------------  ---------------------------  
        state.matrix.modelview              modelview matrix  
  
    The caption for Table X.2.7 should be modified to exclude optional  
    modelview matrix number.  Subsequent references to "modelview matrix   
    zero" and "modelview matrix 1" should be changed to "modelview   
    matrix" and the example "state.matrix.modelview[1].row[0]" should be   
    changed to "state.matrix.modelview.row[0]".  
  
  
homeprevnext Dependencies on ARB_matrix_palette:
  
    If ARB_matrix_palette is not supported, all discussions of the   
    matrix palette should be removed.  
  
    In particular, the line  
  
      "palette" "[" <statePaletteMatNum> "]"  
  
    should be removed from the <stateMatrixName> grammar rule, and the  
    <statePaletteMatNum> grammar rule should be removed entirely.  
    "state.matrix.palette[n]" should be removed from Table X.2.7.  
  
  
homeprevnext Dependencies on ARB_transpose_matrix
  
    If ARB_transpose_matrix is not supported, the discussion of  
    TRANSPOSE_CURRENT_MATRIX_ARB in the edits to section 6.1.2 should be  
    removed.  
  
  
homeprevnext Dependencies on EXT_fog_coord
  
    If EXT_fog_coord is not supported, references to "fog coordinate"  
    in the definition of the "fragment.fogcoord" attribute should be   
    removed.  
  
homeprevnext Dependencies on EXT_texture_rectangle
  
    If NV_texture_rectangle is not supported, the discussion of the  
    rectangle (non-power-of-two) texture target in section 3.11.6 should  
    be removed, and the line  
  
      "RECT"  
  
    should be removed from the <texTarget> grammar rule.  
  
  
homeprevnext Interactions with ARB_shadow
  
    The texture comparison introduced by ARB_shadow can be expressed in   
    terms of a fragment program, and in fact use the same internal   
    resources on some implementations.  Therefore, if fragment program   
    mode is enabled, the GL behaves as if TEXTURE_COMPARE_MODE_ARB is   
    NONE.  
  
  
homeprevnext Interactions with ARB_vertex_program
  
    The program object management entrypoints described in sections  
    2.14.1 (for vertex programs) and 3.11.1 (for fragment programs)  
    are shared by both program targets.  The PROGRAM_ERROR_STRING_ARB  
    and program queries in sections 6.1.11 and 6.1.12 are also shared,  
    as are all common tokens.  
  
    In the presence of ARB_vertex_program, ARB_fragment_program must   
    recognize and return appropriate values for the GetProgram <pname>   
    tokens introduced in that spec but not otherwise shared by   
    ARB_fragment_program:  
  
        PROGRAM_ADDRESS_REGISTERS_ARB                   0x88B0  
        MAX_PROGRAM_ADDRESS_REGISTERS_ARB               0x88B1  
        PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB            0x88B2  
        MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB        0x88B3  
  
    The following tables list new program object state and   
    implementation-dependent state:  
  
    Get Value                        Type   Get Command          Initial Value    Description             Sec       Attrib  
    --------------------             -----  -------------------  ---------------  ----------------------  --------  ------  
    PROGRAM_ADDRESS_REGISTERS_ARB    Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                  address registers  
    PROGRAM_NATIVE_ADDRESS_          Z+     GetProgramivARB      0                bound program native    6.1.12    -  
        REGISTERS_ARB                                                             address registers  
  
    Table X.7.  Program Object State.  Program object queries return attributes of  
    the program object currently bound to the program target <target>.  
  
  
                                                                Minimum  
    Get Value                            Type  Get Command      Value    Description             Sec.       Attrib  
    ---------                            ----  -----------      -------  -----------             ----       ------  
    MAX_PROGRAM_ADDRESS_REGISTERS_ARB    Z+    GetProgramivARB  0        maximum program         6.1.12     -  
                                                                         address registers  
    MAX_PROGRAM_NATIVE_ADDRESS_          Z+    GetProgramivARB  0        maximum program native  6.1.12     -  
        REGISTERS_ARB                                                    address registers  
  
    Table X.10.  New Implementation-Dependent Values Introduced by  
    ARB_vertex_program.  
  
  
    In the presence of ARB_fragment_program, ARB_vertex_program must  
    recognize and return appropriate values for the GetProgram <pname>   
    tokens introduced in this spec.  The following tables list new   
    program object state and implementation-dependent state:  
  
    Get Value                            Type   Get Command          Initial Value    Description             Sec       Attrib  
    --------------------                 -----  -------------------  ---------------  ----------------------  --------  ------  
    PROGRAM_ALU_INSTRUCTIONS_ARB         Z+     GetProgramivARB      0                maximum program         6.1.12    -  
                                                                                      ALU instructions  
    PROGRAM_TEX_INSTRUCTIONS_ARB         Z+     GetProgramivARB      0                maximum program         6.1.12    -  
                                                                                      texture instructions  
    PROGRAM_TEX_INDIRECTIONS_ARB         Z+     GetProgramivARB      0                maximum program         6.1.12    -  
                                                                                      texture indirections  
    PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB  Z+     GetProgramivARB      0                maximum program native  6.1.12    -  
                                                                                      ALU instructions  
    PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB  Z+     GetProgramivARB      0                maximum program native  6.1.12    -  
                                                                                      texture instructions  
    PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB  Z+     GetProgramivARB      0                maximum program native  6.1.12    -  
                                                                                      texture indirections  
  
    Table X.7.  Program Object State.  Program object queries return attributes of  
    the program object currently bound to the program target <target>.  
  
  
                                                                    Minimum  
    Get Value                                Type  Get Command      Value    Description             Sec.       Attrib  
    ---------                                ----  -----------      -------  -----------             ----       ------  
    MAX_PROGRAM_ALU_INSTRUCTIONS_ARB         Z+    GetProgramivARB  0        Number of frag. prg.    6.1.12     -  
                                                                             ALU instructions  
    MAX_PROGRAM_TEX_INSTRUCTIONS_ARB         Z+    GetProgramivARB  0        Number of frag. prg.    6.1.12     -  
                                                                             texture instructions  
    MAX_PROGRAM_TEX_INDIRECTIONS_ARB         Z+    GetProgramivARB  0        Number of frag. prg.    6.1.12     -  
                                                                             texture indirections         
    MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB  Z+    GetProgramivARB  0        maximum program native  6.1.12     -  
                                                                             ALU instructions  
    MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB  Z+    GetProgramivARB  0        maximum program native  6.1.12     -  
                                                                             texture instructions  
    MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB  Z+    GetProgramivARB  0        maximum program native  6.1.12     -  
                                                                             texture indirections  
  
    Table X.10.  New Implementation-Dependent Values Introduced by  
    ARB_fragment_program.  
  
  
homeprevnext Interactions with ATI_fragment_shader
  
    The existing ATI_fragment_shader extension, if supported, also  
    provides a similar fragment programming model.  Mixing the two  
    models in a single application is possible but not recommended.  
    FRAGMENT_PROGRAM_ARB has priority over FRAGMENT_SHADER_ATI if  
    both are enabled.  
  
  
homeprevnext Interactions with NV_fragment_program
  
    The NV_fragment_program extension, if supported, also provides a   
    similar programming model.  This extension is incompatible with  
    NV_fragment_program in a number of different ways.  Mixing the two   
    models in a single application is possible but not recommended.  The   
    interactions between the extensions are defined below.  
  
    Functions, enumerants, and programs defined in NV_fragment_program   
    are called "NV functions", "NV enumerants", and "NV programs,"   
    respectively.  Functions, enumerants, and programs defined in   
    ARB_fragment_program are called "ARB functions", "ARB enumerants",   
    and "ARB programs," respectively.  
  
    The following GL state is identical in the two extensions:  
  
      - Fragment program mode enable.  The NV and ARB enumerants have  
        different values, but the same effect.  
  
      - Program error position.  
  
      - Program error string.  
  
      - NV_fragment_program and ARB_fragment_program "program local  
        parameters."  
  
      - Fragment program names, targets, formats, program string,   
        program string lengths, and residency information.  The ARB and   
        NV query functions operate differently.  The ARB query function   
        does not allow queries of target (passed in to the query) and   
        residency information.  The NV query function does not allow   
        queries of program name (passed in to the query) or format.  The   
        format of NV programs is always PROGRAM_FORMAT_ASCII_ARB.  
  
      - Program object name space.  Program objects are created   
        differently in the NV and ARB specs.  Under the NV spec, program   
        objects are created by calling LoadProgramNV.  Under the ARB   
        spec, program objects are created by calling BindProgramARB with   
        an unused program name.  
  
    The following state is provided only by ARB_fragment_program:  
  
      - Program environment parameters.  
  
      - Implementation-dependent limits on the number of instructions,   
        ALU instructions, texture instructions, texture indirections,   
        program parameters, fragment attributes, resource counts, and   
        native resource counts.  The instruction limit is baked into the   
        NV spec.  Implementations supporting NV_fragment_program have no   
        specific restrictions on the number of ALU instructions, texture   
        instructions, texture indirections, or fragment attributes used.    
        Such implementations also have no limit on program parameters   
        used, except that no more than one may be used by any single   
        program instruction.  
  
    The following state is provided only by NV_fragment_program:  
  
      - Named program parameters (variables defined in the program text   
        and updated by name).  
  
    The following are additional functional differences between  
    ARB_fragment_program and NV_fragment_program:  
  
      - NV programs use a set of register names, with no support for  
        user-defined variables (other than parameters in the program).    
        ARB programs provide no support for fixed variable names; all   
        variables must be declared, explicitly or implicitly, in the   
        program.  
  
      - ARB programs support parameter variables that can be bound to   
        selected GL state variables, and are updated automatically when   
        the underlying state changes.  NV programs provide no such   
        support; applications must set program parameters themselves.  
  
      - ARB_fragment_program doesn't provide explicit support for   
        multiple data types (fx12, fp16, fp32) described in   
        NV_fragment_program, and provides no mechanism for controlling   
        the precision used to carry out arithmetic operations.  
  
      - ARB_fragment_program doesn't support condition codes,   
        conditional writemasks, or the "C" instruction suffix that   
        specifies a condition code update.  
  
      - ARB_fragment_program doesn't support an absolute value operator   
        that can be applied to a source vector as it is loaded.  
  
      - ARB_fragment_program doesn't define behavior for many floating-  
        point special cases.  On platforms where NV_fragment_program is   
        supported, ARB programs will have the same special-case   
        behavior.  
  
      - Language to declare program parameters is slightly different  
        (NV_fragment_program has "DECLARE" and "DEFINE";   
        ARB_fragment_program has "PARAM").  
  
      - NV_fragment_program provides a number of instructions not found   
        in ARB_fragment_program:  
  
          * DDX, DDY:  partial derivatives relative to x and  y.  
  
          * "PK*" and "UP*":  packing and unpacking instructions.  
  
          * RFL:  reflection vector.  
  
          * SEQ, SFL, SGT, SLE, SNE, STR:  set on equal, false, greater   
            than, less than or equal, not equal, and true, respectively.  
  
          * TXD:  texture lookup w/partials.  
  
          * X2D:  2D coordinate transformation.  
  
      - ARB_fragment_program provides several instructions not found in  
        NV_fragment_program, and there are a few instruction set   
        differences:  
  
          * ABS:  absolute value.  ABS instructions are unnecessary in   
              NV_fragment_program because of the free absolute value on   
              input operator.  Equivalent to:  
             
                 MOV dst, |src|;  
  
          * CMP:  compare.  Roughly equivalent to the following   
              sequence, but may be optimized further:  
  
                 SLT tmp, src0;   
                 LRP dst, tmp, src1, src2;  
  
          * DPH:  homogenous dot product.  Equivalent to:  
  
                 DP3 tmp, src0, src1;  
                 ADD dst, tmp, src0.w;  
  
          * KIL:  kill fragment.  Both extensions support this   
              instruction, but the ARB instruction takes a vector   
              operand rather than a condition code.  
  
          * SCS:  sine/cosine.  Emulated using the separate SIN and COS  
              instructions in NV_fragment_program, which also have no  
              restriction on the input values.  
  
          * SWZ:  extended swizzle.  On NV_fragment_program platforms,   
              this instruction will be emulated using a single MAD   
              instruction and a program parameter constant.  
  
          * TXB:  texture sample with bias.  Not exposed in the  
              NV_fragment_program API.  
  
          * XPD:  cross product.  Emulated using a MUL and a MAD   
              instruction.  
  
  
homeprevnext GLX Protocol
  
     The following rendering commands are sent to the server as part of  
     a glXRender request:  
  
        BindProgramARB  
            2           12              rendering command length  
            2           4180            rendering command opcode  
            4           ENUM            target  
            4           CARD32          program  
  
        ProgramEnvParameter4fvARB  
            2           32              rendering command length  
            2           4184            rendering command opcode  
            4           ENUM            target  
            4           CARD32          index  
            4           FLOAT32         params[0]  
            4           FLOAT32         params[1]  
            4           FLOAT32         params[2]  
            4           FLOAT32         params[3]  
  
        ProgramEnvParameter4dvARB  
            2           44              rendering command length  
            2           4185            rendering command opcode  
            4           ENUM            target  
            4           CARD32          index  
            8           FLOAT64         params[0]  
            8           FLOAT64         params[1]  
            8           FLOAT64         params[2]  
            8           FLOAT64         params[3]  
  
        ProgramLocalParameter4fvARB  
            2           32              rendering command length  
            2           4215            rendering command opcode  
            4           ENUM            target  
            4           CARD32          index  
            4           FLOAT32         params[0]  
            4           FLOAT32         params[1]  
            4           FLOAT32         params[2]  
            4           FLOAT32         params[3]  
  
        ProgramLocalParameter4dvARB  
            2           44              rendering command length  
            2           4216            rendering command opcode  
            4           ENUM            target  
            4           CARD32          index  
            8           FLOAT64         params[0]  
            8           FLOAT64         params[1]  
            8           FLOAT64         params[2]  
            8           FLOAT64         params[3]  
  
    The ProgramStringARB is potentially large, and hence can be sent in   
    a glXRender or glXRenderLarge request.  
  
        ProgramStringARB  
            2           16+len+p        rendering command length  
            2           4217            rendering command opcode  
            4           ENUM            target  
            4           ENUM            format  
            4           sizei           len  
            len         LISTofBYTE      program  
            p                           unused, p=pad(len)  
  
         If the command is encoded in a glxRenderLarge request, the   
         command opcode and command length fields above are expanded to   
         4 bytes each:  
  
            4           16+len+p        rendering command length  
            4           4217            rendering command opcode  
  
    The remaining commands are non-rendering commands.  These commands   
    are sent separately (i.e., not as part of a glXRender or   
    glXRenderLarge request), using the glXVendorPrivateWithReply   
    request:  
  
        DeleteProgramsARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           4+n             request length  
            4           1294            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           INT32           n  
            n*4         LISTofCARD32    programs  
  
        GenProgramsARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           4               request length  
            4           1295            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           INT32           n  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           n               reply length  
            24                          unused  
            n*4         LISTofCARD322   programs  
  
        GetProgramEnvParameterfvARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           6               request length  
            4           1296            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           ENUM            target  
            4           CARD32          index  
            4           ENUM            pname  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           m               reply length, m=(n==1?0:n)  
            4                           unused  
            4           CARD32          n (number of parameter components)  
  
            if (n=1) this follows:  
  
            4           FLOAT32         params  
            12                          unused  
  
            otherwise this follows:  
  
            16                          unused  
            n*4         LISTofFLOAT32   params  
  
        GetProgramEnvParameterdvARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           6               request length  
            4           1297            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           ENUM            target  
            4           CARD32          index  
            4           ENUM            pname  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           m               reply length, m=(n==1?0:n*2)  
            4                           unused  
            4           CARD32          n (number of parameter components)  
  
            if (n=1) this follows:  
  
            8           FLOAT64         params  
            8                           unused  
  
            otherwise this follows:  
  
            16                          unused  
            n*8         LISTofFLOAT64   params  
  
        GetProgramLocalParameterfvARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           6               request length  
            4           1305            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           ENUM            target  
            4           CARD32          index  
            4           ENUM            pname  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           m               reply length, m=(n==1?0:n)  
            4                           unused  
            4           CARD32          n (number of parameter components)  
  
            if (n=1) this follows:  
  
            4           FLOAT32         params  
            12                          unused  
  
            otherwise this follows:  
  
            16                          unused  
            n*4         LISTofFLOAT32   params  
  
        GetProgramLocalParameterdvARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           6               request length  
            4           1306            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           ENUM            target  
            4           CARD32          index  
            4           ENUM            pname  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           m               reply length, m=(n==1?0:n*2)  
            4                           unused  
            4           CARD32          n (number of parameter components)  
  
            if (n=1) this follows:  
  
            8           FLOAT64         params  
            8                           unused  
  
            otherwise this follows:  
  
            16                          unused  
            n*8         LISTofFLOAT64   params  
  
        GetProgramivARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           5               request length  
            4           1307            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           ENUM            target  
            4           ENUM            pname  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           m               reply length, m=(n==1?0:n)  
            4                           unused  
            4           CARD32          n  
  
            if (n=1) this follows:  
  
            4           INT32           params  
            12                          unused  
  
            otherwise this follows:  
  
            16                          unused  
            n*4         LISTofINT32     params  
  
        GetProgramStringARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           5               request length  
            4           1308            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           ENUM            target  
            4           ENUM            pname  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           (n+p)/4         reply length  
            4                           unused  
            4           CARD32          n  
            16                          unused  
            n           STRING          program  
            p                           unused, p=pad(n)  
  
        IsProgramARB  
            1           CARD8           opcode (X assigned)  
            1           17              GLX opcode (glXVendorPrivateWithReply)  
            2           4               request length  
            4           1304            vendor specific opcode  
            4           GLX_CONTEXT_TAG context tag  
            4           INT32           n  
          =>  
            1           1               reply  
            1                           unused  
            2           CARD16          sequence number  
            4           0               reply length  
            4           BOOL32          return value  
            20                          unused  
  
  
homeprevnext Errors
    
    The error INVALID_OPERATION is generated by ProgramStringARB if the  
    program string <string> is syntactically incorrect or violates any  
    semantic restriction of the execution environment of the specified   
    program target <target>.  The error INVALID_OPERATION may also be  
    generated by ProgramStringARB if the specified program would exceed   
    native resource limits of the implementation.  
  
    The error INVALID_OPERATION is generated by BindProgramARB if   
    <program> is the name of a program whose target does not match   
    <target>.  
  
    The error INVALID_VALUE is generated by any ProgramEnvParameter*ARB    
    or GetProgramEnvParameter*ARB command if <index> is greater than or   
    equal to the value of MAX_PROGRAM_ENV_PARAMETERS_ARB corresponding   
    to the program target <target>.  
  
    The error INVALID_VALUE is generated by any   
    ProgramLocalParameter*ARB or GetProgramLocalParameter*ARB command if   
    <index> is greater than or equal to the value of   
    MAX_PROGRAM_LOCAL_PARAMETERS_ARB corresponding to the program target   
    <target>.  
  
    The error INVALID_OPERATION is generated if Begin, RasterPos, or any  
    command that performs an explicit Begin is called when fragment   
    program mode is enabled and the currently bound fragment program   
    object does not contain a valid fragment program.  
  
    The error INVALID_OPERATION is generated by any command accessing  
    texture coordinate processing state if the texture unit number  
    corresponding to the current value of ACTIVE_TEXTURE is greater than  
    or equal to the implementation-dependent constant   
    MAX_TEXTURE_COORDS_ARB.  
  
    The error INVALID_OPERATION is generated by any command accessing  
    texture image processing state if the texture unit number   
    corresponding to the current value of ACTIVE_TEXTURE is greater than  
    or equal to the implementation-dependent constant   
    MAX_TEXTURE_IMAGE_UNITS_ARB.  
  
  
homeprevnext New State
  
  
    Get Value                        Type    Get Command    Initial Value Description         Section       Attribute  
    -------------------------------  ------  -------------  ------------- ------------------  ------------  ------------  
    FRAGMENT_PROGRAM_ARB             B       IsEnabled      False         fragment program    3.8           enable  
                                                                          enable  
    -                                24+xR4  GetProgramEnv- (0,0,0,0)     program environment 3.11.1        -  
                                             ParameterARB                 parameters  
    PROGRAM_ERROR_POSITION_ARB       Z       GetIntegerv    -1            last program error  3.11.1        -  
                                                                          position  
    PROGRAM_ERROR_STRING_ARB         0+xub   GetString      ""            last program error  3.11.1        -  
                                                                          string  
  
    Table X.6.  New Accessible State Introduced by ARB_fragment_program.  
  
  
    Get Value                            Type   Get Command          Initial Value    Description             Sec       Attrib  
    --------------------                 -----  -------------------  ---------------  ----------------------  --------  ------  
    PROGRAM_BINDING_ARB                  Z+     GetProgramivARB      object-specific  bound program name      6.1.12    -  
    PROGRAM_LENGTH_ARB                   Z+     GetProgramivARB      0                bound program length    6.1.12    -  
    PROGRAM_FORMAT_ARB                   Z1     GetProgramivARB      PROGRAM_FORMAT_  bound program format    6.1.12    -  
                                                                     ASCII_ARB  
    PROGRAM_STRING_ARB                   ubxn   GetProgramStringARB  (empty)          bound program string    6.1.12    -  
    PROGRAM_INSTRUCTIONS_ARB             Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      total instructions  
    PROGRAM_ALU_INSTRUCTIONS_ARB         Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      ALU instructions  
    PROGRAM_TEX_INSTRUCTIONS_ARB         Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      texture instructions  
    PROGRAM_TEX_INDIRECTIONS_ARB         Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      texture indirections  
    PROGRAM_TEMPORARIES_ARB              Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      temporaries  
    PROGRAM_PARAMETERS_ARB               Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      parameter bindings  
    PROGRAM_ATTRIBS_ARB                  Z+     GetProgramivARB      0                bound program           6.1.12    -  
                                                                                      attribute bindings  
    PROGRAM_NATIVE_INSTRUCTIONS_ARB      Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      instructions  
    PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB  Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      ALU instructions  
    PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB  Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      texture instructions  
    PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB  Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      texture indirections  
    PROGRAM_NATIVE_TEMPORARIES_ARB       Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      temporaries  
    PROGRAM_NATIVE_PARAMETERS_ARB        Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      parameter bindings  
    PROGRAM_NATIVE_ATTRIBS_ARB           Z+     GetProgramivARB      0                bound program native    6.1.12    -  
                                                                                      attribute bindings  
    PROGRAM_UNDER_NATIVE_LIMITS_ARB      B      GetProgramivARB      0                bound program under     6.1.12    -  
                                                                                      native resource limits  
    -                                    24+xR4 GetProgramLocal-     (0,0,0,0)        bound program local     3.11.1    -  
                                                ParameterARB                          parameter value  
  
    Table X.7.  Program Object State.  Program object queries return attributes of  
    the program object currently bound to the program target <target>.  
  
  
    Get Value    Type    Get Command   Initial Value  Description                Sec       Attribute  
    ---------    ------  -----------   -------------  -------------------------  --------  ---------  
    -            16+xR4  -             undefined      temporary registers        3.11.3.3  -  
    -            2xR4    -             undefined      fragment result registers  3.11.3.4  -  
  
    Table X.8.  Fragment Program Per-fragment Execution State.  All per-fragment  
    execution state registers are uninitialized at the beginning of program  
    execution.  
  
  
    Get Value                          Type      Get Command      Initial Value  Description          Sec      Attribute  
    ------------------------------     --------  --------------   -------------  -------------------  -------  ---------  
    CURRENT_MATRIX_ARB                 m*n*xM^4  GetFloatv        Identity       current matrix       6.1.2    -  
    CURRENT_MATRIX_STACK_DEPTH_ARB     m*Z+      GetIntegerv      1              current stack depth  6.1.2    -  
  
    Table X.9.  Current matrix state where m is the total number of matrices  
    including texture matrices and program matrices and n is the number of  
    matrices on each particular matrix stack.  Note that this state is aliased  
    with existing matrix state.  
  
  
homeprevnext New Implementation Dependent State
                                                                    Minimum  
    Get Value                                Type  Get Command      Value      Description             Sec.       Attrib  
    ---------                                ----  -----------      -------    -----------             ----       ------  
    MAX_TEXTURE_COORDS_ARB                   Z+    GetIntegerv      2          number of texture       2.7        -  
                                                                               coordinate sets  
    MAX_TEXTURE_IMAGE_UNITS_ARB              Z+    GetIntegerv      2          number of texture       2.10.2     -  
                                                                               image units  
    MAX_PROGRAM_ENV_PARAMETERS_ARB           Z+    GetProgramivARB  24         maximum program         3.11.1     -  
                                                                               env parameters  
    MAX_PROGRAM_LOCAL_PARAMETERS_ARB         Z+    GetProgramivARB  24         maximum program         3.11.1     -  
                                                                               local parameters  
    MAX_PROGRAM_MATRICES_ARB                 Z+    GetIntegerv      8 (not to  maximum number of       3.11.7     -  
                                                                    exceed 32) program matrices  
    MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB       Z+    GetIntegerv      1          maximum program         3.11.7     -  
                                                                               matrix stack depth  
    MAX_PROGRAM_INSTRUCTIONS_ARB             Z+    GetProgramivARB  72         maximum program         6.1.12     -  
                                                                               total instructions  
    MAX_PROGRAM_ALU_INSTRUCTIONS_ARB         Z+    GetProgramivARB  48         number of frag. prg.    6.1.12     -  
                                                                               ALU instructions  
    MAX_PROGRAM_TEX_INSTRUCTIONS_ARB         Z+    GetProgramivARB  24         number of frag. prg.    6.1.12     -  
                                                                               texture instructions  
    MAX_PROGRAM_TEX_INDIRECTIONS_ARB         Z+    GetProgramivARB  4          number of frag. prg.    6.1.12     -  
                                                                               texture indirections         
    MAX_PROGRAM_TEMPORARIES_ARB              Z+    GetProgramivARB  16         maximum program         6.1.12     -  
                                                                               temporaries  
    MAX_PROGRAM_PARAMETERS_ARB               Z+    GetProgramivARB  24         maximum program         6.1.12     -  
                                                                               parameter bindings  
    MAX_PROGRAM_ATTRIBS_ARB                  Z+    GetProgramivARB  10         maximum program         6.1.12     -  
                                                                               attribute bindings  
    MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB      Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               total instructions  
    MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB  Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               ALU instructions  
    MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB  Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               texture instructions  
    MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB  Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               texture indirections  
    MAX_PROGRAM_NATIVE_TEMPORARIES_ARB       Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               temporaries  
    MAX_PROGRAM_NATIVE_PARAMETERS_ARB        Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               parameter bindings  
    MAX_PROGRAM_NATIVE_ATTRIBS_ARB           Z+    GetProgramivARB  -          maximum program native  6.1.12     -  
                                                                               attribute bindings  
  
    Table X.10.  New Implementation-Dependent Values Introduced by  
    ARB_fragment_program.  Values queried by GetProgram require a <pname> of  
    FRAGMENT_PROGRAM_ARB.  
  
  
homeprevnext Sample Usage
  
    The following program shows how to perform a simple modulation   
    between the interpolated color and a single texture:  
  
      !!ARBfp1.0  
      # Simple program to show how to code up the default texture environment  
  
      ATTRIB tex = fragment.texcoord;      #first set of texture coordinates  
      ATTRIB col = fragment.color.primary; #diffuse interpolated color  
  
      OUTPUT outColor = result.color;  
  
      TEMP tmp;  
  
      TXP tmp, tex, texture, 2D;           #sample the texture  
      
      MUL outColor, tmp, col;              #perform the modulation  
      
      END   
  
    The following is an example the simulates a chrome surface:  
  
      !!ARBfp1.0  
  
      ########################  
      # Input Textures:  
      #-----------------------  
      # Texture 0 contains the default 2D texture used for general mapping  
      # Texture 2 contains a 1D pointlight falloff map  
      # Texture 3 contains a 2D map for calculating specular lighting  
      # Texture 4 contains normalizer cube map  
      #  
      # Input Texture Coordinates:  
      #-----------------------  
      # TexCoord1 contains the calculated normal  
      # TexCoord2 contains the light to vertex vector  
      # TexCoord3 contains the half-vector in tangent space  
      # TexCoord4 contains the light vector in tangent space  
      # TexCoord5 contains the eye vector in tangent space  
      ########################  
  
      TEMP     NdotH, lV, L;  
  
      ALIAS    diffuse  = L;  
      PARAM       half  = { 0.5, 0.5, 0.5, 0.5 };  
      ATTRIB   norm_tc  = fragment.texcoord[1];  
      ATTRIB     lv_tc  = fragment.texcoord[2];  
      ATTRIB   half_tc  = fragment.texcoord[3];  
      ATTRIB  light_tc  = fragment.texcoord[4];  
      ATTRIB    eye_tc  = fragment.texcoord[5];  
      OUTPUT      oCol  = result.color;  
  
      TEX     L, light_tc, texture[4], CUBE; # Sample cube map normalizer  
  
      # Calculate diffuse lighting (N.L)  
      SUB     L, L, half;              # Bias L and then multiply by 2  
      ADD     L, L, L;  
      DP3     diffuse, norm_tc, L;     # N.L  
  
      # Calculate specular lighting component { (N.H), |H|^2 }  
      DP3     NdotH.x, norm_tc, half_tc;  
      DP3     NdotH.y, half_tc, half_tc;  
  
      DP3     lV.x, lv_tc, lv_tc;     # lV = (|light to vertex|)^2  
  
  
      #############  
      # Pass 2  
      #############  
  
      TEMP     base, specular;  
      ALIAS    atten  = lV;  
  
      TEX      base,     eye_tc, texture[0], 2D; # sample enviroment map using eye vector  
      TEX      atten,    lV,     texture[2], 1D; # Sample attenuation map  
      TEX      specular, NdotH,  texture[3], 2D; # Sample specular NHHH map= (N.H)^256  
  
      # specular = (N.H)^256 * (N.L)   
      # this ensures a pixel is only lit if facing the light (since the specular  
      # exponent makes negative N.H positive we must do this)  
      MUL      specular, specular, diffuse;  
  
      # specular = specular * environment map  
      MUL      specular, base, specular;  
  
      # diffuse = diffuse * environment map  
      MUL      diffuse, base, diffuse;  
  
      # outColor = (specular * environment map) + (diffuse * environment map)  
      ADD      base, specular, diffuse;  
  
      # Apply point light attenutaion  
      MUL      oCol, base, atten.r;  
  
      END  
  
  
homeprevnext Revision History
  
   Date: 1/10/2003  
   Revision: 24  
      - Fixed bug where "state.matrix.mvp" was specified incorrectly.  
        It should be P*M0 rather than M0*P.  
      - Added issue warning about CMP opcode's order of operands.  
  
   Date: 10/22/2002  
   Revision: 23  
      - Fixed reference to <extSwizComp> rule in 3.11.5.28.  Instead  
        reference both <xyzwExtSwizComp> and <rgbaExtSwizComp> rules.  
  
   Date: 10/02/2002  
   Revision: 22  
      - Fixed typo in section 3.11.1, where 8 program environment and  
        8 program local parameters are listed as the minimums instead  
        of 24 of each.  Table X.10 had the correct values.  
      - Fixed <stateTexEnvItem> to refer to legacy texture units.  
      - Fixed typos in issue 29 pseudo-code, added some clarification.  
  
   Date: 9/19/2002  
   Revision: 21  
      - Added clarifying paragraph for native texture indirection   
        counting, offering examples of possible cases where texture  
        indirections may be increased.  
      - Fixed typos in issues 25 and 29.  
  
   Date: 9/16/2002  
   Revision: 20  
      - Added precision hint program options.  
      - Fixed various typos, reworded some parts for consistency.  
      - Updated issues list.  
  
   Date: 9/13/2002  
   Revision: 19  
      - Promoted minimum precision of texture coordinates in 2.1.1.  
      - Added ARB_fog_* program options.  
      - Removed modification to 3.9, put clamps in 3.11.4.4.  
      - Made 'texture' a reserved keyword in the grammar.  
      - Fixed various typos.  
      - Updated section 3.11.6.  
      - Updated issues list.  
  
   Date: 9/11/2002  
   Revision: 18  
      - Updated for consistency with ARB_vertex_program revision 36.  
      - Depth output moved to 3rd component of result.depth.  
      - Fixed various typos, reworded things in many places.  
      - Added NV_fragment_program interactions.  
      - Updated issues list.  
  
   Date: 9/09/2002  
   Revision: 17  
      - Added fogcoord and position attributes.  
      - Moved fragment program section to 3.11, after fog.  
      - Changed MAX_TEXTURE_UNITS/MAX_AUX_TEXTURE_UNITS to   
        MAX_TEXTURE_COORDS/MAX_TEXTURE_IMAGE_UNITS.  
      - Removed TRC and MOD instructions.  
      - Added SIN and COS instructions.  
      - Added more clarity to resource consumption wording.  
      - Added invariance wording concerning depth-replacement.  
      - Added rule that a program that fails to load must always fail to  
        load, regardless of GL state.  
      - Updated issues list.  
  
   Date: 8/30/2002  
   Revision: 16  
      - Improved texture indirection description.  
      - Defined result of sample from incomplete texture as (0,0,0,1).  
      - Removed PROGRAMS_LOAD_OVER_NATIVE_LIMITS_ARB per-target query.  
      - Allowed ProgramStringARB to fail on non-native programs.  
      - Updated issues list.  
  
   Date: 8/28/2002  
   Revision: 15  
      - Updated for consistency with ARB_vertex_program revision 35.  
      - Added PROGRAMS_LOAD_OVER_NATIVE_LIMITS_ARB per-target query.  
      - Changed MAX_AUX_TEXTURE_UNITS_ARB enum value.  
      - Updated issues list.  
  
   Date: 8/22/2002  
   Revision: 14  
      - Added sine/cosine instruction (SCS).  
      - Updated texture sample grammar, replaced texenables hierarchy.  
      - Added EXT_vertex_weighting and ARB_vertex_blend dependency.  
      - Updated issues list.  
  
   Date: 8/14/2002  
   Revision: 13  
      - Fixed <paramConstant> grammar rule.  
      - Updated issues list.  
  
   Date: 8/06/2002  
   Revision: 12  
      - Fixed various typos.  
      - Updated issues list.  
      - Added wording to 3.10.3.6 to reflect that native resource  
        consumption may increase due to emulated instructions.  
  
   Date: 7/29/2002  
   Revision: 11  
      - Updated for consistency with ARB_vertex_program revision 34.  
      - Added support for matrix binding.  
      - Removed precision queries.  
      - Updated issues list.  
  
   Date: 7/16/2002  
   Revision: 10  
      - Updated for consistency with ARB_vertex_program revision 31.  
      - Added fog params and depth range bindings to grammar.  
      - Removed stpq writemasks and swizzles from grammar.  
      - Required swizzle components to come from same set, xyzw or rgba.  
  
   Date: 7/10/2002  
   Revision: 9  
      - Made fog params and depth range bindable.  
      - Changed texture instruction names to match 3-letter format.  
      - Made texture instructions more consistent with ALU instructions.  
      - Increased minimums for implementation-dependent values.  
      - Re-introduced 4-components swizzles and the SWZ instruction.  
      - Updated issues list.  
  
   Date: 7/03/2002  
   Revision: 8  
      - Fixed typos.  
      - Added DST, LIT, SGE, SLT instructions.  
      - Changed FRC definition to match ARB_vertex_program, added MOD  
        instruction to expose fmod(arg, 1.0) behavior.  
  
   Date: 6/25/2002  
   Revision: 7  
      - Updated for consistency with ARB_vertex_program revision 29.  
  
   Date: 6/19/2002  
   Revision: 6  
      - Updated for consistency with ARB_vertex_program revision 28.  
      - Changed from ATI to ARB prefix/suffix.  
      - Started using single integer revision number.  
      - Added a few more issues to the list.  
  
   Date: 6/14/2002  
   Revision: 1.4  
      - Updated for consistency with ARB_vertex_program revision 27.  
      - Added a few more issues to the list.  
  
   Date: 6/05/2002  
   Revision: 1.3  
      - Updated for consistency with ARB_vertex_program revision 26.  
      - Incorporated program object management, removing dependency on  
        ARB_vertex_program.  
      - Added interaction with ARB_shadow.  
  
   Date: 6/03/2002  
   Revision: 1.2  
      - Updated for consistency with ARB_vertex_program revision 25.  
      - Fixed TexInstructions to use <texSrcReg>, i.e. no parameters.  
      - Added TRC, POW, DPH instructions, updated FRC and LRP.  
      - Added fog color parameter binding.  
  
   Date: 5/23/2002  
   Revision: 1.1  
      - Updated for consistency with ARB_vertex_program revision 24.  
      - Added GetProgramfvATI entrypoint for querying precision values.  
  
   Date: 5/10/2002  
   Revision: 1.0  
      - First draft for circulation.  
      - First draft for circulation.  
Valid XHTML 1.1! Valid CSS! Last update: November 14, 2006.
Cette page doit être lue avec un navigateur récent respectant le standard XHTML 1.1.