引擎渲染管道:使着色器通用 [英] Engine Rendering pipeline : Making shaders generic

查看:155
本文介绍了引擎渲染管道:使着色器通用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用OpenGL ES 2.0(目前为iOS)制作2D游戏引擎.我已经在Objective C中编写了Application层,并在C ++中编写了一个独立的RendererGLES20.在渲染器外部不会进行GL特定的调用.运行良好.

I am trying to make a 2D game engine using OpenGL ES 2.0 (iOS for now). I've written Application layer in Objective C and a separate self contained RendererGLES20 in C++. No GL specific call is made outside the renderer. It is working perfectly.

但是在使用着色器时,我遇到了一些设计问题.每个着色器都有自己的唯一属性和统一体,需要在主绘制调用之前进行设置(在本例中为glDrawArrays).例如,为了绘制一些几何图形,我会这样做:

But I have some design issues when using shaders. Each shader has its own unique attributes and uniforms that need to be set just before the main draw call (glDrawArrays in this case). For instance, in order to draw some geometry I would do:

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渲染源代码,以合并新的着色器.

As you can see this code is extremely rigid. If I were to use another shader, say ripple effect, i would be needing to pass extra uniforms, vertex attribs etc. In other words I would have to change the RendererGLES20 render source code just to incorporate the new shader.

有什么方法可以使着色器对象完全通用吗?就像我只想更改着色器对象而不担心游戏源重新编译该怎么办?有什么方法可以使渲染器与制服和属性无关?即使我们需要将数据传递给制服,这样做的最佳位置是什么?模特班?模型类是否了解着色器特定的制服和属性?

Is there any way to make the shader object totally generic? Like What if I just want to change the shader object and not worry about game source re-compiling? Any way to make the renderer agnostic of uniforms and attributes etc?. Even though we need to pass data to uniforms, what is the best place to do that? Model class? Is the model class aware of shader specific uniforms and attributes?

以下显示了演员类:

class Actor : public ISceneNode
{
    ModelController * model;
    AIController * AI;
};

模型控制器类: ModelController类 { IShader *着色器类; int textureId; vec4色调; 浮点alpha; struct Vertex * vertexArray; };

Model controller class: class ModelController { class IShader * shader; int textureId; vec4 tint; float alpha; struct Vertex * vertexArray; };

Shader类仅包含着色器对象,编译和链接子例程等.

Shader class just contains the shader object, compiling and linking sub-routines etc.

在Game Logic类中,我实际上是在渲染对象:

In Game Logic class I am actually rendering the object:

void GameLogic::update(float dt)
{
    IRenderer * renderer = g_application->GetRenderer();

    Actor * a = GetActor(id);
    renderer->render(a->model);
}

请注意,即使Actor扩展了ISceneNode,我仍未开始实现SceneGraph.解决此问题后,我会立即这样做.

Please note that even though Actor extends ISceneNode, I haven't started implementing SceneGraph yet. I will do that as soon as I resolve this issue.

任何想法如何改善这一点?相关的设计模式等?

Any ideas how to improve this? Related design patterns etc?

推荐答案

如果属性或制服没有变化,则可以更改着色器,而不必重新编译c ++代码.为此,您可以使用glShaderSource从文本文件中加载着色器代码,然后对其进行编译,或者通过使用glShaderBinary加载预编译的二进制文件.

When no attributes or uniforms change then you can change the shader without having to recompile your c++ code. You do this by either loading you shader code from a text file with glShaderSource and then compiling it, or by loading a precompiled binary file with glShaderBinary.

要对不同的渲染方法进行某种封装,您可以具有从RendererGLES20继承的不同渲染器.这样,只有渲染器才需要知道着色器需要哪些属性和制服.

To get some sort of encapsulation of the different rendering methods you can have different renderers that inherit from RendererGLES20. That way only the renderer needs to know what attributes and uniforms the shader needs.

class RendererGLES20
{
public:
    virtual void render(Model * model) = 0;

    // ...
}

class RippleRenderer : public RendererGLES20
{
    virtual void render(Model * model);
    // ...
}

class BlinnPhongRenderer : public RendererGLES20
{
    virtual void render(Model * model);
    // ...
}

class CartoonRenderer : public RendererGLES20
{
    virtual void render(Model * model);
    // ...
}

这篇关于引擎渲染管道:使着色器通用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