Debo aclarar que sí, estoy completamente loco, así que ahórrate los comentarios tipo "Hacer una game engine tan decente como la que planteas es imposible en solitario", porque solo me darás motivos de reírme de tu cordura.
Dicho esto, estos meses que he estado más inactivo en el grupo de Facebook de Unity3D en Español han sido porque he estado estudiando arduamente para encajar todas las piezas de estos puzzles llamados motores de videojuegos, usando OpenGL y el poderío de C++. Y no solo estudiando sobre como encajar estas piezas con tan solo descripciones detalladas de lo que se busca, si no desarrollando estructuras de código. Pero claro... Game Engines hay muchas y seguramente mejor que mi estructura. Entonces, ¿por qué hago esto? Por ti, lector empedernido por los sistemas 3D, la diferencia es que, aunque sí, quizá haya muchas engines Open Source, no lo explican del tu a tu sobre su mismo desarrollo estilo blog(al menos no que yo conozca, y mira que me he masticado repositorios del Github para poder encajar las piezas). Con esto dicho, queda claro que lo que busco no es competir contra las Engines calidad AAA, ni siquiera pretendo realizar un producto que de una u otra manera sea distribuido para uso comercial. Solo quiero demostrar a los mas curiosos como se hace una buena base de una game engine desde usar tan solo lo mas necesario(las librerías de OpenGL) y qu emejor manera que realizarla uno mismo y encima escribiendo un blog en el cual a parte de enseñar nuevas funciones que engordarán al framebuffer más y más, se muestra como la fina cordura del sujeto de pruebas va decayendo hasta convertirse en un GLdisable. Empecemos:
Primero y antes que nada un poquito de música motivadora para el que se le haga mas ameno con ella.
______________________________________________________________________
______________________________________________________________________
Bien, después de esto, lo siguiente que necesito que hagas son varias cosas:
1.- Si tienes conocimientos previos de haber usado alguna otra Engine, desapréndelos.
2.- Tener conocimientos de nivel medio de C++.
3.- Saber realizar operaciones matemáticas de nivel básico y medio.
3.- Saber por encima la estructura de la GPU y tu computadora en general.
4.- Saber que OpenGL es solo una interfaz para no tener que escribir una versión de los drivers para cada vendedor de GPU's.
5.- Saber que son los drivers.
6.- Tener en tu poder la última versión de los archivos glcorearb.h, glext.h, wglext.h y glxext.h e incluirlos en un header dentro de tu proyecto al cual yo llamaré por ejemplo gllib.h.
7.- Disponer de la última versión de drivers de tu GPU y tener en tu poder la versión 4.5 del OpenGL(toda tarjeta gráfica fabricada desde finales de 2014 debería tener dicha tecnología).
8.- Tener descargada la última Update de Visual Stuido Community 2015 y empezar un empty project en c++ en el cual incluirás la librería gllib.h.
Si no dispones de estos atributos, no sigas con este tutorial.
NOTA: Con usuario me refiero al desarrollador de videojuegos, no al jugador.
Ahora realicemos un esquema para que nos quede claro la estructura que buscamos y que toda Engine estilo Unity, Unreal, etc... debería disponer:
1~ Gráficos: En la cual se incluirá las bases de cualquier 3D Engine(framebuffers, updatear los vertex cada frame, etc..........), el sistema de renderizado(ya sea de meshes, texturas, materiales, texturas en materiales o texturas en material en meshes) a tiempo real, la ventana donde será visualizado nuestro juego, las funciones matemáticas necesarias(vector, matrix, quaternion, etc...) para la visualización 3D y la computación de shaders, teselación, luces, cámara, etc...
2~ Eventos: Un sistema de eventos simple el cual recogerá automaticamente los cambios que hayan ocurrido a un mesh de un frame a otro al vertexbuffer el cual dispondrá de tan solo dos parámetros(una booleana llamada changeenable el cual como su nombre indica nos dirá si la posición del mesh ha cambiado en algo y un int llamado framenumber el cual obtendrá el frame en el que ha ocurrido ese cambio para que el buffer no se haga un batiburrillo por el orden de los eventos). Realmente no necesitamos hacer un sistema de eventos a nada mas que el mesh, ya que todos los cambios que hayan sido producidos en la parte de físicas o animaciones son afectados finalmente al mesh.
3~ Física: Funciones físicas usando matemáticas y mecanica clásica generalmente de nivel medio(las cuales serán explicadas), sistema de Rays(los cuales serán simplemente una línea definida por un punto de origen la cual puede ser la posición de un objeto o un Vector3.WorldPosition y por un punto final el cual puede ser igualmente un Vector3.WorldPosition o la posición de un objeto(si es un ray definido entre un objeto y otro, podrá ser usado por el sistema de colisiones para obtener la información de los objetos entre los dos puntos)) al cual añadiremos un sistema de colisiones con dos contact points los cuales serán definidos por los dos puntos del Ray, y un sistema de renderización de los meshes a los cuales hayan afectado algún factor de estas funciones físicas(la comunicación entre este render y el de los meshes es vital, para ello usaremos archivos temporales codificados para intercambiar los datos(la posición del mesh el cual haya sido afectado por alguna entidad de las funciones físicas para el próximo frame calculada por funciones matemáticas, etc...)), sistema de colisiones en el cual obtendremos la posición de dos meshes(especificados por el Editor), y si coinciden en algún punto(contact point(será modificable también por el Editor)) se aplicarán las funciones físicas que sigan la segunda ley de Newton.
4~ Animación: Sistema de animaciones basado en bones(toda animación será modificada solo por bones, no solo los bipedales) el cual grabará la secuencia frame-by-frame dada por el usuario con el Editor, y escribirá estos datos en archivos temporales los cuales modificaran la posición(Vector3.WorldPosition) de los bones(los cuales no serán mas que meshes creados con el Editor por el usuario, dentro del mesh principal(el modelo en sí), los cuales moverán a este mesh principal usando el sistema de colisiones, más específicamente, usando los contact points).
5~ Partículas(las cuales no son mas que pequeños meshes que haya donde vayan renderizan el shader que se les haya asignado, ya sea humo, nieve, etc...): Crear funciones físicas las cuales simulen el comportamiento de las mismas usando la rama "Mecánica clásica", y renderizarlas como parte del sistema de renderizado de físicas. Crear un mesh el cual será animado con el sistema de animación y adaptado a los vertex de la capa externa de los pequeños meshes(hacer un "caparazón" al sistema de partículas) al cual le aplicaremos el sistema de colisiones para detectar cuando colisiona con otro mesh. La comunicación con el render de meshes y con el sistema de animación es necesaria.
6~ Música: Realizar un sistema de renderizado el cual este basado en leer la metadata del archivo para reproducirlo con un reproductor (será un open source obviamente...) y obtener tan solo un parámetro(al menos por ahora), el del volúmen, y con el Editor el usuario especificará el punto de origen del audio(puede ser un Vector3.WorldPosition si se trata de un audio zonal, o puede ser un audio background el cual el engine solo mandará al programa de terceros que usemos que si el framebuffer es igual a 1(o sea, nada mas comienza el juego), sea reproducido dicho audio) y el rango de este audio (si es zonal). Ahora bien, el volúmen lo queríamos para si el jugador se aleja del punto de origen del audio zonal, pero sigue dentro del rango, bajemos gradualmente el volúmen conforme se aleja del origen, o lo subamos si se acerca.
7~ Input: Recogerá los datos del teclado y ratón para que el usuario defina los movimientos de los objetos si es que son modificados por los mismos.
8~ Editor: Puede ser un windows forms o un forms creado por nosotros, el cual tendrá varias secciones(menos la del juego la cual corre a cargo de GL) para dar acceso al usuario de modificar los parámetros de su juego a su gusto. Obviamente este Editor tiene acceso a los renders de todas las partes de nuestra engine(mesh, animaciones, musica, fisica).
9~ Render: Es el render final, el que generará el juego del usuario. al cual si puedo hacer la engine multiplataforma(esto depende 50% de mí y el otro 50% del día que tengan los desarrolladores de las otras plataformas para prestarme sus arquitecturas), le diremos que build queremos realizar. También será el código main de nuestra engine. No tiene mas misterio mas que pasarle el buffer que hayamos ido generando con los datos del framebuffer, vertexbuffer, etc... NO PUEDE SER MODIFICABLE POR EL USUARIO.
~ Opcionales(pero que son necesarias si se quiere una Engine AAA):
Network: Simplemente eso... unos cuantos headers con los cuales dejamos al usuario fácilmente modificable su multiplayer mode(obviamente enfocándonos en que el usuario va a realizar un videojuego).
UI: Puesto que nuestra engine no tendría una interfaz, el usuario tendría que definir todas las texturas y funciones de cada elemento. El usuario recibe de buen grado una buena UI ya implementada pero modificable.
Serialización permanente de los objetos: Con esto me refiero a dar la opción al usuario de guardar las distintas variables que le añadieron a un objeto, sea del tipo que sea, en un archivo el cual sea guardado y leído por el mismo juego desde el framebuffer = 1, y que este archivo sea modificable aún estando dentro del juego.
Multiplataforma.
Soporte para DirectX.
Espero que les haya gustado esta Introducción y a la vez estructuración de nuestra Engine. Como puedes ver, debes amar y estar obsesionado con este fascinante mundo de simulación 3D para que este tutorial no te aburra como un muerto.
Dentro de poco la parte 2 en la que ya empezaremos a programar la parte gráfica(daré por hecho que ya tendrás preparado el entorno(incluido en el proyecto el header gllib.h en el cual inccluyes esas 4 librerías)).
No hay comentarios:
Publicar un comentario