Eu tenho algum código que percorre um conjunto de objetos e renderiza instâncias desses objetos. A lista de objetos que precisam ser renderizados é armazenada como um std :: map>, onde um objeto da classe MeshResource contém os vértices e índices com os dados reais, e um objeto de classMeshRenderer define o ponto no espaço em que a malha deve ser processado em.
Meu código de renderização é o seguinte:
glDisable(GL_BLEND);
glEnable(GL_CULL_FACE);
glDepthMask(GL_TRUE);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_DEPTH_TEST);
for (std::map<MeshResource*, std::vector<MeshRenderer*> >::iterator it = renderables.begin(); it != renderables.end(); it++)
{
it->first->setupBeforeRendering();
cout << "<";
for (unsigned long i =0; i < it->second.size(); i++)
{
//Pass in an identity matrix to the vertex shader- used here only for debugging purposes; the real code correctly inputs any matrix.
uniformizeModelMatrix(Matrix4::IDENTITY);
/**
* StartHere fix rendering problem.
* Ruled out:
* Vertex buffers correctly.
* Index buffers correctly.
* Matrices correct?
*/
it->first->render();
}
it->first->cleanupAfterRendering();
}
geometryPassShader->disable();
glDepthMask(GL_FALSE);
glDisable(GL_CULL_FACE);
glDisable(GL_DEPTH_TEST);
A função no MeshResource que lida com a configuração dos uniformes é a seguinte:
void MeshResource::setupBeforeRendering()
{
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);
glEnableVertexAttribArray(3);
glEnableVertexAttribArray(4);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iboID);
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), 0); // Vertex position
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 12); // Vertex normal
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 24); // UV layer 0
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 32); // Vertex color
glVertexAttribPointer(4, 1, GL_UNSIGNED_SHORT, GL_FALSE, sizeof(Vertex), (const GLvoid*) 44); //Material index
}
O código que renderiza o objeto é este:
void MeshResource::render()
{
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
E o código que limpa é este:
void MeshResource::cleanupAfterRendering()
{
glDisableVertexAttribArray(0);
glDisableVertexAttribArray(1);
glDisableVertexAttribArray(2);
glDisableVertexAttribArray(3);
glDisableVertexAttribArray(4);
}
O resultado final disso é que eu recebo uma tela preta, embora o final do meu pipeline de renderização após o código de renderização (essencialmente apenas desenhando eixos e linhas na tela) funcione corretamente, por isso tenho certeza de que não é um problema com o passagem de uniformes. Se, no entanto, eu alterar o código levemente para que o código de renderização chame a instalação imediatamente antes da renderização, da seguinte maneira:
void MeshResource::render()
{
setupBeforeRendering();
glDrawElements(GL_TRIANGLES, geometry->numIndices, GL_UNSIGNED_SHORT, 0);
}
O programa funciona como desejado. Porém, não quero fazer isso, pois meu objetivo é configurar dados de vértice, material etc. etc. uma vez por tipo de objeto e renderizar cada instância atualizando apenas as informações de transformação.
O uniformizeModelMatrix funciona da seguinte maneira:
void RenderManager::uniformizeModelMatrix(Matrix4 matrix)
{
glBindBuffer(GL_UNIFORM_BUFFER, globalMatrixUBOID);
glBufferSubData(GL_UNIFORM_BUFFER, 0, sizeof(Matrix4), matrix.ptr());
glBindBuffer(GL_UNIFORM_BUFFER, 0);
}
offsetof
ao especificar atributos de vérticeRespostas:
Primeiro, o OpenGL está cheio de coisas estranhas, então um bug de driver, por mais improvável que seja, ainda é uma opção - considere testar o aplicativo em diferentes configurações (nVidia vs. AMD, drivers mais antigos) e outras pequenas modificações de código. Por exemplo, você pode começar removendo o "glBindBuffer (GL_UNIFORM_BUFFER, 0);" linha - parece não estar fazendo nada útil de qualquer maneira.
Como tudo aqui parece estar correto, o problema provavelmente não está aqui. Existem duas opções: gDEBugger e percorrer o código no depurador C ++. Parece que algo está sendo redefinido antes do desenho. No gDEBugger, existe um recurso "histórico de chamadas" que pode ajudá-lo a ver quais chamadas foram feitas antes da chamada de empate e em que ordem.
A propósito, sugiro fortemente que você agrupe todas as chamadas de retorno de erro com uma macro que verifique todos os erros possíveis e os gere. Ele deve ser uma macro para oferecer suporte à depuração estendida (arquivo de impressão, linha e a própria linha de código defeituosa) que pode ser desabilitada nas compilações de versão. Se alguma regra secreta for violada, essa configuração deve avisá-lo disso imediatamente.
fonte
Tenho certeza de que o atributo deve ser vinculado ao buffer atual, portanto, não há razão para refazer esse negócio com os atributos a cada quadro, a menos que você reconstrua o buffer sempre.
Portanto, você provavelmente deve fazê-lo de uma maneira ou de outra - deixe como está ou reconstrua a coisa toda a cada quadro.
fonte
TL; DR: erros de driver.
Nos meus testes a partir de hoje (outubro de 2016), os buffers uniformes não são suportados adequadamente pela maioria dos drivers existentes.
Alguns não respeitam,
glUniformBlockBinding
outros não atualizam os dados uniformes (glBufferSubData
eglBufferData
) adequadamente, onde as cópias internas em cache dos shaders / GPU dos referidos buffers não são mantidas coerentes.Do jeito que eu entendo (e do jeito que a Nvidia também entende)
glBindBufferBase
ouglBindBufferRange
.glUniformBlockBinding(shader_id, shader_ubo_index, global_ubo_index);
essa configuração por programa de shader , não compartilhado globalmente.Nota: global_ubo_index NÃO é o nome do objeto de buffer uniforme, mas um índice nessa tabela global.
Essa "complexidade" (que é um ótimo recurso para compartilhar UBOs entre diferentes sombreadores, como valores de iluminação) parece ser o que a maioria dos drivers OpenGL erra. Para ser justo, a redação da documentação do OpenGL também não é a mais inequívoca.
Eu tive que recorrer ao uso de uniformes velhos comuns para outros motoristas.
Ambas as capturas de tela usando objetos de buffer uniformes, dois drivers diferentes:
fonte