libdragon
|
RDP Command queue: mode setting. More...
Go to the source code of this file.
Enumerations | |
enum | rdpq_filter_t { FILTER_POINT = SOM_SAMPLE_POINT >> SOM_SAMPLE_SHIFT , FILTER_BILINEAR = SOM_SAMPLE_BILINEAR >> SOM_SAMPLE_SHIFT , FILTER_MEDIAN = SOM_SAMPLE_MEDIAN >> SOM_SAMPLE_SHIFT } |
Texture filtering types. More... | |
enum | rdpq_dither_t { DITHER_SQUARE_SQUARE = (SOM_RGBDITHER_SQUARE | SOM_ALPHADITHER_SAME) >> SOM_ALPHADITHER_SHIFT , DITHER_SQUARE_INVSQUARE = (SOM_RGBDITHER_SQUARE | SOM_ALPHADITHER_INVERT) >> SOM_ALPHADITHER_SHIFT , DITHER_SQUARE_NOISE = (SOM_RGBDITHER_SQUARE | SOM_ALPHADITHER_NOISE) >> SOM_ALPHADITHER_SHIFT , DITHER_SQUARE_NONE = (SOM_RGBDITHER_SQUARE | SOM_ALPHADITHER_NONE) >> SOM_ALPHADITHER_SHIFT , DITHER_BAYER_BAYER = (SOM_RGBDITHER_BAYER | SOM_ALPHADITHER_SAME) >> SOM_ALPHADITHER_SHIFT , DITHER_BAYER_INVBAYER = (SOM_RGBDITHER_BAYER | SOM_ALPHADITHER_INVERT) >> SOM_ALPHADITHER_SHIFT , DITHER_BAYER_NOISE = (SOM_RGBDITHER_BAYER | SOM_ALPHADITHER_NOISE) >> SOM_ALPHADITHER_SHIFT , DITHER_BAYER_NONE = (SOM_RGBDITHER_BAYER | SOM_ALPHADITHER_NONE) >> SOM_ALPHADITHER_SHIFT , DITHER_NOISE_SQUARE = (SOM_RGBDITHER_NOISE | SOM_ALPHADITHER_SAME) >> SOM_ALPHADITHER_SHIFT , DITHER_NOISE_INVSQUARE = (SOM_RGBDITHER_NOISE | SOM_ALPHADITHER_INVERT) >> SOM_ALPHADITHER_SHIFT , DITHER_NOISE_NOISE = (SOM_RGBDITHER_NOISE | SOM_ALPHADITHER_NOISE) >> SOM_ALPHADITHER_SHIFT , DITHER_NOISE_NONE = (SOM_RGBDITHER_NOISE | SOM_ALPHADITHER_NONE) >> SOM_ALPHADITHER_SHIFT , DITHER_NONE_BAYER = (SOM_RGBDITHER_NONE | SOM_ALPHADITHER_SAME) >> SOM_ALPHADITHER_SHIFT , DITHER_NONE_INVBAYER = (SOM_RGBDITHER_NONE | SOM_ALPHADITHER_INVERT) >> SOM_ALPHADITHER_SHIFT , DITHER_NONE_NOISE = (SOM_RGBDITHER_NONE | SOM_ALPHADITHER_NOISE) >> SOM_ALPHADITHER_SHIFT , DITHER_NONE_NONE = (SOM_RGBDITHER_NONE | SOM_ALPHADITHER_NONE) >> SOM_ALPHADITHER_SHIFT } |
Dithering configuration. More... | |
enum | rdpq_tlut_t { TLUT_NONE = 0 , TLUT_RGBA16 = 2 , TLUT_IA16 = 3 } |
Types of palettes supported by RDP. More... | |
enum | rdpq_mipmap_t { MIPMAP_NONE = 0 , MIPMAP_NEAREST = SOM_TEXTURE_LOD >> 32 , MIPMAP_INTERPOLATE = (SOM_TEXTURE_LOD | SOMX_LOD_INTERPOLATE) >> 32 , MIPMAP_INTERPOLATE_SHARPEN = (SOM_TEXTURE_LOD | SOMX_LOD_INTERPOLATE | SOM_TEXTURE_SHARPEN) >> 32 , MIPMAP_INTERPOLATE_DETAIL = (SOM_TEXTURE_LOD | SOMX_LOD_INTERPOLATE | SOM_TEXTURE_DETAIL) >> 32 } |
Types of mipmap supported by RDP. More... | |
enum | rdpq_antialias_t { AA_NONE = 0 , AA_STANDARD = 1 , AA_REDUCED = 2 } |
Types of antialiasing supported by RDP. More... | |
Functions | |
void | rdpq_mode_push (void) |
Push the current render mode into the stack. | |
void | rdpq_mode_pop (void) |
Pop the current render mode from the stack. | |
rdpq_tlut_t | rdpq_tlut_from_format (tex_format_t format) |
Converts the specified texture format to the TLUT mode that is needed to draw a texture of this format. | |
void | rdpq_mode_begin (void) |
Start a batch of RDP mode changes. | |
void | rdpq_mode_end (void) |
Finish a batch of RDP mode changes. | |
Render modes | |
These functions set a new render mode from scratch. Every render state is reset to some value (or default), so no previous state is kept valid. | |
void | rdpq_set_mode_standard (void) |
Reset render mode to standard. | |
void | rdpq_set_mode_fill (color_t color) |
Reset render mode to FILL type. | |
void | rdpq_set_mode_copy (bool transparency) |
Reset render mode to COPY type. | |
void | rdpq_set_mode_yuv (bool bilinear) |
Reset render mode to YUV mode. | |
Render states | |
These functions allow to tweak individual render states. They should be called after one of the render mode reset functions to configure the render states. | |
#define | RDPQ_BLENDER_MULTIPLY RDPQ_BLENDER((IN_RGB, IN_ALPHA, MEMORY_RGB, INV_MUX_ALPHA)) |
Blending mode: multiplicative alpha. | |
#define | RDPQ_BLENDER_MULTIPLY_CONST RDPQ_BLENDER((IN_RGB, FOG_ALPHA, MEMORY_RGB, INV_MUX_ALPHA)) |
Blending mode: multiplicative alpha with a constant value. | |
#define | RDPQ_BLENDER_ADDITIVE RDPQ_BLENDER((IN_RGB, IN_ALPHA, MEMORY_RGB, ONE)) |
Blending mode: additive alpha. You can pass this macro to rdpq_mode_blender. | |
#define | RDPQ_FOG_STANDARD RDPQ_BLENDER((IN_RGB, SHADE_ALPHA, FOG_RGB, INV_MUX_ALPHA)) |
Fogging mode: standard. You can pass this macro to rdpq_mode_fog. | |
void | rdpq_mode_antialias (rdpq_antialias_t mode) |
Activate antialiasing. | |
void | rdpq_mode_combiner (rdpq_combiner_t comb) |
Configure the color combiner. | |
void | rdpq_mode_blender (rdpq_blender_t blend) |
Configure the formula to use for blending. | |
void | rdpq_mode_fog (rdpq_blender_t fog) |
Enable or disable fog. | |
void | rdpq_mode_dithering (rdpq_dither_t dither) |
Change dithering mode. | |
void | rdpq_mode_alphacompare (int threshold) |
Activate alpha compare feature. | |
void | rdpq_mode_zbuf (bool compare, bool update) |
Activate z-buffer usage. | |
void | rdpq_mode_zoverride (bool enable, float z, int16_t deltaz) |
Set a fixed override of Z value. | |
void | rdpq_mode_tlut (rdpq_tlut_t tlut) |
Activate palette lookup during drawing. | |
void | rdpq_mode_filter (rdpq_filter_t filt) |
Activate texture filtering. | |
void | rdpq_mode_mipmap (rdpq_mipmap_t mode, int num_levels) |
Activate mip-mapping. | |
void | rdpq_mode_persp (bool perspective) |
Activate perspective correction for textures. | |
RDP Command queue: mode setting.
The mode API is a high level API to simplify mode setting with RDP. Configuring render modes is possibly the most complex task with RDP programming, as the RDP is full of hardware features that interact badly between them or are in general non-orthogonal. The mode API tries to hide much of the complexity between an API more similar to a modern graphic API like OpenGL.
In general, mode setting with RDP is performed via two commands SET_COMBINE_MODE and SET_OTHER_MODES. These two commands are available as "raw" commands in the basic rdpq API as rdpq_set_combiner_raw and rdpq_set_other_modes_raw. These two functions set the specified configurations into the RDP hardware registers, and do nothing else, so they can always be used to do manual RDP programming.
Instead, the mode API follows the following pattern:
rdpq_set_mode_*
functions.rdpq_mode_*
functions.The rdpq mode API currently offers the following render modes:
rdpq_mode_*
functions).After setting the render mode, you can configure the render states. An important implementation effort has been made to try and make the render states orthogonal, so that each one can be toggled separately without inter-dependence (a task which is particularly complex on the RDP hardware). Not all render states are available in all modes, refer to the documentation of each render state for further information.
The mode API also keeps a small (4 entry) stack of mode configurations. This allows client code to temporarily switch render mode and then get back to the previous mode, which helps modularizing the code.
To save the current render mode onto the stack, use rdpq_mode_push. To restore the previous render mode from the stack, use rdpq_mode_pop.
Notice the mode settings being part of this stack are those which are configured via the mode API functions itself (rdpq_set_mode_*
and rdpq_mode_*
). Anything that doesn't go through the mode API is not saved/restored. For instance, activating blending via rdpq_mode_blender is saved onto the stack, whilst changing the BLEND color register (via rdpq_set_blend_color) is not, and you can tell by the fact that the function called to configure it is not part of the mode API.
#define RDPQ_BLENDER_MULTIPLY RDPQ_BLENDER((IN_RGB, IN_ALPHA, MEMORY_RGB, INV_MUX_ALPHA)) |
Blending mode: multiplicative alpha.
This is standard multiplicative blending between the color being drawn and the framebuffer color.
You can pass this macro to rdpq_mode_blender.
#define RDPQ_BLENDER_MULTIPLY_CONST RDPQ_BLENDER((IN_RGB, FOG_ALPHA, MEMORY_RGB, INV_MUX_ALPHA)) |
Blending mode: multiplicative alpha with a constant value.
This is similar to RDPQ_BLENDER_MULTIPLY, but instead of using the alpha value from the texture (or rather, the one coming out of the color combiner), it uses a constant value that must be programmed via rdpq_set_fog_color:
You can pass this macro to rdpq_mode_blender:
Notice that the alpha value coming out of the combiner is ignored for the effect of blending, but it still used for alpha compare. This is very useful because for instance you can have a sprite with a 1-bit alpha channel to perform alpha compare masking, but still have a semi-transparency effect applied to the visible portions of the sprite.
#define RDPQ_BLENDER_ADDITIVE RDPQ_BLENDER((IN_RGB, IN_ALPHA, MEMORY_RGB, ONE)) |
Blending mode: additive alpha. You can pass this macro to rdpq_mode_blender.
NOTE: additive blending is broken on RDP because it can overflow. Basically, if the result of the sum is larger than 1.5 (in scale 0..1), instead of being clamped to 1, it overflows back to 0, which makes the mode almost useless. It is defined it for completeness.
enum rdpq_filter_t |
enum rdpq_dither_t |
Dithering configuration.
RDP can optionally perform dithering on RGB and Alpha channel of the texture. The dithering is performed by the blender unit, which is also in charge of adapting the pixel color depth to that of the framebuffer. Dithering is a good way to reduce the mach banding effect created by color depth reduction.
The blender in fact will reduce the RGB components of the pixel (coming from the color combiner) to 5-bit when the framebuffer is 16-bit. If the framebuffer is 32-bit, the blender formula will be calculated with 8-bit per channel, so no dithering is required.
On the other hand, the alpha channels (used as multiplicative factors in the blender formulas) will always be reduced to 5-bit depth, even if the framebuffer is 32-bit. If you see banding artifacts in transparency levels of blended polygons, you may want to activate dithering on the alpha channel.
It is important to notice that the VI can optionally run an "dither filter" on the final image, while sending it to the video output. This algorithm tries to recover color depth precision by averaging lower bits in neighborhood pixels, and reducing the small noise created by dithering. display_init currently activates it by default on all 16-bit display modes, if passed FILTERS_DEDITHER or FILTERS_RESAMPLE_ANTIALIAS_DEDITHER.
If you are using an emulator, make sure it correctly emulates the VI dither filter to judge the quality of the final image. For instance, the RDP plugin parallel-RDP (based on Vulkan) emulates it very accurately, so emulators like Ares, dgb-n64 or simple64 will produce a picture closer to real hardware.
The supported dither algorithms are:
SQUARE
(aka "magic square"). This is a custom dithering algorithm, designed to work best with the VI dither filter. When using it, the VI will reconstruct a virtually perfect 32-bit image even though the framebuffer is only 16-bit.BAYER
: standard Bayer dithering. This algorithm looks better than the magic square when the VI dither filter is disabled, or in some specific scenarios like large blended polygons. Make sure to test it as well.INVSQUARE
and INVBAYER
: these are the same algorithms, but using an inverse (symmetrical) pattern. They can be selected for alpha channels to avoid making transparency phase with color dithering, which is sometimes awkward.NOISE
: random noise dithering. The dithering is performed by perturbing the lower bit of each pixel with random noise. This will create a specific visual effect as it changes from frame to frame even on still images; it is especially apparent when used on alpha channel as it can affect transparency. It is more commonly used as a graphic effect rather than an actual dithering.NONE
: disable dithering.While the RDP hardware allows to configure different dither algorithms for RGB and Alpha channels, unfortunately not all combinations are available. This enumerator defines the available combinations. For instance, DITHER_BAYER_NOISE selects the Bayer dithering for the RGB channels, and the noise dithering for alpha channel.
enum rdpq_tlut_t |
Types of palettes supported by RDP.
Enumerator | |
---|---|
TLUT_NONE | No palette. |
TLUT_RGBA16 | Palette made of FMT_RGBA16 colors. |
TLUT_IA16 | Palette made of FMT_IA16 colors. |
enum rdpq_mipmap_t |
Types of mipmap supported by RDP.
enum rdpq_antialias_t |
void rdpq_mode_push | ( | void | ) |
Push the current render mode into the stack.
This function allows to push the current render mode into an internal stack. It allows to temporarily modify the render mode, and later recover its value.
This is effective on all render mode changes that can be modified via rdpq_mode_* function. It does not affect other RDP configurations such as the various colors.
The stack has 4 slots (including the current one).
void rdpq_mode_pop | ( | void | ) |
Pop the current render mode from the stack.
This function allows to pop a previously pushed render mode from the stack, setting it as current again.
|
inline |
Reset render mode to standard.
This is the most basic and general mode reset function. It configures the RDP processor in a standard and very basic way:
You can further configure the mode by calling one of the many functions in the mode API (rdpq_mode_*
).
|
inline |
Reset render mode to FILL type.
This function sets the render mode type to FILL, which is used to quickly fill portions of the screens with a solid color. The specified color is configured via rdpq_set_fill_color, and can be changed later.
Notice that in FILL mode most of the RDP features are disabled, so all other render modes settings (rdpq_mode_* functions) do not work.
[in] | color | The fill color to use |
void rdpq_set_mode_copy | ( | bool | transparency | ) |
Reset render mode to COPY type.
This function sets the render mode type to COPY, which is used to quickly blit bitmaps. In COPY mode, only texture rectangles (aka "sprites") can be drawn and no advanced render mode features are working (rdpq_mode_* functions).
The only available feature is transparency: pixels with alpha set to 0 can optionally be discarded during blit, so that the target buffer contents is not overwritten for those pixels. This is implemented using alpha compare.
The COPY mode is approximately 4 times faster at drawing than the standard mode, so make sure to enable it whenever it is possible.
[in] | transparency | If true, pixels with alpha set to 0 are not drawn |
void rdpq_set_mode_yuv | ( | bool | bilinear | ) |
Reset render mode to YUV mode.
This is a helper function to configure a render mode for YUV conversion. In addition of setting the render mode, this function also configures a combiner (given that YUV conversion happens also at the combiner level), and set standard YUV parameters (for BT.601 TV Range).
After setting the YUV mode, you can load YUV textures to TMEM (using a surface with FMT_YUV16), and then draw them on the screen as part of triangles or rectangles.
[in] | bilinear | If true, YUV textures will also be filtered with bilinear interpolation (note: this will require 2-cycle mode so it will be twice as slow). |
|
inline |
Activate antialiasing.
This function can be used to enable/disable antialias at the RDP level. There are two different kinds of antialias on N64:
This function activates both kinds of antialias, but to display correctly the second type, make sure that you did pass FILTERS_RESAMPLE_ANTIALIAS or FILTERS_RESAMPLE_ANTIALIAS_DEDITHER to display_init.
On the other hand, if you want to make sure that no antialias is performed, disable antialias with rdpq_mode_antialias(false)
(which is the default for rdpq_set_mode_standard), and that will make sure that the VI will not do anything to the image, even if display_init was called with FILTERS_RESAMPLE_ANTIALIAS or FILTERS_RESAMPLE_ANTIALIAS_DEDITHER.
mode | Antialiasing mode to use (or AA_NONE to disable) |
|
inline |
Configure the color combiner.
This function allows to configure the color combiner formula to be used. The color combiner is the internal RDP hardware unit that mixes inputs from textures, colors and other sources and produces a RGB/Alpha value, that is then sent to the blender unit. If the blender is disabled (eg: the polygon is solid), the value produced by the combiner is the one that will be written into the framebuffer.
For common use cases, rdpq offers ready-to-use macros that you can pass to rdpq_mode_combiner: RDPQ_COMBINER_FLAT, RDPQ_COMBINER_SHADE, RDPQ_COMBINER_TEX, RDPQ_COMBINER_TEX_FLAT, RDPQ_COMBINER_TEX_SHADE.
For example, to draw a texture rectangle modulated with a flat color:
Alternatively, you can use your own combiner formulas, created with either RDPQ_COMBINER1 (one pass) or RDPQ_COMBINER2 (two passes). See the respective documentation for all the details on how to create a custom formula.
When using a custom formula, you must take into account that some render states also rely on the combiner to work. Specifically:
comb | The combiner formula to configure |
|
inline |
Configure the formula to use for blending.
This function can be used to configure the formula used in the blender unit.
The standard blending formulas are:
Normally, you would use RDPQ_BLENDER_MULTIPLY when your source texture has an internal alpha channel that you want to use for blending. Otherwise, if you just want to add a fixed-level semi-transparency to an existing texture, use RDPQ_BLENDER_MULTIPLY_CONST.
RDPQ_BLENDER_ADDITIVE is mostly broken on RDP, as it doesn't handle correctly overflowing values. Basically, values up to 1.5 are correctly clamped to 1, but values above 1.5 are wrapped back to 0, which makes the mode almost useless.
It is possible to also create custom formulas. The blender unit allows for up to two passes. Use RDPQ_BLENDER to create a one-pass blending formula, or RDPQ_BLENDER2 to create a two-pass formula.
Please notice that two-pass formulas are not compatible with fogging (rdpq_mode_fog). Also notice that rdpq_mode assumes that any formula that you set here (either one-pass or two-passes) does blend with the background. If you want to use a formula that does not blend with the background, set it via rdpq_mode_fog, otherwise you might get incorrect results when using anti-alias (see rdpq_mode_antialias).
The following example shows how to draw a texture rectangle using a fixed blending value of 0.5 (ignoring the alpha channel of the texture):
blend | Blending formula created with RDPQ_BLENDER, or 0 to disable. |
|
inline |
Enable or disable fog.
This function enables fog on RDP. Fog on RDP is simulated in the following way:
To enable fog, pass RDPQ_FOG_STANDARD to this function, and call rdpq_set_fog_color to configure the fog color. This is the standard fogging formula.
If you want, you can instead build a custom fogging formula using RDPQ_BLENDER. Notice that rdpq_mode assumes that the formula that you set with rdpq_mode_fog does not blend with the background; for that, use rdpq_mode_blender.
To disable fog, call rdpq_mode_fog passing 0.
fog | Fog formula created with RDPQ_BLENDER, or 0 to disable. |
|
inline |
Change dithering mode.
This function allows to change the dithering algorithm performed by RDP on RGB and alpha channels. Note that by default, rdpq_set_mode_standard disables any dithering.
See rdpq_dither_t for an explanation of how RDP applies dithering and how the different dithering algorithms work.
dither | Dithering to perform |
|
inline |
Activate alpha compare feature.
This function activates the alpha compare feature. It allows to do per-pixel rejection (masking) depending on the value of the alpha component of the pixel. The value output from the combiner is compared with a configured threshold and if the value is lower, the pixel is not written to the framebuffer.
Moreover, RDP also support a random noise alpha compare mode, where the threshold value is calculated as a random number for each pixel. This can be used for special graphic effects.
threshold | Threshold value. All pixels whose alpha is less than this threshold will not be drawn. Use 0 to disable. Use a negative value for activating the noise-based alpha compare. |
|
inline |
Activate z-buffer usage.
Activate usage of Z-buffer. The Z-buffer surface must be configured via rdpq_set_z_image.
It is possible to separately activate the depth comparison (reading from the Z-buffer) and the Z update (writing to the Z-buffer).
compare | True if per-pixel depth test must be performed |
update | True if per-pixel depth write must be performed |
|
inline |
Set a fixed override of Z value.
This function activates a special mode in which RDP will use a fixed value of Z for the next drawn primitives. This works with both rectangles (rdpq_fill_rectangle and rdpq_texture_rectangle) and triangles (rdpq_triangle).
If a triangle is drawn with per-vertex Z while the Z-override is active, the per-vertex Z will be ignored.
enable | Enable/disable the Z-override mode |
z | Z value to use (range 0..1) |
deltaz | DeltaZ value to use. |
|
inline |
Activate palette lookup during drawing.
This function allows to enable / disable palette lookup during drawing. Uploading a palette to TMEM can be done via rdpq_tex_upload_tlut, or lower-level functions such as rdpq_load_tlut_raw.
tlut | Palette type, or 0 to disable. |
|
inline |
Activate texture filtering.
This function allows to configure the kind of texture filtering that will be used while sampling textures.
Available in render modes: standard, copy.
filt | Texture filtering type |
|
inline |
Activate mip-mapping.
This function can be used to turn on mip-mapping.
TMEM must have been loaded with multiple level of details (LOds) of the texture (a task for which rdpq is currently missing a helper, so it has to be done manually). Also, multiple consecutive tile descriptors (one for each LOD) must have been configured.
If you call rdpq_triangle when mipmap is active via rdpq_mode_mipmap, pass 0 to the number of mipmaps in rdpq_trifmt_t, as the number of levels set here will win over it.
mode | Mipmapping mode (use MIPMAP_NONE to disable) |
num_levels | Number of mipmap levels to use. Pass 0 when setting MIPMAP_NONE. |
|
inline |
Activate perspective correction for textures.
This function enables or disables the perspective correction for texturing. Perspective correction does not slow down rendering, and thus it is basically free.
To be able to use perspective correction, make sure to pass the Z and W values in the triangle vertices.
perspective | True to activate perspective correction, false to disable it. |
void rdpq_mode_begin | ( | void | ) |
Start a batch of RDP mode changes.
This function can be used as an optimization when changing render mode and/or multiple render states. It allows to batch the changes, so that RDP hardware registers are updated only once.
To use it, put a call to rdpq_mode_begin and rdpq_mode_end around the mode functions that you would like to batch. For instance:
The only effect of using rdpq_mode_begin is more efficient RSP and RDP usage, there is no semantic change in the way RDP is programmed when rdpq_mode_end is called.
rdpq_set_mode_*
and rdpq_mode_*
). Any other function is not batched and will be issued immediately. void rdpq_mode_end | ( | void | ) |
Finish a batch of RDP mode changes.
This function completes a batch of changes started with rdpq_mode_begin.