Coupure prévue mardi 3 Août au matin pour maintenance du serveur. Nous faisons au mieux pour que celle-ci soit la plus brève possible.

GLSLShader.cpp 32.8 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
* Contact information: cgogn@unistra.fr                                        *
*                                                                              *
*******************************************************************************/
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
24

Sylvain Thery's avatar
Sylvain Thery committed
25
#define CGoGN_UTILS_DLL_EXPORT 1
Pierre Kraemer's avatar
Pierre Kraemer committed
26
27
28
29

#include "Utils/GLSLShader.h"
#include <iostream>
#include <fstream>
30
#include <vector>
Sylvain Thery's avatar
Sylvain Thery committed
31
#include <algorithm>
32
#include "Utils/cgognStream.h"
Pierre Kraemer's avatar
Pierre Kraemer committed
33

Sylvain Thery's avatar
Sylvain Thery committed
34
#include "glm/gtc/matrix_inverse.hpp"
Sylvain Thery's avatar
Sylvain Thery committed
35

Pierre Kraemer's avatar
Pierre Kraemer committed
36
37
38
39
40
namespace CGoGN
{

namespace Utils
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
41

42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//#ifdef CGOGN_USE_OGL_CORE_PROFILE
//unsigned int GLSLShader::CURRENT_OGL_VERSION = 3;
//unsigned int GLSLShader::MAJOR_OGL_CORE = 3;
//unsigned int GLSLShader::MINOR_OGL_CORE = 3;
//#else
//unsigned int GLSLShader::CURRENT_OGL_VERSION = 2;
//unsigned int GLSLShader::MAJOR_OGL_CORE = 2;
//unsigned int GLSLShader::MINOR_OGL_CORE = 1;
//#endif



//std::string GLSLShader::DEFINES_GL2=\
//"#version 110\n"
//"#define PRECISION float pipo_PRECISION\n"
//"#define ATTRIBUTE attribute\n"
//"#define VARYING_VERT varying\n"
//"#define VARYING_FRAG varying\n"
//"#define FRAG_OUT_DEF float pipo_FRAGDEF\n"
//"#define FRAG_OUT gl_FragColor\n"
//"#define INVARIANT_POS float pipo_INVARIANT\n"
//"#define TEXTURE2D texture2D\n";


//std::string GLSLShader::DEFINES_GL3=\
//"#version 150\n"
//"#define PRECISION precision highp float\n"
//"#define ATTRIBUTE in\n"
//"#define VARYING_VERT out\n"
//"#define VARYING_FRAG in\n"
//"#define FRAG_OUT_DEF out vec4 outFragColor\n"
//"#define FRAG_OUT outFragColor\n"
//"#define INVARIANT_POS invariant gl_Position\n"
//"#define TEXTURE2D texture\n";


//std::string* GLSLShader::DEFINES_GL = NULL;
79
80
81

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

82
std::set< std::pair<void*, GLSLShader*> >* GLSLShader::m_registeredShaders = NULL;
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
83

84
85
86
//glm::mat4* GLSLShader::s_current_matrices=NULL;
Utils::GL_Matrices* GLSLShader::s_current_matrices=NULL;

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
87
GLSLShader::GLSLShader() :
88
	m_vao(0),
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
89
90
91
	m_vertex_shader_source(NULL),
	m_fragment_shader_source(NULL),
	m_geom_shader_source(NULL)
Pierre Kraemer's avatar
Pierre Kraemer committed
92
{
93
94
95
96
97
98
99
100
101
	*m_vertex_shader_object = 0;
	*m_fragment_shader_object = 0;
	*m_geom_shader_object = 0;
	*m_program_object = 0;
	*m_uniMat_Proj = -1;
	*m_uniMat_Model = -1;
	*m_uniMat_ModelProj = -1;
	*m_uniMat_Normal = -1;

102
103
//	if (DEFINES_GL == NULL)
//		setCurrentOGLVersion(MAJOR_OGL_CORE,MINOR_OGL_CORE);
Sylvain Thery's avatar
Sylvain Thery committed
104
105

	m_nbMaxVertices = 16;
106
107
108

	if (m_registeredShaders==NULL)
		m_registeredShaders = new std::set< std::pair<void*, GLSLShader*> >;
Pierre Kraemer's avatar
Pierre Kraemer committed
109
110
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
111
void GLSLShader::registerShader(void* ptr, GLSLShader* shader)
112
{
113
	m_registeredShaders->insert(std::pair<void*,GLSLShader*>(ptr, shader));
114
115
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
116
void GLSLShader::unregisterShader(void* ptr, GLSLShader* shader)
117
{
118
	m_registeredShaders->erase(std::pair<void*,GLSLShader*>(ptr, shader));
119
120
}

121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
std::string GLSLShader::defines_gl()
{
#ifdef CGOGN_USE_OGL_CORE_PROFILE
	return std::string("#version 330\n\
#define PRECISION precision highp float\n\
#define ATTRIBUTE in\n\
#define VARYING_VERT out\n\
#define VARYING_FRAG in\n\
#define FRAG_OUT_DEF out vec4 outFragColor\n\
#define FRAG_OUT outFragColor\n\
#define INVARIANT_POS invariant gl_Position\n\
#define TEXTURE2D texture\n");
#else
	return std::string("#version 110\n \
#define PRECISION float pipo_PRECISION\n\
#define ATTRIBUTE attribute\n\
#define VARYING_VERT varying\n\
#define VARYING_FRAG varying\n\
#define FRAG_OUT_DEF float pipo_FRAGDEF\n\
#define FRAG_OUT gl_FragColor\n\
#define INVARIANT_POS float pipo_INVARIANT\n\
#define TEXTURE2D texture2D\n");
#endif
}

146
147
std::string GLSLShader::defines_Geom(const std::string& primitivesIn, const std::string& primitivesOut, int maxVert)
{
148
	if (CURRENT_OGL_VERSION >= 3)
149
	{
150
		std::string str("#version 330\n");
151
152
153
154
155
156
157
158
159
160
161
162
		str.append("precision highp float;\n");
		str.append("layout (");
		str.append(primitivesIn);
		str.append(") in;\n");

		str.append("layout (");
		str.append(primitivesOut);
		str.append(", max_vertices = ");
		std::stringstream ss;
		ss << maxVert;
		str.append(ss.str());
		str.append(") out;\n");
sylvain thery's avatar
sylvain thery committed
163
164
		str.append("#define VARYING_IN in\n");
		str.append("#define VARYING_OUT out\n");
165
		str.append("#define POSITION_IN(X) gl_in[X].gl_Position\n");
166
		str.append("#define NBVERTS_IN gl_in.length()\n");
167
168
169
170
		return str;
	}
	else
	{
Sylvain Thery's avatar
Sylvain Thery committed
171
172
		std::string str("#version 110\n");
		str.append("#extension GL_EXT_geometry_shader4 : enable\n");
kvanhoey's avatar
kvanhoey committed
173
		str.append("#define PRECISION float pipo_PRECISION\n");
174
175
176
177
		str.append("#define ATTRIBUTE attribute\n");
		str.append("#define VARYING_IN varying in\n");
		str.append("#define VARYING_OUT varying out\n");
		str.append("#define POSITION_IN(X) gl_PositionIn[X]\n");
178
		str.append("#define NBVERTS_IN gl_VerticesIn\n");
179
180
181
182
		return str;
	}
}

Pierre Kraemer's avatar
Pierre Kraemer committed
183
184
bool GLSLShader::areGeometryShadersSupported()
{
185
	if (!glewGetExtension("GL_ARB_geometry_shader4"))
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
186
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
187
188
189
190
191
192
	return true;
}


bool GLSLShader::areVBOSupported()
{
193
	if (!glewGetExtension("GL_vertex_buffer_object"))
Pierre Kraemer's avatar
Pierre Kraemer committed
194
195
196
197
		return false;
	return true;
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
198
char* GLSLShader::loadSourceFile(const std::string& filename)
Pierre Kraemer's avatar
Pierre Kraemer committed
199
200
201
202
203
204
205
206
207
208
{
	std::ifstream	file;
	int				file_size;
	char*			shader_source;

	/*** opening file ***/
	file.open( filename.c_str() , std::ios::in | std::ios::binary );

	if( !file.good() )
	{
209
		CGoGNerr << "ERROR - GLSLShader::loadSourceFile() - unable to open the file " << filename << "." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
210
211
212
213
214
215
216
217
		return NULL;
	}

	/*** reading file ***/
	try
	{
		/* get file size */
		file.seekg( 0, std::ios::end );
218
		file_size = int(file.tellg());
Pierre Kraemer's avatar
Pierre Kraemer committed
219
220
221
222
223
224
225
226
227
228
229
		file.seekg( 0, std::ios::beg );

		/* allocate shader source table */
		shader_source = new char [ file_size+1 ];

		/* read source file */
		file.read( shader_source, file_size );
		shader_source[ file_size ] = '\0';
	}
	catch( std::exception& io_exception )
	{
230
		CGoGNerr << "ERROR - GLSLShader::loadSourceFile() - " << io_exception.what() << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
231
232
233
234
235
236
237
238
239
240
241
242
		file.close();
		return NULL;
	}

	/*** termination ***/
	file.close();
	return shader_source;
}

bool GLSLShader::loadVertexShader(  const std::string& filename )
{
	bool	flag;
243
//	char	*vertex_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
244

245
246
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
247
	m_vertex_shader_source = NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
248

249
	m_vertex_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
250

251
	if( !m_vertex_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
252
	{
253
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
254
255
256
		return false;
	}

257
258
	flag = loadVertexShaderSourceString( m_vertex_shader_source );
//	delete [] vertex_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
259
260
261
262

	return flag;
}

263
bool GLSLShader::loadFragmentShader(const std::string& filename )
Pierre Kraemer's avatar
Pierre Kraemer committed
264
265
{
	bool	flag;
266
//	char	*fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
267

268
269
	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;
270
	m_fragment_shader_source = NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
271

272
	m_fragment_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
273

274
	if( !m_fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
275
	{
276
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
277
278
279
		return false;
	}

280
281
	flag = loadFragmentShaderSourceString( m_fragment_shader_source );
//	delete [] fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
282
283
284
285
286
287
288

	return flag;
}

bool GLSLShader::loadGeometryShader(const std::string& filename )
{
	bool	flag;
289
//	char	*geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
290

291
292
	if (m_geom_shader_source)
		delete [] m_geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
293

294
	m_geom_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
295

296
	if( !m_geom_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
297
	{
298
		CGoGNerr << "ERROR - GLSLShader::loadGeometryShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
299
300
301
		return false;
	}

302
303
	flag = loadGeometryShaderSourceString( m_geom_shader_source );
//	delete [] geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
304
305
306
307

	return flag;
}

Sylvain Thery's avatar
Sylvain Thery committed
308
bool GLSLShader::logError(GLuint handle, const std::string& nameSrc, const char *src)
Pierre Kraemer's avatar
Pierre Kraemer committed
309
{
Sylvain Thery's avatar
Sylvain Thery committed
310
	char *info_log;
311
	info_log = getInfoLogShader( handle );
Sylvain Thery's avatar
Sylvain Thery committed
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
	if (info_log!=NULL)
	{
		CGoGNerr << "============================================================================" << CGoGNendl;
		CGoGNerr << "Error in " << nameSrc << CGoGNendl;
		CGoGNerr << "----------------------------------------------------------------------------" << CGoGNendl;
		char line[256];
		int ln=1;
		std::stringstream ss(src);
		do
		{
			ss.getline(line,256);
			std::cout << ln++ << ": "<< line<< std::endl;
		}while (!ss.eof());
		CGoGNerr << "----------------------------------------------------------------------------" << CGoGNendl;
		CGoGNerr << info_log;
		CGoGNerr << "============================================================================" << CGoGNendl;
		delete [] info_log;
		return false;
	}
	return true;
}
Pierre Kraemer's avatar
Pierre Kraemer committed
333

Sylvain Thery's avatar
Sylvain Thery committed
334
335
bool GLSLShader::loadVertexShaderSourceString( const char *vertex_shader_source )
{
336
	if (*m_vertex_shader_object!=0)
Sylvain Thery's avatar
Sylvain Thery committed
337
	{
338
339
		glDeleteShader(*m_vertex_shader_object);
		*m_vertex_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
340
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
341
342

	/*** create shader object ***/
343
	*m_vertex_shader_object = glCreateShader( GL_VERTEX_SHADER );
Pierre Kraemer's avatar
Pierre Kraemer committed
344

345
	if( !*m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
346
	{
347
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
348
349
350
351
352
353
		return false;
	}

	/*** load source file ***/
	if( !vertex_shader_source )
	{
354
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - source string is empty." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
355

356
		glDeleteShader(*m_vertex_shader_object );
357
		*m_vertex_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
358
359
360
361

		return false;
	}

362
	glShaderSource( *m_vertex_shader_object, 1, (const char**)&vertex_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
363
364

	/*** compile shader object ***/
365
	glCompileShader( *m_vertex_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
366

Sylvain Thery's avatar
Sylvain Thery committed
367
	if (!logError(*m_vertex_shader_object, m_nameVS, vertex_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
368
	{
369
		glDeleteShader( *m_vertex_shader_object );
370
		*m_vertex_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
371
372
373
374
375
376
377
		return false;
	}

	/*** termination ***/
	return true;
}

378
bool GLSLShader::loadFragmentShaderSourceString( const char *fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
379
{
380
	if (*m_fragment_shader_object!=0)
Sylvain Thery's avatar
Sylvain Thery committed
381
	{
382
383
		glDeleteShader(*m_fragment_shader_object);
		*m_fragment_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
384
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
385
386

	/*** create shader object ***/
387
	*m_fragment_shader_object = glCreateShader( GL_FRAGMENT_SHADER );
Pierre Kraemer's avatar
Pierre Kraemer committed
388

389
	if( !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
390
	{
391
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
392
393
394
395
		return false;
	}

	/*** load source file ***/
396
	if( !fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
397
	{
398
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - source string is empty." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
399

400
		glDeleteShader( *m_fragment_shader_object );
401
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
402
403
404
405

		return false;
	}

406
	glShaderSource( *m_fragment_shader_object, 1, (const char**)&fragment_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
407
408

	/*** compile shader object ***/
409
	glCompileShader( *m_fragment_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
410

Sylvain Thery's avatar
Sylvain Thery committed
411
	if (!logError(*m_fragment_shader_object, m_nameFS, fragment_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
412
	{
413
		glDeleteShader( *m_fragment_shader_object );
414
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
415
416
417
418
419
420
421
422
423
		return false;
	}

	/*** termination ***/
	return true;
}

bool GLSLShader::loadGeometryShaderSourceString( const char *geom_shader_source )
{
424
	if (*m_geom_shader_object!=0)
Sylvain Thery's avatar
Sylvain Thery committed
425
	{
426
427
		glDeleteShader(*m_geom_shader_object);
		*m_geom_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
428
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
429
	/*** create shader object ***/
Sylvain Thery's avatar
Sylvain Thery committed
430
	*m_geom_shader_object = glCreateShader(GL_GEOMETRY_SHADER);
Pierre Kraemer's avatar
Pierre Kraemer committed
431

432
	if( !*m_geom_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
433
	{
434
		CGoGNerr << "ERROR - GLSLShader::loadGeometryShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
435
436
437
438
439
440
		return false;
	}

	/*** load source file ***/
	if( !geom_shader_source )
	{
441
		CGoGNerr << "ERROR - GLSLShader::loadGeometryShader() - source string is empty." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
442

443
		glDeleteShader( *m_geom_shader_object );
444
		*m_geom_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
445
446
447
448

		return false;
	}

449
	glShaderSource( *m_geom_shader_object, 1, (const char**)&geom_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
450
451

	/*** compile shader object ***/
452
	glCompileShader( *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
453

Sylvain Thery's avatar
Sylvain Thery committed
454
	if (!logError(*m_geom_shader_object, m_nameGS, geom_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
455
	{
456
		glDeleteShader( *m_geom_shader_object );
457
		*m_geom_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
458
459
460
461
462
463
464
		return false;
	}

	/*** termination ***/
	return true;
}

465
char* GLSLShader::getInfoLog( GLuint obj )
Pierre Kraemer's avatar
Pierre Kraemer committed
466
{
467
468
469
	char* info_log;
	int info_log_length;
	int length;
Pierre Kraemer's avatar
Pierre Kraemer committed
470

471
	glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &info_log_length);
Sylvain Thery's avatar
Sylvain Thery committed
472
473
474

	if (info_log_length <= 1)
		return NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
475
476

	info_log = new char [info_log_length];
477
	glGetProgramInfoLog( obj, info_log_length, &length, info_log );
Pierre Kraemer's avatar
Pierre Kraemer committed
478
479
480
481

	return info_log;
}

482
483
char* GLSLShader::getInfoLogShader( GLuint obj )
{
484
485
486
	char* info_log;
	int	info_log_length;
	int	length;
487
488
489
490
491
492
493
494
495
496
497
498

    glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &info_log_length);

    if (info_log_length <= 1)
        return NULL;

    info_log = new char [info_log_length+1];
    glGetShaderInfoLog( obj, info_log_length, &length, info_log );
    info_log[info_log_length]=0;
    return info_log;
}

Sylvain Thery's avatar
Sylvain Thery committed
499
bool GLSLShader::create(GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
500
{
501
502
	int	status;
	char* info_log;
Pierre Kraemer's avatar
Pierre Kraemer committed
503

504
	if (nb_max_vertices != -1)
Sylvain Thery's avatar
Sylvain Thery committed
505
506
		m_nbMaxVertices = nb_max_vertices;

507
508
	m_geom_inputPrimitives = inputGeometryPrimitive;
	m_geom_outputPrimitives = outputGeometryPrimitive;
Pierre Kraemer's avatar
Pierre Kraemer committed
509
510

	/*** check if shaders are loaded ***/
511
	if( !*m_vertex_shader_object || !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
512
	{
513
		CGoGNerr << "ERROR - GLSLShader::create() - shaders are not defined." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
514
515
516
517
		return false;
	}

	/*** create program object ***/
518
	m_program_object = glCreateProgram();
Pierre Kraemer's avatar
Pierre Kraemer committed
519

520
	if( !*m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
521
	{
522
		CGoGNerr << "ERROR - GLSLShader::create() - unable to create program object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
523
524
525
526
		return false;
	}

	/*** attach shaders to program object ***/
527
528
	glAttachShader( *m_program_object, *m_vertex_shader_object );
	glAttachShader( *m_program_object, *m_fragment_shader_object );
529
	if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
530
	{
531
		glAttachShader( *m_program_object, *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
532

533
534
535
536
537
538
		if (CURRENT_OGL_VERSION == 2)
		{
			glProgramParameteriEXT(*m_program_object, GL_GEOMETRY_INPUT_TYPE_EXT, inputGeometryPrimitive);
			glProgramParameteriEXT(*m_program_object, GL_GEOMETRY_OUTPUT_TYPE_EXT, outputGeometryPrimitive);
			glProgramParameteriEXT(*m_program_object, GL_GEOMETRY_VERTICES_OUT_EXT, m_nbMaxVertices);
		}
Pierre Kraemer's avatar
Pierre Kraemer committed
539
540
541
	}

	/*** link program object ***/
542
	glLinkProgram( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
543

544
	glGetProgramiv( *m_program_object, GL_LINK_STATUS, &status );
Pierre Kraemer's avatar
Pierre Kraemer committed
545
546
	if( !status )
	{
547
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
548
		info_log = getInfoLog( *m_program_object );
549
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
550
551
		delete [] info_log;

552
553
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
554
		if (*m_geom_shader_object)
555
556
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
557
		*m_program_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
558
559
560
561

		return false;
	}

562
563
564
565
	*m_uniMat_Proj		= glGetUniformLocation(*m_program_object, "ProjectionMatrix");
	*m_uniMat_Model		= glGetUniformLocation(*m_program_object, "ModelViewMatrix");
	*m_uniMat_ModelProj	= glGetUniformLocation(*m_program_object, "ModelViewProjectionMatrix");
	*m_uniMat_Normal	= glGetUniformLocation(*m_program_object, "NormalMatrix");
566

Pierre Kraemer's avatar
Pierre Kraemer committed
567
568
569
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
570
571
572
bool GLSLShader::changeNbMaxVertices(int nb_max_vertices)
{
	m_nbMaxVertices = nb_max_vertices;
573
	if ((*m_geom_shader_object) && (CURRENT_OGL_VERSION == 2))
Sylvain Thery's avatar
Sylvain Thery committed
574
	{
575
		glProgramParameteriEXT(*m_program_object, GL_GEOMETRY_VERTICES_OUT_EXT, m_nbMaxVertices);
Sylvain Thery's avatar
Sylvain Thery committed
576
577
578
579
580
581
		// need to relink
		return true;
	}
	return false;
}

582
583
584
585
586
587
bool GLSLShader::link()
{
	int		status;
	char	*info_log;

	/*** link program object ***/
588
	glLinkProgram( *m_program_object );
589

590
	glGetProgramiv( *m_program_object, GL_OBJECT_LINK_STATUS_ARB, &status );
591
592
	if( !status )
	{
593
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
594
		info_log = getInfoLog( *m_program_object );
595
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
596
597
		delete [] info_log;

598
599
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
600
		if (*m_geom_shader_object)
601
602
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
603
		*m_program_object = 0;
604
605
606
607
608
609

		return false;
	}
	return true;
}

610
bool GLSLShader::bind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
611
{
612
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
613
	{
614
		glUseProgram( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
615
616
		return true;
	}
617
618
	else
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
619
620
}

621
void GLSLShader::unbind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
622
{
623
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
624
	{
625
		glUseProgram( 0 );
Pierre Kraemer's avatar
Pierre Kraemer committed
626
627
628
629
630
	}
}

bool GLSLShader::isBinded()
{
631
632
633
634
635
636
	if (*m_program_object == 0)
		return false;

	GLint po;
	glGetIntegerv(GL_CURRENT_PROGRAM,&po);
	return ( *m_program_object == po );
Pierre Kraemer's avatar
Pierre Kraemer committed
637
638
639
640
}

GLSLShader::~GLSLShader()
{
641
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
642
643
644
	{
		unbind();

645
		if( *m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
646
		{
647
648
			glDetachShader( *m_program_object, *m_vertex_shader_object );
			glDeleteShader( *m_vertex_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
649
		}
650
		if( *m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
651
		{
652
653
			glDetachShader( *m_program_object, *m_fragment_shader_object );
			glDeleteShader( *m_fragment_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
654
		}
655
		if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
656
		{
657
658
			glDetachShader( *m_program_object, *m_geom_shader_object );
			glDeleteShader( *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
659
660
		}

661
		glDeleteShader( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
662
	}
663

664
665
666
667
668
669
670
	if (m_vertex_shader_source != NULL)
		delete[] m_vertex_shader_source;
	if (m_fragment_shader_source != NULL)
		delete[] m_fragment_shader_source;
	if (m_geom_shader_source != NULL)
		delete[] m_geom_shader_source;

671
//	m_registeredShaders->erase(this);
Pierre Kraemer's avatar
Pierre Kraemer committed
672
673
674
675
}

std::string GLSLShader::findFile(const std::string filename)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
676
	// cherche d'abord dans le repertoire courant
Pierre Kraemer's avatar
Pierre Kraemer committed
677
678
679
680
681
682
683
684
685
	std::ifstream file;
	file.open(filename.c_str(),std::ios::in );
	if (!file.fail())
	{
		file.close();
		return filename;
	}
	file.close();

686
687
688
689
690
691
692
693
694
695
696
697
698
699
	for (std::vector<std::string>::const_iterator ipath = m_pathes.begin(); ipath != m_pathes.end(); ++ipath)
	{
		std::string st(*ipath);
		st.append(filename);

		std::ifstream file2;
		file2.open(st.c_str(),std::ios::in);
		if (!file2.fail())
		{
			file2.close();
			return st;
		}
	}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
700
	// LA MACRO SHADERPATH contient le chemin du repertoire qui contient les fichiers textes
Pierre Kraemer's avatar
Pierre Kraemer committed
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
	std::string st(SHADERPATH);
	st.append(filename);

	std::ifstream file2; // on ne peut pas réutiliser file ????
	file2.open(st.c_str(),std::ios::in);
	if (!file2.fail())
	{
		file2.close();
		return st;
	}

	return filename;
}

bool GLSLShader::init()
{
717
#ifndef CGOGN_GLEW_MX
Pierre Kraemer's avatar
Pierre Kraemer committed
718
719
720
	GLenum error = glewInit();

	if (error != GLEW_OK)
721
		CGoGNerr << "Error: " << glewGetErrorString(error) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
722
	else
723
		CGoGNout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
724
725

	if (!areVBOSupported())
726
		CGoGNerr << "VBO not supported !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
727

728
729
730
	if  ((CURRENT_OGL_VERSION == 2) && (!glewIsSupported("GL_VERSION_2_0")))
	{
		CGoGNerr << " GL 2.0 not supported" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
731
732
		return false;
	}
733
734
735
736
737
738
739

	if ((CURRENT_OGL_VERSION == 3) && (!glewIsSupported("GL_VERSION_3_3")))
	{
		CGoGNerr << " GL 3.3 not supported" << CGoGNendl;
		return false;
	}

740
741
742
#endif
	return true;

Pierre Kraemer's avatar
Pierre Kraemer committed
743
744
745
746
}

bool GLSLShader::loadShaders(const std::string& vs, const std::string& ps)
{
Sylvain Thery's avatar
Sylvain Thery committed
747
748
	m_nameVS = vs;
	m_nameFS = ps;
749

Pierre Kraemer's avatar
Pierre Kraemer committed
750
751
752
753
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;
	
	std::string pss = findFile(ps);
754
	if(!loadFragmentShader(pss)) return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
755
756

	if(!create()) {
757
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
758
759
		return false;
	}
760
	CGoGNout << "Shaders loaded (" << vs << "," << ps << ")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
761
762
763
	return true; 
}

Sylvain Thery's avatar
Sylvain Thery committed
764
bool GLSLShader::loadShaders(const std::string& vs, const std::string& ps, const std::string& gs, GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
765
{
Sylvain Thery's avatar
Sylvain Thery committed
766
767
768
769
	m_nameVS = vs;
	m_nameFS = ps;
	m_nameGS = gs;

Pierre Kraemer's avatar
Pierre Kraemer committed
770
771
772
773
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;

	std::string pss = findFile(ps);
774
	if(!loadFragmentShader(pss)) return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
775
776
777
778
779
780

	std::string gss = findFile(gs);
	bool geomShaderLoaded = loadGeometryShader(gss);

	if (!geomShaderLoaded)
	{
781
		CGoGNerr << "Error while loading geometry shader" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
782
783
	}

Sylvain Thery's avatar
Sylvain Thery committed
784
	if(!create(inputGeometryPrimitive,outputGeometryPrimitive,nb_max_vertices))
Pierre Kraemer's avatar
Pierre Kraemer committed
785
	{
786
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
787
788
789
		return false;
	}

790
	CGoGNout << "Shaders loaded (" << vs << "," << ps << "," << gs <<")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
791
792
793
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
794
795
bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs)
{
796
797
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
798
	m_vertex_shader_source = NULL;
799

800
	size_t sz = strlen(vs);
801
	m_vertex_shader_source = new char[sz+1];
802
803
804
	memcpy(m_vertex_shader_source, vs,sz+1);
	

805
806
807
808
809
810

	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

	sz = strlen(fs);
	m_fragment_shader_source = new char[sz+1];
811
	memcpy(m_fragment_shader_source, fs,sz+1);
812

813
814
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
815

816
817
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
818
819
820

	if(!create())
	{
821
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
822
823
824
825
826
		return false;
	}
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
827
bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs, const char* gs, GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices)
Sylvain Thery's avatar
Sylvain Thery committed
828
{
829
830
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
831
	m_vertex_shader_source = NULL;
832

833
	size_t sz = strlen(vs);
834
	m_vertex_shader_source = new char[sz+1];
835
	memcpy(m_vertex_shader_source,vs,sz+1);
836
837
838
839
840
841

	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

	sz = strlen(fs);
	m_fragment_shader_source = new char[sz+1];
842
	memcpy(m_fragment_shader_source,fs,sz+1);
843
844
845
846
847
848

	if (m_geom_shader_source)
		delete [] m_geom_shader_source;

	sz = strlen(gs);
	m_geom_shader_source = new char[sz+1];
849
	memcpy(m_geom_shader_source,gs,sz+1);
850

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
851
852
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
853

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
854
855
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
856

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
857
858
	if(!loadGeometryShaderSourceString(gs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
859

860
	if(!create(inputGeometryPrimitive, outputGeometryPrimitive, nb_max_vertices))
Sylvain Thery's avatar
Sylvain Thery committed
861
	{
862
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
863
864
865
866
867
868
		return false;
	}

	return true;
}

869
870
871
872
bool GLSLShader::reloadVertexShaderFromMemory(const char* vs)
{
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
873
	m_vertex_shader_source = NULL;
874

875
	size_t sz = strlen(vs);
876
	m_vertex_shader_source = new char[sz+1];
877
	memcpy(m_vertex_shader_source,vs,sz+1);
878
879
880
881
882
883
884
885
886

	return true;
}

bool GLSLShader::reloadFragmentShaderFromMemory(const char* fs)
{
	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

887
	unsigned int sz = uint32(strlen(fs));
888
	m_fragment_shader_source = new char[sz+1];
889
	memcpy(m_fragment_shader_source,fs,sz+1);
890
891
892
893
894
895
896
897
898

	return true;
}

bool GLSLShader::reloadGeometryShaderFromMemory(const char* gs)
{
	if (m_geom_shader_source)
		delete [] m_geom_shader_source;

899
	unsigned int sz = uint32(strlen(gs));
900
	m_geom_shader_source = new char[sz+1];
901
	memcpy(m_geom_shader_source,gs,sz+1);
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916

	return true;
}

bool GLSLShader::recompile()
{
	if (m_vertex_shader_source)
		if(!loadVertexShaderSourceString(m_vertex_shader_source)) return false;
	if (m_fragment_shader_source)
		if(!loadFragmentShaderSourceString(m_fragment_shader_source)) return false;
	if (m_geom_shader_source)
		if(!loadGeometryShaderSourceString(m_geom_shader_source)) return false;

	if(!create(m_geom_inputPrimitives,m_geom_outputPrimitives))
	{
917
		CGoGNerr << "Unable to create the shaders !" << CGoGNendl;
918
919
920
		return false;
	}

921
922
923
	*m_uniMat_Proj		= glGetUniformLocation(*m_program_object,"ProjectionMatrix");
	*m_uniMat_Model		= glGetUniformLocation(*m_program_object,"ModelViewMatrix");
	*m_uniMat_ModelProj	= glGetUniformLocation(*m_program_object,"ModelViewProjectionMatrix");
Sylvain Thery's avatar
Sylvain Thery committed
924
	*m_uniMat_Normal	= glGetUniformLocation(*m_program_object,"NormalMatrix");
925
926
927

	restoreUniformsAttribs();

928
929
	updateClippingUniforms();

930
931
932
	return true;
}

933
934
bool GLSLShader::validateProgram()
{
935
	if(!*m_program_object)
936
937
		return false;

938
	glValidateProgram(*m_program_object);
939
	GLint Result = GL_FALSE;
940
	glGetProgramiv(*m_program_object, GL_VALIDATE_STATUS, &Result);
941
942
943

	if(Result == GL_FALSE)
	{
944
		CGoGNout << "Validate program:" << CGoGNendl;
945
		int InfoLogLength;
946
		glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
947
		std::vector<char> Buffer(InfoLogLength);
948
		glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
949
		CGoGNout <<  &(Buffer[0]) << CGoGNendl;
950
951
952
953
954
955
956
957
958
		return false;
	}

	return true;
}

bool GLSLShader::checkProgram()
{
	GLint Result = GL_FALSE;
959
	glGetProgramiv(*m_program_object, GL_LINK_STATUS, &Result);
960
961

	int InfoLogLength;
962
	glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
963
	std::vector<char> Buffer(std::max(InfoLogLength, int(1)));
964
	glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
965
	CGoGNout << &Buffer[0] << CGoGNendl;
966
967
968
969
970
971
972
973

	return Result == GL_TRUE;
}

bool GLSLShader::checkShader(int shaderType)
{
	GLint Result = GL_FALSE;
	int InfoLogLength;
974
	GLuint id;
975
976
977
978

	switch(shaderType)
	{
	case VERTEX_SHADER:
979
		id = *m_vertex_shader_object;
980
981
		break;
	case FRAGMENT_SHADER:
982
		id = *m_fragment_shader_object;
983
984
		break;
	case GEOMETRY_SHADER:
985
		id = *m_geom_shader_object;
986
987
		break;
	default:
988
		CGoGNerr << "Error unkown shader type" << CGoGNendl;
989
990
991
992
993
994
995
996
		return false;
		break;
	}

	glGetShaderiv(id, GL_COMPILE_STATUS, &Result);
	glGetShaderiv(id, GL_INFO_LOG_LENGTH, &InfoLogLength);
	std::vector<char> Buffer(InfoLogLength);
	glGetShaderInfoLog(id, InfoLogLength, NULL, &Buffer[0]);
997
	CGoGNout << &Buffer[0] << CGoGNendl;
998
999
1000
1001

	return Result == GL_TRUE;
}

Sylvain Thery's avatar
Sylvain Thery committed
1002
void GLSLShader::bindAttrib(unsigned int att, const char* name) const
1003
{
1004
	glBindAttribLocation(*m_program_object, att, name);
1005
1006
}

1007
1008
1009
1010
1011
void GLSLShader::addPathFileSeach(const std::string& path)
{
	m_pathes.push_back(path);
}

1012
unsigned int GLSLShader::bindVA_VBO(const std::string& name, VBO* vbo)
Sylvain Thery's avatar
Sylvain Thery committed
1013
{
1014
	GLint idVA = glGetAttribLocation(*(this->m_program_object), name.c_str());
Sylvain Thery's avatar
Sylvain Thery committed
1015
1016
1017
	//valid ?
	if (idVA < 0)
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
1018
		CGoGNerr << "GLSLShader: Attribute " << name << " does not exist in shader" << CGoGNendl;
1019
		return idVA;
Sylvain Thery's avatar
Sylvain Thery committed
1020
	}