[T2][ICG] Pipeline

EDIT:
Nome: José Arnaldo de Assis Pina Neto
Matrícula: 2016064100

Proposto pelo Prof. Christian Pagot, esta postagem faz parte da avaliação da disciplina Introdução à Computação Gráfica como segundo projeto prático, a implementação de um pipeline gráfico.

Afinal, O que é um pipeline gráfico?

Definimos por Pipeline Gráfico todo o conjunto de passos necessários para um computador transformar primitivas (conjunto de vértices que, quando unidos foram figura 2D ou 3D) em desenhos na tela (rasterização). O pipeline em questão é semelhante ao utilizado pela OpenGL.

 

A figura acima ilustra as transformações feitas ao longo do pipeline, que parte do Model Space (Espaço do Objeto/Modelo), passa para o World Space (Espaço do Universo), para o Camera Space (Espaço da Câmera), para o Projection/Clipping Space (Espaço de Recorte), de onde sofre uma transformação canônica e finalmente passa a o Screen Space (Espaço da Tela), onde é rasterizada. Todas as transformações são esmiuçadas ao longo deste trabalho.

Coordenadas Homogêneas

Todo o pipeline gráfico é calculado pela cpu/gpu abstraído através de matrizes. Entretanto, coordenadas cartesianas simples não são capazes de prover envergadura suficiente para que transformações geométricas afins sejam realizadas ao longo de todo o processamento 3D, a saber, as transformações de Escala, Translação e Rotação. Vejamos como converter  coordenadas cartesianas em coordenadas homogêneas:

Convertendo

Na prática, trabalhar com coordenadas  homogêneas significa que, para uma posição cartesiana, digamos, P(x, y), representaremos com uma dimensão w a mais. Assim, em tese, P(x, y) e P'(x, y, w) fazem menção à mesma posição. Explicitando como funciona a conversão, pegamos a coordenada w e multiplicamos por todas as coordenadas disponíveis e, ao fim, atribuímos w como coordenada também. Ex.: Considerando w como 1, e uma posição Q(x, y), Q' (x \cdot 1, y \cdot 1, 1).

A seguir, escrevemos as transformações 3D em relação a coordenadas 2D, utilizando operações com matrizes e vetores já em coordenadas homogêneas.

Matriz de Escala

Seus elementos s_{x}, s_{y} e s_{z} são responsáveis pela escala no respectivo eixo. Se todos os elementos s_{i} forem 1, a matriz se mantém, ou seja, para aumentar ou diminuir a representação, tem de se aplicar, respectivamente, valores maiores ou menores que 1.

\begin{bmatrix}x' \\ y' \\ z' \\ 1\end{bmatrix}=\begin{bmatrix}s_{x} & 0 & 0 & 0 \\ 0 & s_{y} & 0 & 0 \\ 0 & 0 & s_{z} & 0 \\ 0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\ y \\ z \\ 1\end{bmatrix}

Matriz de Rotação

Escrevemos a matriz de rotação em torno do eixo x como:

\begin{bmatrix}x' \\y' \\z' \\1\end{bmatrix}=\begin{bmatrix}1 & 0 & 0 & 0 \\0 & \cos{\theta} & -\sin{\theta} & 0 \\0 & \sin{\theta} & \cos{\theta} & 0 \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\y \\z \\1\end{bmatrix}

Escrevemos a matriz de rotação em torno do eixo y como:

\begin{bmatrix}x' \\y' \\z' \\1\end{bmatrix}=\begin{bmatrix}\cos{\theta} & 0 & \sin{\theta} & 0 \\0 & 1 & 0 & 0 \\-\sin{\theta} & 0 & \cos{\theta} & 0 \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\y \\z \\1\end{bmatrix}

Escrevemos a matriz de rotação em torno do eixo z como:

\begin{bmatrix}x' \\y' \\z' \\1\end{bmatrix}=\begin{bmatrix}\cos{\theta} & -\sin{\theta} & 0 & 0 \\\sin{\theta} & \cos{\theta} & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\y \\z \\1\end{bmatrix}

Matriz de Translação

Escrevemos a matriz de translação em termos de coordenadas (d_{x}, d_{y}, d_{z}) como:

\begin{bmatrix}x' \\y' \\z' \\1\end{bmatrix}=\begin{bmatrix}1 & 0 & 0 & d_{x} \\0 & 1 & 0 & d_{y} \\0 & 0 & 1 & d_{z} \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x \\y \\z \\1\end{bmatrix}

Pipeline Gráfico

Passamos a explicitar Espaço do Objeto, Espaço do Universo, Espaço da Câmera, Espaço de Recorte, Espaço Canônico e Espaço da Tela, além da Transformação Objeto-UniversoTransformação Universo-CâmeraTransformação Câmera-RecorteTransformação Canônica-Tela.

Espaço do Objeto

Espaço onde se dá a modelagem de objetos. Infinito em todas as direções, apenas especifica as dimensões do objeto e não onde eles se localizam na cena.

Espaço do Universo

Onde os objetos se reúnem. Este espaço congrega os objetos em um sistema de coordenadas, sendo capaz de montar a cena. A fim de definir que porção da cena se deseja visualizar, somos levados ao espaço da câmera.

Espaço da Câmera

