OpenGL +面向对象?

时间:2014-01-21 22:58:03

标签: opengl c++11

我最近决定在OpenGL对象中添加一些RAII,直到我意识到OpenGL被设置为状态系统是徒劳的和矛盾的。现在,我实际上想要为涉及OpenGL对象的游戏实现一个类,如下所示:

class RenderTarget: public boost::noncopyable{
public:
    virtual ~RenderTarget();

protected:
    clear(const ColorSet& color);
    copy_to(const RenderTarget& target) = 0;
    copy_from(const RenderTarget& target) = 0;
    attach(const RenderTarget& target);
    detach(const RenderTarget& target);

private:
    //set of opengl framebuffers/renderbuffers/etc. ?
};

正如你所看到的,我希望这个抽象包含一组opengl帧缓冲区,但问题是因为opengl是一个状态机,每当我想调用任何成员函数时,我要么: 假设成员帧缓冲区被绑定(坏),每次调用函数时调用bind / unbind(昂贵),或者暴露bind()/ unbind()接口(丑陋,暴露OpenGL语义)。我有点被困在这里。我是否以错误的方式思考这个问题?

2 个答案:

答案 0 :(得分:1)

我实际上有一个类似于你为我的项目讨论的设计,而不是使用全局数组我有一个类作为状态机的接口,并提供一些类似于不推荐的状态堆栈的功能

示例绑定状态:

class FrameBufferBindState {
friend class eTB_RenderContext;
protected:
  FrameBufferBindState (void) {
    reset ();
  }

  void reset (void) {
    bound      = NULL;
    swap_count = 0;
    req_count  = 0;
  }

  void bind (eTB_FrameBuffer* fbo);

  void push (void);
  void pop  (void);

  eTB_FrameBuffer* bound;
  int              swap_count;
  int              req_count;

  std::stack <eTB_FrameBuffer *> stack;
};

我有一个名为eTB_RenderContext的类,它包含引擎可以绑定的每个基本对象类的类实例(请注意,其中一些类本身也包含绑定,例如程序对象绑定了着色器对象他们)。

我会跟踪bind (...)被调用的次数(req_count)与实际必须更改绑定的次数(swap_count)以衡量批次效率。我还有一个用于绑定和状态的堆栈机制,以使一些算法更容易。

绑定类:

  VertexArrayBindState vertex_array_;
  ProgramBindState     program_;
  FrameBufferBindState framebuffer_;
  SamplerBindState*    samplers_;       // Minimum: 80 in GL4
  TextureBindState*    texture_images_; // Minimum: 80 in GL4

答案 1 :(得分:1)

RAII仍然有利于OpenGL中的资源管理(纹理需要ID等,如果您在游戏中达到下一级并加载新资产,则应该释放它们)。这些任务很少进行,面向对象的开销对响应性的影响很小。

但是对于单独渲染和中帧状态管理,封装会产生很多低效率(例如,为每个对象上传颜色和纹理绑定),而良好的OpenGL性能需要最小化状态更改。即使检测和省略冗余状态更改也无济于事,您需要按排序顺序提交几何图形,而不是根据某些抽象对象模型进行分组。