11 puntos por GN⁺ 2025-11-24 | 1 comentarios | Compartir por WhatsApp
  • Resumen de la experiencia de aprender Vulkan durante 3 meses e implementar personalmente un pequeño motor de juegos que incluye dos juegos de demostración
  • A partir de la experiencia previa con OpenGL, fue superando paso a paso la complejidad de Vulkan e implementó funciones clave como carga de glTF, skinning y shadow mapping
  • El motor es EDBR (Elias Daler’s Bikeshed Engine), está compuesto por unas 19 mil líneas de código y utiliza técnicas gráficas modernas como bindless descriptors, PVP y BDA
  • El artículo comparte detalles prácticos de implementación como bibliotecas esenciales vk-bootstrap, VMA, volk, además de patrones de pipeline, automatización de compilación de shaders y gestión de sincronización
  • Con la transición a Vulkan obtuvo eliminación del estado global, control explícito, un mejor entorno de depuración y consistencia entre GPUs, y planea agregar en el futuro render graph, fuentes SDF y efectos volumétricos

Panorama general del aprendizaje de Vulkan y del desarrollo del motor

  • El autor comenzó de forma autodidacta en programación gráfica y hace año y medio ya había escrito un motor 3D con OpenGL
  • El motor basado en Vulkan está pensado para juegos pequeños basados en niveles, con foco más en el aprendizaje y la experimentación que en la eficiencia
  • Al principio avanzó creando un juego 3D simple y luego separando las partes reutilizables para convertirlas en motor
  • Pudo terminarlo en 3 meses porque lo limitó a un motor con un propósito específico, no a un motor de uso general

Ruta de aprendizaje de programación gráfica

  • Para principiantes se recomienda empezar con OpenGL y aprender a mostrar modelos con texturas, iluminación Blinn-Phong y shadow mapping
  • Como materiales recomendados se mencionan learnopengl.com, Anton’s OpenGL 4 Tutorials y las clases de Thorsten Thormählen
  • También se enfatiza la importancia de entender álgebra lineal (vectores, matrices, cuaterniones) junto con material práctico actualizado de OpenGL 4.6

Consejos para evitar el bike-shedding

  • Evitar el sobrediseño y la abstracción excesiva innecesarios, manteniendo el principio de “implementar solo lo que se necesita ahora”
  • Se recomienda el enfoque de “haz que funcione primero y mejóralo después”
  • Es más eficiente terminar primero un juego pequeño que intentar crear un motor de propósito general
  • No conviene imitar tal cual el código o las estructuras complejas de otras personas; mejor partir de una estructura simple

Por qué eligió Vulkan

  • En juegos AAA suele usarse DirectX, en macOS/iOS Metal, y en la web WebGPU/WebGL
  • El autor prefiere código abierto y tecnologías estándar, y eligió Vulkan para desarrollar pequeños juegos 3D de escritorio
  • OpenGL ya no evoluciona más y fue descartado en macOS
  • WebGPU es más simple, pero tiene limitaciones como falta de estabilidad, restricciones de funciones y ausencia de soporte para bindless y push constants

Proceso de aprendizaje de Vulkan

  • Al principio le pareció tan difícil como “escribir directamente un driver gráfico”,
    pero la aparición de dynamic rendering, vk-bootstrap y vkguide mejoró la accesibilidad
  • Principales recursos de aprendizaje:
    • vkguide.dev (desde lo básico, con enfoque práctico)
    • TU Wien Vulkan Lecture Series
    • 3D Graphics Rendering Cookbook, Mastering Graphics Programming with Vulkan
  • En el primer mes completó la carga de glTF, compute skinning, frustum culling y shadow mapping

Estructura del motor EDBR y procesamiento por frame

  • El motor tiene unas 19,000 líneas de código, el juego 3D 4,600 líneas y el juego de plataformas 2D 1,200 líneas
  • Principales etapas de renderizado:
    • Compute skinningCascaded Shadow Mapping (4096×4096)sombreado de geometría basado en PBR
    • Depth ResolvePost FX (niebla basada en profundidad)renderizado de UI
  • Todos los sistemas gráficos fueron reescritos específicamente para Vulkan, sin mezclar el código anterior de OpenGL

Consejos prácticos para desarrollar con Vulkan

Bibliotecas recomendadas

  • vk-bootstrap: simplifica la inicialización y la configuración del swapchain
  • Vulkan Memory Allocator (VMA): automatiza la gestión de memoria
  • volk: simplifica la carga de funciones de extensiones

Abstracción GfxDevice

  • Administra VkDevice, VkQueue, VmaAllocator y otros dentro de un solo objeto
  • Se encarga del inicio/fin de frame, creación de imágenes y buffers, y gestión de bindless descriptors

Gestión de shaders

  • Usa GLSL y precompila a SPIR-V con glslc en tiempo de build
  • Aprovecha DEPFILE de CMake para recompilar automáticamente cuando cambian los shaders

