Mostrando entradas con la etiqueta tech demo. Mostrar todas las entradas
Mostrando entradas con la etiqueta tech demo. Mostrar todas las entradas

jueves, 24 de diciembre de 2020

Mis proyectos abandonados ven la luz: JMusic y Flappy Adventure X

¡Feliz navidad followers! No me he olvidado de vosotros (bueno, un poquito sí) os dejo un post para acabar este increíble e inolvidable 2020 que estoy seguro de que vosotros también pensáis que ha sido el mejor año que hemos tenido nunca

Imagino que leísteis mi anterior articulo sobre mis proyectos abandonados JMusic y Flappy Adventure 3

Pues bien, ¿que ha pasao'?

JMusic:

Finalmente y gracias al tiempo libre de la cuarentena fue terminado antes de cumplir 1 año en desarrollo. No quedó muy distinta a la aplicación que visteis en el screenshot del primer articulo, y tal y como tenía planeado, se quedó para mi uso privado (de hecho la uso muy frecuentemente).

Flappy Adventure X:

Link al GitHub Descargar ISO PSX



No, no me he equivocado con el título. El proyecto de Flappy Adventure 3 tomó un cambio de rumbo para la que es la última aventura de Flappy (que ya era hora de terminar con la saga).

Todo empezó cuando me di cuenta, tras jugar de nuevo al primer Flappy Adventure web de 2015, de que la mecánica de plataformas 2D de Flappy tenía mucho potencial si se desarrollaba correctamente.

Flappy Adventure 2 es un gran juego, y lo seguirá siendo; pero un sucesor mas avanzado también en 3D conllevaría moverme a Unity, o hacer un mayor esfuerzo en Three.js.

Dicho esto, quise cumplir mi objetivo con FA3 de usar más objetos dinámicos pero en una versión 2D que me llevase menos tiempo desarrollar, y que me permitiese con una mayor calidad final. En esta ocasión ademas, quise volver a los orígenes de Flappy Adventure: las videoconsolas retro.

Pensé en la GameBoy Advance, con la cual ya había trabajado, en la Sega Genesis (descartada porque segúramente me tocase programar en ensamblador del 68000). Pero... ¿y por que no ir un paso más adelante y trabajar en un scroller 3D en una videoconsola de 5ª generación? (Sega Saturn, PSX, Nintendo 64). Descubrí (Y probé) un motor muy sencillo y facil de usar en C para la Saturn, que tenía fama de ser difícil de programar, pero me daba pereza en cualquier caso, y no hice na'... Hasta que me regalaron una PS1 chipeada... (El anterior post sobre ensamblador en PSX no fue casualidad)

La cosa había cambiado, iba a poder probar mi código en hardware real, y en una videoconsola que fue muy popular. Tras analizar los SDKs me quedé con el oficial: PSYQ. Pero la cosa solo acababa de empezar. Me iba a tocar aprender el hardware de la PS1: como trabajar con su GPU, su SPU, el lector de CD, las memory card, el GTE para los graficos 3D,...

Capitulo 1: Mis experimentos en PSX

Empecé con ejemplos chorras, como portar mi motor Voxel de GameBoy Advance a PlayStation, pero en esta ocasión con infinitos angulos de rotación. ¿¿Como?? (La PSX no va sobrada de potencia, y un motor software acaba con la poca que tiene)



Resulta que usando la GPU para dibujar la textura del mapa con rotación y escalado dentro de la VRAM, luego se puede enviar de nuevo a la CPU ¿Pero y que pasa con el mapa de profundidad? Un momento... No veis algo raro en la VRAM? Los pixeles de la textura que hemos mandado a la GPU, que supuestamente son colores de RGB555 de 15 bit, en realidad llevan 7 bits de una paleta de 128 colores, y los valores de 8 bit del mapa de profundidad.


¡La GPU aplica escala y rotación al mapa de profundidad! ¡Pero no es una textura, sino una matriz de alturas que luego enviamos de vuelta a la CPU!

Sí, he implementado un ejempo real de GPU computing en una videoconsola de hace 25 años. Aunque poco tiene que ver esto con CUDA.

Y bueno, tambien hice otros experimentos como detectar colisión en un poligono (muchas matemáticas). He aquí la m*** demo que hice, no me digais que no es hermosa:


Pero bueno, si quería hacer un entorno 3D de verdad necesitaría un motor grafico... Y ahi es donde realmente volví a crear un Flappy Engine desde 0, uno que me permitiera crear mis modelos en mi querido Google SketchUp. ¿Os he dicho ya que la PlayStation no tiene hardware para ordenar poligonos por profundidad y hay que apañarselas manualmente con el orden de los poligonos?


También creé mi propio editor de niveles, en el cual ademas del terreno y las monedas, se pueden añadir montones de objetos dinámicos con distintas propiedades. Definí mi propio formato de archivo para estos niveles de mi juego: *.LVL


Y bueno, el juego fue terminado bastante tarde, en marzo de 2021, porque lo cierto es que no me interesaba mucho ponerme a avanzarlo... Pero lo terminé, que es lo importante. A continuación para los curiosos os muestro 2 screenshots del juego en su versión beta de diciembre 2020 mostrando información de depuración.



viernes, 13 de abril de 2018

Motor 3D para GameBoy Advance: Consiguiendo lo imposible

