2026-03-24 13:40:16 +00:00

11 KiB
Raw Blame History

< Voltar | Sumário | Adiante >

🎨 Periférico GFX (Sistema Gráfico)

1. Visão Geral

O periférico GFX é responsável pela geração de imagem no PROMETEU.

Ele modela um hardware gráfico simples, inspirado em consoles clássicos (SNES, CPS-2, Neo-Geo), priorizando:

  • determinismo
  • baixo custo computacional
  • didática
  • portabilidade

O GFX não é uma GPU moderna.
Ele é um dispositivo explícito, baseado em:

  • framebuffer
  • tilemaps
  • banks de tiles
  • sprites por prioridade
  • composição por ordem de desenho

2. Resolução e Framebuffer

Resolução base

  • 320 × 180 pixels
  • proporção próxima de 16:9
  • escalável pelo host (nearest-neighbor)

Formato de pixel

  • RGB565
    • 5 bits Red
    • 6 bits Green
    • 5 bits Blue
  • sem canal alpha

Transparência é feita por color key.


3. Double Buffering

O GFX mantém dois buffers:

  • Back Buffer — onde o frame é construído
  • Front Buffer — onde o frame é exibido

Fluxo por frame:

  1. O sistema desenha no back buffer
  2. Chama present()
  3. Buffers são trocados
  4. O host exibe o front buffer

Isso garante:

  • ausência de tearing
  • sincronização clara por frame
  • comportamento determinístico

4. Estrutura Gráfica do PROMETEU

O mundo gráfico é composto por:

  • Até 16 Tile Banks
  • 4 Tile Layers (scrolláveis)
  • 1 HUD Layer (fixa, sempre por cima)
  • Sprites com prioridade entre layers

4.1 Tile Banks

  • Existem até 16 banks
  • Cada bank tem tamanho fixo de tile:
    • 8×8, 16×16 ou 32×32
  • Um bank é uma biblioteca de gráficos:
    • ambiente
    • personagens
    • UI
    • efeitos

4.2 Layers

  • Existem:
    • 4 Tile Layers
    • 1 HUD Layer
  • Cada layer aponta para um único bank
  • Sprites podem usar qualquer bank
  • HUD:
    • não scrolla
    • prioridade máxima
    • geralmente usa tiles 8×8

5. Modelo Interno de uma Tile Layer

Uma Tile Layer não é um bitmap de pixels.
Ela é composta por:

  • Um Tilemap lógico (índices de tiles)
  • Um Cache de Borda (janela de tiles visíveis)
  • Um Offset de Scroll

Estrutura:

  • bank_id
  • tile_size
  • tilemap (matriz grande)
  • scroll_x, scroll_y
  • cache_origin_x, cache_origin_y
  • cache_tiles[w][h]

6. Tilemap Lógico

O tilemap representa o mundo:

Cada célula contém:

  • tile_id
  • flip_x
  • flip_y
  • priority (opcional)
  • palette_id (opcional)

O tilemap pode ser muito maior que a tela.


7. Cache de Borda (Tile Cache)

O cache é uma janela de tiles ao redor da câmera.

Exemplo:

  • Tela: 320×180
  • Tiles 16×16 → 20×12 visíveis
  • Cache: 22×14 (margem de 1 tile)

Ele guarda os tiles já resolvidos a partir do tilemap.


8. Atualização do Cache

A cada frame:

  1. Calcular:
  • tile_x = scroll_x / tile_size
  • tile_y = scroll_y / tile_size
  • offset_x = scroll_x % tile_size
  • offset_y = scroll_y % tile_size
  1. Se tile_x mudou:
  • Avança cache_origin_x
  • Recarrega apenas a nova coluna
  1. Se tile_y mudou:
  • Avança cache_origin_y
  • Recarrega apenas a nova linha

Somente uma linha e/ou coluna é atualizada por frame.


9. Cache como Ring Buffer

O cache é circular:

  • Não move dados fisicamente
  • Apenas move índices lógicos

Acesso:

  • real_x = (cache_origin_x + logical_x) % cache_width
  • real_y = (cache_origin_y + logical_y) % cache_height

10. Projeção para o Back Buffer

Para cada frame:

  1. Para cada Tile Layer, em ordem:
  • Rasterizar tiles visíveis do cache
  • Aplicar scroll, flip e transparência
  • Escrever no back buffer
  1. Desenhar sprites:
  • Com prioridade entre layers
  • Ordem de desenho define profundidade
  1. Desenhar HUD layer por último

