Name NV_geometry_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/2006 NVIDIA Revision: 6 Number 323 Dependencies OpenGL 1.1 is required. This extension is written against the OpenGL 2.0 specification. NV_gpu_program4 is required. This extension is supported if "GL_NV_gpu_program4" is found in the extension string. EXT_framebuffer_object interacts with this extension. EXT_framebuffer_blit interacts with this extension. EXT_texture_array interacts with this extension. ARB_texture_rectangle trivially affects the definition of this extension. EXT_texture_buffer_object trivially affects the definition of this extension. NV_primitive_restart trivially affects the definition of this extension. Overview NV_geometry_program4 defines a new type of program available to be run on the GPU, called a geometry program. Geometry programs are run on full primitives after vertices are transformed, but prior to flat shading and clipping. A geometry program begins with a single primitive - a point, line, or triangle. Quads and polygons are allowed, but are decomposed into individual triangles prior to geometry program execution. It can read the attributes of any of the vertex in the primitive and use them to generate new primitives. A geometry program has a fixed output primitive type, either a point, a line strip, or a triangle strip. It emits vertices (using the EMIT opcode) to define the output primitive. The attributes of emitted vertices are specified by writing to the same set of result bindings (e.g., "result.position") provided for vertex programs. Additionally, a geometry program can emit multiple disconnected primitives by using the ENDPRIM opcode, which is roughly equivalent to calling End and then Begin again. The primitives emitted by the geometry program are then clipped and then processed like an equivalent OpenGL primitive specified by the application. This extension provides four additional primitive types: lines with adjacency, line strips with adjacency, separate triangles with adjacency, and triangle strips with adjacency. Some of the vertices specified in these new primitive types are not part of the ordinary primitives. Instead, they represent neighboring vertices that are adjacent to the two line segment end points (lines/strips) or the three triangle edges (triangles/tstrips). These "adjacency" vertices can be accessed by geometry programs and used to match up the outputs of the geometry program with those of neighboring primitives. Additionally, geometry programs allow for layered rendering, where entire three-dimensional, cube map, or array textures (EXT_texture_array) can be bound to the current framebuffer. Geometry programs can use the "result.layer" binding to select a layer or cube map face to render to. Each primitive emitted by such a geometry program is rendered to the layer taken from its provoking vertex. Since geometry programs expect a specific input primitive type, an error will occur if the application presents primtives of a different type. For example, if an enabled geometry program expects points, an error will occur at Begin() time, if a primitive mode of TRIANGLES is specified. New Procedures and Functions void ProgramVertexLimitNV(enum target, int limit); void FramebufferTextureEXT(enum target, enum attachment, uint texture, int level); void FramebufferTextureLayerEXT(enum target, enum attachment, uint texture, int level, int layer); void FramebufferTextureFaceEXT(enum target, enum attachment, uint texture, int level, enum face); New Tokens Accepted by the parameter of Disable, Enable, and IsEnabled, and by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: GEOMETRY_PROGRAM_NV 0x8C26 Accepted by the parameter of GetProgramivARB: MAX_PROGRAM_OUTPUT_VERTICES_NV 0x8C27 MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV 0x8C28 GEOMETRY_VERTICES_OUT_EXT 0x8DDA GEOMETRY_INPUT_TYPE_EXT 0x8DDB GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC Accepted by the parameter of GetBooleanv, GetIntegerv, GetFloatv, and GetDoublev: MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29 Accepted by the parameter of Begin, DrawArrays, MultiDrawArrays, DrawElements, MultiDrawElements, and DrawRangeElements: LINES_ADJACENCY_EXT 0xA LINE_STRIP_ADJACENCY_EXT 0xB TRIANGLES_ADJACENCY_EXT 0xC TRIANGLE_STRIP_ADJACENCY_EXT 0xD Returned by CheckFramebufferStatusEXT: FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8 FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9 Accepted by the parameter of GetFramebufferAttachmentParameterivEXT: FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7 FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4 Accepted by the parameter of Enable, Disable, and IsEnabled, and by the parameter of GetIntegerv, GetFloatv, GetDoublev, and GetBooleanv: PROGRAM_POINT_SIZE_EXT 0x8642 (Note: The "EXT" tokens above are shared with the EXT_geometry_shader4 extension.) (Note: FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER is simply an alias for the FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_EXT token provided in EXT_framebuffer_object. This extension generalizes the notion of "" to include layers of an array texture.) (Note: PROGRAM_POINT_SIZE_EXT is simply an alias for the VERTEX_PROGRAM_POINT_SIZE token provided in OpenGL 2.0, which is itself an alias for VERTEX_PROGRAM_POINT_SIZE_ARB provided by ARB_vertex_program. Program-computed point sizes can be enabled if geometry programs are enabled, even if no vertex program is used.) Additions to Chapter 2 of the OpenGL 1.5 Specification (OpenGL Operation) Modify Section 2.6.1 (Begin and End Objects), p. 13 (Add to end of section, p. 18) (add figure) 1 - - - 2----->3 - - - 4 1 - - - 2--->3--->4--->5 - - - 6 5 - - - 6----->7 - - - 8 (a) (b) Figure X.1 (a) Lines with adjacency, (b) Line strip with adjacency. The vertices connected with solid lines belong to the main primitives; the vertices connected by dashed lines are the adjacent vertices that may be used in a geometry program. Lines with Adjacency Lines with adjacency are independent line segments where each endpoint has a corresponding "adjacent" vertex that can be accessed by a geometry program (Section 2.15). If geometry programs are disabled, the "adjacent" vertices are ignored. A line segment is drawn from the 4i + 2nd vertex to the 4i + 3rd vertex for each i = 0, 1, ... , n-1, where there are 4n+k vertices between the Begin and End. k is either 0, 1, 2, or 3; if k is not zero, the final k vertices are ignored. For line segment i, the 4i + 1st and 4i + 4th vertices are considered adjacent to the 4i + 2nd and 4i + 3rd vertices, respectively. See Figure X.1. Lines with adjacency are generated by calling Begin with the argument value LINES_ADJACENCY_EXT. Line Strips with Adjacency Line strips with adjacency are similar to line strips, except that each line segment has a pair of adjacent vertices that can be accessed by geometry programs (Section 2.15). If geometry programs are disabled, the "adjacent" vertices are ignored. A line segment is drawn from the i + 2nd vertex to the i + 3rd vertex for each i = 0, 1, ..., n-1, where there are n+3 vertices between the Begin and End. If there are fewer than four vertices between a Begin and End, all vertices are ignored. For line segment i, the i + 1st and i + 4th vertices are considered adjacent to the i + 2nd and i + 3rd vertices, respectively. See Figure X.1. Line strips with adjacency are generated by calling Begin with the argument value LINE_STRIP_ADJACENCY_EXT. (add figure) 2 - - - 3 - - - 4 8 - - - 9 - - - 10 ^\ ^\ \ | \ | \ | \ | | \ | \ \ | \ | \ | \ | | \ | \ \ | \ | \ | \ | | v | v 1<------5 7<------11 \ | \ | \ | \ | \ | \ | 6 12 Figure X.2 Triangles with adjacency. The vertices connected with solid lines belong to the main primitive; the vertices connected by dashed lines are the adjacent vertices that may be used in a geometry program. Triangles with Adjacency Triangles with adjacency are similar to separate triangles, except that each triangle edge has an adjacent vertex that can be accessed by geometry programs (Section 2.15). If geometry programs are disabled, the "adjacent" vertices are ignored. The 6i + 1st, 6i + 3rd, and 6i + 5th vertices (in that order) determine a triangle for each i = 0, 1, ..., n-1, where there are 6n+k vertices between the Begin and End. k is either 0, 1, 2, 3, 4, or 5; if k is non-zero, the final k vertices are ignored. For triangle i, the i + 2nd, i + 4th, and i + 6th vertices are considered adjacent to edges from the i + 1st to the i + 3rd, from the i + 3rd to the i + 5th, and from the i + 5th to the i + 1st vertices, respectively. See Figure X.2. Triangles with adjacency are generated by calling Begin with the argument value TRIANGLES_ADJACENCY_EXT. (add figure) 6 6 | \ | \ | \ | \ | \ | \ 2 - - - 3- - - >6 2 - - - 3------>7 2 - - - 3------>7- - - 10 ^\ ^^ | ^^ ^^ | \ | \ | \ | \ | \ \ | \ | \ | \ | \ | | \ | \ | \ | \ | \ | \ | \ \ | \ | \ | \ | \ | | \ | \ | \ | \ | \ | \ | \ \ | \ | \ | v | vv | vv v| 1<------5 1<------5 - - - 8 1<------5<------9 \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | 4 4 4 8 6 10 | \ | \ | \ | \ | \ | \ 2 - - - 3------>7------>11 ^^ ^^ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | \ | vv vv 1<------5<------9 - - - 12 \ | \ | \ | \ | \ | \ | 4 8 Figure X.3 Triangle strips with adjacency. The vertices connected with solid lines belong to the main primitives; the vertices connected by dashed lines are the adjacent vertices that may be used in a geometry program. Triangle Strips with Adjacency Triangle strips with adjacency are similar to triangle strips, except that each triangle edge has an adjacent vertex that can be accessed by geometry programs (Section 2.15). If geometry programs are disabled, the "adjacent" vertices are ignored. In triangle strips with adjacency, n triangles are drawn using 2 * (n+2) + k vertices between the Begin and End. k is either 0 or 1; if k is 1, the final vertex is ignored. If fewer than 6 vertices are specified between the Begin and End, the entire primitive is ignored. Table X.1 describes the vertices and order used to draw each triangle, and which vertices are considered adjacent to each edge of the triangle. See Figure X.3. (add table) primitive adjacent vertices vertices primitive 1st 2nd 3rd 1/2 2/3 3/1 --------------- ---- ---- ---- ---- ---- ---- only (i==0, n==1) 1 3 5 2 6 4 first (i==0) 1 3 5 2 7 4 middle (i odd) 2i+3 2i+1 2i+5 2i-1 2i+4 2i+7 middle (i even) 2i+1 2i+3 2i+5 2i-1 2i+7 2i+4 last (i==n-1, i odd) 2i+3 2i+1 2i+5 2i-1 2i+4 2i+6 last (i==n-1, i even) 2i+1 2i+3 2i+5 2i-1 2i+6 2i+4 Table X.1: Triangles generated by triangle strips with adjacency. Each triangle is drawn using the vertices in the "1st", "2nd", and "3rd" columns under "primitive vertices", in that order. The vertices in the "1/2", "2/3", and "3/1" columns under "adjacent vertices" are considered adjacent to the edges from the first to the second, from the second to the third, and from the third to the first vertex of the triangle, respectively. The six rows correspond to the six cases: the first and only triangle (i=0, n=1), the first triangle of several (i=0, n>0), "odd" middle triangles (i=1,3,5...), "even" middle triangles (i=2,4,6,...), and special cases for the last triangle inside the Begin/End, when i is either even or odd. For the purposes of this table, the first vertex specified after Begin is numbered "1" and the first triangle is numbered "0". Triangle strips with adjacency are generated by calling Begin with the argument value TRIANGLE_STRIP_ADJACENCY_EXT. Modify Section 2.14.1, Lighting (p. 59) (modify fourth paragraph, p. 63) Additionally, vertex and geometry shaders and programs can operate in two-sided color mode, which is enabled and disabled by calling Enable or Disable with the symbolic value VERTEX_PROGRAM_TWO_SIDE. When a vertex or geometry shader is active, the shaders can write front and back color values to the gl_FrontColor, gl_BackColor, gl_FrontSecondaryColor and gl_BackSecondaryColor outputs. When a vertex or geometry program is active, programs can write front and back colors using the available color result bindings. When a vertex or geometry shader or program is active and two-sided color mode is enabled, the GL chooses between front and back colors, as described below. If two-sided color mode is disabled, the front color output is always selected. Insert New Section 2.14.6, Geometry Programs (between 2.14.5, Color Index Lighting and 2.14.6, Clamping and Masking, p. 69) Section 2.14.6, Geometry Programs Each primitive may be optionally transformed by a geometry program. Geometry programs are enabled by calling Enable with the value GEOMETRY_PROGRAM_NV. A geometry program takes a single input primitive and generates vertices to be arranged into one or more output primitives. The original input primitive is discarded, and the output primitives are processed in order by the remainder of the GL pipeline. Section 2.14.6.1, Geometry Program Input Primitives A geometry program can operate on one of five input primitive types, as specified by the mandatory "PRIMITIVE_IN" declaration. Depending on the input primitive type, one to six vertices are available when the program is executed. A geometry program will fail to load unless it contains exactly one such declaration. Each input primitive type supports only a subset of the primitives provided by the GL. If geometry programs are enabled, Begin, or any function that implicitly calls Begin, will produce an INVALID_OPERATION error if the parameter is incompatible with the input primitive type of the current geometry program. The supported input primitive types are: Points (POINTS) Geometry programs that operate on points are valid only for the POINTS primitive type. There is a only a single vertex available for each program invocation: "vertex[0]" refers to the single point. Lines (LINES) Geometry programs that operate on line segments are valid only for the LINES, LINE_STRIP, and LINE_LOOP primitive types. There are two vertices available for each program invocation: "vertex[0]" and "vertex[1]" refer to the beginning and end of the line segment. Lines with Adjacency (LINES_ADJACENCY) Geometry programs that operate on line segments with adjacent vertices are valid only for the LINES_ADJACENCY_EXT and LINE_STRIP_ADJACENCY_EXT primitive types. There are four vertices available for each program invocation. "vertex[1]" and "vertex[2]" refer to the beginning and end of the line segment. "vertex[0]" and "vertex[3]" refer to the vertices adjacent to the beginning and end of the line segment, respectively. Triangles (TRIANGLES) Geometry programs that operate on triangles are valid for the TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, QUAD_STRIP, and POLYGON primitive types. When used with a geometry program that operates on triangles, QUADS, QUAD_STRIP, and POLYGON primitives are decomposed into triangles in an unspecified, implementation-dependent manner. For convex polygons (already required in the core GL specification), this decomposition satisfies three properties: * the collection of triangles fully covers the area of the original primitive, * no two triangles in the decomposition overlap, and * the orientation of each triangle is consistent with the orientation of the original primitive. For such primitives, the program is executed once for each triangle in the decomposition. There are three vertices available for each program invocation. "vertex[0]", "vertex[1]", and "vertex[2]", refer to the first, second, and third vertex of the triangle, respectively. Triangles with Adjacency (TRIANGLES_ADJACENCY) Geometry programs that operate on triangles with adjacent vertices are valid for the TRIANGLES_ADJACENCY_EXT and TRIANGLE_STRIP_ADJACENCY_EXT primitive types. There are six vertices available for each program invocation. "vertex[0]", "vertex[2]", and "vertex[4]" refer to the first, second, and third vertex of the triangle respectively. "vertex[1]", "vertex[3]", and "vertex[5]" refer to the vertices adjacent to the edges from the first to the second vertex, from the second to the third vertex, and from the third to the first vertex, respectively. Section 2.14.6.2, Geometry Program Output Primitives A geometry program can generate primitives of one of three types, as specified by the mandatory "PRIMITIVE_OUT" declaration. A geometry program will fail to load unless it contains exactly one such declaration. The supported output primitive types are points (POINTS), line strips (LINE_STRIP), and triangle strips (TRIANGLE_STRIP). The vertices output by the geometry program are decomposed into points, lines, or triangles based on the output primitive type in the manner described in section 2.6.1. Section 2.14.6.3, Geometry Program Execution Environment Geometry programs execute using the instruction set documented in the GL_NV_gpu_program4 extension specification and in a manner similar to vertex programs. Each vertex attribute access must identify the vertex number being accessed. For example, "vertex[1].position" identifies the transformed position of "vertex[1]" as specified in teh description of the input primitive type. Output vertices are specified by writing to vertex result variables in the same manner as done by vertex programs. The special instruction "EMIT" specifies that a vertex is completed. A vertex is added to the current output primitive using the current values of the vertex result variables. The values of any unwritten result variables (or components) are undefined. After an EMIT instruction is completed, the current values of all vertex result variables become undefined. If a program wants to ensure that the same result is used for every vertex written by the program, it is necessary to write the corresponding value once per vertex. The special instruction "ENDPRIM" specifies that the current output primitive should be completed and a new output primitive should be started. A geometry program starts with an output primitive containing no vertices. When a geometry program terminates, the current output primitive is automatically completed. ENDPRIM has no effect if the geometry program's output primitive type is POINTS. When a primitive generated by a geometry program is completed, the vertices added by the EMIT instruction are decomposed into points, lines, or triangles according to the output primitive type in the manner described in Section 2.8.1. The resulting primitives are then clipped and rasterized. If the number of vertices emitted by the geometry program is not sufficient to produce a single primitive, nothing is drawn. Like vertex and fragment programs, geometry programs can access textures. The maximum number of texture image units that can be accessed by a geometry program is given by the value of MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT. Section 2.14.6.4, Geometry Program Output Limits A geometry program may not emit an limited in the number of vertices per invocation. Each geometry program must declare a vertex limit, which is the maximum number of vertices that the program can ever produce. The vertex limit is specified using the "VERTICES_OUT" declaration. A geometry program will fail to load unless it contains exactly one such declaration. There are two implementation-dependent limits that limit the total number of vertices that a program can emit. First, the vertex limit may not exceed the value of MAX_PROGRAM_OUTPUT_VERTICES_NV. Second, product of the vertex limit and the number of result variable components written by the program (PROGRAM_RESULT_COMPONENTS_NV, as described in section 2.X.3.5 of NV_gpu_program4) may not exceed the value of MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV. A geometry program will fail to load if its maximum vertex count or maximum total component count exceeds the implementation-dependent limit. The limits may be queried by calling GetProgramiv with a of GEOMETRY_PROGRAM_NV. Note that the maximum number of vertices that a geometry program can emit may be much lower than MAX_PROGRAM_OUTPUT_VERTICES_NV if the program writes a large number of result variable components. After a geometry program is compiled, the vertex limit may be changed using the command void ProgramVertexLimitNV(enum target, int limit); must be GEOMETRY_PROGRAM_NV. is the new vertex limit, which must satisfy the two rules described above. The error INVALID_VALUE is generated if is less than or equal to zero, is greater than or equal to MAX_PROGRAM_OUTPUT_VERTICES_NV, or if the total number of components emitted would exceed MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV. The error INVALID_OPERATION is generated if the current geometry program has not been successfully loaded. When a program executes, the number of vertices it emits should not exceed the vertex limit. Once a geometry program emits a number of vertices equal to the vertex limit, subsequent EMIT instructions may or may not have any effect. Modify Section 2.X.2, Program Grammar (replace third paragraph) Geometry programs are required to begin with the header string "!!NVgp4.0". This header string identifies the subsequent program body as being a geometry 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) ::= ::= ::= ::= ::= ::= | | "." | "." | "." "." "." ::= | "." | ::= "PRIMITIVE_IN" | "PRIMITIVE_OUT" | "VERTICES_OUT" ::= "POINTS" | "LINES" | "LINES_ADJACENCY" | "TRIANGLES" | "TRIANGLES_ADJACENCY" ::= "POINTS" | "LINE_STRIP" | "TRIANGLE_STRIP" ::= "EMIT" | "ENDPRIM" ::= "position" | "fogcoord" | "pointsize" | | | | "primitive" "." "id" ::= "color" ::= | | ::= "texcoord" ::= "clip" ::= "attrib" ::= "vertex" ::= "position" | "fogcoord" | "pointsize" | "primid" | "layer" | | | ::= "color" ::= | | ::= "texcoord" ::= "clip" ::= "attrib" ::= "result" "." (add the following subsection to section 2.X.3.2, Program Attribute Variables) Geometry program attribute variables describe the attributes of each transformed vertex accessible to the geometry program. Most attributes correspond to the per-vertex results generated by vertex program execution or fixed-function vertex processing. The "primitive.id" attribute is generated specially, as described below. If vertex programs are enabled, attributes will be obtained from the per-vertex outputs of the vertex program used to generate the vertex in question. Geometry program attributes should be read using the same component data type used to write the corresponding vertex program results. The value of any attribute corresponding to a vertex output not written by the vertex program is undefined. If vertex programs are disabled, attributes will be obtained from the values computed by fixed-function vertex processing. All attributes, except for the primitive ID should be read as floating-point values in this case. Geometry Vertex Binding Components Description ----------------------------- ---------- ---------------------------- vertex[m].position (x,y,z,w) clip coordinates vertex[m].color (r,g,b,a) front primary color vertex[m].color.primary (r,g,b,a) front primary color vertex[m].color.secondary (r,g,b,a) front secondary color vertex[m].color.front (r,g,b,a) front primary color vertex[m].color.front.primary (r,g,b,a) front primary color vertex[m].color.front.secondary (r,g,b,a) front secondary color vertex[m].color.back (r,g,b,a) back primary color vertex[m].color.back.primary (r,g,b,a) back primary color vertex[m].color.back.secondary (r,g,b,a) back secondary color vertex[m].fogcoord (f,-,-,-) fog coordinate vertex[m].pointsize (s,-,-,-) point size vertex[m].texcoord (s,t,r,q) texture coordinate, unit 0 vertex[m].texcoord[n] (s,t,r,q) texture coordinate, unit n vertex[m].attrib[n] (x,y,z,w) generic interpolant n vertex[m].clip[n] (d,-,-,-) clip plane distance vertex[m].texcoord[n..o] (s,t,r,q) array of texture coordinates vertex[m].attrib[n..o] (x,y,z,w) array of generic interpolants vertex[m].clip[n..o] (d,-,-,-) array of clip distances vertex[m].id (id,-,-,-) vertex id primitive.id (id,-,-,-) primitive number Table X.2, Geometry Program Attribute Bindings. refers to a vertex number, while , and refer to integer constants. Only the "vertex[m].texcoord" and "vertex.attrib" bindings are available in arrays. For bindings that include "vertex[m]", identifies the vertex number whose attributes are used for the binding. For bindings in explicit variable declarations, "[m]" is optional. If "[m]" is specified, must be an integer constant and must be in the valid range of vertices supported for the input primitive type. If "[m]" is not specified, the declared variable is accessed as an array, with the first array index specifying the vertex number. If such a variable is declared an array, it must have a second array index to identify the individual array element. For bindings used directly in instructions, "[m]" is required and must be an integer constant specifying a vertex number. The following examples illustrate various legal and illegal geometry program bindings and their meanings. ATTRIB pos = vertex.position; ATTRIB pos2 = vertex[2].position; ATTRIB texcoords[] = { vertex.texcoord[0..3] }; ATTRIB tcoords1[4] = { vertex[1].texcoord[1..4] }; INT TEMP A0; ... MOV R0, pos[1]; # position of vertex 1 MOV R0, vertex[1].position; # position of vertex 1 MOV R0, pos2; # position of vertex 2 MOV R0, texcoords[A0.x][1]; # texcoord 1 of vertex A0.x MOV R0, texcoords[A0.x][A0.y]; # texcoord A0.y of vertex A0.x MOV R0, tcoords1[2]; # texcoord 3 of vertex 1 MOV R0, vertex[A0.x].texcoord[1]; # ILLEGAL allowed -- vertex number # must be constant here. If a geometry attribute binding matches "vertex[m].position", the "x", "y", "z" and "w" components of the geometry attribute variable are filled with the "x", "y", "z", and "w" components, respectively, of the transformed position of vertex , in clip coordinates. If a geometry attribute binding matches any binding in Table X.2 beginning with "vertex[m].color", the "x", "y", "z", and "w" components of the geometry attribute variable are filled with the "r", "g", "b", and "a" components, respectively, of the corresponding color of vertex . Bindings containing "front" and "back" refer to the front and back colors, respectively. Bindings containing "primary" and "secondary" refer to primary and secondary colors, respectively. If face or color type is omitted in the binding, the binding is treated as though "front" and "primary", respectively, were specified. If a geometry attribute binding matches "vertex[m].fogcoord", the "x" component of the geometry attribute variable is filled with the fog coordinate of vertex . The "y", "z", and "w" components are undefined. If a geometry attribute binding matches "vertex[m].pointsize", the "x" component of the geometry attribute variable is filled with the point size of vertex computed by the vertex program. For fixed-function vertex processing, the point size attribute is undefined. The "y", "z", and "w" components are always undefined. If a geometry attribute binding matches "vertex[m].texcoord" or "vertex[m].texcoord[n]", the "x", "y", "z", and "w" coordinates of the geometry attribute variable are filled with the "s", "t", "r", and "q" coordinates of texture coordinate set of vertex . If is omitted, texture coordinate set zero is used. If a geometry attribute binding matches "vertex[m].attrib[n]", the "x", "y", "z", and "w" components of the geometry attribute variable are filled with the "x", "y", "z", and "w" coordinates of generic interpolant of vertex . All generic interpolants will be undefined when used with fixed-function vertex processing. If a geometry attribute binding matches "vertex[m].clip[n]", the "x" component of the geometry attribute variable is filled the clip distance of vertex for clip plane , as written by the vertex program. If fixed-function vertex processing or position-invariant vertex programs are used, the clip distance is obtained by computing the per-clip plane dot product: (p_1' p_2' p_3' p_4') dot (x_e y_e z_e w_e), at the vertex location, as described in section 2.12. The clip distance for clip plane is undefined if clip plane is disabled. The "y", "z", and "w" components of the attribute are undefined. If a geometry attribute binding matches "vertex[m].texcoord[n..o]", "vertex[m].attrib[n..o]", or "vertex[m].clip[n..o]", a sequence of 1+- texture coordinate bindings is created. For texture coordinate bindings, it is as though the sequence "vertex[m].texcoord[n], vertex[m].texcoord[n+1], ... vertex[m].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 geometry attribute binding matches "vertex[m].id", the "x" component is filled with the vertex ID. If a vertex program is currently active, the attribute variable is filled with the vertex ID result written by the vertex program. If fixed-function vertex processing is used, the vertex ID is undefined. The "y", "z", and "w" components of the attribute are undefined. If a geometry attribute binding matches "primitive.id", the "x" component is filled with the number of primitives received by the GL 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 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. 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.) Geometry programs emit vertices, and the set of result variables available to such programs correspond to the attributes of each emitted vertex. The set of allowable result variable bindings for geometry programs is given in Table X.3. Binding Components Description ----------------------------- ---------- ---------------------------- result.position (x,y,z,w) position in clip coordinates result.color (r,g,b,a) front-facing primary color result.color.primary (r,g,b,a) front-facing primary color result.color.secondary (r,g,b,a) front-facing secondary color result.color.front (r,g,b,a) front-facing primary color result.color.front.primary (r,g,b,a) front-facing primary color result.color.front.secondary (r,g,b,a) front-facing secondary color result.color.back (r,g,b,a) back-facing primary color result.color.back.primary (r,g,b,a) back-facing primary color result.color.back.secondary (r,g,b,a) back-facing secondary color result.fogcoord (f,*,*,*) fog coordinate result.pointsize (s,*,*,*) point size result.texcoord (s,t,r,q) texture coordinate, unit 0 result.texcoord[n] (s,t,r,q) texture coordinate, unit n result.attrib[n] (x,y,z,w) generic interpolant n result.clip[n] (d,*,*,*) clip plane distance result.texcoord[n..o] (s,t,r,q) texture coordinates n thru o result.attrib[n..o] (x,y,z,w) generic interpolants n thru o result.clip[n..o] (d,*,*,*) clip distances n thru o result.primid (id,*,*,*) primitive id result.layer (l,*,*,*) layer for cube/array/3D FBOs Table X.3: Geometry Program Result Variable Bindings. Components labeled "*" are unused. If a result variable binding matches "result.position", updates to the "x", "y", "z", and "w" components of the result variable modify the "x", "y", "z", and "w" components, respectively, of the transformed vertex's clip coordinates. Final window coordinates will be generated for the vertex as described in section 2.14.4.4. If a result variable binding match begins with "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 corresponding vertex color attribute in Table X.3. Color bindings that do not specify "front" or "back" are consided to refer to front-facing colors. Color bindings that do not specify "primary" or "secondary" are considered to refer to primary colors. If a result variable binding matches "result.fogcoord", updates to the "x" component of the result variable set the transformed vertex's fog coordinate. Updates to the "y", "z", and "w" components of the result variable have no effect. If a result variable binding matches "result.pointsize", updates to the "x" component of the result variable set the transformed vertex's point size. Updates to the "y", "z", and "w" components of the result variable have no effect. If a result variable binding matches "result.texcoord" or "result.texcoord[n]", updates to the "x", "y", "z", and "w" components of the result variable set the "s", "t", "r" and "q" components, respectively, of the transformed vertex's texture coordinates for texture unit . If "[n]" is omitted, texture unit zero is selected. If a result variable binding matches "result.attrib[n]", updates to the "x", "y", "z", and "w" components of the result variable set the "x", "y", "z", and "w" components of the generic interpolant . If a result variable binding matches "result.clip[n]", updates to the "x" component of the result variable set the clip distance for clip plane . If a result variable binding matches "result.texcoord[n..o]", "result.attrib[n..o]", or "result.clip[n..o]", a sequence of 1+- bindings is created. For texture coordinates, it is as though the sequence "result.texcoord[n], result.texcoord[n+1], ... result.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 result variable binding matches "result.primid", updates to the "x" component of the result variable provide a single integer that serves as a primitive identifier. The written primitive ID is available to fragment programs using the "primitive.id" attribute binding. If a fragment program using primitive IDs is active and a geometry program is also active, the geometry program must write "result.primid" or the primitive ID number is undefined. If a result variable binding matches "result.layer", updates to the "x" component of the result variable provide a single integer that serves as a layer selector for layered rendering (section 2.14.6.5). The layer must be written as an integer value; writing a floating-point layer number will produce undefined results. (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 ----------- - - - - - - ---------- --- -------------------------------- EMIT - - - - - - - - emit vertex ENDPRIM - - - - - - - - end of primitive (add the following subsection to section 2.X.5, Program Options.) Section 2.X.5.Y, Geometry Program Options No options are supported at present for geometry programs. (add the following subsection to section 2.X.6, Program Declarations.) Section 2.X.6.Y, Geometry Program Declarations Geometry programs support three types of declaration statements, as described below. Each of the three must be included exactly once in the geometry program. - Input Primitive Type (PRIMITIVE_IN) The PRIMITIVE_IN statement declares the type of primitives seen by a geometry program. The single argument must be one of "POINTS", "LINES", "LINES_ADJACENCY", "TRIANGLES", or "TRIANGLES_ADJACENCY". - Output Primitive Type (PRIMITIVE_OUT) The PRIMITIVE_OUT statement declares the type of primitive emitted by a geometry program. The single argument must be one of "POINTS", "LINE_STRIP", or "TRIANGLE_STRIP". - Maximum Vertex Count (VERTICES_OUT) The VERTICES_OUT statement declares the maximum number of vertices that may be emitted by a geometry program. The single argument must be a positive integer. A vertex program that emits more than the specified number of vertices may terminate abnormally. (add the following subsections to section 2.X.7, Program Instruction Set.) Section 2.X.7.Z, EMIT: Emit Vertex The EMIT instruction emits a new vertex to be added to the current output primitive of a geometry program. The attributes of the emitted vertex are given by the current values of the vertex result variables. After the EMIT instruction completes, a new vertex is started and all result variables become undefined. Section 2.X.7.Z, ENDPRIM: End of Primitive A geometry program can emit multiple primitives in a single invocation. The ENDPRIM instruction is used in a geometry program to signify the end of the current primitive and the beginning of a new primitive of the same type. The effect of ENDPRIM is roughly equivalent to calling End followed by a new Begin, where the primitive mode is specified in the text of the geometry program. Like End, the ENDPRIM instruction does not emit a vertex. Any result registers written prior to an ENDPRIM instruction are unchanged, and will be used in the vertex specified by the next EMIT instruction if they are not overwritten first. When geometry program execution completes, the current primitive is automatically terminated. It is not necessary to include an ENDPRIM instruction if the geometry program writes only a single primitive. Additions to Chapter 3 of the OpenGL 1.5 Specification (Rasterization) Modify Section 3.3, Points (p. 95) (replace all Section 3.3 text on p. 95) A point is drawn by generating a set of fragments in the shape of a square or circle centered around the vertex of the point. Each vertex has an associated point size that controls the size of that square or circle. If no vertex or geometry program is active, the size of the point is controlled by void PointSize(float size); specifies the requested size of a point. The default value is 1.0. A value less than or equal to zero results in the error INVALID_VALUE. The requested point size is multiplied with a distance attenuation factor, clamped to a specified point size range, and further clamped to the implementation-dependent point size range to produce the derived point size: derived size = clamp(size * sqrt(1/(a+b*d+c*d^2))) where d is the eye-coordinate distance from the eye, (0,0,0,1) in eye coordinates, to the vertex, and a, b, and c are distance attenuation function coefficients. If a vertex or geometry program is active, the derived size depends on the per-vertex point size mode enable. Per-vertex point size mode is enabled or disabled by calling Enable or Disable with the symbolic value PROGRAM_POINT_SIZE_EXT. If per-vertex point size is enabled and a geometry program is active, the point size is taken from the point size emitted by the geometry program. If per-vertex point size is enabled an no geometry program is active, the point size is taken from the point size result of the vertex program. Otherwise, the point size is taken from the value provided to PointSize, with no distance attenuation applied. In all cases, the point size is clamped to the implementation-dependent point size range. If multisampling is not enabled, the derived size is passed on to rasterization as the point width. ... Additions to Chapter 4 of the OpenGL 1.5 Specification (Per-Fragment Operations and the Frame Buffer) None. Additions to Chapter 5 of the OpenGL 1.5 Specification (Special Functions) None. Additions to Chapter 6 of the OpenGL 1.5 Specification (State and State Requests) None. Additions to Appendix A of the OpenGL 1.5 Specification (Invariance) None. Additions to the AGL/GLX/WGL Specifications None. GLX Protocol None. Errors The error INVALID_OPERATION is generated if Begin, or any command that implicitly calls Begin, is called when geometry program mode is enabled and the currently bound geometry program object does not contain a valid geometry program. The error INVALID_OPERATION is generated if Begin, or any command that implicitly calls Begin, is called when geometry program mode is enabled and: * the input primitive type of the current geometry program is POINTS and is not POINTS, * the input primitive type of the current geometry program is LINES and is not LINES, LINE_STRIP, or LINE_LOOP, * the input primitive type of the current geometry program is TRIANGLES and is not TRIANGLES, TRIANGLE_STRIP, TRIANGLE_FAN, QUADS, QUAD_STRIP, or POLYGON, * the input primitive type of the current geometry program is LINES_ADJACENCY and is not LINES_ADJACENCY_EXT or LINE_STRIP_ADJACENCY_EXT, or * the input primitive type of the current geometry program is TRIANGLES_ADJACENCY and is not TRIANGLES_ADJACENCY_EXT or TRIANGLE_STRIP_ADJACENCY_EXT. The error INVALID_ENUM is generated if GetProgramivARB is called with a of MAX_PROGRAM_OUTPUT_VERTICES_NV or MAX_PROGRAM_TOTAL_OUTPUT_COMPONENTS_NV and the target isn't GEOMETRY_PROGRAM_NV. Dependencies on EXT_framebuffer_object If EXT_framebuffer_object (or similar functionality) is not supported, the "result.layer" binding should be removed. "FramebufferTextureEXT" and "FramebufferTextureLayerEXT" should be removed from "New Procedures and Functions", and FRAMEBUFFER_ATTACHMENT_LAYERED_EXT, FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT, and FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT should be removed from "New Tokens". Otherwise, this extension modifies EXT_framebuffer_object to add the notion of layered framebuffer attachments and framebuffers that can be used in conjunction with geometry programs to allow programs to direct primitives to a face of a cube map or layer of a three-dimensional texture or one- or two-dimensional array texture. The layer used for rendering can be selected by the geometry program at run time. (insert before the end of Section 4.4.2, Attaching Images to Framebuffer Objects) There are several types of framebuffer-attachable images: * the image of a renderbuffer object, which is always two-dimensional, * a single level of a one-dimensional texture, which is treated as a two-dimensional image with a height of one, * a single level of a two-dimensional or rectangle texture, * a single face of a cube map texture level, which is treated as a two-dimensional image, or * a single layer of a one- or two-dimensional array texture or three-dimensional texture, which is treated as a two-dimensional image. Additionally, an entire level of a three-dimensional texture, cube map texture, or one- or two-dimensional array texture can be attached to an attachment point. Such attachments are treated as an array of two-dimensional images, arranged in layers, and the corresponding attachment point is considered to be layered. (replace section 4.4.2.3, "Attaching Texture Images to a Framebuffer") GL supports copying the rendered contents of the framebuffer into the images of a texture object through the use of the routines CopyTexImage{1D|2D}, and CopyTexSubImage{1D|2D|3D}. Additionally, GL supports rendering directly into the images of a texture object. To render directly into a texture image, a specified level of a texture object can be attached as one of the logical buffers of the currently bound framebuffer object by calling: void FramebufferTextureEXT(enum target, enum attachment, uint texture, int level); must be FRAMEBUFFER_EXT. must be one of the attachment points of the framebuffer listed in table 1.nnn. If is zero, any image or array of images attached to the attachment point named by is detached, and the state of the attachment point is reset to its initial values. is ignored if is zero. If is non-zero, FramebufferTextureEXT attaches level of the texture object named to the framebuffer attachment point named by . The error INVALID_VALUE is generated if is not the name of a texture object, or if is not a supported texture level number for textures of the type corresponding to . The error INVALID_OPERATION is generated if is the name of a buffer texture. If is the name of a three-dimensional texture, cube map texture, or one- or two-dimensional array texture, the texture level attached to the framebuffer attachment point is an array of images, and the framebuffer attachment is considered layered. The command void FramebufferTextureLayerEXT(enum target, enum attachment, uint texture, int level, int layer); operates like FramebufferTextureEXT, except that only a single layer of the texture level, numbered , is attached to the attachment point. If is non-zero, the error INVALID_VALUE is generated if is negative, or if is not the name of a texture object. The error INVALID_OPERATION is generated unless is zero or the name of a three-dimensional or one- or two-dimensional array texture. The command void FramebufferTextureFaceEXT(enum target, enum attachment, uint texture, int level, enum face); operates like FramebufferTextureEXT, except that only a single face of a cube map texture, given by , is attached to the attachment point. is one of TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z, TEXTURE_CUBE_MAP_NEGATIVE_Z. If is non-zero, the error INVALID_VALUE is generated if is not the name of a texture object. The error INVALID_OPERATION is generated unless is zero or the name of a cube map texture. The command void FramebufferTexture1DEXT(enum target, enum attachment, enum textarget, uint texture, int level); operates identically to FramebufferTextureEXT, except for two additional restrictions. If is non-zero, the error INVALID_ENUM is generated if is not TEXTURE_1D and the error INVALID_OPERATION is generated unless is the name of a one-dimensional texture. The command void FramebufferTexture2DEXT(enum target, enum attachment, enum textarget, uint texture, int level); operates similarly to FramebufferTextureEXT. If is TEXTURE_2D or TEXTURE_RECTANGLE_ARB, must be zero or the name of a two-dimensional or rectangle texture. If is TEXTURE_CUBE_MAP_POSITIVE_X, TEXTURE_CUBE_MAP_NEGATIVE_X, TEXTURE_CUBE_MAP_POSITIVE_Y, TEXTURE_CUBE_MAP_NEGATIVE_Y, TEXTURE_CUBE_MAP_POSITIVE_Z, or TEXTURE_CUBE_MAP_NEGATIVE_Z, must be zero or the name of a cube map texture. For cube map textures, only the single face of the cube map texture level given by is attached. The error INVALID_ENUM is generated if is not zero and is not one of the values enumerated above. The error INVALID_OPERATION is generated if is the name of a texture whose type does not match the texture type required by . The command void FramebufferTexture3DEXT(enum target, enum attachment, enum textarget, uint texture, int level, int zoffset); behaves identically to FramebufferTextureLayerEXT, with the parameter set to the value of . The error INVALID_ENUM is generated if is not TEXTURE_3D. The error INVALID_OPERATION is generated unless is zero or the name of a three-dimensional texture. For all FramebufferTexture commands, if is non-zero and the command does not result in an error, the framebuffer attachment state corresponding to is updated based on the new attachment. FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is set to TEXTURE, FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT is set to , and FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is set to . FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_FACE is set to if FramebufferTexture2DEXT is called and is the name of a cubemap texture; otherwise, it is set to TEXTURE_CUBE_MAP_POSITIVE_X. FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT is set to or if FramebufferTextureLayerEXT or FramebufferTexture3DEXT is called; otherwise, it is set to zero. FRAMEBUFFER_ATTACHMENT_LAYERED_EXT is set to TRUE if FramebufferTextureEXT is called and is the name of a three-dimensional texture, cube map texture, or one- or two-dimensional array texture; otherwise it is set to FALSE. (modify Section 4.4.4.1, Framebuffer Attachment Completeness -- add to the conditions necessary for attachment completeness) The framebuffer attachment point is said to be "framebuffer attachment complete" if ...: * If FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE and FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT names a three-dimensional texture, FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT must be smaller than the depth of the texture. * If FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE and FRAMEBUFFER_ATTACHMENT_OBJECT_NAME_EXT names a one- or two-dimensional array texture, FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT must be smaller than the number of layers in the texture. (modify section 4.4.4.2, Framebuffer Completeness -- add to the list of conditions necessary for completeness) * If any framebuffer attachment is layered, all populated attachments must be layered. Additionally, all populated color attachments must be from textures of the same target (i.e., three-dimensional, cube map, or one- or two-dimensional array textures). { FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT } * If any framebuffer attachment is layered, all attachments must have the same layer count. For three-dimensional textures, the layer count is the depth of the attached volume. For cube map textures, the layer count is always six. For one- and two-dimensional array textures, the layer count is simply the number of layers in the array texture. { FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT } The enum in { brackets } after each clause of the framebuffer completeness rules specifies the return value of CheckFramebufferStatusEXT (see below) that is generated when that clause is violated. ... (add section 4.4.7, Layered Framebuffers) A framebuffer is considered to be layered if it is complete and all of its populated attachments are layered. When rendering to a layered framebuffer, each fragment generated by the GL is assigned a layer number. The layer number for a fragment is zero if * the fragment is generated by DrawPixels, CopyPixels, or Bitmap, * geometry programs are disabled, or * the current geometry program does not contain an instruction that writes to the layer result binding. Otherwise, the layer for each point, line, or triangle emitted by the geometry program is taken from the layer output of the provoking vertex. For line strips, the provoking vertex is the second vertex of each line segment. For triangle strips, the provoking vertex is the third vertex of each individual triangles. The per-fragment layer can be different for fragments generated by each individual point, line, or triangle emitted by a single geometry program invocation. A layer number written by a geometry program has no effect if the framebuffer is not layered. When fragments are written to a layered framebuffer, the fragment's layer number selects an image from the array of images at each attachment point from which to obtain the destination R, G, B, A values for blending (Section 4.1.8) and to which to write the final color values for that attachment. If the fragment's layer number is negative or greater than the number of layers attached, the effects of the fragment on the framebuffer contents are undefined. When the Clear command is used to clear a layered framebuffer attachment, all layers of the attachment are cleared. When commands such as ReadPixels or CopyPixels read from a layered framebuffer, the image at layer zero of the selected attachment is always used to obtain pixel values. When cube map texture levels are attached to a layered framebuffer, there are six layers attached, numbered zero through five. Each layer number is mapped to a cube map face, as indicated in Table X.4. layer number cube map face ------------ --------------------------- 0 TEXTURE_CUBE_MAP_POSITIVE_X 1 TEXTURE_CUBE_MAP_NEGATIVE_X 2 TEXTURE_CUBE_MAP_POSITIVE_Y 3 TEXTURE_CUBE_MAP_NEGATIVE_Y 4 TEXTURE_CUBE_MAP_POSITIVE_Z 5 TEXTURE_CUBE_MAP_NEGATIVE_Z Table X.4, Layer numbers for cube map texture faces. The layers are numbered in the same sequence as the cube map face token values. (modify Section 6.1.3, Enumerated Queries -- Modify/add to list of values for GetFramebufferAttachmentParameterivEXT if FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE_EXT is TEXTURE) If is FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT and the attached image is a layer of a three-dimensional texture or one- or two-dimensional array texture, then will contain the specified layer number. Otherwise, will contain the value zero. If is FRAMEBUFFER_ATTACHMENT_LAYERED_EXT, then will contain TRUE if an entire level of a three-dimesional texture, cube map texture, or one- or two-dimensional array texture is attached to the . Otherwise, will contain FALSE. (Modify the Additions to Chapter 5, section 5.4) Add the commands FramebufferTextureEXT, FramebufferTextureLayerEXT, and FramebufferTextureFaceEXT to the list of commands that are not compiled into a display list, but executed immediately. Dependencies on EXT_framebuffer_blit If EXT_framebuffer_blit is supported, the EXT_framebuffer_object language should be further amended so that values passed to FramebufferTextureEXT and FramebufferTextureLayerEXT can be DRAW_FRAMEBUFFER_EXT or READ_FRAMEBUFFER_EXT, and that those functions set/query state for the draw framebuffer if is FRAMEBUFFER_EXT. Dependencies on EXT_texture_array If EXT_texture_array is not supported, the discussion array textures the layered rendering edits to EXT_framebuffer_object should be removed. Layered rendering to cube map and 3D textures would still be supported. If EXT_texture_array is supported, the edits to EXT_framebuffer_object supersede those made in EXT_texture_array, except for language pertaining to mipmap generation of array textures. There are no functional incompatibilities between the FBO support in these two specifications. The only differences are that this extension supports layered rendering and also rewrites certain sections of the core FBO specification more aggressively. Dependencies on ARB_texture_rectangle If ARB_texture_rectangle is not supported, all references to rectangle textures in the EXT_framebuffer_object spec language should be removed. Dependencies on EXT_texture_buffer_object If EXT_buffer_object is not supported, the reference to an INVALID_OPERATION error if a buffer texture is passed to FramebufferTextureEXT 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. New State Initial Get Value Type Get Command Value Description Sec. Attribute ------------------------- ---- ----------- ------- ---------------------- ------ ---------------- GEOMETRY_PROGRAM_NV B IsEnabled FALSE Geometry shader enable 2.14.6 enable/transform FRAMEBUFFER_ATTACHMENT_ nxB GetFramebuffer- FALSE Framebuffer attachment 4.4.2.3 - LAYERED_EXT Attachment- is layered ParameterivEXT GEOMETRY_VERTICES_OUT_EXT Z+ GetProgramivARB 0 vertex limit of the 2.14.6.4 - current geometry program GEOMETRY_INPUT_TYPE_EXT Z+ GetProgramivARB 0 input primitive type 2.14.6.4 - of the current geometry program GEOMETRY_OUTPUT_TYPE_EXT Z+ GetProgramivARB 0 output primitive type 2.14.6.4 - of the current geometry program New Implementation Dependent State Minimum Get Value Type Get Command Value Description Sec Attrib ------------------------------- ---- --------------- ---------- -------------------- ------------ ------ MAX_GEOMETRY_TEXTURE_ Z+ GetIntegerv 16 maximum number of 2.14.6.3 - IMAGE_UNITS_EXT texture image units accessible in a geometry program MAX_PROGRAM_OUTPUT_VERTICES_NV Z+ GetProgramivARB 256 maximum number of 2.14.6.4 - vertices that any geometry program could emit MAX_PROGRAM_TOTAL_OUTPUT_ Z+ GetProgramivARB 1024 maximum number of 2.14.6.4 - COMPONENTS_NV result components (all vertices) that a geometry program can emit NVIDIA Implementation Details Because of a hardware limitation, some GeForce 8 series chips use the odd vertex of an incomplete TRIANGLE_STRIP_ADJACENCY_EXT primitive as a replacement adjacency vertex rather than ignoring it. Issues (1) How do geometry programs fit into the existing GL pipeline? RESOLVED: The following diagram illustrates how geometry programs fit into the "vertex processing" portion of the GL (Chapter 2 of the OpenGL 2.0 Specification). First, vertex attributes are specified via immediate-mode commands or through vertex arrays. They can be conventional attributes (e.g., glVertex, glColor, glTexCoord) or generic (numbered) attributes. Vertices are then transformed, either using a vertex program or fixed-function vertex processing. Fixed-function vertex processing includes position transformation (modelview and projection matrices), lighting, texture coordinate generation, and other calculations. The results of either method are a "transformed vertex", which has a position (in clip coordinates), front and back colors, texture coordinates, generic attributes (vertex program only), and so on. Note that on many current GL implementations, vertex processing is performed by executing a "fixed function vertex program" generated by the driver. After vertex transformation, vertices are assembled into primitives, according to the topology (e.g., TRIANGLES, QUAD_STRIP) provided by the call to glBegin(). Primitives are points, lines, triangles, quads, or polygons. Many GL implementations do not directly support quads or polygons, but instead decompose them into triangles as permitted by the spec. After initial primitive assembly, a geometry program is executed on each individual point, line, or triangle primitive, if enabled. It can read the attributes of each transformed vertex, perform arbitrary computations, and emit new transformed vertices. These emitted vertices are themselves assembled into primitives according to the output primitive type of the geometry program. Then, the colors of the vertices of each primitive are clamped to [0,1] (if color clamping is enabled), and flat shading may be performed by taking the color from the provoking vertex of the primitive. Each primitive is clipped to the view volume, and to any enabled user-defined clip planes. Color, texture coordinate, and other attribute values are computed for each new vertex introduced by clipping. After clipping, the position of each vertex (in clip coordinates) is converted to normalized device coordinates in the perspective division (divide by w) step, and to window coordinates in the viewport transformation step. At the same time, color values may be converted to normalized fixed-point values according to the "Final Color Processing" portion of the specification. After the vertices of the primitive are transformed to window coordinate, the GL determines if the primitive is front- or back-facing. That information is used for two-sided color selection, where a single set of colors is selected from either the front or back colors associated with each transformed vertex. When all this is done, the final transformed position, colors (primary and secondary), and other attributes are used for rasterization (Chapter 3 in the OpenGL 2.0 Specification). When the raster position is specified (via glRasterPos), it goes through the entire vertex processing pipeline as though it were a point. However, geometry programs are never run on the raster position. |generic |conventional |vertex |vertex |attributes |attributes | | | +-------------------+ | | | V V V vertex fixed-function program vertex | processing | | | | +<-------------------+ | Output |position, color, Primitive |other vertex data Type | | V | Begin/ primitive geometry primitive | End ------> assembly -----> program ----> assembly <-+ State | | V | +<------------------------------+ | | | color flat +----------> clamping ----> shading | | V | +<------------------------------+ | | clipping | | perspective viewport +------> divide ----> transform | | | +---+-----+ | V | | final facing | +------> color determination | | processing | | | | | | | | | | | +-----+ +----+ | | | | | | V V | | two-sided | | coloring | | | | | | | +------------------+ | +-------------+ | | | V V V rasterization | | V (2) Why is this called GL_NV_geometry_program4? There aren't any previous versions of this extension, let alone three? RESOLVED: The instruction set for GPU programs of all types (vertex, fragment, and now geometry) have been unified in the GL_NV_gpu_program4 extension, and the "4" suffix in this extension name indicates the instruction set type. There are three previous NV_vertex_program variants (four if you count NV_vertex_program1_1), so "4" is the next available numeric suffix. (3) Should the GL produce errors at Begin time if an application specifies a primitive mode that is "incompatible" with the geometry program? For example, if the geometry program operates on triangles and the application sends a POINTS primitive? RESOLVED: Yes. Mismatches of app-specified primitive types and geometry program input primitive types seem like clear errors and would produce weird and wonderful effects. (4) Can the input primitive type of a geometry program be changed at run time? RESOLVED: Not in this extension. Each geometry program has a single input primitive type, and vertices are presented to the program in a specific order based on that type. (5) Can the output primitive type of a geometry program be determined at run time? RESOLVED: Not in this extension. (6) Must the output primitive type of a geometry program match the input primitive type in any way? RESOLVED: No, you can have a geometry program generate points out of triangles or triangles out of points. Some combinations are analogous to existing OpenGL operations: reading triangles and writing points or line strips can be used to emulate a subset of PolygonMode functionality. Reading points and writing triangle strips can be used to emulate point sprites. (7) Are primitives emitted by a geometry program processed like any other OpenGL primitive? RESOLVED: Yes. Antialiasing, stippling, polygon offset, polygon mode, culling, two-sided lighting and color selection, point sprite operations, and fragment processing all work as expected. One limitation is that the only output primitive types supported are points, line strips, and triangle strips, none of which meaningfully support edge flags that are sometimes used in conjunction with the POINT and LINE polygon modes (edge flags are always ignored for line-mode triangle strips). (8) Should geometry programs support additional input primitive types? RESOLVED: Possibly in a future extension. It should be straightforward to build a future extension to support geometry programs that operate on quads. Other primitive types might be more demanding on hardware. Quads with adjacency would require 12 vertices per program execution. General polygons may require even more, since there is no fixed bound on the number of vertices in a polygon. (9) Should geometry programs support additional output primitive types? RESOLVED: Possibly in a future extension. Additional output types (e.g., independent lines, line loops, triangle fans, polygons) may be useful in the future; triangle fans/polygons seem particularly useful. (10) Should we provide additional adjacency primitive types that can be used inside a Begin/End? RESOLVED: Not in this extension. It may be desirable to add new primitive types (e.g., TRIANGLE_FAN_ADJACENCY) in a future extension. (11) How do geometry programs interact with RasterPos? RESOLVED: Geometry programs are ignored when specifying the raster position. While the raster position could be treated as a point, turning it into a triangle strip would be quite bizarre. (12) How do geometry programs interact with pixel primitives (DrawPixels, Bitmap)? RESOLVED: They do not. Fragments generated be DrawPixels and Bitmap are injected into the pipeline after the point where geometry program execution occurs. (13) Is there a limit on the number of vertices that can be emitted by a geometry program? RESOLVED: Unfortunately, yes. Besides practical hardware limits, there may also be practical performance advantages when applications guarantee a tight upper bound on the number of vertices a geometry shader will emit. GPUs frequently excecute programs in parallel, and there are substantial implementation challenges to parallel execution of geometry threads that can write an unbounded number of results, particular given that the all the primitives generated by the first geometry program invocation must be consumed before any of the primitives generated by the second program invocation. Limiting the amount of data a geometry program can write substantially eases the implementation burden. A geometry program must declare a maximum number of vertices that can be emitted, called the vertex limit. There is an implementation-dependent limit on the total number of vertices a program can emit (256 minimum) and the product of the vertex limit and the number of active result components (1024 minimum). A program will fail to load if doesn't declare a limit or exceeds either of the two implementatoin-dependent limits. It would be ideal if the limit could be inferred from the instructions in the program itself, and that would be possible for many programs, particularly ones with straight-line flow control. For programs with more complicated flow control (subroutines, data-dependent looping, and so on), it would be impossible to make such an inference and a "safe" limit would have to be used with adverse and possibly unexpected performance consequences. The limit on the number of EMIT instructions that can be issued can not always be enforced at compile time, or even at Begin time. We specify that if a program tries to emit more vertices than the vertex limit allows, emits that exceed the limit may or may not have any effect. (14) Should it be possible to change the limit on the number of vertices emitted by a geometry program after the program is specified? RESOLVED: Yes, using the function ProgramVertexLimitNV(). Applications may want to tweak a piece of data that affects the number of vertices emitted, but doesn't necessarily require recompiling the entire program. Examples might be a "circular point sprite" program, that reads a single point, and draws a circle centered at that point with vertices. An application could change the value at run time, but it could require a change in the vertex limit. Another example might be a geometry program that does some fancy subdivision, where the relevant parameter might be a limit on how far the primitive is subdivided. Ideally, this program object state should be set by a "program parameter" command, much like texture state is set by a "texture parameter" (TexParameter) command. Unfortunately, there are already several different "program parameter" functions: ProgramEnvParameter4fARB() -- sets global environment constants ProgramLocalParameter4fARB() -- sets per-program constants ProgramParameter4fNV() -- also sets global environment constants Additionally, GLSL and OpenGL 2.0 introduced "program objects" which are linked collections of vertex, fragment, and now geometry shaders. A GLSL vertex "shader" is equivalent to an ARB_vertex_program vertex "program", which is nothing like a GLSL program. As of OpenGL 2.0, GLSL programs do not have settable parameters, by subsequent extensions may want to add them (for example, EXT_geometry_shader4, which has this same functionality for GLSL). If that happens, they would want their own ProgramParameter API, but with a different prototype than this extension would want. Naming this function "ProgramVertexLimitNV" sidesteps this issue for now. (15) How do edge flags interact with adjacency primitives? RESOLVED: If geometry programs are disabled, adjacency primitives are still supported. For TRIANGLES_ADJACENCY_EXT, edge flags will apply as they do for TRIANGLES. Such primitives are rendered as independent triangles as though the adjacency vertices were not provided. Edge flags for the "real" vertices are supported. For all other adjacency primitive types, edge flags are irrelevant. (16) How do geometry programs interact with color clamping? RESOLVED: Geometry program execution occurs prior to color clamping in the pipeline. This means the colors written by vertex programs or fixed-function vertex processing are not clamped to [0,1] before they are read by geometry programs. If color clamping is enabled, any vertex colors written by the geometry program will have their components clamped to [0,1]. (17) How are QUADS, QUAD_STRIP, and POLYGON primitives decomposed into triangles in the initial implementation of GL_NV_geometry_program4? RESOLVED: The specification leaves the decomposition undefined, subject to a small number of rules. Assume that four vertices are specified in the order V0, V1, V2, V3. For QUADS primitives, the quad V0->V1->V2->V3 is decomposed into the triangles V0->V1->V2, and V0->V2->V3. The provoking vertex of the quad (V3) is only found in the second triangle. If it's necessary to flat shade over an entire quad, take the attributes from V0, which will be the first vertex for both triangles in the decomposition. For QUAD_STRIP primitives, the quad V0->V1->V3->V2 is decomposed into the triangles V0->V1->V3 and V2->V0->V3. This has the property of leaving the provoking vertex for the polygon (V3) as the third vertex for each triangle of the decomposition. For POLYGON primitives, the polygon V0->V1->V2->V3 is decomposed into the triangles V1->V2->V0 and V2->V3->V0. This has the property of leaving the provoking vertex for the polygon (V0) as the third vertex for each triangle of the decomposition. (18) Should geometry programs be able to select a layer of a 3D texture, cube map texture, or array texture at run time? If so, how? RESOLVED: This extension provides a per-vertex result binding called "result.layer", which is an integer specifying the layer to render to. When an each individual point, line, or triangle is emitted by a geometry program, the layer number is taken from the provoking (last) vertex of the primitive and is used for all fragments generated by that primitive. The EXT_framebuffer_object (FBO) extension is used for rendering to textures, but for cube maps and 3D textures, it only provides the ability to attach a single face or layer of such textures. This extension generalizes FBO by creates new entry points to bind an entire texture level (FramebufferTextureEXT) or a single layer of a texture level (FramebufferTextureLayerEXT) to an attachment point. The existing FBO binding functions, FramebufferTexture[123]DEXT are retained, and are defined in terms of the more general new functions. The new functions do not have a dimension in the function name or a parameter, which can be inferred from the provided texture. They can do anything that the old functions can do, except attach a single face of a cube map texture. We considered adding a separate function FramebufferTextureFaceEXT to provide this functionality, but decided that the existing FramebufferTexture2DEXT API was adequate. We also considered using FramebufferTextureLayerEXT for this purpose, but it was not clear whether a layer number (0-5) or face enum (e.g, TEXTURE_CUBE_MAP_POSITIVE_X) should be provided. When an entire texel level of a cube map, 3D, or array texture is attached, that attachment is considered layered. The framebuffer is considered layered if any attachment is layered. When the framebuffer is layered, there are three additional completeness requirements: * all attachments must be layered * all color attachments must be from textures of identical type * all attachments must have the same number of layers We expect subsequent versions of the FBO spec to relax the requirement that all attachments must have the same width and height, and plan to relax the similar requirement for layer count at that time. When rendering to a layered framebuffer, layer zero is used unless a geometry program that writes the layer result is enabled. When rendering to a non-layered framebuffer, any layer result emitted from geometry programs is ignored and the set of single-image attachments are used. When reading from a layered framebuffer (e.g., ReadPixels), layer zero is always used. When clearing a layered framebuffer, all layers are cleared to the corresponding clear values. Several other approaches were considered, including leveraging existing FBO attachment functions and requiring the use of FramebufferTexture3D with a of zero to make a framebuffer attachment "layerable" (attaching layer zero means that the attachment could be used for either layered- or non-layered rendering). Whether rendering was layered or not could either be inferred from the active geometry program, or set as a new property of the framebuffer object. There is presently FramebufferParameter API to set a property of a framebuffer, so it would have been necessary to create new set/query APIs if this approach were chosen. (19) How can single-pass cube map rendering be done efficiently in a geometry program? UNRESOLVED: To do single-pass cubemap rendering, attach entire cube map textures to framebuffer attachment points using the new functions provided by this extension. The vertex program used should only transform the vertex position to eye coordinates (position relative to the center of the cube map). A geometry program should be used that effectively projects each input triangle onto each of the six faces of the cube map, emitting a triangle for each. Each of the projected vertices should be emitted with a "result.layer" value matching the face number (0-5). When the projected triangle is drawn, it is automatically drawn on the face corresponding to the emitted layer number. It should be simple to skip projecting primitives onto faces they won't touch. For example, if all of the X eye coordinates are positive, there is no reason to project to the "negative X" cube map face. An example should be provided for this issue. (20) How should per-vertex point size work with geometry programs? RESOLVED: We will generalize the existing VERTEX_PROGRAM_POINT_SIZE enable to control the point size behavior if either vertex or geometry programs are enabled. If geometry programs are enabled, the point size is taken from the point size result of the emitted vertex if VERTEX_PROGRAM_POINT_SIZE is enabled, or from the PointSize state otherwise. If no geometry program is enabled, it works like OpenGL 2.0. If a vertex program is active, it's taken from the point size result or PointSize state, depending on the VERTEX_PROGRAM_POINT_SIZE enable. If no program is enabled, normal fixed-function point size handling (including distance attenuation) is supported. This extension creates a new alias for the VERTEX_PROGRAM_POINT_SIZE enum, called PROGRAM_POINT_SIZE_EXT, to reflect that the point size enable now covers multiple program types. Both enums have the same value. (21) How do vertex IDs work with geometry programs? RESOLVED: Vertex IDs are automatically provided to vertex programs when applicable, via the "vertex.id" binding. However, they are not automatically copied the transformed vertex results that are read by geometry programs. Geometry programs can read the ID of vertex via the "vertex[].id" binding, but the vertex ID must have been copied by the vertex program using an instruction such as: MOV result.id.x, vertex.id.x; If a vertex program doesn't write vertex ID, or fixed-function vertex processing is used, the vertex ID visible to geometry programs is undefined. (22) How do primitive IDs work with geometry programs? RESOLVED: Primitive IDs are automatically available to geometry programs via the "primitive.id" binding and indicate the number of input primitives previously processed since the last explicit or implicit Begin call. If a geometry program wants to make the primitive ID available to a fragment program, it should copy the appropriate value to the "result.primid" binding. (23) How do primitive IDs work with primitives not supported directly by geometry program input topologies (e.g., QUADS, POLYGON)? RESOLVED: QUADS are decomposed into two triangles. Both triangles will have the same primitive ID, which is the number of full quads previously processed. POLYGON primitives are decomposed into a series of triangles, and all of them will have the primitive ID -- zero. (24) This is an NV extension (NV_geometry_program4). Why do some of the new tokens have an "EXT" extension? RESOLVED: Some of the tokens are shared between this extension and the comparable high-level GLSL programmability extension (EXT_geometry_shader4). Rather than provide a duplicate set of tokens, we simply use the EXT versions here. The tokens specific to assembly shader uses retain an NV suffix. Revision History None