# OpenGL

O OpenGL (Open Graphics Library) é uma API livre utilizada na computação gráfica, para desenvolvimento de aplicativos gráficos, ambientes 3D, jogos, entre outros. Assim como Direct3D ou Glide, é uma API (Application Programming Interface), termo usado para classificar uma biblioteca de funções específicas disponibilizadas para a criação e desenvolvimento de aplicativos em determinadas linguagens de programação. A OpenGL foi produzida com C e C++ em mente, mas pode ser utilizada para diversas outras com um alto nível de eficiência.

## História do OpenGL

Na década de 80, cada fabricante de hardware tinha seu próprio conjunto de instruções para desenho de gráficos 2D e 3D. Construir aplicações com essas tecnologias que suportassem vários hardwares era um verdadeiro desafio. O esforço era constantemente duplicado e havia pouco espaço para companhias menores e sem capital para tamanho investimento. Isso ainda diminuía consideravelmente a compatibilidade com as placas disponíveis no mercado.
Em meados dos anos 80, um padrão surgiu na indústria, chamado PHIGS (sigla de Programmer’s Hierarchical, Graphics System) e começou a ser adotado por grandes fabricantes da época. Entretanto, embora tenha sido reconhecido por entidades como a ANSI e a ISO, o padrão começou a ser considerado complicado e desatualizado.
No final dos anos 80, a Silicon Graphics Inc. (SGI), desenvolveu um padrão chamado IRIS GL, que não só começou a chamar atenção da indústria, como também foi considerado o estado da arte de uma API gráfica. Consideravelmente mais fácil de usar, a API começou a tornar-se um padrão de fato na indústria.
Entretanto, grandes empresas produtoras do hardware, como a Sun Microsystems e a IBM, ainda eram capazes de fabricar hardware adotando o padrão PHIGS. Isso levou a SGI a tomar uma decisão para que a adoção de sua API fosse impulsionada: torná-la um padrão público, para que todos os fabricantes de hardware pudessem adotá-lo.
A SGI considerou que a API IRIS GL continha muito código proprietário e, portanto, não poderia ser aberta. Ela também lidava com questões não tão relacionadas ao desenho 2D e 3D, como gerenciamento de janelas, teclado e mouse. Ainda assim, era do interesse da Silicon Graphics manter os seus antigos clientes comprando seu hardware.
Como um resultado disso, o padrão OpenGL foi desenvolvido a partir de 1991, e lançado em Janeiro de 1992. Desde 1992, o padrão é mantido pelo ARB (Architecture Review Board), um conselho formado por empresas como a 3DLab, ATI, Dell, Evans&Sutherland, HP, IBM, Intel, Matrox, NVIDIA, Sun e, logicamente, a Silicon Graphics. O papel desse conselho é manter a especificação e indicar quais recursos serão adicionados a cada versão. A versão mais atual do OpenGL até hoje é a 4.6.
Os projetistas do OpenGL sabiam de duas coisas. A primeira é que fabricantes de hardware gostariam de adicionar recursos próprios, sem que tivessem que esperar para esses recursos estarem oficialmente aceitos no padrão. Para resolver esse problema, eles incluíram uma maneira de estender o OpenGL. Muitas vezes, essas extensões são interessantes o suficiente para que outros vendedores de hardware as adotem. Então, quando elas são consideradas suficientemente abrangentes, ou suficientemente importantes, a ARB pode promovê-las para que façam parte do padrão oficial. Praticamente todas as modificações recentes do padrão começaram como extensões, a grande maioria devido ao mercado de jogos.
Em segundo lugar, os projetistas também sabiam que muitos hardwares não seriam poderosos o suficiente para abraçar todo o padrão. Por isso, também incluíram extensões de software, que permitiam emular essas funcionalidades. Isso resolvia um problema sério que ocorria com a Iris: o da aplicação simplesmente não rodar pela falta de um ou outro recurso.
A indústria de jogos, em particular, começou a adotar cada vez mais a API Direct3D como padrão devido à sua quantidade de opções para desenvolvimento de efeitos visuais, e ao fato de que a maior parte dos jogadores utiliza o sistema Windows em seu PC. A maior parte dos games mais recentes e complexos graficamente utiliza a biblioteca para representar ambientes densos, extensos e bonitos, com um grau de realismo crescente, aproveitando o lançamento do DirectX 10, que abriu novas possibilidades de desenvolvimento gráfico.
A OpenGL ainda é relativamente inferior nesse aspecto, mas sua versatilidade está novamente se tornando seu ponto forte: hoje em dia, as produtoras de games visam aumentar cada vez mais o número de cópias vendidas de seus novos títulos, adaptando games de PC para os consoles de última geração. A API Direct3D não é muito flexível neste sentido, então a biblioteca OpenGL está tomando um espaço cada vez maior, devido à sua grande adaptabilidade.
O mundo dos games é bastante turbulento e tendências de desenvolvimento vêm e vão com uma frequência bastante grande. A popularidade de uma API depende da recepção de cada uma das tecnologias em suas aplicações mais direcionadas ao público em geral, e a OpenGL foi, é e será uma das opções mais importantes nesta acirrada competição.

