Color math

From SNESdev Wiki
Revision as of 21:47, 18 August 2022 by Rainwarrior (talk | contribs) (first pass of color math, picture examples are TODO)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigationJump to search

Color math allows the SNES to do some limited blending between layers or colurs. This can be useful for effects like transparent shadows, ghosts that fade away, or a translucent colored text box.

Registers

The following registers directly affect color math:

Name Address Bits Type Notes
TM $212C ...O 4321 W8 Main screen layer enable (PPU registers#).
TS $212D ...O 4321 W8 Sub screen layer enable (#).
CGWSEL $2130 BBMM ..AD W8 Color addition black clip region (B), color math disable region (M), fixed/subscreen (A), direct color (D).
CGADSUB $2131 MHBO 4321 W8 Color math add/subtract (M), half (H), backdrop (B), layer enable (O4321).
COLDATA $2132 BGRC CCCC W8 Fixed color channel select (BGR) and value (C).

In addition to the above, color math can be independently affected by windowing.

As with most PPU registers, color math settings can be changed on a per-scanline basis if needed, typically using HDMA.

Color math sources

There are two options for a color source to blend, selected by CGWSEL bit 1:

  • Fixed color
  • Sub screen

Fixed color

This option applies the blend against a single fixed color, specified by COLDATA.

This is especially useful for blending against a vertical gradient, using HDMA to change COLDATA on each line.

Fixed color is also compatible with high resolution mode.

Sub screen

The **sub screen** reuses the pixels calculated during rendering to composite a second version of the visible screen.

This allows us to select one set of layers for the main screen (TM), and a different set of layers for the sub screen (TS), and use color math to blend between the two.

Because high resolution mode repurposes the sub screen for every second column, it may not be practical to use the sub screen for color math at the same time. (Fixed color does not have this complication.)

Masking

When rendering, the main screen remembers which layer its visible pixel came from, and this can be used to selectively apply color math to only some layers.

CGADSUB lets you designate whether color math can be used wherever the main screen shows: sprites (OBJ), a background (BG1-4), or the backdrop (CGRAM entry 0). If any of these layers are not enabled, it will instead show only the main screen result without color math.

Additionally, sprites using palettes 0-3 will reject color math. This allows us to have both opaque and transparent sprites at the same time. Because this selection is made based on the main screen only, if we wished to blend with sprites using these palettes we could place them on the sub screen instead.

Blend operations

The top two bits of CGADSUB control whether the blend operation is an addition or subtraction, and also whether to half the result. This creates 4 available blend modes.

For each pixel, if the color math operation is not rejected by masking, it blends each RGB color channel: 1. Take the main screen color. 2. Add (or subtract) the fixed (or sub screen) color. 3. Divide by 2, optionally. 4. If the result for a color channel is < 0 or > 31, it will be clamped to 0 or 31.

Add

Additive blending simply adds the two colors together.

This can lighten colors, but not darken them.

Because the strength of the added color is determined by its palette, we can fade an additive blend toward invisible just by fading the relevant palette colors toward black. (Anything + 0 = the same thing.)

Subtract

This subtracts the sub screen (or fixed color) from the main screen.

This can darken colors, but not lighten them.

Typically the palette used for the sub screen layer being subtracted will be inverted (i.e. 31 - the color we want). Subtracing white from the main screen will produce black. Subtracting blue from the main screen produces a yellow filter.

As with additive blending, we can fade the subtractive blend toward invisible by fading its palette colors toward black. (Anything - 0 = the same thing.)

Add + Half

This is a 50% blend between the main screen and sub screen (or fixed color).

Unlike additive or subtractive blending alone, we can't adjust the percentage of fade here by adjusting the palettes. It is always only 50%.

Note that because sprites count as a single layer (OBJ), we cannot blend sprites against other sprites. Only different layers can be blended.

Subtract + Half

This mode is rarely used, because it is essentially the same as subtractive but then the result is reduced to half brightness.

Because subtractive can only darken the picture to begin with, there is not much reason to use this feature to darken it further.

Examples

TODO: picture examples and descriptions showing main + sub = result. Possibilities:

  • Fixed color horizon fade
  • Negative subscreen for all-sprites subtractive workaround and windowed darkness
  • Ghosts fading in and out with additive + animated palette
  • Characters standing half in water

(We should probably make original pictures, to avoid copyright question, but do mention games that do similar things by name.)

Links