Skip to main content

Command Palette

Search for a command to run...

Espacios de Coordenadas en OpenGL

Marcos de Referencia para Crear Gráficos 3D

Updated
13 min read
Espacios de Coordenadas en OpenGL

Introducción

En OpenGL, cada vértice comienza su recorrido en un sistema de coordenadas muy simple: el espacio local del objeto. Sin embargo, antes de llegar a convertirse en un fragmento visible en pantalla, ese mismo vértice debe atravesar una serie de transformaciones geométricas que lo llevan por distintos espacios de coordenadas. Este proceso no es un capricho del pipeline gráfico, sino una necesidad: permite separar responsabilidades, facilitar cálculos como la iluminación, y mantener una forma ordenada y flexible de describir escenas complejas.

English version of this article. Click here

El objetivo final de este recorrido es obtener las llamadas Coordenadas de Dispositivo Normalizadas (NDC), que son indispensables para que el rasterizador pueda convertir la geometría en píxeles. Para llegar a ellas, OpenGL utiliza una secuencia de transformaciones aplicadas mediante matrices: Model, View y Projection. La clave está en que estas operaciones no se aplican por separado, sino que se concatenan en una sola cadena de transformaciones, lo que permite expresar de manera compacta la transición desde el espacio local de un objeto hasta su representación en pantalla.

En este artículo exploraremos cada uno de los espacios de coordenadas que intervienen en este proceso —Local, Mundial, de Vista, de Clip, de NDC y de Pantalla— y veremos cómo la composición de matrices hace posible que un vértice atraviese este camino de forma precisa y eficiente.

2. El Panorama General: La Cadena de Transformación

Para comprender cómo OpenGL lleva un vértice desde su posición original en un objeto hasta su representación final en la pantalla, conviene tener una vista global del proceso. El pipeline gráfico no aplica una única transformación, sino una cadena de operaciones sucesivas, cada una asociada a un espacio de coordenadas específico.

En total, un vértice atraviesa cinco espacios fundamentales:

  1. Espacio Local (Object Space): el sistema propio del objeto, definido durante el modelado.

  2. Espacio Mundial (World Space): unifica todos los objetos de la escena bajo un mismo sistema de referencia global.

  3. Espacio de Vista (Eye Space o View Space): representa la escena desde el punto de vista de la cámara.

  4. Espacio de Clip (Clip Space): el resultado de aplicar la proyección; aquí se determina qué geometría será visible.

  5. Espacio de Dispositivo y Pantalla (NDC y Screen Space): la conversión final a coordenadas normalizadas y luego a píxeles.

La transición entre estos espacios se logra mediante tres matrices principales:

  • Matriz de Modelo (M): lleva vértices del espacio local al mundo.

  • Matriz de Vista (V): convierte las coordenadas del mundo al sistema de la cámara.

  • Matriz de Proyección (P): proyecta la escena de 3D a 2D, generando el espacio de clip.

Estas matrices se aplican de forma concatenada en una expresión compacta:

$$\text{MVP} = P \cdot V \cdot M$$

donde cada vértice v se transforma como:

$$v_{clip} = P \cdot V \cdot M \cdot v_{local}$$

Este esquema refleja el corazón del pipeline gráfico: una secuencia de transformaciones geométricas expresadas como multiplicaciones de matrices. Comprender esta cadena es esencial antes de entrar al detalle de cada espacio, pues ofrece la intuición general del recorrido de un vértice en OpenGL.

3. Espacio Local (Object Space)

El recorrido de un vértice en OpenGL comienza en el espacio local, también llamado object space. Este es el sistema de coordenadas propio del objeto, definido normalmente durante la etapa de modelado. En este espacio, cada vértice se expresa con respecto a un origen y ejes internos al objeto, sin ninguna relación todavía con la escena global ni con la cámara.

