7.5 Espaços do OpenGL

Vimos que, no pipeline gráfico do OpenGL, as primitivas só são renderizadas se estiverem contidas em um “volume de visão” formado por um cubo centralizado na origem, com coordenadas que vão de \(-1\) a \(1\). As coordenadas desse espaço tridimensional são chamadas de coordenadas normalizadas do dispositivo, ou NDC (figura 7.14).

Volume de visão em coordenadas normalizadas do dispositivo.

Figura 7.14: Volume de visão em coordenadas normalizadas do dispositivo.

Observe que os eixos do NDC seguem a regra da mão esquerda, isto é, o eixo \(z\) positivo aponta para dentro da tela.

Por uma questão de simplicidade, até agora representamos todos os objetos diretamente no NDC. Entretanto, essa abordagem é pouco flexível para a maioria das aplicações. Com frequência precisamos trabalhar com coordenadas em intervalos maiores em um sistema orientado segundo a regra da mão direita.

Podemos representar mudanças de pontos entre diferentes quadros intermediários através de transformações matriciais, da forma que considerarmos mais conveniente. Só precisamos garantir que, no vertex shader, essas coordenadas serão finalmente mapeadas para o espaço homogêneo de recorte, que é o sistema de coordenadas utilizado na variável embutida gl_Position, ou diretamente para o NDC, fazendo com que a coordenada homogênea (\(w\)) seja sempre 1.

Usaremos os seguintes quadros, nessa ordem:

  1. Espaço do objeto (local space ou object space).
  2. Espaço do mundo (world space), representando o quadro padrão.
  3. Espaço da câmera (view space, camera space ou eye space).

Além desses, há os quadros utilizados durante o processamento do pipeline gráfico do OpenGL:

  1. Espaço de recorte (clip space).
  2. Espaço normalizado do dispositivo (NDC space).
  3. Espaço da janela (window space).

Um modelo 3D está inicialmente no espaço do objeto. Esse é o espaço das coordenadas dos atributos dos vértices armazenados no VBO. No pipeline de renderização, os pontos/vetores do espaço local são convertidos para os espaços subsequentes através de multiplicações com matrizes de transformação (matrizes \(4 \times 4\), como visto na seção anterior). A figura 7.15 mostra a sequência de transformações de pontos/vetores, do espaço do objeto ao espaço da janela.

Etapas de transformação entre sistemas de coordenadas no pipeline gráfico.

Figura 7.15: Etapas de transformação entre sistemas de coordenadas no pipeline gráfico.

Nesta seção, serão abordados apenas os três primeiros espaços, que são os espaços definidos pelo usuário:

  • Espaço do objeto;
  • Espaço do mundo;
  • Espaço da câmera.

Os espaços restantes serão detalhados no próximo capítulo.

Espaço do objeto

É o espaço local no qual o modelo geométrico é definido inicialmente. Por exemplo, o modelo “Stanford Bunny” do arquivo bunny.obj (seção 6.4) foi definido em um sistema de coordenadas que segue a regra da mão direita (RHS, de right-handed coordinate system), sendo que o eixo \(y\) positivo aponta para cima (figura 7.16). A origem desse sistema de coordenadas é o centro da base do coelho. Além disso, as coordenadas do modelo estão na faixa \(x \in [-1, 0.7]\), \(y \in [0, 1.6]\), \(z \in [-0.5, 0.7]\).

Espaço do objeto do modelo do arquivo `bunny.obj`.

Figura 7.16: Espaço do objeto do modelo do arquivo bunny.obj.

O cubo definido no arquivo box.obj (seção 6.4) usa um sistema de coordenadas que segue a regra da mão esquerda (LHS, de left-handed coordinate system). A origem é o centro do cubo e as coordenadas variam de \(-0.5\) a \(0.5\) em cada dimensão.

Espaço do objeto do modelo do arquivo `box.obj`.

Figura 7.17: Espaço do objeto do modelo do arquivo box.obj.


Observação

Um triângulo definido em um espaço RHS tem sua orientação invertida quando renderizado sem modificações em um espaço LHS, como o NDC.

