libdragon
Data Structures | Macros | Functions | Variables

RDP Command queue: triangle drawing routine. More...

Data Structures

struct  rdpq_tri_edge_data_t
 Precomputed information about edges and slopes. More...
 

Macros

#define TRIANGLE_TRACE   0
 Set to 1 to activate tracing of all parameters of all triangles.
 
#define tracef(fmt, ...)   ({ })
 like debugf(), but writes only if TRIANGLE_TRACE is not 0
 

Functions

void rdpq_triangle_cpu (const rdpq_trifmt_t *fmt, const float *v1, const float *v2, const float *v3)
 RDP triangle primitive assembled on the CPU.
 
void rdpq_triangle_rsp (const rdpq_trifmt_t *fmt, const float *v1, const float *v2, const float *v3)
 RDP triangle primitive assembled on the RSP.
 
void rdpq_triangle (const rdpq_trifmt_t *fmt, const float *v1, const float *v2, const float *v3)
 Draw a triangle (RDP command: TRI_*) More...
 

Variables

const rdpq_trifmt_t TRIFMT_FILL
 Format descriptor for a solid-filled triangle. More...
 
const rdpq_trifmt_t TRIFMT_SHADE
 Format descriptor for a shaded triangle. More...
 
const rdpq_trifmt_t TRIFMT_TEX
 Format descriptor for a textured triangle. More...
 
const rdpq_trifmt_t TRIFMT_SHADE_TEX
 Format descriptor for a shaded, textured triangle. More...
 
const rdpq_trifmt_t TRIFMT_ZBUF
 Format descriptor for a solid-filled, z-buffered triangle. More...
 
const rdpq_trifmt_t TRIFMT_ZBUF_SHADE
 Format descriptor for a z-buffered, shaded triangle. More...
 
const rdpq_trifmt_t TRIFMT_ZBUF_TEX
 Format descriptor for a z-buffered, textured triangle. More...
 
const rdpq_trifmt_t TRIFMT_ZBUF_SHADE_TEX
 Format descriptor for a z-buffered, shaded, textured triangle. More...
 

Detailed Description

RDP Command queue: triangle drawing routine.

This file contains the implementation of a single function: rdpq_triangle.

The RDP triangle commands are complex to assemble because they are designed for the hardware that will be drawing them, rather than for the programmer that needs to create them. Specifically, they contain explicit gradients (partial derivatives aka horizontal and vertical per-pixel increments) for all attributes that need to be interpolated. Moreover, the RDP is able to draw triangles with subpixel precision, so input coordinates are fixed point and the setup code must take into account exactly how the rasterizer will handle fractional values.


Data Structure Documentation

◆ rdpq_tri_edge_data_t

struct rdpq_tri_edge_data_t

Precomputed information about edges and slopes.

Data Fields
float hx High edge (X)
float hy High edge (Y)
float mx Middle edge (X)
float my Middle edge (Y)
float fy Fractional part of Y1 (top vertex)
float ish Inverse slope of higher edge.
float attr_factor Inverse triangle normal (used to calculate gradients)

Function Documentation

◆ rdpq_triangle()

void rdpq_triangle ( const rdpq_trifmt_t fmt,
const float *  v1,
const float *  v2,
const float *  v3 
)

Draw a triangle (RDP command: TRI_*)

This function allows to draw a triangle into the framebuffer using RDP, in screen coordinates. RDP does not handle transform and lightning, so it only reasons of screen level coordinates.

Each vertex of a triangle is made of up to 4 components:

  • Position. 2 values: X, Y. The values must be in screen coordinates, that is they refer to the framebuffer pixels. Fractional values allow for subpixel precision. Supported range is [-4096..4095] (numbers outside that range will be clamped).
  • Depth. 1 value: Z. Supported range in [0..1].
  • Shade. 4 values: R, G, B, A. The values must be in the 0..1 range.
  • Texturing. 3 values: S, T, INV_W. The values S,T address the texture specified by the tile descriptor. INV_W is the inverse of the W vertex coordinate in clip space (after projection), a value commonly used to do the final perspective division. This value is required to do perspective-corrected texturing.

Only the position is mandatory, all other components are optionals, depending on the kind of triangle that needs to be drawn. For instance, specifying only position and shade will allow to draw a gouraud-shaded triangle with no texturing and no z-buffer usage.

The vertex components must be provided via arrays of floating point values. The order of the components within the array is flexible, and can be specified at call time via the rdpq_trifmt_t structure.

Notice that it is important to configure the correct render modes before calling this function. Specifically:

  • To use the depth component, you must activate the z-buffer via rdpq_mode_zbuf.
  • To use the shade component, you must configure a color combiner formula via rdpq_mode_combiner. The formula must use the SHADE slot, to specify the exact pixel formula that will combine the per-pixel color value with other components, like the texture.
  • To use the texturing component, you must configure a color combiner formula via rdpq_mode_combiner that uses the TEX0 (and/or TEX1) slot, such as RDPQ_COMBINER_TEX or RDPQ_COMBINER_SHADE, to specify the exact pixel formula that will combine the per-pixel color value with other components, like the shade. Moreover, you can activate perspective texturing via rdpq_mode_persp.

If you fail to activate a specific render mode for a provided component, the component will be ignored by RDP. For instance, if you provide S,T,W but do not configure a combiner formula that accesses TEX0, the texture will not be rendered. On the contrary, if you activate a specific render mode but then fail to provide the component (eg: activate z buffering but then fail to provide a depth component), RDP will fall into undefined behavior that can vary from nothing being rendered, garbage on the screen or even a freeze. The rdpq validator will do its best to help you catching these mistakes, so remember to activate it via rdpq_debug_start whenever you get a surprising result.

