我正在尝试使用OpenGL ES 2.0(iOS现在)制作2D游戏引擎。我已经在Objective C中编写了应用程序层,并在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 *着色器; int textureId; vec4 tint; float alpha; struct Vertex * vertexArray; };
Shader类只包含着色器对象,编译和链接子程序等
在游戏逻辑类我实际渲染对象:
void GameLogic::update(float dt)
{
IRenderer * renderer = g_application->GetRenderer();
Actor * a = GetActor(id);
renderer->render(a->model);
}
请注意,即使演员延伸ISceneNode ,我还没有开始实施SceneGraph。我会尽快解决此问题。
任何想法如何改善?相关设计模式等?
那么在实际情况下,属性和制服会发生变化。此外,在一个典型的游戏中,可能会有10-15个着色器。所以这是15个扩展类,只适用于RendererGLES20。如果我想将游戏移植到Wii(固定管道)或XNA(directX)上,该怎么办?您可以制作一个C++ DLL和C#接口,但是您必须重写整个渲染器类和其他15个扩展渲染器。此外,每次添加一个新的着色器时,我都必须扩展一个新的渲染器,如果我决定放弃某些着色器,则必须删除相关的类。不是一个好主意! – fakhir
我想知道我们是否可以使渲染器完全不知道着色器的内部细节。 – fakhir
好吧,就像datenwolf所说的那样,OpengGL的新版本牺牲了程序员的便利性,以便提高性能和灵活性,所以没有办法使它变得通用。这只是分享一些渲染代码和成员变量的一种方式。 – Simon