NV_fragment_shader_barycentric

Name

NV_fragment_shader_barycentric

Name Strings

GL_NV_fragment_shader_barycentric

Contact

Pat Brown, NVIDIA (pbrown 'at' nvidia.com)

Contributors

Ashwin Lele, NVIDIA
Jeff Bolz, NVIDIA
Michael Chock, NVIDIA

Status

Shipping

Version

Last Modified:      April 8, 2018
Revision:           2

Number

OpenGL Extension #526
OpenGL ES Extension #316

Dependencies

This extension is written against the OpenGL 4.6 Specification
(Compatibility Profile), dated July 30, 2017.

OpenGL 4.5 or OpenGL ES 3.2 is required.

This extension requires support for the OpenGL Shading Language (GLSL)
extension "NV_fragment_shader_barycentric", which can be found at the
Khronos Group Github site here:

    https://github.com/KhronosGroup/GLSL

Overview

This extension advertises OpenGL support for the OpenGL Shading Language
(GLSL) extension "NV_fragment_shader_barycentric", which provides fragment
shader built-in variables holding barycentric weight vectors that identify
the location of the fragment within its primitive.  Additionally, the GLSL
extension allows fragment the ability to read raw attribute values for
each of the vertices of the primitive that produced the fragment.

New Procedures and Functions

None

New Tokens

None

Modifications to the OpenGL 4.6 Specification (Compatibility Profile)

Modify Section 15.2.2, Shader Inputs (p. 586)

(insert new paragraphs after the first paragraph, p. 589)

Fragment shader input variables can be declared as per-vertex inputs using
the GLSL interpolation qualifier "pervertexNV".  Such inputs are not
produced by attribute interpolation, but are instead taken directly from
corresponding output variables written by the previous shader stage, prior
to primitive clipping and rasterization.  When reading per-vertex inputs,
a fragment shader specifies a vertex number (0, 1, or 2) that identifies a
specific vertex in the point, line, or triangle primitive that produced
the vertex.

When no tessellation or geometry shader is active, the vertices passed to
each draw call are arranged into point, line, or triangle primitives as
described in Section 10.1.  If the <n> vertices passed to a draw call are
numbered 0 through <n>-1, and the point, line, and triangle primitives
produced by the draw call are numbered with consecutive integers beginning
with zero, Table X.1 and Table X.2 indicate the original vertex numbers
used as vertex 0, vertex 1, and vertex 2 when sourcing per-vertex
attributes for fragments produced by the primitive numbered <i>.  Table
X.1 applies when the provoking vertex convention is
FIRST_VERTEX_CONVENTION, while Table X.2 applies when the provoking vertex
convention is LAST_VERTEX_CONVENTION.

    Primitive Type                  Vertex 0    Vertex 1    Vertex 2
    ------------------------        --------    --------    --------
    POINTS                          i           -           -
    LINES                           2i          2i+1        -
    LINE_STRIP                      i           i+1         -
    LINE_LOOP                       i           i+1         -
    LINE_LOOP (last segment)        n-1         0           -
    TRIANGLES                       3i          3i+1        3i+2
    TRIANGLE_STRIP (even)           i           i+1         i+2
    TRIANGLE_STRIP (odd)            i           i+2         i+1
    TRIANGLE_FAN                    i+1         i+2         0
    POLYGON                         0           i           i+1
    LINES_ADJACENCY                 4i+1        4i+2        -
    LINES_STRIP_ADJACENCY           i+1         i+2         -
    TRIANGLES_ADJACENCY             6i          6i+2        6i+4
    TRIANGLE_STRIP_ADJACENCY (even) 2i          2i+2        2i+4
    TRIANGLE_STRIP_ADJACENCY (odd)  2i          2i+4        2i+2

    Table X.1, Vertex Order for per-vertex attributes, using the provoking
    vertex convention FIRST_VERTEX_CONVENTION.

    Primitive Type                  Vertex 0    Vertex 1    Vertex 2
    ------------------------        --------    --------    --------
    POINTS                          i           -           -
    LINES                           2i          2i+1        -
    LINE_STRIP                      i           i+1         -
    LINE_LOOP                       i           i+1         -
    LINE_LOOP (last segment)        n-1         0           -
    TRIANGLES                       3i          3i+1        3i+2
    TRIANGLE_STRIP (even)           i           i+1         i+2
    TRIANGLE_STRIP (odd)            i+1         i           i+2
    TRIANGLE_FAN                    0           i+1         i+2
    POLYGON                         0           i           i+1
    LINES_ADJACENCY                 4i+1        4i+2
    LINES_STRIP_ADJACENCY           i+1         i+2
    TRIANGLES_ADJACENCY             6i          6i+2        6i+4
    TRIANGLE_STRIP_ADJACENCY (even) 2i          2i+2        2i+4
    TRIANGLE_STRIP_ADJACENCY (odd)  2i+2        2i          2i+4

    Table X.2, Vertex Order for per-vertex attributes, using the provoking
    vertex convention LAST_VERTEX_CONVENTION.

