Back to the OpenGL extension cross reference
GL_ATI_text_fragment_shader
    ATI_text_fragment_shader
Name Strings
    GL_ATI_text_fragment_shader
Contributors
    Bob Beretta, Apple Computer
    Dan Ginsburg, ATI Research
    Evan Hart, ATI Research
    Benj Lipchak, ATI Research
    James McCombe, Apple Computer
    Jason Mitchell, ATI Research
    and contributors to the ARB_vertex_program working group,
    the product of which provided the API for program specification
    and object management.
Contact
    Jeremy Sandmel, ATI Research (jsandmel 'at' ati.com)
Status
    Shipping on MacOS X, version 10.2
Version
    Last Modified Date: Sep 5, 2002
    Author Revision: 1.0.10 (based on 1.5 of ATI_fragment_shader)
Number
    269
Dependencies
    ARB_multitexture is required by this extension.
    ARB_shadow interacts with this extension.
    ARB_vertex_program is referred to for documentation on the
    program management API, but not specifically required as long
    as the entry points are exported by this extension.
    ATI_fragment_shader is the architectural basis for this extension,
    but is not specifically required by this extension.
    The extension is written against the OpenGL 1.2.1 Specification.
Overview
    The ATI_fragment_shader extension exposes a powerful fragment
    processing model that provides a very general means of expressing
    fragment color blending and dependent texture address modification.
    The processing is termed a fragment shader or fragment program and 
    is specifed using a register-based model in which there are fixed 
    numbers of instructions, texture lookups, read/write registers, and 
    constants.
    ATI_fragment_shader provides a unified instruction set
    for operating on address or color data and eliminates the
    distinction between the two.  That extension provides all the
    interfaces necessary to fully expose this programmable fragment
    processor in GL.
    ATI_text_fragment_shader is a redefinition of the 
    ATI_fragment_shader functionality, using a slightly different 
    interface.  The intent of creating ATI_text_fragment_shader is to
    take a step towards treating fragment programs similar to other 
    programmable parts of the GL rendering pipeline, specifically 
    vertex programs. This new interface is intended to appear 
    similar to the ARB_vertex_program API, within the limits of the 
    feature set exposed by the original ATI_fragment_shader extension.
    The most significant differences between the two extensions are:
    (1) ATI_fragment_shader provides a procedural function call
        interface to specify the fragment program, whereas
        ATI_text_fragment_shader uses a textual string to specify
        the program.  The fundamental syntax and constructs of the
        program "language" remain the same.
    (2) The program object managment portions of the interface,
        namely the routines used to create, bind, and delete program
        objects and set program constants are managed
        using the framework defined by ARB_vertex_program.
    (3) ATI_fragment_shader refers to the description of the
        programmable fragment processing as a "fragment shader".
        In keeping with the desire to treat all programmable parts
        of the pipeline consistently, ATI_text_fragment_shader refers
        to these as "fragment programs".  The name of the extension is
        left as ATI_text_fragment_shader instead of
        ATI_text_fragment_program in order to indicate the underlying
        similarity between the API's of the two extensions, and to
        differentiate it from any other potential extensions that
        may be able to move even further in the direction of treating
        fragment programs as just another programmable area of the
        GL pipeline.
    Although ATI_fragment_shader was originally conceived as a
    device-independent extension that 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
    in ATI_fragment_shader.  Further, in ATI_text_fragment_shader,
    most of these resource limits are fixed by the text grammar and 
    the queries have been removed altogether.
