310. Máscara de opacidad de fondo

Construir una máscara de opacidad de fondo a partir de datos de nametable y tabla de patrones.

Lección 310 de 356 · tests/chapter_09_sprite_rendering/test_310_background_opaque_mask.py

Archivo a actualizar

emulator/rendering/nametable_renderer.py

Por qué existe este paso

Los sprites tienen un bit de prioridad que puede colocarlos detrás de los píxeles de fondo no transparentes. Para implementar eso correctamente, el compositor necesita saber si cada píxel de fondo es opaco.

Los datos RGB del framebuffer no son suficientes porque, una vez que un píxel de fondo se convierte a RGB, perdemos el índice de color CHR original.

Este paso añade una máscara pura

BackgroundOpaqueMask = list[bool]

Donde

False -> background CHR color index was 0
True  -> background CHR color index was 1, 2, or 3

Ejemplo de implementación sugerido

BackgroundOpaqueMask = list[bool]


def build_background_opaque_mask(
    pattern_table: bytes,
    nametable: bytes,
) -> BackgroundOpaqueMask:
    if len(nametable) != NAMETABLE_SIZE:
        raise ValueError("Nametable must be 960 bytes")

    decoded_tiles = decode_pattern_table(pattern_table)

    opaque_mask: BackgroundOpaqueMask = [False] * (
        BACKGROUND_WIDTH * BACKGROUND_HEIGHT
    )

    for tile_y in range(NAMETABLE_ROWS):
        for tile_x in range(NAMETABLE_TILES_PER_ROW):
            tile_index = nametable[tile_y * NAMETABLE_TILES_PER_ROW + tile_x]
            tile = decoded_tiles[tile_index]

            for pixel_y in range(CHR_TILE_HEIGHT):
                for pixel_x in range(CHR_TILE_WIDTH):
                    color_index = tile[pixel_y][pixel_x]

                    screen_x = tile_x * CHR_TILE_WIDTH + pixel_x
                    screen_y = tile_y * CHR_TILE_HEIGHT + pixel_y

                    mask_index = screen_y * BACKGROUND_WIDTH + screen_x
                    opaque_mask[mask_index] = color_index != 0

    return opaque_mask

¿Por qué no se usa la tabla de atributos ni la RAM de paleta? La opacidad depende únicamente del índice de color CHR. La tabla de atributos y la RAM de paleta deciden qué colores se muestran, pero no cambian si el índice de color CHR de un píxel de fondo es cero o distinto de cero.

Fuera del alcance

  • aplicación de prioridad de sprites
  • modificación del compositor de framebuffer
  • renderizado de sprites
  • sprite 0 hit
  • sprite overflow
  • pygame

Ejecutar esta lección

uv run pytest tests/chapter_09_sprite_rendering/test_310_background_opaque_mask.py -v