Name

    ATI_fragment_shader

Name Strings

    GL_ATI_fragment_shader

Contributors

    Dan Ginsburg
    Evan Hart
    Jason Mitchell
    
Contact

    Benj Lipchak, AMD (benj.lipchak 'at' amd.com)

Status

    Shipping (version 1.0)

Version

    Last Modified Date: November 4, 2006
    Author Revision: 1.8

Number

    245

Dependencies

    ARB_multitexture is required by this extension.
    ARB_shadow interacts with this extension.
    The extension is written against the OpenGL 1.2.1 Specification.

Overview

    This extension exposes a powerful fragment shading model which
    provides a very general means of expressing fragment color blending
    and dependent texture address modification.  The programming is
    a register-based model in which there is a fixed number of 
    instructions, texture lookups, read/write registers, and constants.

    The fragment shader extension provides a unified instruction set
    for operating on address or color data and eliminates the 
    distinction between the two.  This extension provides all the 
    interfaces necessary to fully expose this programmable fragment 
    shader in GL.

    Although conceived as a device-independent extension which would 
    expose the capabilities of future generations of hardware, changing 
    trends in programmable hardware have affected the lifespan of this 
    extension.  For this reason you will now find a fixed set of 
    features and resources exposed, and the queries to determine this 
    set have been deprecated.

Issues
    
    None


New Procedures and Functions

    uint GenFragmentShadersATI (uint range);

    void BindFragmentShaderATI (uint id);

    void DeleteFragmentShaderATI (uint id);

    void BeginFragmentShaderATI (void);

    void EndFragmentShaderATI (void);

    void PassTexCoordATI (uint dst, uint coord, enum swizzle);

    void SampleMapATI (uint dst, uint interp, enum swizzle);

    void ColorFragmentOp1ATI (enum op, uint dst, uint dstMask, 
                              uint dstMod, uint arg1, uint arg1Rep, 
                              uint arg1Mod);

    void ColorFragmentOp2ATI (enum op, uint dst, uint dstMask, 
                              uint dstMod, uint arg1, uint arg1Rep, 
                              uint arg1Mod, uint arg2, uint arg2Rep, 
                              uint arg2Mod);

    void ColorFragmentOp3ATI (enum op, uint dst, uint dstMask, 
                              uint dstMod, uint arg1, uint arg1Rep, 
                              uint arg1Mod, uint arg2, uint arg2Rep, 
                              uint arg2Mod, uint arg3, uint arg3Rep, 
                              uint arg3Mod);

    void AlphaFragmentOp1ATI (enum op, uint dst, uint dstMod, 
                              uint arg1, uint arg1Rep, uint arg1Mod);

    void AlphaFragmentOp2ATI (enum op, uint dst, uint dstMod, 
                              uint arg1, uint arg1Rep, uint arg1Mod, 
                              uint arg2, uint arg2Rep, uint arg2Mod);

    void AlphaFragmentOp3ATI (enum op, uint dst, uint dstMod, 
                              uint arg1, uint arg1Rep, uint arg1Mod,
                              uint arg2, uint arg2Rep, uint arg2Mod,
                              uint arg3, uint arg3Rep, uint arg3Mod);

    void SetFragmentShaderConstantATI (uint dst, const float *value);


