GLSLShader.h 11.9 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-2011, 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.u-strasbg.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/os_spec.h"
Sylvain Thery's avatar
Sylvain Thery committed
33
#include "Utils/vbo.h"
34
#include "Utils/gl_matrices.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
35

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

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

Pierre Kraemer's avatar
Pierre Kraemer committed
44 45
namespace CGoGN
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
46

Pierre Kraemer's avatar
Pierre Kraemer committed
47 48 49
namespace Utils
{

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

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

Sylvain Thery's avatar
Sylvain Thery committed
64 65
	static unsigned int CURRENT_OGL_VERSION;

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

68 69 70
//	static glm::mat4* s_current_matrices;
	static Utils::GL_Matrices* s_current_matrices;

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

	static std::string DEFINES_GL3;

	static std::string* DEFINES_GL;

78 79
	static std::string defines_Geom(const std::string& primitivesIn, const std::string& primitivesOut, int maxVert);

80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
	/**
	 * handle of vertex shader
	 */
	GLhandleARB	m_vertex_shader_object;

	/**
	 * handle of fragment shader
	 */
	GLhandleARB	m_fragment_shader_object;

	/**
	 * handle of geometry shader
	 */
	GLhandleARB	m_geom_shader_object;

Sylvain Thery's avatar
Sylvain Thery committed
95 96 97 98
	std::string m_nameVS;
	std::string m_nameFS;
	std::string m_nameGS;

99 100 101 102 103
	/**
	 * handle of program
	 */
	GLhandleARB m_program_object;

104 105 106 107 108 109 110 111 112 113 114 115
	GLint m_uniMat_Proj;
	GLint m_uniMat_Model;
	GLint m_uniMat_ModelProj;
	GLint m_uniMat_Normal;

	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
116 117 118 119 120 121 122
	/**
	 * a set of pair VA_id / VBO_id
	 */
	std::vector<VAStr> m_va_vbo_binding;

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

123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
	/**
	 * 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
140

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
	/**
	 * 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
168
	bool create(GLint inputGeometryPrimitive=GL_TRIANGLES,GLint outputGeometryPrimitive=GL_TRIANGLES, int nb_max_vertices=16);
169 170 171 172 173 174 175

	/**
	 * 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
176 177

public:
178 179 180
	/**
	 * constructor
	 */
Pierre Kraemer's avatar
Pierre Kraemer committed
181 182
	GLSLShader();

183 184 185 186
	/**
	 * destructor
	 */
	virtual ~GLSLShader();
Pierre Kraemer's avatar
Pierre Kraemer committed
187

Sylvain Thery's avatar
Sylvain Thery committed
188 189
	static void setCurrentOGLVersion(unsigned int version);

190 191 192 193 194
	/*
	 * search file in different path
	 */
	static std::string findFile(const std::string filename);

195 196 197 198
	/**
	 * test support of shader
	 */
	static bool	areShadersSupported();
Pierre Kraemer's avatar
Pierre Kraemer committed
199

200 201 202 203 204 205 206 207 208
	/**
	 * test support of Vertex Buffer Object
	 */
	static bool	areVBOSupported();

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

210 211 212 213
	/**
	 * test support of gl3
	 */
	static bool	isGL3Supported();
Pierre Kraemer's avatar
Pierre Kraemer committed
214

215
	static bool init();
Pierre Kraemer's avatar
Pierre Kraemer committed
216

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

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
219
	static void unregisterShader(void* ptr, GLSLShader* shader);
220 221 222

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

223 224 225 226 227 228 229 230 231
	/**
	 * 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
232 233 234
	 * @param vs vertex shader source file name
	 * @param fs fragment shader source file name
	 * @param gs geometry shader source file name
235 236 237
	 * @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
238
	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
239

Sylvain Thery's avatar
Sylvain Thery committed
240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
	/**
	 * 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
257
	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
258

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
259 260 261
	const char* getVertexShaderSrc() { return m_vertex_shader_source; }
	const char* getFragmentShaderSrc() { return m_fragment_shader_source; }
	const char* getGeometryShaderSrc() { return m_geom_shader_source; }
262 263 264 265 266 267 268 269 270

	bool reloadVertexShaderFromMemory(const char* vs);

	bool reloadFragmentShaderFromMemory(const char* fs);

	bool reloadGeometryShaderFromMemory(const char* gs);

	bool recompile();

271 272 273 274 275
	/**
	 * Link the shader do it just after binding the attributes
	 */
	bool link();

Pierre Kraemer's avatar
Pierre Kraemer committed
276
	inline bool		isCreated();
277

Pierre Kraemer's avatar
Pierre Kraemer committed
278 279
	bool			isBinded();

280 281 282
	virtual bool	bind() const;