Issues
    None
    None.
    NOTE: Though this extension introduces no new procedures and
    functions, it relies on the program object management API from the
    pending ARB_vertex_program extension with the introduction of
    a new program target and program specification syntax.
    See the ARB_vertex_program specification for full details on the
    use of these procedures and functions.
      ProgramStringARB
      BindProgramARB
      DeleteProgramsARB
      GenProgramsARB
      ProgramEnvParameter4{d,dv,f,fv}ARB
      ProgramLocalParameter4{d,dv,f,fv}ARB
      GetProgramEnvParameter{dv,fv}ARB
      GetProgramLocalParameter{dv,fv}ARB
      GetProgramivARB
      GetProgramStringARB
      IsProgramARB
    Accepted by the <cap> parameter of Disable, Enable, and IsEnabled, 
    and by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, 
    and GetDoublev, and by the <target> parameter of ProgramStringARB,
    BindProgramARB, ProgramEnvParameter4{d,dv,f,fv}ARB,
    ProgramLocalParameter4{d,dv,f,fv}ARB, 
    GetProgramEnvParameter{dv,fv}ARB, GetProgramLocalParameter{dv,fv}ARB,
    GetProgramivARB, GetProgramfvATI, and GetProgramStringARB.
        TEXT_FRAGMENT_SHADER_ATI              0x8200
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 Section 3.10, (p. 154) (subsequent sections get incremented)
    3.10  Fragment Programs
    The texture application and texture environments may optionally be 
    replaced by an application supplied program referred to here as a 
    fragment program.  In this case, subsequent processing is still 
    applied normally, including fog, color sum, and antialiasing 
    application.
    The framework for specifying and managing fragment programs is
    the one defined in section 5.7 of ARB_vertex_program.  For fragment
    programs, TEXT_FRAGMENT_SHADER_ATI is used as the <target> for these
    program management entrypoints.
    A fragment program is similar in concept to a vertex program,
    described in section 2.14 of ARB_vertex_program, except that its
    processing is performed at a later stage in the GL pipeline.  Where
    a vertex program takes the current values of the vertex components
    as its inputs, a fragment program takes the fragments and their
    associated data, produced by rasterization, as inputs.  Likewise,
    while a vertex program outputs a homogeneous position and a set of
    attributes, a fragment program outputs a color.
    3.10.1  Fragment Program Grammar and Semantic Restrictions
    Fragment programs are specified as string of ASCII characters
    encoding the programs.  When a program is loaded by a call to
    ProgramStringARB (section 5.7.1), with a target of 
    TEXT_FRAGMENT_SHADER_ATI, the program string is parsed into
    a set of tokens possibly separated by white space.  Spaces, tabs,
    newlines, carriage returns, and comments are considered whitespace.
    Comments begin with the character "#" and are terminated by a
    newline, a carriage return, or the end of the program array.
    The Backus-Naur Form (BNF) grammar below specifies the syntactically
    valid sequences for 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 text fragment shader program is required to begin with the header 
    string "!!ATIfs1.0", without any preceding whitespace.  This string 
    identifies the subsequent program text as a text fragment shader
    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>              ::= <optionalConstDeclareBlock>
                               <optionalPrelimPassBlock>
                               <outputPassBlock>
    <constDeclareBlock>    ::= ""
                             | "StartConstants" ";"
                                   <constDeclareSequence>
                               "EndConstants" ";"
    <constDeclareSequence> ::= <constDeclareSequence> <constDeclareStatement>
                             | ""
    <constDeclareStatement> ::= "CONSTANT" <programConstName> "=" <constBinding> ";"
    <constBinding>          ::= <progEnvParam>
                              | <programLocalParam>
                              | <literalConstBinding>
    <progEnvParam>          ::= "program" "." "env" 
                                 "[" <progEnvParamNum> "]"
    <progEnvParamNum>      ::= <integer> from 0 to 7
    <progLocalParam>       ::= "program" "." "local" 
                                 "[" <progLocalParamNum> "]"
    <progLocalParamNum>    ::= <integer> from 0 to 7
    <literalConstBinding>  ::= "{" <normalizedFloat> "}"
                             | "{" <normalizedFloat> "," 
                                   <normalizedFloat> "}"
                             | "{" <normalizedFloat> "," 
                                   <normalizedFloat> ","
                                   <normalizedFloat> "}"
                             | "{" <normalizedFloat> "," 
                                   <normalizedFloat> ","
                                   <normalizedFloat> "," 
                                   <normalizedFloat> "}"
    <optionalPrelimPassBlock> ::= ""
                                | "StartPrelimPass" ";"
                                      <initRegSequence>
                                      <aluSequence>
                                  "EndPass" ";"
    <outputPassBlock>      ::= ""
                             | "StartOutputPass" ";"
                                   <initRegSequence>
                                   <aluSequence>
                               "EndPass" ";"
    <initRegSequence>      ::= <initRegSequence> <initRegStatement>
                             | ""
    <initRegStatement>     ::= <initRegOp> <initRegDst> <initRegSrc> ";"
    <initRegOp>            ::= "PassTexCoord"
                             | "SampleMap"
    <initRegDst>           ::= <regName>
    <initRegSrc>           ::= <regName> <threeTupleSelect> 
                             | <texCoordName> <threeTupleSelect> 
    <aluSequence>          ::= <aluSequence> <aluStatement>
                             | ""
    <aluStatement>         ::= <unaryOp>   <unaryOpArgs>   ";"
                             | <binaryOp>  <binaryOpArgs>  ";"
                             | <ternaryOp> <ternaryOpArgs> ";"
    <unaryOpArgs>          ::= <dstInfo> <argInfo>
    <binaryOpArgs>         ::= <dstInfo> <argInfo> "," <argInfo>
    <ternaryOpArgs>        ::= <dstInfo> <argInfo> "," <argInfo> "," <argInfo>
    <dstInfo>              ::= <dstName> <optionalDstMask> <optionalDstMod>
    <optionalDstMask>      ::= ""
                             | "." "r"
                             | "." "g"
                             | "." "rg"
                             | "." "b"
                             | "." "rb"
                             | "." "gb"
                             | "." "rgb"
                             | "." "a"
                             | "." "ra"
                             | "." "ga"
                             | "." "rga"
                             | "." "ba"
                             | "." "rba"
                             | "." "gba"
                             | "." "rgba"
    <optionalDstMod>       ::= <dstModSetting> <optionalSaturate>
    <dstModSetting>        ::= ""
                             | "." "2x"
                             | "." "4x"
                             | "." "8x"
                             | "." "half"
                             | "." "quarter"
                             | "." "eighth"
    <optionalSaturate>     ::= "." "sat"
    <dstName>              ::= <regName>
    <argInfo>              ::= <argName> <optionalArgReplicate> <optionalArgMod>
    <argName>              ::= <regName>
                             | <programConstantName>
                             | <fixedConstantName>
                             | <colorName>
    <optionalArgReplicate> ::= ""
                             | "." "r"
                             | "." "g"
                             | "." "b"
                             | "." "a"
    <optionalArgMod>       ::= ""
                             | <optionalNegate> <optional2Times> <optionalBias> <optionalComplement>
    <optionalNegate>       ::= ""
                             | "." "neg"
    <optional2Times>       ::= ""
                             | "." "2x"
    <optionalBias>         ::= ""
                             | "." "bias"
    <optionalComplement>   ::= ""
                             | "." "comp"
    <texCoordName>         ::= "t0"
                             | "t1"
                             | "t2"
                             | "t3"
                             | "t4"
                             | "t5"
    <threeTupleSelect>     ::= "." "str"
                             | "." "stq"
                             | "." "str_dr"
                             | "." "stq_dq"
    <regName>              ::= "r0"
                             | "r1"
                             | "r2"
                             | "r3"
                             | "r4"
                             | "r5"
    <programConstantName>  ::= "c0"
                             | "c1"
                             | "c2"
                             | "c3"
                             | "c4"
                             | "c5"
                             | "c6"
                             | "c7"
    <fixedConstantName>    ::= "0"
                             | "1"
    <colorName>            ::= "color0"
                             | "color1"
    <unaryOp>              ::= "MOV"
    <binaryOp>             ::= "ADD"
                             | "MUL"
                             | "SUB"
                             | "DOT3"
                             | "DOT4"
    <ternaryOp>            ::= "MAD"
                             | "LERP"
                             | "CND"
                             | "CND0"
                             | "DOT2ADD"
    The <integer> rule matches an integer constant.  The integer 
    consists of a sequence of one or more digits ("0" through "9").
    The <normalizedFloat> rule matches a floating-point constant in the 
    range of 0.0 to 1.0, inclusive.
    If TEXT_FRAGMENT_SHADER_ATI is enabled, but the currently bound
    program is invalid, the results of drawing commands are undefined.
    A program may be invalid because it specifically violates the
    syntax of the above grammar or because the specified program
    violates one of the additional semantic restrictions given in
    summary below with details following:
    Summary of semantic restrictions:
    ---------------------------------
    1.  All "cX" constants used by a program must be declared in a 
        constant block, and program constants can be bound at most once.
    2.  If an instruction refers to "cX" constants as arguments, at most
        2 different constants can be used in a single instruction.
    3.  "color0" and "color1" may be used only in the output pass.
    4.  A preliminary pass must contain at least one ALU operation.
    5.  A maximum of 8 pairs or implicit pairs of color and alpha
        instructions (not including "PassTexCoord and" "SampleMap") can
        be used in a single pass.
    6.  A given destination register can only be written by a SampleMap 
        or PassTexCoord instruction once in a given pass.
    7.  The second argument to "PassTexCoord" and "SampleMap" can not be
        an "rX" register in the first pass.
    8.  Once a texture coordinate source is specified with a particular
        choice for coordinate selection, (i.e "str" or "stq"), the
        program may not refer to that same texture coordinate with a 
        different choice later on.  The exception is that a different 
        projection can be specified (i.e. using both "t2.str" and 
        "t2.str_dr" on the same texture coordinate set is legal, but 
        using "t2.str" and "t2.stq" is not)
    9.  The second argument to "PassTexCoord" and "SampleMap" in the
        output pass can not be a register that uses "stq" or "stq_dq"
        as a component choice selection.
    10. Alpha destination masks for DOT2ADD, DOT3, and DOT4 instructions 
        can only be specified in combination with color destination masks.
    11. If a DOT4 is specified to not write the alpha channel of it's 
        destination, then it is illegal to specify the next instruction 
        to write *only* the alpha channel of it's destination.
    12. A program can not issue an instruction which requires the
        use of the alpha component of a "color1" (secondary color) 
        parameter. 
    13. A program may not refer to a register number greater than
        the number of supported texture units.
    14. A program may not refer to a texture coordinate set greater
        than the number of supported texture units.
    The details of the above restrictions and usage guidelines are given
    below:
    There are three types of data that can be in a fragment program:
    registers, constants, and interpolators.  The 6 "rX" registers
    can be used as source or destination in any instruction.
    The final result of the program is whatever value is in
    the register "r0".  This value will be the final color of the
    output fragment passed by the programmable fragment processing
    unit to subsequent non-programmable fragment processing.
    There are 8 constant registers available, "c0" through
    "c7".  To use these constants, a program must include a
    constant declaration block which indicates how the constants are
    to be bound.  Constants can be bound to program local parameters,
    program global parameters, or literal string constants.  Program
    locals represent per-program storage, while program environment 
    parameters are global to all programs.  See the ARB_vertex_program
    documentation for details on the use of 
    ProgramLocalParameter4{d,dv,f,fv}ARB, and 
    ProgramEnvParameter4{d,dv,f,fv}ARB to set these bound constants.
    Constants can also be bound to a constant floating point vector
    within the program text itself, such as "{ 1.0, 0.0, 0.2, 0.5 }".
 
    "cX" constants can be used as source in any instruction,
    but at most 2 different constants may be used as source arguments 
    in any single instruction.
    Additionally, the primary and secondary color interpolators are
    available as source in any instruction, but only in
    the last pass of the program (i.e., the only pass of a one-pass
    program or the second pass of a two-pass program).
    Either one or two passes may be specified in a program.  The
    passes can be thought of as an optional preliminary
    pass and a required final output pass.  The passes are
    delineated by the occurence of the "StartPrelimPass" and "EndPass"
    tokens for the optional preliminary pass, and the
    "StartOutputPass" and "EndPass" tokens for the output pass.  Note
    that in a two-pass shader, the preliminary pass must contain
    at least one match for the <aluStatement> rule in the grammar.
    Or put another way, the preliminary pass can not consist solely of 
    PassTexCoord and SampleMap operations.
    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 followed immediately by one alpha instruction.
    In ATI_fragment_shader, color and alpha instructions were specified
    independently through the use of ColorFragmentOp and AlphaFragmentOp.
    In ATI_text_fragment_shader color instructions are identified by the
    use of the "r", "g", or "b" write masks on the destination register
    of the instruction.  Alpha instructions are identified by the use of
    the "a" write mask.  If the "a" mask and at least one of "r", "g",
    or "b" masks are used, or if no mask is used at all, the
    instruction is considered to be an implicit pair that will apply
    the same operation to the color and the alpha channels.
    For instance, the following would be considered color operations
        "DOT3 r2.rgb, r0, r3;"
        "MUL  r1.g,   r0, r2;"
    The following would be considered alpha operations
        "MOV  r2.a, r0;"
        "MUL  r1.a, r0, r2;"
    The following would each be considered an implicit pair of color
    and alpha operations (i.e. three example pairs are given below)
       "DOT3 r2,      r0, r3;"
       "MUL  r4.ba,   r0, r2;"
       "MUL  r1.rgba, r0, r2;"
    Therefore, the following examples indicate legal pairs of
    instructions, each of which would count against the limit of 8 
    instruction pairs per pass.
        # pair #1
        "DOT3 r2.rgb, r0, r3;"
        "MUL  r1.a,   r0, r2;"
        # pair #2
        "SUB  r4.r,   r0, r3;"
        "MUL  r6.a,   r0, r2;"
        # (implicit) pair #3
        "SUB  r4.rgba, r0, r3;"
        # (implicit) pair #4
        "ADD  r4.ba, r0, r3;"
        # (implicit) pair #5
        "DOT4 r5, r2, r3;"
    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.  In other words,
    if an alpha instruction refers to a temporary register ("rX") that
    was written by it's paired color instruction, then the value of
    that register used by the alpha instruction will be the value
    before the color instruction was executed.
    For instance, consider the following color alpha pairing:
        "SUB  r4.rgb, r0, r3;"
        "MUL  r6.a,   r4, r2;"  # MUL instruction will use the value
                                # in r4 that r4 had before SUB
                                # instruction was issued.
    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.
    Note that a given register can only be used as a destination
    at most once during the <initRegSequence> of each pass.  In other
    words, a program may not initialize the same register twice in
    one pass using the PassTexCoord or SampleMap instructions.  Writing
    to the same register by the <aluSequence> instructions is quite
    legal, however.
    The first instructions specified in each pass of a program are "free"
    instructions in that they don't count against the 8 instructions
    available in each pass.  They are routing instructions that specify
    from where the contents of the registers come.   They are specified
    with the "SampleMap" and "PassTexCoord" tokens.
    The token sequence
      "PassTexCoord <initRegDst> <initRegSrc>;"
    specifies that the value present in <initRegSrc> is passed directly 
    into the contents of <initRegDst> (one of the registers "rX").  
    This value is then available for use as a source argument to 
    subsequent color and alpha instructions following in the same pass.  
    <initRegSrc> may either be the texture coordinates on a texture unit 
    ("tX"), or in the case of a two-pass program's second pass, it may 
    be the value of a register set in the first pass ("rX").
    Note that in order to preserve the contents of a register from the
    first pass to the second, there must be a "PassTexCoord"
    instruction in the setup for the second pass that assigns that
    register to itself.  For example:
      "StartOutputPass;"
      "PassTexCoord r1, r1.str;"
      etc.
    will preserve the first 3 components of "r1" for use in the
    second pass.
    The token sequence
      "SampleMapATI <initRegDst> <initRegSrc>;"
    specifies that the value present in the texture data bound on the
    unit associated with <initRegDst> will be written to that register.  
    A value for <initRegDst> of "rX" means that the actively bound 
    texture on texture unit X will be sampled, and the result written to 
    "rX". The <initRegSrc> parameter specifies which texture coordinate
    interpolator is used to sample the map.  A value of "rX" for
    <initRegSrc> in the second pass of a two-pass program will do 
    dependent texture read sampling using the value in register X.
    Otherwise, specifying "tX" will sample the map using the texture 
    coordinates on unit X.
    Only the first 3 components of <initRegSrc> are used in 
    "PassTexCoord" and "SampleMap".  As such, it is necessary to 
    identify which 3 components are to be used.  To do so, one can append
    a component selection operator on to the end of the <initRegSrc> 
    This parameter was called a swizzle in ATI_fragment_shader and is
    referred to by the <threeTupleSelect> token in the
    ATI_text_fragment_shader grammar.  This 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 (division by the q component) 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
      -------    -----------------------------   -----------------------
      "str"      (s, t, r, undefined)            (s, t, r, undefined)
      "stq"      (s, t, q, undefined)            (s, t, q, undefined)
      "str_dr"   (s/r, t/r, 1/r, undefined)      (undefined)
      "stq_dq"   (s/q, t/q, 1/q, undefined)      (undefined)
         Table 3.20 Coordinate swizzles
    For example, a fragment program could specify
        "PassTexCoord r1, r1.str;"
        or
        "SampleMap    r1, t2.stq_dq;"
    Each texture coordinate source ("tX") used as a <initRegSrc> can 
    only draw upon "str" or "stq" components throughout the program.  
    For example, if "t2" is used in a SampleMapATI as "t2.str", it 
    cannot be used again later as "t2.stq".  The projection, however, 
    may vary.  That is, it would be okay to later use "t2.str_dr".
    Additionally, when the <initRegSrc> is a register (in the second 
    pass of a two-pass program), only "str" and "str_dr" 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 <initRegDst> becomes undefined.
    The color and alpha instructions are divided into unary, binary, and
    ternary instructions depending upon the number of arguments
    each instruction requires.
    Unary instructions have the form:
      <op> <dst>, <a1>;
    Unary instructions include:
      "MOV"
    Binary instructions have the form:
      <op> <dst>, <a1>, <a2>;
    Binary instructions include:
      "ADD"
      "MUL"
      "SUB"
      "DOT3"
      "DOT4"
    Ternary instructions have the form:
      <op> <dst>, <a1>, <a2>, <a3>;
    Ternary instructions include:
      "MAD"
      "LERP"
      "CND"
      "CND0"
      "DOT2ADD"
    Table 3.21 shows the effect of each <op>.
    R(d), G(d), B(d), and A(d) are the destination component
    values and a1, a2, and a3 represent the source arguments to the
    instruction.
      Op                    Result
      --                    ------
      "ADD"                 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"                 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"                 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"                 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" **             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"                 R(d) = R(a1)
                            G(d) = G(a1)
                            B(d) = B(a1)
                            A(d) = A(a1)
      "CND"                 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"                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)
      "DOT2ADD" *           R(d) = G(d) = B(d) = A(d) = R(a1) * R(a2) +
                                                        G(a1) * G(a2) +
                                                        B(a3)
      "DOT3" *              R(d) = G(d) = B(d) = A(d) = R(a1) * R(a2) +
                                                        G(a1) * G(a2) +
                                                        B(a1) * B(a2)
      "DOT4" * **           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:
           *  - DOT2ADD/DOT3/DOT4 can use an alpha destination mask
                only in combindation with a color destination mask.
                That is, it is illegal to use only a ".a" mask specifier
                on the destination register of these instructions
           ** - If a DOT4 is specified with a destination mask that
                does not include alpha (i.e. ".r", ".rb", "g", etc)
                then the immediately following instruction must write
                at least one color channel and can not use the 
                alpha only destination mask specifier ".a".
          *** - 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 ("rX") the
    result of the instruction is written.
    Each <dst> parameter can optionally have a mask appended to the
    "rX" name, as in "r1.r", or "r3.gb".  The mask parameter 
    specifies which of the color components in <dst> will be written.  
    If there is no mask specified, everything is written, or any of the 
    masks "r", "g", "b", and/or "a" can be added to enable writing the 
    output red, green, blue, and/or alpha channels, respectively.  The 
    masks must be specified in "rgba" order.
    Further, each <dst> parameter can optionally have appended a
    modification parameter, as in "r3.2x" or "r3.half".  These can
    be combined with the mask parameter as in "r4.rg.8x".  The result 
    of an instruction can be modulated by appending *one* of the 
    following: "2x", "4x", "8x", "half", "quarter", or "eighth".  
    These are all mutually exclusive. However, you can optionally add 
    "sat" that clamps the result after any modulation occurs.
    Table 3.22 shows the result of each modification.
      Modifier          Result
      --------          ------
      ""                d = d
      "2x"              d = 2 * d
      "4x"              d = 4 * d
      "8x"              d = 8 * d
      "half"            d = d / 2
      "quarter"         d = d / 4
      "eighth"          d = d / 8
      "sat"             d = clamp(d) to range [0, 1]
         Table 3.22 Result of destination modification
    Note that the internal precision of the fragment program allows
    values in the range [-8, 8].
    The <a1>, <a2>, and <a3 parameters specify the source arguments.  
    The source can come from "rX", "cX", "0", "1", "color0", or "color1",
    where "color0" is the primary fragment color and "color1" is the 
    secondary fragment color.  Note that in a two-pass program, "color0" 
    and "color1" cannot be used in the first pass of the program.
    Each source argument can be given a single optional replication
    parameter that specifies the replication of each component.
    Table 3.23 shows the result of each source replication modifier.
      Replication             Result
      -----------             -----
      ""                      R(s) = R(s)
                              G(s) = G(s)
                              B(s) = B(s)
                              A(s) = A(s)
      "r"                     R(s) = R(s)
                              G(s) = R(s)
                              B(s) = R(s)
                              A(s) = R(s)
      "g"                     R(s) = G(s)
                              G(s) = G(s)
                              B(s) = G(s)
                              A(s) = G(s)
      "b"                     R(s) = B(s)
                              G(s) = B(s)
                              B(s) = B(s)
                              A(s) = B(s)
      "a"                     R(s) = A(s)
                              G(s) = A(s)
                              B(s) = A(s)
                              A(s) = A(s)
         Table 3.23 Result of source replication
    Note that the GL secondary color is specified to contain red,
    green, and blue components only.  It is therefore illegal to specify
    a program which requires the use of the alpha component of the 
    "color1" parameters.  This means that using "color1.a" source argument
    replication would be prohibited.  Additionally, issuing an alpha
    operation using the alpha component of "color1", either implicitly
    or explicitly would also be prohibited.
    
    For instance, the following statements would all be illegal:
      "MOV r0, color1;      # implicit alpha op in pair                  "
      "MOV r0.ra, color1;   # explicit alpha op in pair                  "
      "MOV r0.a, color1;    # explicit single alpha op                   "
      "MOV r0.rgb, color1.a # can't replicate non-existent alpha channel "
    On the other hand, both of these are legal:
      "MOV r0.rgb, color1;  # explicit color op, no alpha op specified   "
      "MOV r0, color1.g     # non-alpha component replicated on src      "
    Each argument can also be given an optional modification parameter
    that specifies modifiers to each component.  Any or all of the
    following can be specified  "neg", "comp", "bias", "2x".
    Table 3.24 shows the result of each source modifier.
      Modifier          Result
      --------          ------
      ""                s = s
      "neg"             s = -s
      "comp"            s = 1 - s
      "bias"            s = s - 0.5
      "2x"              s = 2 * s
         Table 3.24 Result of source modification
    If multiple source modifiers are applied, the order of operations is
    "comp", "bias", "2x", 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 program
    instructions, the following entry points (identical to those in
    the pending ARB_vertex_program extension) are used:
    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 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);
    The <target> must be TEXT_FRAGMENT_SHADER_ATI. The <index> specifies
    the number of the parameter to update.  For ATI_text_fragment_shader,
    <index> is limited to the range 0 to 7.  Note that this does *not*
    necessarily correspond to the "X" in the constant named "cX",
    but rather to the parameter index (env or local) to which "cX" is
    bound in the constant declaration block at the beginning of the
    program.  For instance, if constant "c1" is bound as follows:
    
        "StartConstants;                      "
        "    CONSTANT c1 = program.local[3];  "
        "EndConstants;                        "
    
    then to set the value of constant "c1", to the vector value of
    { 0.4, 0.0, 0.5, 0.25), the application could call
    
        glProgramLocalParameter4dARB(TEXT_FRAGMENT_SHADER_ATI, // target
                                     3,                        // index
                                     0.4,                      // x
                                     0.0,                      // y
                                     0.5,                      // z
                                     0.25);                    // w
    
    The <params> pointer, must contain four floating point values in 
    the range [0, 1] to set the components of the constant.  Similarly, 
    the <x>, <y>, <z>, and <w> parameters must also be in the range 
    [0,1].  Constant registers loaded with floating point values 
    outside of this range will have undefined values.
    
    Note that binding a program constant to a literal string constant
    within the program text is roughly analogous to 
    ATI_fragment_shader's use of the call to SetFragmentShaderConstant
    within a BeginFragmentShader/EndFragmentShader pair.  That is, the
    constant value can not be changed without respecifying the program
    and the program constant value is local to the program.
    
    Binding a program constant to a program environment parameter is 
    roughly analogous to ATI_fragment_shader's use of a call to 
    SetFragmentShaderConstant outside of a BeginFragmentShader / 
    EndFragmentShader pair.  That is, the program constant's value can 
    be changed without redefining the program and the program constant
    value is global to all programs with a binding to that specific 
    program environment parameter.
    
    Binding a program constant to a program local parameter has no
    direct analogue in ATI_fragment_shader as it represents a way
    to specify a program parameter which is local to a given
    fragment program object, but allows the parameter's value to
    be changed without redefining the fragment program itself.
    
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)
    None
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
New State
                                                 Initial
    Get Value                 Type  Get Command  Value    Description             Sec.    Attribute
    ---------                 ----  -----------  -------  -----------             ------  ---------
    TEXT_FRAGMENT_SHADER_ATI   B    IsEnabled    False    Fragment shader enable  3.8.11  enable
    Table X.6.  New Accessible State Introduced by ATI_text_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 original ATI_fragment_shader spec included some deprecated
    functionality for determining implementation-dependent constants
    and limits.  Since that functionality was deprecated to the
    point where those queries are specified to return fixed values, and
    most of the limits are specified by the fragment program grammar,
    those queries are not included in the ATI_text_fragment_shader
    extension.
