GLSLShader.h 13.1 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
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 70 71 72
	static unsigned int MAJOR_OGL_CORE;

	static unsigned int MINOR_OGL_CORE;

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

75 76 77
//	static glm::mat4* s_current_matrices;
	static Utils::GL_Matrices* s_current_matrices;

Pierre Kraemer's avatar
Pierre Kraemer committed
78
protected:
Sylvain Thery's avatar
Sylvain Thery committed
79 80 81 82 83 84
	static std::string DEFINES_GL2;

	static std::string DEFINES_GL3;

	static std::string* DEFINES_GL;

85 86
	static std::string defines_Geom(const std::string& primitivesIn, const std::string& primitivesOut, int maxVert);

Sylvain Thery's avatar
Sylvain Thery committed
87 88
	int m_nbMaxVertices;

89 90
	GLuint m_vao;

Sylvain Thery's avatar
Sylvain Thery committed
91

92 93 94
	/**
	 * handle of vertex shader
	 */
95
	CGoGNGLhandle	m_vertex_shader_object;
96 97 98 99

	/**
	 * handle of fragment shader
	 */
100
	CGoGNGLhandle	m_fragment_shader_object;
101 102 103 104

	/**
	 * handle of geometry shader
	 */
105
	CGoGNGLhandle	m_geom_shader_object;
106

Sylvain Thery's avatar
Sylvain Thery committed
107 108 109 110
	std::string m_nameVS;
	std::string m_nameFS;
	std::string m_nameGS;

111 112 113
	/**
	 * handle of program
	 */
Sylvain Thery's avatar
Sylvain Thery committed
114
	CGoGNGLint m_program_object;
115

116 117 118 119
	CGoGNGLint m_uniMat_Proj;
	CGoGNGLint m_uniMat_Model;
	CGoGNGLint m_uniMat_ModelProj;
	CGoGNGLint m_uniMat_Normal;
120 121 122 123 124 125 126 127

	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
128 129 130 131 132 133 134
	/**
	 * 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
135 136 137 138 139 140 141 142 143 144

	/**
	 * @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);

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
	/**
	 * 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
162

163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
	/**
	 * 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)
	 */
190
	bool create(GLint inputGeometryPrimitive = GL_TRIANGLES, GLint outputGeometryPrimitive = GL_TRIANGLES, int nb_max_vertices = -1);
191 192 193 194 195 196

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

199 200
	char* getInfoLogShader( GLuint obj );

Pierre Kraemer's avatar
Pierre Kraemer committed
201
public:
202 203 204
	/**
	 * constructor
	 */
Pierre Kraemer's avatar
Pierre Kraemer committed
205 206
	GLSLShader();

207 208 209 210
	/**
	 * destructor
	 */
	virtual ~GLSLShader();
Pierre Kraemer's avatar
Pierre Kraemer committed
211

Sylvain Thery's avatar
Sylvain Thery committed
212 213
	static void setCurrentOGLVersion(unsigned int version);

214 215
	static void setCurrentOGLVersion(unsigned int major,unsigned int minor);

216 217 218 219 220
	/*
	 * search file in different path
	 */
	static std::string findFile(const std::string filename);

221 222 223
	/**
	 * test support of shader
	 */
224
	static bool	areShadersSupported() { return true;} // deprecated
Pierre Kraemer's avatar
Pierre Kraemer committed
225

226 227 228 229 230 231 232 233 234
	/**
	 * test support of Vertex Buffer Object
	 */
	static bool	areVBOSupported();

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

236 237 238 239
	/**
	 * test support of gl3
	 */
	static bool	isGL3Supported();
Pierre Kraemer's avatar
Pierre Kraemer committed
240

241
	static bool init();
Pierre Kraemer's avatar
Pierre Kraemer committed
242

Pierre Kraemer's avatar
Pierre Kraemer committed
243
	static void registerShader(void* ptr, GLSLShader* shader);
Pierre Kraemer's avatar
Pierre Kraemer committed
244

Pierre Kraemer's avatar
Pierre Kraemer committed
245
	static void unregisterShader(void* ptr, GLSLShader* shader);
246 247 248

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

249 250 251 252 253 254 255 256 257
	/**
	 * 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
258 259 260
	 * @param vs vertex shader source file name
	 * @param fs fragment shader source file name
	 * @param gs geometry shader source file name
261 262 263
	 * @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
264
	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
265

Sylvain Thery's avatar
Sylvain Thery committed
266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
	/**
	 * 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
283
	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
284

Pierre Kraemer's avatar
Pierre Kraemer committed
285 286 287
	const char* getVertexShaderSrc() { return m_vertex_shader_source; }
	const char* getFragmentShaderSrc() { return m_fragment_shader_source; }
	const char* getGeometryShaderSrc() { return m_geom_shader_source; }
288 289 290 291 292 293 294 295 296

	bool reloadVertexShaderFromMemory(const char* vs);

	bool reloadFragmentShaderFromMemory(const char* fs);

	bool reloadGeometryShaderFromMemory(const char* gs);

	bool recompile();

Sylvain Thery's avatar
Sylvain Thery committed
297 298
	bool changeNbMaxVertices(int nb_max_vertices);

299 300 301 302 303
	/**
	 * Link the shader do it just after binding the attributes
	 */
	bool link();

Pierre Kraemer's avatar
Pierre Kraemer committed
304
	inline bool		isCreated();
305

Pierre Kraemer's avatar
Pierre Kraemer committed
306 307
	bool			isBinded();

308 309 310
	virtual bool	bind() const;

	virtual void	unbind() const;
311

312 313 314
	/**
	 * restore all uniforms and vertex attributes after recompiling
	 */