Versión 2:
Descarga ROM y código fuente aquí.
Esta versión ya se mueve fluida a 60fps y permite girar la cámara.
Cambios:
Aparte de las optimizaciones de la versión 1, he añadido mas optimizaciones, y he implementado la rotación de la camara.
-Todo el código es copiado a la RAM y se ejecuta desde ahí. Se usa código ARM en vez de Thumb.
-Para ganar mas velocidad utilizo el modo5, que baja un poco la resolución y permite tener dos framebuffer en la memoria de video evitando tener que usar la RAM para luego copiarla a la VRAM en cada frame. También uso las técnicas de escalado y desplazamiento de la GBA para crear un par de frames intermedios mientras se renderiza el siguiente frame final.

Para la rotación utilizo aproximaciones rápidas de lo que serían los auténticos cálculos de la rotación. Ademas, cada vez que se gira, desplazo la posición de referencia para evitar aun mas cálculos al transformar las coordenadas durante el dibujado.

Para evitar aun mas perdidas de velocidad, he replicado la función crítica Render para cada angulo posible, de forma que las transformaciones de coordenadas están hard-coodeadas dentro de las funciónes Render-n, evitando llamadas a funciones y comprobaciones de angulo cada vez que se procesa un pixel.

Versión 1:
Descarga ROM y código fuente aquí.
La GameBoy Advance fue una de las primeras videoconsolas portatiles que intentó en algunos de sus juegos simular el efecto 3D. Juegos como Driv3r, Asterix y Obelix XXL, o Craxy Taxi. No obstante en la mayoría de dichos juegos el efecto 3D era muy, muy básico. Es por eso que yo, como friki ingeniero informático que soy me puse a investigar de que manera se podría conseguir un motor 3D decente. Tras un día investigando y picando código...¡Este fue el resultado!
Como habréis comprobado, la calidad del efecto 3D casi no se puede comparar con la de ningún otro juego de GBA. El motor es de tipo voxel space y el video fue acelerado algo así como x200 ya que la demo en su versión original (la del vídeo) tardaba 11 segundos en generar cada frame. Esto es debido a la gran cantidad de multiplicaciones y divisiones que debía hacer el motor en cada frame. Para los que no sepáis muy bien como funciona un motor voxel space os lo explico de manera muy sencilla:

Tenemos una imagen de color y otra imagen de profundidad. Dibujamos el entorno desde el frente hacia atras aplicando perspectiva (podeis ver el triangulito con el campo de visión en el GIF), para ello trazamos en la pantalla lineas verticales del color proporcional al pixel horizontal de la pantalla y el pixel horizontal de la linea de campo de visión actual. Esta linea vertical empezará desde la ultima altura dibujada hasta un nuevo valor calculado a partir de la altura en el mapa de profundidad y la distancia con el punto de vista (Si el valor obtenido es menor, no se dibuja la linea).

Optimizando el código:
Pues seguramente la baja potencia del procesador de la GameBoy fue lo que hizo que no apareciera ningún juego usando este tipo de motor, las multiplicaciones y divisiones son muy lentas en su procesador. Estas operaciones son vitales tanto para calcular las posiciones horizontales del campo de vision y pantalla como las de las alturas. ¿Que solucion tenemos? ¡Crear una estructura de datos con estos valores precalculados! En el archivo comprimido podeis encontrar generarmatriz.c que puede ser compilado para PC y usando los datos de matrizalturas.h (compartido con el proyecto devkit) generar una estructura de datos con las alturas precalculadas matrizalturas.raw y posiciones horizontales matrizx.raw las cuales se añaden al ROM. También, para realizar otras divisiones y multiplicaciones con multiplos de 2, utilizo a ser posible las operaciones de desplazamiento << y >> las cuales son mas rápidas.
Ademas, calcularemos el campo de visión menos frecuentemente en posiciones alejadas y limitamos la distancia de dibujado a 512 pixeles.
Estos cambios, junto con otras cuantas optimizaciones de código, permiten tras un gran esfuerzo y sudor conseguir unos gloriosos...
¡5fps!
Lo cual supone aproximadamente un speedup del 3000% y seguiría siendo insuficiente para cualquier juego en condiciones, pero al menos se mueve decentemente.
Se podría decir que la optimización es del 95% ya que los limites técnicos de la consola están ahí. Estas son algunas otras optimizaciones menores posibles que ni me he molestado en hacer:
  • Alinear matrizx.raw a 256 bytes cada linea para asi a la hora de leer sus datos podamos cambiar SCREEN_WIDTH*(step-minstep) por (step-minstep)<<8 aunque esto nos hará desperdiciar 16 bytes de memoria en la estructura de datos en la ROM por cada linea.
  • Dibujar las lineas verticales una por una, de forma que si una alcanza el valor maximo se haga un break y se pase a la siguiente sin seguir avanzando en profundidad. Solo habría aceleración en los casos que el mapa alcanzase la parte de arriba de la pantalla y la aceleración sería irregular. Habría que almacenar los valores de step en una estructura de datos.
  • Si se os ocurriese alguna mas, ¡comentad!
Curiosidad:
Uso de memoria en la demo:

ElementoEspacio (KB)PorcentajeNotas
Código9.790.18%El corasón de la demo. La parte que controla todo el funcionamiento.
Imagen Background39.10.72%La imagen del cielo tan bonica para la mitad superior de la pantalla (240x80) a 16 bit bgr555
Mapa colores204838.07%1024x1024 a 16 bit bgr555
Mapa profundidad102419.03%1024x1024 a 8 bit (valores 0-255)
Matriz x2384.42%Valores para cada pixel horizontal (1-240) en cada profundidad (8-512) de la posición horizontal del campo de visión (valores de 16 bit)
Matriz Alturas202137.57%Valores de altura en la pantalla de 8 bit para cada altura del mapa (0-255) en cada profundidad (8-512) para distintas alturas de camara posibles (16)
Total5379.89100%