New Tokens

    Accepted by the <cap> parameter of Enable, Disable, and IsEnabled,
    and by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv,
    and GetDoublev:

        FRAGMENT_SHADER_ATI                   0x8920
    
    Accepted by the <dst> and <argN> parameters of 
    ColorFragmentOp[1..3]ATI and AlphaFragmentOp[1..3]ATI, and by the 
    <dst> and <coord> parameters of PassTexCoordATI, and by the <dst> 
    and <interp> parameters of SampleMapATI:

        REG_0_ATI                             0x8921
        REG_1_ATI                             0x8922
        REG_2_ATI                             0x8923
        REG_3_ATI                             0x8924
        REG_4_ATI                             0x8925
        REG_5_ATI                             0x8926

    Accepted by the <dst> parameter of SetFragmentShaderConstantATI and 
    the <argN> parameter of ColorFragmentOp[1..3]ATI and 
    AlphaFragmentOp[1..3]ATI:

        CON_0_ATI                             0x8941
        CON_1_ATI                             0x8942
        CON_2_ATI                             0x8943
        CON_3_ATI                             0x8944
        CON_4_ATI                             0x8945
        CON_5_ATI                             0x8946
        CON_6_ATI                             0x8947
        CON_7_ATI                             0x8948
    
    Accepted by the <op> parameter of ColorFragmentOp1ATI and 
    AlphaFragmentOp1ATI:

        MOV_ATI                               0x8961

    Accepted by the <op> parameter of ColorFragmentOp2ATI and 
    AlphaFragmentOp2ATI:

        ADD_ATI                               0x8963
        MUL_ATI                               0x8964
        SUB_ATI                               0x8965
        DOT3_ATI                              0x8966
        DOT4_ATI                              0x8967

    Accepted by the <op> parameter of ColorFragmentOp3ATI and 
    AlphaFragmentOp3ATI:

        MAD_ATI                               0x8968
        LERP_ATI                              0x8969
        CND_ATI                               0x896A
        CND0_ATI                              0x896B
        DOT2_ADD_ATI                          0x896C

    Accepted by the <argN> parameter of ColorFragmentOp[1..3]ATI and 
    AlphaFragmentOp[1..3]ATI:

        ZERO
        ONE
        PRIMARY_COLOR_ARB
        SECONDARY_INTERPOLATOR_ATI            0x896D

    Accepted by the <interp> parameter of SampleMapATI and the <coord> 
    parameter of PassTexCoordATI:

        TEXTURE0_ARB
        TEXTURE1_ARB
        TEXTURE2_ARB
        TEXTURE3_ARB
        TEXTURE4_ARB
        TEXTURE5_ARB
        TEXTURE6_ARB
        TEXTURE7_ARB

    Accepted by the <swizzle> parameter of SampleMapATI and 
    PassTexCoordATI:

        SWIZZLE_STR_ATI                       0x8976
        SWIZZLE_STQ_ATI                       0x8977
        SWIZZLE_STR_DR_ATI                    0x8978
        SWIZZLE_STQ_DQ_ATI                    0x8979
    
    Accepted by the <dstMask> parameter of ColorFragmentOp[1..3]ATI:
    
        NONE
        RED_BIT_ATI                           0x00000001
        GREEN_BIT_ATI                         0x00000002
        BLUE_BIT_ATI                          0x00000004           

    Accepted by the <argNRep> parameter of ColorFragmentOp[1..3]ATI and 
    AlphaFragmentOp[1..3]ATI:

        NONE
        RED
        GREEN
        BLUE
        ALPHA

    Accepted by the <dstMod> parameter of ColorFragmentOp[1..3]ATI and
    AlphaFragmentOp[1..3]ATI:

        NONE
        2X_BIT_ATI                            0x00000001
        4X_BIT_ATI                            0x00000002
        8X_BIT_ATI                            0x00000004
        HALF_BIT_ATI                          0x00000008
        QUARTER_BIT_ATI                       0x00000010
        EIGHTH_BIT_ATI                        0x00000020
        SATURATE_BIT_ATI                      0x00000040
    

    Accepted by the <argNMod> parameter of ColorFragmentOp[1..3]ATI and 
    AlphaFragmentOp[1..3]ATI:

        2X_BIT_ATI                            0x00000001
        COMP_BIT_ATI                          0x00000002
        NEGATE_BIT_ATI                        0x00000004
        BIAS_BIT_ATI                          0x00000008    


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

    None


