Eu estava aprendendo OpenGL recentemente. Nos jogos, precisamos atualizar a posição dos objetos do jogo com frequência, e eles entram e saem da tela constantemente. Portanto, na renderização, precisamos atualizar o buffer de vértice com bastante frequência.
No contexto do OpenGL, uma maneira intuitiva é usar glBufferSubData para atualizar aqueles que foram alterados.
Mas também li on-line um truque chamado Orphaning, que cria novos dados de buffer e carrega todos os dados dos vértices nele.
Também devido ao custo das chagnes do estado e do upload, vários glBufferSubData também podem custar mais.
Aqui está a minha pergunta,
- Qual método é melhor?
- As barracas são realmente importantes neste caso?
- As mudanças de estado e o custo de upload são realmente importantes nesse caso?
Obrigado!
opengl
rendering
optimization
vbo
YiFeng
fonte
fonte
Respostas:
Essa é uma pergunta complexa, com muitos pequenos detalhes que realmente importam; o desempenho varia de acordo com a plataforma e o aplicativo. Portanto, você deve analisar possíveis gargalos antes de investir em otimizações.
Dito isto, em primeiro lugar, presumo que você deve reduzir o máximo de uploads e atualizações, por exemplo, usar instanciamento.
Em segundo lugar, observe que as GPUs não podem transferir buffers e renderizar ao mesmo tempo, portanto, todos os comandos OpenGL na fila de comandos são processados sequencialmente pelo dispositivo. Existem diferentes maneiras de copiar dados e / ou torná-los disponíveis para serem usados pela GPU.
Existem várias maneiras de transmitir dados para a GPU
1-
glBufferData
ouglBufferSubData
métodoUsando
glBufferData
ouglBufferSubData
é como memcpy. você passa um ponteiro e a operação de DMA pode ser executada, como eu disse, porque a memória pode ser fixada na memória da CPU e usada diretamente pela GPU, sem que ocorra uma transferência de memória para a GPU, dependendo do sinalizador de uso (GL_STREAM). Na opinião, você deve tentar isso primeiro porque é mais simples de implementar.2- obter um ponteiro para a memória interna usando
glMapBuffer
Se o descrito acima não for bom o suficiente, você poderá usar
glMapBuffer
um ponteiro para a memória interna e usá-lo para preencher diretamente o buffer, isso é bom para operações de leitura e gravação de arquivos, pois é possível mapear diretamente os dados do arquivo na memória da GPU em vez de copiar primeiro para um buffer temporário. Se você não deseja mapear o buffer inteiro, pode usar oglMapBufferRange
que pode ser usado para mapear uma parte do buffer.Um truque é criar um buffer grande, use a primeira metade para renderização e a segunda metade para atualização.
3- Órfão de buffer
Em relação ao órfão de buffer, isso pode ser feito usando glBufferData com nulo e os mesmos parâmetros que possuía. O driver retornará o bloco de memória assim que não for usado. E será usado pela próxima chamada glBufferData (nenhuma memória nova será alocada).
Todos os métodos mencionados causam muita sincronização cara, novamente as GPUs não podem transferir buffers e renderizar ao mesmo tempo.
4-
Unsynchronized Buffers
O método mais rápido (e mais difícil de acertar) é usar buffers sem sincronização com os quais você pode usar
GL_MAP_UNSYNCHRONIZED_BIT
sinalizadoresglMapBufferRange
; o problema é que nenhuma sincronização é feita; portanto, podemos fazer o upload de dados para um buffer que começa a ser usado e, portanto, estragar tudo. Você pode usar vários buffers com bit unsync para facilitar um pouco as coisas.fonte
Eu faço de outra maneira. Pode haver algo errado lá. Algumas coisas perigosas escondidas.
(Eu uso C # + OpenTK.GameWindow)
Para instanciar o objeto, eu uso um objeto de buffer de matriz separado para o conjunto de matrizes de modelo para cada instância. No vértice compartilhado:
No meu código C #, matrizes são armazenadas em uma matriz flutuante
float[] mat4_array
Em seguida, vinculo a matriz ao objeto de buffer de matriz:
A cada quadro, as matrizes do modelo são atualizadas. Para atualizar
mat4_array
, basta ligar para:e renderize a cena. usando
GL.DrawElementsInstanced
.Não há chamadas OpenGL adicionais e funciona perfeitamente.
fonte