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