Additions to Chapter 3 of the OpenGL 1.2.1 Specification (Rasterization)

    Add New Subsection after 3.8.10, (p. 138)

    3.8.11  Fragment Shaders

    By default, the current texture environment is used to determine
    how textures are combined for rasterization.  However, by enabling
    FRAGMENT_SHADER_ATI, the currently bound fragment shader is used to 
    determine how textures are combined.  The fragment shader replaces 
    the traditional texture environment by exposing a fragment shading 
    model which provides a very general means of expressing fragment 
    color blending and dependent texture address modification.  The 
    distinction between texture address and color data becomes 
    irrelevant in the fragment shader as the two can be used 
    interchangeably.

    A shader is defined between a BeginFragmentShaderATI and 
    EndFragmentShaderATI block.  These commands are defined as follows:

      void BeginFragmentShaderATI(void);
      void EndFragmentShaderATI(void);

    Although there is no restriction as to which GL operations may be
    specified between BeginFragmentShaderATI and EndFragmentShaderATI,
    only the following operations will be compiled into a shader: 
    PassTexCoordATI, SampleMapATI, ColorFragmentOp[1..3]ATI, 
    AlphaFragmentOp[1..3]ATI, and SetFragmentShaderContantATI.
     
    In addition to a default fragment shader, named shaders can be 
    created.  The namespace for shaders is unsigned integers with zero 
    reserved by the GL.  A shader is created by binding an unused name 
    using:
      
      void BindFragmentShaderATI(uint id);

    where <id> is the unused name.  Once a shader has been created it
    can be rebound as the active shader by calling 
    BindFragmentShaderATI.  A shader can be deleted, freeing the name, 
    by calling:

      void DeleteFragmentShaderATI(uint id);

    where <id> is the name to be deleted.  Unique names can be generated
    using:

      uint GenFragmentShadersATI(uint range);

    where <range> is the number of contiguous ids that should be 
    created.  It returns an integer n such that <range> contiguous empty 
    shader ids, with values n, n+1, ..., n+<range>-1, are created.  If 
    <range> is 0, if there is no group of <range> contiguous names
    available, or if any error is generated, no shaders are generated,
    and 0 is returned.

    If FRAGMENT_SHADER_ATI is enabled, but the currently bound shader is
    invalid, the results of drawing commands are undefined.  A shader 
    may be invalid because it is currently being specified (i.e., a 
    drawing command within a Begin/EndFragmentShader pair), or due to 
    some error during the specification of a shader.

    There are three types of data that can be in a fragment shader:
    registers, constants, and interpolators.  The 6 REG_x_ATI registers 
    can be used as source or destination in any color or alpha 
    instruction.  The final result of the shader is whatever value is in 
    REG_0_ATI.  This value will be the final color of the output 
    fragment passed.

    There are 8 constant registers available, CON_0_ATI through 
    CON_7_ATI.  CON_x_ATI constants can be used as source in any color 
    or alpha instruction, but at most 2 different constants may be used 
    as source arguments in each instruction.

    Additionally, the primary and secondary color interpolators are 
    available as source in any color or alpha instruction, but only in 
    the last pass of the shader (i.e., the only pass of a one-pass 
    shader or the second pass of a two-pass shader).

    Either one or two passes may be specified in a shader.  Each pass 
    may use up to 8 pairs of instructions for a total of at most 16 
    pairs in the shader.  A pair consists of one color instruction and 
    one alpha instruction.

    The first instructions specified in each pass of a shader are "free" 
    instructions in that they don't count against the 8 instructions 
    available in each pass.  They are routing instructions which specify 
    from where the contents of the registers come.  The first occurance 
    of one of these free instructions marks the beginning of a pass in 
    the shader.  They are specified with SampleMapATI and 
    PassTexCoordATI.

    The entry point:

      void PassTexCoordATI (uint dst, uint coord, enum swizzle);

    specifies that the value present in <coord> is passed directly into 
    the contents of <dst> (one of the registers REG_x_ATI).  This value 
    is then available for use as a source argument to subsequent color 
    and alpha instructions following in the same pass.  <coord> may 
    either be the texture coordinates on a texture unit (TEXTUREx_ARB), 
    or in the case of a two-pass shader's second pass, it may be the 
    value of a register set in the first pass (REG_x_ATI).

    Note that in order to preserve the contents of a register from the 
    first pass to the second, there must be a PassTexCoordATI 
    instruction in the setup for the second pass that assigns that 
    register to itself.  For example: 

      PassTexCoordATI(REG_1_ATI, REG_1_ATI, SWIZZLE_STR_ATI); 

    will preserve the first 3 components of REG_1_ATI for use in the 
    second pass.

    The entry point:

      void SampleMapATI (uint dst, uint interp, enum swizzle);

    specifies that the value present in the texture data bound on the 
    unit associated with <dst> will be written to that register.  A 
    value for <dst> of REG_x_ATI means that TEXTUREx_ARB will be 
    sampled, and the result written to REG_x_ATI.  The <interp> 
    parameter specifies which texture coordinate interpolator is used to 
    sample the map.  A value of REG_x_ATI for <interp> in the second 
    pass of a two-pass shader will do dependent texture read sampling 
    using the value in register x.  Otherwise, specifying TEXTUREx_ARB 
    will sample the map using the texture coordinates on unit x.

    Only the first 3 components of <coord> or <interp> are used in 
    PassTexCoordATI and SampleMapATI, respectively.  The swizzle 
    parameter is used to select which of the 4 original components of 
    the source register or texture coordinates will be mapped to the 3 
    available positions, and whether or not a projection will occur.  

    Table 3.20 shows the <swizzle> modes:


                           Coordinates Used for 1D or      Coordinates Used for
      Swizzle              2D SampleMap and PassTexCoord   3D or cubemap SampleMap
      -------              -----------------------------   -----------------------
      SWIZZLE_STR_ATI      (s, t, r, undefined)            (s, t, r, undefined)
      SWIZZLE_STQ_ATI      (s, t, q, undefined)            (s, t, q, undefined)
      SWIZZLE_STR_DR_ATI   (s/r, t/r, 1/r, undefined)      (undefined)
      SWIZZLE_STQ_DQ_ATI   (s/q, t/q, 1/q, undefined)      (undefined)

         Table 3.20 Coordinate swizzles


    Each texture coordinate source (TEXTUREx_ARB) used as a <coord> 
    and/or <interp> can only draw upon STR or STQ components throughout 
    the shader.  For example, if TEXTURE2_ARB is used in a SampleMapATI 
    with <swizzle> SWIZZLE_STR_ATI, it cannot be used again later with a 
    <swizzle> of SWIZZLE_STQ_ATI.  The projection, however, may vary.  
    It would be okay to later use TEXTURE2_ARB with a <swizzle> of 
    SWIZZLE_STR_DR_ATI.

    Additionally, when the <coord> or <interp> is a register (in the 
    second pass of a two-pass shader), only SWIZZLE_STR_ATI and 
    SWIZZLE_STR_DR_ATI are allowed.  Note that if this is a 
    PassTexCoord, the fourth component (alpha channel if the register 
    contains RGBA) is not passed along and the fourth component of <dst> 
    becomes undefined.

    The color and alpha instructions performed in the shader are 
    specified with the following entry points:

      void ColorFragmentOp1ATI (enum op, uint dst, uint dstMask, uint dstMod, 
                                uint arg1, uint arg1Rep, uint arg1Mod);
      void ColorFragmentOp2ATI (enum op, uint dst, uint dstMask, uint dstMod, 
                                uint arg1, uint arg1Rep, uint arg1Mod,
                                uint arg2, uint arg2Rep, uint arg2Mod);
      void ColorFragmentOp3ATI (enum op, uint dst, uint dstMask, uint dstMod,
                                uint arg1, uint arg1Rep, uint arg1Mod,
                                uint arg2, uint arg2Rep, uint arg2Mod,
                                uint arg3, uint arg3Rep, uint arg3Mod);
      void AlphaFragmentOp1ATI (enum op, uint dst, uint dstMod, 
                                uint arg1, uint arg1Rep, uint arg1Mod);
      void AlphaFragmentOp2ATI (enum op, uint dst, uint dstMod, 
                                uint arg1, uint arg1Rep, uint arg1Mod, 
                                uint arg2, uint arg2Rep, uint arg2Mod);
      void AlphaFragmentOp3ATI (enum op, uint dst, uint dstMod, 
                                uint arg1, uint arg1Rep, uint arg1Mod,
                                uint arg2, uint arg2Rep, uint arg2Mod,
                                uint arg3, uint arg3Rep, uint arg3Mod);

    A ColorFragmentOp[1..3]ATI followed by an AlphaFragmentOp[1..3]ATI 
    is considered to be an instruction pair, and 8 such pairs may be
    specified per pass.  The color and alpha instructions of a pair are 
    executed in parallel: the result of the color instruction cannot 
    affect the source arguments of the alpha instruction.  Both a color 
    and an alpha instruction need not be specified for every pair; the
    necessary color or alpha no-op is automatically inserted by the GL
    to complete each instruction pair.

    The <op> parameter specifies the instruction to perform on the 
    sources.   

    Table 3.21 shows the effect of each <op>.  R(d), G(d), and B(d) are 
    the destination values when using the instruction on color and A(d) 
    is the destination value when using the instruction on alpha.


      Op                    Result
      --                    ------
      ADD_ATI               R(d) = R(a1) + R(a2)
                            G(d) = G(a1) + G(a2)
                            B(d) = B(a1) + B(a2)
                            A(d) = A(a1) + A(a2)

      SUB_ATI               R(d) = R(a1) - R(a2)
                            G(d) = G(a1) - G(a2)
                            B(d) = B(a1) - B(a2)
                            A(d) = A(a1) - A(a2)

      MUL_ATI               R(d) = R(a1) * R(a2)
                            G(d) = G(a1) * G(a2)
                            B(d) = B(a1) * B(a2)
                            A(d) = A(a1) * A(a2)

      MAD_ATI               R(d) = R(a1) * R(a2) + R(a3)
                            G(d) = G(a1) * G(a2) + G(a3)
                            B(d) = B(a1) * B(a2) + B(a3)
                            A(d) = A(a1) * A(a2) + A(a3)

      LERP_ATI***           R(d) = R(a1) * R(a2) + (1 - R(a1)) * R(a3)
                            G(d) = G(a1) * G(a2) + (1 - G(a1)) * G(a3)
                            B(d) = B(a1) * B(a2) + (1 - B(a1)) * B(a3)
                            A(d) = A(a1) * A(a2) + (1 - A(a1)) * A(a3)

      MOV_ATI               R(d) = R(a1)
                            G(d) = G(a1)
                            B(d) = B(a1)
                            A(d) = A(a1)

      CND_ATI               R(d) = (R(a3) > 0.5) ? R(a1) : R(a2)
                            G(d) = (G(a3) > 0.5) ? G(a1) : G(a2)
                            B(d) = (B(a3) > 0.5) ? B(a1) : B(a2)
                            A(d) = (A(a3) > 0.5) ? A(a1) : A(a2)

      CND0_ATI              R(d) = (R(a3) >= 0) ? R(a1) : R(a2)
                            G(d) = (G(a3) >= 0) ? G(a1) : G(a2)
                            B(d) = (B(a3) >= 0) ? B(a1) : B(a2)
                            A(d) = (A(a3) >= 0) ? A(a1) : A(a2)

      DOT2_ADD_ATI*         R(d) = G(d) = B(d) = A(d) = R(a1) * R(a2) + 
                                                        G(a1) * G(a2) + 
                                                        B(a3)                  

      DOT3_ATI*             R(d) = G(d) = B(d) = A(d) = R(a1) * R(a2) +
                                                        G(a1) * G(a2) +
                                                        B(a1) * B(a2)

      DOT4_ATI* **          R(d) = G(d) = B(d) = A(d) = R(a1) * R(a2) +
                                                        G(a1) * G(a2) +
                                                        B(a1) * B(a2) +
                                                        A(a1) * A(a2)

         Table 3.21 Color and Alpha Fragment Shader Instructions

         Special Notes:
           *   - DOT2_ADD_ATI/DOT3_ATI/DOT4_ATI can only be specified as
                 an alpha instruction directly after being specified as
                 a color instruction.  When specified as an alpha 
                 instruction, the parameters are ignored, although they 
                 should be valid enumerants in order to compile.  The 
                 result of the color instruction will simply be placed
                 in the alpha <dst>.

           **  - After a DOT4_ATI color instruction is specified, the
                 only alpha instruction that can immediately follow is a 
                 DOT4_ATI.  This is because the DOT4 color instruction 
                 implicitely uses an alpha instruction to calculate the 
                 result.  If another type of alpha instruction is 
                 desired after a DOT4_ATI color instruction is issued, 
                 there are two choices: either issue another color 
                 instruction first, or issue the DOT4_ATI alpha 
                 instruction followed by the desired alpha instruction.

           *** - The blend factor (a1) of LERP_ATI must be in the range
                 [0,1] or the results are undefined.

    The <dst> parameter specifies to which register (REG_x_ATI) the 
    result of the instruction is written.

    The <dstMask> parameter specifies which of the color components in 
    <dst> will be written (ColorFragmentOp[1..3]ATI only).  This can 
    either be NONE, in which case there is no mask and everything is 
    written, or the bitwise-or of RED_BIT_ATI, GREEN_BIT_ATI, and 
    BLUE_BIT_ATI.

    The <dstMod> parameter specifies which modifications are performed
    on each component of the destination.  The result can be modulated
    by specifying either 2X_BIT_ATI, 4X_BIT_ATI, 8X_BIT_ATI, 
    HALF_BIT_ATI, QUARTER_BIT_ATI, or EIGHTH_BIT_ATI.  These are all 
    mutually exclusive, and can optionally be bitwise-or'd with 
    SATURATE_BIT_ATI, which clamps the result after any modulation 
    occurs.  

    Table 3.22 shows the result of each <dstMod> modification.


      Modifier                Result
      --------                ------
      NONE                    d = d
      2X_BIT_ATI              d = 2 * d
      4X_BIT_ATI              d = 4 * d
      8X_BIT_ATI              d = 8 * d
      HALF_BIT_ATI            d = d / 2
      QUARTER_BIT_ATI         d = d / 4
      EIGHTH_BIT_ATI          d = d / 8
      SATURATE_BIT_ATI        d = clamp(d) to range [0, 1]
         
         Table 3.22 Result of destination modification     


    Note that the internal precision of the fragment shader allows 
    values in the range [-8, 8].  
     
    The <argN> parameter specifies the source argument.  The source can 
    come from REG_x_ATI, CON_x_ATI, ZERO, ONE, PRIMARY_COLOR_ARB, or 
    SECONDARY_INTERPOLATOR_ATI.  Note that in a two-pass shader, 
    PRIMARY_COLOR_ARB and SECONDARY_INTERPOLATOR_ATI cannot be used in 
    the first pass of the shader.

    Each argument has an <argNRep> parameter which specifies the 
    replication of each component.  

    Table 3.23 shows the result of each <argNRep> source replication.


      Replication             Result
      -----------             -----                 
      NONE                    R(s) = R(s)
                              G(s) = G(s)
                              B(s) = B(s)
                              A(s) = A(s)

      RED                     R(s) = R(s)
                              G(s) = R(s)
                              B(s) = R(s)
                              A(s) = R(s)

      GREEN                   R(s) = G(s)
                              G(s) = G(s)
                              B(s) = G(s)
                              A(s) = G(s)

      BLUE                    R(s) = B(s)
                              G(s) = B(s)
                              B(s) = B(s)
                              A(s) = B(s)

      ALPHA                   R(s) = A(s)
                              G(s) = A(s)
                              B(s) = A(s)
                              A(s) = A(s)

         Table 3.23 Result of source replication


    Each argument also has an <argNMod> parameter which specifies 
    modifiers to each component.  A value of NONE specifies that no 
    modifiers are present.  Otherwise, the bitwise-or of NEGATE_BIT_ATI, 
    BIAS_BIT_ATI, and 2X_BIT_ATI can be specified as modifiers.  

    Table 3.24 shows the result of each <argNMod> source modifier.


      Modifier                Result
      --------                ------
      NONE                    s = s
      NEGATE_BIT_ATI          s = -s
      COMP_BIT_ATI            s = 1 - s
      BIAS_BIT_ATI            s = s - 0.5
      2X_BIT_ATI              s = 2 * s
           
         Table 3.24 Result of source modification


    If multiple source modifiers are applied, the order of operations is
    COMP, BIAS, SCALE, then NEGATE.  The following equation shows the 
    order of operations if all modifiers were to be applied:
	  
         s = -(2 * ((1.0 - s) - 0.5))
     
    In order to set the constants that can be used by shader 
    instructions, the entry point:

      void SetFragmentShaderConstantATI (uint dst, const float *value);

    is used.  The <dst> parameter specifies which of the constants 
    (CON_x_ATI) to set.  The <value> pointer must contain four floating 
    point values in the range [0, 1] to set the components of the 
    constant.  Constant registers loaded with floating point values 
    outside of this range will have undefined values.  Calls to this 
    function which occur inside a shader definition are automatically 
    bound when the shader is bound.  This means that shader constants 
    have scope: if SetFragmentShaderConstantATI is called outside a 
    shader definition, it is bound globally.  However, if that same 
    shader constant is set inside the shader, it overrides the global 
    definition when bound.


