Preconceitos
Ok, então o que eu reuni até agora é o seguinte:
- não use pipeline fixo (descontinuado ou será descontinuado)
- o vbos armazena "modelos de objetos" (n dados de vértices, principalmente)
- vaos descrevem como os dados são estabelecidos para que as chamadas de chamada saibam qual parte de cada vbo é para que tipo de informação de vértice (um vao pode se referir a vários vbos, o oposto é meio difícil)
- cada chamada de desenho também envia dados de vértice para shaders
Como vejo 3D (opcional)
Dadas essas informações, posso ver como desenhar objetos complicados em 3D é muito bom com o OpenGL moderno. Você basicamente carrega vários modelos de objetos (provavelmente do Blender ou outro software similar) nos VBOs com coordenadas locais e simplesmente fornece a cada instância de um objeto um parâmetro de sombreador diferente (deslocamento) para desenhar no espaço do mundo.
Problema / pergunta
Em 2D, problemas e prioridades são completamente diferentes. Você não desenha objetos muito complexos, não precisa de matrizes de projeção complicadas e outros enfeites e shaders são muito mais simples.
Qual seria a melhor maneira de desenhar geometrias que mudam frequentemente (realmente frequentemente, basicamente todos os quadros) com o OpenGL moderno?
No parágrafo a seguir, você pode ver algumas idéias de problemas (o problema do círculo e do retângulo), que identificam melhor o tipo de mudança em que estou interessado.
Minhas tentativas (opcional)
Então, comecei a pensar em como lidaria com o desenho de geometria 2D básica na tela:
- um quadrado: carrega um
[(1, 0), (1, 1), (0, 1), (0, 0)]
VBO para a geometria de um quadrado no espaço local e, em seguida, forneça ao shader a largura real do quadrado e as coordenadas do mundo e as informações de cores
esfria, parece fácil. Vamos para um círculo:
- um círculo: ventilador triangular com ... eh. quanta precisão (número de vértices)? para pequenos círculos, a precisão deve ser pequena e, para círculos de erros, a precisão deve ser alta. O carregamento claro de 1 VBO não pode atender a todos os casos. E se eu precisar adicionar precisão porque um círculo é redimensionado para ser maior?
Menos legal. Vamos para algo um pouco mais fácil, um retângulo:
- um retângulo: eh. não há "geometria geral do retângulo". Você apenas tem uma proporção de largura / altura e é isso, mas cada retângulo provavelmente é diferente se o tamanho mudar.
Como você pode ver, as coisas vão ladeira abaixo a partir daí. Especialmente com polígonos complexos e outros enfeites.
Nenhuma política de código: P
Eu só preciso de uma visão geral da idéia, nenhum código é necessário, especialmente código C ou C ++. Apenas diga coisas como: "faça um VBO com esses dados de vértice e ligue-o, ...".
Respostas:
Sua principal pergunta parece ser:
De muitas maneiras, não há grande diferença entre 2D e 3D OpenGL. O pipeline gráfico possui uma coordenada extra, Z, que não será usada tanto em 2d, mas é isso.
Existem algumas maneiras de alterar a geometria em cada desenho.
Você pode enviar novos vértices fornecidos pela CPU a cada quadro. (Consulte /programming/14155615/opengl-updating-vertex-buffer-with-glbufferdata para obter algumas notas sobre a reutilização de buffers.)
Você pode desenhar diferentes partes de um buffer existente, com
glDrawArrays(mode, first, count)
. Se a animação repetir, talvez você possa colocar os quadros pré-computados com as diferentes listas de vértices em um buffer grande e desenhar a parte apropriada do buffer em cada quadro.Você pode influenciar a lista de vértices com outros dados, como uma matriz uniforme ou uma textura. No seu shader de vértice, leia esses dados e aplique-os adequadamente. Essas são apenas outras expressões idiomáticas para a apresentação de dados na GPU e provavelmente não terão muita diferença no desempenho.
Se você tiver muitas instâncias da mesma geometria (possivelmente influenciadas por atributos),
glDrawElementsInstanced()
poderá ser útilVocê pode influenciar a lista de vértices algoritmicamente nos shaders de vértice, geometria ou mosaico. Se a animação puder ser descrita matematicamente, você poderá manter a mesma lista de vértices e alterar apenas alguns uniformes de shader a cada quadro.
E talvez sua animação possa ser expressa em texturas puras, com todas as animações feitas pixel por pixel pelo processador ou pré-renderizadas a partir do disco.
No geral, eu diria: "Os computadores são rápidos, fazem com que funcione da maneira mais fácil possível, o que provavelmente é configurando vértices frescos da CPU a cada quadro. Depois, veja se isso é bom o suficiente. Analise o uso da bateria / CPU primeiro, pegada de memória segundo. "
Sua outra pergunta , parafraseada, "Qual é uma boa maneira de desenhar círculos e retângulos?"
Círculos.
Com os shaders de mosaico (ou shaders de geometria), você pode tornar sua geometria dinâmica.
Você pode desenhar quadrados e, no fragmento, o shader apenas opaco (alfa = 1,0) dentro de um raio e transparente (alfa = 0,0) fora do raio. Então, é pixel perfeito todas as vezes. (Faça seus vértices quadrados de -1 a +1 e, no fragmento shader, algo como
outColor.a = dot(coord.xy, coord.xy) < 1.0 ? 1.0 : 0.0;
,. Também poderia suavizar um pouco a borda, ficaria bom lá ...)Você sempre pode usar, digamos, uma ventoinha de 120 triângulos. Provavelmente bom o suficiente.
Retângulos.
fonte
Não posso dizer que sou especialista nesse assunto e, no (s) meu (s) projeto (s) de jogo, concentrei-me mais no lado 3D, então meu lado 2D é bastante simples, geralmente usando coisas feitas para o lado 3D; e, obviamente, minha perspectiva é do lado dos jogos, então meus gráficos 2D têm mais a ver com sprites do que com geometria. Nessa perspectiva,
1) Quadrados e retângulos são bem fáceis. Eu tenho apenas uma caixa 1x1 em um VBO que eu uso para cegar tudo. Eu passo matrizes MVP para sombreador com essa "caixa de unidade" e a combinei com escala adicional para dimensionar a caixa para as dimensões corretas - como você sabe, você pode ter diferentes escalas x e y.
Para meus propósitos, tenho pensado em deixar de usar a "caixa unitária" para algum tipo de mecanismo de partículas para misturar sprites 2D, mas isso é outra história.
2) Não trabalho muito com círculos, apenas uso VBOs fixos com número específico de vértices. Mas eu poderia imaginar que poderia dar alguns passos para afetar o número de vértices desenhados para o círculo.
Ao conectar dados VBO a atributos de sombreador, uso glVertexAttribPointer. Possui parâmetro de passada destinado a ser usado para dados intercalados (que eu uso). Mas pode ser possível usá-lo assim:
... para escolher cada enésimo vértice do buffer, afetando assim o número de vértices desenhados para o círculo. Eu poderia criar vários VAOs com o mesmo VBO com passo diferente afetando o número de vértices desenhados para o círculo. Eu não tentei isso, pensou.
Em geral, sim, trabalhar com VBOs e outros torna os ajustes do lado da CPU um pouco mais complexos, por que tenho estudado coisas diferentes para fazer ajustes no lado da GPU (shaders). Ainda assim, de acordo com este artigo, o uso de VBOs é mais eficiente em hardware moderno, mesmo se você precisar de muita "intervenção" do lado da CPU:
http://www.quelsolaar.com/opengl_performance.txt
Espero que isso ajude um pouco a projetar e decidir suas direções.
fonte