## Arquitetura do OpenGL

O OpenGL é um conjunto de algumas centenas de funções, que fornecem acesso a praticamente todos os recursos do hardware de vídeo. Internamente, ele age como uma máquina de estados, que de maneira bem específica dizem ao OpenGL o que fazer. Usando as funções da API, você pode ligar ou desligar vários aspectos dessa máquina, tais como a cor atual, se transparência será usada, se cálculos de iluminação devem ser feitos, se haverá ou não o efeito de neblina, e assim por diante. É importante conhecer cada um desses estados, pois é comum a obtenção de resultados indesejados simplesmente por deixar um ou outro estado definido de maneira incorreta.
O OpenGL também foi projetado para funcionar mesmo que a máquina que esteja exibindo os gráficos não seja a mesma que contém o programa gráfico. Pode ser o caso dos dois computadores estarem conectados em rede e, nesse caso, o computador que gera os comandos é chamado cliente, enquanto o que recebe e executa os comandos de pintura é chamado de servidor. O formato da transmissão desses comandos (chamado protocolo) também é padronizado, então é possível que duas máquinas com sistemas operacionais e hardwares diferentes se comuniquem dessa forma. Se o OpenGL não está sendo executado numa rede, o computador é considerado ao mesmo tempo cliente e servidor.
Essa decisão de design tem uma consequência muito importante: os comandos do OpenGL não são imediatamente jogados para o hardware. Eles são agrupados para serem enviados mais tarde - o que não só melhora o uso da rede, mas também abre margem para outras otimizações. Por consequência, um erro comum de muitos programadores é tentar medir o tempo levado pelos comandos de pintura simplesmente adicionando funções antes e depois de um comando (ou conjunto de comandos) o que, nessa arquitetura, certamente gerará resultados inválidos.
Afinal, não há garantias de que os comandos serão imediatamente executados, e, o que acaba sendo medido com essa estratégia, é a velocidade que o OpenGL armazena os comandos para futura execução. Forçar a execução dos comandos também é uma estratégia ruim, já que com isso muitas otimizações são simplesmente desprezadas. Nessa arquitetura, a forma mais confiável de se medir a performance é através de software especial, que pode ser baixado na própria página do OpenGL

## Rendering Pipeline

