Name EXT_polygon_offset_clamp Name Strings GL_EXT_polygon_offset_clamp Contact Eric Lengyel (lengyel 'at' terathon.com) Contributors Eric Lengyel, Terathon Software Tobias Hector, Imagination Technologies Status Complete. Version Last Modified Date: February 11, 2016 Revision: 4 Number OpenGL Extension #460 OpenGL ES Extension #252 Dependencies OpenGL 3.3 (either core or compatibility profiles), or OpenGL ES 1.0 is required. This extension is written against the OpenGL 3.3 (Core Profile) Specification (March 11, 2010) and the OpenGL ES 3.1 Specification (October 29, 2014). Overview This extension adds a new parameter to the polygon offset function that clamps the calculated offset to a minimum or maximum value. The clamping functionality is useful when polygons are nearly parallel to the view direction because their high slopes can result in arbitrarily large polygon offsets. In the particular case of shadow mapping, the lack of clamping can produce the appearance of unwanted holes when the shadow casting polygons are offset beyond the shadow receiving polygons, and this problem can be alleviated by enforcing a maximum offset value. IP Status No known IP claims. New Procedures and Functions void PolygonOffsetClampEXT(float factor, float units, float clamp); New Tokens Accepted by the parameters of GetBooleanv, GetIntegerv, GetInteger64v, GetFloatv, and GetDoublev: POLYGON_OFFSET_CLAMP_EXT 0x8E1B Additions to Chapter 3 of the OpenGL 3.3 (Core Profile) Specification (Rasterization), and Chapter 13 of the OpenGL ES Specification (Polygons) -- Modify Open GL section 3.6.4 and OpenGL ES section 13.5.2, "Depth Offset" Replace the 1st paragraph... "The depth values of all fragments generated by the rasterization of a polygon may be offset by a single value that is computed for that polygon. The function that determines this value is specified with the commands void PolygonOffsetClampEXT(float factor, float units, float clamp); void PolygonOffset(float factor, float units); scales the maximum depth slope of the polygon, and scales an implementation-dependent constant that relates to the usable resolution of the depth buffer. The resulting values are summed to produce the polygon offset value, which may then be clamped to a minimum or maximum value specified by . The values , , and may each be positive, negative, or zero. Calling the command PolygonOffset is equivalent to calling the command PolygonOffsetClampEXT with equal to zero." Replace the 5th paragraph... "The offset value o for a polygon is _ | m x + r x , if = 0 or NaN; | o = < min(m x + r x , ), if > 0; | |_ max(m x + r x , ), if < 0. m is computed as described above. If the depth buffer uses a fixed- point representation, m is a function of depth values in the range [0, 1], and o is applied to depth values in the same range." Additions to the AGL/EGL/GLX/WGL Specifications None GLX Protocol A new GL rendering command is added. The following command is sent to the server as part of a glXRender request: PolygonOffsetClampEXT 2 16 rendering command length 2 4225 rendering command opcode 4 FLOAT32 factor 4 FLOAT32 units 4 FLOAT32 clamp Errors None New State (OpenGL) Get Value Type Get Command Initial Value Description Sec Attrib ------------------------ ---- ----------- ------------- -------------------- ----- ------- POLYGON_OFFSET_CLAMP_EXT R GetFloatv 0 Polygon offset clamp 3.6.4 polygon New State (OpenGL ES) Add the following to Table 20.6: Rasterization Get Value Type Get Command Initial Value Description Sec ------------------------ ---- ----------- ------------- -------------------- ------ POLYGON_OFFSET_CLAMP_EXT R GetFloatv 0 Polygon offset clamp 13.5.2 New Implementation Dependent State None Issues 1) Should the PolygonOffsetClampEXT command specify only the parameter, or should it specify all three of the parameters , , and ? Defining a new command that specifies new state in addition to state that can be specified with an existing command has a precedent in the BlendFuncSeparate command. The argument can be made that an application would usually want to set the and values at the same time it sets the value, and making one GL call is better than making two GL calls. Furthermore, requiring that a call to PolygonOffset sets POLYGON_OFFSET_CLAMP_EXT to zero insulates applications unaware of the new state from failures to restore it to its initial value in separate libraries, and this cannot be done if an orthogonal command specifying only the value were to be defined. RESOLVED: This extension defines a new command that specifies the , , and parameters. 2) What happens if is infinity or NaN? As per Section 2.1, the result of providing an infinity or NaN is unspecified. However, if is positive or negative infinity, then Equation (3.13), in the literal mathematical sense, is effectively reduced to the case in which no clamping occurs, and this should be the defined behavior. If is a floating-point NaN, then we could leave the result undefined, but that could lead to application code working correctly with one implementation and then inexplicably failing with another. It would be better to define the behavior such that no clamping occurs. If this is not the behavior exhibited by the hardware, then the implementation can turn all infinites and NaNs into zero using the following code: int32_t clampBits = *(int32_t *) &clamp; clampBits &= (((clampBits >> 23) & 0xFF) - 0xFF) >> 31; This ANDs with all one bits if and only if the floating-point exponent is less than 255. Otherwise, it ANDs with all zero bits. (This assumes a well-defined right shift of negative integers.) RESOLVED: If is infinity or NaN, then no clamping is applied to the polygon offset. 3) What happens if is a denormalized floating-point value? As per Section 2.1, the result of providing a denormalized value must yield predictable results. However, some implementations may treat denormalized values as equal to zero, and other implementations may treat them as greater than or less than zero. To ensure uniform behavior across all implementations, we can require that denormalized values not be equal to zero. This may necessitate that implementations convert denormalized values to the smallest representable normalized value with the same sign. RESOLVED: Denormalized values are not considered equal to zero in Equation (3.13). Revision History Rev. Date Author Changes ---- -------- --------- ------------------------------------------ 4 02/11/16 thector Fixed an incorrect vendor suffix (was IMG) 3 10/21/15 thector Added OpenGL ES interactions. 2 08/27/14 elengyel Added enum value for new token, resolved issues, changed status to complete. 1 08/14/14 elengyel Initial draft.