1 /****************************************************************************
2 * Render Radiance Scaling                                                   *
3 * Meshlab's plugin                                                          *
4 *                                                                           *
5 * Copyright(C) 2010                                                         *
6 * Vergne Romain, Dumas Olivier                                              *
7 * INRIA - Institut Nationnal de Recherche en Informatique et Automatique    *
8 *                                                                           *
9 * All rights reserved.                                                      *
10 *                                                                           *
11 * This program is free software; you can redistribute it and/or modify      *
12 * it under the terms of the GNU General Public License as published by      *
13 * the Free Software Foundation; either version 2 of the License, or         *
14 * (at your option) any later version.                                       *
15 *                                                                           *
16 * This program is distributed in the hope that it will be useful,           *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)          *
20 * for more details.                                                         *
21 *                                                                           *
22 ****************************************************************************/
23 #ifndef GPUPROGRAM_H
24 #define GPUPROGRAM_H
25 
26 #include <GL/glew.h>
27 #include <iostream>
28 #include "gpuShader.h"
29 #include <string>
30 #include <vector>
31 #include <map>
32 
33 class GPUProgram {
34 
35  public:
36   GPUProgram(GPUShader *vs=NULL,GPUShader *fs=NULL,GPUShader *geom=NULL,
37              int inputGeometry=0,int outputGeometry=0,int outVertices=0);
38 
39   GPUProgram(const std::string &vsFile="",
40              const std::string &fsFile="",
41              const std::string &gsFile="",
42              int inputGeometry=0,
43              int outputGeometry=0,
44              int outVertices=0);
45 
46   ~GPUProgram();
47 
48   void addUniform(const std::string &uniformName);
49   void addAttribute(const std::string &attributeName);
50   void reload();
51 
52   inline GLuint id() const;
53   bool haveShaderOfType(SHADER_TYPE type);
54   std::string filename(SHADER_TYPE type);
55 
56   inline void enable();
57   inline void disable();
58 
59   inline GLint getUniformLocation(const std::string &uniformName);
60   inline GLint getAttributeLocation(const std::string &attributeName);
61 
62   inline void setUniform1f(const std::string &uniformName,GLfloat v);
63   inline void setUniform2f(const std::string &uniformName,GLfloat v1,GLfloat v2);
64   inline void setUniform3f(const std::string &uniformName,GLfloat v1,GLfloat v2,GLfloat v3);
65   inline void setUniform4f(const std::string &uniformName,GLfloat v1,GLfloat v2,GLfloat v3,GLfloat v4);
66   inline void setUniform1f(GLint loc,GLfloat v);
67   inline void setUniform2f(GLint loc,GLfloat v1,GLfloat v2);
68   inline void setUniform3f(GLint loc,GLfloat v1,GLfloat v2,GLfloat v3);
69   inline void setUniform4f(GLint loc,GLfloat v1,GLfloat v2,GLfloat v3,GLfloat v4);
70 
71   inline void setUniform1i(const std::string &uniformName,GLint v);
72   inline void setUniform2i(const std::string &uniformName,GLint v1,GLint v2);
73   inline void setUniform3i(const std::string &uniformName,GLint v1,GLint v2,GLint v3);
74   inline void setUniform4i(const std::string &uniformName,GLint v1,GLint v2,GLint v3,GLint v4);
75   inline void setUniform1i(GLint loc,GLint v);
76   inline void setUniform2i(GLint loc,GLint v1,GLint v2);
77   inline void setUniform3i(GLint loc,GLint v1,GLint v2,GLint v3);
78   inline void setUniform4i(GLint loc,GLint v1,GLint v2,GLint v3,GLint v4);
79 
80   inline void setUniform1fv(const std::string &uniformName,GLfloat *v,GLsizei count=1);
81   inline void setUniform2fv(const std::string &uniformName,GLfloat *v,GLsizei count=1);
82   inline void setUniform3fv(const std::string &uniformName,GLfloat *v,GLsizei count=1);
83   inline void setUniform4fv(const std::string &uniformName,GLfloat *v,GLsizei count=1);
84   inline void setUniform1fv(GLint loc,GLfloat *v,GLsizei count=1);
85   inline void setUniform2fv(GLint loc,GLfloat *v,GLsizei count=1);
86   inline void setUniform3fv(GLint loc,GLfloat *v,GLsizei count=1);
87   inline void setUniform4fv(GLint loc,GLfloat *v,GLsizei count=1);
88 
89   inline void setUniform1iv(const std::string &uniformName,GLint *v,GLsizei count=1);
90   inline void setUniform2iv(const std::string &uniformName,GLint *v,GLsizei count=1);
91   inline void setUniform3iv(const std::string &uniformName,GLint *v,GLsizei count=1);
92   inline void setUniform4iv(const std::string &uniformName,GLint *v,GLsizei count=1);
93   inline void setUniform1iv(GLint loc,GLint *v,GLsizei count=1);
94   inline void setUniform2iv(GLint loc,GLint *v,GLsizei count=1);
95   inline void setUniform3iv(GLint loc,GLint *v,GLsizei count=1);
96   inline void setUniform4iv(GLint loc,GLint *v,GLsizei count=1);
97 
98   inline void setUniformMatrix2fv(const std::string &uniformName,GLfloat *v,GLsizei count=1,GLboolean transpose=false);
99   inline void setUniformMatrix3fv(const std::string &uniformName,GLfloat *v,GLsizei count=1,GLboolean transpose=false);
100   inline void setUniformMatrix4fv(const std::string &uniformName,GLfloat *v,GLsizei count=1,GLboolean transpose=false);
101   inline void setUniformMatrix2fv(GLint loc,GLfloat *v,GLsizei count=1,GLboolean transpose=false);
102   inline void setUniformMatrix3fv(GLint loc,GLfloat *v,GLsizei count=1,GLboolean transpose=false);
103   inline void setUniformMatrix4fv(GLint loc,GLfloat *v,GLsizei count=1,GLboolean transpose=false);
104 
105   inline void setUniformTexture(const std::string &uniformName,GLint num,GLenum type,GLuint textureName);
106   inline void setUniformTexture(GLint loc,GLint num,GLenum type,GLuint textureName);
107 
108   inline void  setUniformBuffer(const std::string &uniformName,GLuint buffer);
109   inline void  setUniformBuffer(GLint loc,GLuint buffer);
110   inline GLint getUniformBufferSize(const std::string &uniformName);
111   inline GLint getUniformBufferSize(GLint loc);
112 
113  protected:
114   void attach();
115   bool link();
116   bool attachAndLink();
117   void detach();
118   void setGeometryParameters(int inputGeometry,int outputGeometry,int outVertices);
119 
120  private:
121 
122   GPUShader* _vs;
123   GPUShader* _fs;
124   GPUShader* _gs;
125   GLuint     _programId;
126 
127   std::map<std::string,GLint>                _uniformLocations;
128   std::map<std::string,GLint>                _attributeLocations;
129   std::map<GLuint,std::pair<GLenum,GLenum> > _textures;
130 
131   int _inputGeometry;
132   int _outputGeometry;
133   int _outVertices;
134 };
135 
enable()136 inline void GPUProgram::enable() {
137   glUseProgramObjectARB(_programId);
138 
139   for(std::map<GLuint,std::pair<GLenum,GLenum> >::iterator i=_textures.begin();i!=_textures.end();++i) {
140     glActiveTexture((*i).second.first);
141     glBindTexture((*i).second.second,(*i).first);
142     glEnable((*i).second.second);
143   }
144 
145 }
146 
disable()147 inline void GPUProgram::disable() {
148   for(std::map<GLuint,std::pair<GLenum,GLenum> >::reverse_iterator i=_textures.rbegin();i!=_textures.rend();++i) {
149     glActiveTexture((*i).second.first);
150     glDisable((*i).second.second);
151   }
152 
153   glUseProgramObjectARB(0);
154 }
155 
id()156 inline GLuint GPUProgram::id() const {
157   return _programId;
158 }
159 
setUniform1f(const std::string & uniformName,GLfloat v)160 inline void GPUProgram::setUniform1f(const std::string &uniformName,GLfloat v) {
161   glUniform1f(_uniformLocations[uniformName],v);
162 }
163 
setUniform2f(const std::string & uniformName,GLfloat v1,GLfloat v2)164 inline void GPUProgram::setUniform2f(const std::string &uniformName,GLfloat v1,GLfloat v2) {
165   glUniform2f(_uniformLocations[uniformName],v1,v2);
166 }
167 
setUniform3f(const std::string & uniformName,GLfloat v1,GLfloat v2,GLfloat v3)168 inline void GPUProgram::setUniform3f(const std::string &uniformName,GLfloat v1,GLfloat v2,GLfloat v3) {
169   glUniform3f(_uniformLocations[uniformName],v1,v2,v3);
170 }
171 
setUniform4f(const std::string & uniformName,GLfloat v1,GLfloat v2,GLfloat v3,GLfloat v4)172 inline void GPUProgram::setUniform4f(const std::string &uniformName,GLfloat v1,GLfloat v2,GLfloat v3,GLfloat v4) {
173   glUniform4f(_uniformLocations[uniformName],v1,v2,v3,v4);
174 }
175 
setUniform1i(const std::string & uniformName,GLint v)176 inline void GPUProgram::setUniform1i(const std::string &uniformName,GLint v) {
177   glUniform1i(_uniformLocations[uniformName],v);
178 }
179 
setUniform2i(const std::string & uniformName,GLint v1,GLint v2)180 inline void GPUProgram::setUniform2i(const std::string &uniformName,GLint v1,GLint v2) {
181   glUniform2i(_uniformLocations[uniformName],v1,v2);
182 }
183 
setUniform3i(const std::string & uniformName,GLint v1,GLint v2,GLint v3)184 inline void GPUProgram::setUniform3i(const std::string &uniformName,GLint v1,GLint v2,GLint v3) {
185   glUniform3i(_uniformLocations[uniformName],v1,v2,v3);
186 }
187 
setUniform4i(const std::string & uniformName,GLint v1,GLint v2,GLint v3,GLint v4)188 inline void GPUProgram::setUniform4i(const std::string &uniformName,GLint v1,GLint v2,GLint v3,GLint v4) {
189   glUniform4i(_uniformLocations[uniformName],v1,v2,v3,v4);
190 }
191 
setUniform1fv(const std::string & uniformName,GLfloat * v,GLsizei count)192 inline void GPUProgram::setUniform1fv(const std::string &uniformName,GLfloat *v,GLsizei count) {
193   glUniform1fv(_uniformLocations[uniformName],count,v);
194 }
195 
setUniform2fv(const std::string & uniformName,GLfloat * v,GLsizei count)196 inline void GPUProgram::setUniform2fv(const std::string &uniformName,GLfloat *v,GLsizei count) {
197   glUniform2fv(_uniformLocations[uniformName],count,v);
198 }
199 
setUniform3fv(const std::string & uniformName,GLfloat * v,GLsizei count)200 inline void GPUProgram::setUniform3fv(const std::string &uniformName,GLfloat *v,GLsizei count) {
201   glUniform3fv(_uniformLocations[uniformName],count,v);
202 }
203 
setUniform4fv(const std::string & uniformName,GLfloat * v,GLsizei count)204 inline void GPUProgram::setUniform4fv(const std::string &uniformName,GLfloat *v,GLsizei count) {
205   glUniform4fv(_uniformLocations[uniformName],count,v);
206 }
207 
setUniform1iv(const std::string & uniformName,GLint * v,GLsizei count)208 inline void GPUProgram::setUniform1iv(const std::string &uniformName,GLint *v,GLsizei count) {
209   glUniform1iv(_uniformLocations[uniformName],count,v);
210 }
211 
setUniform2iv(const std::string & uniformName,GLint * v,GLsizei count)212 inline void GPUProgram::setUniform2iv(const std::string &uniformName,GLint *v,GLsizei count) {
213   glUniform2iv(_uniformLocations[uniformName],count,v);
214 }
215 
setUniform3iv(const std::string & uniformName,GLint * v,GLsizei count)216 inline void GPUProgram::setUniform3iv(const std::string &uniformName,GLint *v,GLsizei count) {
217   glUniform3iv(_uniformLocations[uniformName],count,v);
218 }
219 
setUniform4iv(const std::string & uniformName,GLint * v,GLsizei count)220 inline void GPUProgram::setUniform4iv(const std::string &uniformName,GLint *v,GLsizei count) {
221   glUniform4iv(_uniformLocations[uniformName],count,v);
222 }
223 
setUniformMatrix2fv(const std::string & uniformName,GLfloat * v,GLsizei count,GLboolean transpose)224 inline void GPUProgram::setUniformMatrix2fv(const std::string &uniformName,GLfloat *v,GLsizei count,GLboolean transpose) {
225   glUniformMatrix2fv(_uniformLocations[uniformName],count,transpose,v);
226 }
227 
setUniformMatrix3fv(const std::string & uniformName,GLfloat * v,GLsizei count,GLboolean transpose)228 inline void GPUProgram::setUniformMatrix3fv(const std::string &uniformName,GLfloat *v,GLsizei count,GLboolean transpose) {
229   glUniformMatrix3fv(_uniformLocations[uniformName],count,transpose,v);
230 }
231 
setUniformMatrix4fv(const std::string & uniformName,GLfloat * v,GLsizei count,GLboolean transpose)232 inline void GPUProgram::setUniformMatrix4fv(const std::string &uniformName,GLfloat *v,GLsizei count,GLboolean transpose) {
233   glUniformMatrix4fv(_uniformLocations[uniformName],count,transpose,v);
234 }
235 
setUniformTexture(const std::string & uniformName,GLint num,GLenum type,GLuint textureName)236 inline void GPUProgram::setUniformTexture(const std::string &uniformName,GLint num,GLenum type,GLuint textureName) {
237   GLenum textureNum;
238 
239   const std::map<GLuint,std::pair<GLenum,GLenum> >::iterator it = _textures.find(textureName);
240 
241   if(it==_textures.end()) {
242     textureNum = GL_TEXTURE0+_textures.size();
243   } else {
244     textureNum = (*it).second.first;
245   }
246 
247   glPushAttrib(GL_TEXTURE_BIT);
248   glActiveTexture(textureNum);
249   glBindTexture(type,textureName);
250   glEnable(type);
251 
252   glUniform1i(_uniformLocations[uniformName],num);
253   _textures[textureName] = std::pair<GLenum,GLenum>(textureNum,type);
254 
255   glDisable(type);
256   glPopAttrib();
257 }
258 
setUniform1f(GLint loc,GLfloat v)259 inline void GPUProgram::setUniform1f(GLint loc,GLfloat v) {
260   glUniform1f(loc,v);
261 }
262 
setUniform2f(GLint loc,GLfloat v1,GLfloat v2)263 inline void GPUProgram::setUniform2f(GLint loc,GLfloat v1,GLfloat v2) {
264   glUniform2f(loc,v1,v2);
265 }
266 
setUniform3f(GLint loc,GLfloat v1,GLfloat v2,GLfloat v3)267 inline void GPUProgram::setUniform3f(GLint loc,GLfloat v1,GLfloat v2,GLfloat v3) {
268   glUniform3f(loc,v1,v2,v3);
269 }
270 
setUniform4f(GLint loc,GLfloat v1,GLfloat v2,GLfloat v3,GLfloat v4)271 inline void GPUProgram::setUniform4f(GLint loc,GLfloat v1,GLfloat v2,GLfloat v3,GLfloat v4) {
272   glUniform4f(loc,v1,v2,v3,v4);
273 }
274 
setUniform1i(GLint loc,GLint v)275 inline void GPUProgram::setUniform1i(GLint loc,GLint v) {
276   glUniform1i(loc,v);
277 }
278 
setUniform2i(GLint loc,GLint v1,GLint v2)279 inline void GPUProgram::setUniform2i(GLint loc,GLint v1,GLint v2) {
280   glUniform2i(loc,v1,v2);
281 }
282 
setUniform3i(GLint loc,GLint v1,GLint v2,GLint v3)283 inline void GPUProgram::setUniform3i(GLint loc,GLint v1,GLint v2,GLint v3) {
284   glUniform3i(loc,v1,v2,v3);
285 }
286 
setUniform4i(GLint loc,GLint v1,GLint v2,GLint v3,GLint v4)287 inline void GPUProgram::setUniform4i(GLint loc,GLint v1,GLint v2,GLint v3,GLint v4) {
288   glUniform4i(loc,v1,v2,v3,v4);
289 }
290 
setUniform1fv(GLint loc,GLfloat * v,GLsizei count)291 inline void GPUProgram::setUniform1fv(GLint loc,GLfloat *v,GLsizei count) {
292   glUniform1fv(loc,count,v);
293 }
294 
setUniform2fv(GLint loc,GLfloat * v,GLsizei count)295 inline void GPUProgram::setUniform2fv(GLint loc,GLfloat *v,GLsizei count) {
296   glUniform2fv(loc,count,v);
297 }
298 
setUniform3fv(GLint loc,GLfloat * v,GLsizei count)299 inline void GPUProgram::setUniform3fv(GLint loc,GLfloat *v,GLsizei count) {
300   glUniform3fv(loc,count,v);
301 }
302 
setUniform4fv(GLint loc,GLfloat * v,GLsizei count)303 inline void GPUProgram::setUniform4fv(GLint loc,GLfloat *v,GLsizei count) {
304   glUniform4fv(loc,count,v);
305 }
306 
setUniform1iv(GLint loc,GLint * v,GLsizei count)307 inline void GPUProgram::setUniform1iv(GLint loc,GLint *v,GLsizei count) {
308   glUniform1iv(loc,count,v);
309 }
310 
setUniform2iv(GLint loc,GLint * v,GLsizei count)311 inline void GPUProgram::setUniform2iv(GLint loc,GLint *v,GLsizei count) {
312   glUniform2iv(loc,count,v);
313 }
314 
setUniform3iv(GLint loc,GLint * v,GLsizei count)315 inline void GPUProgram::setUniform3iv(GLint loc,GLint *v,GLsizei count) {
316   glUniform3iv(loc,count,v);
317 }
318 
setUniform4iv(GLint loc,GLint * v,GLsizei count)319 inline void GPUProgram::setUniform4iv(GLint loc,GLint *v,GLsizei count) {
320   glUniform4iv(loc,count,v);
321 }
322 
setUniformMatrix2fv(GLint loc,GLfloat * v,GLsizei count,GLboolean transpose)323 inline void GPUProgram::setUniformMatrix2fv(GLint loc,GLfloat *v,GLsizei count,GLboolean transpose) {
324   glUniformMatrix2fv(loc,count,transpose,v);
325 }
326 
setUniformMatrix3fv(GLint loc,GLfloat * v,GLsizei count,GLboolean transpose)327 inline void GPUProgram::setUniformMatrix3fv(GLint loc,GLfloat *v,GLsizei count,GLboolean transpose) {
328   glUniformMatrix3fv(loc,count,transpose,v);
329 }
330 
setUniformMatrix4fv(GLint loc,GLfloat * v,GLsizei count,GLboolean transpose)331 inline void GPUProgram::setUniformMatrix4fv(GLint loc,GLfloat *v,GLsizei count,GLboolean transpose) {
332   glUniformMatrix4fv(loc,count,transpose,v);
333 }
334 
setUniformTexture(GLint loc,GLint num,GLenum type,GLuint textureName)335 inline void GPUProgram::setUniformTexture(GLint loc,GLint num,GLenum type,GLuint textureName) {
336   GLenum textureNum;
337 
338   const std::map<GLuint,std::pair<GLenum,GLenum> >::iterator it = _textures.find(textureName);
339 
340   if(it==_textures.end()) {
341     textureNum = GL_TEXTURE0+_textures.size();
342   } else {
343     textureNum = (*it).second.first;
344   }
345 
346   glPushAttrib(GL_TEXTURE_BIT);
347   glActiveTexture(textureNum);
348   glBindTexture(type,textureName);
349   glEnable(type);
350 
351   glUniform1i(loc,num);
352   _textures[textureName] = std::pair<GLenum,GLenum>(textureNum,type);
353 
354   glDisable(type);
355   glPopAttrib();
356 }
357 
getUniformLocation(const std::string & uniformName)358 inline GLint GPUProgram::getUniformLocation(const std::string &uniformName) {
359   return _uniformLocations[uniformName];
360 }
361 
getAttributeLocation(const std::string & attributeName)362 inline GLint GPUProgram::getAttributeLocation(const std::string &attributeName) {
363   return _attributeLocations[attributeName];
364 }
365 
setUniformBuffer(const std::string & uniformName,GLuint buffer)366 inline void GPUProgram::setUniformBuffer(const std::string &uniformName,GLuint buffer) {
367   glUniformBufferEXT(_programId,_uniformLocations[uniformName],buffer);
368 }
369 
setUniformBuffer(GLint loc,GLuint buffer)370 inline void GPUProgram::setUniformBuffer(GLint loc,GLuint buffer) {
371   glUniformBufferEXT(_programId,loc,buffer);
372 }
373 
getUniformBufferSize(const std::string & uniformName)374 inline GLint GPUProgram::getUniformBufferSize(const std::string &uniformName) {
375   return glGetUniformBufferSizeEXT(_programId,_uniformLocations[uniformName]);
376 }
377 
getUniformBufferSize(GLint loc)378 inline GLint GPUProgram::getUniformBufferSize(GLint loc) {
379   return glGetUniformBufferSizeEXT(_programId,loc);
380 }
381 
382 static inline
383 void CheckErrorsGL(const char* location=NULL,std::ostream& ostr = std::cerr) {
384 
385   GLuint errnum;
386   const char *errstr;
387   while((errnum=glGetError())) {
388     ostr << " **************************************************** " << std::endl;
389     ostr << " Checking OpenGL Error " << std::endl;
390 
391     std::cout << " **************************************************** " << std::endl;
392     std::cout << " Checking OpenGL Error " << std::endl;
393 
394     errstr = reinterpret_cast<const char *>(gluErrorString(errnum));
395     ostr << errstr;
396 
397     if(location) ostr << " at " << location;
398     ostr << std::endl;
399     std::cout << " **************************************************** " << std::endl;
400     ostr << " **************************************************** " << std::endl;
401   }
402 }
403 
404 #endif // GPUPROGRAM_H
405