IIC3912 - Tópicos Avanzados de Gráfica Computacional
Francisca T. Gil-Ureta ⋅ 2026

Clase 7 | Ray Tracing

Pintando cada pixel

Clase 06 - Después de esta clase los estudiantes pueden explicar el modelo de cámara pinhole, distinguir entre parámetros intrínsecos y extrínsecos, y calcular una configuración de cámara que encuadre un objeto dentro del frustum.

Clase 07 - Después de esta clase los estudiantes pueden generar rayos desde una cámara para calcular una imagen, identificar intersecciones con la geometría de la escena y explicar cómo el color de cada píxel se determina a partir del primer objeto intersectado.

Rendering

Es el proceso que toma como input un set de objetos y produce como output un arreglo de pixeles. Rendering involucra considerar cómo cada objeto contribuye al color de cada pixel.

Objecto-order rendering (e.g., rasterización): para cada objeto, encontramos los pixeles que influencia y los actualizamos.

Image-order rendering (e.g., ray-tracing): para cada pixel, encontramos todos los objetos que influencian su color y calculamos el color del pixel.

🎨 Image-order rendering es más simple de implementar (versión básica), y más flexible en los efectos que permite, pero usualmente también es más lento de ejecutar

GeForce RTX es una linea de tarjetas gráficas de alto rendimiento que utiliza ray tracing en tiempo real. También cada vez más incluye IA para ofrecer gráficos hiperrealistas, iluminación avanzada, y mantener el alto rendimiento en videojuegos.

Basic Ray-Tracing Algorithm
Basic Ray Tracing

El ray tracer calcula el color de un pixel a la vez. La tarea básica del ray-tracer es encontrar que objetos son vistos en cada pixel.

1. Generación de Rayos: calcula el origen y la dirección del viewing ray de cada pixel.

2. Intersección de Rayos: encuentra el objeto más cercano a la cámara que es intersectado por el rayo.

3. Coloreado (Shading): calcula el color del pixel basado en los resultados de la intersección.


Generación de Rayos

Generación de Rayos

Podemos modelar matemáticamente un rayo cómo un punto donde se origina y una dirección de propagación.

p(t) = e + t(s - e)

e es el punto de origen, y s es un punto en el plano de la imagen (e.g., centro del pixel). t es un escalar que nos hace avanzar desde e a s, desde t=0 a t=1.



Cómo encontramos el punto s?

Para calcular los rayos necesitamos conocer el punto e (viewpoint) y s. Para encontrar s debemos mirar nuevamente al sistema de coordenadas de la cámara.

  • e: punto donde está el origen del sistema de coordenadas de la cámara
  • u: apunta hacia la derecha (desde el punto de vista de la cámara)
  • v: apunta hacia arriba
  • w: apunta en la dirección opuesta a la vista

Plano de la Imagen

Vamos a definir el plano de la imagen usando las coordenadas de la cámara.

  • l y r, son las posiciones de los bordes izquierdo y derecho (left and right)
  • b y t, son las posiciones de los bordes superior e inferior (bottom and top)

Si la imagen tiene W x H pixeles, los pixeles van a estar espaciados por una distancia de (r - l) / W horizontalmente y (t - b) / H verticalmente.

La grilla de pixeles tiene su propia numeración, de (0,0) a (W-1, H-1). Para un pixel (i,j) tiene posición (u,v) en el plano de la imagen dado por:

u = l + (r - l) * (i + 0.5) / W
v = b + (t - b) * (j + 0.5) / H

Vista Ortográfica

En una vista ortográfica, el rayo se origina en el plano de la imagen (centro del pixel) y apunta en la dirección de la vista de la camara (-w).

Para generar los rayos de cada pixel, simplemente calculamos la posición del rayo en image space (u,v) y usamos el sistema de coordenadas de la cámara para calcular las coordenadas en el mundo.

for i in range(0, W):
for j in range(0, H):
u = l + (r - l) * (i + 0.5) / W
v = b + (t - b) * (j + 0.5) / H

# origen y direción expresadas en world coordinates
ray.origin = cam.e + u * cam.u + v * cam.v
ray.dir = - cam.w


Vista Perspectiva

En una vista perspectiva, todos los rayos tienen el mismo origen, el viewpoint e; pero la dirección es distinta para cada pixel.

El plano de la imagen ya no se ubica en e, sino a una distancia d en la dirección de la vista. A esa distancia a veces se le dice focal length, aun que no son exactamente lo mismo, pero cumple un rol similar.

for i in range(0, W):
r - l) * (i + 0.5) / W
v = b + (t
for j in range(0, H):
u = l + (- b) * (j + 0.5) / H

# origen y direción expresadas en world coordinates
ray.origin = cam.e
ray.dir = - d * cam.w + u * cam.u + v * cam.v


1. Generación de Rayos: calcula el origen y la dirección del viewing ray de cada pixel.

2. Intersección de Rayos: encuentra el objeto más cercano a la cámara que es intersectado por el rayo.

3. Coloreado (Shading): calcula el color del pixel basado en los resultados de la intersección.

Intersección Objeto-Rayo

Queremos encontrar la intersección del rayo e+td con cualquier objeto donde para t>0

Intersección Esfera-Rayo

Una esfera con centro c y radio R se puede representar por la función implícita f(p) = 0.

Dado el rayo p(t) = e+td, buscamos el t para el cual f(e+td) = 0, i.e. el punto donde el rayo intersecta a la esfera.


Intersección Triangulo-Rayo

Un punto p que pertenece al triangulo con vertices a, b, c puede ser expresado como una combinación baricéntrica de sus vértices, es decir:

p = αa + βb + γc,

donde α,β,γ ≥ 0 y α + β + γ = 1



Intersección con un Grupo de Objetos

Para cada rayo, revisamos la intersecciones posibles con cada objeto (i.e., cada triangulo) y elegimos la más cercana a la cámara.


Luces

Dado un punto en la superficie podemos obtener su normal (n), material, texturas uv, etc. Esto, combinado con su distancia y orientación hacia las fuentes de luz nor permite colorearlo adecuadamente.

💡El cálculo se hace para cada fuente de luz

Sombras

Para agregar sombras, debemos considerar si el punto logra 'ver' la luz. Si hay un objeto entre la superficie y la luz, la superficie estará en sombra.

Dada las imprecisiones numéricas, el rayo que usamos para evaluar tiene un pequeño epsilon. De esta forma evitamos 'chocar' con la superficie que origina el rayo.

Espejos (Mirrors)

Si estamos mirando una superficie perfectamente especular (e.j., espejo) el color del punto x que miramos va a ser un reflejo de lo que se vería desde ese punto x en la dirección reflejada (r).

Podemos implementar esto cómo una recursion donde paramos cuando el rayo choca con una superficie opaca, o rebota un máximo de veces.


Practical

Colab: https://colab.research.google.com/github/gilureta/grafica/blob/main/practicals/practical_07/RayTracing.ipynb

1. Qué cambios debemos hacer para visualizar los rayos de la Camara de Perspectiva?

2. Cómo aumentamos el numero de pixeles?

3. Qué pasa cuando cambiamos el focal lenght?


Aditional Reading

Fundamentals of Computer Graphics | Capitulo 4 - Ray Tracing

Para que revisen la matemática de ray-tracing en más detalle

Implementing the Raytracing Algorithm by Scratch a Pixel

https://www.scratchapixel.com/lessons/3d-basic-rendering/introduction-to-ray-tracing/implementing-the-raytracing-algorithm.html