PPU sprite priority: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
mNo edit summary
(see also PPU rendering)
Line 13: Line 13:
# The background gets drawn to a separate buffer.
# The background gets drawn to a separate buffer.
# For each pixel in the background buffer, the corresponding sprite pixel replaces it only if the sprite pixel is opaque and front priority.
# For each pixel in the background buffer, the corresponding sprite pixel replaces it only if the sprite pixel is opaque and front priority.
(Low-level hardware detail: The buffers don't actually exist as full-scanline buffers inside the PPU but instead as a set of counters and shift registers. The above logic is implemented a pixel at a time.)
The buffers don't actually exist as full-scanline buffers inside the PPU but instead as a set of counters and shift registers. The above logic is implemented a pixel at a time, as [[PPU rendering]] explains.

Revision as of 17:36, 14 June 2011

In the NES PPU, each sprite has two values that affect priority, or what appears behind what: the index of the sprite within OAM (0 to 63), and the priority bit (attribute 2 bit 5, set to 0 for front or 1 for back). In some cases, putting a back-priority sprite in front of a front-priority sprite can let the background show through and cover up the front-priority sprite. Super Mario Bros. 3 uses this for power-ups sprouting from blocks, putting a blank block "behind" the block at a low index and then putting the power-up "behind" that at a high index. (You can see the corners of this blank block when Mario hits a note block in World 1-2, as the note block becomes more squared off.)

The Nintendo DS PPU handles priority the "obvious" way,[1] and some NES emulator developers initially think the NES PPU handles it the same way:

  1. Front priority sprites in front
  2. The background plane in the middle
  3. Back priority sprites in back

What really happens in the NES PPU is conceptually more like this:

  1. During sprite evaluation for each scanline (cycles 256 to 319), the eight frontmost sprites on this line get drawn front (lower index) to back (higher index) into a buffer, taking only the first opaque pixel that matches each X coordinate. Priority does not affect ordering in this buffer but is saved with each pixel.
  2. The background gets drawn to a separate buffer.
  3. For each pixel in the background buffer, the corresponding sprite pixel replaces it only if the sprite pixel is opaque and front priority.

The buffers don't actually exist as full-scanline buffers inside the PPU but instead as a set of counters and shift registers. The above logic is implemented a pixel at a time, as PPU rendering explains.