No espaço RHS, o lado da frente de um triângulo no plano \(xy\) é o lado com orientação CCW para um observador olhando na direção de \(z\) negativo. Entretanto, se esse mesmo triângulo é utilizado sem modificação no NDC, o lado da frente ficará orientado no sentido CW após o mapeamento no espaço da janela, como se o observador agora olhasse na direção de \(z\) negativo do espaço LHS (figura 7.18).

Mudança de orientação de um sistema RHS para LHS.

Figura 7.18: Mudança de orientação de um sistema RHS para LHS.

Esse problema pode ser resolvido através da negação de cada coordenada \(z\) do modelo. Faremos isso na matriz de projeção, pois sempre consideraremos que o espaço do objeto é RHS.

Espaço do mundo

O espaço do mundo é, geralmente, o quadro padrão utilizado para dispor os diferentes objetos em um cenário virtual. O espaço do mundo segue a regra da mão direita. Por convenção, consideramos que o eixo \(y\) positivo aponta para cima, e o plano \(xz\) com altura \(y=0\) corresponde ao plano do “chão”. A figura 7.19 ilustra a composição de uma cena através da disposição de objetos sobre o plano \(y=0\) do espaço do mundo.

Cena no espaço do mundo.

Figura 7.19: Cena no espaço do mundo.

Em uma cena composta por vários objetos, a transformação que posiciona e orienta um objeto na cena é definida através de uma matriz de modelo (model matrix).

A matriz de modelo é uma concatenação de transformações de rotação, escala e translação que representa uma mudança de quadro: do espaço do objeto para o espaço do mundo.

Cada objeto de uma cena deve ter a sua própria matriz de modelo. Se o objeto foi definido originalmente no quadro padrão, então sua matriz de modelo é uma matriz identidade.

Na cena da figura 7.19, as bases cuboides compartilham o mesmo modelo de um cubo mostrado na figura 7.20, mas cada um usa uma matriz de modelo diferente, pois cada cuboide está numa posição/orientação/escala diferente na cena.

Cubo unitário centralizado na origem.

Figura 7.20: Cubo unitário centralizado na origem.

Por exemplo, para o objeto cuboide que serve de base para o coelho, a matriz de modelo é a seguinte concatenação de transformações:

\[\mathbf{M}=\mathbf{T}\left(-3,\frac{1}{2},-\frac{1}{2}\right).\mathbf{R}_y\left(\frac{7\pi}{36}\right).\mathbf{S}\left(\frac{5}{4}, \frac{1}{2}, \frac{5}{4}\right). \]

A matriz representa a aplicação das transformações na ordem de leitura da direita para a esquerda (figura 7.21):

  1. Escala de \(s_x=1.25\), \(s_y=0.5\), \(s_z=1.25\);
  2. Rotação por \(7\pi/36\) radianos (\(35^{\circ}\)) em torno de \(y\);
  3. Translação por \(t_x=-3\), \(t_y=0.5\), \(t_z=-0.5\).
Sequência de transformações de uma matriz de modelo.

Figura 7.21: Sequência de transformações de uma matriz de modelo.

Se a matriz de modelo é a matriz que converte pontos no quadro local para pontos no quadro do mundo, então a inversa da matriz de modelo faz o mapeamento inverso, isto é, do quadro do mundo para o quadro local. No caso da base cuboide, essa transformação inversa é

\[ \begin{align} \mathbf{M}^{-1}&=\left(\mathbf{T}\left(-3,\frac{1}{2},-\frac{1}{2}\right).\mathbf{R}_y\left(\frac{7\pi}{36}\right).\mathbf{S}\left(\frac{5}{4}, \frac{1}{2}, \frac{5}{4}\right)\right)^{-1}\\ &=\mathbf{S}\left(\frac{5}{4}, \frac{1}{2}, \frac{5}{4}\right)^{-1}.\mathbf{R}_y\left(\frac{7\pi}{36}\right)^{-1}.\mathbf{T}\left(-3,\frac{1}{2},-\frac{1}{2}\right)^{-1}\\ &=\mathbf{S}\left(\frac{4}{5}, 2, \frac{4}{5}\right).\mathbf{R}_y\left(-\frac{7\pi}{36}\right).\mathbf{T}\left(3,-\frac{1}{2},\frac{1}{2}\right). \end{align} \]

Note que as transformações concatenadas da matriz inversa desfazem cada uma das transformações da figura 7.21, no sentido contrário (da etapa 3 até o modelo original).

