GLSLShader.h 12.6 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"
Sylvain Thery's avatar
Sylvain Thery committed
34
#include "Utils/vbo.h"
35
#include "Utils/gl_matrices.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
36

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

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

45

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

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

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

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

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

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

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

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

	static std::string DEFINES_GL3;

	static std::string* DEFINES_GL;

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

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


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

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

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

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

104 105 106
	/**
	 * handle of program
	 */
107
	CGoGNGLhandleARB m_program_object;
108

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

	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
121 122 123 124 125 126 127
	/**
	 * a set of pair VA_id / VBO_id
	 */
	std::vector<VAStr> m_va_vbo_binding;

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

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

146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
	/**
	 * 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)
	 */
Sylvain Thery's avatar
Sylvain Thery committed
173
	bool create(GLint inputGeometryPrimitive=GL_TRIANGLES,GLint outputGeometryPrimitive=GL_TRIANGLES, int nb_max_vertices=-1);
174 175 176 177 178 179 180

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

public:
183 184 185
	/**
	 * constructor
	 */
Pierre Kraemer's avatar
Pierre Kraemer committed
186 187
	GLSLShader();

188 189 190 191
	/**
	 * destructor
	 */
	virtual ~GLSLShader();
Pierre Kraemer's avatar
Pierre Kraemer committed
192

Sylvain Thery's avatar
Sylvain Thery committed
193 194
	static void setCurrentOGLVersion(unsigned int version);

195 196 197 198 199
	/*
	 * search file in different path
	 */
	static std::string findFile(const std::string filename);

200 201 202 203
	/**
	 * test support of shader
	 */
	static bool	areShadersSupported();
Pierre Kraemer's avatar
Pierre Kraemer committed
204

205 206 207 208 209 210 211 212 213
	/**
	 * test support of Vertex Buffer Object
	 */
	static bool	areVBOSupported();

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

215 216 217 218
	/**
	 * test support of gl3
	 */
	static bool	isGL3Supported();
Pierre Kraemer's avatar
Pierre Kraemer committed
219

220
	static bool init();
Pierre Kraemer's avatar
Pierre Kraemer committed
221

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

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
224
	static void unregisterShader(void* ptr, GLSLShader* shader);
225 226 227

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

228 229 230 231 232 233 234 235 236
	/**
	 * 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
237 238 239
	 * @param vs vertex shader source file name
	 * @param fs fragment shader source file name
	 * @param gs geometry shader source file name
240 241 242
	 * @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
243
	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
244

Sylvain Thery's avatar
Sylvain Thery committed
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
	/**
	 * 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
262
	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
263

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
264 265 266
	const char* getVertexShaderSrc() { return m_vertex_shader_source; }
	const char* getFragmentShaderSrc() { return m_fragment_shader_source; }
	const char* getGeometryShaderSrc() { return m_geom_shader_source; }
267 268 269 270 271 272 273 274 275

	bool reloadVertexShaderFromMemory(const char* vs);

	bool reloadFragmentShaderFromMemory(const char* fs);

	bool reloadGeometryShaderFromMemory(const char* gs);

	bool recompile();

Sylvain Thery's avatar
Sylvain Thery committed
276 277
	bool changeNbMaxVertices(int nb_max_vertices);

278 279 280 281 282
	/**
	 * Link the shader do it just after binding the attributes
	 */
	bool link();

Pierre Kraemer's avatar
Pierre Kraemer committed
283
	inline bool		isCreated();
284

Pierre Kraemer's avatar
Pierre Kraemer committed
285 286
	bool			isBinded();

287 288 289
	virtual bool	bind() const;

	virtual void	unbind() const;
290

291 292 293
	/**
	 * restore all uniforms and vertex attributes after recompiling
	 */
294
	virtual void restoreUniformsAttribs() {CGoGNerr << "Warning restoreUniformsAttribs not implemented"<< CGoGNendl;}
Pierre Kraemer's avatar
Pierre Kraemer committed
295

296 297
	virtual void updateClippingUniforms() {CGoGNerr << "Warning updateClippingUniforms not implemented"<< CGoGNendl;}

298 299 300
	/**
	 *
	 */
Sylvain Thery's avatar
Sylvain Thery committed
301
//	GLuint 	getAttribIndex( char* attribName );
Pierre Kraemer's avatar
Pierre Kraemer committed
302
	
303 304 305
	/**
	 * get handler of program for external use og gl functions
	 */
