Skip to content

Latest commit

 

History

History
398 lines (308 loc) · 14.8 KB

README.md

File metadata and controls

398 lines (308 loc) · 14.8 KB

Projeção


Objetivos

  1. Entender a transformação de uma cena em 3D para 2D
  2. Conhecer as matrizes de projeção ortogonal e perspectiva
  3. Entender o funcionamento da projeção em OpenGL

Relembrando o pipeline gráfico


Projeção em Computação Gráfica

  • Transformações de projeção são aquelas capazes de representar pontos ou objetos a partir de um espaço tridimensional (uma cena) em um plano bidimensional (uma imagem).
  • Trata-se de (i) transformar o volume de visualização no volume de visualização canônico (cubo com raio 1) e (ii) guardar as coordenadas z dos vértices no z-buffer ::: figure .layout-split-2.no-margin :::
  • Essa transformação é feita por meio de uma matriz que vai multiplicar as coordenadas dos vértices, assim como as outras transformações que vimos

Elementos da projeção

  1. Plano de projeção:
    • Definido pelo sistema de coordenadas da câmera
  2. Raios de projeção:
    • Ligam um ponto no espaço 3D à imagem 2D representada no plano de projeção
  3. Centro de projeção:
    • Ponto fixo na cena de onde todos os raios de projeção surgem


Projeção Paralela


Projeção Paralela

  • Centro de projeção se encontra no infinito
  • Raios de projeção são paralelos entre si
  • Tamanho relativo em cada eixo é preservado
  • Linhas paralelas permanecem paralelas
  • Existem subtipos de projeção paralela em que o ângulo de incidência dos raios de projeção varia

Projeção Paralela, Ortogonal

  • Projeção ortogonal
    • Ângulo dos raios no plano de projeção = 90º

Projeção Ortogonal em OpenGL

::: figure .layout-split-2.no-margin

void glOrtho(double left,  //l
             double right, //r
             double bottom,//b
             double top,   //t
             double near,  //n
             double far);  //f
\begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{-2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix}
::: - Queridíssimo `glOrtho` ([referência](http://earth.uni-muenster.de/~joergs/opengl/glOrtho.html)) - A função multiplica a matriz corrente por uma matriz da forma acima ⤴️ - Devemos multiplicar a matriz **de projeção (`GL_PROJECTION`)**

Exemplo: projeção no hello world

::: figure .layout-split-3.hello-world-code.compact-code

// define a projeção
glOrtho(0, 100, 0, 100, -1, 1);
// ...
// desenha
glBegin(GL_TRIANGLE_STRIP);
    glVertex3f(20, 20, 0);//v0
    glVertex3f(80, 20, 0);//v1
    glVertex3f(80, 80, 0);//v2
    glVertex3f(20, 80, 0);//v3
glEnd();

::: figure .no-margin flex: 1; display: flex; flex-direction: column; justify-content: flex-start; font-size: 15px;

\begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{-2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix}=
\begin{bmatrix} \frac{2}{100} & 0 & 0 & -\frac{100}{100} \\ 0 & \frac{2}{100} & 0 & -\frac{100}{100} \\ 0 & 0 & \frac{-2}{2} & -\frac{0}{2} \\ 0 & 0 & 0 & 1 \end{bmatrix}=
\begin{bmatrix} 0.02 & 0 & 0 & -1 \\ 0 & 0.02 & 0 & -1 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix}
:::

::: figure .picture-steps.clean.opacity-only padding: 0; align-self: center; font-size: 16px;

v^\prime = M \times v
\begin{bmatrix} v^\prime_x \\ v^\prime_y \\ v^\prime_z \\ 1 \end{bmatrix} = \begin{bmatrix} 0.02 & 0 & 0 & -1 \\ 0 & 0.02 & 0 & -1 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} v_x \\ v_y \\ v_z \\ 1 \end{bmatrix}
\begin{bmatrix} v^\prime_x \\ v^\prime_y \\ v^\prime_z \\ 1 \end{bmatrix} = \begin{bmatrix} 0.02 & 0 & 0 & -1 \\ 0 & 0.02 & 0 & -1 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} 20 \\ 20 \\ 0 \\ 1 \end{bmatrix}
\begin{bmatrix} -0.6 \\ -0.6 \\ 0 \\ 1 \end{bmatrix} = \begin{bmatrix} 0.02 & 0 & 0 & -1 \\ 0 & 0.02 & 0 & -1 \\ 0 & 0 & -1 & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \times \begin{bmatrix} 20 \\ 20 \\ 0 \\ 1 \end{bmatrix}
:::

::: figure . align-self: center; font-size: 14px; margin: 3em 0 0 16em

v^\prime_0 = \begin{bmatrix} -0.6 \\ -0.6 \\ 0 \\ 1 \end{bmatrix}
v^\prime_1 = \begin{bmatrix} 0.6 \\ -0.6 \\ 0 \\ 1 \end{bmatrix}
v^\prime_2 = \begin{bmatrix} 0.6 \\ 0.6 \\ 0 \\ 1 \end{bmatrix}
v^\prime_3 = \begin{bmatrix} -0.6 \\ 0.6 \\ 0 \\ 1 \end{bmatrix}
:::

