我正在尝试使用OpenGL ES 2.0(目前为iOS)制作2D游戏引擎。我已经在Objective C中编写了Application层,并在C ++中编写了一个独立的RendererGLES20。在渲染器外部不会进行GL特定的调用。运行良好。
但是在使用着色器时,我有一些设计问题。每个着色器都有自己的唯一属性和统一体,需要在主绘制调用之前进行设置(在本例中为glDrawArrays)。例如,为了绘制一些几何图形,我要做:
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(.......);
}
如您所见,此代码非常严格。如果要使用另一个着色器(例如波纹效果),我将需要传递额外的制服,顶点属性等。换句话说,我将不得不更改RendererGLES20渲染源代码以仅合并新的着色器。
有什么方法可以使着色器对象完全通用吗?就像我只想更改着色器对象而不担心游戏源重新编译该怎么办?有什么方法可以使渲染器与制服和属性无关?即使我们需要将数据传递给制服,这样做的最佳位置是什么?模特班?模型类是否了解着色器特定的制服和属性?
以下显示演员类:
class Actor : public ISceneNode
{
ModelController * model;
AIController * AI;
};
模型控制器类:类ModelController {类IShader * shader; int textureId; vec4色调; 浮动字母 struct Vertex * vertexArray; };
着色器类仅包含着色器对象,编译和链接子例程等。
在游戏逻辑类中,我实际上是在渲染对象:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
请注意,即使Actor扩展了ISceneNode,我仍未开始实现SceneGraph。解决此问题后,我会立即进行处理。
有什么想法可以改善这一点吗?相关的设计模式等?
感谢您阅读问题。