Un ejemplo sencillo: al crear un cubo en un programa de modelado, sus vértices suelen estar centrados en el origen (0,0,0), con coordenadas que van de −0.5 a 0.5. En ese momento, no importa dónde aparecerá el cubo en la escena: lo único que importa es su forma y su escala relativas a su propio sistema.

    float CubeVertexPositions[108] = {
        -1.0f,  1.0f, -1.0f, -1.0f, -1.0f, -1.0f,  1.0f, -1.0f, -1.0f,
         1.0f, -1.0f, -1.0f,  1.0f,  1.0f, -1.0f, -1.0f,  1.0f, -1.0f,
         1.0f, -1.0f, -1.0f,  1.0f, -1.0f,  1.0f,  1.0f,  1.0f, -1.0f,
         1.0f, -1.0f,  1.0f,  1.0f,  1.0f,  1.0f,  1.0f,  1.0f, -1.0f,
         1.0f, -1.0f,  1.0f, -1.0f, -1.0f,  1.0f,  1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f, -1.0f,  1.0f,  1.0f,  1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f, -1.0f, -1.0f, -1.0f, -1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f, -1.0f, -1.0f,  1.0f, -1.0f, -1.0f,  1.0f,  1.0f,
        -1.0f, -1.0f,  1.0f,  1.0f, -1.0f,  1.0f,  1.0f, -1.0f, -1.0f,
         1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f,  1.0f,
        -1.0f,  1.0f, -1.0f,  1.0f,  1.0f, -1.0f,  1.0f,  1.0f,  1.0f,
         1.0f,  1.0f,  1.0f, -1.0f,  1.0f,  1.0f, -1.0f,  1.0f, -1.0f,
    };

El objetivo principal en este espacio es permitir transformaciones de modelado tales como:

  • Traslación: mover el objeto en relación con su propio origen.

  • Rotación: girar el objeto alrededor de sus ejes locales.

  • Escalado: modificar su tamaño en una o varias direcciones.

Todas estas operaciones se combinan en la llamada Matriz de Modelo (M), que actúa como el puente entre el espacio local y el espacio mundial. Matemáticamente, si v_local es un vértice en coordenadas locales, la conversión al mundo se expresa como:

$$v_{world} = M \cdot v_{local}$$

Un punto crucial es que estas transformaciones no son independientes, sino que pueden concatenarse en una sola matriz. Por ejemplo, si primero escalamos, luego rotamos y después trasladamos un objeto, la matriz resultante será el producto:

$$M = T \cdot R \cdot S$$

donde el orden importa, ya que la multiplicación de matrices no es conmutativa.

glm::mat4 mMat;

mMat = glm::translate(glm::mat4(1.0f), glm::vec3(cubeLocX, cubeLocY, cubeLocZ));

mMat = glm::scale(mMat, glm::vec3(1.5f, 1.5f, 1.5f));

mMat = glm::rotate(mMat, glm::radians(45.0f), glm::vec3(0.0f, 1.0f, 0.0f));

Este espacio local resulta particularmente útil porque permite describir la geometría de manera sencilla y reutilizable: un mismo modelo puede colocarse en diferentes posiciones y escalas en la escena simplemente cambiando su matriz de modelo.

4. Espacio Mundial (World Space)

Una vez que un vértice ha sido definido en el espacio local del objeto, el siguiente paso es situarlo dentro de la escena completa. Para ello se utiliza el espacio mundial (world space), un sistema de coordenadas global que sirve como referencia común para todos los objetos.

En este espacio, cada modelo deja de estar aislado en su propio origen y se coloca en una posición coherente con el resto de la escena. Así, si un cubo se ubica a la izquierda y una esfera a la derecha, ambas comparten un mismo marco de referencia que permite describir sus relaciones espaciales de forma consistente.

La transición de local → mundial ya está definida por la matriz de modelo (M), la cual integra todas las transformaciones aplicadas a cada objeto (escala, rotación y traslación). Al aplicar esta matriz sobre todos los vértices del objeto, se logra colocar el modelo en el mundo en la posición y orientación deseadas:

$$v_{world} = M \cdot v_{local}$$

Un aspecto esencial del espacio mundial es que permite la interacción entre múltiples objetos. Por ejemplo:

  • Colocar una mesa en el centro de una habitación.

  • Ubicar una lámpara sobre la mesa.

  • Posicionar una cámara frente a toda la escena.

Otro punto importante es que las transformaciones de modelado suelen organizarse de forma jerárquica. Esto significa que la posición de un objeto puede depender de otro. Por ejemplo, si un robot tiene un brazo articulado, al mover el cuerpo completo, el brazo también se mueve, ya que hereda las transformaciones de su “padre” en la jerarquía. En este caso, la concatenación de matrices resulta fundamental, pues la matriz de modelo final de un objeto puede estar compuesta por varias transformaciones heredadas.

5. Espacio de Vista (Eye Space / View Space)

Una vez que los objetos han sido colocados en la escena global mediante el espacio mundial, el siguiente paso es observar esa escena desde un punto de vista particular. Aquí es donde entra en juego el espacio de vista, también conocido como eye space o view space.

En este sistema de coordenadas, todo se reinterpreta como si estuviéramos mirando la escena desde los “ojos” de una cámara. Sin embargo, es importante aclarar una confusión muy común: en OpenGL no existe realmente un objeto “cámara” que se pueda mover o renderizar. Lo que hacemos, en realidad, es aplicar una transformación matemática a toda la escena para simular lo que una cámara vería desde cierta posición y orientación.

