Name NV_fragment_program4 Name Strings (none) Contact Pat Brown, NVIDIA Corporation (pbrown 'at' nvidia.com) Status Shipping for GeForce 8 Series (November 2006) Version Last Modified Date: 11/06/2007 NVIDIA Revision: 4 Number 335 Dependencies OpenGL 1.1 is required. NV_gpu_program4 is required. This extension is supported if "GL_NV_gpu_program4" is found in the extension string. ATI_draw_buffers and ARB_draw_buffers trivially affects the definition of this specification. ARB_fragment_program_shadow trivially affects the definition of this specification. NV_primitive_restart trivially affects the definition of this extension. This extension is written against the OpenGL 2.0 specification. Overview This extension builds on the common assembly instruction set infrastructure provided by NV_gpu_program4, adding fragment program-specific features. This extension provides interpolation modifiers to fragment program attributes allowing programs to specify that specified attributes be flat-shaded (constant over a primitive), centroid-sampled (multisample rendering), or interpolated linearly in screen space. The set of input and output bindings provided includes all bindings supported by ARB_fragment_program. Additional input bindings are provided to determine whether fragments were generated by front- or back-facing primitives ("fragment.facing"), to identify the individual primitive used to generate the fragment ("primitive.id"), and to determine distances to user clip planes ("fragment.clip[n]"). Additionally generic input attributes allow a fragment program to receive a greater number of attributes from previous pipeline stages than possible using only the pre-defined fixed-function attributes. By and large, programs written to ARB_fragment_program can be ported directly by simply changing the program header from "!!ARBfp1.0" to "!!NVfp4.0", and then modifying instructions to take advantage of the expanded feature set. There are a small number of areas where this extension is not a functional superset of previous fragment program extensions, which are documented in the NV_gpu_program4 specification. New Procedures and Functions None. New Tokens None. Additions to Chapter 2 of the OpenGL 2.0 Specification (OpenGL Operation) Modify Section 2.X, GPU Programs (insert after second paragraph) Fragment Programs Fragment programs are used to compute the transformed attributes of a fragment, in lieu of the set of fixed-function operations described in sections 3.8 through 3.10. Fragment programs are run on a single fragment at a time, and the state of neighboring fragments is not explicitly available. (In practice, fragment programs may be run on a block of fragments, and neighboring fragments' attributes may be used for texture LOD calculations or partial derivative approximation.) The inputs available to a fragment program are the interpolated attributes of a fragment, which include (among other things) window-space position, primary and secondary colors, and texture coordinates. The results of the program are one (or more) colors and possibly a new window Z coordinate. A fragment program can not modify the (X,Y) location of the fragment. Modify Section 2.X.2, Program Grammar (replace third paragraph) Fragment programs are required to begin with the header string "!!NVfp4.0". This header string identifies the subsequent program body as being a fragment program and indicates that it should be parsed according to the base NV_gpu_program4 grammar plus the additions below. Program string parsing begins with the character immediately following the header string. (add the following grammar rules to the NV_gpu_program4 base grammar) ::= ::= ::= "KIL" | "DDX" "," | "DDY" "," ::= ::= "FLAT" | "CENTROID" | "NOPERSPECTIVE" ::= "fogcoord" | "position" | "facing" | | | | "primitive" "." "id" ::= "color" ::= | | ::= "texcoord" ::= "clip" ::= "attrib" ::= "fragment" "." ::= "color" | "depth" ::= /* empty */ ::= "result" "." (add the following subsection to section 2.X.3.1, Program Variable Types) Explicitly declared fragment program attribute variables may have one or more interpolation modifiers that control how per-fragment values are computed. An attribute variable declared as "FLAT" will be flat-shaded. For such variables, the value of the attribute will be constant over an entire primitive and will taken from the provoking vertex of the primitive, as described in Section 2.14.7. If "FLAT" is not specified, attributes will be interpolated as described in Chapter 3, with the exception that attribute variables bound to colors will still be flat-shaded if the shade model (section 2.14.7) is FLAT. If an attribute variable declared as "FLAT" corresponds to a texture coordinate replaced by a point sprite (s,t) value (section 3.3.1), the value of the attribute is undefined. An attribute variable declared as "CENTROID" will be interpolated using a point on or inside the primitive, if possible, when doing multisample line or polygon rasterization (sections 3.4.4 and 3.5.6). This method can avoid artifacts during multisample rasterization when some samples of a pixel are covered, but the sample location used is outside the primitive. Note that when centroid sampling, the sample points used to generate attribute values for adjacent pixels may not be evenly spaced, which can lead to artifacts when evaluating partial derivatives or performing texture LOD calculations needed for mipmapping. If "CENTROID" is not specified, attributes may be sampled anywhere inside the pixel as permitted by the specification, including at points outside the primitive. An attribute variable declared as "NOPERSPECTIVE" will be interpolated using a method that is linear in screen space, as described in equation 3.7 and the appoximation that follows equation 3.8. If "NOPERSPECTIVE" is not specified, attributes must be interpolated with perspective correction, as described in equations 3.6 and 3.8. When clipping lines or polygons, an alternate method is used to compute the attributes of vertices introduced by clipping when they are specified as "NOPERSPECTIVE" (section 2.14.8). Implicitly declared attribute variables (bindings used directly in a program instruction) will inherit the interpolation modifiers of any explicitly declared attribute variable using the same binding. If no such variable exists, default interpolation modes will be used. For fragments generated by point primitives, DrawPixels, and Bitmap, interpolation modifiers have no effect. Implementations are not required to support arithmetic interpolation of integer values written by a previous pipeline stage. Integer fragment program attribute variables must be flat-shaded; a program will fail to load if it declares a variable with the "INT" or "UINT" data type modifiers without the "FLAT" interpolation modifier. There are several additional limitations on the use of interpolation modifiers. A fragment program will fail to load: * if an interpolation modifier is specified when declaring a non-attribute variable, * if the same interpolation modifier is specified more than once in a single declaration (e.g., "CENTROID CENTROID ATTRIB"), * if the "FLAT" modifier is used together with either "CENTROID" or "NOPERSPECTIVE" in a single declaration, * if any interpolation modifier is specified when declaring a variable bound to a fragment's position, face direction, fog coordinate, or any interpolated clip distance, * if multiple attribute variables with different interpolation modifiers are bound to the same fragment attribute, or * if one variable is bound to the fragment's primary color and a second variable with different interpolation modifiers is bound the the fragment's secondary color. (add the following subsection to section 2.X.3.2, Program Attribute Variables) Fragment program attribute variables describe the attributes of a fragment produced during rasterization. The set of available bindings is enumerated in Table X.X. Most attributes correspond to per-vertex attributes that are interpolated over a primitive; such attributes are subject to the interpolation modifiers described in section 2.X.3.1. The fragment's position, facing, and primitive IDs are the exceptions, and are generated specially during rasterization. Since two-sided color selection occurs prior to rasterization, there are no distinct "front" or "back" colors available to fragment programs. A single set of colors is available, which corresponds to interpolated front or back vertex colors. If geometry programs are enabled, attributes will be obtained by interpolating per-vertex outputs written by the geometry program. If geometry programs are disabled, but vertex programs are enabled, attributes will be obtained by interpolating per-vertex outputs written by the vertex program. In either case, the fragment program attributes should be read using the same component data type used to write the vertex output attributes in the geometry or vertex program. The value of any attribute corresponding to a vertex output not written by the geometry or vertex program is undefined. If neither geometry nor vertex programs are used, attributes will be obtained by interpolating per-vertex values computed by fixed-function vertex processing. All interpolated fragment attributes should be read as floating-point values. Fragment Attribute Binding Components Underlying State -------------------------- ---------- ---------------------------- fragment.color (r,g,b,a) primary color fragment.color.primary (r,g,b,a) primary color fragment.color.secondary (r,g,b,a) secondary color fragment.texcoord (s,t,r,q) texture coordinate, unit 0 fragment.texcoord[n] (s,t,r,q) texture coordinate, unit n fragment.fogcoord (f,-,-,-) fog distance/coordinate * fragment.clip[n] (c,-,-,-) interpolated clip distance n fragment.attrib[n] (x,y,z,w) generic interpolant n fragment.texcoord[n..o] (s,t,r,q) texture coordinates n thru o * fragment.clip[n..o] (c,-,-,-) clip distances n thru o fragment.attrib[n..o] (x,y,z,w) generic interpolants n thru o * fragment.position (x,y,z,1/w) window position * fragment.facing (f,-,-,-) fragment facing * primitive.id (id,-,-,-) primitive number Table X.X: Fragment Attribute Bindings. The "Components" column indicates the mapping of the state in the "Underlying State" column. Bindings containing "[n]" require an integer value of to select an individual item. Interpolation modifiers are not supported on variables that use bindings labeled with "*". If a fragment attribute binding matches "fragment.color" or "fragment.color.primary", the "x", "y", "z", and "w" components of the fragment attribute variable are filled with the "r", "g", "b", and "a" components, respectively, of the fragment's primary color. If a fragment attribute binding matches "fragment.color.secondary", the "x", "y", "z", and "w" components of the fragment attribute variable are filled with the "r", "g", "b", and "a" components, respectively, of the fragment's secondary color. If a fragment attribute binding matches "fragment.texcoord" or "fragment.texcoord[n]", the "x", "y", "z", and "w" components of the fragment attribute variable are filled with the "s", "t", "r", and "q" components, respectively, of the fragment texture coordinates for texture unit . If "[n]" is omitted, texture unit zero is used. If a fragment attribute binding matches "fragment.fogcoord", the "x" component of the fragment attribute variable is filled with either the fragment eye distance or the fog coordinate, depending on whether the fog source is set to FRAGMENT_DEPTH_EXT or FOG_COORDINATE_EXT, respectively. The "y", "z", and "w" coordinates are undefined. If a fragment attribute binding matches "fragment.clip[n]", the "x" component of the fragment attribute variable is filled with the interpolated value of clip distance , as written by the vertex or geometry program. The "y", "z", and "w" components of the variable are undefined. If fixed-function vertex processing or position-invariant vertex programs are used with geometry programs disabled, clip distances are obtained by interpolating the per-clip plane dot product: (p_1' p_2' p_3' p_4') dot (x_e y_e z_e w_e), for clip plane as described in section 2.12. The clip distance for clip plane is undefined if clip plane is disabled. If a fragment attribute binding matches "fragment.attrib[n]", the "x", "y", "z", and "w" components of the fragment attribute variable are filled with the "x", "y", "z", and "w" components of generic interpolant . All generic interpolants will be undefined when used with fixed-function vertex processing with no geometry program enabled. If a fragment attribute binding matches "fragment.texcoord[n..o]", "fragment.clip[n..o]", or "fragment.attrib[n..o]", a sequence of 1+- bindings is created. For texture coordinate bindings, it is as though the sequence "fragment.texcoord[n], fragment.texcoord[n+1], ... fragment.texcoord[o]" were specfied. These bindings are available only in explicit declarations of array variables. A program will fail to load if is greater than . If a fragment attribute binding matches "fragment.position", the "x" and "y" components of the fragment attribute variable are filled with the floating-point (x,y) window coordinates of the fragment center, relative to the lower left corner of the window. The "z" component is filled with the fragment's z window coordinate. If z window coordinates are represented internally by the GL as fixed-point values, the z window coordinate undergoes an implied conversion to floating point. This conversion must leave the values 0 and 1 invariant. The "w" component is filled with the reciprocal of the fragment's clip w coordinate. If a fragment attribute binding matches "fragment.facing", the "x" component of the fragment attribute variable is filled with +1.0 or -1.0, depending on the orientation of the primitive producing the fragment. If the fragment is generated by a back-facing polygon (including point- and line-mode polygons), the facing is -1.0; otherwise, the facing is +1.0. The "y", "z", and "w" coordinates are undefined. If a fragment attribute binding matches "primitive.id", the "x" component of the fragment attribute variable is filled with a single integer. If a geometry program is active, this value is obtained by taking the primitive ID value emitted by the geometry program for the provoking vertex. If no geometry program is active, the value is the number of primitives processed by the rasterizer since the last time Begin was called (directly or indirectly via vertex array functions). The first primitive generated after a Begin is numbered zero, and the primitive ID counter is incremented after every individual point, line, or polygon primitive is processed. For polygons drawn in point or line mode, the primitive ID counter is incremented only once, even though multiple points or lines may be drawn. For QUADS and QUAD_STRIP primitives that are decomposed into triangles, the primitive ID is incremented after each complete quad is processed. For POLYGON primitives, the primitive ID counter is zero. The primitive ID is zero for fragments generated by DrawPixels or Bitmap. Restarting a primitive topology using the primitive restart index has no effect on the primitive ID counter. The "y", "z", and "w" components of the variable are always undefined. (add the following subsection to section 2.X.3.5, Program Results.) Fragment programs produce final fragment values, and the set of result variables available to such programs correspond to the final attributes of a fragment. Fragment program result variables may not be declared as arrays. The set of allowable result variable bindings is given in Table X.X. Binding Components Description ----------------------------- ---------- ---------------------------- result.color (r,g,b,a) color result.color[n] (r,g,b,a) color output n result.depth (*,*,d,*) depth coordinate Table X.X: Fragment Result Variable Bindings. Components labeled "*" are unused. If a result variable binding matches "result.color", updates to the "x", "y", "z", and "w" components of the result variable modify the "r", "g", "b", and "a" components, respectively, of the fragment's output color. If a result variable binding matches "result.color[n]" and the ARB_draw_buffers program option is specified, updates to the "x", "y", "z", and "w" components of the color result variable modify the "r", "g", "b", and "a" components, respectively, of the fragment output color numbered . If the ARB_draw_buffers program option is not specified, the "result.color[n]" binding is unavailable. If a result variable binding matches "result.depth", updates to the "z" component of the result variable modify the fragment's output depth value. If the "result.depth" binding is not in used in a variable written to by any instruction in the fragment program, the interpolated depth value produced by rasterization is used as if fragment program mode is not enabled. Otherwise, the value written by the fragment program is used, and the fragment's final depth value is undefined if the program did not end up writing a depth value due to flow control or write masks. Writes to any component of depth other than the "z" component have no effect. (modify Table X.13 in section 2.X.4, Program Instructions, to include the following.) Modifiers Instruction F I C S H D Inputs Out Description ----------- - - - - - - ---------- --- -------------------------------- DDX X - X X X F v v partial derivative relative to X DDY X - X X X F v v partial derivative relative to Y KIL X X - - X F vc - kill fragment (add the following subsection to section 2.X.5, Program Options.) Section 2.X.5.Y, Fragment Program Options + Fixed-Function Fog Emulation (ARB_fog_exp, ARB_fog_exp2, ARB_fog_linear) If a fragment program specifies one of the options "ARB_fog_exp", "ARB_fog_exp2", or "ARB_fog_linear", the program will apply fog to the program's final color using a fog mode of EXP, EXP2, or LINEAR, respectively, as described in section 3.10. When a fog option is specified in a fragment program, semantic restrictions are added to indicate that a fragment program will fail to load if the number of temporaries it contains exceeds the implementation-dependent limit minus 1, if the number of attributes it contains exceeds the implementation-dependent limit minus 1, or if the number of parameters it contains exceeds the implementation-dependent limit minus 2. Additionally, when the ARB_fog_exp option is specified in a fragment program, a semantic restriction is added to indicate that a fragment program will fail to load if the number of instructions or ALU instructions it contains exceeds the implementation-dependent limit minus 3. When the ARB_fog_exp2 option is specified in a fragment program, a semantic restriction is added to indicate that a fragment program will fail to load if the number of instructions or ALU instructions it contains exceeds the implementation-dependent limit minus 4. When the ARB_fog_linear option is specified in a fragment program, a semantic restriction is added to indicate that a fragment program will fail to load if the number of instructions or ALU instructions it contains exceeds the implementation-dependent limit minus 2. Only one fog application option may be specified by any given fragment program. A fragment program that specifies more than one of the program options "ARB_fog_exp", "ARB_fog_exp2", and "ARB_fog_linear", will fail to load. + Precision Hints (ARB_precision_hint_fastest, ARB_precision_hint_nicest) Fragment program computations are carried out at an implementation- dependent precision. However, some implementations may be able to perform fragment program computations at more than one precision, and may be able to trade off computation precision for performance. If a fragment program specifies the "ARB_precision_hint_fastest" program option, implementations should select precision to minimize program execution time, with possibly reduced precision. If a fragment program specifies the "ARB_precision_hint_nicest" program option, implementations should maximize the precision, with possibly increased execution time. Only one precision control option may be specified by any given fragment program. A fragment program that specifies both the "ARB_precision_hint_fastest" and "ARB_precision_hint_nicest" program options will fail to load. + Multiple Color Outputs (ARB_draw_buffers, ATI_draw_buffers) If a fragment program specifies the "ARB_draw_buffers" or "ATI_draw_buffers" option, it will generate multiple output colors, and the result binding "result.color[n]" is allowed, as described in section 2.X.3.5. If this option is not specified, a fragment program that attempts to bind "result.color[n]" will fail to load, and only "result.color" will be allowed. The multiple color outputs will typically be written to an ordered list of draw buffers in the manner described in the ARB_draw_buffers extension specification. + Fragment Program Shadows (ARB_fragment_program_shadow) The ARB_fragment_program_shadow option introduced a set of "SHADOW" texture targets and made the results of depth texture lookups undefined unless the texture format and compare mode were consistent with the target provided in the fragment program instruction. This behavior is enabled by default in NV_gpu_program4; specifying the option is not illegal but has no additional effect. (add the following subsection to section 2.X.8, Program Instruction Set.) Section 2.X.8.Z, DDX: Partial Derivative Relative to X The DDX instruction computes approximate partial derivatives of the four components of the single floating-point vector operand with respect to the X window coordinate to yield a result vector. The partial derivatives are evaluated at the sample location of the pixel. f = VectorLoad(op0); result = ComputePartialX(f); Note that the partial derivates obtained by this instruction are approximate, and derivative-of-derivate instruction sequences may not yield accurate second derivatives. Note also that the sample locations for attributes declared with the CENTROID interpolation modifier may not be evenly spaced, which can lead to artifacts in derivative calculations. DDX supports only floating-point data type modifiers and is available only to fragment programs. Section 2.X.8.Z, DDY: Partial Derivative Relative to Y The DDY instruction computes approximate partial derivatives of the four components of the single operand with respect to the Y window coordinate to yield a result vector. The partial derivatives are evaluated at the center of the pixel. f = VectorLoad(op0); result = ComputePartialY(f); Note that the partial derivates obtained by this instruction are approximate, and derivative-of-derivate instruction sequences may not yield accurate second derivatives. Note also that the sample locations for attributes declared with the CENTROID interpolation modifier may not be evenly spaced, which can lead to artifacts in derivative calculations. DDY supports only floating-point data type modifiers and is available only to fragment programs. Section 2.X.8.Z, KIL: Kill Fragment The KIL instruction evaluates a condition and kills a fragment if the test passes. A fragment killed by the KIL instruction is discarded, and will not be seen by subsequent stages of the pipeline. A KIL instruction may be specified using either a floating-point vector operand or a condition code test. If a floating-point vector is provided, the fragment is discarded if any of its components are negative: tmp = VectorLoad(op0); if ((tmp.x < 0) || (tmp.y < 0) || (tmp.z < 0) || (tmp.w < 0)) { exit; } If a condition code test is provided, the fragment is discarded if any component of the test passes: if (TestCC(rc.c***) || TestCC(rc.*c**) || TestCC(rc.**c*) || TestCC(rc.***c)) { exit; } KIL supports no data type modifiers. If a vector operand is provided, it must have floating-point components. KIL is available only to fragment programs. Replace Section 2.14.8, and rename it to "Vertex Attribute Clipping" (p. 70). After lighting, clamping or masking and possible flatshading, vertex attributes, including colors, texture and fog coordinates, shader varying variables, and point sizes computed on a per vertex basis, are clipped. Those attributes associated with a vertex that lies within the clip volume are unaffected by clipping. If a primitive is clipped, however, the attributes assigned to vertices produced by clipping are produced by interpolating attributes along the clipped edge. Let the attributes assigned to the two vertices P_1 and P_2 of an unclipped edge be a_1 and a_2. The value of t (section 2.12) for a clipped point P is used to obtain the attribute associated with P as a = t * a_1 + (1-t) * a_2 unless the attribute is specified to be interpolated without perspective correction in a fragment program. In that case, the attribute associated with P is a = t' * a_1 + (1-t') * a_2 where t' = (t * w_1) / (t * w_1 + (1-t) * w_2) and w_1 and w_2 are the w clip coordinates of P_1 and P_2, respectively. If w_1 or w_2 is either zero or negative, the value of the associated attribute is undefined. Additions to Chapter 3 of the OpenGL 2.0 Specification (Rasterization) None Additions to Chapter 4 of the OpenGL 2.0 Specification (Per-Fragment Operations and the Frame Buffer) None Additions to Chapter 5 of the OpenGL 2.0 Specification (Special Functions) None Additions to Chapter 6 of the OpenGL 2.0 Specification (State and State Requests) None Additions to the AGL/GLX/WGL Specifications None Dependencies on ARB_draw_buffers and ATI_draw_buffers If neither ARB_draw_buffers nor ATI_draw_buffers is supported, then the discussion of the ARB_draw_buffers option in section 2.X.5.Y should be removed, as well as the result bindings of the form "result.color[n]" and "result.color[n..o]". Dependencies on ARB_fragment_program_shadow If ARB_fragment_program_shadow is not supported, then the discussion of the ARB_fragment_program_shadow option in section 2.X.5.Y should be removed. Dependencies on NV_primitive_restart The spec describes the behavior that primitive restart does not affect the primitive ID counter, including for POLYGON primitives (where one could argue that the restart index starts a new primitive without a new Begin to reset the count. If NV_primitive_restart is not supported, references to that extension in the discussion of the "primitive.id" attribute should be removed. Errors None New State None New Implementation Dependent State None Issues (1) How should special interpolation controls be specified? RESOLVED: As a special modifier to fragment program attribute variable declarations. It was decided that the fragment program was the most natural place to put the control. This wouldn't require making a large number of related state changes controlling interpolation whenever the fragment program used. The final mechanism using special interpolation modifiers was chosen because it fit well with the other variable modifiers (for data storage size and data type) provided by NV_gpu_program4. Examples: FLAT ATTRIB texcoords[4] = { fragment.texcoord[0..3] }; CENTROID ATTRIB texcoord4 = fragment.texcoord[4]; CENTROID NOPERSPECTIVE ATTRIB attribs[3] = { fragment.attrib[0..2] }; There were a variety of options considered, including: * special declarations in vertex or geometry programs to specify the interpolation type, * special declarations in the fragment program to specify one or more interpolation type modifiers per binding, such as: INTERPOLATE fragment.texcoord[0..3], FLAT; INTERPOLATE fragment.texcoord[4], CENTROID; INTERPOLATE fragment.attrib[0..2], CENTROID, NOPERSPECTIVE; * fixed-function state specifying the interpolation mode glInterpolateAttribNV(GL_TEXTURE0, GL_FLAT); glInterpolateAttribNV(GL_GENERIC_ATTRIB0, GL_CENTROID_NV); Recent updates to GLSL provide similar functionality (for centroid) with a similar approach, using a modifier on varying variable declarations. (2) How should perspective-incorrect interpolation (linear in screen space) and clipping interact? RESOLVED: Primitives with attributes specified to be perspective-incorrect should be clipped so that the vertices introduced by clipping should have attribute values consistent with the interpolation mode. We do not want to have large color shifts introduced by clipping a perspective-incorrect attribute. For example, a primitive that approaches, but doesn't cross, a frustum clip plane should look pretty much identical to a similar primitive that just barely crosses the clip plane. Clipping perspective-incorrect interpolants that cross the W==0 plane is very challenging. The attribute clipping equation provided in the spec effectively projects all the original vertices to screen space while ignoring the X and Y frustum clip plane. As W approaches zero, the projected X/Y window coordinates become extremely large. When clipping an edge with one vertex inside the frustum and the other out near infinity (after projection, due to W approaching zero), the interpolated attribute for the entire visible portion of the edge should almost exactly match the attribute value of the visible vertex. If an outlying vertex approaches and then goes past W==0, it can be said to go "to infinity and beyond" in screen space. The correct answer for screen-linear interpolation is no longer obvious, at least to the author of this specification. Rather than trying to figure out what the "right" answer is or if one even exists, the results of clipping such edges is specified as undefined. (3) If a shader wants to use interpolation modifiers without using declared variables, is that possible? RESOLVED: Yes. If "dummy" variables are declared, all interpolants bound to that variable will get the variable's interpolation modifiers. In the following program: FLAT ATTRIB tc02[3] = { fragment.texcoord[0..2] }; MOV R0, fragment.texcoord[1]; MOV R1, fragment.texcoord[3]; The variable R0 will get texture coordinate set 1, which will be flat-shaded due to the declaration of "tc02". The variable R1 will get texture coordinate set 3, which will be smooth shaded (default). (4) Is it possible to read the same attribute with different interpolation modifiers? RESOLVED: No. A program that tries to do that will fail to compile. (5) Why can't fragment program results be declared as arrays? RESOLVED: This is a limitation of the programming model. If an implementation needs to do run-time indexing of fragment program result variables (effectively writing to "result.color[A0.x]"), code such as the following can be used: TEMP colors[4]; ... MOV colors[A0.x], R1; MOV colors[3], 12.3; ... # end of the program MOV result.color[0], colors[0]; MOV result.color[1], colors[1]; MOV result.color[2], colors[2]; MOV result.color[3], colors[3]; (6) Do clip distances require that the corresponding clip planes be enabled to be read by a fragment program? RESOLVED: No. (7) How do primitive IDs work with fragment programs? RESOLVED: If a geometry program is enabled, the primitive ID is consumed by the geometry program and is not automatically available to the fragment program. If the fragment program needs a primitive ID in this case, the geometry program can write out a primitive ID using the "result.primid" binding, and the fragment program will see the primitive ID written for the provoking vertex. If no geometry program is enabled, the primitive ID is automatically available, and specifies the number of primitives (points, lines, or triangles) processed by since the last explicit or implicit Begin call. (8) What is the primitive ID for non-geometry commands that generate fragments, such as DrawPixels, Bitmap, and CopyPixels. RESOLVED: Zero. (9) How does the FLAT interpolation modifier interact with point sprite coordinate replacement? RESOLVED: The value of such attributes are undefined. Specifying these two operations together is self-contradictory -- FLAT asks for an interpolant that is constant over a primitive, and point sprite coordinate interpolation asks for an interpolant that is non-constant over a point sprite. Revision History Rev. Date Author Changes ---- -------- -------- -------------------------------------------- 4 11/06/07 pbrown Documented interaction between the FLAT interpolation modifier and point sprite coordinate replacement. 1-3 pbrown Internal spec development.