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 parameter of Enable, Disable, and IsEnabled, and by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: FRAGMENT_SHADER_ATI 0x8920 Accepted by the and parameters of ColorFragmentOp[1..3]ATI and AlphaFragmentOp[1..3]ATI, and by the and parameters of PassTexCoordATI, and by the and 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 parameter of SetFragmentShaderConstantATI and the 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 parameter of ColorFragmentOp1ATI and AlphaFragmentOp1ATI: MOV_ATI 0x8961 Accepted by the parameter of ColorFragmentOp2ATI and AlphaFragmentOp2ATI: ADD_ATI 0x8963 MUL_ATI 0x8964 SUB_ATI 0x8965 DOT3_ATI 0x8966 DOT4_ATI 0x8967 Accepted by the parameter of ColorFragmentOp3ATI and AlphaFragmentOp3ATI: MAD_ATI 0x8968 LERP_ATI 0x8969 CND_ATI 0x896A CND0_ATI 0x896B DOT2_ADD_ATI 0x896C Accepted by the parameter of ColorFragmentOp[1..3]ATI and AlphaFragmentOp[1..3]ATI: ZERO ONE PRIMARY_COLOR_ARB SECONDARY_INTERPOLATOR_ATI 0x896D Accepted by the parameter of SampleMapATI and the parameter of PassTexCoordATI: TEXTURE0_ARB TEXTURE1_ARB TEXTURE2_ARB TEXTURE3_ARB TEXTURE4_ARB TEXTURE5_ARB TEXTURE6_ARB TEXTURE7_ARB Accepted by the 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 parameter of ColorFragmentOp[1..3]ATI: NONE RED_BIT_ATI 0x00000001 GREEN_BIT_ATI 0x00000002 BLUE_BIT_ATI 0x00000004 Accepted by the parameter of ColorFragmentOp[1..3]ATI and AlphaFragmentOp[1..3]ATI: NONE RED GREEN BLUE ALPHA Accepted by the 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 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 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 is the name to be deleted. Unique names can be generated using: uint GenFragmentShadersATI(uint range); where is the number of contiguous ids that should be created. It returns an integer n such that contiguous empty shader ids, with values n, n+1, ..., n+-1, are created. If is 0, if there is no group of 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 is passed directly into the contents of (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. 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 will be written to that register. A value for of REG_x_ATI means that TEXTUREx_ARB will be sampled, and the result written to REG_x_ATI. The parameter specifies which texture coordinate interpolator is used to sample the map. A value of REG_x_ATI for 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 or 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 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 and/or can only draw upon STR or STQ components throughout the shader. For example, if TEXTURE2_ARB is used in a SampleMapATI with SWIZZLE_STR_ATI, it cannot be used again later with a of SWIZZLE_STQ_ATI. The projection, however, may vary. It would be okay to later use TEXTURE2_ARB with a of SWIZZLE_STR_DR_ATI. Additionally, when the or 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 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 parameter specifies the instruction to perform on the sources. Table 3.21 shows the effect of each . 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 . ** - 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 parameter specifies to which register (REG_x_ATI) the result of the instruction is written. The parameter specifies which of the color components in 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 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 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 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 parameter which specifies the replication of each component. Table 3.23 shows the result of each 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 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 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 parameter specifies which of the constants (CON_x_ATI) to set. The 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 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 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 register is specified twice in the same pass. The error INVALID_OPERATION is generated by PassTexCoordATI or SampleMapATI if passed to PassTexCoordATI or passed to SampleMapATI is a register in the first pass, or a register with SWIZZLE_STQ_ATI or SWIZZLE_STQ_DQ_ATI in the second pass, or if different parameters are specified for the same or 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 is SECONDARY_INTERPOLATOR_ATI and is ALPHA, or by AlphaFragmentOp[1..3]ATI if is SECONDARY_INTERPOLATOR_ATI and is ALPHA or NONE, or by ColorFragmentOp2ATI if is DOT4_ATI and is SECONDARY_INTERPOLATOR_ATI and is ALPHA or NONE. The error INVALID_OPERATION is generated by ColorFragmentOp3ATI or AlphaFragmentOp3ATI if all three parameters are constants, and all three are different. The error INVALID_OPERATION is generated by AlphaFragmentOp[2..3]ATI if is DOT3_ATI, DOT4_ATI, or DOT2_ADD_ATI and there was no matching ColorFragmentOp[2..3]ATI immediately preceding, or if is not DOT4_ATI and the immediately preceding ColorFragmentOp2ATI specifies an of DOT4_ATI. The error INVALID_ENUM is generated if 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 passed to PassTexCoordATI or 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 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 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 to SampleMapATI or 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 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 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 parameter instead of . - Changed MAD_ATI from (a + b * c) to (a * b + c). Date: 6/11/2001 Revision: 0.4 - Removed FRAC_ATI. - Added 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 to . - 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 from ColorFragmentOp[1..3]ATI. - Changed SHADER_ATI to FRAGMENT_SHADER_ATI. - Fixed the '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