Log In  

Bitplanes are powerful, but they can be difficult to understand. How do you use them in PICO-8?

The short version: bitplanes let you draw colors to the screen without completely overwriting the existing colors, making it possible to do effects like shadows, transparency, etc. But be warned: they come with a lot of unintuitive restrictions, like monopolizing half your screen palette or requiring it to be set up in a particular way.

Longer version: PICO-8 colors are 4-bit numbers (0-15). The screen is a 128x128 4-bit image, but you can imagine it as 4 separate 12x128 1-bit images overlaid on top of each other. By poking a particular location in memory, we can tell PICO-8 to draw to these "bit planes" separately. Normally, drawing overwrites any existing colors, but if we selectively disable some of the bitplanes, some bits of the old color will remain onscreen.

Technical version: see "Technical details" below.

This post lists some specific examples and tricks that you can do with bitplanes. I won't attempt to fully explain how bitplanes work, but I'll leave some resources at the end.

Examples

Shadows

  1. set up your screen palette:
    i. 0-7: shadow palette; 0 is the shadow color for 8, 1 is the shadow color for 9, etc
    ii. 8-15: any colors
  2. draw anything
  3. enable bitplane mode 0x08 (clear the 0/8 bitplane)
  4. draw anything -- any pixels "drawn" will instead overwrite colors 8-15 with their shadow colors
  5. disable bitplane mode

Cart #bitplane_shadows-2 | 2023-09-21 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
9

I used this method in my freecell clone.

Spotlight

  1. set up your screen palette:
    i. 0-7: all identical; e.g. all 0 (black)
    ii. 8-15: any colors
  2. draw your scene using colors 0-7. they will all appear black
  3. enable bitplane mode 0xf8 (only draw the 0/8 bit)
  4. draw a circfill in color 8 -- instead of drawing red, it will add 8 to each color it hits, revealing the image "underneath" the darkness
  5. disable bitplane mode

This cart uses a very similar technique to create an "xray" effect. (They set up their palette differently and use a different bitplane mode, swapping adjacent colors instead of shifting the palette by 8)

1-bit sprite packing

If you have 1-bit sprites, you can store them merged in the 4 bitplanes in the spritesheet, and extract them at runtime using bitplanes. It's essentially another way to do this sprite-layering technique. Here's a tool that does something similar. Neither of these actually use pico8's bitplane feature, but they could be implemented that way to save some tokens and a tiny bit of cpu.

Chromatic aberration

You can create some cool effects (like https://mastodon.social/@zep/109315783011955478) by drawing slightly different images on different bitplanes.

Trippy motion blur

Flashing lights warning, this one can be pretty rough on the eyes. It's a neat trippy effect where each bitplane gets updated every 4 frames, leaving a slightly out-of-date impression onscreen for those other 3 frames, which creates a motion blur of sorts. I find it hard to look at (especially the jelpi example in the replies!) but it looks fascinating and it's very neat how bitplanes make it easy to create this effect in any game. I wonder how this could look with palette specifically designed for it... (the palette from the following "Anti-aliasing" example works decently well!)

(thanks freds72 for finding the link to this! I couldn't remember where I'd seen it)

Anti-aliasing

You can add anti-aliasing by drawing the same thing at slight subpixel offsets, like in this example. (Note that this restricts your palette to 5 colors)

Technical details

Wikipedia has some general info, and the PICO-8 wiki (search "bitplane") has specifics about how they work in PICO-8:

> 0x5f5e / 24414
> Allows PICO-8 to mask out certain bits of the input source color of drawing operations, and to write to specific bitplanes in the screen (there's 4 of them since PICO-8 uses a 4BPP display). Bits 0..3 indicate which bitplanes should be set to the new color value, while bits 4..7 indicate which input color bits to keep.
> For example, poke(0x5f5e, 0b00110111) will cause drawing operations to write to bitplanes 0, 1, and 2 only, with 0 and 1 receiving the color value bits, 2 being cleared, and 3 being unaltered.
> This formula is applied for every pixel written:
> dst_color = (dst_color & ~write_mask) | (src_color & write_mask & read_mask)

If you're not sure what to try, setting the write_mask and read_mask to the same value is often useful.

Other resources

-Bitwise math tutorial
-A simple bitplane example -- three circles rotating in 3D
-My bitplane explorer -- it helps visualize how colors will interact

-The original discovery
-Bitplanes confirmed by zep
-Circular Clipping Masks -- discusses other non-bitplane ways to get shadow and spotlight effects

P#134693 2023-09-21 11:11 ( Edited 2023-09-24 09:27)

1

Not sure about motion blur, but I did take a shot at using bitplanes for antialiasing a little while back: https://www.lexaloffle.com/bbs/?pid=104555#p (the next post in the thread talks about cycling bitplanes each frame).

P#134712 2023-09-21 12:42

@luchak that's a great idea! I haven't seen this before -- very cool. I've added it to the post.

P#134756 2023-09-22 04:26
2

zep motion blur post: https://x.com/lexaloffle/status/1318792339351990272?s=46&t=BxtTLEN0OxzpXviHVA2gqg

(Pancelor: excellent writeup on bitplanes!)

P#134758 2023-09-22 09:54 ( Edited 2023-09-22 10:54)
1

Thanks for this really clear write up. I feel like I'm finally getting it. Will definitely bookmark this post.

P#134773 2023-09-22 17:20

[Please log in to post a comment]