Sample Usage
-----------------------------------------------------
    # The following program shows how to perform a simple modulation
    # between the interpolated color and a single texture:
    !!ATIfs1.0
    StartOutputPass;
        SampleMap r0, t0.stq_dq; #sample the texture
        
        MUL r0, r0, color0;      #perform the modulation
    EndPass;
-----------------------------------------------------
    # The following program shows how to use the constant
    # declaration block in a fragment program.
    !!ATIfs1.0
    
    StartConstants;
        CONSTANT c0 = program.env[0];
        CONSTANT c1 = program.local[3];
        CONSTANT c2 = { 1.0, 0.0, 0.5, 0.75 };
    EndConstants;
    StartOutputPass;
        MUL r2, c1, c0;  # multiply global param by local param
        ADD r0, c2, r0;  # add constant param and put result in r0
    EndPass;
-----------------------------------------------------
    # The following is an example that performs bumped
    # cubic environment mapping:
    !!ATIfs1.0
    StartPrelimPass;
        PassTexCoord r0, t0.str;    # 1st row of 3x3 basis matrix
        PassTexCoord r1, t1.str;    # 2nd row of 3x3 basis matrix
        PassTexCoord r2, t2.str;    # 3rd row of 3x3 basis matrix
        PassTexCoord r3, t3.str;    # Eye vector
        SampleMap    r4, t5.str;    # Sample normal map
        # Three dot products transform from tangent space to cube map space
        DOT3 r0.r, r0, r4;
        DOT3 r0.g, r1, r4;
        DOT3 r0.b, r2, r4;
        DOT3 r2.2x, r0,     r3;      # 2 * (N dot Eye)
        MUL  r2,    r0,     r2;      # 2 * N * (N dot Eye)
        DOT3 r1,    r0,     r0;      # N dot N
        MAD  r1,    r3.neg, r1, r2;  # 2 * N * (N dot Eye) - Eye * (N dot N)
    EndPass;
    StartOutputPass;
        SampleMap r0, r0.str;        # Sample diffuse cubic env map
        SampleMap r1, r1.str;        # Sample specular cubic env map
        SampleMap r2, t5.str;        # Sample the base map (gloss in a)
        MUL r0, r0, r2;              # diffuse * base
        MAD r0, r0, r2.a, r1;        # (diffuse * base) + (spec * gloss)
    EndPass;
