| Name |
| |
| ARB_viewport_array |
| |
| Name Strings |
| |
| GL_ARB_viewport_array |
| |
| Contributors |
| |
| Graham Sellers, AMD |
| Mark Young, AMD |
| Nick Haemel, AMD |
| Bill Licea-Kane, AMD |
| Jeff Bolz, NVIDIA |
| Daniel Koch, TransGaming |
| Pat Brown, NVIDIA |
| Bruce Merry, ARM |
| Ian Stewart, NVIDIA |
| |
| Contact |
| |
| Graham Sellers, AMD (graham.sellers 'at' amd.com) |
| |
| Notice |
| |
| Copyright (c) 2010-2013 The Khronos Group Inc. Copyright terms at |
| http://www.khronos.org/registry/speccopyright.html |
| |
| Specification Update Policy |
| |
| Khronos-approved extension specifications are updated in response to |
| issues and bugs prioritized by the Khronos OpenGL Working Group. For |
| extensions which have been promoted to a core Specification, fixes will |
| first appear in the latest version of that core Specification, and will |
| eventually be backported to the extension document. This policy is |
| described in more detail at |
| https://www.khronos.org/registry/OpenGL/docs/update_policy.php |
| |
| Status |
| |
| Complete. Approved by the ARB on June 9, 2010. |
| Approved by the Khronos Board of Promoters on July 23, 2010. |
| |
| Version |
| |
| Last Modified Date: 06/25/2012 |
| Author Revision: 18 |
| |
| Number |
| |
| ARB Extension #100 |
| |
| Dependencies |
| |
| OpenGL 1.0 is required. |
| |
| OpenGL 3.2 or the EXT_geometry_shader4 or ARB_geometry_shader4 extensions |
| are required. |
| |
| This extension is written against the OpenGL 3.2 (Compatibility) |
| Specification. |
| |
| This extension is written against the OpenGL Shading Language Specification |
| version 1.50.09. |
| |
| Overview |
| |
| OpenGL is modeled on a pipeline of operations. The final stage in this |
| pipeline before rasterization is the viewport transformation. This stage |
| transforms vertices from view space into window coordinates and allows the |
| application to specify a rectangular region of screen space into which |
| OpenGL should draw primitives. Unextended OpenGL implementations provide a |
| single viewport per context. In order to draw primitives into multiple |
| viewports, the OpenGL viewport may be changed between several draw calls. |
| With the advent of Geometry Shaders, it has become possible for an |
| application to amplify geometry and produce multiple output primitives |
| for each primitive input to the Geometry Shader. It is possible to direct |
| these primitives to render into a selected render target. However, all |
| render targets share the same, global OpenGL viewport. |
| |
| This extension enhances OpenGL by providing a mechanism to expose multiple |
| viewports. Each viewport is specified as a rectangle. The destination |
| viewport may be selected per-primitive by the geometry shader. This allows |
| the Geometry Shader to produce different versions of primitives destined |
| for separate viewport rectangles on the same surface. Additionally, when |
| combined with multiple framebuffer attachments, it allows a different |
| viewport rectangle to be selected for each. This extension also exposes a |
| separate scissor rectangle for each viewport. Finally, the viewport bounds |
| are now floating point quantities allowing fractional pixel offsets to be |
| applied during the viewport transform. |
| |
| IP Status |
| |
| No known IP claims. |
| |
| New Procedures and Functions |
| |
| void ViewportArrayv(uint first, sizei count, const float * v); |
| void ViewportIndexedf(uint index, float x, float y, float w, float h); |
| void ViewportIndexedfv(uint index, const float * v); |
| void ScissorArrayv(uint first, sizei count, const int * v); |
| void ScissorIndexed(uint index, int left, int bottom, sizei width, sizei height); |
| void ScissorIndexedv(uint index, const int * v); |
| void DepthRangeArrayv(uint first, sizei count, const clampd * v); |
| void DepthRangeIndexed(uint index, clampd n, clampd f); |
| void GetFloati_v(enum target, uint index, float *data); |
| void GetDoublei_v(enum target, uint index, double *data); |
| |
| void GetIntegerIndexedvEXT(enum target, uint index, int * v); |
| void EnableIndexedEXT(enum target, uint index); |
| void DisableIndexedEXT(enum target, uint index); |
| boolean IsEnabledIndexedEXT(enum target, uint index); |
| |
| Note that GetIntegerIndexedvEXT, EnableIndexedEXT, DisableIndexedEXT and |
| IsEnabledIndexedEXT are introduced by other OpenGL extensions such as |
| EXT_draw_buffers2. If this extension is implemented against an earlier |
| version of OpenGL that does not support GetIntegeri_v and so on, the |
| 'Indexed' versions of these functions may be used in their place. |
| |
| New Tokens |
| |
| Accepted by the <pname> parameter of GetBooleanv, GetIntegerv, GetFloatv, |
| GetDoublev and GetInteger64v: |
| |
| MAX_VIEWPORTS 0x825B |
| VIEWPORT_SUBPIXEL_BITS 0x825C |
| VIEWPORT_BOUNDS_RANGE 0x825D |
| LAYER_PROVOKING_VERTEX 0x825E |
| VIEWPORT_INDEX_PROVOKING_VERTEX 0x825F |
| |
| Accepted by the <pname> parameter of GetIntegeri_v: |
| |
| SCISSOR_BOX 0x0C10 |
| |
| Accepted by the <pname> parameter of GetFloati_v: |
| |
| VIEWPORT 0x0BA2 |
| |
| Accepted by the <pname> parameter of GetDoublei_v: |
| |
| DEPTH_RANGE 0x0B70 |
| |
| Accepted by the <pname> parameter of Enablei, Disablei, and IsEnabledi: |
| |
| SCISSOR_TEST 0x0C11 |
| |
| Returned in the <data> parameter from a Get query with a <pname> of |
| LAYER_PROVOKING_VERTEX or VIEWPORT_INDEX_PROVOKING_VERTEX: |
| |
| FIRST_VERTEX_CONVENTION 0x8E4D |
| LAST_VERTEX_CONVENTION 0x8E4E |
| PROVOKING_VERTEX 0x8E4F |
| UNDEFINED_VERTEX 0x8260 |
| |
| Additions to Chapter 2 of the OpenGL 3.2 (Compatibility) Specification (OpenGL |
| Operation) |
| |
| Modifications to Section 2.15.4, Geometry Shader Execution Environment |
| |
| Add a paragraph after the description of gl_Layer, page 124. |
| |
| The built-in special variable gl_ViewportIndex is used to direct |
| rendering to one of several viewports and is discussed in the section |
| entitled "Layer and Viewport Selection", below. |
| |
| Rename the the "Layered Rendering" subsection to "Layer and Viewport |
| Selection" and append the following: |
| |
| Geometry shaders may also select the destination viewport for each |
| output primitive. The destination viewport for a primitive may be |
| selected in the geometry shader by writing to the built-in output |
| variable gl_ViewportIndex. This functionality allows a geometry |
| shader to direct its output to a different viewport for each |
| primitive, or to draw multiple versions of a primitive into several |
| different viewports. |
| |
| The specific vertex of a primitive that is used to select the |
| rendering layer or viewport index is implementation-dependent and |
| thus portable applications will assign the same layer and viewport |
| index for all vertices in a primitive. The vertex conventions |
| followed for gl_Layer and gl_ViewportIndex may be determined by |
| calling GetIntegerv with the symbolic constants |
| LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX, |
| respectively. For either value, if the value returned is |
| PROVOKING_VERTEX, then vertex selection follows the convention |
| specified by ProvokingVertex (see section 2.21). If the value |
| returned is FIRST_VERTEX_CONVENTION, selection is always taken from |
| the first vertex of a primitive. If the value returned is |
| LAST_VERTEX_CONVENTION, the selection is always taken from the last |
| vertex of a primitive. If the value returned is UNDEFINED_VERTEX, |
| the selection is not guaranteed to be taken from any specific vertex |
| in the primitive. The vertex considered the provoking vertex for |
| particular primitive types is given in Table 2.15. |
| |
| Modify section 2.16.1 "Controlling the Viewport", page 126. |
| |
| Change the first paragraph of section 2.16.1 to read |
| |
| The viewport transformation is determined by the selected viewport's |
| width and height in pixels, p_x and p_y, respectively, and its |
| center (o_x,o_y) (also in pixels) ... |
| |
| { leave equations intact } |
| |
| Multiple viewports are available and are numbered zero through the |
| value of MAX_VIEWPORTS minus one. If a geometry shader is active and |
| writes to gl_ViewportIndex, the viewport transformation uses the |
| viewport corresponding to the value assigned to gl_ViewportIndex |
| taken from an implementation-dependent primitive vertex. If the |
| value of the viewport index is outside the range zero to the value |
| of MAX_VIEWPORTS minus one, the results of the viewport |
| transformation are undefined. If no geometry shader is active, or if |
| the active geometry shader does not write to gl_ViewportIndex, the |
| viewport numbered zero is used by the viewport transformation. |
| |
| A single vertex may be used in more than one individual primitive, in |
| primitives such as TRIANGLE_STRIP. In this case, the viewport |
| transformation is applied separately for each primitive. |
| |
| The factor and offset applied to Z_d for each viewport encoded by n |
| and f are set using |
| |
| void DepthRangeArrayv(uint first, sizei count, const clampd * v); |
| void DepthRangeIndexed(uint index, clampd n, clampd f); |
| void DepthRange(clampd n, clampd f); |
| |
| DepthRangeArrayv is used to specify the depth range for multiple |
| viewports simultaneously. <first> specifies the index of the first |
| viewport to modify and <count> specifies the number of viewports. If |
| (<first> + <count>) is greater than the value of MAX_VIEWPORTS then |
| an INVALID_VALUE error will be generated. Viewports whose indices |
| lie outside the range [<first>, <first> + <count>) are not modified. |
| The <v> parameter contains the address of an array of clampd types |
| specifying near (n) and far (f) for each viewport in that order. |
| |
| DepthRangeIndexed specifies the depth range for a single viewport |
| and is equivalent (assuming no errors are generated) to: |
| |
| clampd v[] = { n, f }; |
| DepthRangeArrayv(index, 1, v); |
| |
| DepthRange sets the depth range for all viewports to the same values |
| and is equivalent (assuming no errors are generated) to: |
| |
| for (uint i = 0; i < MAX_VIEWPORTS; i++) |
| DepthRangeIndexed(i, n, f); |
| |
| Z_w is represented as either ... |
| |
| Replace the end of section 2.16.1, starting from "Viewport transformation |
| parameters are specified using..." |
| |
| Viewport transformation parameters are specified using |
| |
| void ViewportArrayv(uint first, sizei count, const float * v); |
| void Viewport(int x, int y, sizei w, sizei h); |
| void ViewportIndexedf(uint index, float x, float y, float w, float h); |
| void ViewportIndexedfv(uint index, const float * v); |
| |
| ViewportArrayv specifies parameters for multiple viewports |
| simultaneously. <first> specifies the index of the first viewport to |
| modify and <count> specifies the number of viewports. If (<first> + |
| <count>) is greater than the value of MAX_VIEWPORTS then an |
| INVALID_VALUE error will be generated. Viewports whose indices lie |
| outside the range [<first>, <first> + <count>) are not modified. |
| <v> contains the address of an array of floating point values |
| specifying the left (x), bottom (y), width (w) and height (h) of |
| each viewport, in that order. <x> and <y> give the location of the |
| viewport's lower left corner and <w> and <h> give the viewport's |
| width and height, respectively. |
| |
| ViewportIndexedf and ViewportIndexedfv specify parameters for a |
| single viewport and are equivalent (assuming no errors are |
| generated) to: |
| |
| float v[4] = { x, y, w, h }; |
| ViewportArrayv(index, 1, v); |
| |
| and |
| |
| ViewportArrayv(index, 1, v); |
| |
| respectively. |
| |
| Viewport sets the parameters for all viewports to the same values |
| and is equivalent (assuming no errors are generated) to: |
| |
| for (uint i = 0; i < MAX_VIEWPORTS; i++) |
| ViewportIndexedf(i, 1, (float)x, (float)y, (float)w, (float)h); |
| |
| The viewport parameters shown in the above equations are found from these |
| values as |
| |
| o_x = x + w /2, |
| o_y = y + h / 2, |
| p_x = w, |
| p = h. |
| |
| The location of the viewport's bottom-left corner, given by (x,y), are |
| clamped to be within the implementation-dependent viewport bounds range. |
| The viewport bounds range [min, max] tuple may be determined by |
| calling GetFloatv with the symbolic constant VIEWPORT_BOUNDS_RANGE |
| (see section 6.1). |
| |
| Viewport width and height are clamped to implementation-dependent maximums |
| when specified. The maximum width and height may be found by calling |
| GetFloatv with the symbolic constant MAX_VIEWPORT_DIMS. The maximum |
| viewport dimensions must be greater than or equal to the larger of |
| the visible dimensions of the display being rendered to (if a |
| display exists), and the largest renderbuffer image which can be |
| successfully created and attached to a framebuffer object (see |
| chapter 4). INVALID_VALUE is generated if either w or h is negative. |
| |
| The state required to implement the viewport transformations is four |
| floating-point values and two clamped floating-point values for each |
| viewport. In the initial state, w and h for each viewport are set to |
| the width and height, respectively, of the window into which the GL |
| is to do its rendering. If the default framebuffer is bound but no |
| default framebuffer is associated with the GL context (see chapter |
| 4), then w and h are initially set to zero. o_x and o_y are set to |
| w/2 and h/2, respectively. n and f are set to 0.0 and 1.0, |
| respectively. |
| |
| The precision with which the GL interprets the floating point viewport |
| bounds is implementation-dependent and may be determined by querying the |
| implementation-defined constant VIEWPORT_SUBPIXEL_BITS. |
| |
| Additions to Chapter 3 of the OpenGL 3.2 (Compatibility) Specification |
| (Rasterization) |
| |
| None. |
| |
| Additions to Chapter 4 of the OpenGL 3.2 (Compatibility) Specification (Per- |
| Fragment Operations and the Framebuffer) |
| |
| Replace section 4.1.2 "Scissor Test", page 284. |
| |
| The scissor test determines if (xw, yw) lies within the scissor rectangle |
| defined by four values for each viewport. These values are set with |
| |
| void ScissorArrayv(uint first, sizei count, const int * v); |
| void ScissorIndexed(uint index, int left, int bottom, sizei width, sizei height); |
| void ScissorIndexedv(uint index, int * v); |
| void Scissor(int left, int bottom, sizei width, sizei height); |
| |
| ScissorArrayv defines a set of scissor rectangles that are each |
| applied to the corresponding viewport (see section 2.16.1 |
| "Controlling the Viewport"). <first> specifies the index of the |
| first scissor rectangle to modify, and <count> specifies the number |
| of scissor rectangles. If (<first> + <count>) is greater than the |
| value of MAX_VIEWPORTS, then an INVALID_VALUE error is generated. |
| <v> contains the address of an array of integers containing the |
| left, bottom, width and height of the scissor rectangles, in that |
| order. |
| |
| If left <= x_w < left + width and bottom <= y_w < bottom + height |
| for the selected scissor rectangle, then the scissor test passes. |
| Otherwise, the test fails and the fragment is discarded. For points, |
| lines, and polygons, the scissor rectangle for a primitive is |
| selected in the same manner as the viewport (see section 2.16.1). |
| For pixel rectangles and bitmaps, the scissor rectangle numbered |
| zero is used for the scissor test. |
| |
| The scissor test is enabled or disabled for all viewports using |
| Enable or Disable with the symbolic constant SCISSOR_TEST. The test |
| is enabled or disabled for a specific viewport using Enablei or |
| Disablei with the constant SCISSOR_TEST and the index of the |
| selected viewport. When disabled, it is as if the scissor test |
| always passes. The value of the scissor test enable for viewport <i> |
| can be queried by calling IsEnabledi with <target> SCISSOR_TEST and |
| <index> <i>. The value of the scissor test enable for viewport zero |
| may also be queried by calling IsEnabled with the same symbolic |
| constant, but no <index> parameter. If either width or height is |
| less than zero for any scissor rectangle, then an INVALID_VALUE |
| error is generated. If the viewport index specified to Enablei, |
| Disablei or IsEnabledi is greater or equal to the value of |
| MAX_VIEWPORTS, then an INVALID_VALUE error is generated. |
| |
| The state required consists of four integer values per viewport, and |
| a bit indicating whether the test is enabled or disabled for each |
| viewport. In the initial state, left = bottom = 0, and width and |
| height are determined by the size of the window into which the GL is |
| to do its rendering for all viewports. If the default framebuffer is |
| bound but no default framebuffer is associated with the GL context |
| (see chapter 4), then with and height are initially set to zero. |
| Initially, the scissor test is disabled for all viewports. |
| |
| ScissorIndexed and ScissorIndexedv specify the scissor rectangle for |
| a single viewport and are equivalent (assuming no errors are |
| generated) to: |
| |
| int v[] = { left, bottom, width, height }; |
| ScissorArrayv(index, 1, v); |
| |
| and |
| |
| ScissorArrayv(index, 1, v); |
| |
| respectively. |
| |
| Scissor sets the scissor rectangle for all viewports to the same |
| values and is equivalent (assuming no errors are generated) to: |
| |
| for (uint i = 0; i < MAX_VIEWPORTS; i++) { |
| ScissorIndexed(i, left, bottom, width, height); |
| } |
| |
| Calling Enable or Disable with the symbolic constant SCISSOR_TEST is |
| equivalent, assuming no errors, to: |
| |
| for (uint i = 0; i < MAX_VIEWPORTS; i++) { |
| Enablei(SCISSOR_TEST, i); |
| /* or */ |
| Disablei(SCISSOR_TEST, i); |
| } |
| |
| Additions to Chapter 5 of the OpenGL 3.2 (Compatibility) Specification (Special |
| Functions) |
| |
| None. |
| |
| Additions to Chapter 6 of the OpenGL 3.2 (Compatibility) Specification (State |
| and State Requests) |
| |
| Modifications to Section 6.1.1 Simple Queries |
| |
| Add to the list of indexed query functions: |
| |
| void GetFloati_v(enum target, uint index, float *data); |
| void GetDoublei_v(enum target, uint index, float *data); |
| |
| Additions to the OpenGL Shading Language Version 1.50.09 Specification |
| |
| Add a new Section 3.3.x, GL_ARB_viewport_array Extension (p. 13) |
| |
| 3.3.x GL_ARB_viewport_array Extension |
| |
| To use the GL_ARB_viewport_array extension in a shader it must be |
| enabled using the #extension directive. |
| |
| The shading language preprocessor #define GL_ARB_viewport_array will |
| be defined to 1 if the GL_ARB_viewport_array extension is supported. |
| |
| Additions to Section 7.1 "Vertex and Geometry Shader Special Variables" |
| |
| Add a paragraph after the paragraph describing gl_Layer, starting "The |
| built-in output variable gl_Layer is available only in the geometry |
| language, and provides the number of the layer of textures attached to a |
| FBO to direct rendering to.": |
| |
| The built-in output variable gl_ViewportIndex is available only in the |
| geometry language, and provides the index of the viewport to which the |
| next primitive emitted from the geometry shader should be drawn. Primitives |
| generated by the geometry shader will undergo viewport transformation and |
| scissor testing using the viewport transformation and scissor rectangle |
| selected by the value of gl_ViewportIndex. The viewport index used will |
| come from one of the vertices in the primitive being shaded. Which vertex |
| the viewport index comes from is implementation-dependent, so it is best to |
| use the same viewport index for all vertices of the primitive. If a geometry |
| shader does not assign a value to gl_ViewportIndex, viewport transform |
| and scissor rectangle zero will be used. If a geometry shader assigns a |
| value to gl_ViewportIndex and there is a path through the shader that |
| does not set gl_ViewportIndex, then the value of gl_ViewportIndex is |
| undefined for executions of the shader that take that path. See section |
| 2.15.4, under "Geometry Shader Outputs" for more information. |
| |
| Add to the list of geometry shader built-in variables on p. 69: |
| |
| out int gl_ViewportIndex; // may be written to |
| |
| Modify the description of EmitVertex() in Section 8.10, "Geometry Shader |
| Functions", page 104: |
| |
| The function EmitVertex() specifies that a vertex is completed. A vertex |
| is added to the current output primitive using the current values of the |
| geometry shader's output variables, including gl_PointSize, gl_ClipDistance, |
| gl_Layer, gl_Position, gl_PrimitiveID and gl_ViewportIndex. The values |
| of all these... |
| |
| Add to the list of built in constants available to geometry shaders in |
| Section 7.4: |
| |
| const int gl_MaxViewports = 16; |
| |
| Additions to the AGL/GLX/WGL Specifications |
| |
| None. |
| |
| GLX Protocol |
| |
| TBD. |
| |
| Errors |
| |
| INVALID_VALUE is generated by ViewportArrayv if <first> + <count> is |
| greater than or equal to the value of MAX_VIEWPORTS, or if any |
| viewport's width or height is less than 0. |
| |
| INVALID_VALUE is generated by ScissorArrayv if <first> + <count> is |
| greater than or equal to the value of MAX_VIEWPORTS, or if any |
| scissor rectangle's width or height is less than zero. |
| |
| INVALID_VALUE is generated by DepthRangeArrayv if <first> + <count> is |
| greater than or equal to the vaue of MAX_VIEWPORTS. |
| |
| INVALID_VALUE is generated by Enablei, Disablei and IsEnabledi if |
| <index> is greater than or equal to the value of MAX_VIEWPORTS. |
| |
| New State |
| |
| Table 6.13 (p. 405) |
| |
| Get Value Type Get Command Initial Value Description Sec Attribute |
| ------------------------ ---------------- ------------ ------------- ------------------------ ----- --------- |
| VIEWPORT 16* x 4 x R GetFloati_v See 2.11.1 Viewport origin & extent 2.11.1 viewport |
| DEPTH_RANGE 16* x 2 x R[0,1] GetDoublei_v See 2.16.1 Depth range near & far 2.16.1 viewport |
| |
| NOTE: The changes are that VIEWPORT and DEPTH_RANGE are extended to |
| accommodate 16* copies and now consist of floating-point and |
| double-precision values, respectively. |
| |
| Table 6.26 (p. 418) |
| |
| Get Value Type Get Command Initial Value Description Sec Attribute |
| ------------------------ ---------- ------------- ------------- ------------------- ----- --------- |
| SCISSOR_TEST 16* x B IsEnabledi FALSE Scissoring enabled 4.1.2 scissor/enable |
| SCISSOR_BOX 16* x 4 x Z GetIntegeri_v See 4.1.2 Scissor box 4.1.2 scissor |
| |
| NOTE: The only change is that SCISSOR_TEST and SCISSOR_BOX are extended |
| to accommodate 16* copies. |
| |
| New Implementation Dependent State |
| |
| Get Value Type Get Command Minimum Value Description Sec. |
| --------- ---- ----------- ------------- ------------------- ----- |
| MAX_VIEWPORT_DIMS (NOTE 1) 2 x Z+ GetFloatv See 2.16.1 Maximum viewport dimensions 2.16.1 |
| MAX_VIEWPORTS Z+ GetIntegerv 16 Maximum number of 2.16.1 |
| active viewports |
| VIEWPORT_SUBPIXEL_BITS Z+ GetIntegerv 0 Number of bits of sub-pixel 2.16.1 |
| precision for viewport bounds |
| VIEWPORT_BOUNDS_RANGE 2 x R GetFloatv (NOTE 2) Viewport bounds range [min,max] 2.16.1 |
| LAYER_PROVOKING_VERTEX Z_4 GetIntegerv -- (NOTE 3) vertex convention followed by 2.15.4 |
| the gl_Layer GLSL variable |
| VIEWPORT_INDEX_PROVOKING_VERTEX Z_4 GetIntegerv -- (NOTE 3) vertex convention followed by 2.15.4 |
| the gl_ViewportIndex GLSL |
| variable |
| |
| NOTE 1: The recommended get command is changed from GetIntegerv to GetFloatv. |
| NOTE 2: range for viewport bounds: |
| * On GL3-capable hardware the VIEWPORT_BOUNDS_RANGE should be at least |
| [-16384, 16383]. |
| * On GL4-capable hardware the VIEWPORT_BOUNDS_RANGE should be at least |
| [-32768, 32767]. |
| NOTE 3: Valid values are: FIRST_VERTEX_CONVENTION, |
| LAST_VERTEX_CONVENTION, PROVOKING_VERTEX, UNDEFINED_VERTEX. |
| |
| Interactions with NV_depth_buffer_float |
| |
| If NV_depth_buffer_float is supported, add the following commands: |
| |
| void DepthRangeArraydvNV(uint first, sizei count, const double * v); |
| void DepthRangeIndexeddNV(uint index, double n, double f); |
| |
| These functions are equivalent to the corresponding DepthRange* |
| functions, except the the parameters are clamped to [0, 1] when using |
| DepthRange*, but not when using DepthRange*dNV. When <n> and <f> are |
| applied to <z_d>, they are clamped to the range appropriate given the |
| depth buffer's representation. |
| |
| Interactions with ARB_provoking_vertex, EXT_provoking_vertex, and OpenGL 3.2 or later |
| |
| If none of ARB_provoking_vertex, EXT_provoking_vertex or OpenGL 3.2 |
| or later are supported, ignore all references to ProvokingVertex and |
| PROVOKING_VERTEX. This extension will continue to require support |
| for the LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX |
| queries, but only FIRST_VERTEX_CONVENTION, LAST_VERTEX_CONVENTION, |
| or UNDEFINED_VERTEX will be enumerated. |
| |
| Dependencies on compatibitliy profile contexts |
| |
| Pixel rectangle primitives and bitmaps are available only in |
| compatibility profile contexts. In the core profile, references to |
| pixel rectangles and bitmaps are removed from the description of |
| scissor rectangles in section 4.1.2. |
| |
| Interactions with NV_geometry_program4 |
| |
| If NV_geometry_program4 is supported and the "ARB_viewport_array" program |
| option is specified, geometry result variable "result.viewport" can be |
| used to specify the viewport array index to use for primitive viewport |
| transformations and scissoring. |
| |
| (add the following rule to the NV_geometry_program4 grammar) |
| |
| <resultBasic> ::= ... |
| | <resPrefix> "viewport" |
| |
| (add the following to Table X.3, Geometry Program Result Variable Bindings) |
| |
| Binding Components Description |
| ----------------------------- ---------- ---------------------------- |
| result.viewport (v,*,*,*) viewport array index |
| |
| (add the following to Section 2.X.2, Program Grammar) |
| |
| If a result variable binding matches "result.viewport", updates to the "x" |
| component of the result variable provide a single integer that serves as a |
| viewport index specifier for viewport arrays. The index must be written as |
| an integer value; writing a floating-point value will produce undefined |
| results. If a value outside the range [0, MAX_VIEWPORTS-1] is given, the |
| behavior is to proceed as if viewport index 0 was selected. If the |
| "ARB_viewport_array" program option is not specified, the "result.viewport" |
| binding is unavailable. |
| |
| (add the following to Section 2.X.6.Y, Geometry Program Options) |
| |
| + Viewport Array (ARB_viewport_array) |
| |
| If a geometry program specifies the "ARB_viewport_array" option, the |
| result binding "result.viewport" will be available to specify the viewport |
| index to use for primitive viewport transformations and scissoring as |
| described in section 2.X.2. |
| |
| Issues |
| |
| 1) The name glViewportArray infers dynamic behavior and that the GL |
| may use values that present in the array at draw time. Would it be |
| more consistent to call this glViewportiv or glViewportv? |
| |
| UNRESOLVED: For now, we'll leave it as glViewportArray. |
| |
| 2) Should we provide a mechanism to write gl_ViewportIndex in the vertex |
| shader? This would allow an application to assign gl_ViewportIndex |
| based on the value of a uniform, or from data read through an attribute, |
| for example. |
| |
| RESOLVED: No. While it may be possible, there is no compelling use case, |
| and gl_Layer whose precedent we follow here, is not writable in the |
| vertex shader. |
| |
| 3) Does legacy glViewport update just the first viewport, or all of them? |
| |
| RESOLVED: glViewport is equivalent to calling glViewportArray with |
| an array containing a single viewport once for each supported viewport. |
| It therefore defines all viewports in a single call. This is also true |
| for the legacy glScissor, glDepthRange, glEnable and glDisable functions. |
| |
| 4) When EXT_provoking_vertex is supported, is the provoking vertex convention |
| honored when selecting which vertex the gl_ViewportIndex property is to use? |
| |
| RESOLVED: It is desirable that the provoking vertex convention |
| should be honored when selecting the vertex which gl_ViewportIndex is |
| obtained from (and similarly for gl_Layer). Other APIs require that these |
| properties should be taken from the "leading vertex", and this for |
| maximum content portability, it is desireable to be able to configure the |
| pipeline in the same way. However, there exists hardware which would |
| otherwise be able to support these features which does not have the |
| capability to configure which vertex this is selected from (even though |
| it may be doing so in a content-portable way). The |
| LAYER_PROVOKING_VERTEX and VIEWPORT_INDEX_PROVOKING_VERTEX |
| queries have been added to allow applications to determine if the |
| provoking vertex convention is being followed, and if not, which |
| convention is being used (if any). Note that applications which are |
| creating new content are advised that writing the same |
| gl_ViewportIndex and gl_Layer to all the vertices of a primitive is |
| the only portable solution. |
| |
| 5) Why glViewportIndex rather than glEnablei, and so on? |
| |
| DISCUSSION: This extension follows the precedent of extensions such as |
| EXT_draw_buffers2, which introduced glEnableIndexed. These 'indexed' |
| functions since have been promoted to core OpenGL as glEnablei. If |
| this extension is used on an implementation supporting the glEnablei style |
| indexed functions, those may be used instead of, or in conjunction with |
| the glXXXXIndexed style indexed functions. |
| |
| 6) What happens if the viewport bounds lie on exact half-pixel coordinates? |
| For example, on a multi-sample surface, which samples should be considered |
| 'inside' the viewport? |
| |
| DISCUSSION: The viewport transformation includes clipping. Assuming this |
| clipping has similar precision to the viewport transform itself, then |
| the resulting clipped primitives should cut through partial pixels, |
| lighting only some of the samples within the pixel. |
| |
| FEEDBACK FROM PAT: |
| |
| This discussion is technically incorrect -- the viewport |
| transformation technically does *NOT* include any clipping. However, for |
| geometric primitives, the viewport transformation is applied to vertices |
| post-clipping (despite the fact that it precedes clipping in the spec), so |
| there is some clipping in the vicinity of the viewport transformation. |
| |
| "Guardband clipping" is an alternate implementation, producing nearly |
| equivalent results to those specified by OpenGL. When using guardband |
| clipping, primitives are not clipped tightly to the view volume in X/Y: |
| |
| -w <= x <= w |
| -w <= y <= w |
| |
| Instead, looser (or no) clipping is applied, for example: |
| |
| -8w <= x <= 8w |
| -8w <= y <= 8w |
| |
| Since primitives are clipped far less aggressively, something has to be done |
| to produce results similar to those with aggressive clipping. To do this, |
| such implementations will enable per-pixel scissoring to the viewport |
| rectangle. |
| |
| There are several areas of difference that implementations using guardband |
| clipping need to deal with (or ignore): |
| |
| * line- and point-mode polygons: The OpenGL spec says that lines should be |
| drawn along the edges of polygons clipped to the frustum. If you don't clip |
| tightly, you can't draw those edges. (NOTE: The behavior specified by |
| OpenGL ends up being somewhat shitty. Let's say you have a line-mode |
| primitive clipped by both the left and right side of the frustum, which |
| implies that you should have vertical edges on the left and right side of |
| the viewport. With integer viewport coordinates, both edges will be exactly |
| between pixel centers. In practice, implementations' tiebreaking rules will |
| have either the left or right edge light up pixels outside the viewport. If |
| the viewport is the full window, this means that one of those lines won't be |
| visible. |
| |
| * wide points and lines: According to the OpenGL spec, line or point |
| primitives on or near the edge of the viewport should technically extend |
| outside the viewport. For example, a four-pixel point on the left edge of |
| the viewport should light up eight pixels (2x4) outside the left edge of the |
| viewport. The scissoring used for guardband clipping will discard those |
| pixels. In my opinion, the scissored results are preferable to those called |
| for by the spec. Of course, with the OpenGL spec behavior, there are no |
| visible artifacts if: (a) the viewport covers the entire window or (b) the |
| application scissors manually itself. |
| |
| Fractional viewports make things more complicated, particularly if the |
| implementation doesn't scissor at a per-sample granularity. In this case, |
| tight view volume clipping will result in primitives that are fully contained |
| within the fractional viewport (to the limits of clipping math, at least). |
| Guardband clipping will have primitives that extend beyond the viewport and |
| probably cover full pixels at the boundary of the viewport. (This discussion |
| assumes that a guardband implementation with fractional viewports extends its |
| viewport clip to pass on pixels containing any fraction of the floating-point |
| viewport.) |
| |
| Direct3D 11 specifies that rasterization along the one-pixel edges of |
| fractional viewports to be undefined. If implementations want defined |
| behavior with fractional viewports, they can program a slightly wider viewport |
| and scissor away the pixels along the edge of the expanded viewport. |
| |
| My recommendation is as follows: |
| |
| (1) Edit the clipping section of the spec to explicitly permit implementations |
| to clip to larger view volume extents in (x,y) and instead scissor to the |
| viewport rectangle. Note that this scissor rectangle needs to either be |
| separate from the API-level scissor rectangle, or intersected with it. This |
| scissoring would always have to be enabled, regardless of the SCISSOR enabled. |
| |
| (2) Edit the viewport section of the spec to briefly discuss the implications |
| of fractional viewports on the newly permitted scissoring. |
| |
| 7) What is the VIEWPORT_SUBPIXEL_BITS implementation defined value for? |
| |
| This allows an application to query the precision of the viewport |
| transform. More specifically, if VIEWPORT_SUBPIXEL_BITS is zero, then |
| this indicates that the viewport bounds are likely implemented using |
| integers in hardware. If there are more bits (such as fixed point) then |
| this value will be non-zero. If the implementation truely has floating |
| point viewport bounds, it may report a sufficiently high value to |
| indicate this. |
| |
| 8) What happened to glGetIntegerv(GL_VIEWPORT, v)? |
| |
| It still works. You can query floating point state with an integer query. |
| You'll get a rounded version of the state. You can also query indexed |
| state with a non-indexed query - you'll get the state for index 0. Thus |
| glGetIntegerv(GL_VIEWPORT, v) is the same as |
| glGetIntegeri_v(GL_VIEWPORT, 0, v), which is legal. |
| |
| Revision History |
| |
| Rev. Date Author Changes |
| ---- -------- -------- ----------------------------------------- |
| 18 06/25/2012 Jon Leech Fixed GetIntegerIndexedivEXT -> |
| GetIntegerIndexedvEXT typo (Bug 6694). |
| 17 07/25/2010 Jon Leech Fix typo in ViewportArrayv pseudocode |
| (Bug 6682). |
| 16 07/19/2010 Jon Leech Add GetDoublei_v entry point and change |
| state for DEPTH_RANGE to be indexed and |
| queryable with this command (Bug 6495). |
| Reflow a few paragraphs and sync |
| language with 4.1 API spec. |
| 15 06/16/2010 istewart Add interaction with NV_geometry_program4. |
| 14 05/26/2010 Jon Leech Fix minor typos, remove tabs, make language |
| more consistent with GL core spec in |
| some places, and reflow paragraphs |
| following changes. |
| 13 05/18/2010 gsellers Rename to ARB_viewport_array. |
| ARBify. Remove suffixes for Core 4.1. |
| 12 05/17/2010 gsellers Error is not generated for viewport bounds |
| outside VIEWPORT_BOUNDS_RANGE. |
| Incoporate feedback from pbrown. |
| 11 05/11/2010 gsellers Incorporate feedback from bmerry. |
| 10 05/10/2010 dgkoch allow UNDEFINED_VERTEX_EXT for compatibility |
| 9 05/10/2010 dgkoch add VIEWPORT_BOUNDS_RANGE and clarify the |
| valid values for the viewport location. |
| added queries to determing layer and viewport |
| index provoking vertex convention. |
| updated issue 4. |
| 8 05/06/2010 gsellers Remove error if viewport > MAX_VIEWPORT_DIMS. |
| Fix typo in definition of glScissorIndexedv. |
| Update description of ViewportArrayv to accept |
| an array of floats, rather than an array of |
| integers. |
| 7 04/29/2010 gsellers Updates and clarifications. |
| 6 04/15/2010 gsellers Add interaction with NV_depth_range. |
| Change viewport bounds to floating point values. |
| Add viewport subpixel precision query. |
| Chage function names to ...Indexed. |
| Add issues 6 and 7. |
| 5 01/07/2010 gsellers Change from AMD to EXT |
| Change function prototypes |
| Add glViewporti{_v}. |
| Add glScissorArray, glScissori{_v}. |
| Add glDepthRangeArrayv, glDepthRangei. |
| 4 07/16/2009 gsellers Document EXT_provoking_vertex interaction. |
| Change 'leading vertex' to 'provoking vertex'. |
| Clarify interaction with glViewport. |
| Add multiple scissor rectangles. |
| 3 07/14/2009 gsellers Updates from nickh and wwlk |
| 2 07/08/2009 gsellers Updates from myoung |
| 1 07/06/2009 gsellers Initial draft |