Additions to Chapter 4 of the OpenGL 1.2.1 Specification (Per-Fragment
Operations and the Framebuffer)

    None


Additions to Chapter 5 of the OpenGL 1.2.1 Specification (Special 
Functions)

    Modify Section 5.4, Display Lists (p. 175)

    (modify last paragraph, p. 178) ... These are: IsList, GenLists,
    ..., GenFragmentShadersATI, DeleteFragmentShadersATI, 
    BeginFragmentShaderATI, EndFragmentShaderATI, PassTexCoordATI,
    SampleMapATI, ColorFragmentOp[1..3]ATI, AlphaFragmentOp[1..3]ATI, 
    as well as IsEnabled and all of the Get commands (see Chapter 6).


Additions to Chapter 6 of the OpenGL 1.2.1 Specification (State and
State Requests)

    None


Additions to Appendix A of the OpenGL 1.2.1 Specification (Invariance)

    None


Additions to the AGL/GLX/WGL Specifications

    None


Interactions with ARB_shadow

    The texture comparison introduced by ARB_shadow can be expressed in 
    terms of a fragment shader, and in fact use the same internal 
    resources on some implementations.  Therefore, if fragment shader 
    mode is enabled, the GL behaves as if TEXTURE_COMPARE_MODE_ARB is 
    NONE.


