Semestre 02, 2026
Técnica de proyección en la que se lanzan rayos desde un punto (usualmente el jugador) hacia el entorno.
Una columna vertical de la pantalla a la vez.
Nunca dibujamos geometría 3D. Repetimos un cálculo 2D sencillo una vez por columna y el resultado se percibe como profundidad.
Los rayos de los bordes viajan más lejos que los del centro para tocar la misma pared recta. Si usamos esa distancia tal cual, la pared se ve curvada.
La corrección proyecta la distancia sobre la dirección de vista, con \(\beta\) el ángulo del rayo respecto al centro:
$$ d_{\perp} = d \cdot \cos(\beta) $$
for i in 0..5 {
let angle = a - (fov / 2.0)
+ i as f32 * (fov / 5.0);
// lanzar rayo en esa dirección
}
Vista a \(a = 90°\), \(fov = 60°\), 5 rayos. El primero sale en \(90° - 30° = 60°\) y el paso es \(60°/5 = 12°\).
El número de rayos es el ancho de la pantalla: con \(n\) rayos dibujamos \(n\) columnas, una imagen completa.
// hh = mitad de la altura del viewport
let stake_height = hh / intersect.d;
La altura es inversamente proporcional a la distancia: el doble de lejos, la mitad de alto. Eso da la perspectiva.
let stake_top = hh - stake_height / 2.0;
let stake_bottom = hh + stake_height / 2.0;
\(hh = 450\). La altura es \(stake = hh / d\), con la distancia en unidades de celda.
let hitx = x - i * block_size; // offset en el bloque
let tx = (maxhit * 128) / block_size; // 128 = ancho tex.
\(maxhit\) es el punto exacto (en píxeles) donde chocó el rayo dentro del bloque; se reescala al ancho de la textura.
Impacto al centro del bloque: \(maxhit = 32\), \(block = 64\).
Usamos la columna 64 de la imagen de la pared.
let ty = (y - stake_top)
/ (stake_bottom - stake_top)
* texture_height;
"Un mundo 3D no necesita ser complicado para ser convincente."