Patrón de pipeline

  • Separa cada etapa de renderizado en pipelines a nivel de clase (init, cleanup, draw)
  • Usa VK_KHR_dynamic_rendering para omitir render passes y subpasses, manteniendo una estructura más simple

Programmable Vertex Pulling + Buffer Device Address

  • Procesa todas las mallas con una sola estructura Vertex
  • Accede directamente desde el shader mediante buffer_reference, sin necesidad de VAO

Bindless Descriptor

  • Usa arreglos globales de texturas (textures[], samplers[]) para muestreo basado en ID de textura
  • Guarda el ID de textura en la estructura de material y lo pasa por push constants

Carga dinámica de datos

  • Transfiere datos reemplazando buffers de GPU por frame o usando buffers de staging en CPU
  • La clase NBuffer administra la estructura de frames in flight

Limpieza de recursos y sincronización

  • Usa funciones de cleanup explícitas y gestión manual en lugar de depender de destructores automáticos
  • Realiza sincronización de memoria entre passes con vkCmdPipelineBarrier2
  • El Render Graph está planeado para una implementación futura

Casos concretos de implementación

Renderizado de sprites

  • Renderiza miles de sprites de una sola vez con texturas bindless e instancing
  • Sube la estructura SpriteDrawCommand a un buffer de GPU y llama a vkCmdDraw(6, N)
  • Renderiza 10 mil sprites en 315μs

Compute skinning

  • Realiza la deformación de vértices basada en matrices de huesos y pesos en un compute shader
  • Crea un buffer de salida separado por cada instancia y luego lo procesa igual en la etapa de renderizado

Separación entre juego y renderer

  • La lógica del juego usa entt ECS y el renderer solo procesa un vector de DrawCommand
  • Genera comandos de render con llamadas a drawMesh y drawSkinnedMesh

Carga de escenas y prefabs

  • Arma niveles en Blender exportando a glTF, y genera prefabs automáticamente según reglas en los nombres de nodos
  • Los prefabs se definen en JSON y hacen referencia a glTF externos

MSAA, UI, ImGui

  • Aplica MSAA x8 con base en forward rendering
  • Implementa un sistema de layout automático inspirado en la API de UI de Roblox
  • Escribió su propio backend de Vulkan para resolver el problema de sRGB en Dear ImGui

Otros componentes

  • Usa Jolt Physics para físicas, entt como ECS, OpenAL-soft para audio y Tracy como profiler

Ventajas del cambio a Vulkan

  • La eliminación del estado global permitió una estructura de código explícita y modular
  • Las capas de validación y la depuración con RenderDoc facilitan rastrear problemas
  • Mejora la consistencia entre GPU y sistemas operativos, con un comportamiento más predecible que OpenGL
  • Abre posibilidades de expansión con nuevos lenguajes de shading (slang, shady)
  • Menos abstracción y control más claro del pipeline mejoran la mantenibilidad

Planes a futuro

  • Planea agregar fuentes SDF, carga paralela de imágenes y generación de mipmaps, Bloom, niebla volumétrica, animation blending, render graph y AO
  • Aprender Vulkan es difícil, pero resultó de gran ayuda para entender mejor las APIs gráficas modernas y fortalecer la capacidad de diseñar motores