11. Ordem de Desenho e Prioridade

  • Não existe Z-buffer
  • Não existe sorting automático
  • Quem desenha depois fica na frente

Ordem base:

  1. Tile Layer 0
  2. Tile Layer 1
  3. Tile Layer 2
  4. Tile Layer 3
  5. Sprites (por prioridade entre layers)
  6. HUD Layer

12. Transparência (Color Key)

  • Um valor RGB565 é reservado como TRANSPARENT_KEY
  • Pixels com essa cor não são desenhados
if src == TRANSPARENT_KEY:
    skip
else:
    draw

13. Color Math (Blending Discreto)

Inspirado no SNES.

Modos oficiais:

  • BLEND_NONE
  • BLEND_HALF
  • BLEND_HALF_PLUS
  • BLEND_HALF_MINUS
  • BLEND_FULL

Sem alpha contínuo.
Sem blending arbitrário.

Tudo é:

  • inteiro
  • barato
  • determinístico

14. Onde o Blend é Aplicado

  • O blend ocorre durante o desenho
  • O resultado vai direto para o back buffer
  • Não existe composição posterior automática

15. O que o GFX NÃO suporta

Por design:

  • Alpha contínuo
  • RGBA framebuffer
  • Shader
  • Pipeline moderno de GPU
  • HDR
  • Gamma correction

16. Regra de Performance

  • Layers:
    • só atualizam borda ao cruzar tile
    • nunca redesenham mundo inteiro
  • Rasterização:
    • sempre por frame, só área visível
  • Sprites:
    • sempre redesenhados por frame

17. PostFX Especial — Fade (Scene e HUD)

O PROMETEU suporta fade gradual como um PostFX especial, com dois controles independentes:

  • Scene Fade: afeta toda a cena (Tile Layers 03 + Sprites)
  • HUD Fade: afeta apenas o HUD Layer (sempre composto por último)

O fade é implementado sem alpha contínuo por pixel e sem floats. Ele usa um nível inteiro discreto (0..31), que na prática produz um resultado visual “quase contínuo” em 320×180 pixel art.


17.1 Representação do Fade

Cada fade é representado por:

  • fade_level: u8 no intervalo [0..31]
    • 0 → totalmente substituído pela cor de fade
    • 31 → totalmente visível (sem fade)
  • fade_color: RGB565
    • cor para a qual a imagem será misturada

Registradores:

  • SCENE_FADE_LEVEL (0..31)
  • SCENE_FADE_COLOR (RGB565)
  • HUD_FADE_LEVEL (0..31)
  • HUD_FADE_COLOR (RGB565)

Casos comuns:

  • Fade-out: fade_color = BLACK
  • Flash/teleporte: fade_color = WHITE
  • Efeitos especiais: qualquer cor RGB565

17.2 Operação de Fade (Mistura com Cor Arbitrária)

Para cada pixel RGB565 src e cor de fade fc, o pixel final dst é calculado por canal.

  1. Extrair componentes:
  • src_r5, src_g6, src_b5
  • fc_r5, fc_g6, fc_b5
  1. Aplicar mistura inteira:
src_weight = fade_level // 0..31
fc_weight = 31 - fade_level

r5 = (src_r5 * src_weight + fc_r5 * fc_weight) / 31
g6 = (src_g6 * src_weight + fc_g6 * fc_weight) / 31
b5 = (src_b5 * src_weight + fc_b5 * fc_weight) / 31
  • src_r5, src_g6, src_b5
  • fc_r5, fc_g6, fc_b5
  1. Reempacotar:
dst = pack_rgb565(r5, g6, b5)

Observações:

  • Operação determinística
  • Somente inteiros
  • Pode ser otimizada via LUT

17.3 Ordem de Aplicação no Frame

A composição do frame segue esta ordem:

  1. Rasterizar Tile Layers 03 → Back Buffer
  2. Rasterizar Sprites conforme prioridade
  3. (Opcional) Pipeline extra (Emission/Light/Glow etc.)
  4. Aplicar Scene Fade usando:
  • SCENE_FADE_LEVEL
  • SCENE_FADE_COLOR
  1. Rasterizar HUD Layer
  2. Aplicar HUD Fade usando:
  • HUD_FADE_LEVEL
  • HUD_FADE_COLOR
  1. present()

Regras:

  • Scene Fade nunca afeta HUD
  • HUD Fade nunca afeta a cena

