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.
683 lines
14 KiB
683 lines
14 KiB
/**************************************************************************** |
|
* MeshLab o o * |
|
* An extendible mesh processor o o * |
|
* _ O _ * |
|
* Copyright(C) 2005, 2009 \/)\/ * |
|
* Visual Computing Lab /\/| * |
|
* ISTI - Italian National Research Council | * |
|
* \ * |
|
* All rights reserved. * |
|
* * |
|
* This program is free software; you can redistribute it and/or modify * |
|
* it under the terms of the GNU General Public License as published by * |
|
* the Free Software Foundation; either version 2 of the License, or * |
|
* (at your option) any later version. * |
|
* * |
|
* This program is distributed in the hope that it will be useful, * |
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * |
|
* for more details. * |
|
* * |
|
****************************************************************************/ |
|
|
|
#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" |
|
#include "../../vcg/math/matrix33.h" |
|
#include "../../vcg/math/matrix44.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); |
|
if (loc <0) |
|
return; |
|
glUniform1i(loc, x); |
|
} |
|
|
|
void Uniform(const char * name, GLint x, GLint y) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform2i(loc, x, y); |
|
} |
|
|
|
void Uniform(const char * name, GLint x, GLint y, GLint z) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
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); |
|
if (loc <0) |
|
return; |
|
glUniform4i(loc, x, y, z, w); |
|
} |
|
|
|
void Uniform(const char * name, GLfloat x) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform1f(loc, x); |
|
} |
|
|
|
void Uniform(const char * name, GLfloat x, GLfloat y) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform2f(loc, x, y); |
|
} |
|
|
|
void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
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); |
|
if (loc <0) |
|
return; |
|
glUniform4f(loc, x, y, z, w); |
|
} |
|
|
|
void Uniform(const char * name, const vcg::Point2i& p) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform2iv(loc, 1, p.V()); |
|
} |
|
|
|
void Uniform(const char * name, const vcg::Point2f& p) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform2fv(loc, 1, p.V()); |
|
} |
|
|
|
void Uniform(const char * name, const vcg::Point3f& p) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform3fv(loc, 1, p.V()); |
|
} |
|
|
|
void Uniform(const char * name, const vcg::Point4f& p) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
glUniform4fv(loc, 1, p.V()); |
|
} |
|
|
|
void Uniform(const char * name, const vcg::Matrix33f& m,bool traspose = true) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
if (traspose) |
|
glUniformMatrix3fv(loc, 1, GL_TRUE,m.V()); |
|
else |
|
glUniformMatrix3fv(loc, 1, GL_FALSE,m.V()); |
|
} |
|
|
|
void Uniform(const char * name, const vcg::Matrix44f& m,bool traspose = true) |
|
{ |
|
const GLint loc = glGetUniformLocation(this->objectID, name); |
|
if (loc <0) |
|
return; |
|
if (traspose) |
|
glUniformMatrix4fv(loc, 1, GL_TRUE,m.V()); |
|
else |
|
glUniformMatrix4fv(loc, 1, GL_FALSE,m.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; |
|
public: |
|
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__
|
|
|