A polygon results from the decomposition of a triangle strip, triangle fan
or a series of independent triangles.
Like points and line segments, polygon rasterization is controlled by
several variables in the VkPipelineRasterizationStateCreateInfo
structure.
The first step of polygon rasterization is to determine whether the triangle is back-facing or front-facing. This determination is made based on the sign of the (clipped or unclipped) polygon’s area computed in framebuffer coordinates. One way to compute this area is:
where $x_f^i$ and $y_f^i$ are the x and y framebuffer coordinates of the ith vertex of the n-vertex polygon (vertices are numbered starting at zero for the purposes of this computation) and i ⊕ 1 is (i + 1) mod n.
The interpretation of the sign of a is determined by the
VkPipelineRasterizationStateCreateInfo
::frontFace
property of
the currently active pipeline, which takes the following values:
typedef enum VkFrontFace { VK_FRONT_FACE_COUNTER_CLOCKWISE = 0, VK_FRONT_FACE_CLOCKWISE = 1, } VkFrontFace;
If frontFace
is set to VK_FRONT_FACE_COUNTER_CLOCKWISE
, a
triangle with positive area is considered front-facing.
If it is set to VK_FRONT_FACE_CLOCKWISE
, a triangle with negative area
is considered front-facing.
Any triangle which is not front-facing is back-facing, including zero-area
triangles.
Once the orientation of triangles is determined, they are culled according
to the setting of the
VkPipelineRasterizationStateCreateInfo
::cullMode
property of the
currently active pipeline, which takes the following values:
typedef enum VkCullModeFlagBits { VK_CULL_MODE_NONE = 0, VK_CULL_MODE_FRONT_BIT = 0x00000001, VK_CULL_MODE_BACK_BIT = 0x00000002, VK_CULL_MODE_FRONT_AND_BACK = 0x00000003, } VkCullModeFlagBits;
If the cullMode
is set to VK_CULL_MODE_NONE
no triangles are
discarded, if it is set to VK_CULL_MODE_FRONT_BIT
front-facing
triangles are discarded, if it is set to VK_CULL_MODE_BACK_BIT
then
back-facing triangles are discarded and if it is set to
VK_CULL_MODE_FRONT_AND_BACK
then all triangles are discarded.
Following culling, fragments are produced for any triangles which have not
been discarded.
The rule for determining which fragments are produced by polygon rasterization is called point sampling. The two-dimensional projection obtained by taking the x and y framebuffer coordinates of the polygon’s vertices is formed. Fragments are produced for any pixels for which any sample points lie inside of this polygon. Coverage bits that correspond to sample points that satisfy the point sampling criteria are 1, other coverage bits are 0. Special treatment is given to a sample whose sample location lies on a polygon edge. In such a case, if two polygons lie on either side of a common edge (with identical endpoints) on which a sample point lies, then exactly one of the polygons must result in a covered sample for that fragment during rasterization. As for the data associated with each fragment produced by rasterizing a polygon, we begin by specifying how these values are produced for fragments in a triangle. Define barycentric coordinates for a triangle. Barycentric coordinates are a set of three numbers, a, b, and c, each in the range [0,1], with a + b + c = 1. These coordinates uniquely specify any point p within the triangle or on the triangle’s boundary as
where p_{a}, p_{b}, and p_{c} are the vertices of the triangle. a, b, and c are determined by:
where A(lmn) denotes the area in framebuffer coordinates of the triangle with vertices l, m, and n.
Denote an associated datum at p_{a}, p_{b}, or p_{c} as f_{a}, f_{b}, or f_{c}, respectively.
The value of an associated datum f for a fragment produced by rasterizing a triangle, whether it be a shader output or the clip w coordinate, must be determined using perspective interpolation:
where w_{a}, w_{b}, and w_{c} are the clip w
coordinates of p_{a}, p_{b}, and p_{c}, respectively.
a, b, and c are the barycentric coordinates of the
location at which the data are produced - this must be a pixel center or
the location of a sample.
When rasterizationSamples
is VK_SAMPLE_COUNT_1_BIT
, the pixel
center must be used.
Depth values for triangles must be determined using linear interpolation:
where z_{a}, z_{b}, and z_{c} are the depth values of p_{a}, p_{b}, and p_{c}, respectively.
The NoPerspective
and Flat
interpolation decorations can be used
with fragment shader inputs to declare how they are interpolated.
When neither decoration is applied, perspective interpolation is performed as described above.
When the NoPerspective
decoration is used,
linear interpolation is performed in the
same fashion as for depth values, as described above.
When the Flat
decoration is used, no interpolation is performed, and
outputs are taken from the corresponding input value of the
provoking vertex corresponding to that
primitive.
For a polygon with more than three edges, such as are produced by clipping a triangle, a convex combination of the values of the datum at the polygon’s vertices must be used to obtain the value assigned to each fragment produced by the rasterization algorithm. That is, it must be the case that at every fragment
where n is the number of vertices in the polygon and f_{i} is the value of f at vertex i. For each i, 0 ≤ a_{i} ≤ 1 and $\sum_{i=1}^{n}a_i = 1$ . The values of a_{i} may differ from fragment to fragment, but at vertex i, a_{i} = 1 and a_{j} = 0 for j ≠ i.
Note | |
---|---|
One algorithm that achieves the required behavior is to triangulate a polygon (without adding any vertices) and then treat each triangle individually as already discussed. A scan-line rasterizer that linearly interpolates data along each edge and then linearly interpolates data across each horizontal span from edge to edge also satisfies the restrictions (in this case, the numerator and denominator of equation Section 24.7.1, “Basic Polygon Rasterization” are iterated independently and a division performed for each fragment). |
The method of rasterization for polygons is determined by the
VkPipelineRasterizationStateCreateInfo
::polygonMode
property of
the currently active pipeline, which takes the following values:
typedef enum VkPolygonMode { VK_POLYGON_MODE_FILL = 0, VK_POLYGON_MODE_LINE = 1, VK_POLYGON_MODE_POINT = 2, } VkPolygonMode;
The polygonMode
selects which method of rasterization is used for
polygons.
If polygonMode
is VK_POLYGON_MODE_POINT
, then the vertices of
polygons are treated, for rasterization purposes, as if they had been drawn
as points.
VK_POLYGON_MODE_LINE
causes polygon edges to be drawn as line
segments.
VK_POLYGON_MODE_FILL
causes polygons to render using the polygon
rasterization rules in this section.
Note that these modes affect only the final rasterization of polygons: in particular, a polygon’s vertices are shaded and the polygon is clipped and possibly culled before these modes are applied.
The depth values of all fragments generated by the rasterization of a
polygon can be offset by a single value that is computed for that polygon.
This behavior is controlled by the depthBiasEnable
,
depthBiasConstantFactor
, depthBiasClamp
, and
depthBiasSlopeFactor
members of
VkPipelineRasterizationStateCreateInfo
, or by the corresponding
parameters to the vkCmdSetDepthBias
command if depth bias state is
dynamic.
void vkCmdSetDepthBias( VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor);
commandBuffer
is the command buffer into which the command will be
recorded.
depthBiasConstantFactor
is a scalar factor controlling the
constant depth value added to each fragment.
depthBiasClamp
is the maximum (or minimum) depth bias of a
fragment.
depthBiasSlopeFactor
is a scalar factor applied to a fragment’s
slope in depth bias calculations.
If depthBiasEnable
is VK_FALSE
, no depth bias is applied and the
fragment’s depth values are unchanged.
depthBiasSlopeFactor
scales the maximum depth slope of the polygon,
and depthBiasConstantFactor
scales an implementation-dependent
constant that relates to the usable resolution of the depth buffer.
The resulting values are summed to produce the depth bias value which is
then clamped to a minimum or maximum value specified by
depthBiasClamp
.
depthBiasSlopeFactor
, depthBiasConstantFactor
, and
depthBiasClamp
can each be positive, negative, or zero.
The maximum depth slope m of a triangle is
where (x_{f}, y_{f}, z_{f}) is a point on the triangle. m may be approximated as
The minimum resolvable difference r is an implementation-dependent
parameter that depends on the depth buffer representation.
It is the smallest difference in framebuffer coordinate z values that
is guaranteed to remain distinct throughout polygon rasterization and in the
depth buffer.
All pairs of fragments generated by the rasterization of two polygons with
otherwise identical vertices, but z
_{f} values that differ by
$r$, will have distinct depth values.
For fixed-point depth buffer representations, r is constant throughout the range of the entire depth buffer. For floating-point depth buffers, there is no single minimum resolvable difference. In this case, the minimum resolvable difference for a given polygon is dependent on the maximum exponent, e, in the range of z values spanned by the primitive. If n is the number of bits in the floating-point mantissa, the minimum resolvable difference, r, for the given primitive is defined as
If no depth buffer is present, r is undefined.
The bias value o for a polygon is
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.
For fixed-point depth buffers, fragment depth values are always limited to the range [0,1] by clamping after depth bias addition is performed. Fragment depth values are clamped even when the depth buffer uses a floating-point representation.