Estou tentando criar um mecanismo de jogo 2D usando o OpenGL ES 2.0 (iOS por enquanto). Eu escrevi a camada Application no Objective C e um RendererGLES20 independente em C ++. Nenhuma chamada específica de GL é feita fora do renderizador. Está funcionando perfeitamente.
Mas tenho alguns problemas de design ao usar shaders. Cada sombreador possui seus próprios atributos e uniformes que precisam ser configurados imediatamente antes da chamada de desenho principal (neste caso, glDrawArrays). Por exemplo, para desenhar alguma geometria, eu faria:
void RendererGLES20::render(Model * model)
{
// Set a bunch of uniforms
glUniformMatrix4fv(.......);
// Enable specific attributes, can be many
glEnableVertexAttribArray(......);
// Set a bunch of vertex attribute pointers:
glVertexAttribPointer(positionSlot, 2, GL_FLOAT, GL_FALSE, stride, m->pCoords);
// Now actually Draw the geometry
glDrawArrays(GL_TRIANGLES, 0, m->vertexCount);
// After drawing, disable any vertex attributes:
glDisableVertexAttribArray(.......);
}
Como você pode ver, esse código é extremamente rígido. Se eu usasse outro shader, digamos efeito cascata, eu precisaria passar uniformes extras, atributos de vértices etc. Em outras palavras, eu teria que alterar o código-fonte de renderização do RendererGLES20 apenas para incorporar o novo shader.
Existe alguma maneira de tornar o objeto shader totalmente genérico? Como E se eu apenas quiser alterar o objeto shader e não me preocupar com a recompilação da fonte do jogo? Qualquer maneira de tornar o renderizador independente de uniformes e atributos etc? Mesmo que precisamos passar dados para uniformes, qual é o melhor lugar para fazer isso? Classe modelo? A classe do modelo está ciente dos atributos e uniformes específicos do shader?
A seguir, mostra a classe Ator:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
Classe do controlador de modelo: class ModelController {class IShader * shader; int textureId; tonalidade vec4; alfa flutuante; struct Vertex * vertexArray; };
A classe Shader contém apenas o objeto shader, compilando e vinculando sub-rotinas etc.
Na classe Game Logic, na verdade, estou processando o objeto:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
Observe que, embora o Actor estenda o ISceneNode, ainda não comecei a implementar o SceneGraph. Farei isso assim que resolver esse problema.
Alguma idéia de como melhorar isso? Padrões de design relacionados etc?
Obrigado por ler a pergunta.