我正在嘗試使用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