| Name |
| |
| NV_coverage_sample |
| |
| Name Strings |
| |
| GL_NV_coverage_sample |
| EGL_NV_coverage_sample |
| |
| Contact |
| |
| Gary King, NVIDIA Corporation (gking 'at' nvidia.com) |
| |
| Notice |
| |
| Copyright NVIDIA Corporation, 2005 - 2007 |
| |
| Status |
| |
| NVIDIA Proprietary |
| |
| Version |
| |
| Last Modified Date: 2007/03/20 |
| NVIDIA Revision: 1.0 |
| |
| Number |
| |
| EGL Extension #17 |
| OpenGL ES Extension #72 |
| |
| Dependencies |
| |
| Written based on the wording of the OpenGL 2.0 specification |
| and the EXT_framebuffer_object specification. |
| |
| Written based on the wording of the EGL 1.2 specification. |
| |
| Requires OpenGL-ES 2.0 and OES_framebuffer_object. |
| |
| Requires EGL 1.1. |
| |
| Overview |
| |
| Anti-aliasing is a critical component for delivering high-quality |
| OpenGL rendering. Traditionally, OpenGL implementations have |
| implemented two anti-aliasing algorithms: edge anti-aliasing |
| and multisampling. |
| |
| Edge anti-aliasing computes fractional fragment coverage for all |
| primitives in a rendered frame, and blends edges of abutting |
| and/or overlapping primitives to produce smooth results. The |
| image quality produced by this approach is exceptionally high; |
| however, applications are render their geometry perfectly ordered |
| back-to-front in order to avoid artifacts such as bleed-through. |
| Given the algorithmic complexity and performance cost of performing |
| exact geometric sorts, edge anti-aliasing has been used very |
| sparingly, and almost never in interactive games. |
| |
| Multisampling, on the other hand, computes and stores subpixel |
| (a.k.a. "sample") coverage for rasterized fragments, and replicates |
| all post-alpha test operations (e.g., depth test, stencil test, |
| alpha blend) for each sample. After the entire scene is rendered, |
| the samples are filtered to compute the final anti-aliased image. |
| Because the post-alpha test operations are replicated for each sample, |
| all of the bleed-through and ordering artifacts that could occur with |
| edge anti-aliasing are avoided completely; however, since each sample |
| must be computed and stored separately, anti-aliasing quality is |
| limited by framebuffer storage and rendering performance. |
| |
| This extension introduces a new anti-aliasing algorithm to OpenGL, |
| which dramatically improves multisampling quality without |
| adversely affecting multisampling's robustness or significantly |
| increasing the storage required, coverage sampling. |
| |
| Coverage sampling adds an additional high-precision geometric |
| coverage buffer to the framebuffer, which is used to produce |
| high-quality filtered results (with or without the presence of a |
| multisample buffer). This coverage information is computed and stored |
| during rasterization; since applications may render objects where the |
| specified geometry does not correspond to the visual result (examples |
| include alpha-testing for "imposters," or extruded volume rendering |
| for stencil shadow volumes), coverage buffer updates may be masked |
| by the application, analagous to masking the depth buffer. |
| |
| IP Status |
| |
| NVIDIA Proprietary |
| |
| New Procedures and Functions |
| |
| void CoverageMaskNV( boolean mask ) |
| void CoverageOperationNV( enum operation ) |
| |
| New Tokens |
| |
| |
| Accepted by the <attrib_list> parameter of eglChooseConfig |
| and eglCreatePbufferSurface, and by the <attribute> |
| parameter of eglGetConfigAttrib |
| |
| EGL_COVERAGE_BUFFERS_NV 0x30E0 |
| EGL_COVERAGE_SAMPLES_NV 0x30E1 |
| |
| Accepted by the <internalformat> parameter of |
| RenderbufferStorageEXT and the <format> parameter of ReadPixels |
| |
| COVERAGE_COMPONENT_NV 0x8ED0 |
| |
| Accepted by the <internalformat> parameter of |
| RenderbufferStorageEXT |
| |
| COVERAGE_COMPONENT4_NV 0x8ED1 |
| |
| Accepted by the <operation> parameter of CoverageOperationNV |
| |
| COVERAGE_ALL_FRAGMENTS_NV 0x8ED5 |
| COVERAGE_EDGE_FRAGMENTS_NV 0x8ED6 |
| COVERAGE_AUTOMATIC_NV 0x8ED7 |
| |
| Accepted by the <attachment> parameter of |
| FramebufferRenderbuffer, and GetFramebufferAttachmentParameteriv |
| |
| COVERAGE_ATTACHMENT_NV 0x8ED2 |
| |
| Accepted by the <buf> parameter of Clear |
| |
| COVERAGE_BUFFER_BIT_NV 0x8000 |
| |
| Accepted by the <pname> parameter of GetIntegerv |
| |
| COVERAGE_BUFFERS_NV 0x8ED3 |
| COVERAGE_SAMPLES_NV 0x8ED4 |
| |
| Changes to Chapter 4 of the OpenGL 2.0 Specification |
| |
| Insert a new section, after Section 3.2.1 (Multisampling) |
| |
| "3.2.2 Coverage Sampling |
| |
| Coverage sampling is a mechanism to antialias all GL primitives: points, |
| lines, polygons, bitmaps and images. The technique is similar to |
| multisampling, with all primitives being sampled multiple times at each |
| pixel, and a sample resolve applied to compute the color values stored |
| in the framebuffer's color buffers. As with multisampling, coverage |
| sampling resolves color sample and coverage values to a single, displayable |
| color each time a pixel is updated, so antialiasing appears to be automatic |
| at the application level. Coverage sampling may be used simultaneously |
| with multisampling; however, this is not required. |
| |
| An additional buffer, called the coverage buffer, is added to |
| the framebuffer. This buffer stores additional coverage information |
| that may be used to produce higher-quality antialiasing than what is |
| provided by conventional multisampling. |
| |
| When the framebuffer includes a multisample buffer (3.5.6), the |
| samples contain this coverage information, and the framebuffer |
| does not include the coverage buffer. |
| |
| If the value of COVERAGE_BUFFERS_NV is one, the rasterization of |
| all primitives is changed, and is referred to as coverage sample |
| rasterization. Otherwise, primitive rasterization is referred to |
| as multisample rasterization (if SAMPLE_BUFFERS is one) or |
| single-sample rasterization (otherwise). The value of |
| COVERAGE_BUFFERS_NV is queried by calling GetIntegerv with <pname> |
| set to COVERAGE_BUFFERS_NV. |
| |
| During coverage sample rasterization the pixel fragment contents |
| are modified to include COVERAGE_SAMPLES_NV coverage values. The |
| value of COVERAGE_SAMPLES_NV is an implementation-dependent |
| constant, and is queried by calling GetIntegerv with <pname> set |
| to COVERAGE_SAMPLES_NV. |
| |
| The command |
| |
| CoverageOperationNV(enum operation) |
| |
| may be used to modify the manner in which coverage sampling is |
| performed for all primitives. If <operation> is |
| COVERAGE_ALL_FRAGMENTS_NV, coverage sampling will be performed and the |
| coverage buffer updated for all fragments generated during rasterization. |
| If <operation> is COVERAGE_EDGE_FRAGMENTS_NV, coverage sampling will |
| only be performed for fragments generated at the edge of the |
| primitive (by only updating fragments at the edges of primitives, |
| applications may get better visual results when rendering partially |
| transparent objects). If <operation> is COVERAGE_AUTOMATIC_NV, |
| the GL will automatically select the appropriate coverage operation, |
| dependent on the GL blend mode and the use of gl_LastFragColor / |
| gl_LastFragData in the bound fragment program. If blending is enabled, |
| or gl_LastFragColor / gl_LastFragData appears in the bound fragment |
| program, COVERAGE_AUTOMATIC_NV will behave identically to |
| COVERAGE_EDGE_FRAGMENTS_NV; otherwise, COVERAGE_AUTOMATIC_NV will behave |
| identically to COVERAGE_ALL_FRAGMENTS_NV. The default coverage operation |
| is COVERAGE_AUTOMATIC_NV." |
| |
| Insert a new section, after Section 3.3.3 (Point Multisample |
| Rasterization) |
| |
| "3.3.4 Point Coverage Sample Rasterization |
| |
| If the value of COVERAGE_BUFFERS_NV is one, then points are |
| rasterized using the following algorithm, regardless of whether |
| point antialiasing (POINT_SMOOTH) is enabled or disabled. Point |
| rasterization produces fragments using the same algorithm described |
| in section 3.3.3; however, sample points are divided into SAMPLES |
| multisample points and COVERAGE_SAMPLES_NV coverage sample points. |
| |
| Rasterization for multisample points uses the algorithm described |
| in section 3.3.3. Rasterization for coverage sample points uses |
| implementation-dependent algorithms, ultimately storing the results |
| in the coverage buffer." |
| |
| Insert a new section, after Section 3.4.4 (Line Multisample |
| Rasterization) |
| |
| "3.4.5 Line Coverage Sample Rasterization |
| |
| If the value of COVERAGE_BUFFERS_NV is one, then lines are |
| rasterized using the following algorithm, regardless of whether |
| line antialiasing (LINE_SMOOTH) is enabled or disabled. Line |
| rasterization produces fragments using the same algorithm described |
| in section 3.4.4; however, sample points are divided into SAMPLES |
| multisample points and COVERAGE_SAMPLES_NV coverage sample points. |
| |
| Rasterization for multisample points uses the algorithm described in |
| section 3.4.4. Rasterization for coverage sample points uses |
| implementation-dependent algorithms, ultimately storing results in |
| the coverage buffer." |
| |
| Insert a new section, after Section 3.5.6 (Polygon Multisample |
| Rasterization) |
| |
| "3.5.7 Polygon Coverage Sample Rasterization |
| |
| If the value of COVERAGE_BUFFERS_NV is one, then polygons are |
| rasterized using the following algorithm, regardless of whether |
| polygon antialiasing (POLYGON_SMOOTH) is enabled or disabled. Polygon |
| rasterization produces fragments using the same algorithm described in |
| section 3.5.6; however, sample points are divided into SAMPLES multisample |
| points and COVERAGE_SAMPLES_NV coverage sample points. |
| |
| Rasterization for multisample points uses the algorithm described in |
| section 3.5.7. Rasterization for coverage sample points uses |
| implementation-dependent algorithms, ultimately storing results in the |
| coverage buffer." |
| |
| Insert a new section, after Section 3.6.6 (Pixel Rectangle Multisample |
| Rasterization) |
| |
| "3.6.7 Pixel Rectangle Coverage Sample Rasterization |
| |
| If the value of COVERAGE_BUFFERS_NV is one, then pixel rectangles are |
| rasterized using the algorithm described in section 3.6.6." |
| |
| Modify the first sentence of the second-to-last paragraph of section |
| 3.7 (Bitmaps) to read: |
| |
| "Bitmap Multisample and Coverage Sample Rasterization |
| |
| If MULTISAMPLE is enabled, and the value of SAMPLE_BUFFERS is one; |
| or if the value of COVERAGE_BUFFERS_NV is one, then bitmaps are |
| rasterized using the following algorithm. [...]" |
| |
| Insert after the first paragraph of Section 4.2.2 (Fine Control of |
| Buffer Updates): |
| |
| "The coverage buffer can be enabled or disabled for writing coverage |
| sample values using |
| |
| void CoverageMaskNV( boolean mask ); |
| |
| If <mask> is non-zero, the coverage buffer is enabled for writing; |
| otherwise, it is disabled. In the initial state, the coverage |
| buffer is enabled for writing." |
| |
| And change the text of the last 2 paragraphs of Section 4.2.2 to read: |
| |
| "The state required for the various masking operations is three |
| integers and two bits: an integer for color indices, an integer for |
| the front and back stencil values, a bit for depth values, and a |
| bit for coverage sample values. A set of four bits is also required |
| indicating which components of an RGBA value should be written. In the |
| initial state, the integer masks are all ones, as are the bits |
| controlling the depth value, coverage sample value and RGBA component |
| writing. |
| |
| Fine Control of Multisample Buffer Updates |
| |
| When the value of SAMPLE_BUFFERS is one, ColorMask, DepthMask, |
| CoverageMask, and StencilMask or StencilMaskSeparate control the |
| modification of values in the multisample buffer. [...]" |
| |
| Change paragraph 2 of Section 4.2.3 (Clearing the Buffers) to read: |
| |
| "is the bitwise OR of a number of values indicating which buffers are to |
| be cleared. The values are COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT, |
| STENCIL_BUFFER_BIT, ACCUM_BUFFER_BIT and COVERAGE_BUFFER_BIT_NV, indicating |
| the buffers currently enabled for color writing, the depth buffer, |
| the stencil buffer, the accumulation buffer and the virtual-coverage |
| buffer, respectively. [...]" |
| |
| Insert a new paragraph after paragraph 4 of Section 4.3.2 (Reading Pixels) |
| (beginning with "If there is a multisample buffer ..."): |
| |
| "If the <format> is COVERAGE_COMPONENT_NV, then values are taken from the |
| coverage buffer; again, if there is no coverage buffer, the error |
| INVALID_OPERATION occurs. When <format> is COVERAGE_COMPONENT_NV, |
| <type> must be GL_UNSIGNED_BYTE. Any other value for <type> will |
| generate the error INVALID_ENUM. If there is a multisample buffer, the |
| values are undefined." |
| |
| |
| |
| Modifications to the OES_framebuffer_object specification |
| |
| Add a new table at the end of Section 4.4.2.1 (Renderbuffer Objects) |
| |
| "+-------------------------+-----------------------+-----------+ |
| | Sized internal format | Base Internal Format | C Samples | |
| +-------------------------+-----------------------+-----------+ |
| | COVERAGE_COMPONENT4_NV | COVERAGE_COMPONENT_NV | 4 | |
| +-------------------------+-----------------------+-----------+ |
| Table 1.ooo Desired component resolution for each sized internal |
| format that can be used only with renderbuffers" |
| |
| Add to the bullet list in Section 4.4.4 (Framebuffer Completeness) |
| |
| "An internal format is 'coverage-renderable' if it is COVERAGE_COMPONENT_NV |
| or one of the COVERAGE_COMPONENT_NV formats from table 1.ooo. No other |
| formats are coverage-renderable" |
| |
| Add to the bullet list in Section 4.4.4.1 (Framebuffer Attachment |
| Completeness) |
| |
| "If <attachment> is COVERAGE_ATTACHMENT_NV, then <image> must have a |
| coverage-renderable internal format." |
| |
| Add a paragraph at the end of Section 4.4.4.2 (Framebuffer Completeness) |
| |
| "The values of COVERAGE_BUFFERS_NV and COVERAGE_SAMPLES_NV are derived from |
| the attachments of the currently bound framebuffer object. If the current |
| FRAMEBUFFER_BINDING_OES is not 'framebuffer-complete', then both |
| COVERAGE_BUFFERS_NV and COVERAGE_SAMPLES_NV are undefined. Otherwise, |
| COVERAGE_SAMPLES_NV is equal to the number of coverage samples for the |
| image attached to COVERAGE_ATTACHMENT_NV, or zero if COVERAGE_ATTACHMENT_NV |
| is zero." |
| |
| Additions to the EGL 1.2 Specification |
| |
| Add to Table 3.1 (EGLConfig attributes) |
| +---------------------------+---------+-----------------------------------+ |
| | Attribute | Type | Notes | |
| +---------------------------+---------+-----------------------------------+ |
| | EGL_COVERAGE_BUFFERS_NV | integer | number of coverage buffers | |
| | EGL_COVERAGE_SAMPLES_NV | integer | number of coverage samples per | |
| | | | pixel | |
| +---------------------------+---------+-----------------------------------+ |
| |
| Modify the first sentence of the last paragraph of the "Buffer |
| Descriptions and Attributes" subsection of Section 3.4 (Configuration |
| Management), p. 16 |
| |
| "There are no single-sample depth, stencil or coverage buffers for a |
| multisample EGLConfig; the only depth, stencil and coverage buffers are |
| those in the multisample buffer. [...]" |
| |
| And add the following text at the end of that paragraph: |
| |
| "The <coverage buffer> is used only by OpenGL ES. It contains primitive |
| coverage information that is used to produce a high-quality anti-aliased |
| image. The format of the coverage buffer is not specified, and its |
| contents are not directly accessible. Only the existence of the coverage |
| buffer, and the number of coverage samples it contains, are exposed by EGL. |
| |
| EGL_COVERAGE_BUFFERS_NV indicates the number of coverage buffers, which |
| must be zero or one. EGL_COVERAGE_SAMPLES_NV gives the number of coverage |
| samples per pixel; if EGL_COVERAGE_BUFFERS_NV is zero, then |
| EGL_COVERAGE_SAMPLES_NV will also be zero." |
| |
| Add to Table 3.4 (Default values and match criteria for EGLConfig |
| attributes) |
| |
| +---------------------------+-----------+-------------+---------+---------+ |
| | Attribute | Default | Selection | Sort | Sort | |
| | | | Criteria | Order | Priority| |
| +---------------------------+-----------+-------------+---------+---------+ |
| | EGL_COVERAGE_BUFFERS_NV | 0 | At Least | Smaller | 7 | |
| | EGL_COVERAGE_SAMPLES_NV | 0 | At Least | Smaller | 8 | |
| +---------------------------+-----------+-------------+---------+---------+ |
| And renumber existing sort priorities 7-11 as 9-13. |
| |
| Modify the list in "Sorting of EGLConfigs" (Section 3.4.1, pg 20) |
| |
| " [...] |
| 5. Smaller EGL_SAMPLE_BUFFERS |
| 6. Smaller EGL_SAMPLES |
| 7. Smaller EGL_COVERAGE_BUFFERS_NV |
| 8. Smaller EGL_COVERAGE_SAMPLES_NV |
| 9. Smaller EGL_DEPTH_SIZE |
| 10. Smaller EGL_STENCIL_SIZE |
| 11. Smaller EGL_ALPHA_MASK_SIZE |
| 12. Special: [...] |
| 13. Smaller EGL_CONFIG_ID [...]" |
| |
| Usage Examples |
| |
| (1) Basic Coverage Sample Rasterization |
| |
| glCoverageMaskNV(GL_TRUE); |
| glDepthMask(GL_TRUE); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| |
| while (1) |
| { |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | |
| GL_COVERAGE_BUFFER_BIT_NV); |
| glDrawElements(...); |
| eglSwapBuffers(...); |
| } |
| |
| (2) Multi-Pass Rendering Algorithms |
| |
| while (1) |
| { |
| glDepthMask(GL_TRUE); |
| glCoverageMaskNV(GL_TRUE); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | |
| GL_COVERAGE_BUFFER_BIT_NV); |
| |
| // first render pass: render Z-only (occlusion surface), with |
| // coverage info. color writes are disabled |
| |
| glCoverageMaskNV(GL_TRUE); |
| glDepthMask(GL_TRUE); |
| glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); |
| glDepthFunc(GL_LESS); |
| glDrawElements(...); |
| |
| // second render pass: set Z test to Z-equals, disable Z-writes & |
| // coverage writes. enable color writes. coverage may be |
| // disabled, because subsequent rendering passes are rendering |
| // identical geometry -- since the final coverage buffer will be |
| // unchanged, we can disable coverage writes as an optimization. |
| |
| glCoverageMaskNV(GL_FALSE); |
| glDepthMask(GL_FALSE); |
| glDepthFunc(GL_EQUAL); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| glDrawElements(...); |
| |
| eglSwapBuffers(); |
| } |
| |
| (3) Rendering Translucent Objects on Top of Opaque Objects |
| |
| while (1) |
| { |
| glDepthMask(GL_TRUE); |
| glCoverageMaskNV(GL_TRUE); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | |
| GL_COVERAGE_BUFFER_BIT_NV); |
| |
| // render opaque, Z-buffered geometry with coverage info for the |
| // entire primitive. Overwrite coverage data for all fragments, so |
| // that interior fragments do not get resolved incorrectly. |
| |
| glDepthFunc(GL_LESS); |
| glCoverageOperationNV(GL_COVERAGE_ALL_FRAGMENTS_NV); |
| glDrawElements(...); |
| |
| // render translucent, Z-buffered geometry. to ensure that visible |
| // edges of opaque geometry remain anti-aliased, change the |
| // coverage operation to just edge fragments. this will maintain |
| // the coverage information underneath the translucent geometry, |
| // except at translucent edges. |
| |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| glCoverageOperationNV(GL_COVERAGE_EDGE_FRAGMENTS_NV); |
| glEnable(GL_BLEND); |
| glDrawElements(...); |
| glDisable(GL_BLEND); |
| |
| eglSwapBuffers(); |
| } |
| |
| (4) Rendering Opacity-Mapped Particle Systems & HUDs on Top of Opaque |
| Geometry |
| |
| while (1) |
| { |
| glDepthMask(GL_TRUE); |
| glCoverageMaskNV(GL_TRUE); |
| glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | |
| GL_COVERAGE_BUFFER_BIT_NV); |
| |
| // render opaque, Z-buffered geometry, with coverage info. |
| glDepthFunc(GL_LESS); |
| glDrawElements(...); |
| |
| // render opacity-mapped geometry. disable Z writes, enable alpha |
| // blending. also, disable coverage writes -- the edges of the |
| // geometry used for the HUD/particle system have alpha values |
| // tapering to zero, so edge coverage is uninteresting, and |
| // interior coverage should still refer to the underlying opaque |
| // geometry, so that opaque edges visible through the translucent |
| // regions remain anti-aliased. |
| |
| glCoverageMaskNV(GL_FALSE); |
| glDepthMask(GL_FALSE); |
| glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| glEnable(GL_BLEND); |
| glDrawElements(...); |
| glDisable(GL_BLEND); |
| |
| eglSwapBuffers(); |
| } |
| |
| |
| Issues |
| |
| 1. Is any specific discussion of coverage sampling resolves required, |
| particularly with respect to application-provided framebuffer objects? |
| |
| RESOLVED: No. Because the coverage sampling resolve is an |
| implementation-dependent algorithm, it is always legal behavior for |
| framebuffer read / copy functions to return the value in the selected |
| ReadBuffer as if COVERAGE_BUFFERS_NV was zero. This allows |
| textures attached to the color attachment points of framebuffer objects |
| to behave predictably, even when COVERAGE_BUFFERS_NV is one. |
| |
| Implementations are encouraged, whenever possible, to use the highest- |
| quality coverage sample resolve supported for calls to eglSwapBuffers, |
| eglCopyBuffers, ReadPixels, CopyPixels and CopyTex{Sub}Image. |
| |
| 2. Should all render buffer & texture types be legal sources for image |
| resolves and coverage attachment? |
| |
| RESOLVED: This spec should not place any arbitrary limits on usage; |
| however, there are many reasons why implementers may not wish to |
| support coverage sampling for all surface types. |
| |
| Implementations may return FRAMEBUFFER_UNSUPPORTED_OES from |
| CheckFramebufferStatusOES if an object bound to COVERAGE_ATTACHMENT_NV |
| is incompatible with one or more objects bound to DEPTH_ATTACHMENT_OES, |
| STENCIL_ATTACHMENT_OES, or COLOR_ATTACHMENTi_OES. |
| |
| Revision History |
| |
| #1.0 - 20.03.2007 |
| |
| Renumbered enumerants. Reformatted to 80 columns. |