	virtual void	unbind() const;
283

284 285 286
	/**
	 * restore all uniforms and vertex attributes after recompiling
	 */
287
	virtual void restoreUniformsAttribs() {CGoGNerr << "Warning restoreUniformsAttribs not implemented"<< CGoGNendl;}
Pierre Kraemer's avatar
Pierre Kraemer committed
288

289 290 291
	virtual void updateClippingUniforms() {CGoGNerr << "Warning updateClippingUniforms not implemented"<< CGoGNendl;}


292 293 294
	/**
	 *
	 */
Sylvain Thery's avatar
Sylvain Thery committed
295
//	GLuint 	getAttribIndex( char* attribName );
Pierre Kraemer's avatar
Pierre Kraemer committed
296
	
297 298 299 300 301
	/**
	 * get handler of program for external use og gl functions
	 */
	GLuint program_handler() { return m_program_object;}

302 303 304
	/**
	 * check shader validity width official GLSL syntax
	 */
305 306
	bool validateProgram();

307 308 309
	/**
	 * check program link status
	 */
310 311
	bool checkProgram();

312 313 314
	/**
	 * check shader compile status
	 */
315 316
	bool checkShader(int shaderType);

Pierre Kraemer's avatar
Pierre Kraemer committed
317
public:
318 319 320 321 322 323 324
	/**
	 * 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
	 */
325
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
326
	void setuniformf( const char* name, const float* val);
327

328 329 330 331 332 333 334
	/**
	 * 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
	 */
335
	template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
336
	void setuniformi( const char* name, const int* val);
337 338 339 340 341 342 343

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

Sylvain Thery's avatar
Sylvain Thery committed
344 345 346 347 348 349 350 351

	/**
	 * remove VBO index from binding
	 */
	void unbindVA(const std::string& name);

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

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

Sylvain Thery's avatar
Sylvain Thery committed
366 367 368 369 370 371
	void bindAttrib(unsigned int att, const char* name) const;

	/**
	 * update projection, modelview, ... matrices
	 */
	void updateMatrices(const glm::mat4& projection, const glm::mat4& modelview);
372 373 374 375 376

	/**
	 * bind, enable, and set all vertex attrib pointers
	 * @param stride: the stride parameter, number osf byte between two consecutive attributes
	 */
377
	void enableVertexAttribs(unsigned int stride=0, unsigned int begin=0) const;
378 379 380 381 382

	/**
	 * disenable all vertex attribs
	 */
	void disableVertexAttribs() const;
383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398

	/// sent current matrices to all shaders
	static void updateCurrentMatrices();
	/// 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();}


399 400 401 402 403 404 405 406 407 408 409 410
};


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


inline bool GLSLShader::isCreated()
{
	return ( m_program_object != 0 );
}

template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
411
void GLSLShader::setuniformf( const char* name, const float* val)
412 413
{
	GLint uni = glGetUniformLocationARB(m_program_object,name);
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
414
	if (uni >= 0)
415 416 417 418
	{
		switch(NB)
		{
		case 1:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
419
			glUniform1fvARB(uni, 1, val) ;
420 421
			break;
		case 2:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
422
			glUniform2fvARB(uni, 1, val) ;
423 424
			break;
		case 3:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
425
			glUniform3fvARB(uni, 1, val) ;
426 427
			break;
		case 4:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
428
			glUniform4fvARB(uni, 1, val) ;
429 430
			break;
		case 16:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
431
			glUniformMatrix4fv(uni, 1, false, val);
432 433 434
			break;
		}
	}
435
}
436

437
template<unsigned int NB>
Sylvain Thery's avatar
Sylvain Thery committed
438
void GLSLShader::setuniformi( const char* name, const int* val)
439 440 441
{
	GLint uni = glGetUniformLocationARB(m_program_object,name);
	if (uni>=0)
442 443 444 445
	{
		switch(NB)
		{
		case 1:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
446
			glUniform1ivARB(uni, 1, val) ;
447 448
			break;
		case 2:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
449
			glUniform2ivARB(uni, 1, val) ;
450 451
			break;
		case 3:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
452
			glUniform3ivARB(uni, 1, val) ;
453 454
			break;
		case 4:
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
455
			glUniform4ivARB(uni, 1, val) ;
456 457 458
			break;
		}
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
459 460
}

461
} //namespace Utils
Pierre Kraemer's avatar
Pierre Kraemer committed
462

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
463
} //namespace CGoGN
Pierre Kraemer's avatar
Pierre Kraemer committed
464

Sylvain Thery's avatar
Sylvain Thery committed
465
#endif