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.
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.

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.

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.

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.

Vamos a definir el plano de la imagen usando las coordenadas de la cámara.
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

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.

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.

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.
Queremos encontrar la intersección del rayo e+td con cualquier objeto donde para t>0

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.

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
Para cada rayo, revisamos la intersecciones posibles con cada objeto (i.e., cada triangulo) y elegimos la más cercana a la cámara.

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

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.

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.
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?

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