Functions that perform primitive rasterization & data interpolation.
More...
| static double | signedAreaParallelogram (const vec3d *restrict a, const vec3d *restrict b) |
| |
| static void | calculateBarycentricCoordinatesForPointAndBarycentricDeltas (const vec3d *restrict SSPositions, const vec3d *restrict edgeVectors, vec2d point, double *restrict barycentricCoordinates, double *restrict barycentricDeltaX, double *restrict barycentricDeltaY) |
| |
| static bool | triangleIsEdgeFlatTopOrLeft (const vec3d *restrict edgeVector) |
| |
| static void | triangleInterpolatePositionAndVertexVariables (const SRPvsOutput vertices[3], const double barycentricCoordinates[3], const SRPShaderProgram *restrict sp, SRPInterpolated *pInterpolatedBuffer, vec4d *interpolatedPosition) |
| |
| void | drawTriangle (const SRPFramebuffer *fb, const SRPvsOutput vertices[3], const SRPShaderProgram *restrict sp, size_t primitiveID) |
| |
Functions that perform primitive rasterization & data interpolation.
◆ calculateBarycentricCoordinatesForPointAndBarycentricDeltas()
| static void calculateBarycentricCoordinatesForPointAndBarycentricDeltas |
( |
const vec3d *restrict |
SSPositions, |
|
|
const vec3d *restrict |
edgeVectors, |
|
|
vec2d |
point, |
|
|
double *restrict |
barycentricCoordinates, |
|
|
double *restrict |
barycentricDeltaX, |
|
|
double *restrict |
barycentricDeltaY |
|
) |
| |
|
static |
Calculate barycentric coordinates for a point and barycentric coordinates' delta values.
- Parameters
-
| [in] | SSPositions | Vertices' positions in screen-space |
| [in] | edgeVectors | Triangle's edge vectors, where 0th element is a vector pointing from vertex 0 to vertex 1, 1th - from vertex 1 to vertex 2 and so on. |
| [in] | point | A point for which to calculate the barycentric coordinates |
| [out] | barycentricCoordinates | A pointer to 3-element double array to where output barycentric coordinates to |
| [out] | barycentricDeltaX,barycentricDeltaY | A pointer to 3-element double array to where to output the X and Y barycentric delta values. These show how much does the barycentric coordinates change if we move one pixel to the +X or to the +Y direction. Used in incremental computation of barycentric coordinates when looping over triangle's bounding box |
◆ drawTriangle()
Draw the triangle that is specified by three vertices to the framebuffer
- Parameters
-
| [in] | `fb` | The framebuffer to draw to |
| [in] | `vertices` | Pointer to an array of 3 SRPvsOutputs |
| [in] | `sp` | The shader program to use |
| [in] | `primitiveID` | Primitive ID of this triangle |
- Todo:
- Why compute these two edge vectors twice?
- Todo:
- Are rasterization rules working? Rough equality here?
- Todo:
- Avoid VLA (custom allocator?)
- Todo:
- fix rasterizer to accept both cw and ccw vertices and add correct
frontFacing here!
- Todo:
fragCoord should be window-space: see https://www.khronos.org/opengl/wiki/Fragment_Shader#Inputs
- Todo:
SRPfsOutput.fragDepth may be set to 0 manually by the user
◆ signedAreaParallelogram()
| static double signedAreaParallelogram |
( |
const vec3d *restrict |
a, |
|
|
const vec3d *restrict |
b |
|
) |
| |
|
static |
◆ triangleInterpolatePositionAndVertexVariables()
| static void triangleInterpolatePositionAndVertexVariables |
( |
const SRPvsOutput |
vertices[3], |
|
|
const double |
barycentricCoordinates[3], |
|
|
const SRPShaderProgram *restrict |
sp, |
|
|
SRPInterpolated * |
pInterpolatedBuffer, |
|
|
vec4d * |
interpolatedPosition |
|
) |
| |
|
static |
Interpolate the fragment position and vertex variables inside the triangle.
- Parameters
-
| [in] | vertices | A pointer to an array of 3 vertices |
| [in] | barycentricCoordinates | Barycentric coordinates of the fragment |
| [in] | sp | A pointer to shader program to use |
| [out] | pInterpolatedBuffer | A pointer to the buffer where interpolated variables will appear. Must be big enough to hold all of them |
| [out] | interpolatedPosition | A pointer to vec4d where interpolated position will appear. |
Let \( v_0, v_1, v_2 \) be points in space that form a triangle and \( a, b, c \) be barycentric coordinates for a point \( P \) according to \( v_0, v_1, v_2 \) respectively. Then, by the property of barycentric coordinates \( P = av_0 + bv_1 + cv_2 \). This can be extrapolated to arbitrary values assigned to vertices, so this property lies in the core of so-called "affine" attribute interpolation.
But this method does not take into account that we have performed the perspective divide, so the texture (or whatever) will appear "skewed" on the primitive.
It can be shown (see the "see also" section) that perspective-correct Z value can be obtained by linearly interpolating between the reciprocals of input Z values, and similarly for arbitrary parameters. This is called perspective-correct attribute interpolation.
- See also
- https://www.comp.nus.edu.sg/%7Elowkl/publications/lowk_persp_interp_techrep.pdf
-
https://www.youtube.com/watch?v=F5X6S35SW2s
◆ triangleIsEdgeFlatTopOrLeft()
| static bool triangleIsEdgeFlatTopOrLeft |
( |
const vec3d *restrict |
edgeVector | ) |
|
|
static |
Check if a triangle's edge is flat top or left. Used in rasterization rules.
- Parameters
-
| [in] | edgeVector | A pointer to an edge vector (pointing from one vertex to the other) |
- Returns
- Whether or not this edge is flat top or left
- Todo:
- Does it matter if I pass edge 0->1 or 1->0 (numbers = vertex indices)? This should be documented.