Errors
  
    The error INVALID_VALUE is generated if GenFragmentShadersATI is
    called where <range> is zero.

    The error INVALID_OPERATION is generated if GenFragmentShadersATI, 
    BindFragmentShaderATI, DeleteFragmentShaderATI, or 
    BeginFragmentShaderATI are specified inside a 
    Begin/EndFragmentShaderATI pair.

    The error INVALID_OPERATION is generated if EndFragmentShaderATI, 
    PassTexCoordATI, SampleMapATI, ColorFragmentOp[1..3]ATI, or 
    AlphaFragmentOp[1..3]ATI is specified outside a 
    Begin/EndFragmentShaderATI pair.
   
    The error INVALID_OPERATION is generated by EndFragmentShaderATI if 
    <argN> passed to ColorFragmentOp[1..3]ATI or 
    AlphaFragmentOp[1..3]ATI is PRIMARY_COLOR_ARB or 
    SECONDARY_INTERPOLATOR_ATI on the first pass of a two-pass shader, 
    or if the shader cannot be compiled due to some other 
    implementation-dependent limitation.  EndFragmentShaderATI will 
    still have a side-effect if this error is encountered: the 
    Begin/EndFragmentShaderATI pair will be closed, and the current 
    shader will be undefined.

    The error INVALID_OPERATION is generated by PassTexCoordATI or 
    SampleMapATI if two shader passes have already been specified, or if 
    the same <dst> register is specified twice in the same pass.

    The error INVALID_OPERATION is generated by PassTexCoordATI or 
    SampleMapATI if <coord> passed to PassTexCoordATI or <interp> passed 
    to SampleMapATI is a register in the first pass, or a register with 
    SWIZZLE_STQ_ATI or SWIZZLE_STQ_DQ_ATI <swizzle> in the second pass, 
    or if different <swizzle> parameters are specified for the same 
    <coord> or <interp> in the same pass.

    The error INVALID_OPERATION is generated by ColorFragmentOp[1..3]ATI 
    or AlphaFragmentOp[1..3]ATI if more than 8 instructions have been 
    specified for a shader pass.

    The error INVALID_OPERATION is generated by ColorFragmentOp[1..3]ATI 
    if <argN> is SECONDARY_INTERPOLATOR_ATI and <argNRep> is ALPHA, or 
    by AlphaFragmentOp[1..3]ATI if <argN> is SECONDARY_INTERPOLATOR_ATI
    and <argNRep> is ALPHA or NONE, or by ColorFragmentOp2ATI if <op> is
    DOT4_ATI and <argN> is SECONDARY_INTERPOLATOR_ATI and <argNRep> is
    ALPHA or NONE.

    The error INVALID_OPERATION is generated by ColorFragmentOp3ATI or 
    AlphaFragmentOp3ATI if all three <argN> parameters are constants, 
    and all three are different.

    The error INVALID_OPERATION is generated by AlphaFragmentOp[2..3]ATI 
    if <op> is DOT3_ATI, DOT4_ATI, or DOT2_ADD_ATI and there was no 
    matching ColorFragmentOp[2..3]ATI immediately preceding, or if <op> 
    is not DOT4_ATI and the immediately preceding ColorFragmentOp2ATI 
    specifies an <op> of DOT4_ATI.

    The error INVALID_ENUM is generated if <dst> passed to 
    PassTexCoordATI, SampleMapATI, ColorFragmentOp[1..3]ATI, or 
    AlphaFragmentOp[1..3]ATI is not a valid register or is greater than 
    the number of texture units available on the implementation.

    The error INVALID_ENUM is generated if <coord> passed to 
    PassTexCoordATI or <interp> passed to SampleMapATI is not a valid 
    register or texture unit, or the register or texture unit is greater 
    than the number of texture units available on the implementation.

    The error INVALID_ENUM is generated if <argN> passed to 
    ColorFragmentOp[1..3]ATI or AlphaFragmentOp[1..3]ATI is not a valid 
    constant, interpolator, or register.

    The error INVALID_ENUM is generated if <dstMod> passed to 
    ColorFragmentOp[1..3]ATI or AlphaFragmentOp[1..3]ATI contains 
    multiple mutually exclusive modifier bits, not counting 
    SATURATE_BIT_ATI.


