GLSLShader.cpp 29.3 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

Pierre Kraemer's avatar
Pierre Kraemer committed
25 26 27 28 29
#define EXPORTING 1

#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 35
#include "glm/gtx/inverse_transpose.hpp"

Sylvain Thery's avatar
Sylvain Thery committed
36

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

namespace Utils
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
42 43

unsigned int GLSLShader::CURRENT_OGL_VERSION = 2;
Sylvain Thery's avatar
Sylvain Thery committed
44 45 46

std::string GLSLShader::DEFINES_GL2=\
"#version 110\n"
47
"#define PRECISON float pipo_PRECISION\n"
Sylvain Thery's avatar
Sylvain Thery committed
48 49 50
"#define ATTRIBUTE attribute\n"
"#define VARYING_VERT varying\n"
"#define VARYING_FRAG varying\n"
51 52
"#define FRAG_OUT_DEF float pipo_FRAGDEF\n"
"#define INVARIANT_POS float pipo_INVARIANT\n";
Sylvain Thery's avatar
Sylvain Thery committed
53

Pierre Kraemer's avatar
Pierre Kraemer committed
54

Sylvain Thery's avatar
Sylvain Thery committed
55
std::string GLSLShader::DEFINES_GL3=\
56
"#version 150\n"
57
"#define PRECISON precision highp float\n"
Sylvain Thery's avatar
Sylvain Thery committed
58 59 60 61
"#define ATTRIBUTE in\n"
"#define VARYING_VERT smooth out\n"
"#define VARYING_FRAG smooth in\n"
"#define FRAG_OUT_DEF out vec4 gl_FragColor\n"
62
"#define INVARIANT_POS invariant gl_Position\n";
Sylvain Thery's avatar
Sylvain Thery committed
63

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
64 65

std::string* GLSLShader::DEFINES_GL = NULL;
66 67 68

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

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


72 73 74
//glm::mat4* GLSLShader::s_current_matrices=NULL;
Utils::GL_Matrices* GLSLShader::s_current_matrices=NULL;

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
75 76 77 78
GLSLShader::GLSLShader() :
	m_vertex_shader_source(NULL),
	m_fragment_shader_source(NULL),
	m_geom_shader_source(NULL)
Pierre Kraemer's avatar
Pierre Kraemer committed
79
{
80 81 82 83 84 85 86 87 88
	*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
89
	if (DEFINES_GL == NULL)
90
		DEFINES_GL = &DEFINES_GL2;
Sylvain Thery's avatar
Sylvain Thery committed
91 92

	m_nbMaxVertices = 16;
Pierre Kraemer's avatar
Pierre Kraemer committed
93 94
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
95
void GLSLShader::registerShader(void* ptr, GLSLShader* shader)
96
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
97
	m_registeredShaders.insert(std::pair<void*,GLSLShader*>(ptr, shader));
98 99
}

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
100
void GLSLShader::unregisterShader(void* ptr, GLSLShader* shader)
101
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
102
	m_registeredShaders.erase(std::pair<void*,GLSLShader*>(ptr, shader));
103 104 105 106
}

std::string GLSLShader::defines_Geom(const std::string& primitivesIn, const std::string& primitivesOut, int maxVert)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
107
	if (CURRENT_OGL_VERSION == 3)
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
	{
		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");
		str.append("#define VARYING_IN in\n");
		str.append("#define VARYING_OUT smooth out\n");
		str.append("#define POSITION_IN(X) gl_in[X].gl_Position\n");
125
		str.append("#define NBVERTS_IN gl_in.length()\n");
126 127 128 129
		return str;
	}
	else
	{
Sylvain Thery's avatar
Sylvain Thery committed
130 131 132
		std::string str("#version 110\n");
		str.append("#extension GL_EXT_geometry_shader4 : enable\n");
		str.append("#define PRECISON float pipo_PRECISION\n");
133 134 135 136
		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");
137
		str.append("#define NBVERTS_IN gl_VerticesIn\n");
138 139 140 141
		return str;
	}
}

Pierre Kraemer's avatar
Pierre Kraemer committed
142 143
bool GLSLShader::areGeometryShadersSupported()
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
144 145
	if (!glewGetExtension("GL_EXT_geometry_shader4"))
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
	return true;
}

bool GLSLShader::areShadersSupported()
{
	if ( ! glewGetExtension("GL_ARB_vertex_shader")) return false;
	if ( ! glewGetExtension("GL_ARB_fragment_shader")) return false;
	if ( ! glewGetExtension("GL_ARB_shader_objects")) return false;
	if ( ! glewGetExtension("GL_ARB_shading_language_100")) return false;

	return true;
}

bool GLSLShader::areVBOSupported()
{
	if (!glewGetExtension("GL_ARB_vertex_buffer_object"))
		return false;
	return true;
}

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

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

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

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

213 214
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
215
	m_vertex_shader_source = NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
216

217
	m_vertex_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
218

219
	if( !m_vertex_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
220
	{
221
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
222 223 224 225
		return false;
	}


226 227
	flag = loadVertexShaderSourceString( m_vertex_shader_source );
//	delete [] vertex_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
228 229 230 231

	return flag;
}

232
bool GLSLShader::loadFragmentShader(const std::string& filename )
Pierre Kraemer's avatar
Pierre Kraemer committed
233 234
{
	bool	flag;
235
//	char	*fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
236

237 238
	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;
239
	m_fragment_shader_source = NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
240

241
	m_fragment_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
242

243
	if( !m_fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
244
	{
245
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
246 247 248
		return false;
	}

249 250
	flag = loadFragmentShaderSourceString( m_fragment_shader_source );
//	delete [] fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
251 252 253 254 255 256 257 258


	return flag;
}

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

261 262
	if (m_geom_shader_source)
		delete [] m_geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
263

264
	m_geom_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
265

266
	if( !m_geom_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
267
	{
268
		CGoGNerr << "ERROR - GLSLShader::loadGeometryShader() - error occured while loading source file." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
269 270 271
		return false;
	}

272 273
	flag = loadGeometryShaderSourceString( m_geom_shader_source );
//	delete [] geom_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
274 275 276 277

	return flag;
}

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

Sylvain Thery's avatar
Sylvain Thery committed
304 305 306

bool GLSLShader::loadVertexShaderSourceString( const char *vertex_shader_source )
{
307
	if (*m_vertex_shader_object==0)
Sylvain Thery's avatar
Sylvain Thery committed
308
	{
309 310
		glDeleteShader(*m_vertex_shader_object);
		*m_vertex_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
311
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
312 313

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

316
	if( !*m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
317
	{
318
		CGoGNerr << "ERROR - GLSLShader::loadVertexShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
319 320 321 322 323 324
		return false;
	}

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

327
		glDeleteShader(*m_vertex_shader_object );
328
		*m_vertex_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
329 330 331 332

		return false;
	}

333
	glShaderSource( *m_vertex_shader_object, 1, (const char**)&vertex_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
334 335

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

Sylvain Thery's avatar
Sylvain Thery committed
338
	if (!logError(*m_vertex_shader_object, m_nameVS, vertex_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
339
	{
340
		glDeleteShader( *m_vertex_shader_object );
341
		*m_vertex_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
342 343 344 345 346 347 348
		return false;
	}

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

349
bool GLSLShader::loadFragmentShaderSourceString( const char *fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
350
{
351
	if (*m_fragment_shader_object==0)
Sylvain Thery's avatar
Sylvain Thery committed
352
	{
353 354
		glDeleteShader(*m_fragment_shader_object);
		*m_fragment_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
355
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
356 357

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

360
	if( !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
361
	{
362
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - unable to create shader object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
363 364 365 366
		return false;
	}

	/*** load source file ***/
367
	if( !fragment_shader_source )
Pierre Kraemer's avatar
Pierre Kraemer committed
368
	{
369
		CGoGNerr << "ERROR - GLSLShader::loadFragmentShader() - source string is empty." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
370

371
		glDeleteShader( *m_fragment_shader_object );
372
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
373 374 375 376

		return false;
	}

377
	glShaderSource( *m_fragment_shader_object, 1, (const char**)&fragment_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
378 379

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

Sylvain Thery's avatar
Sylvain Thery committed
382
	if (!logError(*m_fragment_shader_object, m_nameFS, fragment_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
383
	{
384
		glDeleteShader( *m_fragment_shader_object );
385
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
386 387 388
		return false;
	}

Sylvain Thery's avatar
Sylvain Thery committed
389

Pierre Kraemer's avatar
Pierre Kraemer committed
390 391 392 393 394 395
	/*** termination ***/
	return true;
}

bool GLSLShader::loadGeometryShaderSourceString( const char *geom_shader_source )
{
396
	if (*m_geom_shader_object==0)
Sylvain Thery's avatar
Sylvain Thery committed
397
	{
398 399
		glDeleteShader(*m_geom_shader_object);
		*m_geom_shader_object=0;
Sylvain Thery's avatar
Sylvain Thery committed
400
	}
Pierre Kraemer's avatar
Pierre Kraemer committed
401
	/*** create shader object ***/
402
	*m_geom_shader_object = glCreateShader(GL_GEOMETRY_SHADER_EXT);
Pierre Kraemer's avatar
Pierre Kraemer committed
403

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

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

415
		glDeleteShader( *m_geom_shader_object );
416
		*m_geom_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
417 418 419 420

		return false;
	}

421
	glShaderSource( *m_geom_shader_object, 1, (const char**)&geom_shader_source, NULL );
Pierre Kraemer's avatar
Pierre Kraemer committed
422 423

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

Sylvain Thery's avatar
Sylvain Thery committed
426
	if (!logError(*m_geom_shader_object, m_nameGS, geom_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
427
	{
428
		glDeleteShader( *m_geom_shader_object );
429
		*m_geom_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
430 431 432
		return false;
	}

Sylvain Thery's avatar
Sylvain Thery committed
433

Pierre Kraemer's avatar
Pierre Kraemer committed
434 435 436 437
	/*** termination ***/
	return true;
}

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

Sylvain Thery's avatar
Sylvain Thery committed
444 445 446 447
	glGetShaderiv(obj, GL_INFO_LOG_LENGTH, &info_log_length);

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

	info_log = new char [info_log_length];
Sylvain Thery's avatar
Sylvain Thery committed
450
	glGetShaderInfoLog( obj, info_log_length, &length, info_log );
Pierre Kraemer's avatar
Pierre Kraemer committed
451 452 453 454

	return info_log;
}

Sylvain Thery's avatar
Sylvain Thery committed
455 456


Sylvain Thery's avatar
Sylvain Thery committed
457
bool GLSLShader::create(GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
458 459 460 461
{
	int		status;
	char	*info_log;

462
	if (nb_max_vertices != -1)
Sylvain Thery's avatar
Sylvain Thery committed
463 464
		m_nbMaxVertices = nb_max_vertices;

465 466
	m_geom_inputPrimitives = inputGeometryPrimitive;
	m_geom_outputPrimitives = outputGeometryPrimitive;
Pierre Kraemer's avatar
Pierre Kraemer committed
467 468

	/*** check if shaders are loaded ***/
469
	if( !*m_vertex_shader_object || !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
470
	{
471
		CGoGNerr << "ERROR - GLSLShader::create() - shaders are not defined." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
472 473 474 475
		return false;
	}

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

478
	if( !*m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
479
	{
480
		CGoGNerr << "ERROR - GLSLShader::create() - unable to create program object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
481 482 483 484
		return false;
	}

	/*** attach shaders to program object ***/
485 486
	glAttachShader( *m_program_object, *m_vertex_shader_object );
	glAttachShader( *m_program_object, *m_fragment_shader_object );
487
	if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
488
	{
489
		glAttachShader( *m_program_object, *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
490

491 492 493
		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
494 495 496
	}

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

499
	glGetProgramiv( *m_program_object, GL_OBJECT_LINK_STATUS_ARB, &status );
Pierre Kraemer's avatar
Pierre Kraemer committed
500 501
	if( !status )
	{
502
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
503
		info_log = getInfoLog( *m_program_object );
504
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
505 506
		delete [] info_log;

507 508
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
509
		if (*m_geom_shader_object)
510 511
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
512
		*m_program_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
513 514 515 516

		return false;
	}

517 518 519 520
	*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");
521

Pierre Kraemer's avatar
Pierre Kraemer committed
522 523 524
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544


bool GLSLShader::changeNbMaxVertices(int nb_max_vertices)
{
	m_nbMaxVertices = nb_max_vertices;
	if (*m_geom_shader_object)
	{
		glProgramParameteriEXT(*m_program_object,GL_GEOMETRY_VERTICES_OUT_EXT,m_nbMaxVertices);
		// need to relink
		return true;
	}
	return false;
}







545 546 547 548 549 550
bool GLSLShader::link()
{
	int		status;
	char	*info_log;

	/*** link program object ***/
551
	glLinkProgram( *m_program_object );
552

553
	glGetProgramiv( *m_program_object, GL_OBJECT_LINK_STATUS_ARB, &status );
554 555
	if( !status )
	{
556
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
557
		info_log = getInfoLog( *m_program_object );
558
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
559 560
		delete [] info_log;

561 562
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
563
		if (*m_geom_shader_object)
564 565
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
566
		*m_program_object = 0;
567 568 569 570 571 572 573

		return false;
	}

	return true;
}

574
bool GLSLShader::bind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
575
{
576
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
577
	{
578
		glUseProgram( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
579 580
		return true;
	}
581 582
	else
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
583 584
}

585
void GLSLShader::unbind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
586
{
587
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
588
	{
589
		glUseProgram( 0 );
Pierre Kraemer's avatar
Pierre Kraemer committed
590 591 592 593 594
	}
}

bool GLSLShader::isBinded()
{
595 596 597 598 599 600
	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
601 602 603 604
}

GLSLShader::~GLSLShader()
{
605
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
606 607 608
	{
		unbind();

609
		if( *m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
610
		{
611 612
			glDetachShader( *m_program_object, *m_vertex_shader_object );
			glDeleteShader( *m_vertex_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
613
		}
614
		if( *m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
615
		{
616 617
			glDetachShader( *m_program_object, *m_fragment_shader_object );
			glDeleteShader( *m_fragment_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
618
		}
619
		if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
620
		{
621 622
			glDetachShader( *m_program_object, *m_geom_shader_object );
			glDeleteShader( *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
623 624
		}

625
		glDeleteShader( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
626
	}
627

628 629 630 631 632 633 634
	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;

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
635
//	m_registeredShaders.erase(this);
Pierre Kraemer's avatar
Pierre Kraemer committed
636 637 638 639
}

std::string GLSLShader::findFile(const std::string filename)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
640
	// cherche d'abord dans le repertoire courant
Pierre Kraemer's avatar
Pierre Kraemer committed
641 642 643 644 645 646 647 648 649
	std::ifstream file;
	file.open(filename.c_str(),std::ios::in );
	if (!file.fail())
	{
		file.close();
		return filename;
	}
	file.close();

650 651 652 653 654 655 656 657 658 659 660 661 662 663
	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
664
	// LA MACRO SHADERPATH contient le chemin du repertoire qui contient les fichiers textes
Pierre Kraemer's avatar
Pierre Kraemer committed
665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680
	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()
{
681
#ifndef GLEW_MX
Pierre Kraemer's avatar
Pierre Kraemer committed
682 683 684
	GLenum error = glewInit();

	if (error != GLEW_OK)
685
		CGoGNerr << "Error: " << glewGetErrorString(error) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
686
	else
687
		CGoGNout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
688 689

	if (!areVBOSupported())
690
		CGoGNout << "VBO not supported !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
691 692

	if(!areShadersSupported()) {
693
		CGoGNout << "Shaders not supported !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
694 695
		return false;
	}
696 697 698
#endif
	return true;

Pierre Kraemer's avatar
Pierre Kraemer committed
699 700 701 702
}

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

Pierre Kraemer's avatar
Pierre Kraemer committed
706 707 708 709
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;
	
	std::string pss = findFile(ps);
710
	if(!loadFragmentShader(pss)) return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
711 712

	if(!create()) {
713
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
714 715
		return false;
	}
716
	CGoGNout << "Shaders loaded (" << vs << "," << ps << ")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
717 718 719
	return true; 
}

Sylvain Thery's avatar
Sylvain Thery committed
720
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
721
{
Sylvain Thery's avatar
Sylvain Thery committed
722 723 724 725
	m_nameVS = vs;
	m_nameFS = ps;
	m_nameGS = gs;

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 733 734 735 736

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

	if (!geomShaderLoaded)
	{
737
		CGoGNerr << "Error while loading geometry shader" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
738 739
	}

Sylvain Thery's avatar
Sylvain Thery committed
740
	if(!create(inputGeometryPrimitive,outputGeometryPrimitive,nb_max_vertices))
Pierre Kraemer's avatar
Pierre Kraemer committed
741
	{
742
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
743 744 745
		return false;
	}

746
	CGoGNout << "Shaders loaded (" << vs << "," << ps << "," << gs <<")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
747 748 749
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
750 751
bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs)
{
752 753
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
754
	m_vertex_shader_source = NULL;
755 756 757

	unsigned int sz = strlen(vs);
	m_vertex_shader_source = new char[sz+1];
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
758
	strcpy(m_vertex_shader_source, vs);
759 760 761 762 763 764

	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

	sz = strlen(fs);
	m_fragment_shader_source = new char[sz+1];
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
765
	strcpy(m_fragment_shader_source, fs);
766

767 768
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
769

770 771
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
772 773 774

	if(!create())
	{
775
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
776 777 778 779 780
		return false;
	}
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
781
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
782
{
783 784
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
785
	m_vertex_shader_source = NULL;
786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804

	unsigned int sz = strlen(vs);
	m_vertex_shader_source = new char[sz+1];
	strcpy(m_vertex_shader_source,vs);

	if (m_fragment_shader_source)
		delete [] m_fragment_shader_source;

	sz = strlen(fs);
	m_fragment_shader_source = new char[sz+1];
	strcpy(m_fragment_shader_source,fs);

	if (m_geom_shader_source)
		delete [] m_geom_shader_source;

	sz = strlen(gs);
	m_geom_shader_source = new char[sz+1];
	strcpy(m_geom_shader_source,gs);

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
805 806
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
807

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
808 809
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
810

Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
811 812
	if(!loadGeometryShaderSourceString(gs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
813

814
	if(!create(inputGeometryPrimitive, outputGeometryPrimitive, nb_max_vertices))
Sylvain Thery's avatar
Sylvain Thery committed
815
	{
816
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
817 818 819 820 821 822
		return false;
	}

	return true;
}

823 824 825 826
bool GLSLShader::reloadVertexShaderFromMemory(const char* vs)
{
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
827
	m_vertex_shader_source = NULL;
828 829 830

	unsigned int sz = strlen(vs);
	m_vertex_shader_source = new char[sz+1];
831

832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871
	strcpy(m_vertex_shader_source,vs);

	return true;
}

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

	unsigned int sz = strlen(fs);
	m_fragment_shader_source = new char[sz+1];
	strcpy(m_fragment_shader_source,fs);

	return true;
}

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

	unsigned int sz = strlen(gs);
	m_geom_shader_source = new char[sz+1];
	strcpy(m_geom_shader_source,gs);

	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))
	{
872
		CGoGNerr << "Unable to create the shaders !" << CGoGNendl;
873 874 875
		return false;
	}

876 877 878
	*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
879
	*m_uniMat_Normal	= glGetUniformLocation(*m_program_object,"NormalMatrix");
880 881 882

	restoreUniformsAttribs();

883 884
	updateClippingUniforms();

885 886 887
	return true;
}

888 889
bool GLSLShader::validateProgram()
{
890
	if(!*m_program_object)
891 892
		return false;

893
	glValidateProgram(*m_program_object);
894
	GLint Result = GL_FALSE;
895
	glGetProgramiv(*m_program_object, GL_VALIDATE_STATUS, &Result);
896 897 898

	if(Result == GL_FALSE)
	{
899
		CGoGNout << "Validate program:" << CGoGNendl;
900
		int InfoLogLength;
901
		glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
902
		std::vector<char> Buffer(InfoLogLength);
903
		glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
904
		CGoGNout <<  &(Buffer[0]) << CGoGNendl;
905 906 907 908 909 910 911 912 913
		return false;
	}

	return true;
}

bool GLSLShader::checkProgram()
{
	GLint Result = GL_FALSE;
914
	glGetProgramiv(*m_program_object, GL_LINK_STATUS, &Result);
915 916

	int InfoLogLength;
917
	glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
918
	std::vector<char> Buffer(std::max(InfoLogLength, int(1)));
919
	glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
920
	CGoGNout << &Buffer[0] << CGoGNendl;
921 922 923 924 925 926 927 928

	return Result == GL_TRUE;
}

bool GLSLShader::checkShader(int shaderType)
{
	GLint Result = GL_FALSE;
	int InfoLogLength;
929
	GLuint id;
930 931 932 933

	switch(shaderType)
	{
	case VERTEX_SHADER:
934
		id = *m_vertex_shader_object;
935 936
		break;
	case FRAGMENT_SHADER:
937
		id = *m_fragment_shader_object;
938 939
		break;
	case GEOMETRY_SHADER:
940
		id = *m_geom_shader_object;
941 942
		break;
	default:
943
		CGoGNerr << "Error unkown shader type" << CGoGNendl;
944 945 946 947 948 949 950 951
		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]);
952
	CGoGNout << &Buffer[0] << CGoGNendl;
953 954 955 956

	return Result == GL_TRUE;
}

Sylvain Thery's avatar
Sylvain Thery committed
957
void GLSLShader::bindAttrib(unsigned int att, const char* name) const
958
{
959
	glBindAttribLocation(*m_program_object, att, name);
960 961
}

962 963 964 965 966
void GLSLShader::addPathFileSeach(const std::string& path)
{
	m_pathes.push_back(path);
}

967
unsigned int GLSLShader::bindVA_VBO(const std::string& name, VBO* vbo)
Sylvain Thery's avatar
Sylvain Thery committed
968
{
969
	GLint idVA = glGetAttribLocation(*(this->m_program_object), name.c_str());
Sylvain Thery's avatar
Sylvain Thery committed
970 971 972
	//valid ?
	if (idVA < 0)
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
973
		CGoGNerr << "GLSLShader: Attribute " << name << " does not exist in shader" << CGoGNendl;
974
		return idVA;
Sylvain Thery's avatar
Sylvain Thery committed
975 976 977 978 979 980
	}
	// search if name already exist
	for (std::vector<VAStr>::iterator it = m_va_vbo_binding.begin(); it != m_va_vbo_binding.end(); ++it)
	{
		if (it->va_id == idVA)
		{
981 982
			it->vbo_ptr = vbo;
			return (it - m_va_vbo_binding.begin());
Sylvain Thery's avatar
Sylvain Thery committed
983 984 985 986 987
		}
	}
	// new one:
	VAStr temp;
	temp.va_id = idVA;
988
	temp.vbo_ptr = vbo;
Sylvain Thery's avatar
Sylvain Thery committed
989
	m_va_vbo_binding.push_back(temp);
990 991 992 993 994 995
	return (m_va_vbo_binding.size() -1);
}

void GLSLShader::changeVA_VBO(unsigned int id, VBO* vbo)
{
	m_va_vbo_binding[id].vbo_ptr = vbo;
Sylvain Thery's avatar
Sylvain Thery committed
996 997 998 999
}

void GLSLShader::unbindVA(const std::string& name)
{
1000
	GLint idVA = glGetAttribLocation(*(this->m_program_object), name.c_str());
Sylvain Thery's avatar
Sylvain Thery committed
1001 1002 1003
	//valid ?
	if (idVA < 0)
	{
1004
		CGoGNerr << "GLSLShader: Attribute " << name << " does not exist in shader, not unbinded" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
1005 1006 1007 1008
		return;
	}
	// search if name already exist
	unsigned int nb = m_va_vbo_binding.size();
1009
	for (unsigned int i = 0; i < nb; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
1010 1011 1012 1013 1014 1015 1016 1017 1018
	{
		if (m_va_vbo_binding[i].va_id == idVA)
		{
			if (i != (nb-1))
				m_va_vbo_binding[i] = m_va_vbo_binding[nb-1];
			m_va_vbo_binding.pop_back();
			return;
		}
	}
1019
	CGoGNerr << "GLSLShader: Attribute "<<name<< " not binded"<< CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
1020 1021 1022 1023
}

void GLSLShader::setCurrentOGLVersion(unsigned int version)
{
Pierre Kraemer's avatar
merge..  
Pierre Kraemer committed
1024
	CURRENT_OGL_VERSION = version;
Sylvain Thery's avatar
Sylvain Thery committed
1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
	switch(version)
	{
	case 2:
		DEFINES_GL = &DEFINES_GL2;
		break;
	case 3:
		DEFINES_GL = &DEFINES_GL3;
		break;
	}
}

/**
 * update projection, modelview, ... matrices
 */
void GLSLShader::updateMatrices(const glm::mat4& projection, const glm::mat4& modelview)
{
	this->bind();
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059

	if (*m_uniMat_Proj >= 0)
		glUniformMatrix4fv(*m_uniMat_Proj, 1, false, &projection[0][0]);

	if (*m_uniMat_Model >= 0)
		glUniformMatrix4fv(*m_uniMat_Model,	1, false, &modelview[0][0]);

	if (*m_uniMat_ModelProj >= 0)
	{
		glm::mat4 PMV = projection * modelview;
		glUniformMatrix4fv(*m_uniMat_ModelProj,	1 , false, &PMV[0][0]);
	}

	if (*m_uniMat_Normal >= 0)
	{
		glm::mat4 normalMatrix = glm::gtx::inverse_transpose::inverseTranspose(modelview);
		glUniformMatrix4fv(*m_uniMat_Normal, 	1 , false, &normalMatrix[0][0]);
	}
1060 1061

	this->unbind();
Sylvain Thery's avatar
Sylvain Thery committed
1062 1063 1064 1065 1066 1067