No espaço da câmera, todos os objetos precisam ser transformados para um novo sistema de coordenadas, a fim de serem visualizados. Com parâmetros como a posição da câmera (EYE) no espaço do universo, o vetor direção (AT), e o vetor UP, que indica o lado de cima da câmera, somos capazes de montar o espaço da câmera.

Espaço Recorte

Tendo os pontos do espaço da câmera, se faz necessário descartar todos os pontos que não são vistos, tendo vista a eficiência da renderização. Assim, projeta-se tudo em um viewplane e descarta-se o que não for visível. Para tanto, escolhe-se que tipo de projeção se utilizará, que pode ser ortogonal ou perspectiva. A imagem abaixo ilustra as "fronteiras". Fora do "cubo" ou da "pirâmide", nada é visualizado e, portanto, descartado.

Espaço Canônico

É no espaço canônico que as matrizes de todos os objetos são convertidos para coordenadas homogêneas, de maneira que, devido a uma distorção dos vértices, objetos mais próximos da câmera aparecem maiores e objetos distantes, aparecem menores.

Espaço da Tela

Agora que todas as coordenadas estão homogêneas, podemos transferir informação para a tela, multiplando a matriz de coordenadas homogêneas pela matriz view port.

Transformação Objeto-Universo

A matriz responsável por levar informação do espaço dos objetos para o universo, é denominada Model, e é resultado de sucessivas multiplicações de matrizes de Escala, Rotação e Translação.

Transformação Universo-Câmera

Através da matriz View, que aplica mais uma rotação e translação, transferimos o centro da cena para a posição da câmera.

A partir dos parâmetros EYEAT e UP conseguimos determinar o sistema de coordenada da câmera (x_{c}, y_{c}, z_{c}). O eixo é oposto a AT, isto é, fazemos a diferença entre EYE - AT. A direção x_{c} é obtida pelo produto vetorial de AT por UP e y_{c} pelo produto vetorialx_{c}z_{c}. Note que UP não é necessáriamente ortogonal a AT .

z_{c} = \frac{EYE - AT}{||EYE-AT||}

x_{c} = \frac{UP \times z_{c}}{||UP \times z_{c}||}

 y_{c} = z_{c} \times x_{c}

Transformação Câmera-Recorte

Feita pela matriz Projection, esta transformação é  feita pela multiplicando-se da matriz abaixo. Note que ela só depende da distância da câmera (d) até o volume de projeção (ortogonal ou perspectivo).

M_{pt}=\begin{bmatrix}1 & 0 & 0 & d_{x} \\0 & 1 & 0 & d_{y} \\0 & 0 & 1 & d_{z} \\0 & 0 & {\displaystyle-\frac{1}{d}}& 1\end{bmatrix}

Transformação Canônica-Tela

Por fim, para aplicar a última tranformação, é necessário fazer uma escala de -1 no eixo y, uma escala w/2 e h/2 nos eixos x e y, respectivamente, e uma translação de (w-1)/2 em x e (h-1)/2 em y.

Abaixo as matrizes responsáveis.

\begin{bmatrix}x' \\y' \\z' \\1\end{bmatrix}=
=\begin{bmatrix}1 & 0 & 0 & {\displaystyle\frac{w-1}{2}} \\0 & 1 & 0 & {\displaystyle\frac{h-1}{2}} \\0 & 0 & 1 & 0 \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}{\displaystyle\frac{w}{2}} & 0 & 0 & 0 \\0 & {\displaystyle\frac{w}{2}} & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}1 & 0 & 0 & 0 \\0 & -1 & 0 & 0 \\0 & 0 & 1 & 0 \\0 & 0 & 0 & 1\end{bmatrix}\begin{bmatrix}x\\y\\z\\1\end{bmatrix}

Capturas de Tela

A primeira imagem mostra um modelo de cubo e a segunda, de um macaquinho. Respectivamente, cube.objmonkey_head2.obj.

Dificuldades

Gostaria de dizer que foram poucas, mas as dificuldades foram muitas. Primeiro, prazo. O prazo para este projeto foi extendido, o que vejo como grande consideração do professor para com a turma e, na mesma linha, os prazos de outras disciplinas também. Então tempo e energia (vontade de continuar vivo), foram cruciais para que se finalizasse este projeto.

O Loader. Brincadeiras a parte, os problemas envolveram basicamente o loader de arquivos *.obj, que, como detalhado na descrição do projeto, seria fornecido e eu não o encontrei. Vergonhosamente, copiei o loader e todas as suas dependências de um projeto pronto de períodos anteriores.

O GLM. Implementar matrizes parece muito simples na teoria com o GLM. Entretando, aliado ao problema do loader e da falta de tempo, não foi possível deixar a implementação perfeita, de maneira que durante a rotação algumas arestas saem do lugar, como é possível ver nas capturas de tela, dando esta impressão "bugada".

Melhorias

Este projeto poderia ser melhorado revisando-se os métodos responsáveis pela passagem de coordenadas dos vértices, afim de manter um equilibrio nas aretas durante a rotação.

Um loader proprietário também poderia ser criado afim de simplificar o problema, utilizando somente implementação estritamente necessária.

Conclusão

Embora atrasado, com loader copiado e aspecto-geral bugado, este projeto me proporcionou dias de aprendizado acelerado e ininterrupto. Não é objeto de grande orgulho neste momento, entretanto, definitivamente pretendo concluí-lo durante as férias e agradeço ao Mestre por tê-lo sugerido como parte da avaliação. Nos vemos período que vem. 🙂