For instance, this code snippet will draw a filled triangle, with a flat green color:

// Reset to standard rendering mode.
// Configure the combiner for flat-color rendering
// Configure the flat color
rdpq_set_prim_color(RGBA32(0, 255, 0, 255));
// Draw the triangle
float v1[] = { 100, 100 };
float v2[] = { 200, 200 };
float v3[] = { 100, 200 };
rdpq_triangle(&TRIFMT_FILL, v1, v2, v3);
#define RGBA32(rx, gx, bx, ax)
Create a color_t from the R,G,B,A components in the RGBA32 range (0-255).
Definition: graphics.h:49
void rdpq_set_prim_color(color_t color)
Set the RDP PRIM combiner register (color only) (RDP command: SET_PRIM_COLOR)
Definition: rdpq.h:949
#define RDPQ_COMBINER_FLAT
Draw a flat color. Configure the color via rdpq_set_prim_color.
Definition: rdpq_macros.h:468
void rdpq_mode_combiner(rdpq_combiner_t comb)
Configure the color combiner.
Definition: rdpq_mode.h:465
void rdpq_set_mode_standard(void)
Reset render mode to standard.
Definition: rdpq_mode.c:92
const rdpq_trifmt_t TRIFMT_FILL
Format descriptor for a solid-filled triangle.
Definition: rdpq_tri.c:39
void rdpq_triangle(const rdpq_trifmt_t *fmt, const float *v1, const float *v2, const float *v3)
Draw a triangle (RDP command: TRI_*)
Definition: rdpq_tri.c:533

The three vertices (v1, v2, v3) can be provided in any order (clockwise or counter-clockwise). The function will render the triangle in any case (so back-face culling must be handled before calling it).

Parameters
fmtFormat of the triangle being drawn. This structure specifies the order of the components within the vertex arrays, and also some additional rasterization parameters. You can pass one of the predefined formats (TRIFMT_FILL, TRIFMT_TEX, etc.), or a custom one.
v1Array of components for vertex 1
v2Array of components for vertex 2
v3Array of components for vertex 3

Variable Documentation

◆ TRIFMT_FILL

const rdpq_trifmt_t TRIFMT_FILL
Initial value:
.pos_offset = 0, .shade_offset = -1, .tex_offset = -1, .z_offset = -1,
}
Format descriptor of a triangle.
Definition: rdpq_tri.h:34

Format descriptor for a solid-filled triangle.

Vertex array format: (float){X, Y} (2 floats)

Given that only position is provided, the triangle is drawn with a solid color, which is the output of the color combiner. See rdpq_mode_combiner for more information.

A common choice for a combiner formula is RDPQ_COMBINER_FLAT, that will simply output whatever color is configured via rdpq_set_prim_color.

◆ TRIFMT_SHADE

const rdpq_trifmt_t TRIFMT_SHADE
Initial value:
.pos_offset = 0, .shade_offset = 2, .tex_offset = -1, .z_offset = -1,
}

Format descriptor for a shaded triangle.

Vertex array format: (float){X, Y, R, G, B, A} (6 floats)

◆ TRIFMT_TEX

const rdpq_trifmt_t TRIFMT_TEX
Initial value:
.pos_offset = 0, .shade_offset = -1, .tex_offset = 2, .z_offset = -1,
}

Format descriptor for a textured triangle.

Vertex array format: (float){X, Y, S, T, INV_W} (5 floats)

◆ TRIFMT_SHADE_TEX

const rdpq_trifmt_t TRIFMT_SHADE_TEX
Initial value:
.pos_offset = 0, .shade_offset = 2, .tex_offset = 6, .z_offset = -1,
}

Format descriptor for a shaded, textured triangle.

Vertex array format: (float){X, Y, R, G, B, A, S, T, INV_W} (9 floats)

◆ TRIFMT_ZBUF

const rdpq_trifmt_t TRIFMT_ZBUF
Initial value:
.pos_offset = 0, .shade_offset = -1, .tex_offset = -1, .z_offset = 2,
}

Format descriptor for a solid-filled, z-buffered triangle.

Vertex array format: (float){X, Y, Z} (3 floats)

◆ TRIFMT_ZBUF_SHADE

const rdpq_trifmt_t TRIFMT_ZBUF_SHADE
Initial value:
.pos_offset = 0, .shade_offset = 3, .tex_offset = -1, .z_offset = 2,
}

Format descriptor for a z-buffered, shaded triangle.

Vertex array format: (float){X, Y, Z, R, G, B, A} (7 floats)

◆ TRIFMT_ZBUF_TEX

const rdpq_trifmt_t TRIFMT_ZBUF_TEX
Initial value:
.pos_offset = 0, .shade_offset = -1, .tex_offset = 3, .z_offset = 2,
}

Format descriptor for a z-buffered, textured triangle.

Vertex array format: (float){X, Y, Z, S, T, INV_W} (6 floats)

◆ TRIFMT_ZBUF_SHADE_TEX

const rdpq_trifmt_t TRIFMT_ZBUF_SHADE_TEX
Initial value:
.pos_offset = 0, .shade_offset = 3, .tex_offset = 7, .z_offset = 2,
}

Format descriptor for a z-buffered, shaded, textured triangle.

Vertex array format: (float){X, Y, Z, R, G, B, A, S, T, INV_W} (10 floats)