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.
