#include "resources.h"
#include "scene.h"
#include "sequencetemplate.h"
-#include "tests.h"
using namespace std;
#include <msp/gl/extensions/arb_draw_buffers.h>
#include <msp/gl/extensions/arb_direct_state_access.h>
-#include <msp/gl/extensions/ext_framebuffer_blit.h>
#include <msp/gl/extensions/ext_framebuffer_object.h>
#include <msp/gl/extensions/ext_texture_array.h>
#include <msp/gl/extensions/ext_texture3d.h>
#include "renderbuffer.h"
#include "texture2d.h"
#include "texture3d.h"
+#include "windowview.h"
using namespace std;
Framebuffer::Framebuffer(unsigned i):
id(i),
+ status(FRAMEBUFFER_COMPLETE),
dirty(0)
{
if(id)
throw invalid_argument("System framebuffer must have id 0");
- glGetIntegerv(GL_VIEWPORT, &view.left);
- width = view.width;
- height = view.height;
+ int view[4];
+ glGetIntegerv(GL_VIEWPORT, view);
+ width = view[2];
+ height = view[3];
}
Framebuffer::Framebuffer():
width(0),
height(0),
+ status(FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT),
dirty(0)
{
static Require _req(EXT_framebuffer_object);
{
if(id)
glDeleteFramebuffers(1, &id);
- if(current()==this)
- unbind();
}
-void Framebuffer::update_attachment(unsigned mask) const
+void Framebuffer::update() const
{
- if(!ARB_direct_state_access && current()!=this)
- {
- dirty |= mask;
- return;
- }
-
vector<GLenum> color_bufs;
color_bufs.reserve(attachments.size());
for(unsigned i=0; i<attachments.size(); ++i)
{
const Attachment &attch = attachments[i];
- if(mask&(1<<i))
+ if(dirty&(1<<i))
{
if(attch.type==GL_RENDERBUFFER)
{
if(MSP_buffer_control)
glReadBuffer(first_buffer);
}
+
+ if(ARB_direct_state_access)
+ status = static_cast<FramebufferStatus>(glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER));
+ else
+ status = static_cast<FramebufferStatus>(glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ dirty = 0;
}
void Framebuffer::check_size()
{
- bool full_viewport = (view.left==0 && view.bottom==0 && view.width==width && view.height==height);
for(vector<Attachment>::iterator i=attachments.begin(); i!=attachments.end(); ++i)
if(i->type)
{
width = max(static_cast<TextureCube *>(i->tex)->get_size()>>i->level, 1U);
height = width;
}
- if(full_viewport)
- reset_viewport();
break;
}
}
unsigned i = get_attachment_index(attch);
attachments[i].set(tex, level, layer);
- update_attachment(1<<i);
+ dirty |= 1<<i;
check_size();
}
unsigned i = get_attachment_index(attch);
attachments[i].set(rbuf);
- update_attachment(1<<i);
+ dirty |= 1<<i;
check_size();
}
unsigned i = get_attachment_index(attch);
attachments[i].clear();
- update_attachment(1<<i);
+ dirty |= 1<<i;
check_size();
}
-FramebufferStatus Framebuffer::check_status() const
+void Framebuffer::resize(const WindowView &view)
{
- if(ARB_direct_state_access)
- return static_cast<FramebufferStatus>(glCheckNamedFramebufferStatus(id, GL_FRAMEBUFFER));
- else
- {
- BindRestore _bind(this);
- return static_cast<FramebufferStatus>(glCheckFramebufferStatus(GL_FRAMEBUFFER));
- }
+ if(id)
+ throw invalid_operation("Framebuffer::resize");
+
+ width = view.get_width();
+ height = view.get_height();
}
void Framebuffer::require_complete() const
{
- FramebufferStatus status = check_status();
if(status!=FRAMEBUFFER_COMPLETE)
throw framebuffer_incomplete(status);
}
-void Framebuffer::viewport(int l, int b, unsigned w, unsigned h)
-{
- view.left = l;
- view.bottom = b;
- view.width = w;
- view.height = h;
-
- if(current()==this)
- glViewport(view.left, view.bottom, view.width, view.height);
-}
-
-void Framebuffer::reset_viewport()
-{
- viewport(0, 0, width, height);
-}
-
-void Framebuffer::clear()
-{
- clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT|STENCIL_BUFFER_BIT);
-}
-
-void Framebuffer::clear(BufferBits bits)
-{
- BindRestore _bind(this);
- 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 Require _req(EXT_framebuffer_blit);
-
- if(ARB_direct_state_access)
- {
- glBlitNamedFramebuffer(other.id, id, sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, bits, (filter ? GL_LINEAR : GL_NEAREST));
- return;
- }
-
- const Framebuffer *old = current();
- if(set_current(this))
- {
- glBindFramebuffer(GL_DRAW_FRAMEBUFFER, id);
- if(dirty)
- {
- update_attachment(dirty);
- dirty = 0;
- }
- }
- if(old!=&other)
- glBindFramebuffer(GL_READ_FRAMEBUFFER, other.id);
-
- glBlitFramebuffer(sx0, sy0, sx1, sy1, dx0, dy0, dx1, dy1, bits, (filter ? GL_LINEAR : GL_NEAREST));
-
- set_current(old);
- glBindFramebuffer(GL_FRAMEBUFFER, (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(id && attachments.empty())
- throw invalid_operation("Framebuffer::bind");
-
- if(set_current(this))
- {
- glBindFramebuffer(GL_FRAMEBUFFER, id);
- if(dirty)
- {
- update_attachment(dirty);
- dirty = 0;
- }
-
- if(width && height)
- glViewport(view.left, view.bottom, view.width, view.height);
- }
-}
-
-const Framebuffer *Framebuffer::current()
-{
- if(!cur_obj)
- cur_obj = &system();
- return cur_obj;
-}
-
-void Framebuffer::unbind()
-{
- system().bind();
-}
-
void Framebuffer::set_debug_name(const string &name)
{
#ifdef DEBUG
type = 0;
}
-
-Framebuffer::Viewport::Viewport():
- left(0),
- bottom(0),
- width(0),
- height(0)
-{ }
-
} // namespace GL
} // namespace Msp
class Texture;
class Texture2D;
class Texture3D;
+class WindowView;
enum FramebufferAttachment
{
Requires the GL_EXT_framebuffer_object extension. The blit functions require
the GL_EXT_framebuffer_blit extension.
*/
-class Framebuffer: public Bindable<Framebuffer>
+class Framebuffer
{
private:
struct Attachment
void clear();
};
- struct Viewport
- {
- int left;
- int bottom;
- unsigned width;
- unsigned height;
-
- Viewport();
- };
-
unsigned id;
std::vector<Attachment> attachments;
unsigned width;
unsigned height;
- Viewport view;
+ mutable FramebufferStatus status;
mutable unsigned dirty;
Framebuffer(unsigned);
unsigned get_height() const { return height; }
private:
- void update_attachment(unsigned) const;
+ void update() const;
void check_size();
unsigned get_attachment_index(FramebufferAttachment);
void set_texture_attachment(FramebufferAttachment, Texture &, unsigned, int);
void attach_layered(FramebufferAttachment attch, TextureCube &tex, unsigned level = 0);
void detach(FramebufferAttachment attch);
- /** Checks the completeness of the framebuffer. Returns
- FRAMEBUFFER_COMPLETE if the framebuffer is complete and can be rendered to,
- or one of the error status codes otherwise. */
- FramebufferStatus check_status() const;
+ void resize(const WindowView &);
+
+ /** Returns FRAMEBUFFER_COMPLETE if the framebuffer is complete and can be
+ rendered to, or one of the error status codes otherwise. */
+ FramebufferStatus get_status() const { return status; }
/** Ensures that the framebuffer is complete, throwing an exception if it
isn't. */
void require_complete() const;
- void viewport(int, int, unsigned, unsigned);
- void reset_viewport();
-
- void clear();
- void clear(BufferBits);
-
- /** Blits a region from another framebuffer into this one. If the source
- and destination regions have different dimensions, the contents will be
- stretched. If filter is true, linear interpolation will be used, otherwise
- no interpolation is done. */
- void 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);
-
- /** Blits a region from another framebuffer into this one, retaining its
- dimensions. */
- void blit_from(const Framebuffer & other, int sx, int sy,
- unsigned wd, unsigned ht, int dx, int dy, BufferBits bits);
-
- /** Blits the entire contents of another framebuffer into this one. */
- void blit_from(const Framebuffer &other, BufferBits bits, bool filter);
-
- void bind() const;
+ void refresh() const { if(dirty) update(); }
- static const Framebuffer *current();
- static void unbind();
+ unsigned get_id() const { return id; }
void set_debug_name(const std::string &);
#include "buffer.h"
#include "deviceinfo.h"
#include "depthtest.h"
+#include "framebuffer.h"
#include "pipelinestate.h"
#include "program.h"
+#include "rect.h"
#include "stenciltest.h"
#include "texture.h"
#include "uniformblock.h"
vector<int> PipelineState::bound_tex_targets;
PipelineState::PipelineState():
+ framebuffer(0),
+ viewport(0),
+ scissor(0),
shprog(0),
vertex_setup(0),
front_face(COUNTERCLOCKWISE),
}
}
+void PipelineState::set_framebuffer(const Framebuffer *f)
+{
+ set(framebuffer, f, FRAMEBUFFER|VIEWPORT);
+}
+
+void PipelineState::set_viewport(const Rect *v)
+{
+ set(viewport, v, VIEWPORT);
+}
+
+void PipelineState::set_scissor(const Rect *s)
+{
+ set(scissor, s, SCISSOR);
+}
+
void PipelineState::set_shader_program(const Program *p)
{
set(shprog, p, SHPROG);
void PipelineState::apply(unsigned mask) const
{
+ if(mask&FRAMEBUFFER)
+ {
+ glBindFramebuffer(GL_FRAMEBUFFER, framebuffer ? framebuffer->get_id() : 0);
+ if(framebuffer)
+ {
+ framebuffer->refresh();
+ framebuffer->require_complete();
+ }
+ }
+
+ if(mask&VIEWPORT)
+ {
+ if(viewport)
+ glViewport(viewport->left, viewport->bottom, viewport->width, viewport->height);
+ else if(framebuffer)
+ glViewport(0, 0, framebuffer->get_width(), framebuffer->get_height());
+ }
+
+ if(mask&SCISSOR)
+ {
+ if(scissor)
+ {
+ glEnable(GL_SCISSOR_TEST);
+ glScissor(scissor->left, scissor->bottom, scissor->width, scissor->height);
+ }
+ else
+ glDisable(GL_SCISSOR_TEST);
+ }
+
if(mask&SHPROG)
glUseProgram(shprog ? shprog->get_id() : 0);
class BufferBackedUniformBlock;
class DefaultUniformBlock;
class DepthTest;
+class Framebuffer;
class Program;
+class Rect;
class Sampler;
class StencilTest;
class Texture;
UNIFORMS = 32,
DEPTH_TEST = 64,
STENCIL_TEST = 128,
- BLEND = 256
+ BLEND = 256,
+ FRAMEBUFFER = 512,
+ VIEWPORT = 1024,
+ SCISSOR = 2048
};
+ const Framebuffer *framebuffer;
+ const Rect *viewport;
+ const Rect *scissor;
const Program *shprog;
const VertexSetup *vertex_setup;
FaceWinding front_face;
template<typename T>
void set(T &, T, unsigned);
public:
+ void set_framebuffer(const Framebuffer *);
+ void set_viewport(const Rect *);
+ void set_scissor(const Rect *);
void set_shader_program(const Program *);
void set_vertex_setup(const VertexSetup *);
void set_front_face(FaceWinding);
--- /dev/null
+#ifndef MSP_GL_RECT_H_
+#define MSP_GL_RECT_H_
+
+namespace Msp {
+namespace GL {
+
+struct Rect
+{
+ int left;
+ int bottom;
+ unsigned width;
+ unsigned height;
+
+ Rect(): left(0), bottom(0), width(0), height(0) { }
+ Rect(int l, int b, unsigned w, unsigned h): left(l), bottom(b), width(w), height(h) { }
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
+++ /dev/null
-#include "tests.h"
-
-namespace Msp {
-namespace GL {
-
-ScissorTest::ScissorTest():
- left(0),
- bottom(0),
- width(1),
- height(1)
-{ }
-
-ScissorTest::ScissorTest(int l, int b, unsigned w, unsigned h):
- left(l),
- bottom(b),
- width(w),
- height(h)
-{ }
-
-void ScissorTest::bind() const
-{
- if(set_current(this))
- {
- glEnable(GL_SCISSOR_TEST);
- glScissor(left, bottom, width, height);
- }
-}
-
-void ScissorTest::unbind()
-{
- if(set_current(0))
- glDisable(GL_SCISSOR_TEST);
-}
-
-} // namespace GL
-} // namespace Msp
+++ /dev/null
-#ifndef MSP_GL_TESTS_H_
-#define MSP_GL_TESTS_H_
-
-#include "bindable.h"
-#include "gl.h"
-#include "predicate.h"
-
-namespace Msp {
-namespace GL {
-
-/**
-Tests fragment coordinates against a rectangle. Any fragments outside the
-rectangle are discarded.
-*/
-class ScissorTest: public Bindable<ScissorTest>
-{
-private:
- int left;
- int bottom;
- unsigned width;
- unsigned height;
-
-public:
- ScissorTest();
- ScissorTest(int, int, unsigned, unsigned);
-
- void bind() const;
-
- static void unbind();
-};
-
-} // namespace GL
-} // namespace Msp
-
-#endif
#include "renderer.h"
#include "resources.h"
#include "shader.h"
-#include "tests.h"
using namespace std;
void AmbientOcclusion::render(Renderer &renderer, const Texture2D &color, const Texture2D &depth)
{
+ const Framebuffer *out_fbo = renderer.get_framebuffer();
+
Renderer::Push push(renderer);
renderer.set_texture("source", &color, &nearest_clamp_sampler);
renderer.set_texture("depth", &depth, &nearest_clamp_sampler);
renderer.set_texture("rotate", &rotate_lookup, &nearest_sampler);
renderer.set_shader_program(&occlude_shader, &shdata);
- {
- BindRestore bind_fbo(occlude_target.get_framebuffer());
- quad.draw(renderer);
- }
+ renderer.set_framebuffer(&occlude_target.get_framebuffer());
+ quad.draw(renderer);
+ renderer.set_framebuffer(out_fbo);
renderer.set_shader_program(&combine_shader);
quad.draw(renderer);
}
#include "renderer.h"
#include "resources.h"
#include "shader.h"
-#include "tests.h"
using namespace std;
renderer.set_shader_program(&blur_shader, &common_shdata);
for(unsigned i=0; i<2; ++i)
{
- BindRestore bind_fbo(target[i]->get_framebuffer());
Renderer::Push push2(renderer);
+ renderer.set_framebuffer(&target[i]->get_framebuffer());
renderer.set_texture("source", (i ? &target[0]->get_target_texture(RENDER_COLOR) : &src), &nearest_sampler);
renderer.add_shader_data(blur_shdata[i]);
quad.draw(renderer);
TextureCubeFace face = TextureCube::enumerate_faces(i);
faces[i].fbo.attach(COLOR_ATTACHMENT0, env_tex, face, 0);
faces[i].fbo.attach(DEPTH_ATTACHMENT, depth_buf);
- faces[i].fbo.require_complete();
faces[i].camera.set_look_direction(TextureCube::get_face_direction(face));
faces[i].camera.set_up_direction(TextureCube::get_t_direction(face));
faces[i].camera.set_field_of_view(Geometry::Angle<float>::right());
Vector3 center = matrix->column(3).slice<3>(0);
- BindRestore bind_fbo(faces[0].fbo);
for(unsigned i=0; i<6; ++i)
{
faces[i].camera.set_position(center);
- faces[i].fbo.bind();
- faces[i].fbo.clear();
+ renderer.set_framebuffer(&faces[i].fbo);
+ renderer.clear();
renderer.set_camera(faces[i].camera);
renderer.render(environment);
}
- irradiance_fbo.bind();
+ renderer.set_framebuffer(&irradiance_fbo);
renderer.set_shader_program(&irradiance_shprog, &prefilter_shdata);
renderer.set_texture("environment_map", &env_tex, &sampler);
fullscreen_mesh.draw(renderer);
for(unsigned i=0; i<specular_fbos.size(); ++i)
{
prefilter_shdata.uniform("roughness", 1.0f-sqrt(1.0f-static_cast<float>(i+1)/specular_fbos.size()));
- specular_fbos[i].bind();
+ renderer.set_framebuffer(&specular_fbos[i]);
fullscreen_mesh.draw(renderer);
}
}
depth_buf.storage(DEPTH_COMPONENT32F, size, size, 1);
fbo.attach(DEPTH_ATTACHMENT, depth_buf, 0);
- fbo.require_complete();
depth_test.enabled = true;
depth_test.compare = LEQUAL;
shdata.uniform("shd_world_matrix", shadow_matrix);
- BindRestore bind_fbo(fbo);
- fbo.clear(DEPTH_BUFFER_BIT);
-
Renderer::Push push(renderer);
+ renderer.set_framebuffer(&fbo);
+ renderer.clear(DEPTH_BUFFER_BIT);
renderer.set_camera(shadow_camera);
renderer.set_depth_test(&depth_test);
if(transmittance_lookup_dirty)
{
transmittance_lookup_dirty = false;
- Bind bind_fbo(transmittance_lookup.get_framebuffer());
+ renderer.set_framebuffer(&transmittance_lookup.get_framebuffer());
renderer.set_shader_program(&transmittance_shprog, &shdata);
fullscreen_mesh.draw(renderer);
}
- Bind bind_fbo(distant.get_framebuffer());
+ renderer.set_framebuffer(&distant.get_framebuffer());
renderer.set_shader_program(&distant_shprog, &shdata);
renderer.set_texture("transmittance_lookup", &transmittance_lookup.get_target_texture(0), &sampler);
fullscreen_mesh.draw(renderer);
const Mesh &mesh = resources.get<Mesh>("_fullscreen_quad.mesh");
Framebuffer fresnel_lookup_fbo;
fresnel_lookup_fbo.attach(COLOR_ATTACHMENT0, *fresnel_lookup);
- Bind bind_fbo(fresnel_lookup_fbo);
Renderer renderer;
+ renderer.set_framebuffer(&fresnel_lookup_fbo);
renderer.set_shader_program(&shprog, &shdata);
mesh.draw(renderer);
+#include <msp/gl/extensions/arb_direct_state_access.h>
+#include <msp/gl/extensions/ext_framebuffer_blit.h>
+#include <msp/gl/extensions/ext_framebuffer_object.h>
#include "batch.h"
#include "buffer.h"
#include "camera.h"
changed |= MATRIX;
}
+void Renderer::set_framebuffer(const Framebuffer *f)
+{
+ state->framebuffer = f;
+}
+
+void Renderer::set_viewport(const Rect *v)
+{
+ state->viewport = v;
+}
+
+void Renderer::set_scissor(const Rect *s)
+{
+ state->scissor = s;
+}
+
void Renderer::set_texture(Tag tag, const Texture *tex, const Sampler *samp)
{
if(tex)
renderable.render(*this, tag);
}
+void Renderer::clear()
+{
+ clear(COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT|STENCIL_BUFFER_BIT);
+}
+
+void Renderer::clear(BufferBits buffers)
+{
+ pipeline_state.set_framebuffer(state->framebuffer);
+ pipeline_state.apply();
+ glClear(buffers);
+}
+
void Renderer::draw(const Batch &batch)
{
apply_state();
batch.draw_instanced(count);
}
+void Renderer::resolve_multisample(Framebuffer &target, BufferBits buffers)
+{
+ if(!state->framebuffer)
+ throw invalid_operation("Renderer::resolve_multisample");
+
+ unsigned width = state->framebuffer->get_width();
+ unsigned height = state->framebuffer->get_height();
+ if(target.get_width()!=width || target.get_height()!=height)
+ throw incompatible_data("Renderer::resolve_multisample");
+
+ if(ARB_direct_state_access)
+ glBlitNamedFramebuffer(state->framebuffer->get_id(), target.get_id(), 0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST);
+ else
+ {
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, state->framebuffer->get_id());
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target.get_id());
+
+ target.refresh();
+
+ glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, buffers, GL_NEAREST);
+
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+ pipeline_state.set_framebuffer(0);
+ }
+}
+
void Renderer::apply_state()
{
if(!state->shprog)
changed &= ~MATRIX;
}
+ pipeline_state.set_framebuffer(state->framebuffer);
+ pipeline_state.set_viewport(state->viewport);
+ pipeline_state.set_scissor(state->scissor);
+
bool shprog_changed = (state->shprog!=pipeline_state.get_shader_program());
pipeline_state.set_shader_program(state->shprog);
Renderer::State::State():
camera(0),
+ framebuffer(0),
+ viewport(0),
+ scissor(0),
texture_count(0),
lowest_effect_texunit(Limits::get_global().max_texture_bindings),
clipping(0),
#include <set>
#include <vector>
+#include "framebuffer.h"
#include "matrix.h"
#include "pipelinestate.h"
#include "programdata.h"
{
const Camera *camera;
Matrix model_matrix;
+ const Framebuffer *framebuffer;
+ const Rect *viewport;
+ const Rect *scissor;
unsigned texture_count;
unsigned lowest_effect_texunit;
const Clipping *clipping;
/** Returns the current model matrix. */
const Matrix &get_matrix() const { return state->model_matrix; }
+ void set_framebuffer(const Framebuffer *);
+ void set_viewport(const Rect *);
+ void set_scissor(const Rect *);
+
+ const Framebuffer *get_framebuffer() const { return state->framebuffer; }
+
void set_texture(Tag, const Texture *, const Sampler * = 0);
private:
void flush_textures();
void exclude(const Renderable &);
void include(const Renderable &);
+ void clear();
+ void clear(BufferBits);
+
void render(const Renderable &, Tag = Tag());
void draw(const Batch &);
void draw_instanced(const Batch &, unsigned);
+ void resolve_multisample(Framebuffer &, BufferBits);
+
private:
void apply_state();
};
}
buffers.push_back(tgt);
}
-
- fbo.require_complete();
}
RenderTarget::~RenderTarget()
return get_target_texture(index);
}
-void RenderTarget::blit_from(const RenderTarget &other)
-{
- fbo.blit_from(other.fbo, COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT, false);
-}
-
void RenderTarget::set_debug_name(const string &name)
{
#ifdef DEBUG
Framebuffer &get_framebuffer() { return fbo; }
const Texture2D &get_target_texture(unsigned) const;
const Texture2D &get_target_texture(RenderOutput) const;
- void blit_from(const RenderTarget &);
void set_debug_name(const std::string &);
};
#include "renderbuffer.h"
#include "renderer.h"
#include "sequence.h"
-#include "tests.h"
#include "texture2d.h"
#include "view.h"
if(tag.id)
return;
- const Framebuffer *out_fbo = Framebuffer::current();
- // These are no-ops but will ensure the related state gets restored
- BindRestore restore_fbo(out_fbo);
+ Renderer::Push _push(renderer);
+
+ const Framebuffer *out_fbo = renderer.get_framebuffer();
if(target[0])
{
- Framebuffer &fbo = (samples ? target_ms : target[0])->get_framebuffer();
- fbo.bind();
- fbo.clear();
+ renderer.set_framebuffer(&(samples ? target_ms : target[0])->get_framebuffer());
+ renderer.clear();
}
for(vector<Step>::const_iterator i=steps.begin(); i!=steps.end(); ++i)
{
- Renderer::Push push(renderer);
+ Renderer::Push _push2(renderer);
renderer.set_depth_test(&i->get_depth_test());
renderer.set_stencil_test(&i->get_stencil_test());
if(target[0])
{
+ if(samples)
+ renderer.resolve_multisample(target[0]->get_framebuffer(), COLOR_BUFFER_BIT|DEPTH_BUFFER_BIT);
+
renderer.set_depth_test(0);
renderer.set_stencil_test(0);
renderer.set_blend(0);
- if(samples)
- target[0]->blit_from(*target_ms);
-
for(unsigned i=0; i<postproc.size(); ++i)
{
unsigned j = i%2;
- if(i+1<postproc.size())
- target[1-j]->get_framebuffer().bind();
- else
- out_fbo->bind();
+ renderer.set_framebuffer(i+1<postproc.size() ? &target[1-j]->get_framebuffer() : out_fbo);
const Texture2D &color = target[j]->get_target_texture(RENDER_COLOR);
const Texture2D &depth = target[j]->get_target_texture(RENDER_DEPTH);
postproc[i].postproc->render(renderer, color, depth);
void View::render(Renderer &renderer)
{
- Bind bind_fbo(target);
- target.clear();
+ Renderer::Push _push(renderer);
+ renderer.set_framebuffer(&target);
+ renderer.clear();
if(content)
{
- Renderer::Push push(renderer);
if(camera)
renderer.set_camera(*camera);
content->setup_frame(renderer);
void WindowView::window_resized(unsigned w, unsigned h)
{
- target.viewport(0, 0, w, h);
+ Framebuffer::system().resize(*this);
float aspect = static_cast<float>(w)/h;
if(camera)
camera->set_aspect_ratio(aspect);