-----------------------------------------------------
    # Chrome shader from ATIRadeon8500_PointLight_Shader demo
    !!ATIfs1.0
    StartPrelimPass;
        # get the outputs from the vertex shader
        PassTexCoord r1, t1.str;    # N
        PassTexCoord r2, t2.str;    # light to vtx vector in light space
        PassTexCoord r3, t3.str;    # H
        SampleMap    r4, t4.str;    # L  (sample cubemap normalizer)
        DOT3 r4, r1, r4.2x.bias;    # reg4 = N.L
        DOT3 r1, r1, r3;            # reg1 = N.H
        DOT3 r1.g, r3, r3;          # reg1(green) = H.H  aka |H|^2)
        DOT3 r2, r2, r2;            # reg2 = |light to vertex|^2
    EndPass;
    StartOutputPass;
        SampleMap    r0, t5.str;   # sample env map using eye vector
        SampleMap    r2, r2.str;   # sample atten map
        SampleMap    r3, r1.str;   # sample spec NHHH map = (N.H)^256
        PassTexCoord r4, r4.str;   # pass N.L through
        # this ensures a pixel is only lit if facing the light
        # (since the spec exp makes negative N.H positive 
        # we must do this)
        MUL r3, r3, r4;             # reg3 = ((N.H)^256 *  N.L)
        MUL r3, r0, r3;             # reg3 = spec * env map
        MUL r4, r0, r4;             # reg4 = diff * env map
        ADD r0, r3, r4;             # reg0 = ((spec * env map) + diff * env map)
        MUL r0.sat, r0, r2.r;       # apply point light attenuation
    EndPass;
