605 lines
9.9 KiB
C++
605 lines
9.9 KiB
C++
#ifndef __SHADERS_H__
|
|
#define __SHADERS_H__
|
|
|
|
#include <GL/glew.h>
|
|
#include <stdio.h>
|
|
#include <set>
|
|
|
|
#include "gl_object.h"
|
|
#include "../../vcg/space/point2.h"
|
|
#include "../../vcg/space/point3.h"
|
|
#include "../../vcg/space/point4.h"
|
|
|
|
class Shader : public GLObject, public Bindable
|
|
{
|
|
public:
|
|
typedef enum
|
|
{
|
|
VERTEX,
|
|
FRAGMENT,
|
|
GEOMETRY
|
|
} ShaderType;
|
|
|
|
Shader(void) : GLObject(), Bindable()
|
|
{
|
|
this->flags = 0;
|
|
this->flags |= SOURCE_DIRTY;
|
|
this->compiled = false;
|
|
}
|
|
|
|
void Gen(void)
|
|
{
|
|
this->Del();
|
|
GLenum t;
|
|
switch (this->Type())
|
|
{
|
|
case Shader::VERTEX : t = GL_VERTEX_SHADER; break;
|
|
case Shader::FRAGMENT : t = GL_FRAGMENT_SHADER; break;
|
|
case Shader::GEOMETRY : t = GL_GEOMETRY_SHADER_EXT; break;
|
|
default: return;
|
|
};
|
|
this->objectID = glCreateShader(t);
|
|
}
|
|
|
|
void Del(void)
|
|
{
|
|
if (this->objectID == 0) return;
|
|
glDeleteShader(this->objectID);
|
|
this->objectID = 0;
|
|
}
|
|
|
|
virtual ShaderType Type(void) const = 0;
|
|
|
|
void SetSource(const char * src)
|
|
{
|
|
if (this->objectID==0)
|
|
Gen();
|
|
|
|
this->flags |= SOURCE_DIRTY;
|
|
this->compiled = false;
|
|
this->source = src;
|
|
|
|
const char * pSrc = this->source.c_str();
|
|
glShaderSource(this->objectID, 1, &pSrc, 0);
|
|
}
|
|
|
|
bool LoadSource(const char * fileName)
|
|
{
|
|
if (this->objectID==0)
|
|
Gen();
|
|
|
|
this->flags |= SOURCE_DIRTY;
|
|
this->compiled = false;
|
|
FILE * f = fopen(fileName, "rb");
|
|
if (f == 0)
|
|
{
|
|
this->source = "";
|
|
return false;
|
|
}
|
|
fseek(f, 0, SEEK_END);
|
|
const size_t sz = (size_t)ftell(f);
|
|
rewind(f);
|
|
char * buff = new char[sz + 1];
|
|
fread(buff, sizeof(char), sz, f);
|
|
fclose(f);
|
|
buff[sz] = '\0';
|
|
|
|
this->source = buff;
|
|
delete [] buff;
|
|
|
|
const char * pSrc = this->source.c_str();
|
|
glShaderSource(this->objectID, 1, &pSrc, 0);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Compile(void)
|
|
{
|
|
glCompileShader(this->objectID);
|
|
GLint cm = 0;
|
|
glGetShaderiv(this->objectID, GL_COMPILE_STATUS, &cm);
|
|
this->compiled = (cm != GL_FALSE);
|
|
this->flags = 0;
|
|
return this->compiled;
|
|
}
|
|
|
|
bool IsCompiled(void)
|
|
{
|
|
return this->compiled;
|
|
}
|
|
|
|
std::string InfoLog(void)
|
|
{
|
|
GLint len = 0;
|
|
glGetShaderiv(this->objectID, GL_INFO_LOG_LENGTH, &len);
|
|
char * ch = new char[len + 1];
|
|
glGetShaderInfoLog(this->objectID, len, &len, ch);
|
|
std::string infoLog = ch;
|
|
delete [] ch;
|
|
return infoLog;
|
|
}
|
|
|
|
protected:
|
|
enum
|
|
{
|
|
SOURCE_DIRTY
|
|
};
|
|
|
|
std::string source;
|
|
unsigned int flags;
|
|
bool compiled;
|
|
|
|
void DoBind(void)
|
|
{
|
|
}
|
|
|
|
void DoUnbind(void)
|
|
{
|
|
}
|
|
};
|
|
|
|
class VertexShader : public Shader
|
|
{
|
|
public:
|
|
VertexShader(void) : Shader()
|
|
{
|
|
}
|
|
|
|
ShaderType Type(void) const
|
|
{
|
|
return Shader::VERTEX;
|
|
}
|
|
};
|
|
|
|
class FragmentShader : public Shader
|
|
{
|
|
public:
|
|
FragmentShader(void) : Shader()
|
|
{
|
|
}
|
|
|
|
ShaderType Type(void) const
|
|
{
|
|
return Shader::FRAGMENT;
|
|
}
|
|
};
|
|
|
|
class GeometryShader : public Shader
|
|
{
|
|
public:
|
|
GeometryShader(void) : Shader()
|
|
{
|
|
}
|
|
|
|
ShaderType Type(void) const
|
|
{
|
|
return Shader::GEOMETRY;
|
|
}
|
|
};
|
|
|
|
#if 0
|
|
class Program;
|
|
|
|
class Uniform
|
|
{
|
|
friend class Program;
|
|
|
|
public:
|
|
/*
|
|
typedef enum
|
|
{
|
|
U_BOOL,
|
|
U_BVEC2,
|
|
U_BVEC3,
|
|
U_BVEC4,
|
|
U_BMAT2,
|
|
U_BMAT3,
|
|
U_BMAT4,
|
|
|
|
U_INT,
|
|
U_IVEC2,
|
|
U_IVEC3,
|
|
U_IVEC4,
|
|
U_IMAT2,
|
|
U_IMAT3,
|
|
U_IMAT4,
|
|
|
|
U_FLOAT,
|
|
U_FVEC2,
|
|
U_FVEC3,
|
|
U_FVEC4,
|
|
U_FMAT2,
|
|
U_FMAT3,
|
|
U_FMAT4,
|
|
|
|
U_SAMPLER1D,
|
|
U_SAMPLER2D,
|
|
U_SAMPLER3D,
|
|
U_SAMPLERCUBE,
|
|
U_SAMPLER1DSHADOW,
|
|
U_SAMPLER2DSHADOW
|
|
} UniformType;
|
|
*/
|
|
|
|
const std::string & Name(void) const
|
|
{
|
|
return this->name;
|
|
}
|
|
|
|
virtual GLenum Type(void) const = 0;
|
|
|
|
protected:
|
|
Program * prog;
|
|
GLint location;
|
|
std::string name;
|
|
|
|
Uniform(Program * prog, GLint location, const std::string & name)
|
|
{
|
|
this->prog = prog;
|
|
this->location = location;
|
|
this->name = name;
|
|
}
|
|
|
|
virtual void Apply(void) = 0;
|
|
};
|
|
|
|
class Uniform1b : public Uniform;
|
|
{
|
|
public:
|
|
|
|
void SetValue(GLboolean x)
|
|
{
|
|
this->value[0] = x;
|
|
}
|
|
|
|
GLboolean GetValue(void) const
|
|
{
|
|
return this->value[0];
|
|
}
|
|
|
|
protected:
|
|
Program * prog;
|
|
GLboolean value[1];
|
|
|
|
Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
|
|
{
|
|
this->value = GL_FALSE;
|
|
}
|
|
};
|
|
|
|
class Uniform2b : public Uniform;
|
|
{
|
|
public:
|
|
|
|
void SetValue(GLboolean x, GLboolean y)
|
|
{
|
|
this->value[0] = x;
|
|
this->value[1] = y;
|
|
}
|
|
|
|
GLboolean GetValueX(void) const
|
|
{
|
|
return this->value[0];
|
|
}
|
|
|
|
GLboolean GetValueY(void) const
|
|
{
|
|
return this->value[1];
|
|
}
|
|
|
|
protected:
|
|
Program * prog;
|
|
GLboolean value[2];
|
|
|
|
Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
|
|
{
|
|
this->value[0] = GL_FALSE;
|
|
this->value[1] = GL_FALSE;
|
|
}
|
|
};
|
|
|
|
class Uniform3b : public Uniform;
|
|
{
|
|
public:
|
|
|
|
void SetValue(GLboolean x, GLboolean y, GLboolean z)
|
|
{
|
|
this->value[0] = x;
|
|
this->value[1] = y;
|
|
this->value[2] = z;
|
|
}
|
|
|
|
GLboolean GetValueX(void) const
|
|
{
|
|
return this->value[0];
|
|
}
|
|
|
|
GLboolean GetValueY(void) const
|
|
{
|
|
return this->value[1];
|
|
}
|
|
|
|
GLboolean GetValueZ(void) const
|
|
{
|
|
return this->value[2];
|
|
}
|
|
|
|
protected:
|
|
Program * prog;
|
|
GLboolean value[2];
|
|
|
|
Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
|
|
{
|
|
this->value[0] = GL_FALSE;
|
|
this->value[1] = GL_FALSE;
|
|
}
|
|
};
|
|
|
|
class Uniform1i : public Uniform;
|
|
{
|
|
public:
|
|
|
|
void SetValue(GLint v)
|
|
{
|
|
this->value = v;
|
|
}
|
|
|
|
GLint GetValue(void) const
|
|
{
|
|
return this->value;
|
|
}
|
|
|
|
protected:
|
|
Program * prog;
|
|
GLint value;
|
|
|
|
Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
|
|
{
|
|
this->value = 0;
|
|
}
|
|
};
|
|
#endif
|
|
|
|
class Program : public GLObject, public Bindable
|
|
{
|
|
public:
|
|
|
|
Program(void)
|
|
{
|
|
this->linked = false;
|
|
}
|
|
|
|
void Gen(void)
|
|
{
|
|
this->Del();
|
|
this->objectID = glCreateProgram();
|
|
}
|
|
|
|
void Del(void)
|
|
{
|
|
if (this->objectID == 0) return;
|
|
glDeleteProgram(this->objectID);
|
|
this->objectID = 0;
|
|
}
|
|
|
|
void Attach(Shader * shd)
|
|
{
|
|
if (this->objectID==0)
|
|
Gen();
|
|
this->shaders.insert(shd);
|
|
this->linked = false;
|
|
glAttachShader(this->objectID, shd->ObjectID());
|
|
}
|
|
|
|
void Detach(Shader * shd)
|
|
{
|
|
this->shaders.erase(shd);
|
|
this->linked = false;
|
|
glDetachShader(this->objectID, shd->ObjectID());
|
|
}
|
|
|
|
GLsizei AttachedShaders(void) const
|
|
{
|
|
return ((GLsizei)(this->shaders.size()));
|
|
}
|
|
|
|
Shader * AttachedShader(int i)
|
|
{
|
|
Shader * shd = 0;
|
|
int cnt = 0;
|
|
for (std::set<Shader *>::iterator it=this->shaders.begin(); (cnt < i) && (it!=this->shaders.end()); ++it)
|
|
{
|
|
shd = (*it);
|
|
}
|
|
return shd;
|
|
}
|
|
|
|
bool Link(void)
|
|
{
|
|
bool ok = true;
|
|
for (std::set<Shader *>::iterator it=this->shaders.begin(); it!=this->shaders.end(); ++it)
|
|
{
|
|
Shader * shd = (*it);
|
|
if (!shd->IsCompiled())
|
|
{
|
|
ok = shd->Compile() && ok;
|
|
}
|
|
}
|
|
|
|
if (!ok)
|
|
return false;
|
|
|
|
glLinkProgram(this->objectID);
|
|
|
|
GLint cm = 0;
|
|
glGetProgramiv(this->objectID, GL_LINK_STATUS, &cm);
|
|
this->linked = (cm != GL_FALSE);
|
|
|
|
return this->linked;
|
|
}
|
|
|
|
bool IsLinked(void) const
|
|
{
|
|
return this->linked;
|
|
}
|
|
|
|
std::string InfoLog(void)
|
|
{
|
|
GLint len = 0;
|
|
glGetProgramiv(this->objectID, GL_INFO_LOG_LENGTH, &len);
|
|
char * ch = new char[len + 1];
|
|
glGetProgramInfoLog(this->objectID, len, &len, ch);
|
|
std::string infoLog = ch;
|
|
delete [] ch;
|
|
return infoLog;
|
|
}
|
|
|
|
void Uniform(const char * name, GLint x)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform1i(loc, x);
|
|
}
|
|
|
|
void Uniform(const char * name, GLint x, GLint y)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform2i(loc, x, y);
|
|
}
|
|
|
|
void Uniform(const char * name, GLint x, GLint y, GLint z)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform3i(loc, x, y, z);
|
|
}
|
|
|
|
void Uniform(const char * name, GLint x, GLint y, GLint z, GLint w)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform4i(loc, x, y, z, w);
|
|
}
|
|
|
|
void Uniform(const char * name, GLfloat x)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform1f(loc, x);
|
|
}
|
|
|
|
void Uniform(const char * name, GLfloat x, GLfloat y)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform2f(loc, x, y);
|
|
}
|
|
|
|
void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform3f(loc, x, y, z);
|
|
}
|
|
|
|
void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform4f(loc, x, y, z, w);
|
|
}
|
|
|
|
void Uniform(const char * name, const vcg::Point2f& p)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform2fv(loc, 1, p.V());
|
|
}
|
|
|
|
void Uniform(const char * name, const vcg::Point3f& p)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform3fv(loc, 1, p.V());
|
|
}
|
|
|
|
void Uniform(const char * name, const vcg::Point4f& p)
|
|
{
|
|
const GLint loc = glGetUniformLocation(this->objectID, name);
|
|
glUniform4fv(loc, 1, p.V());
|
|
}
|
|
|
|
void Parameter(GLenum pname, int value)
|
|
{
|
|
glProgramParameteriEXT(this->objectID, pname, value);
|
|
}
|
|
|
|
void Attribute(int index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
|
|
{
|
|
glVertexAttrib4f(index, x, y, z, w);
|
|
}
|
|
|
|
void BindAttribute(int index, const char * name)
|
|
{
|
|
glBindAttribLocation(this->objectID, index, name);
|
|
}
|
|
|
|
protected:
|
|
std::set<Shader *> shaders;
|
|
bool linked;
|
|
|
|
void DoBind(void)
|
|
{
|
|
if (!this->IsLinked())
|
|
{
|
|
this->Link();
|
|
}
|
|
glUseProgram(this->objectID);
|
|
}
|
|
|
|
void DoUnbind(void)
|
|
{
|
|
glUseProgram(0);
|
|
}
|
|
};
|
|
|
|
class ProgramVF : public Bindable
|
|
{
|
|
public:
|
|
Program prog;
|
|
VertexShader vshd;
|
|
FragmentShader fshd;
|
|
|
|
ProgramVF(void) : Bindable()
|
|
{
|
|
}
|
|
|
|
void SetSources(const char * vsrc, const char * fsrc)
|
|
{
|
|
if (vsrc) {
|
|
this->vshd.SetSource(vsrc);
|
|
this->prog.Attach(&(this->vshd));
|
|
}
|
|
if (fsrc) {
|
|
this->fshd.SetSource(fsrc);
|
|
this->prog.Attach(&(this->fshd));
|
|
}
|
|
}
|
|
|
|
void LoadSources(const char * vfile, const char * ffile)
|
|
{
|
|
if (vfile) {
|
|
this->vshd.LoadSource(vfile);
|
|
this->prog.Attach(&(this->vshd));
|
|
}
|
|
if (ffile) {
|
|
this->fshd.LoadSource(ffile);
|
|
this->prog.Attach(&(this->fshd));
|
|
}
|
|
}
|
|
|
|
protected:
|
|
void DoBind(void)
|
|
{
|
|
this->prog.Bind();
|
|
}
|
|
|
|
void DoUnbind(void)
|
|
{
|
|
this->prog.Unbind();
|
|
}
|
|
};
|
|
|
|
#endif // __SHADERS_H__
|