GLSLShader.cpp 31.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
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
#include "glm/gtc/matrix_inverse.hpp"
Sylvain Thery's avatar
Sylvain Thery committed
35

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
Pierre Kraemer committed
42

43 44 45
#ifdef USE_OGL_CORE_PROFILE
unsigned int GLSLShader::CURRENT_OGL_VERSION = 3;
#else
Pierre Kraemer's avatar
Pierre Kraemer committed
46
unsigned int GLSLShader::CURRENT_OGL_VERSION = 2;
47 48 49 50 51
#endif

unsigned int GLSLShader::MAJOR_OGL_CORE = 3;
unsigned int GLSLShader::MINOR_OGL_CORE = 3;

Sylvain Thery's avatar
Sylvain Thery committed
52 53 54

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

Pierre Kraemer's avatar
Pierre Kraemer committed
63

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

Pierre Kraemer's avatar
Pierre Kraemer committed
74 75

std::string* GLSLShader::DEFINES_GL = NULL;
76 77 78

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

79
std::set< std::pair<void*, GLSLShader*> >* GLSLShader::m_registeredShaders = NULL;
Pierre Kraemer's avatar
Pierre Kraemer committed
80 81


82 83 84
//glm::mat4* GLSLShader::s_current_matrices=NULL;
Utils::GL_Matrices* GLSLShader::s_current_matrices=NULL;

Pierre Kraemer's avatar
Pierre Kraemer committed
85
GLSLShader::GLSLShader() :
86
	m_vao(0),
Pierre Kraemer's avatar
Pierre Kraemer committed
87 88 89
	m_vertex_shader_source(NULL),
	m_fragment_shader_source(NULL),
	m_geom_shader_source(NULL)
Pierre Kraemer's avatar
Pierre Kraemer committed
90
{
91 92 93 94 95 96 97 98 99
	*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
Pierre Kraemer committed
100
	if (DEFINES_GL == NULL)
101
		DEFINES_GL = &DEFINES_GL2;
Sylvain Thery's avatar
Sylvain Thery committed
102 103

	m_nbMaxVertices = 16;
104 105 106

	if (m_registeredShaders==NULL)
		m_registeredShaders = new std::set< std::pair<void*, GLSLShader*> >;
107

Pierre Kraemer's avatar
Pierre Kraemer committed
108 109
}

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

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

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

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


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

Pierre Kraemer's avatar
Pierre Kraemer committed
172
char* GLSLShader::loadSourceFile(const std::string& filename)
Pierre Kraemer's avatar
Pierre Kraemer committed
173 174 175 176 177 178 179 180 181 182
{
	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() )
	{
183
		CGoGNerr << "ERROR - GLSLShader::loadSourceFile() - unable to open the file " << filename << "." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
		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 )
	{
204
		CGoGNerr << "ERROR - GLSLShader::loadSourceFile() - " << io_exception.what() << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
205 206 207 208 209 210 211 212 213 214 215 216
		file.close();
		return NULL;
	}

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

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

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

223
	m_vertex_shader_source = loadSourceFile( filename );
Pierre Kraemer's avatar
Pierre Kraemer committed
224

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


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

	return flag;
}

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

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

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

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

255 256
	flag = loadFragmentShaderSourceString( m_fragment_shader_source );
//	delete [] fragment_shader_source;
Pierre Kraemer's avatar
Pierre Kraemer committed
257 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;
}

284
bool GLSLShader::logError(GLuint handle, const std::string& nameSrc, const char *src)
Pierre Kraemer's avatar
Pierre Kraemer committed
285
{
286
	char *info_log;
287
	info_log = getInfoLogShader( handle );
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

310 311 312

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

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

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

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

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

		return false;
	}

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

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

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

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

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

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

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

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

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

		return false;
	}

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

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

388
	if (!logError(*m_fragment_shader_object, m_nameFS, fragment_shader_source))
Pierre Kraemer's avatar
Pierre Kraemer committed
389
	{
390
		glDeleteShader( *m_fragment_shader_object );
391
		*m_fragment_shader_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
392 393 394
		return false;
	}

395

Pierre Kraemer's avatar
Pierre Kraemer committed
396 397 398 399 400 401
	/*** termination ***/
	return true;
}

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

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

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

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

		return false;
	}

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

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

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

