Created
November 9, 2010 22:59
-
-
Save BlockoS/670007 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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