Preparacion del pipeline GPU. Codigo nuevo aislado en
core/rendering/gpu/; el runtime sigue usando SDL_Renderer hasta
Fase 7b. Tras 7a el juego sigue funcionando identico.
Shaders (shaders/):
- line.vert.glsl: vertex shader, transforma de pixeles logicos a NDC
via uniform buffer LineUniforms{viewport_w, viewport_h}.
- line.frag.glsl: pinta el color RGBA interpolado.
Build:
- CMakeLists.txt: step nuevo que compila *.glsl a build/shaders/*.spv
con glslc. ALL depende del target 'shaders' para incluirlo en cada
build. Falla en cmake config si glslc no esta instalado.
Wrappers C++ (source/core/rendering/gpu/):
- gpu_device.hpp/cpp: GpuDevice, claim del window, loadShader desde
.spv. Backends solicitados: Vulkan + Metal (sin DirectX).
- gpu_line_pipeline.hpp/cpp: GpuLinePipeline. Vertex layout
(vec2 pos + vec4 color), primitive TRIANGLELIST (lineas como
quads), alpha blending estandar, sin culling ni depth.
- gpu_frame_renderer.hpp/cpp: GpuFrameRenderer, API alto nivel:
beginFrame / pushLine / endFrame. Extrusion perpendicular en CPU
por linea (thickness libre por linea). Un draw call por frame
con vertex+index buffers transitorios.
Plan: 7b swap del SDL_Renderer al GpuFrameRenderer en SDLManager.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
6.8 KiB
Plan de migración Orni Attack → SDL3 GPU + física vectorial
Documento maestro de la rama rewrite/physics-gpu. Resumen del progreso y
qué queda. Si pierdes el contexto de la sesión, léeme primero.
Visión
Modernizar la base técnica del juego antes de tunear jugabilidad:
- Limpiar legacy (polares, mezcla catalán/inglés, header guards).
- Adoptar formato 16:9 (1280×720).
- Importar subsistemas robustos de AEEA (audio, input deferido).
- Implementar física vectorial 2D con rigid bodies + colisiones elásticas.
- Migrar renderizado a SDL3 GPU sin fallback (memoria: project-no-sdl-fallback).
- Postprocesado y color.
El tuning de feeling se hace al final, post-GPU.
Estado actual
Rama de trabajo: rewrite/physics-gpu (pusheada a Gitea).
Tag de seguridad: beta-3.0 (snapshot de main antes de empezar).
| Fase | Estado | Commits |
|---|---|---|
| 0 — Limpieza de código muerto (primitives, polígonos, Bresenham, polares) | ✅ | 6cf990b |
1a — Punt → Vec2 con operadores modernos |
✅ | cd38101 |
| 1b — Renames de entidades + métodos virtuales a camelBack | ✅ | ae5cc1c |
| 1c — Renames de escenas | ✅ | 5871d29 |
| 1d — Renames effects/stage_system/locales | ✅ | 7ee359b |
| 1e — Pragma once + locales restantes + comentarios castellano | ✅ | bf83f16 |
(fix) — clave YAML quadrat → cuadrado post-sweep |
✅ | 56533ca |
| 2 — Cambio a 1280×720 (16:9) | ✅ | a4f6a55 |
| 3 — Import del subsistema de Audio desde AEEA | ✅ | ed98ef6 |
| 4 — Input parcial AEEA | ⏭️ saltado (decisión usuario) | — |
5 — Infraestructura física (RigidBody, PhysicsWorld) |
✅ | 0fd9360 |
6a+b — body_ en Entity + world_ en GameScene |
✅ | 0574077 |
| 6c — Migrar Ship | ✅ | 2fe22ff |
| 6d — Migrar Enemy | ✅ | 27242f5 |
| 6e — Migrar Bullet | ✅ | 9993b2d |
| 7a — Infra GPU (shaders + wrappers, runtime dormido) | ✅ | (este commit) |
| 7b — Swap SDL_Renderer → SDL_GPUDevice (clear/present por GPU) | 🔲 | — |
| 7c — Pipeline de líneas (quads con thickness configurable) | 🔲 | — |
| 7d — Refactor de firmas (SDL_Renderer* → FrameContext*) | 🔲 | — |
| 7e — Cleanup + smoke test final | 🔲 | — |
| 8 — Postprocesado, color, paleta por tipo | 🔲 | — |
| 9 — Refactor de GameScene (2.877 LOC → módulos) | 🔲 | — |
| 10 — Tuning final de masa/restitución/damping | 🔲 | — |
Lo que queda inmediato (Fase 7b)
Swap del runtime de SDL_Renderer a SDL_GPUDevice.
Fase 7a completada: infraestructura GPU dormida (no llamada en runtime aún).
shaders/line.{vert,frag}.glsl→ compilados en build abuild/shaders/*.spv(CMake step conglslc). Vertex layout: vec2 position + vec4 color. Transformación a NDC vía uniform bufferLineUniforms{viewport_w, viewport_h}.core/rendering/gpu/:GpuDevice: claim del window, loadShader desde .spv.GpuLinePipeline: pipeline TRIANGLELIST con vertex layout + alpha blending.GpuFrameRenderer: APIbeginFrame / pushLine / endFrame. Extrusión perpendicular en CPU por línea (thickness configurable libre). Un draw call por frame con un vertex/index buffer transitorio.
Backend: Vulkan (Linux/Windows) y Metal (macOS). Sin DirectX.
Fase 7b siguiente:
- En
SDLManager::iniciar, sustituirSDL_CreateRendererporRendering::GPU::GpuFrameRenderer::init(window, 1280, 720). SDLManager::neteja(r,g,b)→gpu_renderer_.beginFrame(r/255, g/255, b/255).SDLManager::presenta()→gpu_renderer_.endFrame().- Borrar
renderer_(SDL_Renderer*) del SDLManager. - Validar arranque con xvfb: pantalla negra (sin líneas todavía), sin crash.
Después de 7b el juego se verá NEGRO porque ningún sistema sabe pintar líneas todavía. Eso se arregla en 7c (line_renderer apunta al pipeline GPU) y 7d (refactor de firmas SDL_Renderer* → FrameContext*).
Fase 10 (tuning) queda pendiente para después de SDL3 GPU + postpro.
Memoria del proyecto
Las preferencias y decisiones persistentes están en:
~/.claude/projects/-home-sergio-gitea-orni-attack/memory/MEMORY.md y los
archivos enlazados desde ahí. Léelos al empezar sesión nueva.
Resumen:
- No fallback a SDL_Renderer en Fase 7 — solo GPU o falla.
- Naming:
.clang-tidyexigeCamelCasetipos,camelBackmétodos,lower_case_miembros privados,UPPER_CASEconstantes. - Costuras del título tras 16:9 son tuning artístico, no bug, post-Fase 10.
- Push automático tras cada commit en
rewrite/physics-gpu. - Smoke test xvfb (
timeout 5 xvfb-run -a ./build/orni 2>&1 | head -40) tras builds importantes para validar arranque.
Convenciones técnicas
- Lenguaje código: inglés. Lenguaje comentarios: castellano. Strings de UI: valenciano (preservados).
- Coordenadas: cartesianas (
Vec2). Polares prohibidas (legacy). - Resolución lógica: 1280×720. Constantes en
core/defaults.hpp. - Audio: import de AEEA. API:
Audio::get()->playSound/playMusiccon crossfade y efectos. - Física:
Physics::RigidBodyencore/physics/rigid_body.hpp,Physics::PhysicsWorldencore/physics/physics_world.hpp/.cpp. Entity tienebody_como member. Flujo tri-fase por frame enGameScene::update:physics_world_.update(dt)— integrar y resolverentity.postUpdate(dt)— sincronizar mirror (center_, angle_)- Lógica del juego (input, AI, etc.) — aplica fuerzas/cambia velocity
Cómo reanudar tras compactación
- Lee este archivo.
- Lee
MEMORY.md(memorias persistentes). git log --oneline -20para ver últimos commits.git statuspara ver si hay trabajo en curso sin commitear.- Si la fase actual estaba a medias: continúa donde se quedó (este archivo indica en qué fase estamos).
- Tras cada commit, push automático:
git push origin rewrite/physics-gpu.
Configuración física actual (Fase 6e)
| Entidad | mass | radius (world) | restitution | linear_damping | angular_damping |
|---|---|---|---|---|---|
| Ship | 10.0 | 12 | 0.6 | 1.5 | 0.0 |
| Enemy Pentagon | 5.0 | 20 | 1.0 | 0.0 | 0.0 |
| Enemy Quadrat | 8.0 | 20 | 1.0 | 0.0 | 0.0 |
| Enemy Molinillo | 4.0 | 20 | 1.0 | 0.0 | 0.0 |
| Bullet | 0.5 | 0 (cinemática) | 0 | 0 | 0 |
| Wall (PLAYAREA bounds) | ∞ (estático) | — | — | — | — |
Nota: Bullet usa radius=0 en el body físico para que no participe en las
colisiones del world (ni body-body ni bounds). El radio de gameplay
(Defaults::Entities::BULLET_RADIUS = 3) lo expone vía getCollisionRadius()
y lo consumen check_collision y la detección de salida del PLAYAREA en
Bullet::update.
Las paredes son implícitas: physics_world_.setBounds(PLAYAREA) en
GameScene::init. No son RigidBody separados, sino un AABB que rebota.