When using geometry shaders, vertices used for per-vertex fragment shader
inputs are determined using Table X.1 or X.2 by treating the primitive(s)
produced by the geometry shader as though they were passed to a DrawArrays
calls.  When using a tessellation evaluation shader, or when using QUADS
or QUAD_STRIP primitives, the vertices used for reading per-vertex
fragment shader inputs are assigned in an implementation-dependent order.

The built-in variables gl_BaryCoordNV and gl_BaryCoordNoPerspNV are
three-component floating-point vectors holding barycentric coordinates for
the fragment.  These built-ins are computed by clipping (Section 13.6.1)
and interpolating (Sections 14.5.1 and 14.6.1) a three-component vector
attribute.  The vertices that are numbered 0, 1, and 2 for the purposes of
reading per-vertex fragment shader inputs are assigned values of (1,0,0),
(0,1,0), and (0,0,1), respectively.  For gl_BaryCoordNV, these values are
clipped and interpolated using perspective correction.  For
gl_BaryCoordNoPerspNV, these values are clipped and interpolated without
perspective correction, like other fragment shader inputs qualified with
"noperspective".

Additions to the AGL/GLX/WGL Specifications

None

Interactions with OpenGL ES

Vertex order always corresponds to provoking vertex convention
LAST_VERTEX_CONVENTION.

Ignore references to unsupported primitive types QUADS, QUAD_STRIP, and
POLYGON.

Errors

None

New State

None

New Implementation Dependent State

None

Issues

(1) Can applications use the original order of vertices in a draw call to
    determine the order of the three vertices used when reading per-vertex
    fragment shader inputs?

  RESOLVED:  Yes, in most cases.

  This extension allows fragment shaders to read inputs qualified with
  "pervertexNV" using a vertex number 0, 1, or 2.  For most primitive
  types, the OpenGL Specification already specifies how the original
  vertices passed to a draw call are assigned to individual point, line,
  or triangle primitives.  The extension extends that language to define a
  specific vertex order that will be used for sourcing per-vertex
  attributes.  In some cases, this vertex order depends on the provoking
  vertex convention.

  When using a tessellation evaluation shader, QUADS primitives, or
  QUAD_STRIP primitives, the OpenGL Specification already indicates that
  patches or quadrilaterals can be decomposed into finer primitives in an
  implementation-dependent order.  In these cases, we do not guarantee a
  specific vertex order.  However, we still guarantee that the vertices
  numbered 0, 1, 2 have corresponding barycentric weights (gl_BaryCoordNV)
  of (1,0,0), (0,1,0), and (0,0,1), respectively.  With this guarantee,
  interpolating attributes manually in a fragment shader with code like:

    float value = (gl_BaryCoordNV.x * v[0].attrib +
                   gl_BaryCoordNV.y * v[1].attrib +
                   gl_BaryCoordNV.z * v[2].attrib);

  should produce results approximately equal to those that would be
  obtained via conventional attribute interpolation.

(2) How are clipped primitives handled when using "pervertexNV"
    fragment shader inputs?

  RESOLVED:  In the OpenGL pipeline, clipped primitives are normally
  handled by having the clipper remove one of the original vertices,
  introduce one or more new vertices, and process the result as an
  unclipped primitive.  In this model, the provoking vertex still needs to
  be maintained because inputs qualified with "flat" use the values from
  that vertex even if the provoking vertex is clipped.

  In this extension, we guarantee that the three sets of per-vertex values
  available as fragment shader inputs are those of the original primitive
  vertices prior to clipping.  To ensure consistent attribute handling,
  the barycentric weights are computed relative to the original primitive,
  not the clipped one.  For example, if the left half of triangle ABC
  below is clipped away, the clipper introduces a new vertex D and
  rasterizes triangle DBC instead.

                      + B (0,1,0)
                     /|\
                    / | \
                   /  |  \
                  /   |   \
                 /    |    \
                /     |     \
     (1,0,0) A +------+------+ C (0,0,1)
                      D

  When we process the clipped triangle, the three vertices available for
  "pervertexNV" inputs are actually A, B, and C (in undefined order).
  If vertices "v[0]", "v[1]", and "v[2]" are assigned to A, B, and C,
  respectively, fragments at A, B, and C will have barycentric coordinates
  of (1,0,0), (0,1,0), and (0,0,1), respectively.  A fragment at the
  vertex D introduced by the clipper will have a weight like (0.5, 0.0,
  0.5) -- exactly the same value it would have if ABC were unclipped.

(3) Should we have any program interface query API support where
    application code can inspect the active fragment shader inputs and
    determine which ones were declared with "pervertexNV"?

  RESOLVED:  No.  We don't have this for other interpolation qualifiers
  like "flat" or "noperspective".

Also, please refer to issues in the GLSL extension specification.

Revision History

Revision 2 (mchock)
- Add support for OpenGL ES.

Revision 1 (pbrown)
- Internal revisions.