306
	GLhandleARB program_handler() { return *m_program_object;}
307

308 309 310
	/**
	 * check shader validity width official GLSL syntax
	 */
311 312
	bool validateProgram();

313 314 315
	/**
	 * check program link status
	 */
316 317
	bool checkProgram();

318 319 320
	/**
	 * check shader compile status
	 */
321 322
	bool checkShader(int shaderType);

Pierre Kraemer's avatar
Pierre Kraemer committed
323
public:
324 325 326 327 328 329 330
	/**
	 * 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
	 */
331
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
332
	void setuniformf( const char* name, const float* val);
333

334 335 336 337 338 339 340
	/**
	 * 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
	 */
341
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
342
	void setuniformi( const char* name, const int* val);
343 344 345 346 347 348 349

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

Sylvain Thery's avatar
Sylvain Thery committed
350 351 352 353 354 355 356
	/**
	 * remove VBO index from binding
	 */
	void unbindVA(const std::string& name);

	/**
	 * associate an attribute name of shader with a vbo
357
	 * @return the index in vector of pair binding, negative if fail
Sylvain Thery's avatar
Sylvain Thery committed
358
	 */
359 360 361 362 363 364
	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
365 366 367 368

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

Sylvain Thery's avatar
Sylvain Thery committed
371 372 373 374 375 376
	void bindAttrib(unsigned int att, const char* name) const;

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

Sylvain Thery's avatar
Sylvain Thery committed
378 379 380 381 382 383
	/**
	 * update projection, modelview, ... matrices
	 */
	void updateMatrices(const glm::mat4& projection, const glm::mat4& modelview, const glm::mat4& PMV, const glm::mat4& normalMatrix);


384 385 386 387
	/**
	 * bind, enable, and set all vertex attrib pointers
	 * @param stride: the stride parameter, number osf byte between two consecutive attributes
	 */
388
	void enableVertexAttribs(unsigned int stride = 0, unsigned int begin = 0) const;
389 390 391 392 393

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

395 396 397
	/// get back OpenGL standard matrices & send to all shaders
	static void updateAllFromGLMatrices();

398 399
	/// sent current matrices to all shaders
	static void updateCurrentMatrices();
Sylvain Thery's avatar
Sylvain Thery committed
400 401 402 403 404


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

405 406 407 408 409 410 411 412 413 414 415
	/// 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();}
416 417
	// apply a transformation given by its matrix
	static void applyTransfo(const glm::mat4& m) { s_current_matrices->apply(m);}
418 419 420 421 422 423 424 425
};


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


inline bool GLSLShader::isCreated()
{
426
	return ( *m_program_object != 0 );
427 428 429
}

template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
430
void GLSLShader::setuniformf( const char* name, const float* val)
431
{
432
	GLint uni = glGetUniformLocationARB(*m_program_object,name);
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
433
	if (uni >= 0)
434 435 436 437
	{
		switch(NB)
		{
		case 1:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
438
			glUniform1fvARB(uni, 1, val) ;
439 440
			break;
		case 2:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
441
			glUniform2fvARB(uni, 1, val) ;
442 443
			break;
		case 3:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
444
			glUniform3fvARB(uni, 1, val) ;
445 446
			break;
		case 4:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
447
			glUniform4fvARB(uni, 1, val) ;
448 449
			break;
		case 16:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
450
			glUniformMatrix4fv(uni, 1, false, val);
451 452 453
			break;
		}
	}
454
}
455

456
template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
457
void GLSLShader::setuniformi( const char* name, const int* val)
458
{
459
	GLint uni = glGetUniformLocationARB(*m_program_object,name);
460
	if (uni>=0)
461 462 463 464
	{
		switch(NB)
		{
		case 1:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
465
			glUniform1ivARB(uni, 1, val) ;
466 467
			break;
		case 2:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
468
			glUniform2ivARB(uni, 1, val) ;
469 470
			break;
		case 3:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
471
			glUniform3ivARB(uni, 1, val) ;
472 473
			break;
		case 4:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
474
			glUniform4ivARB(uni, 1, val) ;
475 476 477
			break;
		}
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
478 479
}

480
} //namespace Utils
Pierre Kraemer's avatar
Pierre Kraemer committed
481

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
482
} //namespace CGoGN
Pierre Kraemer's avatar
Pierre Kraemer committed
483

Sylvain Thery's avatar
Sylvain Thery committed
484
#endif