El concepto clave es el siguiente:

  • Mover la cámara hacia adelante es equivalente a mover toda la escena hacia atrás.

  • Girar la cámara hacia la derecha es lo mismo que rotar todo el mundo hacia la izquierda.

De esta manera, en lugar de trasladar o rotar una cámara, lo que hacemos es aplicar la Matriz de Vista (V) a todos los vértices de la escena:

$$v_{view} = V \cdot v_{world}$$

La matriz de vista se construye generalmente a partir de tres parámetros:

  1. La posición de la cámara (desde dónde miramos).

  2. El punto de enfoque (hacia dónde miramos).

  3. El vector “arriba” (up vector), que define la orientación vertical.

Con esta información, la matriz de vista se calcula de forma que traslada y rota la escena entera, colocando la cámara en el origen del espacio de vista, mirando hacia el eje −Z por convención en OpenGL.

glm::mat4 vMat;

vMat = glm::lookAt(
glm::vec3(cameraX, cameraY, cameraZ), // eye position
glm::vec3(0.0f, 0.0f, 0.0f),         // center: where the eye is looking at
glm::vec3(0.0f, 1.0f, 0.0f)          // up: the upward direction
);

¿Por qué este paso es tan útil? Porque muchos cálculos gráficos, como la iluminación y el sombreado, se simplifican al trabajar en un sistema donde el observador está en un punto fijo y conocido: el origen de coordenadas.


6. Espacio de Clip (Clip Space)

Después de transformar la escena al espacio de vista (Eye Space), el siguiente paso es proyectarla al espacio de clip (clip space). Este es un espacio intermedio donde OpenGL decide qué geometría está dentro del campo de visión y, por tanto, puede llegar a la pantalla.

La transición de vista → clip se realiza mediante la matriz de proyección P:

$$v_{clip} = P \cdot v_{view}$$

En este punto, cada vértice todavía tiene cuatro componentes (x,y,z,w), y será la división por w la que lo convertirá en coordenadas normalizadas (NDC).


6.1 Matriz de Proyección en Perspectiva

La proyección en perspectiva imita la forma en que los humanos percibimos el mundo: los objetos cercanos se ven más grandes que los lejanos. Esto se logra mediante una transformación que introduce la componente w, de manera que la profundidad afecta al tamaño aparente de los objetos.

Para construir esta matriz se necesitan cuatro parámetros:

  1. Field of View (FOV): ángulo vertical del campo de visión.

  2. Aspect ratio: relación ancho/alto de la ventana de visualización.

  3. Near clipping plane (Znear): plano cercano donde se empieza a proyectar la escena.

  4. Far clipping plane (Zfar): plano lejano que limita la proyección.

Geométricamente, estos parámetros definen un frustum, una pirámide truncada que representa todo lo que la cámara puede ver. Todo objeto fuera de este volumen es descartado mediante clipping.

En código, usando GLM, se construye así:

float aspect = (float)width / (float)height;
glm::mat4 pMat = glm::perspective(1.0472f, aspect, 0.1f, 1000.0f);  // 60 grados vertical

Esta matriz transforma coordenadas de Eye Space a Clip Space, ajustando la perspectiva y preparando los vértices para la normalización posterior en NDC.


6.2 Matriz de Proyección Ortográfica

En una proyección ortográfica, los objetos no se escalan con la distancia: las líneas paralelas permanecen paralelas, y no hay efecto de profundidad visual. Esto es útil en CAD, mapas, o cuando queremos mediciones precisas de los objetos, sin distorsión por perspectiva.

Para construir esta matriz se definen los límites del volumen de visión ortográfico:

  • L, R: límites izquierdo y derecho en X.

  • B, T: límites inferior y superior en Y.

  • Znear, Zfar: planos cercanos y lejanos en Z.

La proyección ortográfica proyecta directamente todos los vértices dentro de este volumen hacia Clip Space sin alterar sus proporciones. En GLM, se construye con:

glm::mat4 pMat = glm::ortho(left, right, bottom, top, nearPlane, farPlane);

7. Coordenadas de Dispositivo Normalizadas (NDC)

Una vez que los vértices han sido transformados al espacio de clip, todavía no están listos para el rasterizador. En este punto, cada vértice se representa en coordenadas homogéneas de la forma (x,y,z,w). Para normalizarlos y llevarlos a un espacio uniforme, OpenGL realiza automáticamente la llamada división de perspectiva (perspective divide):

$$v_{ndc} = \left(\frac{x}{w}, \frac{y}{w}, \frac{z}{w}\right)$$

