434 lines
8.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

< [Voltar](chapter-3.md) | [Sumário](table-of-contens.md) | [Adiante](chapter-5.md) >
# 🎨 **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 Game 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 Game 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 Game Layer
Uma Game 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`
2. Se `tile_x` mudou:
- Avança `cache_origin_x`
- Recarrega apenas a nova coluna
3. 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 Game Layer, em ordem:
- Rasterizar tiles visíveis do cache
- Aplicar scroll, flip e transparência
- Escrever no back buffer
2. Desenhar sprites:
- Com prioridade entre layers
- Ordem de desenho define profundidade
3. 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. Game Layer 0
2. Game Layer 1
3. Game Layer 2
4. Game 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 (Game 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`
2) 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`
2) 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
3) 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 **Game 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`
5. Rasterizar **HUD Layer**
6. Aplicar **HUD Fade** usando:
- `HUD_FADE_LEVEL`
- `HUD_FADE_COLOR`
7. `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. 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 game layers + 1 HUD
- Layer = tilemap + cache + scroll
- Projeção rasterizada por frame
- Profundidade definida por ordem de desenho
< [Voltar](chapter-3.md) | [Sumário](table-of-contens.md) | [Adiante](chapter-5.md) >