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 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 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.