-----------------------------------------------------
    # Rusty shader from ATIRadeon8500_PointLight_Shader demo
    !!ATIfs1.0
    StartPrelimPass;
        # get the outputs from the vertex shader
        SampleMap r1, t0.str;    # N from bump map
        PassTexCoord r2, t2.str; # light to vertex vector in light space  
        PassTexCoord r3, t3.str; # H
        SampleMap r4, t4.str;    # L (sample cubemap normalizer)
        SampleMap r5, t0.str;    # specular map (provides our k term for computing N.H^k)
        
        DOT3 r4, r1.2x.bias, r4.2x.bias; # reg4 = N.L
        DOT3 r1, r1.2x.bias, r3;         # reg1 = N.H
        MUL  r1, r1, r1;                 # reg1 = N.H * N.H = (N.H)^2
        DOT3 r1.b, r3, r3;               # reg1(blue) = H.H = |H|^2
        MUL  r1.g.half, r1.b, r5;        # reg1(green) = |H|^2 * 0.5 * k
        DOT3 r2, r2, r2;                 # reg2 = |light to vertex|^2
    EndPass;
    
    StartOutputPass;
        SampleMap r0, t0.str;    # base map
        SampleMap r2, r2.str;    # attenuation
        # note the swizzle (str_DR) because we devide by R we get the following:
        # <(N.H)^2, |H|^2 * 0.5 * k> / |H|^2 = <(N.H)^2/|H>H|^2, 0.5 * k>
        # note that N.H^2 / |H|^2 effectively takes care of the denormalized H term
        # and reduces to N.H^2 also note that raising this to the (0.5*k) power
        # results in (N.H)^k     ... it's a little tricky but it works and now you
        # get per pixel specular lighting with per pixel k exponents!
        SampleMap r3, r1.str_dr; # (N.H)^k
        PassTexCoord r4, r4.str; # N.L
        # reg3 = (N.H)^k * (N.L) 
        # this ensures a pixel is only lit if facing the light 
        # (since the specular exponent makes negative N.H look positive, 
        # we must do this)
        MUL r3, r3, r4;
        
        MUL r3, r0, r3;       # reg3 = specular * basemap
        MUL r4, r0, r4;       # reg4 = diffuse * basemap
        ADD r0, r3, r4;       # reg0 = specular + diffuse
        MUL r0.sat, r0, r2.r; # apply attenuation
    EndPass;