315
	virtual void restoreUniformsAttribs() {CGoGNerr << "Warning restoreUniformsAttribs not implemented"<< CGoGNendl;}
Pierre Kraemer's avatar
Pierre Kraemer committed
316

317 318
	virtual void updateClippingUniforms() {CGoGNerr << "Warning updateClippingUniforms not implemented"<< CGoGNendl;}

319 320 321
	/**
	 *
	 */
Sylvain Thery's avatar
Sylvain Thery committed
322
//	GLuint 	getAttribIndex( char* attribName );
Pierre Kraemer's avatar
Pierre Kraemer committed
323
	
324 325 326
	/**
	 * get handler of program for external use og gl functions
	 */
327
	GLuint program_handler() { return *m_program_object;}
328

329 330 331
	/**
	 * check shader validity width official GLSL syntax
	 */
332 333
	bool validateProgram();

334 335 336
	/**
	 * check program link status
	 */
337 338
	bool checkProgram();

339 340 341
	/**
	 * check shader compile status
	 */
342 343
	bool checkShader(int shaderType);

Pierre Kraemer's avatar
Pierre Kraemer committed
344
public:
345 346
	/**
	 * set uniform shader float variable
347
	 * @warning practical but less efficient that storing id (get with glGetUniformLocation) and use glUniform*fv
348 349 350 351
	 * @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 setuniformf( const char* name, const float* val);
354

355 356
	/**
	 * set uniform shader int variable
357
	 * @warning practical but less efficient that storing id (get with glGetUniformLocation) and use glUniform*iv
358 359 360 361
	 * @param NB template size of variable to set
	 * @param name name in shader
	 * @param pointer on data to copy
	 */
362
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
363
	void setuniformi( const char* name, const int* val);
364 365 366 367 368 369 370

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

Sylvain Thery's avatar
Sylvain Thery committed
371 372 373 374 375 376 377
	/**
	 * remove VBO index from binding
	 */
	void unbindVA(const std::string& name);

	/**
	 * associate an attribute name of shader with a vbo
378
	 * @return the index in vector of pair binding, negative if fail
Sylvain Thery's avatar
Sylvain Thery committed
379
	 */
380 381 382 383 384 385
	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
386 387 388 389

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

Sylvain Thery's avatar
Sylvain Thery committed
392 393 394 395 396 397
	void bindAttrib(unsigned int att, const char* name) const;

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

Sylvain Thery's avatar
Sylvain Thery committed
399 400 401 402 403
	/**
	 * update projection, modelview, ... matrices
	 */
	void updateMatrices(const glm::mat4& projection, const glm::mat4& modelview, const glm::mat4& PMV, const glm::mat4& normalMatrix);

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

406 407
	/**
	 * bind, enable, and set all vertex attrib pointers
408
	 * @param stride: the stride parameter, number of bytes between two consecutive attributes
409
	 */
410
	void enableVertexAttribs(unsigned int stride = 0, unsigned int begin = 0);
411 412 413 414

	/**
	 * disenable all vertex attribs
	 */
415
	void disableVertexAttribs();
416

417 418 419
	/// get back OpenGL standard matrices & send to all shaders
	static void updateAllFromGLMatrices();

420 421
	/// sent current matrices to all shaders
	static void updateCurrentMatrices();
Sylvain Thery's avatar
Sylvain Thery committed
422 423 424 425 426


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

427 428 429 430 431 432 433 434 435 436 437
	/// 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();}
438 439
	// apply a transformation given by its matrix
	static void applyTransfo(const glm::mat4& m) { s_current_matrices->apply(m);}
440 441 442 443 444 445 446 447
};


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


inline bool GLSLShader::isCreated()
{
448
	return ( *m_program_object != 0 );
449 450 451
}

template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
452
void GLSLShader::setuniformf( const char* name, const float* val)
453
{
454
	GLint uni = glGetUniformLocation(*m_program_object,name);
Pierre Kraemer's avatar
Pierre Kraemer committed
455
	if (uni >= 0)
456 457 458 459
	{
		switch(NB)
		{
		case 1:
460
			glUniform1fv(uni, 1, val) ;
461 462
			break;
		case 2:
463
			glUniform2fv(uni, 1, val) ;
464 465
			break;
		case 3:
466
			glUniform3fv(uni, 1, val) ;
467 468
			break;
		case 4:
469
			glUniform4fv(uni, 1, val) ;
470 471
			break;
		case 16:
Pierre Kraemer's avatar
Pierre Kraemer committed
472
			glUniformMatrix4fv(uni, 1, false, val);
473 474 475
			break;
		}
	}
476
}
477

478
template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
479
void GLSLShader::setuniformi( const char* name, const int* val)
480
{
481
	GLint uni = glGetUniformLocation(*m_program_object,name);
482
	if (uni>=0)
483 484 485 486
	{
		switch(NB)
		{
		case 1:
487
			glUniform1iv(uni, 1, val) ;
488 489
			break;
		case 2:
490
			glUniform2iv(uni, 1, val) ;
491 492
			break;
		case 3:
493
			glUniform3iv(uni, 1, val) ;
494 495
			break;
		case 4:
496
			glUniform4iv(uni, 1, val) ;
497 498 499
			break;
		}
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
500 501
}

502
} //namespace Utils
Pierre Kraemer's avatar
Pierre Kraemer committed
503

Pierre Kraemer's avatar
Pierre Kraemer committed
504
} //namespace CGoGN
Pierre Kraemer's avatar
Pierre Kraemer committed
505

Sylvain Thery's avatar
Sylvain Thery committed
506
#endif