New State

                                            Initial
    Get Value            Type  Get Command  Value    Description             Sec.    Attribute
    ---------            ----  -----------  -------  -----------             ------  ---------
    FRAGMENT_SHADER_ATI   B    IsEnabled    False    Fragment shader enable  3.8.11  enable

    Table X.6.  New Accessible State Introduced by ATI_fragment_shader.


    Get Value    Type    Get Command   Initial Value  Description          Sec     Attribute
    ---------    ------  -----------   -------------  -------------------  ------  ---------
    -            6xR4    -             undefined      temporary registers  3.8.11  -

    Table X.9.  Fragment Shader Per-fragment Execution State.  All per-fragment
    execution state registers are uninitialized at the beginning of program
    execution.


New Implementation Dependent State

    None


Deprecated Functionality

    The following queryable implementation-dependent constants are 
    described here for backward-compatibility.  They are now specified 
    to always return fixed values on all implementations, and are thus 
    obsolete.

    The number of available registers can be queried by doing a glGet on 
    NUM_FRAGMENT_REGISTERS_ATI.  This refers to the number of 
    REG_x_ATI's, and is now fixed at 6.

    The number of available constants can be queried by doing a glGet on 
    NUM_FRAGMENT_CONSTANTS.  This refers to the number of CON_x_ATI's, 
    and is now fixed at 8.

    The number of passes, instructions per pass, and total instructions
    available to a shader can be queried using glGet.  Querying for 
    NUM_PASSES_ATI returns the maximum number of passes that the shader 
    can perform, now fixed at 2.  Querying for 
    NUM_INSTRUCTIONS_PER_PASS_ATI returns the maximum number of 
    instructions available on a given pass, now fixed at 8.  Finally, 
    NUM_INSTRUCTIONS_TOTAL_ATI returns the maximum number of total 
    instructions available to a shader, now fixed at 16 (2 per pass).  

    COLOR_ALPHA_PAIRING_ATI can be queried by glGet to determine if each
    ColorFragmentOp[1..3]ATI/AlphaFragmentOp[1..3]ATI pair counts as one 
    instruction against the limit, or if each color and alpha 
    instruction is counted individually (i.e., each pair counts as two 
    instructions).  This query now always returns TRUE: each pair counts 
    as one instruction against the 8 instructions allowed per pass.

    The number of components available in a coordinate interpolator, 
    passed in as <interp> to SampleMapATI or <coord> to PassTexCoord, 
    can be queried using NUM_INTERPOLATOR_COMPONENTS_ATI.  This query 
    now always returns 3, meaning the fourth component is ignored.

    The number of components passed in the registers via PassTexCoord 
    from the first pass to the second can be queried using 
    NUM_LOOPBACK_COMPONENTS_ATI.  This query now always returns 3, 
    meaning the fourth component of <dst> is undefined.


