OpenGL: VBO ou glBegin () + glEnd ()?

16

Recentemente, recebi este link de um site de tutoriais de alguém para quem eu dei o OGL Redbook original. O terceiro cabeçalho abaixo diz claramente para esquecer glBegin () & glEnd () como o método de renderização típico. Eu aprendi através do método Redbook, mas vejo alguns benefícios nos VBOs. Esse é realmente o caminho a percorrer? Se houver, existe uma maneira de converter facilmente o código de renderização e os shaders subsequentes em VBOs e tipos de dados subsequentes?

S. Fitzgerald
fonte

Respostas:

27

Com as modernas VBOs do OpenGL, o material de funções fixas (incluindo glBegin / glEnd e o material intermediário) foi preterido desde o 3.0 e removido desde o 3.1.

Com o OpenGL Core Profile, o OpenGL ES 2.0+ e o WebGL, você nem sequer tem acesso aos itens antigos.

Algumas pessoas pensam que aprender o material antigo primeiro é melhor porque é um pouco mais fácil, mas o que você aprende é geralmente inútil e depois o que precisa desaprender.

Porém, não são apenas os VBOs, você precisa usar shaders para tudo e fazer matrizes se transformar (ou usar GLM).

O único motivo para usar o material antigo seria se você quisesse segmentar o OpenGL antes da 2.0. que foi lançado em 2003. Existem alguns chipsets de netbook embutidos realmente ruins que são 1,5, mas até 1,5 devem suportar VBOs, mas não shaders. Ou o OpenGL ES 1.x, que se baseia no pipeline de função fixa (por exemplo, é usado em iPhones mais antigos). Ou OpenGL SC (para sistemas críticos de segurança).

As seguintes funções comumente usadas estão obsoletas:

  • glBegin
  • glEnd
  • glVertex *
  • glNormal *
  • glTextCoord *
  • glTranslate *
  • glRotate *
  • glScale *
  • glLoadIdenity
  • glModelViewMatrix

Os tutoriais do opengl-tutorial.org têm o que eu acho que é a melhor maneira de aprender sobre o OpenGL. Eles confiam em algumas das coisas de compatibilidade herdadas, mas na verdade não ensinam isso a você. Por exemplo, você não deve renderizar nada sem um sombreador, mas funciona. E você precisa lidar com operações de matrizes (girar, traduzir etc.), mas por padrão você terá uma viewport 2D plana básica.

Além de evitar as coisas obsoletas, existem várias funções que tornam a codificação do OpenGL muito mais agradável, mas com muitas delas você precisa decidir se aceita a exigência de versões mais recentes 3.x + do OpenGL e hardware compatível.

Há mais informações em um post que fiz aqui .

Se você precisar oferecer suporte ao OpenGL antigo por algum motivo, poderá usar VBOs quando possível e, quando não estiver, fornecer um fallback que use glBegin / glEnd e faça um loop nos dados de vértice.

Por outro lado, não há uma maneira 'fácil' real de converter up antigo código de renderização. Talvez você possa implementar sua própria versão das funções que adicionam os vértices a um vetor / matriz que os despeja em um VBO e o desenha quando você chama glEnd. mas isso seria muito ineficiente, já que o faria em todos os quadros (a menos que você marque apenas uma vez, mas que não funcione para objetos animados) e provavelmente seria mais trabalhoso do que mudar para VBOs. Suponho que, se você tivesse muito código, essa abordagem poderia funcionar.

David C. Bishop
fonte
7

Com os VBOs, você geralmente tem duas vantagens principais.

A vantagem 1 refere-se a dados totalmente estáticos e é possível manter seus dados de vértice na memória mais ideal para a GPU.

A vantagem 2 refere-se a dados dinâmicos e resulta da capacidade de especificar seus dados de vértice a qualquer momento antes de usá-los para renderização, que pode ser melhor canalizada.

Uma terceira vantagem vem do lote de chamadas de empate, mas também é compartilhado com matrizes de vértices da velha escola, portanto, não estou chamando isso especificamente para VBOs. O envio de dados para uma GPU (ou o uso de dados já existentes na GPU) é semelhante em muitos aspectos ao disco de E / S e tráfego de rede - se você tiver alguns lotes grandes, será mais eficiente do que muitos lotes pequenos.

Uma boa analogia (não 100% precisa, mas suficiente para ajudar você a ter uma idéia) é se você é um motorista de ônibus que precisa levar 50 pessoas de uma cidade para outra. Você pode carregá-los um de cada vez e fazer 50 viagens separadas - isso é glBegin / glEnd. Como alternativa, você pode colocar todos os 50 deles no barramento e apenas fazer uma única viagem - isso inclui lotes de vértices ou VBOs (no caso da VBO, as 50 pessoas já estariam no barramento;)).

Porém, isso tem um preço, e aqui o preço é que você perde a capacidade de especificar apenas dados de vértice como e quando necessário. Bem, tudo bem, você pode fazer isso (com algum trabalho adicional), mas não obterá o desempenho completo do seu código. Em vez disso, você precisa pensar mais sobre seus dados de vértice, como são usados, como (e se) precisam ser atualizados, se alguma animação pode ser feita em um sombreador (permitindo que os dados permaneçam estáticos - os VBOs realmente precisam de sombreadores para um muitos casos de animação para funcionar bem) ou se você precisa respeitar novamente os dados dos vértices em cada quadro, estratégias de atualização eficientes nos últimos, etc. Se você não fizer isso e apenas implementar uma conversão ingênua, corre o risco de colocar em muito trabalho apenas para que o resultado final realmente corra mais devagar!

Isso pode parecer uma enorme quantidade de trabalho quando você o encontra pela primeira vez, mas na verdade não é. Depois de entrar no modo de pensar assim, você descobrirá que é incrivelmente fácil e quase vem naturalmente. Mas você pode estragar suas primeiras tentativas e não deve ficar desanimado - se estragar é uma oportunidade de aprender com o que você fez de errado.

Algumas considerações finais.

Ter os dados do modelo em um formato que possa ser facilmente carregado em uma VBO pode ajudar a tornar todo esse processo muito mais fácil para você. Isso significa que você deve evitar formatos mais complexos ou exóticos, pelo menos a princípio (e até que você esteja mais confortável com o processo); mantenha as coisas o mais simples e básicas possíveis ao aprender e haverá menos coisas para dar errado e menos lugares para procurar erros se (ou quando!) as coisas derem errado.

Às vezes, as pessoas ficam adiadas se virem uma implementação VBO usando mais memória do que uma implementação glBegin / glEnd otimizada / compactada (elas podem até se referir a ela como "desperdício"). Não seja assim. Exceto em casos extremos, o uso de memória não é realmente que importante. É uma troca clara aqui - você está aceitando um uso potencialmente maior de memória em troca de um desempenho substancialmente mais alto. Também ajuda a desenvolver a mentalidade de que a memória é um recurso barato e abundante que existe para ser usado; desempenho não é.

E, finalmente, a velha castanha - se já é rápida o suficiente, então seu trabalho está feito. Se você estiver atingindo a taxa de quadros de destino, se tiver espaço para condições transitórias, será bom o suficiente e poderá passar para a próxima etapa. Você pode desperdiçar muito tempo e energia extraindo 10% extra de algo que realmente não precisa dele (já esteve lá, fez isso, ainda cai na armadilha), portanto, sempre considere qual é o melhor uso do seu tempo. - porque o tempo do programador é ainda menos barato e menos abundante que o desempenho!

Maximus Minimus
fonte