EXT_polygon_offset_clamp

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 <pname> 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);

<factor> scales the maximum depth slope of the polygon, and <units>
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 <clamp>. The
values <factor>, <units>, and <clamp> may each be positive,
negative, or zero. Calling the command PolygonOffset is equivalent
to calling the command PolygonOffsetClampEXT with <clamp> equal to
zero."

Replace the 5th paragraph...

"The offset value o for a polygon is
      _
     |   m x <factor> + r x <units>,          if <clamp> = 0 or NaN;
     |
o = <    min(m x <factor> + r x <units>, <clamp>),   if <clamp> > 0;
     |
     |_  max(m x <factor> + r x <units>, <clamp>),   if <clamp> < 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 <clamp>
    parameter, or should it specify all three of the parameters
    <factor>, <units>, and <clamp>?

    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 <factor>
    and <units> values at the same time it sets the <clamp> 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 <clamp> value were to be
    defined.

    RESOLVED: This extension defines a new command that specifies
    the <factor>, <units>, and <clamp> parameters.

2)  What happens if <clamp> is infinity or NaN?

    As per Section 2.1, the result of providing an infinity or NaN
    is unspecified. However, if <clamp> 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 <clamp> 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 <clamp> is infinity or NaN, then no clamping is
    applied to the polygon offset.

3)  What happens if <clamp> 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.