--- /dev/null
+/* $Id$
+
+This file is part of libmspgl
+Copyright © 2010 Mikko Rasa, Mikkosoft Productions
+Distributed under the LGPL
+*/
+
+#ifndef MSP_GL_BINDABLE_H_
+#define MSP_GL_BINDABLE_H_
+
+namespace Msp {
+namespace GL {
+
+template<typename T>
+class Bindable
+{
+protected:
+ static const T *cur_obj;
+
+ Bindable() { }
+
+ static bool set_current(const T *obj)
+ {
+ if(obj==cur_obj)
+ return false;
+
+ cur_obj=obj;
+ return true;
+ }
+
+public:
+ const T *current() const { return cur_obj; }
+};
+
+template<typename T>
+const T *Bindable<T>::cur_obj;
+
+
+/**
+RAII class for binding things. Binds the thing upon construction and unbinds
+it upon destruction. If a null pointer is given, unbinds upon construction and
+does nothing upon destruction.
+*/
+class Bind
+{
+private:
+ struct Base
+ {
+ virtual ~Base() { }
+ };
+
+ template<typename T>
+ struct Binder: Base
+ {
+ const T &obj;
+
+ Binder(const T &o): obj(o) { obj.bind(); }
+ ~Binder() { obj.unbind(); }
+ };
+
+ Base *binder;
+
+public:
+ template<typename T>
+ Bind(const T &o): binder(new Binder<T>(o)) { }
+
+ template<typename T>
+ Bind(const T *o): binder(o ? new Binder<T>(*o) : 0) { if(!o) T::unbind(); }
+
+private:
+ Bind(const Bind &);
+ Bind &operator=(const Bind &);
+
+public:
+ ~Bind() { delete binder; }
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif
/* $Id$
This file is part of libmspgl
-Copyright © 2008 Mikko Rasa, Mikkosoft Productions
+Copyright © 2008, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
namespace Msp {
namespace GL {
+Blend::Blend():
+ eq(ADD),
+ src_factor(ONE),
+ dst_factor(ZERO)
+{ }
+
+Blend::Blend(BlendFactor sf, BlendFactor df):
+ eq(ADD),
+ src_factor(sf),
+ dst_factor(df)
+{ }
+
+Blend::Blend(BlendEquation e, BlendFactor sf, BlendFactor df):
+ eq(e),
+ src_factor(sf),
+ dst_factor(df)
+{
+ if(eq!=ADD)
+ static RequireVersion _ver(1, 2);
+}
+
+void Blend::bind() const
+{
+ if(set_current(this))
+ {
+ glEnable(GL_BLEND);
+ // XXX Don't try to set equation if version < 1.2
+ glBlendEquation(eq);
+ glBlendFunc(src_factor, dst_factor);
+ }
+}
+
+const Blend &Blend::alpha()
+{
+ static Blend blend(SRC_ALPHA, ONE_MINUS_SRC_ALPHA);
+ return blend;
+}
+
+void Blend::unbind()
+{
+ if(set_current(0))
+ glDisable(GL_BLEND);
+}
+
+
void blend_equation(BlendEquation eq)
{
static RequireVersion _ver(1, 2);
/* $Id$
This file is part of libmspgl
-Copyright © 2008 Mikko Rasa, Mikkosoft Productions
+Copyright © 2008, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
#ifndef MSP_GL_BLEND_H_
#define MSP_GL_BLEND_H_
+#include "bindable.h"
#include "gl.h"
namespace Msp {
ONE_MINUS_CONSTANT_ALPHA = GL_ONE_MINUS_CONSTANT_ALPHA
};
+/**
+Blends incoming fragments with those already in the framebuffer.
+*/
+class Blend: public Bindable<Blend>
+{
+private:
+ BlendEquation eq;
+ BlendFactor src_factor;
+ BlendFactor dst_factor;
+
+public:
+ Blend();
+ Blend(BlendFactor, BlendFactor);
+ Blend(BlendEquation, BlendFactor, BlendFactor);
+
+ void bind() const;
+
+ static const Blend &alpha();
+ static void unbind();
+};
+
void blend_equation(BlendEquation eq);
void blend_func(BlendFactor src, BlendFactor dst);
void get(GLenum, int *);
int get_i(GLenum);
-class Bind
-{
-private:
- struct Base
- {
- virtual ~Base() { }
- };
-
- template<typename T>
- struct Binder: Base
- {
- const T &obj;
-
- Binder(const T &o): obj(o) { obj.bind(); }
- ~Binder() { obj.unbind(); }
- };
-
- Base *binder;
-
-public:
- template<typename T>
- Bind(const T &o): binder(new Binder<T>(o)) { }
- ~Bind() { delete binder; }
-};
-
} // namespace GL
} // namespace Msp
/* $Id$
This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
#define MSP_GL_OBJECT_H_
#include <vector>
-#include "misc.h"
+#include "bindable.h"
#include "renderable.h"
#include "renderpass.h"
/* $Id$
This file is part of libmspgl
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
+#include "blend.h"
#include "camera.h"
#include "effect.h"
#include "except.h"
#include "pipeline.h"
#include "postprocessor.h"
#include "renderbuffer.h"
+#include "tests.h"
#include "texture2d.h"
using namespace std;
void Pipeline::render(const Tag &tag) const
{
const PipelinePass &pass=get_pass(tag);
- if(pass.lighting)
- pass.lighting->bind();
+
+ Bind bind_depth_test(pass.depth_test);
+ Bind bind_blend(pass.blend);
+ Bind bind_lighting(pass.lighting);
+
for(vector<Effect *>::const_iterator i=pass.effects.begin(); i!=pass.effects.end(); ++i)
(*i)->prepare();
+
for(vector<const Renderable *>::const_iterator i=renderables.begin(); i!=renderables.end(); ++i)
(*i)->render(tag);
- for(vector<Effect *>::const_iterator i=pass.effects.end(); i--!=pass.effects.begin();)
- (*i)->cleanup();
- if(pass.lighting)
- Lighting::unbind();
+
+ for(vector<Effect *>::const_iterator i=pass.effects.end(); i!=pass.effects.begin();)
+ (*--i)->cleanup();
}
void Pipeline::render_all() const
for(vector<Effect *>::const_iterator i=effects.begin(); i!=effects.end(); ++i)
(*i)->prepare();
+
for(vector<Tag>::const_iterator i=pass_order.begin(); i!=pass_order.end(); ++i)
render(*i);
- for(vector<Effect *>::const_iterator i=effects.end(); i--!=effects.begin();)
- (*i)->cleanup();
+
+ for(vector<Effect *>::const_iterator i=effects.end(); i!=effects.begin();)
+ (*--i)->cleanup();
if(fbo)
Framebuffer::unbind();
/* $Id$
This file is part of libmspgl
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
namespace GL {
PipelinePass::PipelinePass():
- lighting(0)
+ lighting(0),
+ depth_test(0),
+ blend(0)
{ }
} // namespace GL
/* $Id$
This file is part of libmspgl
-Copyright © 2009 Mikko Rasa, Mikkosoft Productions
+Copyright © 2009-2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
namespace Msp {
namespace GL {
+class Blend;
+class DepthTest;
class Effect;
class Lighting;
{
std::vector<Effect *> effects;
const Lighting *lighting;
+ const DepthTest *depth_test;
+ const Blend *blend;
PipelinePass();
};
/* $Id$
This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2007, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
namespace Msp {
namespace GL {
-void scissor(int left, int bottom, unsigned width, unsigned height)
+AlphaTest::AlphaTest():
+ pred(ALWAYS),
+ ref(0)
+{ }
+
+AlphaTest::AlphaTest(Predicate p, float r):
+ pred(p),
+ ref(r)
+{ }
+
+void AlphaTest::bind() const
{
- glScissor(left, bottom, width, height);
+ if(set_current(this))
+ {
+ glEnable(GL_ALPHA_TEST);
+ glAlphaFunc(pred, ref);
+ }
+}
+
+void AlphaTest::unbind()
+{
+ if(set_current(0))
+ glDisable(GL_ALPHA_TEST);
}
void alpha_func(Predicate func, float ref)
glAlphaFunc(func, ref);
}
+
+DepthTest::DepthTest():
+ write(true),
+ pred(LESS)
+{ }
+
+DepthTest::DepthTest(Predicate p, bool w):
+ write(w),
+ pred(p)
+{ }
+
+void DepthTest::bind() const
+{
+ if(set_current(this))
+ {
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(pred);
+ glDepthMask(write);
+ }
+}
+
+const DepthTest &DepthTest::lequal()
+{
+ static DepthTest test(LEQUAL);
+ return test;
+}
+
+void DepthTest::unbind()
+{
+ if(set_current(0))
+ glDisable(GL_DEPTH_TEST);
+}
+
void depth_func(Predicate func)
{
glDepthFunc(func);
}
+
+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);
+}
+
+void scissor(int left, int bottom, unsigned width, unsigned height)
+{
+ glScissor(left, bottom, width, height);
+}
+
} // namespace GL
} // namespace Msp
/* $Id$
This file is part of libmspgl
-Copyright © 2007 Mikko Rasa, Mikkosoft Productions
+Copyright © 2007, 2010 Mikko Rasa, Mikkosoft Productions
Distributed under the LGPL
*/
#ifndef MSP_GL_TESTS_H_
#define MSP_GL_TESTS_H_
+#include "bindable.h"
#include "gl.h"
#include "predicate.h"
DEPTH_TEST = GL_DEPTH_TEST
};
-void scissor(int left, int bottom, unsigned width, unsigned height);
+/**
+Tests incoming fragment alpha values against a reference. If the test fails,
+the fragment is discarded.
+*/
+class AlphaTest: public Bindable<AlphaTest>
+{
+private:
+ Predicate pred;
+ float ref;
+
+public:
+ AlphaTest();
+ AlphaTest(Predicate, float);
+
+ void bind() const;
+
+ static void unbind();
+};
void alpha_func(Predicate func, float ref);
+
+/**
+Tests incoming fragment depth values against the depth buffer. If the test
+fails, the fragment is discarded.
+*/
+class DepthTest: public Bindable<DepthTest>
+{
+private:
+ bool write;
+ Predicate pred;
+
+ static const DepthTest *current;
+
+public:
+ DepthTest();
+ DepthTest(Predicate, bool = true);
+
+ void bind() const;
+
+ static const DepthTest &lequal();
+ static void unbind();
+};
+
void depth_func(Predicate func);
+
+/**
+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();
+};
+
+void scissor(int left, int bottom, unsigned width, unsigned height);
+
} // namespace GL
} // namespace Msp