439

Pierre Kraemer's avatar
Pierre Kraemer committed
440 441 442 443
	/*** termination ***/
	return true;
}

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

450
	glGetProgramiv(obj, GL_INFO_LOG_LENGTH, &info_log_length);
451 452 453

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

	info_log = new char [info_log_length];
456
	glGetProgramInfoLog( obj, info_log_length, &length, info_log );
Pierre Kraemer's avatar
Pierre Kraemer committed
457 458 459 460

	return info_log;
}

461

462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480
char* GLSLShader::getInfoLogShader( GLuint obj )
{
    char	*info_log;
    int		info_log_length;
    int		length;

    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;
}



481

Sylvain Thery's avatar
Sylvain Thery committed
482
bool GLSLShader::create(GLint inputGeometryPrimitive,GLint outputGeometryPrimitive, int nb_max_vertices)
Pierre Kraemer's avatar
Pierre Kraemer committed
483 484 485 486
{
	int		status;
	char	*info_log;

487
	if (nb_max_vertices != -1)
Sylvain Thery's avatar
Sylvain Thery committed
488 489
		m_nbMaxVertices = nb_max_vertices;

490 491
	m_geom_inputPrimitives = inputGeometryPrimitive;
	m_geom_outputPrimitives = outputGeometryPrimitive;
Pierre Kraemer's avatar
Pierre Kraemer committed
492 493

	/*** check if shaders are loaded ***/
494
	if( !*m_vertex_shader_object || !*m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
495
	{
496
		CGoGNerr << "ERROR - GLSLShader::create() - shaders are not defined." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
497 498 499 500
		return false;
	}

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

503
	if( !*m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
504
	{
505
		CGoGNerr << "ERROR - GLSLShader::create() - unable to create program object." << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
506 507 508 509
		return false;
	}

	/*** attach shaders to program object ***/
510 511
	glAttachShader( *m_program_object, *m_vertex_shader_object );
	glAttachShader( *m_program_object, *m_fragment_shader_object );
512
	if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
513
	{
514
		glAttachShader( *m_program_object, *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
515

516 517 518 519 520 521
		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
522 523 524
	}

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

527
	glGetProgramiv( *m_program_object, GL_LINK_STATUS, &status );
Pierre Kraemer's avatar
Pierre Kraemer committed
528 529
	if( !status )
	{
530
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
531
		info_log = getInfoLog( *m_program_object );
532
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
533 534
		delete [] info_log;

535 536
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
537
		if (*m_geom_shader_object)
538 539
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
540
		*m_program_object = 0;
Pierre Kraemer's avatar
Pierre Kraemer committed
541 542 543 544

		return false;
	}

545 546 547 548
	*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");
549

Pierre Kraemer's avatar
Pierre Kraemer committed
550 551 552
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
553 554 555 556 557


bool GLSLShader::changeNbMaxVertices(int nb_max_vertices)
{
	m_nbMaxVertices = nb_max_vertices;
558
	if ((*m_geom_shader_object) && (CURRENT_OGL_VERSION == 2))
Sylvain Thery's avatar
Sylvain Thery committed
559 560 561 562 563 564 565 566 567 568 569 570 571 572
	{
		glProgramParameteriEXT(*m_program_object,GL_GEOMETRY_VERTICES_OUT_EXT,m_nbMaxVertices);
		// need to relink
		return true;
	}
	return false;
}







573 574 575 576 577 578
bool GLSLShader::link()
{
	int		status;
	char	*info_log;

	/*** link program object ***/
579
	glLinkProgram( *m_program_object );
580

581
	glGetProgramiv( *m_program_object, GL_OBJECT_LINK_STATUS_ARB, &status );
582 583
	if( !status )
	{
584
		CGoGNerr << "ERROR - GLSLShader::create() - error occured while linking shader program." << CGoGNendl;
585
		info_log = getInfoLog( *m_program_object );
586
		CGoGNerr << "  LINK " << info_log << CGoGNendl;
587 588
		delete [] info_log;

589 590
		glDetachShader( *m_program_object, *m_vertex_shader_object );
		glDetachShader( *m_program_object, *m_fragment_shader_object );
591
		if (*m_geom_shader_object)
592 593
			glDetachShader( *m_program_object, *m_geom_shader_object );
		glDeleteShader( *m_program_object );
594
		*m_program_object = 0;
595 596 597 598 599 600

		return false;
	}
	return true;
}

601
bool GLSLShader::bind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
602
{
603
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
604
	{
605
		glUseProgram( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
606 607
		return true;
	}
608 609
	else
		return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
610 611
}

612
void GLSLShader::unbind() const
Pierre Kraemer's avatar
Pierre Kraemer committed
613
{
614
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
615
	{
616
		glUseProgram( 0 );
Pierre Kraemer's avatar
Pierre Kraemer committed
617 618 619 620 621
	}
}

bool GLSLShader::isBinded()
{
622 623 624 625 626 627
	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
628 629 630 631
}

GLSLShader::~GLSLShader()
{
632
	if( *m_program_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
633 634 635
	{
		unbind();

636
		if( *m_vertex_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
637
		{
638 639
			glDetachShader( *m_program_object, *m_vertex_shader_object );
			glDeleteShader( *m_vertex_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
640
		}
641
		if( *m_fragment_shader_object )
Pierre Kraemer's avatar
Pierre Kraemer committed
642
		{
643 644
			glDetachShader( *m_program_object, *m_fragment_shader_object );
			glDeleteShader( *m_fragment_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
645
		}
646
		if (*m_geom_shader_object)
Pierre Kraemer's avatar
Pierre Kraemer committed
647
		{
648 649
			glDetachShader( *m_program_object, *m_geom_shader_object );
			glDeleteShader( *m_geom_shader_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
650 651
		}

652
		glDeleteShader( *m_program_object );
Pierre Kraemer's avatar
Pierre Kraemer committed
653
	}
654

655 656 657 658 659 660 661
	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;

662
//	m_registeredShaders->erase(this);
Pierre Kraemer's avatar
Pierre Kraemer committed
663 664 665 666
}

std::string GLSLShader::findFile(const std::string filename)
{
Pierre Kraemer's avatar
Pierre Kraemer committed
667
	// cherche d'abord dans le repertoire courant
Pierre Kraemer's avatar
Pierre Kraemer committed
668 669 670 671 672 673 674 675 676
	std::ifstream file;
	file.open(filename.c_str(),std::ios::in );
	if (!file.fail())
	{
		file.close();
		return filename;
	}
	file.close();

677 678 679 680 681 682 683 684 685 686 687 688 689 690
	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
Pierre Kraemer committed
691
	// LA MACRO SHADERPATH contient le chemin du repertoire qui contient les fichiers textes
Pierre Kraemer's avatar
Pierre Kraemer committed
692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707
	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()
{
708
#ifndef GLEW_MX
Pierre Kraemer's avatar
Pierre Kraemer committed
709 710 711
	GLenum error = glewInit();

	if (error != GLEW_OK)
712
		CGoGNerr << "Error: " << glewGetErrorString(error) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
713
	else
714
		CGoGNout << "Status: Using GLEW " << glewGetString(GLEW_VERSION) << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
715 716

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

719 720 721
	if  ((CURRENT_OGL_VERSION == 2) && (!glewIsSupported("GL_VERSION_2_0")))
	{
		CGoGNerr << " GL 2.0 not supported" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
722 723
		return false;
	}
724 725 726 727 728 729 730

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

731 732 733
#endif
	return true;

Pierre Kraemer's avatar
Pierre Kraemer committed
734 735 736 737
}

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

Pierre Kraemer's avatar
Pierre Kraemer committed
741 742 743 744
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;
	
	std::string pss = findFile(ps);
745
	if(!loadFragmentShader(pss)) return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
746 747

	if(!create()) {
748
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
749 750
		return false;
	}
751
	CGoGNout << "Shaders loaded (" << vs << "," << ps << ")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
752 753 754
	return true; 
}

Sylvain Thery's avatar
Sylvain Thery committed
755
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
756
{
Sylvain Thery's avatar
Sylvain Thery committed
757 758 759 760
	m_nameVS = vs;
	m_nameFS = ps;
	m_nameGS = gs;

Pierre Kraemer's avatar
Pierre Kraemer committed
761 762 763 764
	std::string vss = findFile(vs);
	if(!loadVertexShader(vss)) return false;

	std::string pss = findFile(ps);
765
	if(!loadFragmentShader(pss)) return false;
Pierre Kraemer's avatar
Pierre Kraemer committed
766 767 768 769 770 771

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

	if (!geomShaderLoaded)
	{
772
		CGoGNerr << "Error while loading geometry shader" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
773 774
	}

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

781
	CGoGNout << "Shaders loaded (" << vs << "," << ps << "," << gs <<")" << CGoGNendl;
Pierre Kraemer's avatar
Pierre Kraemer committed
782 783 784
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
785 786
bool GLSLShader::loadShadersFromMemory(const char* vs, const char* fs)
{
787 788
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
789
	m_vertex_shader_source = NULL;
790 791 792

	unsigned int sz = strlen(vs);
	m_vertex_shader_source = new char[sz+1];
Pierre Kraemer's avatar
Pierre Kraemer committed
793
	strcpy(m_vertex_shader_source, vs);
794 795 796 797 798 799

	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
Pierre Kraemer committed
800
	strcpy(m_fragment_shader_source, fs);
801

802 803
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
804

805 806
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
807 808 809

	if(!create())
	{
810
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
811 812 813 814 815
		return false;
	}
	return true;
}

Sylvain Thery's avatar
Sylvain Thery committed
816
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
817
{
818 819
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
820
	m_vertex_shader_source = NULL;
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839

	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
Pierre Kraemer committed
840 841
	if(!loadVertexShaderSourceString(vs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
842

Pierre Kraemer's avatar
Pierre Kraemer committed
843 844
	if(!loadFragmentShaderSourceString(fs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
845

Pierre Kraemer's avatar
Pierre Kraemer committed
846 847
	if(!loadGeometryShaderSourceString(gs))
		return false;
Sylvain Thery's avatar
Sylvain Thery committed
848

849
	if(!create(inputGeometryPrimitive, outputGeometryPrimitive, nb_max_vertices))
Sylvain Thery's avatar
Sylvain Thery committed
850
	{
851
		CGoGNout << "Unable to create the shaders !" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
852 853 854 855 856 857
		return false;
	}

	return true;
}

858 859 860 861
bool GLSLShader::reloadVertexShaderFromMemory(const char* vs)
{
	if (m_vertex_shader_source)
		delete [] m_vertex_shader_source;
862
	m_vertex_shader_source = NULL;
863 864 865

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

867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
	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))
	{
907
		CGoGNerr << "Unable to create the shaders !" << CGoGNendl;
908 909 910
		return false;
	}

911 912 913
	*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
914
	*m_uniMat_Normal	= glGetUniformLocation(*m_program_object,"NormalMatrix");
915 916 917

	restoreUniformsAttribs();

918 919
	updateClippingUniforms();

920 921 922
	return true;
}

923 924
bool GLSLShader::validateProgram()
{
925
	if(!*m_program_object)
926 927
		return false;

928
	glValidateProgram(*m_program_object);
929
	GLint Result = GL_FALSE;
930
	glGetProgramiv(*m_program_object, GL_VALIDATE_STATUS, &Result);
931 932 933

	if(Result == GL_FALSE)
	{
934
		CGoGNout << "Validate program:" << CGoGNendl;
935
		int InfoLogLength;
936
		glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
937
		std::vector<char> Buffer(InfoLogLength);
938
		glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
939
		CGoGNout <<  &(Buffer[0]) << CGoGNendl;
940 941 942 943 944 945 946 947 948
		return false;
	}

	return true;
}

bool GLSLShader::checkProgram()
{
	GLint Result = GL_FALSE;
949
	glGetProgramiv(*m_program_object, GL_LINK_STATUS, &Result);
950 951

	int InfoLogLength;
952
	glGetProgramiv(*m_program_object, GL_INFO_LOG_LENGTH, &InfoLogLength);
953
	std::vector<char> Buffer(std::max(InfoLogLength, int(1)));
954
	glGetProgramInfoLog(*m_program_object, InfoLogLength, NULL, &Buffer[0]);
955
	CGoGNout << &Buffer[0] << CGoGNendl;
956 957 958 959 960 961 962 963

	return Result == GL_TRUE;
}

bool GLSLShader::checkShader(int shaderType)
{
	GLint Result = GL_FALSE;
	int InfoLogLength;
964
	GLuint id;
965 966 967 968

	switch(shaderType)
	{
	case VERTEX_SHADER:
969
		id = *m_vertex_shader_object;
970 971
		break;
	case FRAGMENT_SHADER:
972
		id = *m_fragment_shader_object;
973 974
		break;
	case GEOMETRY_SHADER:
975
		id = *m_geom_shader_object;
976 977
		break;
	default:
978
		CGoGNerr << "Error unkown shader type" << CGoGNendl;
979 980 981 982 983 984 985 986
		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]);
987
	CGoGNout << &Buffer[0] << CGoGNendl;
988 989 990 991

	return Result == GL_TRUE;
}

Sylvain Thery's avatar
Sylvain Thery committed
992
void GLSLShader::bindAttrib(unsigned int att, const char* name) const
993
{
994
	glBindAttribLocation(*m_program_object, att, name);
995 996
}

997 998 999 1000 1001
void GLSLShader::addPathFileSeach(const std::string& path)
{
	m_pathes.push_back(path);
}

1002
unsigned int GLSLShader::bindVA_VBO(const std::string& name, VBO* vbo)
Sylvain Thery's avatar
Sylvain Thery committed
1003
{
1004
	GLint idVA = glGetAttribLocation(*(this->m_program_object), name.c_str());
Sylvain Thery's avatar
Sylvain Thery committed
1005 1006 1007
	//valid ?
	if (idVA < 0)
	{
Pierre Kraemer's avatar
Pierre Kraemer committed
1008
		CGoGNerr << "GLSLShader: Attribute " << name << " does not exist in shader" << CGoGNendl;
1009
		return idVA;
Sylvain Thery's avatar
Sylvain Thery committed
1010
	}
1011

Sylvain Thery's avatar
Sylvain Thery committed
1012 1013 1014 1015 1016
	// 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)
		{
1017 1018
			it->vbo_ptr = vbo;
			return (it - m_va_vbo_binding.begin());
Sylvain Thery's avatar
Sylvain Thery committed
1019 1020 1021 1022 1023
		}
	}
	// new one:
	VAStr temp;
	temp.va_id = idVA;
1024
	temp.vbo_ptr = vbo;
Sylvain Thery's avatar
Sylvain Thery committed
1025
	m_va_vbo_binding.push_back(temp);
1026

1027 1028 1029 1030 1031 1032
	return (m_va_vbo_binding.size() -1);
}

void GLSLShader::changeVA_VBO(unsigned int id, VBO* vbo)
{
	m_va_vbo_binding[id].vbo_ptr = vbo;
1033

Sylvain Thery's avatar
Sylvain Thery committed
1034 1035 1036 1037
}

void GLSLShader::unbindVA(const std::string& name)
{
1038
	GLint idVA = glGetAttribLocation(*(this->m_program_object), name.c_str());
Sylvain Thery's avatar
Sylvain Thery committed
1039 1040 1041
	//valid ?
	if (idVA < 0)
	{
1042
		CGoGNerr << "GLSLShader: Attribute " << name << " does not exist in shader, not unbinded" << CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
1043 1044 1045 1046
		return;
	}
	// search if name already exist
	unsigned int nb = m_va_vbo_binding.size();
1047
	for (unsigned int i = 0; i < nb; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
1048 1049 1050 1051 1052 1053 1054 1055 1056
	{
		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;
		}
	}
1057
	CGoGNerr << "GLSLShader: Attribute "<<name<< " not binded"<< CGoGNendl;
Sylvain Thery's avatar
Sylvain Thery committed
1058 1059 1060 1061
}

void GLSLShader::setCurrentOGLVersion(unsigned int version)
{
Pierre Kraemer's avatar
Pierre Kraemer committed
1062
	CURRENT_OGL_VERSION = version;
Sylvain Thery's avatar
Sylvain Thery committed
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
	switch(version)
	{
	case 2:
		DEFINES_GL = &DEFINES_GL2;
		break;
	case 3:
		DEFINES_GL = &DEFINES_GL3;
		break;
	}
}

1074 1075 1076 1077 1078 1079 1080 1081
void GLSLShader::setCurrentOGLVersion(unsigned int major,unsigned int minor)
{
	setCurrentOGLVersion(major);
	MAJOR_OGL_CORE = major;
	MINOR_OGL_CORE = minor;
}


Sylvain Thery's avatar
Sylvain Thery committed
1082 1083 1084 1085 1086
/**
 * update projection, modelview, ... matrices
 */
void GLSLShader::updateMatrices(const glm::mat4& projection, const glm::mat4& modelview)
{
Kenneth Vanhoey's avatar
Kenneth Vanhoey committed
1087
    this->bind();
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102

	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)
	{
Sylvain Thery's avatar
Sylvain Thery committed
1103
		glm::mat4 normalMatrix = glm::inverseTranspose(modelview);
1104 1105
		glUniformMatrix4fv(*m_uniMat_Normal, 	1 , false, &normalMatrix[0][0]);
	}
1106 1107

	this->unbind();
Sylvain Thery's avatar
Sylvain Thery committed
1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121
}

void GLSLShader::updateMatrices(const glm::mat4& projection, const glm::mat4& modelview, const glm::mat4& PMV, const glm::mat4& normalMatrix)
{
	this->bind();

	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)
		glUniformMatrix4fv(*m_uniMat_ModelProj,	1 , false, &PMV[0][0]);
1122

Sylvain Thery's avatar
Sylvain Thery committed
1123 1124
	if (*m_uniMat_Normal >= 0)
		glUniformMatrix4fv(*m_uniMat_Normal, 	1 , false, &normalMatrix[0][0]);
1125 1126

	this->unbind();
1127 1128
}

Sylvain Thery's avatar
Sylvain Thery committed
1129

1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
void GLSLShader::updateMatrices(const Utils::GLSLShader *sh)
{
	float mp[16];
	float mmv[16];
	float mmpv[16];
	float mn[16];

	sh->bind();
	if (*m_uniMat_Proj >= 0)
		glGetUniformfv(*(sh->m_program_object),*(sh->m_uniMat_Proj),mp);


	if (*m_uniMat_Model >= 0)
		glGetUniformfv(*(sh->m_program_object),*(sh->m_uniMat_Model),mmv);

	if (*m_uniMat_ModelProj >= 0)
		glGetUniformfv(*(sh->m_program_object),*(sh->m_uniMat_ModelProj),mmpv);

	if (*m_uniMat_Normal >= 0)
		glGetUniformfv(*(sh->m_program_object),*(sh->m_uniMat_Normal),mn);


	this->bind();

	if (*m_uniMat_Proj >= 0)
		glUniformMatrix4fv(*m_uniMat_Proj, 1, false, mp);

	if (*m_uniMat_Model >= 0)
		glUniformMatrix4fv(*m_uniMat_Model,	1, false, mmv);

	if (*m_uniMat_ModelProj >= 0)
		glUniformMatrix4fv(*m_uniMat_ModelProj,	1 , false, mmpv);

	if (*m_uniMat_Normal >= 0)
		glUniformMatrix4fv(*m_uniMat_Normal, 	1 , false, mn);

	this->unbind();
}




Sylvain Thery's avatar
Sylvain Thery committed
1172 1173


1174
void GLSLShader::enableVertexAttribs(unsigned int stride, unsigned int begin)
1175 1176
{
	this->bind();
1177 1178

	if (CURRENT_OGL_VERSION>=3)
1179
	{
sylvain thery's avatar
sylvain thery committed
1180 1181 1182
        if (m_vao!=0)
            glDeleteVertexArrays(1, &m_vao);
        glGenVertexArrays(1, &m_vao);
1183 1184 1185 1186 1187 1188 1189 1190 1191
		glBindVertexArray(m_vao);

		for (std::vector<Utils::GLSLShader::VAStr>::const_iterator it = m_va_vbo_binding.begin(); it != m_va_vbo_binding.end(); ++it)
		{
			assert(((it->vbo_ptr->nbElts()==0) || (it->vbo_ptr->dataSize()!=0) ) || !"dataSize of VBO is 0 ! could not draw");
			glBindBuffer(GL_ARRAY_BUFFER, it->vbo_ptr->id());
			glEnableVertexAttribArray(it->va_id);
			glVertexAttribPointer(it->va_id, it->vbo_ptr->dataSize(), GL_FLOAT, false, stride, (const GLvoid*)((unsigned long)(begin)));
		}
1192
	}
1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203
	else
	{
		for (std::vector<Utils::GLSLShader::VAStr>::const_iterator it = m_va_vbo_binding.begin(); it != m_va_vbo_binding.end(); ++it)
		{
			assert(((it->vbo_ptr->nbElts()==0) || (it->vbo_ptr->dataSize()!=0) ) || !"dataSize of VBO is 0 ! could not draw");
			glBindBuffer(GL_ARRAY_BUFFER, it->vbo_ptr->id());
			glVertexAttribPointer(it->va_id, it->vbo_ptr->dataSize(), GL_FLOAT, false, stride, (const GLvoid*)((unsigned long)(begin)));
			glEnableVertexAttribArray(it->va_id);
		}
	}
	//	this->unbind();
1204
}
Sylvain Thery's avatar
Sylvain Thery committed
1205

1206
void GLSLShader::disableVertexAttribs()
1207
{
1208
//	this->bind();
1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219

	if (CURRENT_OGL_VERSION>=3)
	{
		glBindVertexArray(0);
	}
	else
	{
		for (std::vector<Utils::GLSLShader::VAStr>::const_iterator it = m_va_vbo_binding.begin(); it != m_va_vbo_binding.end(); ++it)
			glDisableVertexAttribArray(it->va_id);
		this->unbind();
	}
1220 1221
}

Sylvain Thery's avatar
Sylvain Thery committed
1222

1223 1224 1225 1226 1227
void GLSLShader::updateCurrentMatrices()
{
	glm::mat4 model(currentModelView());
	model *= currentTransfo();

Sylvain Thery's avatar
Sylvain Thery committed
1228
	currentPMV() = currentProjection() * model;
Sylvain Thery's avatar
Sylvain Thery committed
1229
	currentNormalMatrix() = glm::inverseTranspose(model);
Sylvain Thery's avatar
Sylvain Thery committed
1230

1231
	for(std::set< std::pair<void*, GLSLShader*> >::iterator it = m_registeredShaders->begin(); it != m_registeredShaders->end(); ++it)
Sylvain Thery's avatar
Sylvain Thery committed
1232
		it->second->updateMatrices(currentProjection(), model, currentPMV(), currentNormalMatrix());
Sylvain Thery's avatar
Sylvain Thery committed
1233
}
Pierre Kraemer's avatar
Pierre Kraemer committed
1234

1235 1236 1237 1238 1239 1240 1241
void GLSLShader::updateAllFromGLMatrices()
{
	GLdouble modelview[16];
	GLdouble projection[16];
	glGetDoublev( GL_MODELVIEW_MATRIX, modelview );
	glGetDoublev( GL_PROJECTION_MATRIX, projection );

1242 1243
	glm::mat4& model = currentModelView();
	glm::mat4& proj = currentProjection();
1244 1245

	for (unsigned int i=0; i< 4; ++i)
Sylvain Thery's avatar
Sylvain Thery committed
1246
	{
1247 1248 1249 1250 1251
		for (unsigned int j=0; j<4; ++j)
		{
			proj[i][j] = float(projection[4*i+j]);
			model[i][j] = float(modelview[4*i+j]);
		}
Sylvain Thery's avatar
Sylvain Thery committed
1252
	}
Sylvain Thery's avatar
Sylvain Thery committed
1253
	model = currentTransfo() * model;
Sylvain Thery's avatar
Sylvain Thery committed
1254 1255

	currentPMV() = proj * model;
Sylvain Thery's avatar
Sylvain Thery committed
1256
	currentNormalMatrix() = glm::inverseTranspose(model);
1257

1258
	for(std::set< std::pair<void*, GLSLShader*> >::iterator it = m_registeredShaders->begin(); it != m_registeredShaders->end(); ++it)
Sylvain Thery's avatar
Sylvain Thery committed
1259
		it->second->updateMatrices(proj, model, currentPMV(), currentNormalMatrix());
1260 1261 1262
}


Pierre Kraemer's avatar
Pierre Kraemer committed
1263
} // namespace Utils
Pierre Kraemer's avatar
Pierre Kraemer committed
1264

Pierre Kraemer's avatar
Pierre Kraemer committed
1265
} // namespace CGoGN