O OpenGL possui quatro versões principais diferentes, sem contar as versões para dispositivos móveis e sistemas incorporados (OpenGL | ES) e a Web via JavaScript (WebGL). Assim como o Direct3D 11 tem uma maneira diferente de fazer as coisas que o Direct3D 8, o OpenGL 3 tem uma maneira diferente de fazer as coisas que o OpenGL 1. A grande diferença é que as versões do OpenGL são apenas complementos das versões mais antigas (mas não inteiramente).
Além das diferentes edições e versões do OpenGL, o OpenGL principal também adicionou o conceito de perfis. Ou seja, o perfil de compatibilidade (que habilita o suporte a APIs de versões mais antigas) e o perfil principal (que desabilita essas APIs antigas). Coisas como glBegin
simplesmente não funcionam quando você usa o Perfil Principal, mas funcionam quando você usa o Perfil de Compatibilidade (que é o padrão).
Como mais uma complicação importante, algumas implementações do OpenGL (como a da Apple, entre outras) só habilitarão os recursos mais recentes do OpenGL quando você estiver usando o Perfil principal. Isso significa que você deve parar de usar APIs mais antigas para usar APIs mais recentes.
Você acaba com vários cenários muito confusos para os tutoriais:
- O tutorial é antigo e usa apenas APIs obsoletas.
- O tutorial é novo e bem escrito e usa apenas APIs compatíveis com Core.
- O tutorial é novo, mas comete o erro de assumir que você está trabalhando com um driver que habilita todas as APIs no modo de compatibilidade e combina livremente APIs novas e antigas.
- O tutorial é para uma edição diferente do OpenGL, como o OpenGL | ES, que não suporta nenhuma das APIs antigas, em nenhuma versão.
Coisas como glBegin
fazem parte do que às vezes é chamado de API de modo imediato. Isso também é super confuso, porque não existe um modo retido no OpenGL e o "modo imediato" já tinha uma definição diferente nos gráficos. É muito melhor referir-se a essas APIs do OpenGL 1.x, pois elas estão obsoletas desde o OpenGL 2.1.
A API 1.x do OpenGL enviava imediatamente vértices para o pipeline de gráficos nos velhos tempos. Isso funcionou bem quando a velocidade do hardware que renderizou os vértices estava aproximadamente no mesmo nível da velocidade da CPU que gerava os dados do vértice. O OpenGL naquela época descarregava a rasterização do triângulo e não muito mais.
Hoje em dia, a GPU pode vasculhar um grande número de vértices em velocidades muito altas enquanto executa uma transformação avançada de vértices e pixels, e a CPU simplesmente não consegue acompanhar remotamente. Além disso, a interface entre a CPU e a GPU foi projetada com base nessa diferença de velocidade, o que significa que nem é possível enviar vértices para a GPU, um de cada vez.
Todos os drivers GL devem emular glBegin
alocando internamente um buffer de vértice, colocando os vértices enviados glVertex
nesse buffer e enviando esse buffer inteiro em uma única chamada de desenho quando glEnd
é chamado. A sobrecarga dessas funções é muito maior do que se você mesmo atualizasse o buffer de vértice, e é por isso que alguma documentação (muito equivocadamente!) Se refere a buffers de vértice como "uma otimização" (não é uma otimização; é a única maneira de realmente fale com a GPU).
Existem várias outras APIs que foram descontinuadas ou obsoletas no OpenGL ao longo dos anos. O chamado oleoduto de função fixa é outra dessas peças. Alguma documentação ainda pode usar esse pipeline ou misturar-se ao pipeline programável. O pipeline de função fixa vem dos velhos tempos em que as placas gráficas codificavam toda a matemática usada para renderizar cenas em 3D e a API do OpenGL limitava-se a definir alguns valores de configuração para essa matemática. Atualmente, o hardware possui muito pouca matemática codificada e (assim como a sua CPU) executa programas fornecidos pelo usuário (geralmente chamados de shaders).
Mais uma vez, os drivers devem emular a API antiga, pois os recursos de função fixa simplesmente não estão mais presentes no hardware. Isso significa que o driver possui vários shaders de compatibilidade incorporados que executam a matemática antiga a partir dos dias de função fixa que são usados quando você não fornece seus próprios shaders. As antigas funções do OpenGL que modificam esse antigo estado de função fixa (como a antiga API de iluminação do OpenGL) estão na verdade usando recursos modernos do OpenGL, como buffers uniformes, para alimentar esses valores com os sombreadores de compatibilidade do driver.
Os drivers compatíveis com a compatibilidade precisam fazer muito trabalho nos bastidores para descobrir quando você está usando esses recursos obsoletos e certificando-se de combiná-los com os recursos modernos sem problemas, o que aumenta a sobrecarga e complica muito o driver. Esse é um dos motivos pelos quais alguns drivers o obrigam a permitir que o Core Profile obtenha recursos mais novos; simplifica muito os internos de drivers, não precisando oferecer suporte a APIs antigas e novas usadas simultaneamente.
Muita documentação pode recomendar que você comece com as APIs antigas simplesmente por serem mais fáceis de começar. O Direct3D resolveu esse problema para iniciantes, oferecendo uma biblioteca complementar ( DirectX Tool Kit ) que fornece APIs de desenho mais simples e shaders pré-escritos, que podem ser livremente misturados ao uso bruto do Direct3D 11 à medida que sua experiência aumenta. Infelizmente, a comunidade mais ampla do OpenGL mantém o Perfil de Compatibilidade para iniciantes, o que é problemático, pois novamente existem sistemas que não permitem que você misture APIs OpenGL antigas com as mais recentes. Existem bibliotecas e ferramentas não oficiais para renderização mais simples no novo OpenGL, com níveis variados de recursos e casos de uso e idiomas de destino ( MonoGame para usuários do .NET, por exemplo), mas nada oficialmente aprovado ou amplamente aceito.
A documentação que você encontra pode até não ser para o OpenGL, mas pode ser para uma das outras APIs semelhantes. O OpenGL | ES 1.x tinha renderização de função fixa, mas não tinha as APIs do OpenGL 1.x para envio de vértices. O OpenGL | ES 2.x + e o WebGL 1+ não possuem nenhum recurso de função fixa e não há modos de compatibilidade com versões anteriores para essas APIs.
Essas APIs parecem muito muito semelhantes ao OpenGL principal; eles não são totalmente compatíveis, mas existem extensões oficiais para o OpenGL que alguns (nem todos) os drivers suportam para se tornarem compatíveis com o OpenGL | ES (no qual o WebGL se baseia). Porque as coisas não eram confusas o suficiente antes.