Projeto Virtual Worlds

Computação Gráfica 3D em C

O que é e o que não é o OpenGL

Antes de continuar debulhando algorítmos e funções é interessante definir o que OpenGL pode fazer o que não pode. Alguns de vocês pode ter o conteito de que OpenGL é uma biblioteca mágica que engloba todas as funcionalidades possíveis para o desenho, em tempo real, de qualquer efeito ou recurso necessário para obter uma animação realista tridimensional. Se for assim, ficará desapontado… Grande parte do que pode ser visto em jogos, por exemplo, é criado por rotinas independentes do OpenGL (ou do DirectX, no caso do Windows)…

Em resumo, OpenGL é uma biblioteca que permite posicionar pontos no espaço tridimensional e projetá-los no espaço bidimensional correspondente a uma janela ou a tela do computador. Ele também contém alguns recursos interessantes como texturas. Ele não contém rotinas para renderizar sombras, iluminação, detecção de colisões, “radiosidade”, oclusão, … Tudo isso é feito fora do contexto do OpenGL ou, no máximo, no interior de rotinas especializadas chamadas de shaders − mesmo assim, são rotinas definidas pelo programador!

Você viu, anteriormente, que existem diversos sistemas de coordenadas usadas pelo OpenGL. Mas, o que ocorre, na realidade, é que só existem 2 sistemas: World CoordinatesScreen Coordinates. O segundo é a projeção do primeiro no plano xy. Para facilitar a vida criam-se outros sistemas com o auxílio de transformações lineares:

Transformações lineares.

Transformações lineares.

No OpenGL anterior à versão 3, as matrizes de transformação mostradas acima eram codificadas em funções do próprio OpenGL… Isso não existe mais. Para posicionar e transformar os objetos definidos no object space para o Screen Space temos que, explicitamente, definir as matrizes ModelView e Projection e passá-las para o vertex shader. Isso significa que esses “espaços” são construções meramente matemáticas e já fazem parte do OpenGL. Um vertex shader típico seria:

#version 430 core

layout(location=0) in vec3 vpos;

uniform mat4 modelviewMatrix;
uniform mat4 projectionMatrix;

void main()
{
  gl_Position = projectionMatrix * modelviewMatrix * vec4(vpos, 1.0);
}

Onde modelviewMatrixprojectionMatrix são definidas no programa host. A primeira transforma o objeto definido no object space para o view space (ou camera space) e a segunda faz a projeção do espaço tridimensional do view space para o espaço bidimensional do Screen space.

Note também que OpenGL não lida, diretamente, com a figura geométrica como um todo… Ao definir um triângulo, definimos apenas as características dos vértices. As informações de preenchimento e contorno dos lados são interpolações lineares baseadas nos atributos dos vértices. Interpolações lineares seguem a equação abaixo:

\displaystyle \dot{p}'=(1-n)\dot{p}_1+n\dot{p}_2,\quad n \in [0,1]

Por causa dessa interpolação, OpenGL não garante que duas placas de vídeo desenharão triângulos do mesmo jeito. Praticamente tudo o que OpenGL garante é que a sequência dos comendos será obedecida… Ao mandar OpenGL desenhar um triângulo ele o fará, mas se as bordas serão desenhadas antes do preenchimento, ou vice-versa, isso não é garantido.

Outra garantia do OpenGL: Uma vez definido o viewport (a área retangular que será visível no plano da tela), os limites de coordenadas são padronizados em [-1, 1]. Ou seja, o canto inferior esquedo da área visível é (-1,-1) e o canto superior direito (1,1). Ainda, o centro da área visível é a origem do sistema de coordenadas (0,0)… Observe, de novo, como defini o triângulo no exemplo do post anterior… Lá, a sequência de coordenadas é definida no sentido anti-horário e a primeira coordenada é (0, 0.707, -1). Ou seja, o topo do triângulo está a pouco mais de 70% do caminho entre o centro da janela e o topo. Ao mesmo tempo, os outros dois pontos são definidos com suas coordenadas X como -0.5 e 0.5, respectivamente:

Saída do código de exemplo.

Saída do código de exemplo.

Assim, o escalonamento é importante. Ao definir seu mundo em uma escala, você será obrigado a modificá-la para caber no padrão do OpenGL (e isso pode ser feito na matriz modelview). E, é claro, dependendo do aspect ratio, esse exemplo ai em cima pode ficar distorcido… No exemplo criei uma janela de aspect ratio 16:9, já que esse é o formato de meu monitor de vídeo… Ou seja, nesse formato é garantido que o pixel terá o formato “quadrado” esperado. Se tivesse escolhido uma resolução de 640×480, ou seja, com aspect ratio de 4:3, o triângulo seria mais achatado, horizontalmente.

 

Anúncios

Deixe um comentário

Faça o login usando um destes métodos para comentar:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s