Ray Tracing: Cálculo de Intersecciones y Normales

Juan Mellado, 19 Octubre, 2005 - 11:55

Tal y como se vio en el artículo anterior, un rayo define una línea recta imaginaria que parte de la posición del observador y atraviesa el centro de un pixel. Para determinar el color de dicho pixel se debe determinar que objetos ve el observador mirando a lo largo de la dirección del rayo que lo atraviesa, y para ello se deben calcular las intersecciones que ocurren entre el rayo y los objetos presentes en la escena.

Saber como se calculan estas intersecciones permite generar una imagen de forma rápida, ya que, para obtener el color de un pixel, basta con calcular todas las intersecciones posibles que se producen entre el rayo que lo atraviesa y los objetos de la escena, y asignar a dicho pixel el color del objeto intersectado más cercano al observador.

Este artículo presenta fórmulas genéricas para el cálculo de las intersecciones de los rayos con los objetos y para la obtención de las normales a los objetos en dichas intersecciones. El cálculo de normales no será de utilidad hasta que presenten los modelos de iluminación, pero resulta muy conveniente introducirlo en este momento porque las normales se calculan en los puntos de intersección.

Ecuación del Rayo

Tal y como se detalló en el artículo anterior, los rayos se caracterizan por su origen O = (ox, oy, oz), y su vector dirección normalizado D = (dx, dy, dz), lo que permite definirlos mediante la siguiente ecuación paramétrica:

R(t) = O + D * t

Ecuación que puede reescribirse considerando cada componente por separado:

x = ox + dx * t
y = oy + dy * t
z = oz + dz * t

Un valor de t = 0 nos sitúa en la posición que ocupa el observador, un valor negativo por detrás, y uno positivo por delante. Aunque de forma general se suele acotar los posibles valores válidos con dos límites, uno superior y otro inferior:

t_near <= t <= t_far

El valor t_near se toma próximo a cero, y no exactamente cero, para intentar salvar los habituales problemas de precisión en el cálculo computacional. El valor t_far, que indica el mayor valor considerado para t, permite descartar objetos que se encuentran muy lejanos al observador, y cuya aportación no es significativa.

Intersección con un Objeto

Hasta ahora se había hablado de los objetos presentes en la escena de forma muy genérica, pero en la práctica se suelen definir mediante primitivas geométricas como esferas, cilindros o planos. La ventaja de este de tipo de entidades es que se pueden generalizar mediante una ecuación implícita de la siguiente forma:

S(x, y, z) = 0

Los puntos (x, y, z) para los que se cumple la ecuación representan los puntos que se encuentran sobre la superficie del objeto, de forma que los puntos de intersección entre un rayo y dicha superficie se obtienen sustituyendo en la ecuación de la superficie la ecuación del rayo, y resolviendo por t:

S(ox + dx * t, oy + dy * t, oz + dz * t) = S'(t) = 0

Los puntos que satisfacen ambas ecuaciones al unísono son puntos que se encuentran al mismo tiempo en el rayo y la superficie, o sea, son puntos de intersección entre ambos.

El cálculo de intersecciones se reduce así a encontrar todos los valores reales de t que verifican la ecuación. Los valores de t encontrados, y evaluados en la ecuación del rayo, proporcionarán los puntos del espacio en que se producen dichas intersecciones.

Dependiendo de la dirección del rayo, y la forma de la superficie del objeto contra la que se compruebe la intersección, se puede obtener cero, una ó más soluciones reales. La intersección con menor valor de t será la más cercana al punto de partida del rayo. Los valores negativos corresponderán a puntos situados por detrás del origen del rayo, en sentido contrario a su dirección, por lo que no se tendrán en cuenta. Y las raices imaginarias (no reales) se interpretarán como que no se produce intersección.

Así, si ti es el valor de t para el que se produce una intersección, entonces el punto intersectado I = (ix, iy, iz) es:

I = R(ti) = O + D * ti

O escribiendo cada componente por separado:

ix = ox + dx * ti
iy = oy + dy * ti
iz = oz + dz * ti

Normal al Punto de Intersección con un Objeto

Una vez determinado el punto de intersección I con un objeto, se puede determinar la normal Ni al objeto en dicho punto. Su utilidad se verá clara en un artículo posterior dedicado a iluminación.

La normal de un objeto en un punto concreto de su superficie es un vector perpendicular a la superficie en dicho punto, y realmente, cuando se habla de calcular la normal, se habla de calcular la dirección de dicho vector perpendicular. Por ejemplo, la dirección de la normal en un punto concreto de la superficie de una esfera la marca la dirección que une el centro de la esfera con dicho punto. En cambio, la normal en cualquier punto de la superficie de un plano totalmente horizontal es un vector totalmente vertical. Es decir, que la forma de obtener la normal varía significativamente en función del tipo de objeto, ya que su cálculo depende completamente de la forma del mismo, y no puede estudiarse de forma global, debe hacerse individualmente.

Otro factor a tener en cuenta a la hora de calcular la normal es saber si la intersección con el rayo se produce en la cara interior o exterior del objeto. Y aunque en principio pueda resultar bastante difícil de calcular, en realidad es bastante sencillo gracias al producto escalar, ya que si dos vectores apuntan hacia un mismo lado de un plano el signo de dicho producto es positivo, y si lo hacen hacia lados contrarios es negativo. Con lo que, si el signo del producto escalar entre la normal y el rayo es negativo entonces el rayo incide en la cara exterior del objeto (apunta en dirección contraria a la normal), y si es positivo incide sobre la cara interior (apunta en la misma dirección que la normal). El valor cero corresponde al caso en que ambos vectores son perpendiculares, es decir, el rayo es tangente al objeto.

Si el rayo incide en la cara interior del objeto (se cumple Ni · D > 0) se cambiará la dirección de la normal, esto es, se tomará -Ni, para tener en cuenta tal circunstancia.

La explicación de en qué consiste el producto escalar queda fuera del alcance de este artículo, puede encontrarse en cualquier tutorial básico de cálculo de vectores. Baste decir que dados dos vectores A = (ax, ay, az) y B = (bx, by, bz), el producto escalar es el valor resultante de evaluar la siguiente expresión:

A · B = (ax * bx) + (ay * by) + (az * bz)