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
Status
Shipping
Version
Last Modified: September 15, 2018
Revision: 1
Number
OpenGL Extension #526
Dependencies
This extension is written against the OpenGL 4.6 Specification
(Compatibility Profile), dated July 30, 2017.
OpenGL 4.5 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 vertices passed to a draw call are
numbered 0 through -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 *. 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
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 1 (pbrown)
- Internal revisions.
*