GLSLShader.h 13 KB
Newer Older
Pierre Kraemer's avatar
Pierre Kraemer committed
1 2 3
/*******************************************************************************
* CGoGN: Combinatorial and Geometric modeling with Generic N-dimensional Maps  *
* version 0.1                                                                  *
4
* Copyright (C) 2009-2012, IGG Team, LSIIT, University of Strasbourg           *
Pierre Kraemer's avatar
Pierre Kraemer committed
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
*                                                                              *
* This library is free software; you can redistribute it and/or modify it      *
* under the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation; either version 2.1 of the License, or (at your     *
* option) any later version.                                                   *
*                                                                              *
* This library 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 Lesser General Public License  *
* for more details.                                                            *
*                                                                              *
* You should have received a copy of the GNU Lesser General Public License     *
* along with this library; if not, write to the Free Software Foundation,      *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.           *
*                                                                              *
20
* Web site: http://cgogn.unistra.fr/                                           *
Pierre Kraemer's avatar
Pierre Kraemer committed
21 22 23 24 25 26 27 28
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/

/***********************************************
*  Thanks to Frederic Larue for this class
***********************************************/

Sylvain Thery's avatar
Sylvain Thery committed
29 30
#ifndef __CGoGN_GLSL_SHADER__
#define __CGoGN_GLSL_SHADER__
Pierre Kraemer's avatar
Pierre Kraemer committed
31

32
#include "Utils/gl_def.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
33
#include "Utils/os_spec.h"
Thery Sylvain's avatar
Thery Sylvain committed
34
#include "Utils/vbo_base.h"
35
#include "Utils/gl_matrices.h"
Thery Sylvain's avatar
Thery Sylvain committed
36
#include "Utils/cgognStream.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
37

Sylvain Thery's avatar
Sylvain Thery committed
38
#include "glm/glm.hpp"
Pierre Kraemer's avatar
Pierre Kraemer committed
39 40 41 42
#include <GL/glew.h>

#include <stdlib.h>
#include <string>
43
#include <vector>
44 45
#include <set>

46

Pierre Kraemer's avatar
Pierre Kraemer committed
47 48
namespace CGoGN
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
49

