Estoy tratando de hacer un motor de juego en 2D usando OpenGL ES 2.0 (iOS por ahora). He escrito Application layer en Objective C y un RendererGLES20 independiente en C ++. No se realiza una llamada específica de GL fuera del renderizador. Funciona perfectamente
Pero tengo algunos problemas de diseño cuando uso sombreadores. Cada sombreador tiene sus propios atributos y uniformes únicos que deben establecerse justo antes de la llamada del sorteo principal (glDrawArrays en este caso). Por ejemplo, para dibujar algo de geometría haría:
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 puede ver, este código es extremadamente rígido. Si tuviera que usar otro sombreador, digamos efecto ondulación, tendría que pasar uniformes adicionales, atributos de vértice, etc. En otras palabras, tendría que cambiar el código fuente de renderizado RendererGLES20 solo para incorporar el nuevo sombreador.
¿Hay alguna forma de hacer que el objeto sombreador sea totalmente genérico? ¿Qué sucede si solo quiero cambiar el objeto del sombreador y no preocuparme por la compilación de la fuente del juego? ¿Alguna forma de hacer que el renderizador sea agnóstico de uniformes y atributos, etc.? A pesar de que necesitamos pasar datos a los uniformes, ¿cuál es el mejor lugar para hacerlo? Clase de modelo? ¿La clase de modelo conoce los uniformes y atributos específicos del sombreador?
A continuación se muestra la clase de actor:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
Clase de controlador de modelo: class ModelController {class IShader * shader; int textureId; tinte vec4; flotador alfa; struct Vertex * vertexArray; };
La clase de sombreador solo contiene el objeto de sombreador, compilando y vinculando subrutinas, etc.
En la clase Game Logic, en realidad estoy renderizando el objeto:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
Tenga en cuenta que aunque Actor extiende ISceneNode, todavía no he comenzado a implementar SceneGraph. Lo haré tan pronto como resuelva este problema.
¿Alguna idea de cómo mejorar esto? ¿Patrones de diseño relacionados, etc.?
Gracias por leer la pregunta.