-----------------------------------------------------
Revision History
    Date: 9/5/2002
    Revision: 1.0.10
      - final version for submission to registry
      - clarified contact/contributor info
      - fixed a misplaced ".half" typo in the rusty shader example 
        code
    Date: 8/9/2002
    Revision: 1.0.9
      - fixed a typo which refered to "color1" and "color2" instead of
        "color0" and "color1"
      - clarified semantic restrictrions surrounding DOT2ADD/DOT3/DOT4
        to make them slightly less restrictive and more closely aligned 
        with underlying hardware implementation and original 
        ATI_fragment_shader restrictions.
    Date: 7/9/2002
    Revision: 1.0.8
      - fixed a typo where constant declarations were missing the
        "CONSTANT" keyword
    Date: 6/26/2002
    Revision: 1.0.7
      - clarified additional semantic constraints regarding
        pass delimiters (prelim pass must have at least one ALU op)
      - fixed a typo in the rusty shader example code
      - clarified error conditions involving the use of the alpha
        component of the secondary color parameter.
    Date: 6/23/2002
    Revision: 1.0.6
      - Very minor spec bug fixes:
      - removed _ATI from several instructions
      - fixed up some wrong line wrappings
      - formally listed the <optionalDstMask> options to disallow 
        masks of the form ".r.g.b.a." which were never really legal,
        but were allowed by the grammar as specified before.
      - cleaned up the list of GL functions which accept
        TEXT_FRAGMENT_SHADER_ATI as an enumerant.
      - formally defined the value of TEXT_FRAGMENT_SHADER_ATI
      - fixed 2 typos in the "simple modulation" sample shader
        (SampleMap uses the r# to choose the texture unit,
         and make sure to use the stq_dq source selector)
      - removed an ambiguous "1.0" from the example code on
        how to set a constant bound to a program local parameter.
    Date: 6/6/2002
    Revision: 1.0.5
      - Apple would now like the program local/env syntax added
        in version 1.0.3 added back in to fit better into their
        "pipeline program" based architecture and program token
        stream syntax.  Adding back in the changes introduced
        in version 1.0.3.
      - Fixed a typo in the description of constant binding syntax
        where text referred to "c4" but the sample code referred
        to "c1". "c1" is correct.
      - Synced spec with version 1.4 and 1.5 of ATI_fragment_shader
        1.5: Added interaction with ARB_shadow.
        1.4: Specified that LERP's blend factor must be in the range 
             [0,1].
    Date: 5/31/2002
    Revision: 1.0.4
      - To get the equivalent functionality to ATI_fragment_shader,
        we only need inline constants and program env parameters,
        So,based on some feedback from Apple, for simplicity, we remove 
        the usage of program locals that was added in 1.0.3 .
        We keep program env parameters however.
    Date: 5/31/2002
    Revision: 1.0.3
      - added in the ability to declare constants as
        program local/env parameters as in ARB_vertex_program
      - added in the ability to declare constants as textual
        string constants.
      - above changes required additional "constant declaration"
        block before the preliminary pass block, in order to
        specify the program constant bindings.
      - changed some tokens in the grammar to add the word
        optional (they were already optional, just changed the name).
      - fixed a reference in the text where "2x" was called "scale"
      - fixed a bug in the grammar where it was possible to specify the
        "." of a <dstMask> (now <optionalDstMask>) without specifying
        the "r","g","b", or "a" mask values.
      
    Date: 5/26/2002
    Revision: 1.0.2
      - some spec language english grammatical fixes
      - cleaned up description in usage guidelines to refer
        to tokens named in the text grammar
      - reordered semantic restriction summary to correspond to
        order of explanations in following section.
      - clarify that ATI_text_fragment_shader does not
        replace color sum stage, (neither did ATI_fragment_shader).
      - pulled "!!ATIfs1.0" header token from grammar and simply
        required it to identify the subsequent language as
        was done for ARB_vertex_program, version 24.
      - clarified that the restriction on using a destination
        register once in a singe pass applies only to 
        the PassTexCoord and SampleMap instructions.
    Date: 5/23/2002
    Revision: 1.0.1
      - added back in the concept of color/alpha pairing that was
        removed in the first pass at the extension grammar
        This lets color and alpha instructions be co-issued and
        gives a program the opportunity to do different operations
        on color and alpha components.
        This feature of ATI_fragment_shader should not have been removed
        in the original ATI_text_fragment_shader spec.
      - add commas between instruction arguments in the grammar and
        examples
      - clean up some white space issues
      - add a couple of references to TEXT_FRAGMENT_SHADER_ATI as
        the target of the entry points shared with ARB_vertex_program.
    Date: 5/22/2002
    Revision: 1.0
      - first fully specified version
      - based on the 1.3 version of ATI_fragment_shader specification
Implementation Support
   List of OpenGL implementations supporting the GL_ATI_text_fragment_shader extension
Original File
   Original text file for the GL_ATI_text_fragment_shader extension
Page generated on Sun Nov 20 18:40:33 2005