Pierre Kraemer's avatar
Pierre Kraemer committed
50 51 52
namespace Utils
{

53
class GLSLShader
Pierre Kraemer's avatar
Pierre Kraemer committed
54
{
55
public:
Sylvain Thery's avatar
Sylvain Thery committed
56 57 58 59 60 61
	struct VAStr
	{
		int va_id;
		VBO* vbo_ptr;
	};

62 63 64 65
	/**
	 * enum of supported shader type
	 */
	enum shaderType {VERTEX_SHADER = 1, FRAGMENT_SHADER = 2, GEOMETRY_SHADER = 3 };
Pierre Kraemer's avatar
Pierre Kraemer committed
66

Sylvain Thery's avatar
Sylvain Thery committed
67 68
	static unsigned int CURRENT_OGL_VERSION;

69
	static std::set< std::pair<void*, GLSLShader*> >* m_registeredShaders;
Pierre Kraemer's avatar
Pierre Kraemer committed
70

71 72 73
//	static glm::mat4* s_current_matrices;
	static Utils::GL_Matrices* s_current_matrices;

Pierre Kraemer's avatar
Pierre Kraemer committed
74
protected:
Sylvain Thery's avatar
Sylvain Thery committed
75 76 77 78 79 80
	static std::string DEFINES_GL2;

	static std::string DEFINES_GL3;

	static std::string* DEFINES_GL;

81 82
	static std::string defines_Geom(const std::string& primitivesIn, const std::string& primitivesOut, int maxVert);

Sylvain Thery's avatar
Sylvain Thery committed
83 84 85
	int m_nbMaxVertices;


86 87 88
	/**
	 * handle of vertex shader
	 */
89
	CGoGNGLhandleARB	m_vertex_shader_object;
90 91 92 93

	/**
	 * handle of fragment shader
	 */
94
	CGoGNGLhandleARB	m_fragment_shader_object;
95 96 97 98

	/**
	 * handle of geometry shader
	 */
99
	CGoGNGLhandleARB	m_geom_shader_object;
100

Sylvain Thery's avatar
Sylvain Thery committed
101 102 103 104
	std::string m_nameVS;
	std::string m_nameFS;
	std::string m_nameGS;

105 106 107
	/**
	 * handle of program
	 */
Sylvain Thery's avatar
Sylvain Thery committed
108
	CGoGNGLint m_program_object;
109

110 111 112 113
	CGoGNGLint m_uniMat_Proj;
	CGoGNGLint m_uniMat_Model;
	CGoGNGLint m_uniMat_ModelProj;
	CGoGNGLint m_uniMat_Normal;
114 115 116 117 118 119 120 121

	char* m_vertex_shader_source;
	char* m_fragment_shader_source;
	char* m_geom_shader_source;

	GLint m_geom_inputPrimitives;
	GLint m_geom_outputPrimitives;

Sylvain Thery's avatar
Sylvain Thery committed
122 123 124 125 126 127 128
	/**
	 * a set of pair VA_id / VBO_id
	 */
	std::vector<VAStr> m_va_vbo_binding;

	static std::vector<std::string> m_pathes;

Sylvain Thery's avatar
Sylvain Thery committed
129 130 131 132 133 134 135 136 137 138

	/**
	 * @brief log compile error
	 * @param handle handle of shader
	 * @param nameSrc name of shader
	 * @param src source of shader
	 * @return true if ok false if not
	 */
	bool logError(GLuint handle, const std::string& nameSrc, const char *src);

139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
	/**
	 * load vertex shader
	 * @param vertex_shader_source src text shader
	 */
	bool loadVertexShaderSourceString( const char* vertex_shader_source );

	/**
	 * load fragment shader
	 * @param fragment_shader_source src text shader
	 */
	bool loadFragmentShaderSourceString( const char* fragment_shader_source );

	/**
	 * load geometry shader
	 * @param geom_shader_source src text shader
	 */
	bool loadGeometryShaderSourceString( const char* geom_shader_source );
Pierre Kraemer's avatar
Pierre Kraemer committed
156

157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
	/**
	 * load vertex shader
	 * @param filename file name
	 */
	bool loadVertexShader( const std::string& filename );

	/**
	 * load fragment shader
	 * @param filename file name
	 */
	bool loadFragmentShader( const std::string& filename );

	/**
	 * load geometry shader
	 * @param filename file name
	 */
	bool  loadGeometryShader( const std::string& filename );

	/**
	 * Load of source file in a char buffer
	 * @param source_file file name
	 */
	char* loadSourceFile( const std::string& source_file );

	/**
	 * create the shader (attach and link shaders into program)
	 */
184
	bool create(GLint inputGeometryPrimitive = GL_TRIANGLES, GLint outputGeometryPrimitive = GL_TRIANGLES, int nb_max_vertices = -1);
185 186 187 188 189 190

	/**
	 * get log after compiling
	 * @param obj what log do you want ?
	 * @return the log
	 */
191
	char* getInfoLog( GLuint obj );
Pierre Kraemer's avatar
Pierre Kraemer committed
192 193

public:
194 195 196
	/**
	 * constructor
	 */
Pierre Kraemer's avatar
Pierre Kraemer committed
197 198
	GLSLShader();

199 200 201 202
	/**
	 * destructor
	 */
	virtual ~GLSLShader();
Pierre Kraemer's avatar
Pierre Kraemer committed
203

Sylvain Thery's avatar
Sylvain Thery committed
204 205
	static void setCurrentOGLVersion(unsigned int version);

206 207 208 209 210
	/*
	 * search file in different path
	 */
	static std::string findFile(const std::string filename);

211 212 213 214
	/**
	 * test support of shader
	 */
	static bool	areShadersSupported();
Pierre Kraemer's avatar
Pierre Kraemer committed
215

216 217 218 219 220 221 222 223 224
	/**
	 * test support of Vertex Buffer Object
	 */
	static bool	areVBOSupported();

	/**
	 * test support of geometry shader
	 */
	static bool	areGeometryShadersSupported();
Pierre Kraemer's avatar
Pierre Kraemer committed
225

226 227 228 229
	/**
	 * test support of gl3
	 */
	static bool	isGL3Supported();
Pierre Kraemer's avatar
Pierre Kraemer committed
230

231
	static bool init();
Pierre Kraemer's avatar
Pierre Kraemer committed
232

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
233
	static void registerShader(void* ptr, GLSLShader* shader);
Pierre Kraemer's avatar
Pierre Kraemer committed
234

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
235
	static void unregisterShader(void* ptr, GLSLShader* shader);
236 237 238

//	static void updateMatricesRunningShaders(const glm::mat4& projection, const glm::mat4& modelview);

239 240 241 242 243 244 245 246 247
	/**
	 * load shaders (compile and link)
	 * @param vs vertex shader source file
	 * @param fs fragment shader source file
	 */
	bool loadShaders(const std::string& vs, const std::string& fs);

	/**
	 * load shaders (compile and link)
Sylvain Thery's avatar
Sylvain Thery committed
248 249 250
	 * @param vs vertex shader source file name
	 * @param fs fragment shader source file name
	 * @param gs geometry shader source file name
251 252 253
	 * @param inputGeometryPrimitive primitives used in geometry shader as input
	 * @param outputGeometryPrimitive primitives generated in geometry shader as output
	 */
Sylvain Thery's avatar
Sylvain Thery committed
254
	bool loadShaders(const std::string& vs, const std::string& fs, const std::string& gs, GLint inputGeometryPrimitive=GL_TRIANGLES,GLint outputGeometryPrimitive=GL_TRIANGLE_STRIP, int nb_max_vertices=16);
Pierre Kraemer's avatar
Pierre Kraemer committed
255

Sylvain Thery's avatar
Sylvain Thery committed
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
	/**
	 * load shaders (compile and link)
	 * @param vs vertex shader source char* prt
	 * @param fs fragment shader source char* prt

	 * @param outputGeometryPrimitive primitives generated in geometry shader as output
	 */
	bool loadShadersFromMemory(const char* vs, const char* fs);

	/**
	 * load shaders (compile and link)
	 * @param vs vertex shader source char* prt
	 * @param fs fragment shader source char* prt
	 * @param fs geometry shader source char* prt
	 * @param inputGeometryPrimitive primitives used in geometry shader as input
	 * @param outputGeometryPrimitive primitives generated in geometry shader as output
	 */
Sylvain Thery's avatar
Sylvain Thery committed
273
	bool loadShadersFromMemory(const char* vs, const char* fs, const char* gs, GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices=16);
Sylvain Thery's avatar
Sylvain Thery committed
274

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
275 276 277
	const char* getVertexShaderSrc() { return m_vertex_shader_source; }
	const char* getFragmentShaderSrc() { return m_fragment_shader_source; }
	const char* getGeometryShaderSrc() { return m_geom_shader_source; }
278 279 280 281 282 283 284 285 286

	bool reloadVertexShaderFromMemory(const char* vs);

	bool reloadFragmentShaderFromMemory(const char* fs);

	bool reloadGeometryShaderFromMemory(const char* gs);

	bool recompile();

Sylvain Thery's avatar
Sylvain Thery committed
287 288
	bool changeNbMaxVertices(int nb_max_vertices);

289 290 291 292 293
	/**
	 * Link the shader do it just after binding the attributes
	 */
	bool link();

Pierre Kraemer's avatar
Pierre Kraemer committed
294
	inline bool		isCreated();
295

Pierre Kraemer's avatar
Pierre Kraemer committed
296 297
	bool			isBinded();

298 299 300
	virtual bool	bind() const;

	virtual void	unbind() const;
301

302 303 304
	/**
	 * restore all uniforms and vertex attributes after recompiling
	 */
305
	virtual void restoreUniformsAttribs() {CGoGNerr << "Warning restoreUniformsAttribs not implemented"<< CGoGNendl;}
Pierre Kraemer's avatar
Pierre Kraemer committed
306

307 308
	virtual void updateClippingUniforms() {CGoGNerr << "Warning updateClippingUniforms not implemented"<< CGoGNendl;}

309 310 311
	/**
	 *
	 */
Sylvain Thery's avatar
Sylvain Thery committed
312
//	GLuint 	getAttribIndex( char* attribName );
Pierre Kraemer's avatar
Pierre Kraemer committed
313
	
314 315 316
	/**
	 * get handler of program for external use og gl functions
	 */
317
	GLuint program_handler() { return *m_program_object;}
318

319 320 321
	/**
	 * check shader validity width official GLSL syntax
	 */
322 323
	bool validateProgram();

324 325 326
	/**
	 * check program link status
	 */
327 328
	bool checkProgram();

329 330 331
	/**
	 * check shader compile status
	 */
332 333
	bool checkShader(int shaderType);

Pierre Kraemer's avatar
Pierre Kraemer committed
334
public:
335 336 337 338 339 340 341
	/**
	 * set uniform shader float variable
	 * @warning practical but less efficient that storing id (get with glGetUniformLocation) and use glUniform*fvARB
	 * @param NB template size of variable to set
	 * @param name name in shader
	 * @param pointer on data to copy
	 */
342
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
343
	void setuniformf( const char* name, const float* val);
344

345 346 347 348 349 350 351
	/**
	 * set uniform shader int variable
	 * @warning practical but less efficient that storing id (get with glGetUniformLocation) and use glUniform*ivARB
	 * @param NB template size of variable to set
	 * @param name name in shader
	 * @param pointer on data to copy
	 */
352
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
353
	void setuniformi( const char* name, const int* val);
354 355 356 357 358 359 360

	/**
	 * add search path for file
	 * @param path to add
	 */
	void addPathFileSeach(const std::string& path);

Sylvain Thery's avatar
Sylvain Thery committed
361 362 363 364 365 366 367
	/**
	 * remove VBO index from binding
	 */
	void unbindVA(const std::string& name);

	/**
	 * associate an attribute name of shader with a vbo
368
	 * @return the index in vector of pair binding, negative if fail
Sylvain Thery's avatar
Sylvain Thery committed
369
	 */
370 371 372 373 374 375
	unsigned int bindVA_VBO(const std::string& name, VBO* vbo);

	/**
	 * change the vbo of id case of binding vector
	 */
	void changeVA_VBO(unsigned int id, VBO* vbo);
Sylvain Thery's avatar
Sylvain Thery committed
376 377 378 379

	/**
	 * get binding VA VBO
	 */
380
//	const std::vector<VAStr>& getVA_VBO_Bindings() { return m_va_vbo_binding; }
381

Sylvain Thery's avatar
Sylvain Thery committed
382 383 384 385 386 387
	void bindAttrib(unsigned int att, const char* name) const;

	/**
	 * update projection, modelview, ... matrices
	 */
	void updateMatrices(const glm::mat4& projection, const glm::mat4& modelview);
388

Sylvain Thery's avatar
Sylvain Thery committed
389 390 391 392 393
	/**
	 * update projection, modelview, ... matrices
	 */
	void updateMatrices(const glm::mat4& projection, const glm::mat4& modelview, const glm::mat4& PMV, const glm::mat4& normalMatrix);

394
	void updateMatrices(const Utils::GLSLShader *sh);
Sylvain Thery's avatar
Sylvain Thery committed
395

396 397 398 399
	/**
	 * bind, enable, and set all vertex attrib pointers
	 * @param stride: the stride parameter, number osf byte between two consecutive attributes
	 */
400
	void enableVertexAttribs(unsigned int stride = 0, unsigned int begin = 0) const;
401 402 403 404 405

	/**
	 * disenable all vertex attribs
	 */
	void disableVertexAttribs() const;
406

407 408 409
	/// get back OpenGL standard matrices & send to all shaders
	static void updateAllFromGLMatrices();

410 411
	/// sent current matrices to all shaders
	static void updateCurrentMatrices();
Sylvain Thery's avatar
Sylvain Thery committed
412 413 414 415 416


	static glm::mat4& currentNormalMatrix() { return s_current_matrices->m_matrices[4];}
	static glm::mat4& currentPMV() { return s_current_matrices->m_matrices[3];}

417 418 419 420 421 422 423 424 425 426 427
	/// get current transformation matrix
	static glm::mat4& currentTransfo() { return s_current_matrices->m_matrices[2];}
	/// get current modelview matrix
	static glm::mat4& currentModelView() { return s_current_matrices->m_matrices[1];}
	/// get current projection matrix
	static glm::mat4& currentProjection() { return s_current_matrices->m_matrices[0];}

	/// push transformation matrix
	static void pushTransfo() {s_current_matrices->pushTransfo();}
	/// pop transformation matrix
	static void popTransfo() {s_current_matrices->popTransfo();}
428 429
	// apply a transformation given by its matrix
	static void applyTransfo(const glm::mat4& m) { s_current_matrices->apply(m);}
430 431 432 433 434 435 436 437
};


////////// INLINE FUNCTIONS //////////


inline bool GLSLShader::isCreated()
{
438
	return ( *m_program_object != 0 );
439 440 441
}

template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
442
void GLSLShader::setuniformf( const char* name, const float* val)
443
{
444
	GLint uni = glGetUniformLocationARB(*m_program_object,name);
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
445
	if (uni >= 0)
446 447 448 449
	{
		switch(NB)
		{
		case 1:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
450
			glUniform1fvARB(uni, 1, val) ;
451 452
			break;
		case 2:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
453
			glUniform2fvARB(uni, 1, val) ;
454 455
			break;
		case 3:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
456
			glUniform3fvARB(uni, 1, val) ;
457 458
			break;
		case 4:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
459
			glUniform4fvARB(uni, 1, val) ;
460 461
			break;
		case 16:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
462
			glUniformMatrix4fv(uni, 1, false, val);
463 464 465
			break;
		}
	}
466
}
467

468
template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
469
void GLSLShader::setuniformi( const char* name, const int* val)
470
{
471
	GLint uni = glGetUniformLocationARB(*m_program_object,name);
472
	if (uni>=0)
473 474 475 476
	{
		switch(NB)
		{
		case 1:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
477
			glUniform1ivARB(uni, 1, val) ;
478 479
			break;
		case 2:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
480
			glUniform2ivARB(uni, 1, val) ;
481 482
			break;
		case 3:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
483
			glUniform3ivARB(uni, 1, val) ;
484 485
			break;
		case 4:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
486
			glUniform4ivARB(uni, 1, val) ;
487 488 489
			break;
		}
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
490 491
}

492
} //namespace Utils
Pierre Kraemer's avatar
Pierre Kraemer committed
493

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
494
} //namespace CGoGN
Pierre Kraemer's avatar
Pierre Kraemer committed
495

Sylvain Thery's avatar
Sylvain Thery committed
496
#endif