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.