17.4 Casos de Uso

  • Troca de HUD:

    • diminuir HUD_FADE_LEVEL até 0
    • trocar HUD/tilemap
    • aumentar HUD_FADE_LEVEL até 31
  • Troca de área:

    • diminuir SCENE_FADE_LEVEL até 0
    • trocar cenário
    • aumentar SCENE_FADE_LEVEL até 31
  • Flash / dano / teleporte:

    • usar fade_color = WHITE ou outra cor temática

18. Sistema de Paletas

18.1. Visão Geral

O PROMETEU utiliza exclusivamente gráficos indexados por paleta.

Não existe modo RGB direto por pixel.
Todo pixel gráfico é um índice que aponta para uma cor real em uma paleta.

Objetivos:

  • reduzir uso de RAM e storage
  • permitir troca de cores sem shader
  • manter identidade retrô
  • facilitar efeitos como variação, dano, dia/noite

18.2. Formato de Pixel

Cada pixel de um tile ou sprite é:

  • 4 bits por pixel (4bpp)
  • valores: 0..15

Regra fixa:

  • Índice 0 = TRANSPARENTE
  • Índices 1..15 = cores válidas da paleta

18.3. Estrutura de Paletas

Cada Tile Bank contém:

  • Até 256 paletas
  • Cada paleta tem:
    • 16 cores
    • cada cor em RGB565 (u16)

Tamanho:

  • 1 paleta = 16 × 2 bytes = 32 bytes
  • 256 paletas = 8 KB por bank
  • 16 banks = 128 KB máximo de paletas

18.4. Associação de Paleta

Regra Fundamental

  • Cada tile usa uma única paleta
  • Cada sprite usa uma única paleta
  • A paleta deve ser informada explicitamente em todo draw

Não existe troca de paleta dentro do mesmo tile ou sprite.


18.5. Onde a Paleta é Definida

Tilemap

Cada célula do tilemap contém:

  • tile_id
  • palette_id (u8)
  • flip_x
  • flip_y

Sprite

Cada sprite draw contém:

  • bank_id
  • tile_id
  • palette_id (u8)
  • x, y
  • flip_x, flip_y
  • priority

18.6. Resolução de Cor

O pipeline funciona assim:

  1. Ler pixel indexado do tile (valor 0..15)
  2. Se índice == 0 → pixel transparente
  3. Caso contrário:
  • cor_real = paleta[palette_id][indice]
  1. Aplicar:
  • flip
  • blend discreto
  • escrita no back buffer

Ou seja:

pixel_index = tile_pixel(x,y)
if pixel_index == 0:
    skip
else:
    color = bank.palettes[palette_id][pixel_index]
    draw(color)

18.7. Organização dos Tile Banks

Os Tile Banks são “assets fortes”:

  • Tiles e paletas vivem juntos
  • Exportação/importação sempre leva:
    • tiles + paletas
  • O hardware não impõe organização semântica:
    • o agrupamento é decisão do criador
  • Tooling e scripts podem criar convenções:
    • ex.: paletas 0..15 = inimigos
    • 16..31 = cenário
    • etc.

18.8. Efeitos Possíveis com Paletas

Sem shader, é possível:

  • Palette swap:
    • inimigos com variação de cor
  • Estados:
    • dano, gelo, veneno, power-up
  • Dia / noite:
    • trocar paletas globalmente
  • Biomas:
    • mesma arte, clima diferente
  • UI themes

Tudo isso sem mudar os tiles.


18.9. Limitações Artísticas

  • Cada tile/sprite:

    • máximo de 16 cores
  • Gradientes suaves exigem:

    • dithering
    • blend discreto
    • glow/emission

Essa limitação é intencional e faz parte da identidade do PROMETEU.


18.10. Métricas para Certificação (CAP)

O sistema pode medir:

  • palettes_loaded_total
  • palettes_referenced_this_frame
  • tiles_drawn_by_palette_id
  • sprites_drawn_by_palette_id

Isso permite:

  • analisar custo artístico
  • ensinar impacto de variedade excessiva
  • sugerir boas práticas de coesão visual

19. Resumo

O GFX do PROMETEU é simples por escolha, não por limitação.

  • Framebuffer RGB565 com double buffer
  • Color key para transparência
  • Blending discreto estilo SNES
  • Até 16 tile banks
  • 4 Tile Layers + 1 HUD
  • Layer = tilemap + cache + scroll
  • Projeção rasterizada por frame
  • Profundidade definida por ordem de desenho

< Voltar | Sumário | Adiante >