| Name |
| |
| SUN_triangle_list |
| |
| |
| Name Strings |
| |
| GL_SUN_triangle_list |
| |
| Contact |
| |
| Jack Middleton, Sun (Jack.Middleton 'at' eng.sun.com) |
| |
| Status |
| |
| Shipping |
| |
| Version |
| |
| $Date: 1999/12/28 01:40:37 $ $Revision: 1.4 $ |
| SUN Date: 99/06/25 13:12:54 Revision: 1.6 |
| |
| Number |
| |
| 165 |
| |
| Dependencies |
| |
| OpenGL 1.1 is required |
| |
| |
| Overview |
| |
| OpenGL has two chained triangle primitives, TRIANGLE_STRIP and |
| TRIANGLE_FAN. For multiple, consecutive triangle strips or |
| triangle fans, the overhead of Begin and End, or separate calls to |
| DrawArrays, can be significant depending on the number of triangles |
| per strip or fan. |
| |
| Many surface tessellators produce triangle strips with very few |
| triangles per strip before needing to restart a new strip. Even |
| sophisticated tessellators typically need to restart a new strip, |
| or switch from a triangle strip to a triangle fan, many times |
| within a single object. Such tessellators can often produce a more |
| efficient tessellation--one with fewer vertices--by mixing strips |
| and fans within the same object. The ability to switch from one to |
| the other without restarting the strip or fan yields even more |
| savings. Unfortunately, the overhead of switching from a triangle |
| strip to a triangle fan, or vice versa, can reduce, or even |
| eliminate the benefit gained from reducing the number of vertices. |
| |
| A new triangle list primitive, along with an associated replacement |
| code attribute, is defined by this extension to allow multiple |
| triangle strips and fans to be specified within the same Begin/End |
| pair or from a single call to DrawArrays. The triangle list |
| extension also provides the means to switch between triangle strips |
| and triangle fans with or without restarting the strip or fan. |
| |
| TRIANGLE_LIST is a new primitive type (i.e., new Begin mode) that |
| uses the ReplacementCodeSUN state attribute to determine whether the |
| current vertex replaces the oldest vertex, as in a triangle strip, |
| the middle vertex, as in a triangle fan, or restarts a new chained |
| triangle list. The first vertex of a new triangle list is |
| implicitly treated as a RESTART. The first three vertices complete |
| the first triangle, after which the replacement codes of the vertex |
| are used. The two vertices immediately following a |
| restart--including the implicit restart on the first vertex--are |
| ignored. The ReplacementCodeSUN attribute is part of the vertex |
| state, and is only used by the TRIANGLE_LIST primitive. |
| |
| |
| Issues |
| |
| 1. Two types of restarts: CW/CCW |
| |
| Compressed geometry supports the notion of RESTART_CW versus |
| RESTART_CCW. These two types of restart are supported by all |
| of Sun's hardware and this capability was exposed via XGL. We |
| need to decide whether we want to expose this in OpenGL. In a |
| sense, we already have exposed it with the compressed geometry |
| extension, since the compressed geometry spec allows both types |
| of restart. |
| |
| It is worth noting that these modes are somewhat misnamed. |
| They really don't override the meaning of the GL_FRONT_FACE |
| flag (nor did they override the equivalent XGL mode, either). |
| Rather, the type of restart either inverts the GL_FRONT_FACE |
| state, in the case of RESTART_CW, or it uses the GL_FRONT_FACE |
| flag unmodified, in the case of RESTART_CCW. This should be |
| the case for compressed geometry today (although it may be |
| broken), and it would be true for triangle lists if we decided |
| to expose this capability. My preference would be to not |
| expose this, since all it really does is create a documentation |
| headache. The user can always define a generalized triangle list |
| with consistently wound triangles using the CCW variant of restart. |
| Supporting both types of restart just doesn't fit into OpenGL's |
| (or Java 3D's) model cleanly. |
| |
| [NOTE: a decision has been made to not expose the CW/CCW feature] |
| |
| 2. Enumerated values for replacement codes |
| |
| Enumerated values used for extensions are typically defined as |
| integers in a specified range. This range depends on whether |
| they are vendor private (_SUN) or multi-vendor (_EXT or _ARB) |
| extensions. For this extension, we are defining a new |
| replacement code attribute that is part of the vertex state |
| and is expected to be processed directly by hardware. Given |
| this, we have defined the replacement codes as small integer |
| values (1, 2, and 3) that correspond with what the hardware |
| wants to see. The cost for having these values be different, |
| especially for replacement codes in a vertex array, are too |
| great. |
| |
| Another reason for not using constants in the range of |
| extension enums is that if this ever became part of the core |
| after first being an extension, or even if it became a |
| multi-vendor extension after first being a Sun-private |
| extension, then the codes would change. This would be |
| unworkable for an attribute such as this, since it is part of |
| the vertex pipeline. |
| |
| We need to ensure that our current plan of defining |
| replacement codes outside the range of extension enums is not |
| violating any rules. I think that this shouldn't be a problem |
| since the replacement codes themselves are really just |
| parameters to the replacement code command. As such, they are |
| just bit patterns and shouldn't need to be unique. |
| |
| |
| New Procedures and Functions |
| |
| void ReplacementCodeuiSUN(uint code); |
| |
| void ReplacementCodeusSUN(ushort code); |
| |
| void ReplacementCodeubSUN(ubyte code); |
| |
| void ReplacementCodeuivSUN(const uint *code); |
| |
| void ReplacementCodeusvSUN(const ushort *code); |
| |
| void ReplacementCodeubvSUN(const ubyte *code); |
| |
| void ReplacementCodePointerSUN(enum type, |
| sizei stride, |
| const void *pointer); |
| |
| |
| New Tokens |
| |
| Accepted by the <mode> parameter of Begin, DrawArrays, |
| DrawElements, MultiDrawArraysSUN, MultiDrawArraysEXT, |
| MultiDrawElementsSUN, and MultiDrawElementsEXT: |
| |
| TRIANGLE_LIST_SUN 0x81D7 |
| |
| Accepted by the by the <pname> parameter of GetBooleanv, |
| GetIntegerv, GetFloatv, and GetDoublev: |
| |
| REPLACEMENT_CODE_SUN 0x81D8 |
| |
| Accepted by the <code> parameter of ReplacementCode{ui,us,ub}[v]SUN: |
| |
| RESTART_SUN 0x01 |
| REPLACE_MIDDLE_SUN 0x02 |
| REPLACE_OLDEST_SUN 0x03 |
| |
| Accepted by the <array> parameter of EnableClientState and |
| DisableClientState, and by the <cap> parameter of IsEnabled: |
| |
| REPLACEMENT_CODE_ARRAY_SUN 0x85C0 |
| |
| Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, |
| GetFloatv, and GetDoublev: |
| |
| REPLACEMENT_CODE_ARRAY_TYPE_SUN 0x85C1 |
| REPLACEMENT_CODE_ARRAY_STRIDE_SUN 0x85C2 |
| |
| Accepted by the <pname> parameter of GetPointerv: |
| |
| REPLACEMENT_CODE_ARRAY_POINTER_SUN 0x85C3 |
| |
| |
| Accepted by the <format> parameter of InterleavedArrays: |
| |
| R1UI_V3F_SUN 0x85C4 |
| R1UI_C4UB_V3F_SUN 0x85C5 |
| R1UI_C3F_V3F_SUN 0x85C6 |
| R1UI_N3F_V3F_SUN 0x85C7 |
| R1UI_C4F_N3F_V3F_SUN 0x85C8 |
| R1UI_T2F_V3F_SUN 0x85C9 |
| R1UI_T2F_N3F_V3F_SUN 0x85CA |
| R1UI_T2F_C4F_N3F_V3F_SUN 0x85CB |
| |
| |
| Additions to Chapter 2 of the GL Specification (OpenGL Operation) |
| |
| Replacement Code |
| ---------------- |
| The replacement code is a per-vertex state attribute that controls |
| triangle vertex replacement for the triangle list primitive; it is |
| ignored for all other primitives. This state attribute is set by |
| the ReplacementCodeSUN command. Since it is part of the vertex state, |
| the ReplacementCodeSUN command may appear within a Begin/End pair. The |
| replacement code is an enum with 3 values, RESTART_SUN, |
| REPLACE_MIDDLE_SUN, and REPLACE_OLDEST_SUN. |
| |
| Note that the replacement code follows the same rules as other |
| per-vertex state attributes. The current value of the replacement |
| code state attribute affects subsequent vertices until the next |
| time the ReplacementCodeSUN command is executed, updating the value |
| of the state attribute. This means that a replacement code that is |
| set outside of a Begin/End will affect subsequent triangle lists in |
| which the replacement code is not set. Similarly, the value of the |
| last replacement code set within a Begin/End will affect subsequent |
| triangle lists in which the replacement code is not set. |
| |
| Triangle List |
| ------------- |
| A triangle list primitive is a series of triangles that are |
| connected according to the replacement codes associated with each |
| vertex in the list. A triangle list is specified by giving a |
| series of defining vertices between a Begin/End pair when Begin is |
| called with TRIANGLE_LIST. As with a triangle strip and a triangle |
| fan, the first three vertices define a triangle. The order of the |
| three vertices is significant. Subsequent vertices either define a |
| triangle that is connected to the previous triangle using the new |
| vertex and two vertices from the previous triangle, or they restart |
| a new triangle, depending on the value specified by the replacement |
| code state. The edge flag attribute is ignored by the triangle list |
| primitive. If PolygonMode is set to LINE or POINT, then all edges |
| or vertices are drawn (as with TRIANGLE_STRIP and TRIANGLE_FAN). |
| |
| In addition to the current vertex, the state required to support |
| triangle lists consists of a 2-bit vertex counter that indicates |
| the number of vertices since the beginning of the list or since a |
| restart, two stored processed vertices, and a one-bit pointer |
| indicating the order of drawing (oldest-middle-current versus |
| middle-oldest-current). |
| |
| The rules for determining when to draw a triangle and what vertices |
| to use and in what order are as follows: |
| |
| 1. When a BEGIN command is called with TRIANGLE_LIST, the vertex |
| counter is set to 0. |
| |
| 2. When a new vertex is completed, the following logic is used to |
| process the vertex: |
| |
| if (vertex_counter == 0) { |
| vertex_counter = 1 |
| drawing_order = 0 |
| vertexA = currentVertex |
| } |
| else if (vertex_counter == 1) { |
| vertex_counter = 2 |
| vertexB = currentVertex |
| } |
| else if (vertex_counter == 2) { |
| vertex_counter = 3 |
| draw(vertexA, vertexB, currentVertex) |
| } |
| else { |
| if (repl_code == RESTART) { |
| vertex_counter = 1 |
| drawing_order = 0 |
| vertexA = currentVertex |
| } |
| else { |
| if (repl_code == REPLACE_OLDEST) |
| drawing_order = !drawing_order |
| |
| if (drawing_order == 0) |
| draw(vertexA, vertexB, currentVertex) |
| else |
| draw(vertexB, vertexA, currentVertex) |
| |
| if (repl_code == REPLACE_OLDEST) |
| vertexA = vertexB |
| vertexB = currentVertex |
| } |
| } |
| |
| If a triangle list has fewer than 3 vertices then no triangles are |
| drawn. If a triangle list has fewer than 2 vertices following a |
| vertex with a RESTART replacement code, then the restart is |
| ignored, along with the one vertex after the restart, if present. |
| |
| Because the replacement code is ignored for the first vertex and |
| the two vertices immediately following a restart, a constant |
| replacement code has a well-defined, consistent semantic. If the |
| replacement code for each vertex is REPLACE_OLDEST, then a triangle |
| strip will be drawn. If the replacement code for each vertex is |
| REPLACE_MIDDLE, then a triangle fan will be drawn. If the |
| replacement code for each vertex is RESTART, then isolated |
| triangles will be drawn. |
| |
| The following example illustrates the use of vertex replacement |
| within a single triangle list to draw triangle strips, triangle |
| fans, isolated triangles, and, finally, a triangle strip that |
| switches to a fan and back to a strip without a restart. In this |
| example REPLACE_OLDEST is abbreviated RO and REPLACE_MIDDLE is |
| abbreviated RM. Note that the initial RESTART replacement appears |
| in square brackets, indicating that it is an implicit restart; the |
| replacement code is ignored for the first vertex following a begin |
| command. The replacement code is also ignored for the two |
| vertices immediately following a restart. |
| |
| 2 4 6 |
| V1 [RESTART] .-------.-------. |
| V2 -- /\ /\ / |
| V3 -- / \ / \ / |
| V4 RO / \ / \ / Triangle Strip |
| V5 RO / \/ \/ |
| V6 RO .-------.-------. |
| 1 3 5 |
| |
| 9.-------.10 |
| /\ /\ |
| V7 RESTART / \ / \ |
| V8 -- / \ / \ |
| V9 -- / \/ \ |
| V10 RM 8.------.7-------.11 Triangle Fan |
| V11 RM 14\ /\ / |
| V12 RM \ / \ / |
| V13 RM \ / \ / |
| V14 RM \/ \/ |
| .-------. |
| 13 12 |
| |
| 16 19 |
| V15 RESTART . . |
| V16 -- /\ /\ |
| V17 -- / \ / \ |
| V18 RESTART / \ / \ Isolated Triangles |
| V19 -- / \ / \ |
| V20 -- .--------. .--------. |
| 15 17 18 20 |
| |
| 22 24 26 |
| .-----.-----. |
| V21 RESTART |\ |\ |\ |
| V22 -- | \ | \ | \ |
| V23 -- | \ | \ | .27 |
| V24 RO | \ | \ | /\ |
| V25 RO | \| 25/ \ |
| V26 RO .-----.-----.---.28 Mixed Strip & Fan |
| V27 RO 21 23 /|\ | |
| V28 RM / | \ | |
| V29 RM / | \| |
| V30 RM .---.---.29 |
| V31 RM 31\ /30 |
| V32 RO \ / |
| . |
| 32 |
| |
| |
| |
| Triangle list primitives may be drawn using vertex arrays in the |
| same manner as other primitives. The replacement code state flag |
| may be enabled as part of a vertex array operation. The |
| REPLACEMENT_CODE_ARRAY_SUN enum is used to enable or disable the |
| replacement code array using the EnableClientState and |
| DisableClientState functions. |
| |
| The following function defines the type, stride, and pointer for |
| the replacement code data. |
| |
| void ReplacementCodePointerSUN(enum type, |
| sizei stride, |
| const void *pointer); |
| |
| Legal values for type are UNSIGNED_BYTE, UNSIGNED_SHORT, and |
| UNSIGNED_INT. As with other vertex state, the value of the |
| replacement code attribute is undefined after a vertex array |
| command has been executed. |
| |
| The following describes the memory layout of the new interleaved |
| array types. These new types may be used as the format parameter |
| of the InterleavedArrays function. |
| |
| format pt pc pn pv s |
| --------------------- ------ ------ ------ ------ ------ |
| R1UI_V3F i i+3f |
| R1UI_C4UB_V3F i i+c i+c+3f |
| R1UI_C3F_V3F i i+3f i+6f |
| R1UI_N3F_V3F i i+3f i+6f |
| R1UI_C4F_N3F_V3F i i+4f i+7f i+10f |
| R1UI_T2F_V3F i i+2f i+5f |
| R1UI_T2F_N3F_V3F i i+2f i+5f i+8f |
| R1UI_T2F_C4F_N3F_V3F i i+2f i+6f i+9f i+12f |
| |
| Where i is sizeof(UNSIGNED_INT) rounded up to the nearest multiple of |
| f. The replacement code pointer always starts at offset 0 from the |
| interleaved array pointer. |
| |
| |
| Additions to Chapter 3 of the GL Specification (Rasterization) |
| |
| None |
| |
| |
| Additions to Chapter 4 of the GL Specification (Per-Fragment Operations |
| and the Framebuffer) |
| |
| None |
| |
| |
| Additions to Chapter 5 of the GL Specification (Special Functions) |
| |
| None |
| |
| |
| Additions to Chapter 6 of the GL Specification (State and State Requests) |
| |
| None |
| |
| Additions to the GLX / WGL / AGL Specifications |
| |
| None |
| |
| GLX Protocol |
| |
| Three rendering commands are sent to the server as part of |
| the glXRender request: |
| |
| ReplacementCodeuiSUN |
| 2 8 rendering command length |
| 2 16388 rendering command opcode |
| 4 CARD32 code |
| |
| ReplacementCodeubSUN |
| 2 8 rendering command length |
| 2 16389 rendering command opcode |
| 1 CARD8 code |
| 1 CARD8 pad |
| 2 CARD16 pad |
| |
| ReplacementCodeusSUN |
| 2 8 rendering command length |
| 2 16390 rendering command opcode |
| 2 CARD16 code |
| 2 CARD16 pad |
| |
| |
| Errors |
| |
| INVALID_ENUM is generated if ReplacementCodePointerSUN parameter |
| <type> is not UNSIGNED_BYTE, UNSIGNED_SHORT, or UNSIGNED_INT. |
| |
| INVALID_VALUE is generated if ReplacementCodePointerSUN parameter |
| <stride> is negative. |
| |
| |
| New State |
| |
| Get Value Get Command Type Initial Value |
| --------- ----------- ---- ------------- |
| REPLACEMENT_CODE_SUN GetIntegerv Z4 REPLACE_OLDEST |
| REPLACEMENT_CODE_ARRAY_SUN IsEnabled B False |
| REPLACEMENT_CODE_ARRAY_TYPE_SUN GetIntegerv Z3 UNSIGNED_INT |
| REPLACEMENT_CODE_ARRAY_STRIDE_SUN GetIntegerv Z+ 0 |
| REPLACEMENT_CODE_ARRAY_POINTER_SUN GetPointerv Y 0 |
| |
| Get Value Attribute |
| --------- --------- |
| REPLACEMENT_CODE_SUN current |
| REPLACEMENT_CODE_ARRAY_SUN vertex-array |
| REPLACEMENT_CODE_ARRAY_TYPE_SUN vertex-array |
| REPLACEMENT_CODE_ARRAY_STRIDE_SUN vertex-array |
| REPLACEMENT_CODE_ARRAY_POINTER_SUN vertex-array |
| |
| New Implementation Dependent State |
| |
| None |
| |
| Revision History |
| |
| 6/25/99 Added fields from the new extension template. |