1 comentarios

 
GN⁺ 2025-11-24
Comentarios en Hacker News
  • Desde mi post de hace un año, mi opinión sobre Vulkan no ha cambiado mucho
    Puede resultar interesante para quien quiera control gráfico de bajo nivel, pero para mí fue una API realmente desagradable de usar
    Sigo queriendo hacer mi propio motor de juegos, pero todavía me da miedo incluso la configuración inicial de Vulkan
    Lo que quiero es algo así como una versión 3D de la forma en que SDL maneja los gráficos 2D
    Si quieres hacer 3D en SDL, al final tienes que bajar a OpenGL, y ese no es el nivel que estoy buscando
    Tal vez WebGPU sea una alternativa con la que sí podría disfrutar trabajar

    • SDL 3.0 introdujo una API de GPU hace como un año. Es una capa de abstracción que envuelve varios backends como Vulkan, así que vale la pena revisarla
      Yo también hice un motor con eso, pero al final volví a un motor basado en Vulkan porque quería más control y rendimiento
      Aun así, aprendí patrones de sincronización del código de SDL GPU y me ayudaron mucho en mi motor con Vulkan
    • wgpu de Rust es un punto medio que ofrece el nivel de abstracción de WebGPU
      Es más potente que OpenGL, pero no necesitas manejar directamente detalles como resource barriers o layout transitions
      Se encarga en runtime de parte del bookkeeping, y tiene limitaciones como soportar solo una cola
      Vulkan es duro, pero mejora bastante si usas extensiones compatibles con los principales vendors
      Aun así, sigue habiendo complejidad innecesaria, como exigir configuraciones detalladas que los drivers terminan ignorando
    • Como viejo programador de OpenGL, estoy totalmente de acuerdo
      Ahora mismo ya no existe una API intermedia entre los motores de juego de alto nivel y Vulkan/Metal de bajo nivel
      Para que un principiante aprenda gráficos 3D, hace falta una API simple al nivel de “dibujar un triángulo”, donde no haga falta conocer conceptos como shaders o buffers
      El control minucioso de Vulkan solo lo necesita una minoría muy pequeña de desarrolladores de motores; para la mayoría, el nivel de OpenGL es suficiente
    • Intentar hacer un “3D tipo SDL” rápidamente termina creciendo hasta convertirse en un motor full stack
      En 3D hay muchísimos más elementos combinables que en 2D, así que una API gráfica simple no da abasto
      OpenGL originalmente también apuntaba a eso, pero terminó volviéndose complejo
  • ‘bike shedding’ significa obsesionarse con problemas menores mientras se pierde de vista lo importante
    Lo que describe el texto original en realidad se parece más a feature creep o over-engineering

    • Si fuera el autor, también podría haber usado la expresión “hobby horsing
      Se refiere a enfocarse solo en el disfrute personal hasta bloquear el avance del proyecto
      bike shedding suele explicarse como “decidir primero el color del cobertizo para bicicletas antes de terminar la casa”
    • En cierto modo, están haciendo bike shedding sobre la propia palabra “bike shedding”
  • Se dijo que “no es buena idea empezar el desarrollo de un motor con un clon multijugador de Minecraft”,
    pero en realidad mucha gente hace juegos tipo Minecraft como su primer proyecto de motor
    En los motores vóxel, eso es una especie de “Hello, world”

  • En ese momento, el post de (2024) registró 625 puntos y 260 comentarios — enlace original

  • Vulkan fue la tecnología más difícil que he aprendido
    Es tan poco intuitiva y tan repetitiva que le quita toda la diversión a programar

    • No es que tú seas lento. Vulkan es una API de abstracción de chips de bajo nivel, así que es tan entretenida como una API de USB
      Si quieres empezar de forma más simple, recomiendo OpenGL, especialmente las versiones anteriores a la introducción de shaders
      Pero la industria cada vez desplaza más a OpenGL
    • Yo sentí exactamente lo mismo cuando empecé a aprender Vulkan
      Solo seguía tutoriales y copiaba código, sin entender realmente los conceptos
      Entonces me cambié a WebGPU (Google Dawn), y fue mucho más simple que Vulkan
      Gracias a las restricciones de WebGPU pude aprender los conceptos, y después volver a Vulkan fue mucho más fácil
      WebGPU no tiene push constants y tiene el problema de la explosión de pipelines, pero en Vulkan la sincronización y la gestión de memoria son más difíciles
      SDL_GPU también tiene una API de nivel parecido, así que sirve bien para empezar
    • Esa es también la razón por la que yo todavía no he pasado de OpenGL a Vulkan
      Vulkan es una API sobrediseñada
      En CUDA puedes asignar memoria GPU en una sola línea, pero en Vulkan eso exige una enorme cantidad de boilerplate
      Vulkan moderno ha mejorado mucho, pero todavía le falta bastante
    • Cuando ves ejemplos típicos de código Vulkan, te das cuenta de inmediato de que esto no está hecho para desarrolladores de juegos
      Ojalá SDL3 o wgpu se conviertan en la capa de abstracción que alivie esta complejidad
      Como Valve apoya SDL3, creo que ese lado tiene más posibilidades
    • Programar con Vulkan/DX12 es realmente doloroso
      Primero hay que hacerse la pregunta: “¿de verdad necesito procesar gráficos en multihilo?”
      Si no, no hay razón para usar Vulkan/DX12
      Hasta que aparezcan problemas de rendimiento, es mucho mejor usar OpenGL, DX11 o directamente un motor de juego
  • Me fascina la programación 3D/de videojuegos y suelo ver a varios youtubers creando juegos
    Pero comparado con las web apps o DevOps, es un mundo muchísimo más complejo
    Aparecen pixel shaders, compute shaders, geometría, álgebra lineal e incluso PDE
    Canal de YouTube de TokyoSpliff

  • Me gusta que hoy en día hacer un motor de juegos como hobby se vea como algo genial
    Yo también llevo 10 años desarrollando mi propio motor, y ha sido una experiencia muy gratificante

  • Si vas a hacer programación gráfica por primera vez, conviene empezar por OpenGL
    Leí los tutoriales de OpenGL de NeHe hace 23 años, y todavía me parecen uno de los materiales de aprendizaje mejor organizados que existen

  • Como referencia, yo no soy el autor del post original; solo mantuve el título