Developer Documentation
UniformPool.cc
1 /*===========================================================================*\
2  * *
3  * OpenFlipper *
4  * Copyright (c) 2001-2015, RWTH-Aachen University *
5  * Department of Computer Graphics and Multimedia *
6  * All rights reserved. *
7  * www.openflipper.org *
8  * *
9  *---------------------------------------------------------------------------*
10  * This file is part of OpenFlipper. *
11  *---------------------------------------------------------------------------*
12  * *
13  * Redistribution and use in source and binary forms, with or without *
14  * modification, are permitted provided that the following conditions *
15  * are met: *
16  * *
17  * 1. Redistributions of source code must retain the above copyright notice, *
18  * this list of conditions and the following disclaimer. *
19  * *
20  * 2. Redistributions in binary form must reproduce the above copyright *
21  * notice, this list of conditions and the following disclaimer in the *
22  * documentation and/or other materials provided with the distribution. *
23  * *
24  * 3. Neither the name of the copyright holder nor the names of its *
25  * contributors may be used to endorse or promote products derived from *
26  * this software without specific prior written permission. *
27  * *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS *
29  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED *
30  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A *
31  * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER *
32  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, *
33  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, *
34  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR *
35  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF *
36  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING *
37  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS *
38  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
39  * *
40 \*===========================================================================*/
41 
42 
43 #include <iostream>
44 #include <QTextStream>
45 
46 #include <ACG/GL/acg_glew.hh>
47 #include <ACG/GL/GLError.hh>
48 #include "UniformPool.hh"
49 
50 #ifdef WIN32
51  #ifndef __MINGW32__
52  #define snprintf sprintf_s
53  #endif
54 #endif
55 
56 //==============================================================================
57 
58 namespace GLSL {
59 
60  //--------------------------------------------------------------------------
61  // Uniform Pool
62  //--------------------------------------------------------------------------
63 
64 
66  }
67 
68 
70  addPool(_pool);
71  }
72 
73 
77  clear();
78  }
79 
80 
82  addPool(_other);
83  return *this;
84  }
85 
87  // Delete the uniforms in that pool
88  for (UniformListIt it = pool_.begin(); it != pool_.end(); ++it)
89  delete (*it);
90 
91  // Clear the pool
92  pool_.clear();
93  }
94 
95  bool UniformPool::empty() const {
96  return pool_.empty();
97  }
98 
99 
100  QString UniformPool::toString() const {
101 
102  QString result;
103  QTextStream resultStrm(&result);
104 
105  for (UniformList::const_iterator it = pool_.begin(); it != pool_.end(); ++it) {
106  resultStrm << (*it)->toString() << "\n";
107  }
108 
109  return result;
110  }
111 
116  void UniformPool::bind( PtrProgram _prog ) const {
117  bind(_prog->getProgramId());
118  }
119 
124  void UniformPool::bind( GLuint _prog ) const {
125  for (UniformList::const_iterator it = pool_.begin(); it != pool_.end(); ++it) {
126  (*it)->bind(_prog);
127  }
128  }
129 
135  UniformPool::UniformListIt UniformPool::findEntry( std::string _name ) {
136 
137  for (UniformListIt it = pool_.begin(); it != pool_.end(); ++it){
138  if ((*it)->id.compare(_name) == 0)
139  return it;
140  }
141 
142  return pool_.end();
143  }
144 
149  void UniformPool::addPool( const UniformPool& _src ){
150 
151  for (UniformList::const_iterator it = _src.pool_.begin(); it != _src.pool_.end(); ++it){
152 
153  // determine type
154  const UniformVecf* pVecf = dynamic_cast<const UniformVecf*>(*it);
155  const UniformVeci* pVeci = dynamic_cast<const UniformVeci*>(*it);
156  const UniformVecui* pVecui = dynamic_cast<const UniformVecui*>(*it);
157  const UniformMat* pMat = dynamic_cast<const UniformMat*>(*it);
158  const UniformBuf* pBuf = dynamic_cast<const UniformBuf*>(*it);
159 
160  // add to our list
161  if (pVecf)
162  addVecf(*pVecf);
163 
164  if (pVeci)
165  addVeci(*pVeci);
166 
167  if (pVecui)
168  addVecui(*pVecui);
169 
170  else if (pMat)
171  addMatrix(*pMat);
172 
173  else if (pBuf)
174  addBuf(pBuf->id.c_str(), pBuf->val, pBuf->size, pBuf->integer);
175  }
176  }
177 
178 
183  void UniformPool::UniformVecf::bind( GLuint _progID ) const {
184  checkGLError2("prev opengl error");
185  GLint location = glGetUniformLocation(_progID, id.c_str());
186  checkGLError2(id.c_str());
187 
188  switch (size){
189  case 1:
190  glUniform1fv(location, 1, val.data());
191  break;
192  case 2:
193  glUniform2fv(location, 1, val.data());
194  break;
195  case 3:
196  glUniform3fv(location, 1, val.data());
197  break;
198  case 4:
199  glUniform4fv(location, 1, val.data());
200  break;
201 
202  default:
203  std::cerr << "UniformPool::UniformVecf : invalid size " << size << std::endl;
204  break;
205  }
206 
207  checkGLError2(id.c_str());
208  }
209 
210 
215  const char* fmt = size > 1 ? "uniform vec%2 %1 = vec%2(" : "uniform float %1 = ";
216  QString str = QString(fmt).arg(id.c_str()).arg(size);
217  for (int i = 0; i < size; ++i) {
218  str += QString::number(val[i]);
219  if (i + 1 < size)
220  str += ", ";
221  }
222  if (size > 1)
223  str += ");";
224  return str;
225  }
226 
231  void UniformPool::UniformVeci::bind( GLuint _progID ) const {
232  checkGLError2("prev opengl error");
233  GLint location = glGetUniformLocation(_progID, id.c_str());
234  checkGLError2(id.c_str());
235 
236  switch (size){
237  case 1:
238  glUniform1iv(location, 1, (GLint*)val.data());
239  break;
240  case 2:
241  glUniform2iv(location, 1, (GLint*)val.data());
242  break;
243  case 3:
244  glUniform3iv(location, 1, (GLint*)val.data());
245  break;
246  case 4:
247  glUniform4iv(location, 1, (GLint*)val.data());
248  break;
249 
250  default:
251  std::cerr << "UniformPool::UniformVeci : invalid size " << size << std::endl;
252  break;
253  }
254 
255  checkGLError2(id.c_str());
256  }
257 
258 
263  const char* fmt = size > 1 ? "uniform ivec%2 %1 = ivec%2(" : "uniform int %1 = ";
264  QString str = QString(fmt).arg(id.c_str()).arg(size);
265  for (int i = 0; i < size; ++i) {
266  str += QString::number(val[i]);
267  if (i + 1 < size)
268  str += ", ";
269  }
270  if (size > 1)
271  str += ");";
272  return str;
273  }
274 
279  void UniformPool::UniformVecui::bind( GLuint _progID ) const {
280  checkGLError2("prev opengl error");
281  GLint location = glGetUniformLocation(_progID, id.c_str());
282  checkGLError2(id.c_str());
283 
284  switch (size){
285  case 1:
286  glUniform1uiv(location, 1, (GLuint*)val.data());
287  break;
288  case 2:
289  glUniform2uiv(location, 1, (GLuint*)val.data());
290  break;
291  case 3:
292  glUniform3uiv(location, 1, (GLuint*)val.data());
293  break;
294  case 4:
295  glUniform4uiv(location, 1, (GLuint*)val.data());
296  break;
297 
298  default:
299  std::cerr << "UniformPool::UniformVecui : invalid size " << size << std::endl;
300  break;
301  }
302 
303  checkGLError2(id.c_str());
304  }
305 
306 
311  const char* fmt = size > 1 ? "uniform uvec%2 %1 = uvec%2(" : "uniform uint %1 = ";
312  QString str = QString(fmt).arg(id.c_str()).arg(size);
313  for (int i = 0; i < size; ++i) {
314  str += QString::number(val[i]);
315  if (i + 1 < size)
316  str += ", ";
317  }
318  if (size > 1)
319  str += ");";
320  return str;
321  }
322 
327  void UniformPool::UniformMat::bind( GLuint _progID ) const {
328  checkGLError2("prev opengl error");
329  GLint location = glGetUniformLocation(_progID, id.c_str());
330  checkGLError2(id.c_str());
331 
332  switch (size){
333  case 2: {
334  float tmp[4];
335  for (int i = 0; i < 2; ++i)
336  for (int k = 0; k < 2; ++k)
337  tmp[i*2+k] = val.data()[i*4+k];
338  glUniformMatrix2fv(location, 1, transposed, tmp);
339  } break;
340 
341  case 3: {
342  float tmp[9];
343  for (int i = 0; i < 3; ++i)
344  for (int k = 0; k < 3; ++k)
345  tmp[i*3+k] = val.data()[i*4+k];
346  glUniformMatrix3fv(location, 1, transposed, tmp);
347  } break;
348 
349  case 4: glUniformMatrix4fv(location, 1, transposed, val.data()); break;
350 
351  default:
352  std::cerr << "UniformPool::UniformMat : invalid size " << size << std::endl;
353  break;
354  }
355 
356  checkGLError2(id.c_str());
357  }
358 
359 
364  QString str = QString("uniform mat%2 %1 = {").arg(id.c_str()).arg(size);
365  for (int y = 0; y < size; ++y) {
366  str += "{";
367  for (int x = 0; x < size; ++x) {
368  str += QString::number(val(y,x));
369  if (x + 1 < size)
370  str += ", ";
371  }
372  str += "}";
373  if (y + 1 < size)
374  str += ", ";
375  }
376  str += "};";
377  return str;
378  }
379 
384  void UniformPool::UniformBuf::bind( GLuint _progID ) const {
385  checkGLError2("prev opengl error");
386  GLint location = glGetUniformLocation(_progID, id.c_str());
387  checkGLError2(id.c_str());
388 
389  if (integer){
390  glUniform1iv(location, size, (GLint*)val);
391  }
392  else{
393  glUniform1fv(location, size, val);
394  }
395 
396  checkGLError2(id.c_str());
397  }
398 
399 
404  QString str = QString("uniform %3 %2[%1] = {").arg(id.c_str()).arg(size).arg(integer ? "int" : "float");
405  for (int y = 0; y < size; ++y) {
406  if (integer)
407  str += QString::number(((GLint*)val)[y]);
408  else
409  str += QString::number(val[y]);
410  if (y + 1 < size)
411  str += ", ";
412  }
413  str += "};";
414  return str;
415  }
416 
420  : val(0), integer(false), size(0)
421  {
422  }
423 
427  delete [] val;
428  }
429 
430 
435  void UniformPool::addVecf( const UniformVecf& _vec ) {
436  // look for existing uniform in pool
437  UniformListIt it = findEntry(_vec.id);
438 
439  // storage address of uniform
440  UniformVecf* dst = 0;
441 
442  if ( it == pool_.end() ){
443  // create new entry
444  dst = new UniformVecf;
445  pool_.push_back(dst);
446  }
447  else{
448  // use existing entry
449  dst = dynamic_cast<UniformVecf*>( *it );
450 
451  if (!dst)
452  std::cerr << "UniformPool::addVecf type of " << _vec.id << " incorrect." << std::endl;
453  }
454 
455  if (dst) {
456  // update data
457  dst->id = _vec.id;
458  dst->size = _vec.size;
459  dst->val = _vec.val;
460  }
461 
462  }
463 
468  void UniformPool::addVeci( const UniformVeci& _vec ) {
469  // look for existing uniform in pool
470  UniformListIt it = findEntry(_vec.id);
471 
472  // storage address of uniform
473  UniformVeci* dst = 0;
474 
475  if ( it == pool_.end() ){
476  // create new entry
477  dst = new UniformVeci;
478  pool_.push_back(dst);
479  }
480  else{
481  // use existing entry
482  dst = dynamic_cast<UniformVeci*>( *it );
483 
484  if (!dst)
485  std::cerr << "UniformPool::addVeci type of " << _vec.id << " incorrect." << std::endl;
486  }
487 
488  if (dst) {
489  // update data
490  dst->id = _vec.id;
491  dst->size = _vec.size;
492  dst->val = _vec.val;
493  }
494 
495  }
496 
501  void UniformPool::addVecui( const UniformVecui& _vec ) {
502  // look for existing uniform in pool
503  UniformListIt it = findEntry(_vec.id);
504 
505  // storage address of uniform
506  UniformVecui* dst = 0;
507 
508  if ( it == pool_.end() ){
509  // create new entry
510  dst = new UniformVecui;
511  pool_.push_back(dst);
512  }
513  else{
514  // use existing entry
515  dst = dynamic_cast<UniformVecui*>( *it );
516 
517  if (!dst)
518  std::cerr << "UniformPool::addVecui type of " << _vec.id << " incorrect." << std::endl;
519  }
520 
521  if (dst) {
522  // update data
523  dst->id = _vec.id;
524  dst->size = _vec.size;
525  dst->val = _vec.val;
526  }
527 
528  }
529 
534  void UniformPool::addMatrix( const UniformMat& _mat ) {
535  // look for existing uniform in pool
536  UniformListIt it = findEntry(_mat.id);
537 
538  // storage address of uniform
539  UniformMat* dst = 0;
540 
541  if ( it == pool_.end() ){
542  // create new entry
543  dst = new UniformMat;
544  pool_.push_back(dst);
545  }
546  else{
547  // use existing entry
548  dst = dynamic_cast<UniformMat*>( *it );
549 
550  if (!dst)
551  std::cerr << "UniformPool::addMatrix type of " << _mat.id << " incorrect." << std::endl;
552  }
553 
554  if (dst) {
555  // update data
556  dst->id = _mat.id;
557  dst->size = _mat.size;
558  dst->transposed = _mat.transposed;
559  dst->val = _mat.val;
560  }
561  }
562 
570  void UniformPool::addBuf( const char* _name, void* _values, int _count, bool _integer ) {
571  // look for existing uniform in pool
572  UniformListIt it = findEntry(_name);
573 
574  // storage address of uniform
575  UniformBuf* dst = 0;
576 
577  if ( it == pool_.end() ){
578  // create new entry
579  dst = new UniformBuf();
580  pool_.push_back(dst);
581  }
582  else{
583  // use existing entry
584  dst = dynamic_cast<UniformBuf*>( *it );
585 
586  if (!dst)
587  std::cerr << "UniformPool::addBuf type of " << _name << " incorrect." << std::endl;
588  }
589 
590  if (dst) {
591  // update data
592  dst->id = _name;
593 
594  if (dst->size < _count)
595  {
596  // resize
597  delete [] dst->val;
598  dst->val = new float[_count];
599  }
600 
601  dst->size = _count;
602 
603  if (_values)
604  memcpy(dst->val, _values, _count * sizeof(float));
605  }
606  }
607 
608 
614  void UniformPool::setUniform( const char *_name, GLint _value ) {
615  // create uniform descriptor
616  UniformVeci tmp;
617  tmp.id = _name;
618  tmp.size = 1;
619  tmp.val[0] = _value;
620 
621  // add/update in pool
622  addVeci(tmp);
623  }
624 
630  void UniformPool::setUniform( const char *_name, const ACG::Vec2i &_value ) {
631  // create uniform descriptor
632  UniformVeci tmp;
633  tmp.id = _name;
634  tmp.size = 2;
635  tmp.val[0] = _value[0];
636  tmp.val[1] = _value[1];
637 
638  // add/update in pool
639  addVeci(tmp);
640  }
641 
647  void UniformPool::setUniform( const char *_name, const ACG::Vec3i &_value ) {
648  // create uniform descriptor
649  UniformVeci tmp;
650  tmp.id = _name;
651  tmp.size = 3;
652  tmp.val[0] = _value[0];
653  tmp.val[1] = _value[1];
654  tmp.val[2] = _value[2];
655 
656  // add/update in pool
657  addVeci(tmp);
658  }
659 
665  void UniformPool::setUniform( const char *_name, const ACG::Vec4i &_value ) {
666  // create uniform descriptor
667  UniformVeci tmp;
668  tmp.id = _name;
669  tmp.size = 4;
670  tmp.val = _value;
671 
672  // add/update in pool
673  addVeci(tmp);
674  }
675 
681  void UniformPool::setUniform( const char *_name, GLuint _value ) {
682  // create uniform descriptor
683  UniformVecui tmp;
684  tmp.id = _name;
685  tmp.size = 1;
686  tmp.val[0] = _value;
687 
688  // add/update in pool
689  addVecui(tmp);
690  }
691 
697  void UniformPool::setUniform( const char *_name, const ACG::Vec2ui &_value ) {
698  // create uniform descriptor
699  UniformVecui tmp;
700  tmp.id = _name;
701  tmp.size = 2;
702  tmp.val[0] = _value[0];
703  tmp.val[1] = _value[1];
704 
705  // add/update in pool
706  addVecui(tmp);
707  }
708 
714  void UniformPool::setUniform( const char *_name, const ACG::Vec3ui &_value ) {
715  // create uniform descriptor
716  UniformVecui tmp;
717  tmp.id = _name;
718  tmp.size = 3;
719  tmp.val[0] = _value[0];
720  tmp.val[1] = _value[1];
721  tmp.val[2] = _value[2];
722 
723  // add/update in pool
724  addVecui(tmp);
725  }
726 
732  void UniformPool::setUniform( const char *_name, const ACG::Vec4ui &_value ) {
733  // create uniform descriptor
734  UniformVecui tmp;
735  tmp.id = _name;
736  tmp.size = 4;
737  tmp.val = _value;
738 
739  // add/update in pool
740  addVecui(tmp);
741  }
742 
743 
749  void UniformPool::setUniform( const char *_name, GLfloat _value ) {
750  // create uniform descriptor
751  UniformVecf tmp;
752  tmp.id = _name;
753  tmp.size = 1;
754  tmp.val[0] = _value;
755 
756  // add/update in pool
757  addVecf(tmp);
758  }
759 
765  void UniformPool::setUniform( const char *_name, const ACG::Vec2f &_value ) {
766  // create uniform descriptor
767  UniformVecf tmp;
768  tmp.id = _name;
769  tmp.size = 2;
770  tmp.val[0] = _value[0];
771  tmp.val[1] = _value[1];
772 
773  // add/update in pool
774  addVecf(tmp);
775  }
776 
782  void UniformPool::setUniform( const char *_name, const ACG::Vec3f &_value ) {
783  // create uniform descriptor
784  UniformVecf tmp;
785  tmp.id = _name;
786  tmp.size = 3;
787  tmp.val[0] = _value[0];
788  tmp.val[1] = _value[1];
789  tmp.val[2] = _value[2];
790 
791  // add/update in pool
792  addVecf(tmp);
793  }
794 
800  void UniformPool::setUniform( const char *_name, const ACG::Vec4f &_value ) {
801  // create uniform descriptor
802  UniformVecf tmp;
803  tmp.id = _name;
804  tmp.size = 4;
805  tmp.val = _value;
806 
807  // add/update in pool
808  addVecf(tmp);
809  }
810 
817  void UniformPool::setUniform( const char *_name, const ACG::GLMatrixf &_value, bool _transposed ) {
818  // create uniform descriptor
819  UniformMat tmp;
820  tmp.id = _name;
821  tmp.transposed = _transposed;
822  tmp.size = 4;
823  tmp.val = _value;
824 
825  // add/update in pool
826  addMatrix(tmp);
827  }
828 
835  void UniformPool::setUniformMat3( const char *_name, const ACG::GLMatrixf &_value, bool _transposed ) {
836  // create uniform descriptor
837  UniformMat tmp;
838  tmp.id = _name;
839  tmp.transposed = _transposed;
840  tmp.size = 3;
841  tmp.val = _value;
842 
843  // add/update in pool
844  addMatrix(tmp);
845  }
846 
853  void UniformPool::setUniform( const char *_name, GLint *_values, int _count ) {
854  // add/update in pool
855  addBuf(_name, _values, _count, true);
856  }
857 
864  void UniformPool::setUniform( const char *_name, GLfloat *_values, int _count ) {
865  // add/update in pool
866  addBuf(_name, _values, _count, false);
867  }
868 
869 }
870 
871 
872 //==============================================================================
This namespace contains all the classes and functions for handling GLSL shader and program objects...
Definition: AntiAliasing.hh:66
void clear()
Clear the pool.
Definition: UniformPool.cc:86
void setUniformMat3(const char *_name, const ACG::GLMatrixf &_value, bool _transposed=false)
Set 3x3fMatrix uniform to specified value.
Definition: UniformPool.cc:835
void addVecui(const UniformVecui &_vec)
Add or update a vector type uniform in pool.
Definition: UniformPool.cc:501
void setUniform(const char *_name, GLint _value)
Set int uniform to specified value.
Definition: UniformPool.cc:614
void bind(GLuint _progID) const
Bind uniform uint vector to shader.
Definition: UniformPool.cc:279
void addVecf(const UniformVecf &_vec)
Add or update a vector type uniform in pool.
Definition: UniformPool.cc:435
virtual ~UniformPool()
Destructor.
Definition: UniformPool.cc:76
UniformListIt findEntry(std::string _name)
Search the pool for an existing value for a uniform name.
Definition: UniformPool.cc:135
UniformList pool_
list of uniform params
Definition: UniformPool.hh:199
bool empty() const
returns if the pool is empty
Definition: UniformPool.cc:95
GLuint getProgramId()
Returns opengl id.
Definition: GLSLShader.cc:376
virtual QString toString() const
print int vector to string
Definition: UniformPool.cc:262
virtual QString toString() const
print float vector to string
Definition: UniformPool.cc:214
void bind(GLuint _progID) const
Bind uniform matrix to shader.
Definition: UniformPool.cc:327
GLSL program class.
Definition: GLSLShader.hh:211
UniformPool & operator=(const UniformPool &_other)
copy
Definition: UniformPool.cc:81
void bind(GLuint _progID) const
Bind uniform int vector to shader.
Definition: UniformPool.cc:231
virtual QString toString() const
print buffer id to string
Definition: UniformPool.cc:403
void bind(GLuint _progID) const
Bind uniform float vector to shader.
Definition: UniformPool.cc:183
void addBuf(const char *_name, void *_values, int _count, bool _integer)
Add or update an array type uniform in pool.
Definition: UniformPool.cc:570
virtual QString toString() const
print matrix to string
Definition: UniformPool.cc:363
void addPool(const UniformPool &_src)
Add all uniforms of a pool to this pool.
Definition: UniformPool.cc:149
virtual QString toString() const
print uint vector to string
Definition: UniformPool.cc:310
GLSL uniform pool.
Definition: UniformPool.hh:64
void addMatrix(const UniformMat &_mat)
Add or update a matrix type uniform in pool.
Definition: UniformPool.cc:534
QString toString() const
print to string for debugging
Definition: UniformPool.cc:100
UniformBuf()
Creates a copy of input data.
Definition: UniformPool.cc:419
void addVeci(const UniformVeci &_vec)
Add or update a vector type uniform in pool.
Definition: UniformPool.cc:468
void bind(PtrProgram _prog) const
Send all stored uniforms to program.
Definition: UniformPool.cc:116
UniformPool()
Constructor.
Definition: UniformPool.cc:65
void bind(GLuint _progID) const
Bind uniform array to shader.
Definition: UniformPool.cc:384