2012-04-30 20:23:53 +02:00
|
|
|
#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
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
public:
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef void BaseType;
|
|
|
|
typedef VertexAttributeBinding ThisType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef std::map<std::string, GLuint> Map;
|
|
|
|
typedef Map::const_iterator ConstIterator;
|
|
|
|
typedef Map::iterator Iterator;
|
|
|
|
typedef Map::value_type Value;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
Map bindings;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
VertexAttributeBinding(void)
|
|
|
|
{
|
|
|
|
this->clear();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
void clear(void)
|
|
|
|
{
|
|
|
|
this->bindings.clear();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
GLuint operator [] (const std::string & attributeName) const
|
|
|
|
{
|
|
|
|
return this->bindings.find(attributeName)->second;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
GLuint & operator [] (const std::string & attributeName)
|
|
|
|
{
|
|
|
|
return this->bindings[attributeName];
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class GeometryStage
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
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;
|
|
|
|
*/
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class TransformFeedbackStream
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
public:
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef void BaseType;
|
|
|
|
typedef TransformFeedbackStream ThisType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef std::vector<std::string> VaryingVector;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
VaryingVector varyings;
|
|
|
|
GLenum bufferMode;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
TransformFeedbackStream(void)
|
|
|
|
{
|
|
|
|
this->clear();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
void clear(void)
|
|
|
|
{
|
|
|
|
this->varyings.clear();
|
|
|
|
this->bufferMode = GL_INTERLEAVED_ATTRIBS;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class RasterizerSettings
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
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;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class FragmentOutputBinding
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
public:
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef void BaseType;
|
|
|
|
typedef FragmentOutputBinding ThisType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef std::map<std::string, GLuint> Map;
|
|
|
|
typedef Map::const_iterator ConstIterator;
|
|
|
|
typedef Map::iterator Iterator;
|
|
|
|
typedef Map::value_type Value;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
Map bindings;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
FragmentOutputBinding(void)
|
|
|
|
{
|
|
|
|
this->clear();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
void clear(void)
|
|
|
|
{
|
|
|
|
this->bindings.clear();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
GLuint operator [] (const std::string & outName) const
|
|
|
|
{
|
|
|
|
return this->bindings.find(outName)->second;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
GLuint & operator [] (const std::string & outName)
|
|
|
|
{
|
|
|
|
return this->bindings[outName];
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class ProgramArguments : public ObjectArguments
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
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();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
class Program : public Object
|
2012-04-30 20:23:53 +02:00
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
friend class Context;
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
public:
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef Object BaseType;
|
|
|
|
typedef Program ThisType;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
virtual ~Program(void)
|
|
|
|
{
|
|
|
|
this->destroy();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
virtual Type type(void) const
|
|
|
|
{
|
|
|
|
return ProgramType;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
const ProgramArguments & arguments(void) const
|
|
|
|
{
|
|
|
|
return this->m_arguments;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
const std::string & log(void) const
|
|
|
|
{
|
|
|
|
return this->m_log;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
const std::string & fullLog(void) const
|
|
|
|
{
|
|
|
|
return this->m_fullLog;
|
|
|
|
}
|
2012-06-01 18:57:42 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
bool isLinked(void) const
|
|
|
|
{
|
|
|
|
return this->m_linked;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
GLint getUniformLocation(const std::string & name) const
|
|
|
|
{
|
2012-05-19 19:59:50 +02:00
|
|
|
#if GLW_ASSERT_UNIFORM_LOCATION
|
2014-08-09 02:04:18 +02:00
|
|
|
GLW_ASSERT(this->m_uniforms.count(name) > 0);
|
2012-05-19 19:59:50 +02:00
|
|
|
#endif
|
2014-08-09 02:04:18 +02:00
|
|
|
UniformMapConstIterator it = this->m_uniforms.find(name);
|
|
|
|
if (it == this->m_uniforms.end()) return -1;
|
|
|
|
return it->second.location;
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
|
|
|
|
#define _GLW_IMPLEMENT_SCALAR_UNIFORM_(TYPE, FUNCION_SUFFIX) \
|
2014-08-09 02:04:18 +02:00
|
|
|
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); }
|
2012-04-30 20:23:53 +02:00
|
|
|
|
|
|
|
#define _GLW_IMPLEMENT_VECTOR_UNIFORM_(TYPE, FUNCION_SUFFIX) \
|
2014-08-09 02:04:18 +02:00
|
|
|
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 ); }
|
2012-04-30 20:23:53 +02:00
|
|
|
|
|
|
|
#define _GLW_IMPLEMENT_MATRIX_UNIFORM_(TYPE, FUNCION_SUFFIX) \
|
2014-08-09 02:04:18 +02:00
|
|
|
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 )
|
2014-08-23 03:30:40 +02:00
|
|
|
// _GLW_IMPLEMENT_SCALAR_UNIFORM_(double, d )
|
2014-08-09 02:04:18 +02:00
|
|
|
_GLW_IMPLEMENT_VECTOR_UNIFORM_(int, i )
|
|
|
|
_GLW_IMPLEMENT_VECTOR_UNIFORM_(unsigned int, ui)
|
|
|
|
_GLW_IMPLEMENT_VECTOR_UNIFORM_(float, f )
|
2014-08-23 03:30:40 +02:00
|
|
|
// _GLW_IMPLEMENT_VECTOR_UNIFORM_(double, d )
|
2014-08-09 02:04:18 +02:00
|
|
|
_GLW_IMPLEMENT_MATRIX_UNIFORM_(float, f )
|
2014-08-23 03:30:40 +02:00
|
|
|
// _GLW_IMPLEMENT_MATRIX_UNIFORM_(double, d )
|
2014-08-09 02:04:18 +02:00
|
|
|
|
|
|
|
GLW_IMPLEMENT_CUSTOM_UNIFORMS;
|
2012-04-30 20:23:53 +02:00
|
|
|
|
|
|
|
#undef _GLW_IMPLEMENT_SCALAR_UNIFORM_
|
|
|
|
#undef _GLW_IMPLEMENT_VECTOR_UNIFORM_
|
|
|
|
#undef _GLW_IMPLEMENT_MATRIX_UNIFORM_
|
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
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);
|
2012-04-30 20:23:53 +02:00
|
|
|
|
2012-05-07 18:12:40 +02:00
|
|
|
#if GLW_PRINT_LOG_TO_STDERR
|
2014-08-09 02:04:18 +02:00
|
|
|
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;
|
2012-05-07 18:12:40 +02:00
|
|
|
#endif
|
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
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();
|
|
|
|
}
|
2012-04-30 20:23:53 +02:00
|
|
|
};
|
|
|
|
|
2012-05-07 15:18:05 +02:00
|
|
|
namespace detail { template <> struct BaseOf <Program> { typedef Object Type; }; };
|
|
|
|
typedef detail::ObjectSharedPointerTraits <Program> ::Type ProgramPtr;
|
|
|
|
|
|
|
|
class SafeProgram : public SafeObject
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
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());
|
|
|
|
}
|
2012-05-07 15:18:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
public:
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef ObjectBindingParams BaseType;
|
|
|
|
typedef ProgramBindingParams ThisType;
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
ProgramBindingParams(void)
|
|
|
|
: BaseType(GL_CURRENT_PROGRAM, 0)
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
2012-05-07 15:18:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
class BoundProgram : public BoundObject
|
|
|
|
{
|
2014-08-09 02:04:18 +02:00
|
|
|
friend class Context;
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
public:
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
typedef BoundObject BaseType;
|
|
|
|
typedef BoundProgram ThisType;
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
BoundProgram(void)
|
|
|
|
: BaseType()
|
|
|
|
{
|
|
|
|
;
|
|
|
|
}
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
const ProgramHandle & handle(void) const
|
|
|
|
{
|
|
|
|
return static_cast<const ProgramHandle &>(BaseType::handle());
|
|
|
|
}
|
2012-05-07 15:18:05 +02:00
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
ProgramHandle & handle(void)
|
|
|
|
{
|
|
|
|
return static_cast<ProgramHandle &>(BaseType::handle());
|
|
|
|
}
|
2012-05-07 15:18:05 +02:00
|
|
|
|
|
|
|
#define _GLW_FORWARD_SCALAR_UNIFORM_(TYPE) \
|
2014-08-09 02:04:18 +02:00
|
|
|
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); }
|
2012-05-07 15:18:05 +02:00
|
|
|
|
|
|
|
#define _GLW_FORWARD_VECTOR_UNIFORM_(TYPE) \
|
2014-08-09 02:04:18 +02:00
|
|
|
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); }
|
2012-05-07 15:18:05 +02:00
|
|
|
|
|
|
|
#define _GLW_FORWARD_MATRIX_UNIFORM_(TYPE) \
|
2014-08-09 02:04:18 +02:00
|
|
|
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)
|
2014-08-23 03:30:40 +02:00
|
|
|
// _GLW_FORWARD_SCALAR_UNIFORM_(double)
|
2014-08-09 02:04:18 +02:00
|
|
|
_GLW_FORWARD_VECTOR_UNIFORM_(int)
|
|
|
|
_GLW_FORWARD_VECTOR_UNIFORM_(unsigned int)
|
|
|
|
_GLW_FORWARD_VECTOR_UNIFORM_(float)
|
2014-08-23 03:30:40 +02:00
|
|
|
// _GLW_FORWARD_VECTOR_UNIFORM_(double)
|
2014-08-09 02:04:18 +02:00
|
|
|
_GLW_FORWARD_MATRIX_UNIFORM_(float)
|
2014-08-23 03:30:40 +02:00
|
|
|
// _GLW_FORWARD_MATRIX_UNIFORM_(double)
|
2012-05-07 15:18:05 +02:00
|
|
|
|
|
|
|
#undef _GLW_FORWARD_SCALAR_UNIFORM_
|
|
|
|
#undef _GLW_FORWARD_VECTOR_UNIFORM_
|
|
|
|
#undef _GLW_FORWARD_MATRIX_UNIFORM_
|
|
|
|
|
2014-08-09 02:04:18 +02:00
|
|
|
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);
|
|
|
|
}
|
2012-05-07 15:18:05 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
};
|
2012-04-30 20:23:53 +02:00
|
|
|
|
|
|
|
#endif // GLW_PROGRAM_H
|