00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __SHADERS_H__
00025 #define __SHADERS_H__
00026
00027 #include <GL/glew.h>
00028 #include <stdio.h>
00029 #include <set>
00030
00031 #include "gl_object.h"
00032 #include "../../vcg/space/point2.h"
00033 #include "../../vcg/space/point3.h"
00034 #include "../../vcg/space/point4.h"
00035
00036 class Shader : public GLObject, public Bindable
00037 {
00038 public:
00039 typedef enum
00040 {
00041 VERTEX,
00042 FRAGMENT,
00043 GEOMETRY
00044 } ShaderType;
00045
00046 Shader(void) : GLObject(), Bindable()
00047 {
00048 this->flags = 0;
00049 this->flags |= SOURCE_DIRTY;
00050 this->compiled = false;
00051 }
00052
00053 void Gen(void)
00054 {
00055 this->Del();
00056 GLenum t;
00057 switch (this->Type())
00058 {
00059 case Shader::VERTEX : t = GL_VERTEX_SHADER; break;
00060 case Shader::FRAGMENT : t = GL_FRAGMENT_SHADER; break;
00061 case Shader::GEOMETRY : t = GL_GEOMETRY_SHADER_EXT; break;
00062 default: return;
00063 };
00064 this->objectID = glCreateShader(t);
00065 }
00066
00067 void Del(void)
00068 {
00069 if (this->objectID == 0) return;
00070 glDeleteShader(this->objectID);
00071 this->objectID = 0;
00072 }
00073
00074 virtual ShaderType Type(void) const = 0;
00075
00076 void SetSource(const char * src)
00077 {
00078 if (this->objectID==0)
00079 Gen();
00080
00081 this->flags |= SOURCE_DIRTY;
00082 this->compiled = false;
00083 this->source = src;
00084
00085 const char * pSrc = this->source.c_str();
00086 glShaderSource(this->objectID, 1, &pSrc, 0);
00087 }
00088
00089 bool LoadSource(const char * fileName)
00090 {
00091 if (this->objectID==0)
00092 Gen();
00093
00094 this->flags |= SOURCE_DIRTY;
00095 this->compiled = false;
00096 FILE * f = fopen(fileName, "rb");
00097 if (f == 0)
00098 {
00099 this->source = "";
00100 return false;
00101 }
00102 fseek(f, 0, SEEK_END);
00103 const size_t sz = (size_t)ftell(f);
00104 rewind(f);
00105 char * buff = new char[sz + 1];
00106 fread(buff, sizeof(char), sz, f);
00107 fclose(f);
00108 buff[sz] = '\0';
00109
00110 this->source = buff;
00111 delete [] buff;
00112
00113 const char * pSrc = this->source.c_str();
00114 glShaderSource(this->objectID, 1, &pSrc, 0);
00115
00116 return true;
00117 }
00118
00119 bool Compile(void)
00120 {
00121 glCompileShader(this->objectID);
00122 GLint cm = 0;
00123 glGetShaderiv(this->objectID, GL_COMPILE_STATUS, &cm);
00124 this->compiled = (cm != GL_FALSE);
00125 this->flags = 0;
00126 return this->compiled;
00127 }
00128
00129 bool IsCompiled(void)
00130 {
00131 return this->compiled;
00132 }
00133
00134 std::string InfoLog(void)
00135 {
00136 GLint len = 0;
00137 glGetShaderiv(this->objectID, GL_INFO_LOG_LENGTH, &len);
00138 char * ch = new char[len + 1];
00139 glGetShaderInfoLog(this->objectID, len, &len, ch);
00140 std::string infoLog = ch;
00141 delete [] ch;
00142 return infoLog;
00143 }
00144
00145 protected:
00146 enum
00147 {
00148 SOURCE_DIRTY
00149 };
00150
00151 std::string source;
00152 unsigned int flags;
00153 bool compiled;
00154
00155 void DoBind(void)
00156 {
00157 }
00158
00159 void DoUnbind(void)
00160 {
00161 }
00162 };
00163
00164 class VertexShader : public Shader
00165 {
00166 public:
00167 VertexShader(void) : Shader()
00168 {
00169 }
00170
00171 ShaderType Type(void) const
00172 {
00173 return Shader::VERTEX;
00174 }
00175 };
00176
00177 class FragmentShader : public Shader
00178 {
00179 public:
00180 FragmentShader(void) : Shader()
00181 {
00182 }
00183
00184 ShaderType Type(void) const
00185 {
00186 return Shader::FRAGMENT;
00187 }
00188 };
00189
00190 class GeometryShader : public Shader
00191 {
00192 public:
00193 GeometryShader(void) : Shader()
00194 {
00195 }
00196
00197 ShaderType Type(void) const
00198 {
00199 return Shader::GEOMETRY;
00200 }
00201 };
00202
00203 #if 0
00204 class Program;
00205
00206 class Uniform
00207 {
00208 friend class Program;
00209
00210 public:
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247 const std::string & Name(void) const
00248 {
00249 return this->name;
00250 }
00251
00252 virtual GLenum Type(void) const = 0;
00253
00254 protected:
00255 Program * prog;
00256 GLint location;
00257 std::string name;
00258
00259 Uniform(Program * prog, GLint location, const std::string & name)
00260 {
00261 this->prog = prog;
00262 this->location = location;
00263 this->name = name;
00264 }
00265
00266 virtual void Apply(void) = 0;
00267 };
00268
00269 class Uniform1b : public Uniform;
00270 {
00271 public:
00272
00273 void SetValue(GLboolean x)
00274 {
00275 this->value[0] = x;
00276 }
00277
00278 GLboolean GetValue(void) const
00279 {
00280 return this->value[0];
00281 }
00282
00283 protected:
00284 Program * prog;
00285 GLboolean value[1];
00286
00287 Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
00288 {
00289 this->value = GL_FALSE;
00290 }
00291 };
00292
00293 class Uniform2b : public Uniform;
00294 {
00295 public:
00296
00297 void SetValue(GLboolean x, GLboolean y)
00298 {
00299 this->value[0] = x;
00300 this->value[1] = y;
00301 }
00302
00303 GLboolean GetValueX(void) const
00304 {
00305 return this->value[0];
00306 }
00307
00308 GLboolean GetValueY(void) const
00309 {
00310 return this->value[1];
00311 }
00312
00313 protected:
00314 Program * prog;
00315 GLboolean value[2];
00316
00317 Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
00318 {
00319 this->value[0] = GL_FALSE;
00320 this->value[1] = GL_FALSE;
00321 }
00322 };
00323
00324 class Uniform3b : public Uniform;
00325 {
00326 public:
00327
00328 void SetValue(GLboolean x, GLboolean y, GLboolean z)
00329 {
00330 this->value[0] = x;
00331 this->value[1] = y;
00332 this->value[2] = z;
00333 }
00334
00335 GLboolean GetValueX(void) const
00336 {
00337 return this->value[0];
00338 }
00339
00340 GLboolean GetValueY(void) const
00341 {
00342 return this->value[1];
00343 }
00344
00345 GLboolean GetValueZ(void) const
00346 {
00347 return this->value[2];
00348 }
00349
00350 protected:
00351 Program * prog;
00352 GLboolean value[2];
00353
00354 Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
00355 {
00356 this->value[0] = GL_FALSE;
00357 this->value[1] = GL_FALSE;
00358 }
00359 };
00360
00361 class Uniform1i : public Uniform;
00362 {
00363 public:
00364
00365 void SetValue(GLint v)
00366 {
00367 this->value = v;
00368 }
00369
00370 GLint GetValue(void) const
00371 {
00372 return this->value;
00373 }
00374
00375 protected:
00376 Program * prog;
00377 GLint value;
00378
00379 Uniform(Program * prog, GLint location, const std::string & name) : Uniform(prog, location, name)
00380 {
00381 this->value = 0;
00382 }
00383 };
00384 #endif
00385
00386 class Program : public GLObject, public Bindable
00387 {
00388 public:
00389
00390 Program(void)
00391 {
00392 this->linked = false;
00393 }
00394
00395 void Gen(void)
00396 {
00397 this->Del();
00398 this->objectID = glCreateProgram();
00399 }
00400
00401 void Del(void)
00402 {
00403 if (this->objectID == 0) return;
00404 glDeleteProgram(this->objectID);
00405 this->objectID = 0;
00406 }
00407
00408 void Attach(Shader * shd)
00409 {
00410 if (this->objectID==0)
00411 Gen();
00412 this->shaders.insert(shd);
00413 this->linked = false;
00414 glAttachShader(this->objectID, shd->ObjectID());
00415 }
00416
00417 void Detach(Shader * shd)
00418 {
00419 this->shaders.erase(shd);
00420 this->linked = false;
00421 glDetachShader(this->objectID, shd->ObjectID());
00422 }
00423
00424 GLsizei AttachedShaders(void) const
00425 {
00426 return ((GLsizei)(this->shaders.size()));
00427 }
00428
00429 Shader * AttachedShader(int i)
00430 {
00431 Shader * shd = 0;
00432 int cnt = 0;
00433 for (std::set<Shader *>::iterator it=this->shaders.begin(); (cnt < i) && (it!=this->shaders.end()); ++it)
00434 {
00435 shd = (*it);
00436 }
00437 return shd;
00438 }
00439
00440 bool Link(void)
00441 {
00442 bool ok = true;
00443 for (std::set<Shader *>::iterator it=this->shaders.begin(); it!=this->shaders.end(); ++it)
00444 {
00445 Shader * shd = (*it);
00446 if (!shd->IsCompiled())
00447 {
00448 ok = shd->Compile() && ok;
00449 }
00450 }
00451
00452 if (!ok)
00453 return false;
00454
00455 glLinkProgram(this->objectID);
00456
00457 GLint cm = 0;
00458 glGetProgramiv(this->objectID, GL_LINK_STATUS, &cm);
00459 this->linked = (cm != GL_FALSE);
00460
00461 return this->linked;
00462 }
00463
00464 bool IsLinked(void) const
00465 {
00466 return this->linked;
00467 }
00468
00469 std::string InfoLog(void)
00470 {
00471 GLint len = 0;
00472 glGetProgramiv(this->objectID, GL_INFO_LOG_LENGTH, &len);
00473 char * ch = new char[len + 1];
00474 glGetProgramInfoLog(this->objectID, len, &len, ch);
00475 std::string infoLog = ch;
00476 delete [] ch;
00477 return infoLog;
00478 }
00479
00480 void Uniform(const char * name, GLint x)
00481 {
00482 const GLint loc = glGetUniformLocation(this->objectID, name);
00483 glUniform1i(loc, x);
00484 }
00485
00486 void Uniform(const char * name, GLint x, GLint y)
00487 {
00488 const GLint loc = glGetUniformLocation(this->objectID, name);
00489 glUniform2i(loc, x, y);
00490 }
00491
00492 void Uniform(const char * name, GLint x, GLint y, GLint z)
00493 {
00494 const GLint loc = glGetUniformLocation(this->objectID, name);
00495 glUniform3i(loc, x, y, z);
00496 }
00497
00498 void Uniform(const char * name, GLint x, GLint y, GLint z, GLint w)
00499 {
00500 const GLint loc = glGetUniformLocation(this->objectID, name);
00501 glUniform4i(loc, x, y, z, w);
00502 }
00503
00504 void Uniform(const char * name, GLfloat x)
00505 {
00506 const GLint loc = glGetUniformLocation(this->objectID, name);
00507 glUniform1f(loc, x);
00508 }
00509
00510 void Uniform(const char * name, GLfloat x, GLfloat y)
00511 {
00512 const GLint loc = glGetUniformLocation(this->objectID, name);
00513 glUniform2f(loc, x, y);
00514 }
00515
00516 void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z)
00517 {
00518 const GLint loc = glGetUniformLocation(this->objectID, name);
00519 glUniform3f(loc, x, y, z);
00520 }
00521
00522 void Uniform(const char * name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
00523 {
00524 const GLint loc = glGetUniformLocation(this->objectID, name);
00525 glUniform4f(loc, x, y, z, w);
00526 }
00527
00528 void Uniform(const char * name, const vcg::Point2f& p)
00529 {
00530 const GLint loc = glGetUniformLocation(this->objectID, name);
00531 glUniform2fv(loc, 1, p.V());
00532 }
00533
00534 void Uniform(const char * name, const vcg::Point3f& p)
00535 {
00536 const GLint loc = glGetUniformLocation(this->objectID, name);
00537 glUniform3fv(loc, 1, p.V());
00538 }
00539
00540 void Uniform(const char * name, const vcg::Point4f& p)
00541 {
00542 const GLint loc = glGetUniformLocation(this->objectID, name);
00543 glUniform4fv(loc, 1, p.V());
00544 }
00545
00546 void Parameter(GLenum pname, int value)
00547 {
00548 glProgramParameteriEXT(this->objectID, pname, value);
00549 }
00550
00551 void Attribute(int index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
00552 {
00553 glVertexAttrib4f(index, x, y, z, w);
00554 }
00555
00556 void BindAttribute(int index, const char * name)
00557 {
00558 glBindAttribLocation(this->objectID, index, name);
00559 }
00560
00561 protected:
00562 std::set<Shader *> shaders;
00563 bool linked;
00564
00565 void DoBind(void)
00566 {
00567 if (!this->IsLinked())
00568 {
00569 this->Link();
00570 }
00571 glUseProgram(this->objectID);
00572 }
00573
00574 void DoUnbind(void)
00575 {
00576 glUseProgram(0);
00577 }
00578 };
00579
00580 class ProgramVF : public Bindable
00581 {
00582 public:
00583 Program prog;
00584 VertexShader vshd;
00585 FragmentShader fshd;
00586
00587 ProgramVF(void) : Bindable()
00588 {
00589 }
00590
00591 void SetSources(const char * vsrc, const char * fsrc)
00592 {
00593 if (vsrc) {
00594 this->vshd.SetSource(vsrc);
00595 this->prog.Attach(&(this->vshd));
00596 }
00597 if (fsrc) {
00598 this->fshd.SetSource(fsrc);
00599 this->prog.Attach(&(this->fshd));
00600 }
00601 }
00602
00603 void LoadSources(const char * vfile, const char * ffile)
00604 {
00605 if (vfile) {
00606 this->vshd.LoadSource(vfile);
00607 this->prog.Attach(&(this->vshd));
00608 }
00609 if (ffile) {
00610 this->fshd.LoadSource(ffile);
00611 this->prog.Attach(&(this->fshd));
00612 }
00613 }
00614
00615 protected:
00616 void DoBind(void)
00617 {
00618 this->prog.Bind();
00619 }
00620
00621 void DoUnbind(void)
00622 {
00623 this->prog.Unbind();
00624 }
00625 };
00626
00627 #endif // __SHADERS_H__