Name ATI_text_fragment_shader Name Strings GL_ATI_text_fragment_shader Contributors Bob Beretta, Apple Computer Dan Ginsburg, AMD Evan Hart, NVIDIA Benj Lipchak, AMD James McCombe, Apple Computer Jason Mitchell and contributors to the ARB_vertex_program working group, the product of which provided the API for program specification and object management. Contact Benj Lipchak, AMD (benj.lipchak 'at' amd.com) Jeremy Sandmel, Apple Computer (jsandmel 'at' apple.com) Status Shipping on MacOS X, version 10.2 Version Last Modified Date: November 4, 2006 Author Revision: 1.0.11 (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 New Procedures and Functions 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 New Tokens Accepted by the parameter of Disable, Enable, and IsEnabled, and by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev, and by the 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 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. ::= ::= "" | "StartConstants" ";" "EndConstants" ";" ::= | "" ::= "CONSTANT" "=" ";" ::= | | ::= "program" "." "env" "[" "]" ::= from 0 to 7 ::= "program" "." "local" "[" "]" ::= from 0 to 7 ::= "{" "}" | "{" "," "}" | "{" "," "," "}" | "{" "," "," "," "}" ::= "" | "StartPrelimPass" ";" "EndPass" ";" ::= "" | "StartOutputPass" ";" "EndPass" ";" ::= | "" ::= ";" ::= "PassTexCoord" | "SampleMap" ::= ::= | ::= | "" ::= ";" | ";" | ";" ::= ::= "," ::= "," "," ::= ::= "" | "." "r" | "." "g" | "." "rg" | "." "b" | "." "rb" | "." "gb" | "." "rgb" | "." "a" | "." "ra" | "." "ga" | "." "rga" | "." "ba" | "." "rba" | "." "gba" | "." "rgba" ::= ::= "" | "." "2x" | "." "4x" | "." "8x" | "." "half" | "." "quarter" | "." "eighth" ::= "." "sat" ::= ::= ::= | | | ::= "" | "." "r" | "." "g" | "." "b" | "." "a" ::= "" | ::= "" | "." "neg" ::= "" | "." "2x" ::= "" | "." "bias" ::= "" | "." "comp" ::= "t0" | "t1" | "t2" | "t3" | "t4" | "t5" ::= "." "str" | "." "stq" | "." "str_dr" | "." "stq_dq" ::= "r0" | "r1" | "r2" | "r3" | "r4" | "r5" ::= "c0" | "c1" | "c2" | "c3" | "c4" | "c5" | "c6" | "c7" ::= "0" | "1" ::= "color0" | "color1" ::= "MOV" ::= "ADD" | "MUL" | "SUB" | "DOT3" | "DOT4" ::= "MAD" | "LERP" | "CND" | "CND0" | "DOT2ADD" The rule matches an integer constant. The integer consists of a sequence of one or more digits ("0" through "9"). The 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 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 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 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 ;" specifies that the value present in is passed directly into the contents of (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. 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 ;" specifies that the value present in the texture data bound on the unit associated with will be written to that register. A value for of "rX" means that the actively bound texture on texture unit X will be sampled, and the result written to "rX". The parameter specifies which texture coordinate interpolator is used to sample the map. A value of "rX" for 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 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 This parameter was called a swizzle in ATI_fragment_shader and is referred to by the 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 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 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 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 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: , ; Unary instructions include: "MOV" Binary instructions have the form: , , ; Binary instructions include: "ADD" "MUL" "SUB" "DOT3" "DOT4" Ternary instructions have the form: , , , ; Ternary instructions include: "MAD" "LERP" "CND" "CND0" "DOT2ADD" Table 3.21 shows the effect of each . 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 parameter specifies to which register ("rX") the result of the instruction is written. Each 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 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 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 , , and must be TEXT_FRAGMENT_SHADER_ATI. The specifies the number of the parameter to update. For ATI_text_fragment_shader, 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 pointer, must contain four floating point values in the range [0, 1] to set the components of the constant. Similarly, the , , , and 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: 11/4/2006 Revision: 1.0.11 - Updated contact info after ATI/AMD merger. 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 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 (now ) 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