Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. Programming

Construyamos un motor gráfico 3D: Espacios y sacrificios

by
Read Time:7 minsLanguages:
This post is part of a series called Let’s Build a 3D Graphics Software Engine.
Let's Build a 3D Graphics Engine: Linear Transformations
Let's Build a 3D Graphics Engine: Rasterizing Line Segments and Circles

Spanish (Español) translation by Esther (you can also view the original English article)

¡Bienvenido! Esta es la tercera parte de nuestra serie sobre motores gráficos 3D. Si has llegado hasta aquí en la serie, te alegrará saber que esta pieza será mucho más ligera en el aspecto matemático de los motores 3D, y en su lugar se centrará en cosas más prácticas, en particular, la adición de una cámara y un sistema de renderizado básico.

Consejo: Si aún no has leído las dos primeras partes, te recomiendo que lo hagas antes de continuar.

También puedes obtener ayuda adicional en Envato Studio, donde puedes elegir entre una amplia gama de servicios de diseño y modelado 3D de alta calidad de proveedores experimentados.

3D Design Modeling services3D Design Modeling services3D Design Modeling services
Servicios de diseño y modelado 3D en Envato Studio

Recapitulemos

En primer lugar, echemos un vistazo a las clases que hemos creado hasta ahora:

El uso de estas dos clases por separado ha demostrado ser un poco desordenado hasta ahora, y dibujar todos los puntos posibles puede agotar la memoria del sistema con bastante rapidez. Para resolver estos problemas, vamos a introducir una nueva clase en nuestro motor de juego: la cámara.

Nuestra cámara va a ser donde todo nuestro renderizado ocurre, exclusivamente; va a sacrificar todos nuestros objetos a la pantalla, y también va a manejar una lista de todos nuestros puntos.

Pero antes de llegar a todo eso, debemos hablar un poco de la eliminación selectiva.


Sacrificio en Londres

El sacrificio, por definición, es la selección de objetos de un grupo mayor de objetos. Para nuestro motor de juego, la pequeña selección que tomamos serán los puntos que queremos dibujar en la pantalla. El grupo más grande de objetos serán todos los puntos que existen.

Al hacer esto, se reduce drásticamente el consumo de memoria del motor, ya que solo se dibuja lo que el jugador puede ver realmente, en lugar de los puntos de todo un mundo. En nuestro motor, vamos a hacer esto estableciendo parámetros para un espacio de vista.

Nuestro espacio de visión se definirá a través de los tres ejes tradicionales: x, y y z. Su definición x consistirá en todo lo que se encuentre entre los límites izquierdo y derecho de la ventana, su definición y consistirá en todo lo que se encuentre entre los límites superior e inferior de la ventana, y su definición z estará entre 0 (donde se encuentra la cámara) y la distancia de visión de nuestro jugador (para nuestra demostración, utilizaremos un valor arbitrario de 100).

Antes de dibujar un punto, nuestra clase de cámara va a comprobar si ese punto se encuentra dentro de nuestro espacio de visión. Si lo está, entonces el punto se dibujará; de lo contrario, no lo hará.


¿Podemos poner algunas cámaras aquí?

Con esa comprensión básica de la selección, podemos deducir que nuestra clase tendrá este aspecto, hasta ahora:

También vamos a hacer que nuestra cámara se encargue de todo el renderizado para nuestro motor. Dependiendo del motor, encontrarás que los renderizadores suelen estar separados de los sistemas de cámara. Esto se hace típicamente para mantener los sistemas encapsulados de manera agradable, ya que, dependiendo del alcance de tu motor, los dos podrían ser bastante desordenados si se mantienen juntos. Para nuestros propósitos, sin embargo, será más simple tratarlos como uno solo.

En primer lugar, vamos a querer una función que pueda ser llamada externamente desde la clase que dibujará la escena. Esta función recorrerá cada uno de los puntos existentes, los comparará con los parámetros de selección de la cámara y los dibujará si es el caso.

ViewFrustumViewFrustumViewFrustum
Fuente: http://en.wikipedia.org/wiki/File:ViewFrustum.svg

Consejo: Si quieres separar tu sistema de cámara de tu renderizador, podrías simplemente crear una clase Renderer, hacer que el sistema de cámara extraiga los puntos, almacene los que van a ser dibujados en un array, y luego envíe ese array a la función draw() de tu renderizador.


Gestión de puntos

La última pieza de nuestra clase de cámara va a ser su sistema de gestión de puntos. Dependiendo del lenguaje de programación que estés usando, esto podría ser un simple array de todos los objetos que pueden ser dibujados (manejaremos más que puntos en partes posteriores). Alternativamente, puede que tengas que usar la clase padre de objetos por defecto del lenguaje. Si tienes súper mala suerte, tendrás que crear tu propia clase padre de objetos y hacer que cada clase dibujable (hasta ahora solo puntos) sea hijo de esa clase.

Después de añadir esto a la clase, un resumen básico de nuestra cámara se vería así:

Con estas adiciones, vamos a mejorar un poco el programa que hicimos la última vez.


Cosas más grandes y mejores

Vamos a crear un sencillo programa de dibujo de puntos, con el programa de ejemplo que creamos la última vez como punto de partida.

En esta iteración del programa, vamos a añadir el uso de nuestra nueva clase de cámara. Cuando la tecla D es presionada, el programa redibujará la pantalla sin sacrificio, mostrando el número de objetos que fueron renderizados en la esquina superior derecha de la pantalla. Al pulsar la tecla C, el programa redibujará la pantalla con el sacrificio, mostrando también el número de objetos renderizados.

Echemos un vistazo al código:

¡Ahora puedes ver, de primera mano, el poder del sacrificio! Tenga en cuenta que si usted está mirando a través del código de ejemplo, algunas cosas se hacen un poco diferente con el fin de hacer las demostraciones más amigable web. (Puedes ver mi demostración simple aquí).


Conclusión

Con una cámara y un sistema de renderizado en tu haber, técnicamente puedes decir que has creado un motor de juego en 3D. Puede que aún no sea demasiado impresionante, pero está en camino.

En nuestro próximo artículo, veremos cómo añadir algunas formas geométricas a nuestro motor (en concreto, segmentos de línea y círculos), y hablaremos de los algoritmos que se pueden utilizar para ajustar sus ecuaciones a los píxeles de una pantalla.

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.