Este paso tiene dos consecuencias fundamentales:

  1. Normalización:
    Los vértices quedan contenidos en un cubo de coordenadas conocido como volumen NDC (Normalized Device Coordinates), que va de −1 a 1 en cada eje.

    $$-1 \leq x{ndc}, y{ndc}, z_{ndc} \leq 1$$

  2. Profundidad en perspectiva:
    En una proyección en perspectiva, los objetos lejanos obtienen un valor de w mayor, lo que hace que sus coordenadas normalizadas se reduzcan, simulando así el efecto de que los objetos se ven más pequeños al alejarse.

De esta manera, la división entre w es el paso que convierte la proyección en perspectiva en algo tangible: el foreshortening o acortamiento visual que da realismo a la escena.

El volumen NDC tiene una forma cúbica muy estricta:

  • En el eje x, de −1 (izquierda) a 1 (derecha).

  • En el eje y, de −1 (abajo) a 1 (arriba).

  • En el eje z, de −1 (cerca) a 1 (lejos) en OpenGL clásico. (Nota: algunas APIs como DirectX usan [0,1] para z).

Cualquier vértice que quede fuera de este rango será descartado, pues no puede ser representado en pantalla.


8. Espacio de Pantalla (Screen Space)

Después de normalizar los vértices en el espacio NDC, todavía nos queda un último paso: transformarlos a coordenadas de pantalla que correspondan a píxeles reales en el monitor. Este espacio se conoce como screen space o window space.

El mapeo de NDC a pantalla se realiza mediante la transformación de ventana (viewport transform). Conceptualmente, esta transformación escala y traslada las coordenadas normalizadas [−1,1] de cada eje a valores enteros correspondientes a píxeles:

$$\text{Eje } x: \; [-1, 1] \;\;\longrightarrow\;\; [0, \text{ancho de la ventana}]$$

$$\text{Eje } y: \; [-1, 1] \;\;\longrightarrow\;\; [0, \text{alto de la ventana}]$$

La función de OpenGL glViewport(x, y, width, height) define esta correspondencia. Esencialmente, indica:

  • (x, y): la esquina inferior izquierda del área de renderizado.

  • (width, height): las dimensiones del viewport, es decir, el área de la ventana donde se dibujará la escena.

Matemáticamente, la conversión de NDC a pantalla para cada eje se puede expresar como:

$$x_{screen} = \frac{(x_{ndc} + 1)}{2} \cdot \text{width} + x$$

$$y_{screen} = \frac{(y_{ndc} + 1)}{2} \cdot \text{height} + y$$

El eje z también se transforma a un rango apropiado para el depth buffer, que permite el cálculo de la visibilidad de los fragmentos durante el rasterizado. (este tema sera tratado en articulos posteriores).

Ejemplo.

Conclusión: ¿Por Qué Tantos Espacios de Coordenadas?

A lo largo del recorrido de un vértice en OpenGL, hemos visto cómo pasa por diferentes espacios de coordenadas: local, mundial, de vista, de clip, NDC y finalmente de pantalla. A primera vista, puede parecer que el vértice “viaja” por distintos mundos o que cada espacio es un lugar físico distinto. Pero no es así.

En realidad, cada espacio no es más que un marco de referencia matemático, una forma conveniente de describir posiciones y transformaciones en el proceso de generación de gráficos. No hay múltiples escenas o cámaras flotando en paralelo: todo ocurre dentro de un mismo sistema numérico, y lo único que hacemos es reinterpretar las coordenadas en función del problema que queremos resolver en cada etapa.

  • Espacio local: sirve como marco para modelar un objeto respecto a sí mismo.

  • Espacio mundial: nos da un punto de referencia común para posicionar varios objetos en una misma escena.

  • Espacio de vista: cambia el marco de referencia a la perspectiva de la cámara (o más bien, del observador).

  • Espacio de clip y NDC: son marcos diseñados para simplificar el proceso de proyección y rasterización.

La clave está en la concatenación de matrices (modelo, vista, proyección), que nos permite pasar de un marco a otro sin perder información esencial. Cada transformación se aplica con un propósito específico, y al final todo converge en el mismo resultado: coordenadas listas para dibujarse como píxeles en pantalla.

Gráficos por computadora.

Part 3 of 6

Artículos dedicados a los gráficos por computadora, con explicaciones claras de los conceptos clave y ejemplos prácticos de técnicas como renderizado, iluminación, transformaciones, rasterización y más.

Up next

Matemáticas para Gráficos 3D con OpenGL

Vectores, matrices y transformaciones en gráficos 3D

More from this blog