Name EXT_clip_cull_distance Name Strings GL_EXT_clip_cull_distance Contact Maurice Ribble, Qualcomm Technologies Inc. (mribble 'at' qti.qualcomm.com) Contributors Kulin Seth, Qualcomm Technologies Inc. Sam Holmes, Qualcomm Technologies Inc. Jeff Leger, Qualcomm Technologies Inc. Daniel Koch, NVIDIA Jan-Harald Fredriksen, ARM Bill Licea-Kane, Qualcomm Technologies Inc. Status Complete Version Last Modified Date: February 27, 2024 Revision: 4 Number OpenGL ES Extension #257 Dependencies This specification is written against the OpenGL ES 3.2 Specification (August 10, 2015), and the OpenGL ES 3.2 Shading Language Specification (August 6, 2015) but can apply to prior specifications. OpenGL ES 3.0 is required. This extension interacts with OpenGL ES 3.2. This extension interacts with OES_tessellation_shader and EXT_tessellation_shader. This extension trivially interacts with OES_tessellation_point_size and EXT_tessellation_point_size. This extension interacts with OES_geometry_shader and EXT_geometry_shader. This extension interacts with OES_shader_io_blocks. Overview This extension adds support for hardware clip planes and cull distances to OpenGL ES. The language for this extension is based on the OpenGL 4.5 API Specification (May 28, 2015) and ARB_clip_distance. New Procedures and Functions None New Tokens Accepted by the parameters of GetBooleanv, GetIntegerv, GetInteger64v, and GetFloatv: MAX_CLIP_DISTANCES_EXT 0x0D32 MAX_CULL_DISTANCES_EXT 0x82F9 MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA Accepted by the parameters of Enable, Disable and IsEnabled: CLIP_DISTANCE0_EXT 0x3000 CLIP_DISTANCE1_EXT 0x3001 CLIP_DISTANCE2_EXT 0x3002 CLIP_DISTANCE3_EXT 0x3003 CLIP_DISTANCE4_EXT 0x3004 CLIP_DISTANCE5_EXT 0x3005 CLIP_DISTANCE6_EXT 0x3006 CLIP_DISTANCE7_EXT 0x3007 Additions to Chapter 7 of the OpenGL ES 3.2 Specification (Programs and Shaders) Modify Section 7.4.1 "Shader Interface Matching" (p. 97), adding the following to the end of the third paragraph (beginning with "For program objects containing mutliple shaders,..."): "If either shader redeclares the built-in arrays gl_CullDistance[] or gl_ClipDistance[] the array must have the same size in both shaders." Additions to Chapter 11 of the OpenGL ES 3.2 Specification (Programmable Vertex Processing) Modify Section 11.1.3.10, "Shader Outputs" (p. 300), adding the following as a new paragraph after the description of gl_Position: "The built-in output variables gl_ClipDistance and gl_CullDistance respectively hold the the clip distance and cull distance used in the clipping stage, as described in section 12.4. If clipping is enabled, gl_ClipDistance should be written." Modify Section 11.2.1.2.2, "Tessellation Control Shader Inputs" (p. 307), replacing the last sentence of the first paragraph as follows: "The members of each element of the gl_in array are gl_Position, gl_CullDistance, and gl_ClipDistance [[ If OES_tessellation_point_size or EXT_tessellation_point_size are supported: ]] and gl_PointSize." Modify Section 11.2.1.2.3, "Tessellation Control Shader Outputs" (p. 308), replacing the last two sentences of the first paragraph as follows: "The members of each element of the gl_out array are gl_Position, gl_ClipDistance and gl_CullDistance [[ If OES_tessellation_point_size or EXT_tessellation_point_size are supported: ]] and gl_PointSize, and behave identically to equivalently named vertex shader outputs (see section 11.1.3)." Modify Section 11.2.3.3 "Tessellation Evaluation Shader Inputs" (p. 321), replacing the last sentence of the first paragraph as follows: "The members of each element of the gl_in array are gl_Position, gl_CullDistance, and gl_ClipDistance [[ If OES_tessellation_point_size or EXT_tessellation_point_size are supported: ]] and gl_PointSize." Modify Section 11.2.3.4, "Tessellation Evaluation Shader Outputs" (p. 322), replacing the first two sentences of the first paragraph as follows: "Tessellation evalution shaders have a number of built-in output variables used to pass values to equivalent built-in input variagles read by subsequent shader stages or to subsequent fixed functionality vertex processing pipeline stages. These variables are gl_Position, gl_ClipDistance and gl_CullDistance [[ If OES_tessellation_point_size or EXT_tessellation_point_size are supported: ]] and gl_PointSize, and all behave identically to equivalently named vertex shader outputs (see section 11.1.3)." Modify Section 11.3.4.3, "Geometry Shader Inputs" (p. 327) by adding the following two bullet points to the description of the elements of gl_in[]: "* Structure member gl_ClipDistance[] holds the per-vertex array of clip distances, as written by the upstream shader to the built-in output variable gl_ClipDistance[]. * Structure member gl_CullDistance[] holds the per-vertex array of cull distances, as written by the upstream shader to the built-in output variable gl_CullDistance[]." Modify Section 11.3.4.4 "Geometry Shader Outputs" (p. 329), adding the following paragraph after the description of gl_Position: "The built-in outputs gl_ClipDistance and gl_CullDistance hold the clip distance and cull distance, respectively, used in the clipping stage, as described in Section 12.4." Additions to Chapter 12 of the OpenGL ES 3.2 Specification (Fixed-Function Vertex Post-Processing) Modify Section 12.4, "Primitive Clipping" (p. 341), replacing the first four paragraphs with the following: "Primitives are culled against the cull volume and then clipped to the clip volume. In clip coordinates, the view volume is defined by -wc <= xc <= wc -wc <= yc <= wc -zmin <= zc <= wc. where zmin is -wc. This view volume may be further restricted by as many as client-defined halfspaces. is an implementation-dependent maximum that must be at least 8, and may be determined by calling GetIntegerv with pname MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT. The cull volume is the intersection of up to the value of MAX_CULL_DISTANCES_EXT client-defined half-spaces (if no client-defined cull half-spaces are enabled, culling against the cull volume is skipped). The number of enabled cull half-spaces is determined by the explicit or implicit size of the built-in array gl_CullDistance in the last shader stage before rasterization which has an active program. A shader may write a single cull distance for each enabled cull half-space to elements of the gl_CullDistance[] array. If the cull distance for any enabled cull half-space is negative for all of the vertices of the primitive under consideration, the primitive is discarded. Otherwise the primitive is clipped against the clip volume as defined below. The clip volume is the intersection of up to the value of MAX_CLIP_DISTANCES_EXT client-defined half-spaces with the view volume (if no client-defined clip half-spaces are enabled, the clip volume is the view volume). A vertex shader may write a single clip distance for each enabled clip halfspace to elements of the gl_ClipDistance[] array. Clip half-space is then given by the set of points satisfying the inequality ci(P) >= 0, where ci(P) is the value of clip distance at point P. For point primitives, ci(P) is simply the clip distance for the vertex in question. For line and triangle primitives, per-vertex clip distances are interpolated using a weighted mean, with weights derived according to the algorithms described in sections 13.6 (Line Segments) and 13.7 (Polygons). Client-defined clip half-spaces are enabled or disabled by calling Enable or Disable with target CLIP_DISTANCE_EXT, where is an integer between 0 and - 1; specifying a value of enables or disables the client-defined clip half-space with index . The constants obey CLIP_DISTANCE_EXT = CLIP_DISTANCE0_EXT + . If the primitive under consideration is a point, then clipping passes it unchanged if it lies withing the clip volume; otherwise it is discarded. If the primitive is a line segment, then clipping does nothing to it if it lies entirely withing the clip volume, and discards it if it lies entirely outside the volume. If part of the line segment lies in the volume and part of it lies outside, then the line segment is clipped and new vertex coordinates are computed for one or both vertices. A clipped line segment endpoint lies on both the original line segment and the boundary of the clip volume. This clipping produces..." Add the following text to the end of Section 12.4: "Primitives rendered with user-defined half-spaces must satisfy a complimentary criterion. Suppose a series of primitives is drawn where each vertex has a single specified clip distance (or a number of similarly specified clip distances, if multiple half-spaces are enabled). Next, suppose that the same series of primitives are drawn again with each such clip distance replaced by - (and the GL is otherwise in the same state). In this case, primitives must not be missing any pixels, nor may any pixels be drawn twice in regions where those primitives are cut by the clip planes. The state required for clipping is MAX_CLIP_DISTANCES_EXT bits indicating which of the client-defined half-spaces are enabled. In the initial state, all half-spaces are disabled." Additions to OpenGL ES Shading Language 3.20 Specification Including the following line in a shader can be used to control the language features described in this extension: #extension GL_EXT_clip_cull_distance : where is as described in section 3.4. A new preprocessor #define is added to the OpenGL ES Shading Language: #define GL_EXT_clip_cull_distance 1 Additions to Chapter 7 of the OpenGL ES Shading Language 3.20 Specification (Built-in Variables) Modify Section 7.1, Vertex Shader Special Variables (p. 119) out gl_PerVertex { ... highp float gl_ClipDistance[]; highp float gl_CullDistance[]; }; If I/O blocks are not in use, these variables are not in gl_PerVertex. Similar changes in Geometry, Tessellation Control, Tessellation Evaluation language "in gl_PerVertex" and "out gl_PerVertex" structures. Modify Section 7.1.5 "Fragment Shader Special Variables" (p. 123) in highp float gl_ClipDistance[]; in highp float gl_CullDistance[]; The variable gl_ClipDistance provides the mechanism for controlling user clipping. The element gl_ClipDistance[i] specifies a clip distance for each plane . A distance of 0 means the vertex is on the plane, a positive distance means the vertex is inside the clip plane, and a negative distance means the point is outside the clip plane. The clip distances will be linearly interpolated across the primitive and the portion of the primitive with interpolated distances less than 0 will be clipped. The gl_ClipDistance array is predeclared as unsized and must be explicitly sized by the shader either redeclaring it with a size or implicitly sized by indexing it only with integral constant expressions. This needs to size the array to include all the clip planes that are enabled via the OpenGL ES API; if the size does not include all enabled planes, results are undefined. The size can be at most gl_MaxClipDistances. The number of varying components (see gl_MaxVaryingComponents) consumed by gl_ClipDistance will match the size of the array, no matter how many planes are enabled. The shader must also set all values in gl_ClipDistance that have been enabled via the OpenGL ES API, or results are undefined. Values written into gl_ClipDistance for planes that are not enabled have no effect. As an output variable, gl_ClipDistance provides the place for the shader to write these distances. As an input in all but the fragment language, it reads the values written in the previous shader stage. In the fragment language, gl_ClipDistance array contains linearly interpolated values for the vertex values written by a shader to the gl_ClipDistance vertex output variable. Only elements in this array that have clipping enabled will have defined values. The variable gl_CullDistance provides a mechanism for controlling user culling. The element gl_CullDistance[i] specifies a cull distance for plane . A distance of 0 means the vertex is on the plane, a positive distance means the vertex is inside the cull volume, and a negative distance means the point is outside the cull volume. Primitives whose vertices all have a negative clip distance for plane will be discarded. The gl_CullDistance array is predeclared as unsized and must be sized by the shader either redeclaring it with a size or indexing it only with integral constant expressions. The size determines the number and set of enabled cull distances and can be at most gl_MaxCullDistances. The number of varying components (see gl_MaxVaryingComponents) consumed by gl_CullDistance will match the size of the array. Shaders writing gl_CullDistance must write all enabled distances, or culling results are undefined. As an output variable, gl_CullDistance provides the place for the shader to write these distances. As an input in all but the fragment language, it reads the values written in the previous shader stage. In the fragment language, gl_CullDistance array contains linearly interpolated values for the vertex values written by a shader to the gl_CullDistance vertex output variable. It is a compile-time or link-time error for the set of shaders forming a program to have the sum of the sizes of the gl_ClipDistance and gl_CullDistance arrays to be larger than gl_MaxCombinedClipAndCullDistances. Modify Section 7.2, "Built-In Constants" (p. 126) const mediump int gl_MaxClipDistances = 8; const mediump int gl_MaxCullDistances = 8; const mediump int gl_MaxCombinedClipAndCullDistances = 8; Additions to the AGL/EGL/GLX/WGL Specifications None Dependencies on OpenGL ES 3.2 If OpenGL ES 3.2 is not supported, ignore all references to geometry and tessellation shaders (unless one of the following extensions is supported). Dependencies on OES_tessellation_shader and EXT_tessellation_shader If neither OES_tessellation_shader nor EXT_tessellation_shader are supported, ignore all references to tessellation shaders. Dependencies on OES_tessellation_point_size and EXT_tessellation_point_size If neither OES_tessellation_point_size nor EXT_tessellation_point_size are supported, ignore all references to gl_PointSize as inputs or outputs to the tessellation stages. Dependencies on OES_geometry_shader and EXT_geometry_shader If neither OES_geometry_shader nor EXT_geometry_shader are supported, ignore all references to geometry shaders. Errors none New State Add the following to Table 21.6 (Transformation State), p447: Initial Get Value Type Get Command Value Description Sec. ------------------ ------ ----------- -------- ----------------- ---- CLIP_DISTANCEi_EXT 8* x B IsEnabled FALSE ith user clipping 12.4 plane enabled New Implementation Dependent State Add the following to Table 21.40 (Implementation Dependent Values), p481: Minimum Get Value Type Get Command Value Description Sec. ---------------------- ---- ----------- -------- ----------------- ---- MAX_CLIP_DISTANCES_EXT Z+ GetIntegerv 8 Max. no. of user 12.4 clipping planes MAX_CULL_DISTANCE_EXT Z+ GetIntegerv 8 Max. no. of user 12.4 cull distances MAX_COMBINED_CLIP_AND- Z+ GetIntegerv 8 Max. combined no. 12.4 _CULL_DISTANCES_EXT of user clipping Conformance Tests Unspecified at this time. Issues For historical issues see ARB_clip_distance (1) If the vertex shader stages write to clip/cull distance, do further vertex processing stages need to pass it through? RESOLVED: Yes. This is how it works in OpenGL. (2) Should we have two separate GLSL behavior: #extension GL_EXT_clip_distance : #extension GL_EXT_cull_distance : or single behavior for both: #extension GL_EXT_clip_cull_distance : RESOLVED: Single behavior for both the clip/cull functionality: #extension GL_EXT_clip_cull_distance : Revision History Rev. Date Author Changes ---- -------- ------ --------------------------------- 4 02/27/24 zmike Add GL_OES_shader_io_blocks interaction. 3 03/09/16 mribble Clean up QTI names and emails. 2 03/08/16 dkoch Language consistency and cleanup pass. Added a bunch of missing language. 1 kseth Initial draft