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: Rasterización de segmentos de líneas y círculos

by
Read Time:8 minsLanguages:
This post is part of a series called Let’s Build a 3D Graphics Software Engine.
Let's Build a 3D Graphics Engine: Spaces and Culling
Let's Build a 3D Graphics Engine: Rasterizing Triangles and Quads

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

Hola, esta es la cuarta parte de nuestra serie sobre motores gráficos 3D. En esta ocasión, cubriremos la rasterización: el proceso de tomar una forma descrita por fórmulas matemáticas y convertirla en una imagen en tu pantalla.

Consejo: Todos los conceptos de este artículo se basan en las clases que hemos establecido en los tres primeros posts, así que asegúrate de consultarlos primero.


Recapitulemos

Aquí tienes un repaso a las clases que hemos hecho hasta ahora:

Puedes consultar el programa de ejemplo de la tercera parte de la serie para ver cómo funcionan juntos.

Ahora, ¡vamos a ver algunas novedades!


Rasterización

La rasterización (o rasterización, si se quiere) es el proceso de tomar una forma descrita en un formato gráfico vectorial (o en nuestro caso, matemático) y convertirla en una imagen rasterizada (donde la forma se ajusta a una estructura de píxeles).

Como las matemáticas no siempre son tan precisas como necesitamos para los gráficos por ordenador, debemos utilizar algoritmos para ajustar las formas que describen a nuestra pantalla basada en números enteros. Por ejemplo, un punto puede caer en la coordenada \((3,2, 4,6)\) en matemáticas, pero cuando lo representamos, debemos empujarlo a \((3, 5)\) para que pueda encajar en la estructura de píxeles de nuestra pantalla.

Cada tipo de forma que rastericemos tendrá su propio algoritmo para hacerlo. Empecemos con una de las formas más sencillas de rasterizar: el segmento de línea.


Segmentos de línea

Source: https://en.wikipedia.org/wiki/File:Bresenham.svgSource: https://en.wikipedia.org/wiki/File:Bresenham.svgSource: https://en.wikipedia.org/wiki/File:Bresenham.svg
Fuente: http://en.wikipedia.org/wiki/File:Bresenham.svg

Los segmentos de línea son una de las formas más sencillas que se pueden dibujar, por lo que suelen ser una de las primeras cosas que se tratan en cualquier clase de geometría. Están representados por dos puntos distintos (uno inicial y otro final) y la línea que los une. El algoritmo más utilizado para rasterizar un segmento de línea se llama Algoritmo de Bresenham.

Paso a paso, el Algoritmo de Bresenham funciona así:

  1. Recibe como entrada los puntos inicial y final de un segmento de línea.
  2. Identificamos la dirección de un segmento de línea determinando sus propiedades \(dx\) y \(dy\) (\(dx = x_{1} - x_{0}\), \(dy = y_{1} - y_{0}\).
  3. Determina las propiedades sx, sy, y la captura de errores (mostraré la definición matemática de estas a continuación).
  4. Redondea cada punto del segmento de línea al píxel superior o inferior.

Antes de implementar el Algoritmo de Bresenham, vamos a crear una clase básica de segmento de línea para utilizarla en nuestro motor:

Si quieres realizar una transformación en nuestra nueva clase LineSegment, todo lo que tienes que hacer es aplicar la transformación elegida a los puntos inicial y final del LineSegment y luego colocarlos de nuevo en la clase. Todos los puntos intermedios se procesarán cuando se dibuje el propio LineSegment, ya que el Algoritmo de Bresenham solo requiere los puntos inicial y final para encontrar cada punto posterior.

Para que la clase LineSegment se adapte a nuestro motor actual, no podemos tener una función draw() integrada en la clase, por lo que he optado por utilizar una función returnPointsInSegment en su lugar. Esta función devolverá un array de todos los puntos que existen dentro del segmento de línea, permitiéndonos dibujar y seleccionar fácilmente el segmento de línea según sea necesario.

Nuestra función returnPointsInSegment() se parece un poco a esto (en JavaScript):

La forma más sencilla de añadir el renderizado de nuestros segmentos de línea en nuestra clase de cámara es añadir una simple estructura if, similar a la siguiente:

Eso es todo lo que necesitas para poner en marcha tu primera clase de forma. Si quieres aprender más sobre los aspectos más técnicos del Algoritmo de Bresenham (en particular las secciones de error), puedes consultar el artículo de Wikipedia sobre el mismo.


Círculos

Source: http://en.wikipedia.org/wiki/File:Bresenham_circle.svg
Fuente: http://en.wikipedia.org/wiki/File:Bresenham_circle.svg

Rasterizar un círculo es un poco más difícil que rasterizar un segmento de línea, pero no mucho. Utilizaremos el algoritmo del círculo de punto medio para hacer todo el trabajo pesado, que es una extensión del ya mencionado Algoritmo de Bresenham. Como tal, sigue pasos similares a los enumerados anteriormente, con algunas diferencias menores.

Nuestro nuevo algoritmo funciona así:

  1. Recibe el punto central y el radio de un círculo.
  2. Fijar a la fuerza los puntos en cada dirección cardinal
  3. Recorre cada uno de nuestros cuadrantes, dibujando sus arcos

Nuestra clase de círculo será muy similar a nuestra clase de segmento de línea, con un aspecto similar al siguiente:

Nuestra función returnPointsInCircle() se va a comportar de la misma manera que la función de nuestra clase LineSegment, devolviendo un array de puntos para que nuestra cámara pueda renderizarlos y seleccionarlos según sea necesario. Esto permite a nuestro motor manejar una variedad de formas, con solo pequeños cambios necesarios para cada uno.

Este es el aspecto que tendrá nuestra función returnPointsInCircle() (en JavaScript):

Ahora, ¡solo tenemos que añadir otra sentencia if a nuestro bucle de dibujo principal, y estos círculos estarán totalmente integrados!

Así es como puede verse el bucle de dibujo actualizado:

Ahora que hemos sacado nuestras nuevas clases, ¡vamos a hacer algo!


Maestro de Rasterización

Nuestro programa va a ser sencillo esta vez. Cuando el usuario haga clic en la pantalla, vamos a dibujar un círculo cuyo punto central es el punto en el que se ha hecho clic, y cuyo radio es un número aleatorio.

Echemos un vistazo al código:

Con un poco de suerte, ahora deberías ser capaz de utilizar tu motor actualizado para dibujar algunos círculos impresionantes.


Conclusión

Ahora que tenemos algunas características básicas de rasterización en nuestro motor, ¡podemos finalmente empezar a dibujar algunas cosas útiles en nuestra pantalla! Nada demasiado complicado todavía, pero si quisieras, podrías juntar algunas figuras de palo, o algo por el estilo.

En el siguiente post, vamos a echar otro vistazo a la rasterización. Solo que esta vez, vamos a configurar dos clases más para ser utilizadas dentro de nuestro motor: triángulos y cuadriláteros. ¡Sigue atento!

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.