O núcleo do OpenGL é conhecido como “rendering pipeline” ou dutos de renderização. É importante notar que o OpenGL lida tanto com o desenhos na forma vetorial, definidos por vértices, como com mapas de bits, definidos pixel-a-pixel. Os principais elementos desse duto estão descritos abaixo:
* Listas de exibição (Display lists): Todos os dados, sejam de vértices pertencentes a geometrias ou pixels, podem ser salvos lista de exibição para uso atual ou posterior;
* Avaliadores (evaluators): Todas as primitivas geométricas, no OpenGL são descrita por vértices. Curvas e superfícies paramétricas podem ser descritas por fórmulas - usadas na construção dos vértices. Quem faz essa avaliação são os avaliadores.
* Operações pré-vértices: Para os dados de vértices, as operações pré-vértice convertem os vértices em primitivas de desenho. Nessa etapa, cada vértice é convertido em matrizes 4×4, então cálculos são realizados para que sejam convertidos do espaço 3D para as coordenadas de tela. Essa etapa ainda realiza operações de cálculos de textura, iluminação, materiais, etc. de acordo com quais estados tenham sido habilitados;
* Montagem de primitivas (primitive assembly): A fase de montagem de primitivas preocupa-se com a eliminação das partes da geometria que caiam fora do plano. Essa fase também aplica os cálculos de perspectiva, fazendo os objetos distantes parecerem menores em relação a objetos próximos. Se cálculos de abate (culling) estiverem ativos, partes dos objetos podem ser desprezadas durante essa fase. É aqui também que se decide se um polígono deve ser desenhado através de pontos ou linhas;
* Operações com pixels: Enquanto os dados geométricos seguem pelo duto de renderização, os mapas de pixels passam por diferentes tipos de transformação. Primeiramente, os pixels são descompactados de acordo com o seu número de componentes, então eles têm sua escala ajustada, seu formato final é calculado, parte de sua área é recortada e então são enviados para o passo chamado rasterização ("rasterization").
* Montagem de texturas (texture assembly): Permite a aplicação de imagens como texturas nas geometrias, para que elas pareçam mais realistas. Algumas implementações do OpenGL podem ter recursos especiais para acelerar esse processo;
* Rasterização (Rasterization): Transforma todos os dados em fragmentos. Cada fragmento é um quadrado que corresponde a pixels no quadro de armazenamento auxiliar (framebuffer). Padrões de linhas e polígonos, largura da linha, tamanho do ponto, sombreamento ("shading"), cálculos de cobertura e anti-serrilhado (antialiasing) são todos levados em conta durante essa fase. Cores e valores de profundidade são considerados para cada fragmento;
* Operações sobre fragmentos (Fragment Operations): Finalmente, operações finais são aplicadas aos fragmentos, tais como recortes, operações de máscaras de bits, como mistura (blending), são aplicadas. Então, os pixels são finalmente calculados e são encaminhados para desenho.

## Outras bibliotecas relacionadas ao OpenGL

O OpenGL fornece um conjunto poderoso de comandos, mas restrito apenas ao desenho. Várias bibliotecas existem para facilitar a manipulação de outros aspectos da aplicação, como as seguintes:
* OpenGL Utility Library (GLU): Fornece diversas funções para auxiliar na montagem de matrizes de visualização e projeção, desenho de superfícies e imagens 3D. Essa biblioteca é fornecida juntamente com as implementações do OpenGL e todas as rotinas dessa biblioteca tem o prefixo glu.
* Cada ambiente de janelas tem uma biblioteca de extensão do OpenGL. Por exemplo, o sistema X possui o GLX, enquanto o Windows fornece a extensão WGL e já o Mac OS X fornece o CGL.
* OpenGL Utility Toolkit (GLUT): É um toolkit que abstrai o sistema de janelas, fornecendo uma interface simples para a criação de uma aplicação OpenGL.

## Outras características importantes

* O OpenGL trabalha com a medida de ângulos em graus e não em radianos, como ocorre com a maioria das linguagens;
* Cada componente de cor no OpenGL é normalmente definido por um número de ponto flutuante, que varia de 0 até 1, e não um número inteiro de 0 até 255;
* As coordenadas gráficas no OpenGL seguem o eixo cartesiano. Assim, o número da linha é decrescente, e não crescente, como em boa parte das implementações.
* Matrizes no OpenGL são calculadas com base nas colunas, e não nas linhas.