Buffer de vértice grande versus várias chamadas de empate

14

Estou apenas começando com o OpenGL e estou tentando usá-lo para criar um jogo em 2D. Neste jogo, eu tenho uma grade hexagonal composta por uma variedade muito grande de hexágonos de cores diferentes. Como programador iniciante em OpenGL, vejo duas maneiras de desenhar essa grade:

  1. Usando um buffer de vértice com os dados para um único hexágono, depois usando um valor de deslocamento uniforme e iterando na CPU para desenhar o mesmo programa várias vezes até que eu tenha uma grade.
  2. Criando um buffer de vértice pré-calculado muito grande e singular que desenha todos os hexágonos em uma única chamada.

Qual é o método mais eficiente? Existe um jeito melhor de fazer isso?

Alexis King
fonte
Seu buffer de vértice pré-calculado precisa apenas ultrapassar a tela em um hexágono. Você pode falsificá-lo rolando suavemente até obter um hexágono completo e depois "distorcer", pois para as cores nesse cenário, você pode manter um Textura 2D na GPU, leia-a no shader de vértice e interpole-a no shader de fragmento.
MickLH
Os passes geralmente se referem a uma situação em que uma operação de renderização se baseia nos resultados de uma operação anterior. O que você está perguntando nesta pergunta está realmente relacionado à redução do número de chamadas de empate em um único passe. Eu sei que soa pedante, mas é muito importante entender a diferença de outra forma algoritmos multi-passagem não fará muito sentido;)
Andon M. Coleman
@ AndonM.Coleman Hmm, obrigado, eu claramente não estou familiarizado com a terminologia gráfica. Então, neste caso, como eu o descreveria? Várias chamadas de sombreador / programa?
Alexis King
Você pode dizer imediatamente que esse é um algoritmo de passagem única porque não há dependência de ordem; você pode desenhar esses hexágonos em qualquer ordem e ainda assim obter o mesmo resultado. Você pode fazer várias chamadas de empate para fornecer ao OpenGL os dados necessários para renderizá-las, mas o OpenGL é efetivamente livre para desenhar todas em paralelo, pois não há dependências. Se fosse de várias passagens , o hexágono B poderá exigir o resultado do hexágono A antes de poder ser desenhado, ou talvez seja necessário desenhar o mesmo hexágono várias vezes e combinar o resultado.
Andon M. Coleman

Respostas:

9

De fato, existem algumas maneiras de fazer essa grade.

A maneira mais eficiente seria instanciar. Dessa forma, você cria seu hexágono apenas uma vez em um VBO e o processa cem, mil ou um milhão de vezes. Você pode fazer isso manualmente usando sombreadores com uniformes, como você disse no ponto 1, mas também há uma funcionalidade OpenGL incorporada. Para isso, dê uma olhada no glDrawElementsInstanced .

Observe que instanciar é apenas mais rápido que outros métodos se você desenhar mais do que uma certa quantidade de objetos instanciados. Por exemplo, o desenho 300 pode ser mais rápido usando 1 VBO grande, mas o desenho de 2 milhões pode ser mais rápido se você usar a renderização instanciada.

Se você usar a renderização instanciada, poderá enviar dados por objeto usando os Divisores de Atributo . No seu caso, você deseja enviar a posição e a cor.

Um bom tutorial sobre renderização instanciada: clique

Realmente, a melhor maneira é tentar os dois métodos e verificar a quantidade de milissegundos necessária para desenhar 1 quadro. Dessa forma, você também aprende nos dois sentidos, o que é sempre bom.

Observe também que a renderização instanciada é uma funcionalidade moderna do OpenGL e você precisará usar shaders para usá-la. Mas é sempre melhor aprender da maneira correta desde o início.

Basaa
fonte
2
Instanciar não é necessariamente o mais eficiente; em muitas implementações em que vi perfis, o suporte de instanciamento foi implementado para conformidade, mas mais lento que o desenho individual de muitos objetos (na verdade, era provavelmente apenas um loop mal implementado no driver que fazia exatamente isso). É uma opção, e boa, mas deve-se ter cuidado em criar um perfil e testar no SO / hardware de destino antes de fazer qualquer suposição sobre "a mais eficiente".
Sean Middleditch
Acordado. Eu já vi performances diferentes no Windows / Linux e Ati / nVidia, por exemplo. Obrigado pela adição.
Basaa 5/09/2013
1
De fato. Se você desenhar várias malhas combinadas em um único vbo (que compartilham o mesmo espaço). De nenhuma maneira instanciar poderia ser mais rápido. O problema da instanciação é: os vértices não são instâncias cruzadas calculadas paralelamente. Ele apenas elimina a chamada gpu / cpu / gpu sync / drawcall. Portanto, é mais rápido desenhar um buffer de vértice contendo 1000 esferas do que desenhar 1000 esferas com instanciamento de hardware. (sem frustum abate / distância do objecto detalhe optimização envolvida)
Jeroen van Langen
3

O método 1 é mais simples de codificar e ficará bem desde que você não tenha muitos hexágonos à vista de uma só vez. Você pode ficar com isso, já que é novo no OpenGL, para evitar colocar muita complexidade em seu prato ao mesmo tempo.

Se houver um grande número de hexágonos (como várias centenas ou mais de mil) em exibição ao mesmo tempo, seria necessário um método de menor sobrecarga para evitar que a sobrecarga da CPU fizesse tantos empates individuais. O método 2 funcionaria para isso, ou melhor ainda, para instanciar. Eu esperaria que o instanciamento fosse mais rápido que o método 2, ou certamente pior, já que você só precisa atualizar um buffer de dados por instância em vez de um buffer (muito maior) de dados de vértice para todas as instâncias.

Nathan Reed
fonte