Skip to content

Instantly share code, notes, and snippets.

@BlockoS
Created November 9, 2010 22:59
Show Gist options
  • Save BlockoS/670007 to your computer and use it in GitHub Desktop.
Save BlockoS/670007 to your computer and use it in GitHub Desktop.
// TODO :
// * Rename into Effect
// * Add attachRenderBuffer (depth, stencil)
#ifndef _PASS_H_
#define _PASS_H_
#include "Program.h"
#include "Texture.h"
#include "Renderbuffer.h"
namespace blcks
{
class Pass
{
protected:
struct Input
{
GLuint unit;
Texture *tex;
};
class BaseOutput
{
public:
virtual ~BaseOutput() {}
virtual void Attach() const = 0;
virtual void Detach() const = 0;
};
template<typename Image>
class Output : public BaseOutput
{
public:
Output(GLenum attachment, Image* target, int level=0, int layer=0);
Output(const Output& out);
virtual ~Output() {}
Output& operator=(const Output& out);
virtual void Attach() const { Log_Error(""); }
virtual void Detach() const { Log_Error(""); }
protected:
GLenum _attachment;
Image *_target;
GLint _level;
GLint _layer;
};
public:
typedef Output<Renderbuffer> RenderbufferOutput;
typedef Output<Texture2D> Texture2DOutput;
typedef Output<Texture3D> Texture3DOutput;
protected:
enum State
{
UNITIALIZED = 0,
COMPILATION_NEEDED,
READY
};
public:
Pass();
virtual ~Pass();
virtual bool Create (GLsizei width, GLsizei height, int nInputs=0);
virtual void Destroy();
virtual bool Compile();
virtual void Begin();
virtual void End();
virtual void Update() = 0;
bool AttachInput (unsigned int index, Texture* inTex);
template <typename Image>
bool AttachOutput(GLenum attachment, Image* target, int level=0, int layer=0);
protected:
int _state;
GLuint _framebuffer;
GLsizei _width, _height;
GLenum* _drawBuffers;
unsigned int _nInputs;
Input *_in;
unsigned int _nOutputs;
Pass::BaseOutput **_out;
};
template<typename Image>
Pass::Output<typename Image>::Output(GLenum attachment, Image* target, int level, int layer) :
_attachment(attachment),
_target(target),
_level(level),
_layer(layer)
{}
template<typename Image>
Pass::Output<typename Image>::Output(const Output& out) :
_attachment(out._attachment),
_target(out._target),
_level(out._level),
_layer(out._layer)
{}
template<typename Image>
Pass::Output<typename Image>& Pass::Output<typename Image>::operator=(const Output& out)
{
_attachment = out._attachment;
_target = out._target;
_level = out._level;
_layer = out._layer;
return *this;
}
template<>
void Pass::Output<Renderbuffer>::Attach() const
{
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, _attachment, GL_RENDERBUFFER, _target->Id());
}
template<>
void Pass::Output<Renderbuffer>::Detach() const
{
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, _attachment, GL_RENDERBUFFER, 0);
}
template<>
void Pass::Output<Texture2D>::Attach () const
{
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, _attachment, _target->GetType(), _target->Id(), _level);
}
template<>
void Pass::Output<Texture2D>::Detach () const
{
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, _attachment, _target->GetType(), 0, _level);
}
template<>
void Pass::Output<Texture3D>::Attach() const
{
glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, _attachment, _target->GetType(), _target->Id(), _level, _layer);
}
template<>
void Pass::Output<Texture3D>::Detach() const
{
glFramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, _attachment, _target->GetType(), 0, _level, _layer);
}
template<typename Image>
bool Pass::AttachOutput(GLenum attachment, Image* target, int level, int layer)
{
int index;
// Validate target
if(target->Width() != _width)
{
Log_Error("Target width (%d) does not match framebuffer width (%d)", target->Width(), _width);
return false;
}
if(target->Height() != _height)
{
Log_Error("Target height (%d) does not match framebuffer height (%d)",target->Height(), _height);
return false;
}
switch(attachment)
{
case GL_DEPTH_ATTACHMENT:
index = 0;
break;
case GL_STENCIL_ATTACHMENT:
index = 1;
break;
case GL_DEPTH_STENCIL_ATTACHMENT:
index = 2;
break;
default:
if((attachment < GL_COLOR_ATTACHMENT0) || (attachment > (GL_COLOR_ATTACHMENT0+_nOutputs-3)))
{
Log_Error("Unsupported attachment type: %x", attachment);
return false;
}
index = attachment - GL_COLOR_ATTACHMENT0;
break;
}
// Add it to output list
Pass::Output<Image> *output = new Pass::Output<Image>(attachment, target, level, layer);
if(output == NULL)
{
Log_Error("Memory allocation failed!");
return false;
}
_out[index] = output;
return true;
}
}
#endif // _PASS_H_
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment