GLSLShader.cpp 32 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
#ifdef CGOGN_USE_OGL_CORE_PROFILE
43
unsigned int GLSLShader::CURRENT_OGL_VERSION = 3;
Sylvain Thery's avatar
Sylvain Thery committed
44 45
unsigned int GLSLShader::MAJOR_OGL_CORE = 3;
unsigned int GLSLShader::MINOR_OGL_CORE = 3;
46
#else
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
47
unsigned int GLSLShader::CURRENT_OGL_VERSION = 2;
Sylvain Thery's avatar
Sylvain Thery committed
48 49
unsigned int GLSLShader::MAJOR_OGL_CORE = 2;
unsigned int GLSLShader::MINOR_OGL_CORE = 1;
50 51 52
#endif


Sylvain Thery's avatar
Sylvain Thery committed
53 54 55

std::string GLSLShader::DEFINES_GL2=\
"#version 110\n"
56
"#define PRECISION float pipo_PRECISION\n"
Sylvain Thery's avatar
Sylvain Thery committed
57 58 59
"#define ATTRIBUTE attribute\n"
"#define VARYING_VERT varying\n"
"#define VARYING_FRAG varying\n"
60
"#define FRAG_OUT_DEF float pipo_FRAGDEF\n"
61
"#define FRAG_OUT gl_FragColor\n"
Sylvain Thery's avatar
Sylvain Thery committed
62 63 64
"#define INVARIANT_POS float pipo_INVARIANT\n"
"#define TEXTURE2D texture2D\n"
;
Sylvain Thery's avatar
Sylvain Thery committed
65

Pierre Kraemer's avatar
Pierre Kraemer committed
66

Sylvain Thery's avatar
Sylvain Thery committed
67
std::string GLSLShader::DEFINES_GL3=\
68
"#version 150\n"
69
"#define PRECISION precision highp float\n"
Sylvain Thery's avatar
Sylvain Thery committed
70
"#define ATTRIBUTE in\n"
sylvain thery's avatar
sylvain thery committed
71 72
"#define VARYING_VERT out\n"
"#define VARYING_FRAG in\n"
73 74
"#define FRAG_OUT_DEF out vec4 outFragColor\n"
"#define FRAG_OUT outFragColor\n"
Sylvain Thery's avatar
Sylvain Thery committed
75 76
"#define INVARIANT_POS invariant gl_Position\n"
"#define TEXTURE2D texture\n";
Sylvain Thery's avatar
Sylvain Thery committed
77

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
78 79

std::string* GLSLShader::DEFINES_GL = NULL;
80 81 82

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

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

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

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
88
GLSLShader::GLSLShader() :
89
	m_vao(0),
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
90 91 92
	m_vertex_shader_source(NULL),
	m_fragment_shader_source(NULL),
	m_geom_shader_source(NULL)
Pierre Kraemer's avatar
Pierre Kraemer committed
93
{
94 95 96 97 98 99 100 101 102
	*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;

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
103
	if (DEFINES_GL == NULL)
Sylvain Thery's avatar
Sylvain Thery committed
104
		setCurrentOGLVersion(MAJOR_OGL_CORE,MINOR_OGL_CORE);
Sylvain Thery's avatar
Sylvain Thery committed
105 106

	m_nbMaxVertices = 16;
107 108 109

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

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

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

std::string GLSLShader::defines_Geom(const std::string& primitivesIn, const std::string& primitivesOut, int maxVert)
{
124
	if (CURRENT_OGL_VERSION >= 3)
125 126 127 128 129 130 131 132 133 134 135 136 137 138
	{
		std::string str("#version 150\n");
		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
139 140
		str.append("#define VARYING_IN in\n");
		str.append("#define VARYING_OUT out\n");
141
		str.append("#define POSITION_IN(X) gl_in[X].gl_Position\n");
142
		str.append("#define NBVERTS_IN gl_in.length()\n");
143 144 145 146
		return str;
	}
	else
	{
Sylvain Thery's avatar
Sylvain Thery committed
147 148
		std::string str("#version 110\n");
		str.append("#extension GL_EXT_geometry_shader4 : enable\n");
kvanhoey's avatar
kvanhoey committed
149
		str.append("#define PRECISION float pipo_PRECISION\n");
150 151 152 153
		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");
154
		str.append("#define NBVERTS_IN gl_VerticesIn\n");
155 156 157 158
		return str;
	}
}

Pierre Kraemer's avatar
Pierre Kraemer committed
159 160
bool GLSLShader::areGeometryShadersSupported()
{
161
	if (!glewGetExtension("GL_ARB_geometry_shader4"))
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
162
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
163 164 165 166 167 168
	return true;
}


bool GLSLShader::areVBOSupported()
{
169
	if (!glewGetExtension("GL_vertex_buffer_object"))
Pierre Kraemer's avatar
Pierre Kraemer committed
170 171 172 173
		return false;
	return true;
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
174
char* GLSLShader::loadSourceFile(const std::string& filename)
Pierre Kraemer's avatar
Pierre Kraemer committed
175 176 177 178 179 180 181 182 183 184
{
	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() )
	{
185
		CGoGNerr << "ERROR - GLSLShader::loadSourceFile() - unable to open the file " << filename << "." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
186 187 188 189 190 191 192 193
		return NULL;
	}

	/*** reading file ***/
	try
	{
		/* get file size */
		file.seekg( 0, std::ios::end );
194
		file_size = int(file.tellg());
Pierre Kraemer's avatar
Pierre Kraemer committed
195 196 197 198 199 200 201 202 203 204 205
		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 )
	{
206
		CGoGNerr << "ERROR - GLSLShader::loadSourceFile() - " << io_exception.what() << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
207 208 209 210 211 212 213 214 215 216 217 218
		file.close();
		return NULL;
	}

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

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

221 222
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
223
	m_vertex_shader_source = NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
224

225
	m_vertex_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
226

227
	if( !m_vertex_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
228
	{
229
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
230 231 232
		return false;
	}

233 234
	flag = loadVertexShaderSourceString( m_vertex_shader_source );
//	delete [] vertex_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
235 236 237 238

	return flag;
}

239
bool GLSLShader::loadFragmentShader(const std::string& filename )
Pierre Kraemer's avatar
Pierre Kraemer committed
240 241
{
	bool	flag;
242
//	char	*fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
243

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

248
	m_fragment_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
249

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

256 257
	flag = loadFragmentShaderSourceString( m_fragment_shader_source );
//	delete [] fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
258 259 260 261 262 263 264

	return flag;
}

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

267 268
	if (m_geom_shader_source)
		delete [] m_geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
269

270
	m_geom_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
271

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

278 279
	flag = loadGeometryShaderSourceString( m_geom_shader_source );
//	delete [] geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
280 281 282 283

	return flag;
}

Sylvain Thery's avatar
Sylvain Thery committed
284
bool GLSLShader::logError(GLuint handle, const std::string& nameSrc, const char *src)
Pierre Kraemer's avatar
Pierre Kraemer committed
285
{
Sylvain Thery's avatar
Sylvain Thery committed
286
	char *info_log;
287
	info_log = getInfoLogShader( handle );
Sylvain Thery's avatar
Sylvain Thery committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
	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
309

Sylvain Thery's avatar
Sylvain Thery committed
310 311
bool GLSLShader::loadVertexShaderSourceString( const char *vertex_shader_source )
{
312
	if (*m_vertex_shader_object!=0)
Sylvain Thery's avatar
Sylvain Thery committed
313
	{
314 315
		glDeleteShader(*m_vertex_shader_object);
		*m_vertex_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
316
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
317 318

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

321
	if( !*m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
322
	{
323
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
324 325 326 327 328 329
		return false;
	}

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

332
		glDeleteShader(*m_vertex_shader_object );
333
		*m_vertex_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
334 335 336 337

		return false;
	}

338
	glShaderSource( *m_vertex_shader_object, 1, (const char**)&vertex_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
339 340

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

Sylvain Thery's avatar
Sylvain Thery committed
343
	if (!logError(*m_vertex_shader_object, m_nameVS, vertex_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
344
	{
345
		glDeleteShader( *m_vertex_shader_object );
346
		*m_vertex_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
347 348 349 350 351 352 353
		return false;
	}

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

354
bool GLSLShader::loadFragmentShaderSourceString( const char *fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
355
{
356
	if (*m_fragment_shader_object!=0)
Sylvain Thery's avatar
Sylvain Thery committed
357
	{
358 359
		glDeleteShader(*m_fragment_shader_object);
		*m_fragment_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
360
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
361 362

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

365
	if( !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
366
	{
367
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
368 369 370 371
		return false;
	}

	/*** load source file ***/
372
	if( !fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
373
	{
374
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - source string is empty." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
375

376
		glDeleteShader( *m_fragment_shader_object );
377
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
378 379 380 381

		return false;
	}

382
	glShaderSource( *m_fragment_shader_object, 1, (const char**)&fragment_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
383 384

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

Sylvain Thery's avatar
Sylvain Thery committed
387
	if (!logError(*m_fragment_shader_object, m_nameFS, fragment_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
388
	{
389
		glDeleteShader( *m_fragment_shader_object );
390
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
391 392 393 394 395 396 397 398 399
		return false;
	}

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

bool GLSLShader::loadGeometryShaderSourceString( const char *geom_shader_source )
{
400
	if (*m_geom_shader_object!=0)
Sylvain Thery's avatar
Sylvain Thery committed
401
	{
402 403
		glDeleteShader(*m_geom_shader_object);
		*m_geom_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
404
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
405
	/*** create shader object ***/
Sylvain Thery's avatar
Sylvain Thery committed
406
	*m_geom_shader_object = glCreateShader(GL_GEOMETRY_SHADER);
Pierre Kraemer's avatar
Pierre Kraemer committed
407

408
	if( !*m_geom_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
409
	{
410
		CGoGNerr << "ERROR - GLSLShader::loadGeometryShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
411 412 413 414 415 416
		return false;
	}

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

419
		glDeleteShader( *m_geom_shader_object );
420
		*m_geom_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
421 422 423 424

		return false;
	}

425
	glShaderSource( *m_geom_shader_object, 1, (const char**)&geom_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
426 427

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

Sylvain Thery's avatar
Sylvain Thery committed
430
	if (!logError(*m_geom_shader_object, m_nameGS, geom_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
431
	{
432
		glDeleteShader( *m_geom_shader_object );
433
		*m_geom_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
434 435 436 437 438 439 440
		return false;
	}

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

441
char* GLSLShader::getInfoLog( GLuint obj )
Pierre Kraemer's avatar
Pierre Kraemer committed
442
{
443 444 445
	char* info_log;
	int info_log_length;
	int length;
Pierre Kraemer's avatar
Pierre Kraemer committed
446

447
	glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &info_log_length);
Sylvain Thery's avatar
Sylvain Thery committed
448 449 450

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

	info_log = new char [info_log_length];
453
	glGetProgramInfoLog( obj, info_log_length, &length, info_log );
Pierre Kraemer's avatar
Pierre Kraemer committed
454 455 456 457

	return info_log;
}

458 459
char* GLSLShader::getInfoLogShader( GLuint obj )
{
460 461 462
	char* info_log;
	int	info_log_length;
	int	length;
463 464 465 466 467 468 469 470 471 472 473 474

    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
475
bool GLSLShader::create(GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
476
{
477 478
	int	status;
	char* info_log;
Pierre Kraemer's avatar
Pierre Kraemer committed
479

480
	if (nb_max_vertices != -1)
Sylvain Thery's avatar
Sylvain Thery committed
481 482
		m_nbMaxVertices = nb_max_vertices;

483 484
	m_geom_inputPrimitives = inputGeometryPrimitive;
	m_geom_outputPrimitives = outputGeometryPrimitive;
Pierre Kraemer's avatar
Pierre Kraemer committed
485 486

	/*** check if shaders are loaded ***/
487
	if( !*m_vertex_shader_object || !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
488
	{
489
		CGoGNerr << "ERROR - GLSLShader::create() - shaders are not defined." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
490 491 492 493
		return false;
	}

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

496
	if( !*m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
497
	{
498
		CGoGNerr << "ERROR - GLSLShader::create() - unable to create program object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
499 500 501 502
		return false;
	}

	/*** attach shaders to program object ***/
503 504
	glAttachShader( *m_program_object, *m_vertex_shader_object );
	glAttachShader( *m_program_object, *m_fragment_shader_object );
505
	if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
506
	{
507
		glAttachShader( *m_program_object, *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
508

509 510 511 512 513 514
		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
515 516 517
	}

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

520
	glGetProgramiv( *m_program_object, GL_LINK_STATUS, &status );
Pierre Kraemer's avatar
Pierre Kraemer committed
521 522
	if( !status )
	{
523
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
524
		info_log = getInfoLog( *m_program_object );
525
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
526 527
		delete [] info_log;

528 529
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
530
		if (*m_geom_shader_object)
531 532
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
533
		*m_program_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
534 535 536 537

		return false;
	}

538 539 540 541
	*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");
542

Pierre Kraemer's avatar
Pierre Kraemer committed
543 544 545
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
546 547 548
bool GLSLShader::changeNbMaxVertices(int nb_max_vertices)
{
	m_nbMaxVertices = nb_max_vertices;
549
	if ((*m_geom_shader_object) && (CURRENT_OGL_VERSION == 2))
Sylvain Thery's avatar
Sylvain Thery committed
550
	{
551
		glProgramParameteriEXT(*m_program_object, GL_GEOMETRY_VERTICES_OUT_EXT, m_nbMaxVertices);
Sylvain Thery's avatar
Sylvain Thery committed
552 553 554 555 556 557
		// need to relink
		return true;
	}
	return false;
}

558 559 560 561 562 563
bool GLSLShader::link()
{
	int		status;
	char	*info_log;

	/*** link program object ***/
564
	glLinkProgram( *m_program_object );
565

566
	glGetProgramiv( *m_program_object, GL_OBJECT_LINK_STATUS_ARB, &status );
567 568
	if( !status )
	{
569
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
570
		info_log = getInfoLog( *m_program_object );
571
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
572 573
		delete [] info_log;

574 575
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
576
		if (*m_geom_shader_object)
577 578
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
579
		*m_program_object = 0;
580 581 582 583 584 585

		return false;
	}
	return true;
}

586
bool GLSLShader::bind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
587
{
588
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
589
	{
590
		glUseProgram( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
591 592
		return true;
	}
593 594
	else
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
595 596
}

597
void GLSLShader::unbind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
598
{
599
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
600
	{
601
		glUseProgram( 0 );
Pierre Kraemer's avatar
Pierre Kraemer committed
602 603 604 605 606
	}
}

bool GLSLShader::isBinded()
{
607 608 609 610 611 612
	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
613 614 615 616
}

GLSLShader::~GLSLShader()
{
617
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
618 619 620
	{
		unbind();

621
		if( *m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
622
		{
623 624
			glDetachShader( *m_program_object, *m_vertex_shader_object );
			glDeleteShader( *m_vertex_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
625
		}
626
		if( *m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
627
		{
628 629
			glDetachShader( *m_program_object, *m_fragment_shader_object );
			glDeleteShader( *m_fragment_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
630
		}
631
		if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
632
		{
633 634
			glDetachShader( *m_program_object, *m_geom_shader_object );
			glDeleteShader( *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
635 636
		}

637
		glDeleteShader( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
638
	}
639

640 641 642 643 644 645 646
	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;

647
//	m_registeredShaders->erase(this);
Pierre Kraemer's avatar
Pierre Kraemer committed
648 649 650 651
}

std::string GLSLShader::findFile(const std::string filename)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
652
	// cherche d'abord dans le repertoire courant
Pierre Kraemer's avatar
Pierre Kraemer committed
653 654 655 656 657 658 659 660 661
	std::ifstream file;
	file.open(filename.c_str(),std::ios::in );
	if (!file.fail())
	{
		file.close();
		return filename;
	}
	file.close();

662 663 664 665 666 667 668 669 670 671 672 673 674 675
	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
676
	// LA MACRO SHADERPATH contient le chemin du repertoire qui contient les fichiers textes
Pierre Kraemer's avatar
Pierre Kraemer committed
677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692
	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()
{
693
#ifndef CGOGN_GLEW_MX
Pierre Kraemer's avatar
Pierre Kraemer committed
694 695 696
	GLenum error = glewInit();

	if (error != GLEW_OK)
697
		CGoGNerr << "Error: " << glewGetErrorString(error) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
698
	else
699
		CGoGNout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
700 701

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

704 705 706
	if  ((CURRENT_OGL_VERSION == 2) && (!glewIsSupported("GL_VERSION_2_0")))
	{
		CGoGNerr << " GL 2.0 not supported" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
707 708
		return false;
	}
709 710 711 712 713 714 715

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

716 717 718
#endif
	return true;

Pierre Kraemer's avatar
Pierre Kraemer committed
719 720 721 722
}

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

Pierre Kraemer's avatar
Pierre Kraemer committed
726 727 728 729
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;
	
	std::string pss = findFile(ps);
730
	if(!loadFragmentShader(pss)) return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
731 732

	if(!create()) {
733
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
734 735
		return false;
	}
736
	CGoGNout << "Shaders loaded (" << vs << "," << ps << ")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
737 738 739
	return true; 
}

Sylvain Thery's avatar
Sylvain Thery committed
740
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
741
{
Sylvain Thery's avatar
Sylvain Thery committed
742 743 744 745
	m_nameVS = vs;
	m_nameFS = ps;
	m_nameGS = gs;

Pierre Kraemer's avatar
Pierre Kraemer committed
746 747 748 749
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;

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

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

	if (!geomShaderLoaded)
	{
757
		CGoGNerr << "Error while loading geometry shader" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
758 759
	}

Sylvain Thery's avatar
Sylvain Thery committed
760
	if(!create(inputGeometryPrimitive,outputGeometryPrimitive,nb_max_vertices))
Pierre Kraemer's avatar
Pierre Kraemer committed
761
	{
762
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
763 764 765
		return false;
	}

766
	CGoGNout << "Shaders loaded (" << vs << "," << ps << "," << gs <<")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
767 768 769
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
770 771
bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs)
{
772 773
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
774
	m_vertex_shader_source = NULL;
775

776
	size_t sz = strlen(vs);
777
	m_vertex_shader_source = new char[sz+1];
778 779 780
	memcpy(m_vertex_shader_source, vs,sz+1);
	

781 782 783 784 785 786

	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

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

789 790
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
791

792 793
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
794 795 796

	if(!create())
	{
797
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
798 799 800 801 802
		return false;
	}
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
803
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
804
{
805 806
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
807
	m_vertex_shader_source = NULL;
808

809
	size_t sz = strlen(vs);
810
	m_vertex_shader_source = new char[sz+1];
811
	memcpy(m_vertex_shader_source,vs,sz+1);
812 813 814 815 816 817

	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

	sz = strlen(fs);
	m_fragment_shader_source = new char[sz+1];
818
	memcpy(m_fragment_shader_source,fs,sz+1);
819 820 821 822 823 824

	if (m_geom_shader_source)
		delete [] m_geom_shader_source;

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

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
827 828
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
829

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
830 831
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
832

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
833 834
	if(!loadGeometryShaderSourceString(gs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
835

836
	if(!create(inputGeometryPrimitive, outputGeometryPrimitive, nb_max_vertices))
Sylvain Thery's avatar
Sylvain Thery committed
837
	{
838
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
839 840 841 842 843 844
		return false;
	}

	return true;
}

845 846 847 848
bool GLSLShader::reloadVertexShaderFromMemory(const char* vs)
{
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
849
	m_vertex_shader_source = NULL;
850

851
	size_t sz = strlen(vs);
852
	m_vertex_shader_source = new char[sz+1];
853
	memcpy(m_vertex_shader_source,vs,sz+1);
854 855 856 857 858 859 860 861 862

	return true;
}

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

863
	unsigned int sz = uint32(strlen(fs));
864
	m_fragment_shader_source = new char[sz+1];
865
	memcpy(m_fragment_shader_source,fs,sz+1);
866 867 868 869 870 871 872 873 874

	return true;
}

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

875
	unsigned int sz = uint32(strlen(gs));
876
	m_geom_shader_source = new char[sz+1];
877
	memcpy(m_geom_shader_source,gs,sz+1);
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892

	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))
	{
893
		CGoGNerr << "Unable to create the shaders !" << CGoGNendl;
894 895 896
		return false;
	}

897 898 899
	*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
900
	*m_uniMat_Normal	= glGetUniformLocation(*m_program_object,"NormalMatrix");
901 902 903

	restoreUniformsAttribs();

904 905
	updateClippingUniforms();

906 907 908
	return true;
}

909 910
bool GLSLShader::validateProgram()
{
911
	if(!*m_program_object)
912 913
		return false;

914
	glValidateProgram(*m_program_object);
915
	GLint Result = GL_FALSE;
916
	glGetProgramiv(*m_program_object, GL_VALIDATE_STATUS, &Result);
917 918 919

	if(Result == GL_FALSE)
	{
920
		CGoGNout << "Validate program:" << CGoGNendl;
921
		int InfoLogLength;
922
		glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
923
		std::vector<char> Buffer(InfoLogLength);
924
		glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
925
		CGoGNout <<  &(Buffer[0]) << CGoGNendl;
926 927 928 929 930 931 932 933 934
		return false;
	}

	return true;
}

bool GLSLShader::checkProgram()
{
	GLint Result = GL_FALSE;
935
	glGetProgramiv(*m_program_object, GL_LINK_STATUS, &Result);
936 937

	int InfoLogLength;
938
	glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
939
	std::vector<char> Buffer(std::max(InfoLogLength, int(1)));
940
	glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
941
	CGoGNout << &Buffer[0] << CGoGNendl;
942 943 944 945 946 947 948 949

	return Result == GL_TRUE;
}

bool GLSLShader::checkShader(int shaderType)
{
	GLint Result = GL_FALSE;
	int InfoLogLength;
950
	GLuint id;
951 952 953 954

	switch(shaderType)
	{
	case VERTEX_SHADER:
955
		id = *m_vertex_shader_object;
956 957
		break;
	case FRAGMENT_SHADER:
958
		id = *m_fragment_shader_object;
959 960
		break;
	case GEOMETRY_SHADER:
961
		id = *m_geom_shader_object;
962 963
		break;
	default:
964
		CGoGNerr << "Error unkown shader type" << CGoGNendl;
965 966 967 968 969 970 971 972
		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]);
973
	CGoGNout << &Buffer[0] << CGoGNendl;
974 975 976 977

	return Result == GL_TRUE;
}

Sylvain Thery's avatar
Sylvain Thery committed
978
void GLSLShader: