blob: e016a6fc83240576c5fe991f08fae4f73c0938b0 [file] [log] [blame]
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.