Sample Usage

    The following is an example that simulates a chrome surface:

      shadername = glGenFragmentShadersATI(1);
      glBindFragmentShaderATI(shadername);
      glBeginFragmentShaderATI();

      // Pass 1
      glPassTexCoordATI(GL_REG_1_ATI, GL_TEXTURE1_ARB, GL_SWIZZLE_STR_ATI); // N
      glPassTexCoordATI(GL_REG_2_ATI, GL_TEXTURE2_ARB, GL_SWIZZLE_STR_ATI); // light to vertex vector in light space
      glPassTexCoordATI(GL_REG_3_ATI, GL_TEXTURE3_ARB, GL_SWIZZLE_STR_ATI); // H
      glSampleMapATI(GL_REG_4_ATI, GL_TEXTURE4_ARB, GL_SWIZZLE_STR_ATI);    // L (sample cubemap normalizer)

      // reg4 = N.L
      glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_4_ATI, GL_NONE, GL_NONE,
                            GL_REG_1_ATI, GL_NONE, GL_NONE,
                            GL_REG_4_ATI, GL_NONE, GL_2X_BIT_ATI|GL_BIAS_BIT_ATI);

      // reg1 = N.H
      glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_1_ATI, GL_NONE, GL_NONE,
                            GL_REG_1_ATI, GL_NONE, GL_NONE,
                            GL_REG_3_ATI, GL_NONE, GL_NONE);

      // reg1(green) = H.H (aka |H|^2)
      glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_1_ATI, GL_GREEN_BIT_ATI, GL_NONE,
                            GL_REG_3_ATI, GL_NONE, GL_NONE,
                            GL_REG_3_ATI, GL_NONE, GL_NONE);

      // reg2 = |light to vertex|^2
      glColorFragmentOp2ATI(GL_DOT3_ATI, GL_REG_2_ATI, GL_NONE, GL_NONE,
                            GL_REG_2_ATI, GL_NONE, GL_NONE,
                            GL_REG_2_ATI, GL_NONE, GL_NONE);

      // Pass 2
      glSampleMapATI(GL_REG_0_ATI, GL_TEXTURE5_ARB, GL_SWIZZLE_STR_ATI); // sample enviroment map using eye vector
      glSampleMapATI(GL_REG_2_ATI, GL_REG_2_ATI, GL_SWIZZLE_STR_ATI);    // sample attenuation map
      glSampleMapATI(GL_REG_3_ATI, GL_REG_1_ATI, GL_SWIZZLE_STR_ATI);    // sample specular NHHH map = (N.H)^256
      glPassTexCoordATI(GL_REG_4_ATI, GL_REG_4_ATI, GL_SWIZZLE_STR_ATI); // pass N.L through

      // reg3 = (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)
      glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_3_ATI, GL_NONE, GL_NONE,
                            GL_REG_3_ATI, GL_NONE, GL_NONE,
                            GL_REG_4_ATI, GL_NONE, GL_NONE);

      // reg3 = specular * environment map
      glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_3_ATI, GL_NONE, GL_NONE,
                            GL_REG_0_ATI, GL_NONE, GL_NONE,
                            GL_REG_3_ATI, GL_NONE, GL_NONE);

      // reg4 = diffuse * environment map
      glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_4_ATI, GL_NONE, GL_NONE,
                            GL_REG_0_ATI, GL_NONE, GL_NONE,
                            GL_REG_4_ATI, GL_NONE, GL_NONE);

      // reg0 = (specular * environment map) + (diffuse * environment map)
      glColorFragmentOp2ATI(GL_ADD_ATI, GL_REG_0_ATI, GL_NONE, GL_NONE,
                            GL_REG_3_ATI, GL_NONE, GL_NONE,
                            GL_REG_4_ATI, GL_NONE, GL_NONE);

      // apply point light attenuation
      glColorFragmentOp2ATI(GL_MUL_ATI, GL_REG_0_ATI, GL_NONE, GL_SATURATE_BIT_ATI,
                            GL_REG_0_ATI, GL_NONE, GL_NONE,
                            GL_REG_2_ATI, GL_RED, GL_NONE);
      glEndFragmentShaderATI();