Espaço da câmera

O espaço da câmera representa o ponto de vista da câmera virtual posicionada no mundo, isto é, o ponto de vista de um observador em primeira pessoa dentro da cena.

No espaço da câmera, a câmera está posicionada na origem, olhando na direção do eixo \(z\) negativo. As coordenadas de todos os objetos da cena são descritos em relação à câmera. A figura 7.22 ilustra o quadro de uma câmera em relação ao mundo. A direção de visão é representada pela seta tracejada, que é a direção do eixo \(z\) negativo do quadro da câmera.

Quadro da câmera em relação ao quadro do mundo.

Figura 7.22: Quadro da câmera em relação ao quadro do mundo.

A figura 7.23 ilustra como a cena é vista a partir da câmera, e como a câmera vê o quadro do mundo.

Quadro do mundo do ponto de vista da câmera.

Figura 7.23: Quadro do mundo do ponto de vista da câmera.

A transformação que transforma pontos do espaço do mundo para o espaço da câmera é definida através de uma matriz de visão (view matrix). Essa matriz é uma concatenação de rotações e uma translação.

Para construir uma matriz de visão, precisamos de uma posição e uma orientação.

  • A posição é a localização da câmera no espaço do mundo. Do ponto de vista da câmera, é a origem (ponto \((0,0,0)\)) de seu quadro. Essa informação fica armazenada na parte de translação da matriz de visão (parte \(3 \times 1\) da quarta coluna)
  • A orientação é uma base ortonormal, e corresponde à parte \(3 \times 3\) superior da matriz de visão (mudança de base).

Descreveremos na seção 7.6 o processo de construção de uma matriz de visão a partir da posição da câmera, a posição para onde a câmera está olhando, e um vetor de direção para cima, que geralmente é o vetor \(\hat{\mathbf{j}}=\begin{bmatrix}0&1&0\end{bmatrix}^T\) do \(\mathbb{R}^3\).

Concatenação das matrizes de modelo e visão

Sempre que um objeto for renderizado, a posição de cada um de seus vértices precisa ser transformada. Isso pode ser feito em duas etapas:

  1. Conversão do espaço local para o espaço do mundo: \[\mathbf{p}'=\mathbf{M}_{\textrm{model}}.\mathbf{p},\] onde \(\mathbf{M}_{\textrm{model}}\) é a matriz de modelo do objeto que está sendo renderizado.

  2. Conversão do espaço do mundo para o espaço da câmera: \[\mathbf{p}''=\mathbf{M}_{\textrm{view}}.\mathbf{p}',\] onde \(\mathbf{M}_{\textrm{view}}\) é a matriz de visão. A matriz de visão deve ser a mesma para todos os objetos da cena renderizada.

É comum combinar as duas transformações em uma só matriz modelo-visão:

\[ \mathbf{M}_{\textrm{modelview}}=\mathbf{M}_{\textrm{view}}.\mathbf{M}_{\textrm{model}}. \]

Assim, no vertex shader basta uma multiplicação matricial para transformar a posição do vértice pela matriz modelo-visão. O resultado será um ponto no espaço da câmera.

Observação

Após a transformação do ponto para o espaço da câmera, é necessário aplicar ainda uma transformação projetiva através de uma matriz de projeção \(\mathbf{M}_{\textrm{proj}}\).

A matriz de projeção converte um ponto do espaço da câmera para o espaço homogêneo de recorte, que é o espaço esperado pela variável embutida gl_Position no vertex shader. A transformação completa fica como a seguir:

\[ \mathbf{p}'=\mathbf{M}_{\textrm{proj}}.\mathbf{M}_{\textrm{view}}.\mathbf{M}_{\textrm{model}}.\mathbf{p}, \]

onde

  • \(\mathbf{p}\) é a entrada do vertex shader, isto é, a posição do vértice no formato \(\begin{bmatrix}x&y&z&1\end{bmatrix}^T\);
  • \(\mathbf{p}'\) é a posição transformada no formato \(\begin{bmatrix}x'&y'&z'&w\end{bmatrix}^T\). Essa é a posição que será copiada para gl_Position.

Os conceitos sobre transformações de projeção e o processo de construir a matriz \(\mathbf{M}_{\textrm{proj}}\) serão abordados no próximo capítulo.