You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
665 lines
24 KiB
665 lines
24 KiB
#ifndef GLW_PROGRAM_H |
|
#define GLW_PROGRAM_H |
|
|
|
#include <memory.h> |
|
|
|
#include <string> |
|
#include <vector> |
|
#include <map> |
|
|
|
#include "./vertexshader.h" |
|
#include "./geometryshader.h" |
|
#include "./fragmentshader.h" |
|
|
|
namespace glw |
|
{ |
|
|
|
typedef std::vector<ShaderHandle> ShaderHandleVector; |
|
|
|
class VertexAttributeBinding |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef VertexAttributeBinding ThisType; |
|
|
|
typedef std::map<std::string, GLuint> Map; |
|
typedef Map::const_iterator ConstIterator; |
|
typedef Map::iterator Iterator; |
|
typedef Map::value_type Value; |
|
|
|
Map bindings; |
|
|
|
VertexAttributeBinding(void) |
|
{ |
|
this->clear(); |
|
} |
|
|
|
void clear(void) |
|
{ |
|
this->bindings.clear(); |
|
} |
|
|
|
GLuint operator [] (const std::string & attributeName) const |
|
{ |
|
return this->bindings.find(attributeName)->second; |
|
} |
|
|
|
GLuint & operator [] (const std::string & attributeName) |
|
{ |
|
return this->bindings[attributeName]; |
|
} |
|
}; |
|
|
|
class GeometryStage |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef GeometryStage ThisType; |
|
|
|
/* |
|
GLenum inputPrimitiveType; |
|
GLenum outputPrimitiveType; |
|
GLint maxOutputVertices; |
|
*/ |
|
|
|
GeometryStage(void) |
|
{ |
|
this->clear(); |
|
} |
|
|
|
void clear(void) |
|
{ |
|
/* |
|
this->inputPrimitiveType = GLW_DONT_CARE; |
|
this->outputPrimitiveType = GLW_DONT_CARE; |
|
this->maxOutputVertices = GLW_DONT_CARE; |
|
*/ |
|
} |
|
}; |
|
|
|
class TransformFeedbackStream |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef TransformFeedbackStream ThisType; |
|
|
|
typedef std::vector<std::string> VaryingVector; |
|
|
|
VaryingVector varyings; |
|
GLenum bufferMode; |
|
|
|
TransformFeedbackStream(void) |
|
{ |
|
this->clear(); |
|
} |
|
|
|
void clear(void) |
|
{ |
|
this->varyings.clear(); |
|
this->bufferMode = GL_INTERLEAVED_ATTRIBS; |
|
} |
|
}; |
|
|
|
class RasterizerSettings |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef RasterizerSettings ThisType; |
|
|
|
enum RasterizerExecution |
|
{ |
|
DontCare = 0, |
|
Autodetect, |
|
ForceEnabled, |
|
ForceDisabled |
|
}; |
|
|
|
// TODO |
|
//RasterizerExecution execution; |
|
|
|
RasterizerSettings(void) |
|
{ |
|
this->clear(); |
|
} |
|
|
|
void clear(void) |
|
{ |
|
//this->execution = ThisType::Autodetect; |
|
} |
|
}; |
|
|
|
class FragmentOutputBinding |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef FragmentOutputBinding ThisType; |
|
|
|
typedef std::map<std::string, GLuint> Map; |
|
typedef Map::const_iterator ConstIterator; |
|
typedef Map::iterator Iterator; |
|
typedef Map::value_type Value; |
|
|
|
Map bindings; |
|
|
|
FragmentOutputBinding(void) |
|
{ |
|
this->clear(); |
|
} |
|
|
|
void clear(void) |
|
{ |
|
this->bindings.clear(); |
|
} |
|
|
|
GLuint operator [] (const std::string & outName) const |
|
{ |
|
return this->bindings.find(outName)->second; |
|
} |
|
|
|
GLuint & operator [] (const std::string & outName) |
|
{ |
|
return this->bindings[outName]; |
|
} |
|
}; |
|
|
|
class ProgramArguments : public ObjectArguments |
|
{ |
|
public: |
|
|
|
typedef ObjectArguments BaseType; |
|
typedef ProgramArguments ThisType; |
|
|
|
ShaderHandleVector shaders; |
|
VertexAttributeBinding vertexInputs; |
|
GeometryStage geometryStage; |
|
TransformFeedbackStream feedbackStream; |
|
RasterizerSettings rasterSettings; |
|
FragmentOutputBinding fragmentOutputs; |
|
|
|
ProgramArguments(void) |
|
: BaseType() |
|
{ |
|
; |
|
} |
|
|
|
void clear(void) |
|
{ |
|
BaseType::clear(); |
|
this->shaders .clear(); |
|
this->vertexInputs .clear(); |
|
this->geometryStage .clear(); |
|
this->feedbackStream .clear(); |
|
this->rasterSettings .clear(); |
|
this->fragmentOutputs .clear(); |
|
} |
|
}; |
|
|
|
class Program : public Object |
|
{ |
|
friend class Context; |
|
|
|
public: |
|
|
|
typedef Object BaseType; |
|
typedef Program ThisType; |
|
|
|
virtual ~Program(void) |
|
{ |
|
this->destroy(); |
|
} |
|
|
|
virtual Type type(void) const |
|
{ |
|
return ProgramType; |
|
} |
|
|
|
const ProgramArguments & arguments(void) const |
|
{ |
|
return this->m_arguments; |
|
} |
|
|
|
const std::string & log(void) const |
|
{ |
|
return this->m_log; |
|
} |
|
|
|
const std::string & fullLog(void) const |
|
{ |
|
return this->m_fullLog; |
|
} |
|
|
|
bool isLinked(void) const |
|
{ |
|
return this->m_linked; |
|
} |
|
|
|
GLint getUniformLocation(const std::string & name) const |
|
{ |
|
#if GLW_ASSERT_UNIFORM_LOCATION |
|
GLW_ASSERT(this->m_uniforms.count(name) > 0); |
|
#endif |
|
UniformMapConstIterator it = this->m_uniforms.find(name); |
|
if (it == this->m_uniforms.end()) return -1; |
|
return it->second.location; |
|
} |
|
|
|
#define _GLW_IMPLEMENT_SCALAR_UNIFORM_(TYPE, FUNCION_SUFFIX) \ |
|
void setUniform (const std::string & name, TYPE x ) { glUniform1 ## FUNCION_SUFFIX (this->getUniformLocation(name), x ); } \ |
|
void setUniform (const std::string & name, TYPE x, TYPE y ) { glUniform2 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y ); } \ |
|
void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z ) { glUniform3 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y, z ); } \ |
|
void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z, TYPE w ) { glUniform4 ## FUNCION_SUFFIX (this->getUniformLocation(name), x, y, z, w); } |
|
|
|
#define _GLW_IMPLEMENT_VECTOR_UNIFORM_(TYPE, FUNCION_SUFFIX) \ |
|
void setUniform1 (const std::string & name, const TYPE * v, int count = 1) { glUniform1 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \ |
|
void setUniform2 (const std::string & name, const TYPE * v, int count = 1) { glUniform2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \ |
|
void setUniform3 (const std::string & name, const TYPE * v, int count = 1) { glUniform3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } \ |
|
void setUniform4 (const std::string & name, const TYPE * v, int count = 1) { glUniform4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), v ); } |
|
|
|
#define _GLW_IMPLEMENT_MATRIX_UNIFORM_(TYPE, FUNCION_SUFFIX) \ |
|
void setUniform2x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform2x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2x3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform2x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix2x4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform3x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3x2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform3x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform3x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix3x4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform4x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4x2 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform4x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4x3 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } \ |
|
void setUniform4x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { glUniformMatrix4 ## FUNCION_SUFFIX ## v (this->getUniformLocation(name), GLsizei(count), GLboolean(transpose), m ); } |
|
|
|
_GLW_IMPLEMENT_SCALAR_UNIFORM_(int, i ) |
|
_GLW_IMPLEMENT_SCALAR_UNIFORM_(unsigned int, ui) |
|
_GLW_IMPLEMENT_SCALAR_UNIFORM_(float, f ) |
|
// _GLW_IMPLEMENT_SCALAR_UNIFORM_(double, d ) |
|
_GLW_IMPLEMENT_VECTOR_UNIFORM_(int, i ) |
|
_GLW_IMPLEMENT_VECTOR_UNIFORM_(unsigned int, ui) |
|
_GLW_IMPLEMENT_VECTOR_UNIFORM_(float, f ) |
|
// _GLW_IMPLEMENT_VECTOR_UNIFORM_(double, d ) |
|
_GLW_IMPLEMENT_MATRIX_UNIFORM_(float, f ) |
|
// _GLW_IMPLEMENT_MATRIX_UNIFORM_(double, d ) |
|
|
|
GLW_IMPLEMENT_CUSTOM_UNIFORMS; |
|
|
|
#undef _GLW_IMPLEMENT_SCALAR_UNIFORM_ |
|
#undef _GLW_IMPLEMENT_VECTOR_UNIFORM_ |
|
#undef _GLW_IMPLEMENT_MATRIX_UNIFORM_ |
|
|
|
protected: |
|
|
|
Program(Context * ctx) |
|
: BaseType (ctx) |
|
, m_linked (false) |
|
{ |
|
; |
|
} |
|
|
|
bool create(const ProgramArguments & args) |
|
{ |
|
this->destroy(); |
|
|
|
this->m_arguments = args; |
|
|
|
GLint boundName = 0; |
|
glGetIntegerv(GL_CURRENT_PROGRAM, &boundName); |
|
|
|
this->m_name = glCreateProgram(); |
|
this->m_fullLog = ""; |
|
|
|
// shaders |
|
{ |
|
for (size_t i=0; i<this->m_arguments.shaders.size(); ++i) |
|
{ |
|
const ShaderHandle & shader = this->m_arguments.shaders[i]; |
|
if (!shader) continue; |
|
this->m_fullLog += shader->log(); |
|
if (!shader->isCompiled()) continue; |
|
glAttachShader(this->m_name, shader->name()); |
|
} |
|
} |
|
|
|
// vertex |
|
{ |
|
for (VertexAttributeBinding::ConstIterator it=this->m_arguments.vertexInputs.bindings.begin(); it!=this->m_arguments.vertexInputs.bindings.end(); ++it) |
|
{ |
|
glBindAttribLocation(this->m_name, it->second, it->first.c_str()); |
|
} |
|
} |
|
|
|
// geometry |
|
{ |
|
; |
|
} |
|
|
|
// transform feedback |
|
{ |
|
const size_t count = this->m_arguments.feedbackStream.varyings.size(); |
|
if (count > 0) |
|
{ |
|
const char ** varyings = new const char * [count]; |
|
for (size_t i=0; i<count; ++i) |
|
{ |
|
varyings[i] = this->m_arguments.feedbackStream.varyings[i].c_str(); |
|
} |
|
glTransformFeedbackVaryings(this->m_name, GLsizei(count), varyings, this->m_arguments.feedbackStream.bufferMode); |
|
delete [] varyings; |
|
} |
|
} |
|
|
|
// TODO |
|
// rasterizer |
|
{ |
|
; |
|
} |
|
|
|
// fragment |
|
{ |
|
for (FragmentOutputBinding::ConstIterator it=this->m_arguments.fragmentOutputs.bindings.begin(); it!=this->m_arguments.fragmentOutputs.bindings.end(); ++it) |
|
{ |
|
glBindFragDataLocation(this->m_name, it->second, it->first.c_str()); |
|
} |
|
} |
|
|
|
glLinkProgram(this->m_name); |
|
|
|
GLint linkStatus = 0; |
|
glGetProgramiv(this->m_name, GL_LINK_STATUS, &linkStatus); |
|
|
|
this->m_log = ThisType::getInfoLog(this->m_name); |
|
this->m_fullLog += this->m_log; |
|
this->m_linked = (linkStatus != GL_FALSE); |
|
|
|
#if GLW_PRINT_LOG_TO_STDERR |
|
std::cerr << "---------------------------" << std::endl; |
|
std::cerr << "[Program Link Log]: " << ((this->m_linked) ? ("OK") : ("FAILED")) << std::endl; |
|
std::cerr << this->m_log << std::endl; |
|
std::cerr << "---------------------------" << std::endl; |
|
#endif |
|
|
|
if (this->m_linked) |
|
{ |
|
this->postLink(); |
|
} |
|
|
|
glUseProgram(boundName); |
|
|
|
return this->m_linked; |
|
} |
|
|
|
virtual void doDestroy() |
|
{ |
|
glDeleteProgram(this->m_name); |
|
this->m_arguments.clear(); |
|
this->m_log.clear(); |
|
this->m_fullLog.clear(); |
|
this->m_linked = false; |
|
} |
|
|
|
virtual bool doIsValid(void) const |
|
{ |
|
return this->m_linked; |
|
} |
|
|
|
private: |
|
|
|
class UniformInfo |
|
{ |
|
public: |
|
|
|
typedef void BaseType; |
|
typedef UniformInfo ThisType; |
|
|
|
std::string name; |
|
GLint location; |
|
GLenum type; |
|
GLint size; |
|
|
|
UniformInfo(void) |
|
: location (-1) |
|
, type (GL_NONE) |
|
, size (0) |
|
{ |
|
; |
|
} |
|
}; |
|
|
|
typedef std::map<std::string, UniformInfo> UniformMap; |
|
typedef UniformMap::const_iterator UniformMapConstIterator; |
|
typedef UniformMap::iterator UniformMapIterator; |
|
typedef UniformMap::value_type UniformMapValue; |
|
|
|
ProgramArguments m_arguments; |
|
UniformMap m_uniforms; |
|
std::string m_log; |
|
std::string m_fullLog; |
|
bool m_linked; |
|
|
|
static std::string getInfoLog(GLuint Program) |
|
{ |
|
std::string log; |
|
GLint logLen = 0; |
|
glGetProgramiv(Program, GL_INFO_LOG_LENGTH, &logLen); |
|
if (logLen > 0) |
|
{ |
|
char * sLog = new char[logLen + 1]; |
|
glGetProgramInfoLog(Program, logLen, &logLen, sLog); |
|
if (logLen > 0) |
|
{ |
|
if (sLog[0] != '\0') |
|
{ |
|
sLog[logLen - 1] = '\0'; |
|
log = sLog; |
|
} |
|
} |
|
delete [] sLog; |
|
} |
|
return log; |
|
} |
|
|
|
void setupUniforms(void) |
|
{ |
|
this->m_uniforms.clear(); |
|
|
|
GLint ucount = 0; |
|
glGetProgramiv(this->m_name, GL_ACTIVE_UNIFORMS, &ucount); |
|
if (ucount <= 0) return; |
|
|
|
GLint ulen = 0; |
|
glGetProgramiv(this->m_name, GL_ACTIVE_UNIFORM_MAX_LENGTH, &ulen); |
|
ulen++; // according to specs, +1 (for null) is already accounted, but some implementations are broken. |
|
if (ulen <= 0) return; |
|
|
|
UniformInfo info; |
|
GLchar * uname = new GLchar [ulen + 1]; |
|
for (int i=0; i<int(ucount); ++i) |
|
{ |
|
GLsizei length = 0; |
|
glGetActiveUniform(this->m_name, GLuint(i), GLsizei(ulen), &length, &(info.size), &(info.type), uname); |
|
info.name = uname; |
|
info.location = glGetUniformLocation(this->m_name, uname); |
|
this->m_uniforms.insert(UniformMapValue(info.name, info)); |
|
} |
|
delete [] uname; |
|
} |
|
|
|
void postLink(void) |
|
{ |
|
this->setupUniforms(); |
|
} |
|
}; |
|
|
|
namespace detail { template <> struct BaseOf <Program> { typedef Object Type; }; }; |
|
typedef detail::ObjectSharedPointerTraits <Program> ::Type ProgramPtr; |
|
|
|
class SafeProgram : public SafeObject |
|
{ |
|
friend class Context; |
|
friend class BoundProgram; |
|
|
|
public: |
|
|
|
typedef SafeObject BaseType; |
|
typedef SafeProgram ThisType; |
|
|
|
const ProgramArguments & arguments(void) const |
|
{ |
|
return this->object()->arguments(); |
|
} |
|
|
|
const std::string & log(void) const |
|
{ |
|
return this->object()->log(); |
|
} |
|
|
|
const std::string & fullLog(void) const |
|
{ |
|
return this->object()->fullLog(); |
|
} |
|
|
|
bool isLinked(void) const |
|
{ |
|
return this->object()->isLinked(); |
|
} |
|
|
|
protected: |
|
|
|
SafeProgram(const ProgramPtr & program) |
|
: BaseType(program) |
|
{ |
|
; |
|
} |
|
|
|
const ProgramPtr & object(void) const |
|
{ |
|
return static_cast<const ProgramPtr &>(BaseType::object()); |
|
} |
|
|
|
ProgramPtr & object(void) |
|
{ |
|
return static_cast<ProgramPtr &>(BaseType::object()); |
|
} |
|
}; |
|
|
|
namespace detail { template <> struct BaseOf <SafeProgram> { typedef SafeObject Type; }; }; |
|
namespace detail { template <> struct ObjectBase <SafeProgram> { typedef Program Type; }; }; |
|
namespace detail { template <> struct ObjectSafe <Program > { typedef SafeProgram Type; }; }; |
|
typedef detail::ObjectSharedPointerTraits <SafeProgram> ::Type ProgramHandle; |
|
|
|
class ProgramBindingParams : public ObjectBindingParams |
|
{ |
|
public: |
|
|
|
typedef ObjectBindingParams BaseType; |
|
typedef ProgramBindingParams ThisType; |
|
|
|
ProgramBindingParams(void) |
|
: BaseType(GL_CURRENT_PROGRAM, 0) |
|
{ |
|
; |
|
} |
|
}; |
|
|
|
class BoundProgram : public BoundObject |
|
{ |
|
friend class Context; |
|
|
|
public: |
|
|
|
typedef BoundObject BaseType; |
|
typedef BoundProgram ThisType; |
|
|
|
BoundProgram(void) |
|
: BaseType() |
|
{ |
|
; |
|
} |
|
|
|
const ProgramHandle & handle(void) const |
|
{ |
|
return static_cast<const ProgramHandle &>(BaseType::handle()); |
|
} |
|
|
|
ProgramHandle & handle(void) |
|
{ |
|
return static_cast<ProgramHandle &>(BaseType::handle()); |
|
} |
|
|
|
#define _GLW_FORWARD_SCALAR_UNIFORM_(TYPE) \ |
|
void setUniform (const std::string & name, TYPE x ) { this->object()->setUniform(name, x ); } \ |
|
void setUniform (const std::string & name, TYPE x, TYPE y ) { this->object()->setUniform(name, x, y ); } \ |
|
void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z ) { this->object()->setUniform(name, x, y, z ); } \ |
|
void setUniform (const std::string & name, TYPE x, TYPE y, TYPE z, TYPE w ) { this->object()->setUniform(name, x, y, z, w); } |
|
|
|
#define _GLW_FORWARD_VECTOR_UNIFORM_(TYPE) \ |
|
void setUniform1 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform1(name, v, count); } \ |
|
void setUniform2 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform2(name, v, count); } \ |
|
void setUniform3 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform3(name, v, count); } \ |
|
void setUniform4 (const std::string & name, const TYPE * v, int count = 1) { this->object()->setUniform4(name, v, count); } |
|
|
|
#define _GLW_FORWARD_MATRIX_UNIFORM_(TYPE) \ |
|
void setUniform2x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform2x2(name, m, transpose, count); } \ |
|
void setUniform2x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform2x3(name, m, transpose, count); } \ |
|
void setUniform2x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform2x4(name, m, transpose, count); } \ |
|
void setUniform3x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform3x2(name, m, transpose, count); } \ |
|
void setUniform3x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform3x3(name, m, transpose, count); } \ |
|
void setUniform3x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform3x4(name, m, transpose, count); } \ |
|
void setUniform4x2 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform4x2(name, m, transpose, count); } \ |
|
void setUniform4x3 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform4x3(name, m, transpose, count); } \ |
|
void setUniform4x4 (const std::string & name, const TYPE * m, bool transpose, int count = 1) { this->object()->setUniform4x4(name, m, transpose, count); } |
|
|
|
_GLW_FORWARD_SCALAR_UNIFORM_(int) |
|
_GLW_FORWARD_SCALAR_UNIFORM_(unsigned int) |
|
_GLW_FORWARD_SCALAR_UNIFORM_(float) |
|
// _GLW_FORWARD_SCALAR_UNIFORM_(double) |
|
_GLW_FORWARD_VECTOR_UNIFORM_(int) |
|
_GLW_FORWARD_VECTOR_UNIFORM_(unsigned int) |
|
_GLW_FORWARD_VECTOR_UNIFORM_(float) |
|
// _GLW_FORWARD_VECTOR_UNIFORM_(double) |
|
_GLW_FORWARD_MATRIX_UNIFORM_(float) |
|
// _GLW_FORWARD_MATRIX_UNIFORM_(double) |
|
|
|
#undef _GLW_FORWARD_SCALAR_UNIFORM_ |
|
#undef _GLW_FORWARD_VECTOR_UNIFORM_ |
|
#undef _GLW_FORWARD_MATRIX_UNIFORM_ |
|
|
|
protected: |
|
|
|
BoundProgram(const ProgramHandle & handle, const ProgramBindingParams & params) |
|
: BaseType(handle, params) |
|
{ |
|
; |
|
} |
|
|
|
const ProgramPtr & object(void) const |
|
{ |
|
return this->handle()->object(); |
|
} |
|
|
|
ProgramPtr & object(void) |
|
{ |
|
return this->handle()->object(); |
|
} |
|
|
|
virtual void bind(void) |
|
{ |
|
glUseProgram(this->object()->name()); |
|
} |
|
|
|
virtual void unbind(void) |
|
{ |
|
glUseProgram(0); |
|
} |
|
}; |
|
|
|
namespace detail { template <> struct ParamsOf <BoundProgram> { typedef ProgramBindingParams Type; }; }; |
|
namespace detail { template <> struct BaseOf <BoundProgram> { typedef BoundObject Type; }; }; |
|
namespace detail { template <> struct ObjectBase <BoundProgram> { typedef Program Type; }; }; |
|
namespace detail { template <> struct ObjectBound <Program > { typedef BoundProgram Type; }; }; |
|
typedef detail::ObjectSharedPointerTraits <BoundProgram> ::Type BoundProgramHandle; |
|
|
|
}; |
|
|
|
#endif // GLW_PROGRAM_H
|
|
|