Revision History

    Date: 11/4/2006
    Revision: 1.8
      - Updated contact info after ATI/AMD merger.

    Date: 8/21/2002
    Revision: 1.7
      - Fixed lack of comma typo in glAlphaFragmentOp2ATI prototypes.

    Date: 8/1/2002
    Revision: 1.6
      - Changed DeleteFragmentShaderATI behavior to silently ignore the 
        deletion of non-existent or default shaders.

    Date: 6/5/2002
    Revision: 1.5
      - Added interaction with ARB_shadow.

    Date: 5/30/2002
    Revision: 1.4
      - Specified that LERP's blend factor must be in the range [0,1].
      - Added error condition when trying to use secondary color in DOT4
        color instruction when replication is GL_NONE or GL_ALPHA.

    Date: 5/21/2002
    Revision: 1.3
      - Made number of registers (REG_x_ATI) explicit: 6.
      - Changed CND0_ATI definition from >0 to >=0.
      - Added wording to emphasize [0,1] range for constants.
      - Added wording to reflect that EndFragmentShaderATI will close
        Begin/End pair even if error is encountered.
      - Added wording to reflect parallelism of color/alpha pairs.
      - Added error condition when trying to use secondary color alpha.
      - Added error condition when generating shader IDs with <range> 0.
      - Added display list exclusion for everything except 
        BindFragmentShaderATI and SetFragmentShaderConstantATI.
      - Cleaned up, fixed typos, and reformatted.
      - Added New State section.
      - Replaced sample code.

    Date: 4/19/2002
    Revision: 1.2
      - Updated swizzle table to indicate that projected texcoords are
        undefined when used in conjunction with cubemaps or 3D textures.

    Date: 3/20/2002
    Revision: 1.1
      - Made resource availability explicit.
      - Deprecated implementation-dependent constant queries.
      - Added various error conditions described in prose of spec.
      - Changed PRIMARY_COLOR_EXT to PRIMARY_COLOR_ARB.
      - Cleaned up and fixed typos throughout.

    Date: 1/2/2002
    Revision: 1.02
      - Added note that PRIMARY_COLOR_EXT and SECONDARY_INTERPOLATOR_ATI can not
        be used on the first pass of a two pass shader.  Also added error
        for this case to Errors section.
      - Added note that in order to save the contents of a register from the 
        first pass to the second, there has to be a PassTexCoordATI() on that
        register to itself on the next pass.
      - Changed PRIMARY_COLOR to PRIMARY_COLOR_EXT.

    Date: 10/15/2001
    Revision: 1.01
      - Fixed typos in example program.
      - Added language about the shader result being placed in REG_0_ATI.
      - Specify range supported [-8..8].
      - Added notes on how to specify whether DOT4/DOT3/DOT2_ADD result 
        goes to alpha channel.

    Date: 8/21/2001
    Revision: 1.0
      - Added equation for source modifiers.

    Date: 8/6/2001
    Revision: 0.6
      - Added restraint that only SWIZZLE_STR_ATI and SWIZZLE_STR_DR_ATI
        can be used on the second pass when the source is a register.

    Date: 6/29/2001
    Revision: 0.5
      - Removed glTexProjectATI and change glSampleMapATI/glPassTexCoordATI to
        take a <swizzle> parameter instead of <project>.
      - Changed MAD_ATI from (a + b * c) to (a * b + c).

    Date: 6/11/2001
    Revision: 0.4
      - Removed FRAC_ATI.
      - Added <project> parameter to SampleMapATI and PassTexCoordATI to
        match current implementation.

    Date: 5/01/2001
    Revision: 0.3
      - Added COLOR_ALPHA_PAIRING_ATI.
      - Attempted to clarify definition of SampleMapATI in the documentation
        section.  Changed <map> to <interp>.
      - Added TexProjectATI and documented texture projection modes to allow
        implementations that only support 3-tuples to select between (s, t, r)
        and (s, t, q) coordinates.

    Date: 4/19/2001
    Revision: 0.2
      - Removed <dstRot> from ColorFragmentOp[1..3]ATI.
      - Changed SHADER_ATI to FRAGMENT_SHADER_ATI.
      - Fixed the <op>'s in the New Tokens section to go to the proper
        Color/AlphaOp functions.
      - Added ZERO and ONE constants.
      - Made number of passes queryable: removed NUM_PASSn_INSTRUCTIONS_ATI, 
        replaced with NUM_PASSES_ATI, NUM_INSTRUCTIONS_PER_PASS_ATI, and
        NUM_INSTRUCTIONS_TOTAL_ATI.
      - Documented when new pass starts (SampleMapATI/PassCoordATI).
      - Added NUM_INPUT_INTERPOLATOR_COMPONENTS_ATI/NUM_LOOPBACK_COMPONENTS_ATI.
      - Fixed sample usage to not do a dependent read on the base map.

    Date: 4/16/2001
    Revision: 0.1
      - First draft