Projeção "Padrão"

  • Se você não definir uma projeção, existe a matriz identidade previamente carregada
  • Isso é equivalente a glOrtho(-1, 1, -1, 1, -1, 1) (exceto pelo -1): ::: figure .no-margin display: flex; flex-direction: row; justify-content; center
    \begin{bmatrix} \frac{2}{r-l} & 0 & 0 & -\frac{r+l}{r-l} \\ 0 & \frac{2}{t-b} & 0 & -\frac{t+b}{t-b} \\ 0 & 0 & \frac{-2}{f-n} & -\frac{f+n}{f-n} \\ 0 & 0 & 0 & 1 \end{bmatrix}=
    \begin{bmatrix} \frac{2}{1+1} & 0 & 0 & -\frac{1-1}{1+1} \\ 0 & \frac{2}{1+1} & 0 & -\frac{1-1}{1+1} \\ 0 & 0 & \frac{-2}{1+1} & -\frac{1-1}{1+1} \\ 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}
    :::

E esse z negativo?

::: figure .full-width display:flex; justify-content: space-around; :::

O OpenGL nos permite trabalhar right-handed ↖️,
mas ele projeta num sistema left-handed ↗️


Projeção Paralela, Isométrica

  • A cena é orientada em 45º relativo ao plano de projeção
  • Também podemos usar glOrtho, mas vamos precisar "movimentar a câmera" usando gluLookAt (veremos logo mais)

Projeção Perspectiva


Projeção Perspectiva

  • A projeção perspectiva mapeia os pontos no plano de projeção ao longo dos raios de projeção que emanam de um centro de projeção
  • Características:
    1. Objetos mais próximos ao plano de projeção são maiores
    2. Linhas paralelas se encontram em pontos de fuga
    3. Aparência semelhante ao modelo do nosso olho

Mesmo objeto, projeções diferentes


Objetos 3D

Façamos uma breve digressão...


O pulo do gato da raposa

  • Um objeto tridimensional é formado por várias faces (polígonos) adjacentes que podem estar no mesmo plano ou não


Exemplo de objetos 3D

Para desenhar um cubo em vez de um quadrado, basta desenhar 6 faces em vez de 1

::: figure .layout-split-2

glBegin(GL_QUADS);
  // Cima (y = +1)
  glVertex3f( 1, 1, -1); glVertex3f(-1, 1, -1);
  glVertex3f(-1, 1,  1); glVertex3f( 1, 1,  1);
  // Baixo (y = -1)
  glVertex3f( 1, -1,  1); glVertex3f(-1, -1,  1);
  glVertex3f(-1, -1, -1); glVertex3f( 1, -1, -1);
  // Direita (x = +1)
  // ...

:::


Roubando com o FreeGLUT

  • O FreeGLUT possui algumas funções para desenho de objetos tridimensionais:

    1. glutSolidTeapot, glutWireTeapot

      Solid ~ desenha polígonos preenchidos

      Wire ~ desenha apenas contornos

  • Referência das funções


Formas 3D do GLUT

::: figure .layout-split-2.full-width


Projeção Perspectiva

  • Voltando ao tema de hoje...

glFrustum (referência)

  • Assinatura da função:
    void glFrustum(double left,   double right,
                   double bottom, double top,
                   double near,   double far);
    • near e far devem ser positivos e near < far

Projeção perspectiva no OpenGL

  • \begin{bmatrix} \frac{2n}{r-l} & 0 & \frac{r+l}{r-l} & 0 \\ 0 & \frac{2n}{t-b} & \frac{t+b}{t-b} & 0 \\ 0 & 0 & \frac{f+n}{f-n} & \frac{2fn}{f-n} \\ 0 & 0 & -1 & 0 \end{bmatrix}
    glFrustum multiplica a matriz corrente por uma matriz da forma ➡️
    glFrustum(left, right,  // l, r
              bottom, top,  // b, t
              near, far);   // n, f
  • Lembre-se: a matriz de projeção (glOrtho ou glFrustum) deve ser colocada na pilha de matrizes de projeção do OpenGL:

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    glFrustum(-1, 1, -1, 1, 1, 20);

Exemplo Projeção Ortogonal vs Perspectiva

  • Pressionar barra de espaço para alternar de projeção perspectiva para ortogonal


gluPerspective (referência)

  • Não é muito intuitivo configurar a perspectiva usando glFrustum
  • Uma forma mais comum para configurar perspectiva é usando dois parâmetros:
    1. Um ângulo para o campo de visão
    2. Razão de aspecto (largura / altura)

gluPerspective - exemplo

  • A biblioteca GLU (OpenGL Utilities) contém uma função para isso, o gluPerspective:
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    // fovy, aspectRatio, nearZ, farZ
    gluPerspective(45.0f, 4.0f/3.0f, 1, 20);
  • O gluPerspective substitui o uso de glFrustum, já que ele gera uma matriz de transformação perspectiva da mesma forma, porém usando outros tipos de parâmetros
  • Campo de visão (fov, ou field of view)
    • Determina o quanto queremos enxergar da cena
    • Para aplicações interativas, tipicamente algo entre 45º e 60º

Diminuindo o FoV


Razão de aspecto

  • Calculada pela divisão da largura pela altura
  • Deve ser a mesma razão de aspecto da janela/tela em que estamos desenhando para que não haja distorção

gluLookAt

  • Além de configurar a projeção que queremos (via glOrtho, glFrustum, gluPerspective), queremos também poder posicionar e mirar nossa câmera virtual

  • É uma transformação de visualização - ou seja, usamos a pilha de matrizes GL_MODELVIEW


gluLookAt - assinatura

void gluLookAt(double eyeX, eyeY, eyeZ            // posição do olho
               double centerX, centerY, centerZ   // para onde olhamos
               double upX, upY, upZ);             // onde fica "para cima"
  • A transformação de visualização deve acontecer ANTES das transformações de modelo
    • Ou seja, gluLookAt(...) deve ser chamada na função desenhaCena antes de começarmos a desenhar os objetos da cena

Referências