From: Mikko Rasa Date: Tue, 11 Jan 2011 21:13:42 +0000 (+0000) Subject: Add EXT_framebuffer_blit and EXT_framebuffer_multisample X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=7f888de83aa5398fafaa7661547ee80395377b5c Add EXT_framebuffer_blit and EXT_framebuffer_multisample Make Framebuffer attach level 0 of textures by default Add multisampling support for Pipeline Separate functions for setting HDR and multisample in Pipeline Make the hdr parameter to Pipeline constructor optional --- diff --git a/source/ext_framebuffer_blit.cpp b/source/ext_framebuffer_blit.cpp new file mode 100644 index 00000000..613f514a --- /dev/null +++ b/source/ext_framebuffer_blit.cpp @@ -0,0 +1,15 @@ +#include "extension.h" +#include "ext_framebuffer_blit.h" + +namespace Msp { +namespace GL { + +PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT=0; + +void init_ext_framebuffer_blit() +{ + glBlitFramebufferEXT=reinterpret_cast(get_proc_address("glBlitFramebufferEXT")); +} + +} // namespace GL +} // namespace Msp diff --git a/source/ext_framebuffer_blit.h b/source/ext_framebuffer_blit.h new file mode 100644 index 00000000..0b651970 --- /dev/null +++ b/source/ext_framebuffer_blit.h @@ -0,0 +1,17 @@ +#ifndef MSP_GL_EXT_FRAMEBUFFER_BLIT_ +#define MSP_GL_EXT_FRAMEBUFFER_BLIT_ + +#include "gl.h" +#include + +namespace Msp { +namespace GL { + +extern PFNGLBLITFRAMEBUFFEREXTPROC glBlitFramebufferEXT; + +void init_ext_framebuffer_blit(); + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/ext_framebuffer_multisample.cpp b/source/ext_framebuffer_multisample.cpp new file mode 100644 index 00000000..22b00a9e --- /dev/null +++ b/source/ext_framebuffer_multisample.cpp @@ -0,0 +1,15 @@ +#include "extension.h" +#include "ext_framebuffer_multisample.h" + +namespace Msp { +namespace GL { + +PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT=0; + +void init_ext_framebuffer_multisample() +{ + glRenderbufferStorageMultisampleEXT=reinterpret_cast(get_proc_address("glRenderbufferStorageMultisampleEXT")); +} + +} // namespace GL +} // namespace Msp diff --git a/source/ext_framebuffer_multisample.h b/source/ext_framebuffer_multisample.h new file mode 100644 index 00000000..479ef693 --- /dev/null +++ b/source/ext_framebuffer_multisample.h @@ -0,0 +1,17 @@ +#ifndef MSP_GL_EXT_FRAMEBUFFER_MULTISAMPLE_ +#define MSP_GL_EXT_FRAMEBUFFER_MULTISAMPLE_ + +#include "gl.h" +#include + +namespace Msp { +namespace GL { + +extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEEXTPROC glRenderbufferStorageMultisampleEXT; + +void init_ext_framebuffer_multisample(); + +} // namespace GL +} // namespace Msp + +#endif diff --git a/source/extension.cpp b/source/extension.cpp index c2f1f600..fbed6e26 100644 --- a/source/extension.cpp +++ b/source/extension.cpp @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007, 2009-2010 Mikko Rasa, Mikkosoft Productions +Copyright © 2007, 2009-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -16,6 +16,8 @@ Distributed under the LGPL #include "arb_vertex_buffer_object.h" #include "arb_vertex_program.h" #include "arb_vertex_shader.h" +#include "ext_framebuffer_blit.h" +#include "ext_framebuffer_multisample.h" #include "ext_framebuffer_object.h" #include "except.h" #include "extension.h" @@ -52,6 +54,10 @@ bool is_supported(const string &ext) init_arb_vertex_program(); if(extensions.count("GL_EXT_framebuffer_object")) init_ext_framebuffer_object(); + if(extensions.count("GL_EXT_framebuffer_blit")) + init_ext_framebuffer_blit(); + if(extensions.count("GL_EXT_framebuffer_multisample")) + init_ext_framebuffer_multisample(); if(extensions.count("GL_ARB_vertex_buffer_object")) init_arb_vertex_buffer_object(); if(extensions.count("GL_NV_primitive_restart")) diff --git a/source/framebuffer.cpp b/source/framebuffer.cpp index ea28d5db..3d9b0133 100644 --- a/source/framebuffer.cpp +++ b/source/framebuffer.cpp @@ -1,11 +1,12 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ #include "extension.h" +#include "ext_framebuffer_blit.h" #include "ext_framebuffer_object.h" #include "framebuffer.h" #include "misc.h" @@ -146,6 +147,39 @@ void Framebuffer::clear(BufferBits bits) glClear(bits); } +void Framebuffer::blit_from(const Framebuffer &other, int sx0, int sy0, int sx1, int sy1, int dx0, int dy0, int dx1, int dy1, BufferBits bits, bool filter) +{ + static RequireExtension _ext("GL_EXT_framebuffer_blit"); + + const Framebuffer *old = current(); + if(set_current(this)) + { + glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, id); + if(dirty) + { + update_attachment(dirty); + dirty = 0; + } + } + if(old!=&other) + glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, other.id); + + glBlitFramebufferEXT(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, bits, (filter ? GL_LINEAR : GL_NEAREST)); + + set_current(old); + glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, (old ? old->id : 0)); +} + +void Framebuffer::blit_from(const Framebuffer &other, int sx, int sy, unsigned wd, unsigned ht, int dx, int dy, BufferBits bits) +{ + blit_from(other, sx, sy, sx+wd, sy+ht, dx, dy, dx+wd, dy+ht, bits, false); +} + +void Framebuffer::blit_from(const Framebuffer &other, BufferBits bits, bool filter) +{ + blit_from(other, 0, 0, other.width, other.height, 0, 0, width, height, bits, filter); +} + void Framebuffer::bind() const { if(set_current(this)) diff --git a/source/framebuffer.h b/source/framebuffer.h index 89147b2c..ea462bf6 100644 --- a/source/framebuffer.h +++ b/source/framebuffer.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007, 2009-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -110,7 +110,7 @@ private: void check_size(); public: void attach(FramebufferAttachment attch, Renderbuffer &rbuf); - void attach(FramebufferAttachment attch, Texture2D &tex, unsigned level); + void attach(FramebufferAttachment attch, Texture2D &tex, unsigned level = 0); void detach(FramebufferAttachment attch); /** @@ -121,6 +121,9 @@ public: FramebufferStatus check_status() const; void clear(BufferBits); + void blit_from(const Framebuffer &, int, int, int, int, int, int, int, int, BufferBits, bool); + void blit_from(const Framebuffer &, int, int, unsigned, unsigned, int, int, BufferBits); + void blit_from(const Framebuffer &, BufferBits, bool); void bind() const; diff --git a/source/pipeline.cpp b/source/pipeline.cpp index 570014d3..8517805e 100644 --- a/source/pipeline.cpp +++ b/source/pipeline.cpp @@ -28,9 +28,13 @@ Pipeline::Pipeline(unsigned w, unsigned h, bool d): width(w), height(h), hdr(d), + samples(0), fbo(0), color_buf(0), - depth_buf(0) + depth_buf(0), + fbo_ms(0), + color_buf_ms(0), + depth_buf_ms(0) { } Pipeline::~Pipeline() @@ -40,6 +44,20 @@ Pipeline::~Pipeline() delete depth_buf; } +void Pipeline::set_hdr(bool h) +{ + hdr = h; + if(!postproc.empty()) + create_fbos(); +} + +void Pipeline::set_multisample(unsigned s) +{ + samples = s; + if(!postproc.empty()) + create_fbos(); +} + void Pipeline::set_camera(const Camera *c) { camera = c; @@ -115,22 +133,8 @@ void Pipeline::add_postprocessor(PostProcessor &pp) { postproc.push_back(&pp); if(!fbo) + create_fbos(); { - fbo = new Framebuffer; - - color_buf = new Texture2D; - color_buf->set_min_filter(NEAREST); - color_buf->set_mag_filter(NEAREST); - color_buf->set_wrap(CLAMP_TO_EDGE); - color_buf->storage((hdr ? RGB16F : RGB), width, height); - fbo->attach(COLOR_ATTACHMENT0, *color_buf, 0); - - depth_buf = new Texture2D; - depth_buf->set_min_filter(NEAREST); - depth_buf->set_mag_filter(NEAREST); - depth_buf->set_wrap(CLAMP_TO_EDGE); - depth_buf->storage(DEPTH_COMPONENT, width, height); - fbo->attach(DEPTH_ATTACHMENT, *depth_buf, 0); } } @@ -160,8 +164,9 @@ void Pipeline::render_all() const if(fbo) { - fbo->bind(); - fbo->clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT); + Framebuffer *f = (fbo_ms ? fbo_ms : fbo); + f->bind(); + f->clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT); } for(vector::const_iterator i=effects.begin(); i!=effects.end(); ++i) @@ -175,13 +180,60 @@ void Pipeline::render_all() const (*--i)->cleanup(); if(fbo) + { + if(fbo_ms) + fbo->blit_from(*fbo_ms, COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT, false); Framebuffer::unbind(); + } // XXX Need two color buffer textures to handle multiple post-processors correctly for(vector::const_iterator i=postproc.begin(); i!=postproc.end(); ++i) (*i)->render(*color_buf, *depth_buf); } +void Pipeline::create_fbos() +{ + delete fbo; + delete color_buf; + delete depth_buf; + + delete fbo_ms; + fbo_ms = 0; + delete color_buf_ms; + color_buf_ms = 0; + delete depth_buf_ms; + depth_buf_ms = 0; + + fbo = new Framebuffer; + + color_buf = new Texture2D; + color_buf->set_min_filter(NEAREST); + color_buf->set_mag_filter(NEAREST); + color_buf->set_wrap(CLAMP_TO_EDGE); + color_buf->storage((hdr ? RGB16F : RGB), width, height); + fbo->attach(COLOR_ATTACHMENT0, *color_buf, 0); + + depth_buf = new Texture2D; + depth_buf->set_min_filter(NEAREST); + depth_buf->set_mag_filter(NEAREST); + depth_buf->set_wrap(CLAMP_TO_EDGE); + depth_buf->storage(DEPTH_COMPONENT, width, height); + fbo->attach(DEPTH_ATTACHMENT, *depth_buf, 0); + + if(samples) + { + fbo_ms = new Framebuffer; + + color_buf_ms = new Renderbuffer; + color_buf_ms->storage_multisample(samples, (hdr ? RGB16F : RGB), width, height); + fbo_ms->attach(COLOR_ATTACHMENT0, *color_buf_ms); + + depth_buf_ms = new Renderbuffer; + depth_buf_ms->storage_multisample(samples, DEPTH_COMPONENT, width, height); + fbo_ms->attach(DEPTH_ATTACHMENT, *depth_buf_ms); + } +} + Pipeline::Slot::Slot(const Renderable *r): renderable(r) diff --git a/source/pipeline.h b/source/pipeline.h index e4509af8..f7f7e06c 100644 --- a/source/pipeline.h +++ b/source/pipeline.h @@ -45,14 +45,20 @@ private: unsigned width; unsigned height; bool hdr; + unsigned samples; Framebuffer *fbo; Texture2D *color_buf; Texture2D *depth_buf; + Framebuffer *fbo_ms; + Renderbuffer *color_buf_ms; + Renderbuffer *depth_buf_ms; public: - Pipeline(unsigned, unsigned, bool); + Pipeline(unsigned, unsigned, bool = false); ~Pipeline(); + void set_hdr(bool); + void set_multisample(unsigned); void set_camera(const Camera *); PipelinePass &add_pass(const Tag &tag); @@ -67,6 +73,9 @@ public: virtual void render(Renderer &, const Tag &tag = Tag()) const; void render_all() const; + +private: + void create_fbos(); }; } // namespace GL diff --git a/source/renderbuffer.cpp b/source/renderbuffer.cpp index d28237be..bd37aeea 100644 --- a/source/renderbuffer.cpp +++ b/source/renderbuffer.cpp @@ -1,11 +1,12 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ #include "extension.h" +#include "ext_framebuffer_multisample.h" #include "ext_framebuffer_object.h" #include "renderbuffer.h" @@ -32,6 +33,16 @@ void Renderbuffer::storage(PixelFormat fmt, unsigned w, unsigned h) glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, fmt, width, height); } +void Renderbuffer::storage_multisample(unsigned samples, PixelFormat fmt, unsigned w, unsigned h) +{ + static RequireExtension _ext("GL_EXT_framebuffer_multisample"); + + Bind _bind(this, true); + width = w; + height = h; + glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples, fmt, width, height); +} + void Renderbuffer::bind() const { if(set_current(this)) diff --git a/source/renderbuffer.h b/source/renderbuffer.h index b88db17a..7f9d7a42 100644 --- a/source/renderbuffer.h +++ b/source/renderbuffer.h @@ -1,7 +1,7 @@ /* $Id$ This file is part of libmspgl -Copyright © 2007 Mikko Rasa, Mikkosoft Productions +Copyright © 2007, 2009-2011 Mikko Rasa, Mikkosoft Productions Distributed under the LGPL */ @@ -37,6 +37,7 @@ public: unsigned get_height() const { return height; } void storage(PixelFormat fmt, unsigned width, unsigned height); + void storage_multisample(unsigned, PixelFormat fmt, unsigned, unsigned); void bind() const;