framework2

Форк
0
1565 строк · 51.7 Кб
1
#include "ofShader.h"
2
#include "ofUtils.h"
3
#include "ofFileUtils.h"
4
#include "ofGraphics.h"
5
#include "ofGLProgrammableRenderer.h"
6
#include "ofTexture.h"
7
#include "ofMatrix4x4.h"
8
#include "ofMatrix3x3.h"
9
#include "ofParameterGroup.h"
10
#include "ofParameter.h"
11
#include "ofBufferObject.h"
12
#include "ofShadow.h"
13
#include "ofLight.h"
14
#include "ofCubeMap.h"
15
#ifdef TARGET_ANDROID
16
#include "ofxAndroidUtils.h"
17
#endif
18
#include <regex>
19

20
using std::unordered_map;
21
using std::vector;
22
using std::string;
23
using std::endl;
24
using std::setw;
25
using std::stringstream;
26
using std::ostringstream;
27

28
static const string COLOR_ATTRIBUTE="color";
29
static const string POSITION_ATTRIBUTE="position";
30
static const string NORMAL_ATTRIBUTE="normal";
31
static const string TEXCOORD_ATTRIBUTE="texcoord";
32

33
static unordered_map<GLuint,int> & getShaderIds(){
34
	static unordered_map<GLuint,int> * ids = new unordered_map<GLuint,int>;
35
	return *ids;
36
}
37

38
static unordered_map<GLuint,int> & getProgramIds(){
39
	static unordered_map<GLuint,int> * ids = new unordered_map<GLuint,int>;
40
	return *ids;
41
}
42

43
//--------------------------------------------------------------
44
static void retainShader(GLuint id){
45
	if(id==0) return;
46
	if(getShaderIds().find(id)!=getShaderIds().end()){
47
		getShaderIds()[id]++;
48
	}else{
49
		getShaderIds()[id]=1;
50
	}
51
}
52

53
//--------------------------------------------------------------
54
static void releaseShader(GLuint program, GLuint id){
55
	if(getShaderIds().find(id)!=getShaderIds().end()){
56
		getShaderIds()[id]--;
57
		if(getShaderIds()[id]==0){
58
			glDetachShader(program, id);
59
			glDeleteShader(id);
60
			getShaderIds().erase(id);
61
		}
62
	}else{
63
		ofLogWarning("ofShader") << "releaseShader(): something's wrong here, releasing unknown shader id " << id << " from program " << program;
64
		glDetachShader(program, id);
65
		glDeleteShader(id);
66
	}
67
}
68

69
//--------------------------------------------------------------
70
static void retainProgram(GLuint id){
71
	if(id==0) return;
72
	if(getProgramIds().find(id)!=getProgramIds().end()){
73
		getProgramIds()[id]++;
74
	}else{
75
		getProgramIds()[id]=1;
76
	}
77
}
78

79
//--------------------------------------------------------------
80
static void releaseProgram(GLuint id){
81
	if(getProgramIds().find(id)!=getProgramIds().end()){
82
		getProgramIds()[id]--;
83
		if(getProgramIds()[id]==0){
84
			glDeleteProgram(id);
85
			getProgramIds().erase(id);
86
		}
87
	}else{
88
		ofLogWarning("ofShader") << "releaseProgram(): something's wrong here, releasing unknown program id " << id;
89
		glDeleteProgram(id);
90
	}
91
}
92

93
#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
94
//--------------------------------------------------------------
95
ofShader::TransformFeedbackRangeBinding::TransformFeedbackRangeBinding(const ofBufferObject & buffer, GLuint offset, GLuint size)
96
	:offset(offset)
97
	,size(size)
98
	,buffer(buffer){}
99

100
//--------------------------------------------------------------
101
ofShader::TransformFeedbackBaseBinding::TransformFeedbackBaseBinding(const ofBufferObject & buffer)
102
	:buffer(buffer){}
103
#endif
104

105
//--------------------------------------------------------------
106
ofShader::ofShader() :
107
	program(0),
108
	bLoaded(false)
109
{
110
}
111

112
//--------------------------------------------------------------
113
ofShader::~ofShader() {
114
	unload();
115
}
116

117
//--------------------------------------------------------------
118
ofShader::ofShader(const ofShader & mom)
119
	:program(mom.program)
120
	,bLoaded(mom.bLoaded)
121
	,shaders(mom.shaders)
122
	,uniformsCache(mom.uniformsCache)
123
	,attributesBindingsCache(mom.attributesBindingsCache)
124
  #ifndef TARGET_OPENGLES
125
	,uniformBlocksCache(mom.uniformBlocksCache)
126
  #endif
127
{
128
	if(mom.bLoaded){
129
		retainProgram(program);
130
		for(auto it: shaders){
131
			auto shader = it.second;
132
			retainShader(shader.id);
133
		}
134
#ifdef TARGET_ANDROID
135
		ofAddListener(ofxAndroidEvents().unloadGL,this,&ofShader::unloadGL);
136
#endif
137
	}
138
}
139

140
//--------------------------------------------------------------
141
ofShader & ofShader::operator=(const ofShader & mom){
142
	if(this == &mom) {
143
		return *this;
144
	}
145
	if(bLoaded){
146
		unload();
147
	}
148
	program = mom.program;
149
	bLoaded = mom.bLoaded;
150
	shaders = mom.shaders;
151
	attributesBindingsCache = mom.attributesBindingsCache;
152
	uniformsCache = mom.uniformsCache;
153
	if(mom.bLoaded){
154
		retainProgram(program);
155
		for(auto it: shaders){
156
			auto shader = it.second;
157
			retainShader(shader.id);
158
		}
159
#ifdef TARGET_ANDROID
160
		ofAddListener(ofxAndroidEvents().unloadGL,this,&ofShader::unloadGL);
161
#endif
162
	}
163
	return *this;
164
}
165

166
ofShader::ofShader(ofShader && mom)
167
	:program(std::move(mom.program))
168
	,bLoaded(std::move(mom.bLoaded))
169
	,shaders(std::move(mom.shaders))
170
	,uniformsCache(std::move(mom.uniformsCache))
171
	,attributesBindingsCache(std::move(mom.attributesBindingsCache)){
172
	if(mom.bLoaded){
173
#ifdef TARGET_ANDROID
174
		ofAddListener(ofxAndroidEvents().unloadGL,this,&ofShader::unloadGL);
175
#endif
176
	}
177
	mom.bLoaded = false;
178
}
179

180
ofShader & ofShader::operator=(ofShader && mom){
181
	if(this == &mom) {
182
		return *this;
183
	}
184
	if(bLoaded){
185
		unload();
186
	}
187
	program = std::move(mom.program);
188
	bLoaded = std::move(mom.bLoaded);
189
	shaders = std::move(mom.shaders);
190
	attributesBindingsCache = std::move(mom.attributesBindingsCache);
191
	uniformsCache = std::move(mom.uniformsCache);
192
	if(mom.bLoaded){
193
#ifdef TARGET_ANDROID
194
		ofAddListener(ofxAndroidEvents().unloadGL,this,&ofShader::unloadGL);
195
#endif
196
	}
197
	mom.bLoaded = false;
198
	return *this;
199
}
200

201
//--------------------------------------------------------------
202
bool ofShader::load(const of::filesystem::path& shaderName) {
203
	return load(shaderName.string() + ".vert", shaderName.string() + ".frag");
204
}
205

206
//--------------------------------------------------------------
207
bool ofShader::load(const of::filesystem::path& vertName, const of::filesystem::path& fragName, const of::filesystem::path& geomName) {
208
	if(vertName.empty() == false) setupShaderFromFile(GL_VERTEX_SHADER, vertName);
209
	if(fragName.empty() == false) setupShaderFromFile(GL_FRAGMENT_SHADER, fragName);
210
#ifndef TARGET_OPENGLES
211
	if(geomName.empty() == false) setupShaderFromFile(GL_GEOMETRY_SHADER_EXT, geomName);
212
#endif
213
	if(ofIsGLProgrammableRenderer()){
214
		bindDefaults();
215
	}
216
	return linkProgram();
217
}
218

219
#if !defined(TARGET_OPENGLES) && defined(glDispatchCompute)
220
//--------------------------------------------------------------
221
bool ofShader::loadCompute(const of::filesystem::path& shaderName) {
222
	return setupShaderFromFile(GL_COMPUTE_SHADER, shaderName) && linkProgram();
223
}
224
#endif
225

226
//--------------------------------------------------------------
227
bool ofShader::setup(const ofShaderSettings & settings) {
228
	for (auto shader : settings.shaderFiles) {
229
		auto ty = shader.first;
230
		auto file = shader.second;
231
		auto shaderSource = sourceFromFile(ty, file);
232
		shaderSource.intDefines = settings.intDefines;
233
		shaderSource.floatDefines = settings.floatDefines;
234
		if (!setupShaderFromSource(std::move(shaderSource))) {
235
			return false;
236
		}
237
	}
238

239
	for (auto shader : settings.shaderSources) {
240
		auto ty = shader.first;
241
		auto source = shader.second;
242
		Source shaderSource{ty, source, settings.sourceDirectoryPath};
243
		shaderSource.intDefines = settings.intDefines;
244
		shaderSource.floatDefines = settings.floatDefines;
245
		if (!setupShaderFromSource(std::move(shaderSource))) {
246
			return false;
247
		}
248
	}
249

250
	if (ofIsGLProgrammableRenderer() && settings.bindDefaults) {
251
		bindDefaults();
252
	}
253

254
	return linkProgram();
255
}
256

257
#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
258
//--------------------------------------------------------------
259
bool ofShader::setup(const TransformFeedbackSettings & settings) {
260
	for (auto shader : settings.shaderFiles) {
261
		auto ty = shader.first;
262
		auto file = shader.second;
263
		auto shaderSource = sourceFromFile(ty, file);
264
		shaderSource.intDefines = settings.intDefines;
265
		shaderSource.floatDefines = settings.floatDefines;
266
		if (!setupShaderFromSource(std::move(shaderSource))) {
267
			return false;
268
		}
269
	}
270

271
	for (auto shader : settings.shaderSources) {
272
		auto ty = shader.first;
273
		auto source = shader.second;
274
		Source shaderSource{ty, source, settings.sourceDirectoryPath};
275
		shaderSource.intDefines = settings.intDefines;
276
		shaderSource.floatDefines = settings.floatDefines;
277
		if (!setupShaderFromSource(std::move(shaderSource))) {
278
			return false;
279
		}
280
	}
281

282
	if (ofIsGLProgrammableRenderer() && settings.bindDefaults) {
283
		bindDefaults();
284
	}
285

286
	if (!settings.varyingsToCapture.empty()) {
287
		std::vector<const char*> varyings(settings.varyingsToCapture.size());
288
		std::transform(settings.varyingsToCapture.begin(), settings.varyingsToCapture.end(), varyings.begin(), [](const std::string & str) {
289
			return str.c_str();
290
		});
291
		glTransformFeedbackVaryings(getProgram(), varyings.size(), varyings.data(), settings.bufferMode);
292
	}
293
	return linkProgram();
294
}
295
#endif
296

297
//--------------------------------------------------------------
298
bool ofShader::setupShaderFromFile(GLenum type, const of::filesystem::path & filename) {
299
	ofBuffer buffer = ofBufferFromFile(filename);
300
	// we need to make absolutely sure to have an absolute path here, so that any #includes
301
	// within the shader files have a root directory to traverse from.
302
	auto absoluteFilePath = ofFilePath::getAbsolutePath(filename, true);
303
	auto sourceDirectoryPath = ofFilePath::getEnclosingDirectory(absoluteFilePath,false);
304
	if(buffer.size()) {
305
		return setupShaderFromSource(type, buffer.getText(), sourceDirectoryPath);
306
	} else {
307
		ofLogError("ofShader") << "setupShaderFromFile(): couldn't load " << nameForType(type) << " shader " << " from \"" << absoluteFilePath << "\"";
308
		return false;
309
	}
310
}
311

312
//--------------------------------------------------------------
313
ofShader::Source ofShader::sourceFromFile(GLenum type, const of::filesystem::path& filename) {
314
	ofBuffer buffer = ofBufferFromFile(filename);
315
	// we need to make absolutely sure to have an absolute path here, so that any #includes
316
	// within the shader files have a root directory to traverse from.
317
	auto absoluteFilePath = ofFilePath::getAbsolutePath(filename, true);
318
	auto sourceDirectoryPath = ofFilePath::getEnclosingDirectory(absoluteFilePath,false);
319
	if(buffer.size()) {
320
		// return Source{type, buffer.getText(), sourceDirectoryPath.string() };
321
		return Source{type, buffer.getText(), sourceDirectoryPath };
322
	} else {
323
		ofLogError("ofShader") << "setupShaderFromFile(): couldn't load " << nameForType(type) << " shader " << " from \"" << absoluteFilePath << "\"";
324
		return Source{};
325
	}
326
}
327

328
//--------------------------------------------------------------
329
// FIXME: change to of::filesystem
330
bool ofShader::setupShaderFromSource(GLenum type, string source, string sourceDirectoryPath) {
331
	return setupShaderFromSource({type, source, sourceDirectoryPath});
332
}
333

334

335
//--------------------------------------------------------------
336
bool ofShader::setupShaderFromSource(ofShader::Source && source){
337
	unload();
338

339
	// create program if it doesn't exist already
340
	checkAndCreateProgram();
341
	GLuint clearErrors = glGetError(); //needed for some users to clear gl errors
342
	if( clearErrors != GL_NO_ERROR ){
343
		ofLogVerbose("ofShader") << "setupShaderFromSource(): OpenGL error after checkAndCreateProgram() (probably harmless): error " << clearErrors;
344
	}
345

346
	// create shader
347
	GLuint shaderId = glCreateShader(source.type);
348
	if(shaderId == 0) {
349
		ofLogError("ofShader") << "setupShaderFromSource(): failed creating " << nameForType(source.type) << " shader";
350
		return false;
351
	} else {
352
		// if the shader object has been allocated successfully on the GPU
353
		// we must retain it so that it can be de-allocated again, once
354
		// this ofShader object has been discarded, or re-allocated.
355
		// we need to do this at this point in the code path, since early
356
		// return statements might prevent us from retaining later.
357
		retainShader(shaderId);
358
	}
359
 
360
        // look for OF_GLSL_SHADER_HEADER header placeholder
361
	// this will swap the glsl version based on the OpenGL version set in main.cpp
362
	// note this won't always work, but is handy for switching between compatible versions of GLSL based on the system
363
	if( ofIsStringInString(source.source, "OF_GLSL_SHADER_HEADER") ){
364
            ofStringReplace(source.source, "OF_GLSL_SHADER_HEADER", ofGLSLGetDefaultHeader());
365
	}
366

367
	// parse for includes
368
	source.expandedSource = parseForIncludes( source.source, source.directoryPath );
369

370
	// parse and set defines
371
	for (auto& define : source.intDefines) {
372
		const auto& name = define.first;
373
		const auto& value = define.second;
374
		std::regex re_define("#define[ \t]+" + name + "[ \t]+(([1-9][0-9]*)|(0([xX][0-9a-fA-F]+)?))");
375
		source.expandedSource = std::regex_replace(source.expandedSource, re_define, "#define " + name + " " + std::to_string(value));
376
	}
377

378
	for (auto& define : source.floatDefines) {
379
		const auto& name = define.first;
380
		const auto& value = define.second;
381
		std::regex re_define("#define[ \t]+" + name + "[ \t]+[0-9]*(\\.[0-9]*f?)?");
382
		source.expandedSource = std::regex_replace(source.expandedSource, re_define, "#define " + name + " " + std::to_string(value));
383
	}
384

385
	// store source code (that's the expanded source with all includes copied in)
386
	// we need to store this here, and before shader compilation,
387
	// so that any shader compilation errors can be
388
	// traced down to the correct shader source code line.
389
	shaders[source.type] = { shaderId, std::move(source) };
390
	auto & shader = shaders[source.type];
391

392
	// compile shader
393
	const char* sptr = shader.source.expandedSource.c_str();
394
	int ssize = shader.source.expandedSource.size();
395
	glShaderSource(shaderId, 1, &sptr, &ssize);
396
	glCompileShader(shaderId);
397

398
	// check compile status
399
	GLint status = GL_FALSE;
400
	glGetShaderiv(shaderId, GL_COMPILE_STATUS, &status);
401
	GLuint err = glGetError();
402
	if (err != GL_NO_ERROR){
403
		ofLogError("ofShader") << "setupShaderFromSource(): OpenGL generated error " << err << " trying to get the compile status for a " << nameForType(shader.source.type) << " shader, does your video card support this?";
404
		return false;
405
	}
406

407
	if(status == GL_TRUE){
408
		ofLogVerbose("ofShader") << "setupShaderFromSource(): " << nameForType(shader.source.type) + " shader compiled";
409
#ifdef TARGET_EMSCRIPTEN
410
		checkShaderInfoLog(shaderId, source.type, OF_LOG_VERBOSE);
411
#else
412
		checkShaderInfoLog(shaderId, source.type, OF_LOG_WARNING);
413
#endif
414
	}else if (status == GL_FALSE) {
415
		ofLogError("ofShader") << "setupShaderFromSource(): " << nameForType(shader.source.type) + " shader failed to compile";
416
		checkShaderInfoLog(shaderId, source.type, OF_LOG_ERROR);
417
		return false;
418
	}
419
	return true;
420
}
421

422
/*
423
 * Parse for GLSL includes based on
424
 * https://www.opengl.org/discussion_boards/showthread.php/169209-include-in-glsl?p=1192415&viewfull=1#post1192415
425
 */
426

427
//--------------------------------------------------------------
428
string ofShader::parseForIncludes( const string& source, const of::filesystem::path& sourceDirectoryPath) {
429
	vector<string> included;
430
	return parseForIncludes( source, included, 0, sourceDirectoryPath);
431
}
432

433
//--------------------------------------------------------------
434
// FIXME: update to use fs::path in vector and source
435
string ofShader::parseForIncludes( const string& source, vector<string>& included, int level, const of::filesystem::path& sourceDirectoryPath) {
436

437
	if ( level > 32 ) {
438
		ofLogError( "ofShader", "glsl header inclusion depth limit reached, might be caused by cyclic header inclusion" );
439
		return "";
440
	}
441

442
	stringstream output;
443
	stringstream input;
444
	input << source;
445

446
	auto match_pragma_include = [](const std::string& s_, std::string& filename_) -> bool {
447
		filename_ = "";
448
		std::istringstream s(s_);
449
		s >> std::ws; // eat up any leading whitespace.
450

451
		if (s.peek() != '#') return false;
452
		// -----| invariant: found '#'
453
		s.seekg(1, std::ios::cur); // move forward one character
454

455
		std::string p, i, f;
456

457
		// while skipping whitespace, read in tokens for: pragma, include, and filename
458
		s >> std::skipws >> p >> i >> f;
459

460
		if (p.empty())
461
			return false;
462
		else if (p == "include") {
463
			f = i;
464
			i = p;
465
		}
466
		else if (p != "pragma")
467
			return false;
468
		
469
		if (i.empty() || (f.size() < 2) )
470
			return false;
471
		
472
		if (i != "include") return false;
473

474
		// first and last character of filename token must match and be either
475
		// '<' and '>', or '"
476

477
		if (f[0] == '<' && f[f.size()-1] != '>') return false; //< mismatching brackets
478

479
		if ((f[0] == '"' || f[0] == '\'') && (f[0] != f[f.size()-1])) return false; // mismatching quotes
480

481
		// invariant: filename properly quoted.
482

483
		filename_ = f.substr(1,f.size()-2);
484

485
		return true;
486
	};
487

488
	// once std::regex is available across the board, use this regex in favour of the above lambda:
489
	// std::regex re("^\\s*#\\s*pragma\\s+include\\s+[\"<](.*)[\">].*");
490

491
	string line;
492
	while( std::getline( input, line ) ) {
493

494
		string include;
495

496
		if (!match_pragma_include(line, include)){
497
			output << line << endl;
498
			continue;
499
		};
500

501
		// --------| invariant: '#pragma include' has been requested
502

503
		if ( std::find( included.begin(), included.end(), include ) != included.end() ) {
504
			ofLogVerbose("ofShader") << include << " already included";
505
			continue;
506
		}
507

508
		// we store the absolute paths so as have (more) unique file identifiers.
509
		// FIXME: Included can be a vector of of::filesystem::path in near future
510
		include = ofFile(
511
			sourceDirectoryPath / include
512
		// ).getAbsolutePath().string();
513
		).getAbsolutePath();
514

515
		included.push_back( include );
516

517
		ofBuffer buffer = ofBufferFromFile( include );
518
		if ( !buffer.size() ) {
519
			ofLogError("ofShader") <<"Could not open glsl include file " << include;
520
			continue;
521
		}
522

523
		auto currentDir = ofFile(include).getEnclosingDirectory();
524
		output << parseForIncludes( buffer.getText(), included, level + 1, currentDir ) << endl;
525
	}
526

527
	return output.str();
528
}
529

530
//--------------------------------------------------------------
531
string ofShader::getShaderSource(GLenum type)  const{
532
	auto source = shaders.find(type);
533
	if ( source != shaders.end()) {
534
		return source->second.source.expandedSource;
535
	} else {
536
		ofLogError("ofShader") << "No shader source for shader of type: " << nameForType(type);
537
		return "";
538
	}
539
}
540

541
//--------------------------------------------------------------
542
void ofShader::setGeometryInputType(GLenum type) {
543
#ifndef TARGET_OPENGLES
544
	checkAndCreateProgram();
545
	glProgramParameteri(program, GL_GEOMETRY_INPUT_TYPE_EXT, type);
546
#endif
547
}
548

549
//--------------------------------------------------------------
550
void ofShader::setGeometryOutputType(GLenum type) {
551
#ifndef TARGET_OPENGLES
552
	checkAndCreateProgram();
553
	glProgramParameteri(program, GL_GEOMETRY_OUTPUT_TYPE_EXT, type);
554
#endif
555
}
556

557
//--------------------------------------------------------------
558
void ofShader::setGeometryOutputCount(int count) {
559
#ifndef TARGET_OPENGLES
560
	checkAndCreateProgram();
561
	glProgramParameteri(program, GL_GEOMETRY_VERTICES_OUT_EXT, count);
562
#endif
563
}
564

565
//--------------------------------------------------------------
566
int ofShader::getGeometryMaxOutputCount()  const{
567
#ifndef TARGET_OPENGLES
568
	int temp;
569
	glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &temp);
570
	return temp;
571
#else
572
	return 0;
573
#endif
574
}
575

576
//--------------------------------------------------------------
577
bool ofShader::checkProgramLinkStatus() {
578
	GLint status;
579
	glGetProgramiv(program, GL_LINK_STATUS, &status);
580
	GLuint err = glGetError();
581
	if (err != GL_NO_ERROR){
582
		ofLogError("ofShader") << "checkProgramLinkStatus(): OpenGL generated error " << err << " trying to get the program link status, does your video card support shader programs?";
583
		return false;
584
	}
585
	if(status == GL_TRUE)
586
		ofLogVerbose("ofShader") << "checkProgramLinkStatus(): program " << program << " linked";
587
	else if (status == GL_FALSE) {
588
		ofLogError("ofShader") << "checkProgramLinkStatus(): program failed to link";
589
		checkProgramInfoLog();
590
		return false;
591
	}
592
	return true;
593
}
594

595
//--------------------------------------------------------------
596
void ofShader::checkShaderInfoLog(GLuint shader, GLenum type, ofLogLevel logLevel) {
597
	GLsizei infoLength;
598
	glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLength);
599
	if (infoLength > 1) {
600
		ofBuffer infoBuffer;
601
		infoBuffer.allocate(infoLength);
602
		glGetShaderInfoLog(shader, infoLength, &infoLength, infoBuffer.getData());
603
		ofLog(logLevel, "ofShader: %s shader reports:\n%s", nameForType(type).c_str(), infoBuffer.getText().c_str());
604
#if (!defined(TARGET_LINUX) || defined(GCC_HAS_REGEX))
605
		if (shaders.find(type) != shaders.end()) {
606
			// The following regexp should match shader compiler error messages by Nvidia and ATI.
607
			// Unfortunately, each vendor's driver formats error messages slightly different.
608
			std::regex nvidia_ati("^.*[(:]{1}(\\d+)[:)]{1}.*");
609
			std::regex intel("^[0-9]+:([0-9]+)\\([0-9]+\\):.*$");
610
			std::smatch matches;
611
			string infoString = ofTrim(infoBuffer);
612
			if (std::regex_search(infoString, matches, intel) || std::regex_search(infoString, matches, nvidia_ati)){
613
				ofBuffer buf;
614
				buf.set(shaders[type].source.expandedSource);
615
				ofBuffer::Line line = buf.getLines().begin();
616
				int  offendingLineNumber = ofToInt(matches[1]);
617
				ostringstream msg;
618
				msg << "ofShader: " + nameForType(type) + ", offending line " << offendingLineNumber << ":"<< endl;
619
				for(int i=0; line != buf.getLines().end(); line++, i++ ){
620
					string s = *line;
621
					if ( i >= offendingLineNumber -3 && i < offendingLineNumber + 2 ){
622
						msg << "\t" << setw(5) << (i+1) << "\t" << s << endl;
623
					}
624
				}
625
				ofLog(logLevel) << msg.str();
626
			}else{
627
				ofLog(logLevel) << shaders[type].source.expandedSource;
628
			}
629
		}
630
#endif
631
	}
632
}
633

634
//--------------------------------------------------------------
635
void ofShader::checkProgramInfoLog() {
636
	GLsizei infoLength;
637
	glGetProgramiv(program, GL_INFO_LOG_LENGTH, &infoLength);
638
	if (infoLength > 1) {
639
		ofBuffer infoBuffer;
640
		infoBuffer.allocate(infoLength);
641
		glGetProgramInfoLog(program, infoLength, &infoLength, infoBuffer.getData());
642
		// TODO: it appears that Raspberry Pi only reports shader errors whilst linking,
643
		// but then it becomes hard to figure out whether the fragment or the
644
		// vertex shader caused the error.
645
		// We need to find a robust way of extracing this information from
646
		// the log, and unfortunately can't use regex whilst gcc on RPi is assumed to
647
		// be < 4.9, which is the first version fully supporting this c++11 feature.
648
		string msg = "ofShader: program reports:\n";
649
		ofLogError("ofShader") << msg + infoBuffer.getText();
650
#ifdef TARGET_RAPSBERRY_PI
651
		for(auto it: shaders){
652
			ofLogNotice("ofShader") << it.second.expandedSource;
653
		}
654
#endif
655
	}
656
}
657

658

659

660
//--------------------------------------------------------------
661
void ofShader::checkAndCreateProgram() {
662
#ifndef TARGET_OPENGLES
663
	if(GL_ARB_shader_objects) {
664
#else
665
	if(ofIsGLProgrammableRenderer()){
666
#endif
667
		if(program == 0) {
668
			ofLogVerbose("ofShader") << "checkAndCreateProgram(): creating GLSL program";
669
			program = glCreateProgram();
670
			retainProgram(program);
671
		}
672
	} else {
673
		ofLogError("ofShader") << "sorry, it looks like you can't run 'ARB_shader_objects'";
674
		ofLogError("ofShader") << "please check the capabilites of your graphics card: http://www.ozone3d.net/gpu_caps_viewer";
675
	}
676
}
677

678
//--------------------------------------------------------------
679
bool ofShader::linkProgram() {
680
	if(shaders.empty()) {
681
		ofLogError("ofShader") << "linkProgram(): trying to link GLSL program, but no shaders created yet";
682
	} else {
683
		checkAndCreateProgram();
684

685
		for(auto it: shaders){
686
			auto shader = it.second;
687
			if(shader.id>0) {
688
				ofLogVerbose("ofShader") << "linkProgram(): attaching " << nameForType(it.first) << " shader to program " << program;
689
				glAttachShader(program, shader.id);
690
			}
691
		}
692

693
		glLinkProgram(program);
694

695
		checkProgramLinkStatus();
696

697

698
		// Pre-cache all active uniforms
699
		GLint numUniforms = 0;
700
		glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms);
701

702
		GLint uniformMaxLength = 0;
703
		glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxLength);
704

705
		GLint count = -1;
706
		GLenum type = 0;
707
		GLsizei length;
708
		GLint location;
709
		vector<GLchar> uniformName(uniformMaxLength);
710
		for(GLint i = 0; i < numUniforms; i++) {
711
			glGetActiveUniform(program, i, uniformMaxLength, &length, &count, &type, uniformName.data());
712
			string name(uniformName.begin(), uniformName.begin()+length);
713
			// some drivers return uniform_name[0] for array uniforms
714
			// instead of the real uniform name
715
			location = glGetUniformLocation(program, name.c_str());
716
			if (location == -1) continue; // ignore uniform blocks
717

718
			uniformsCache[name] = location;
719
			auto arrayPos = name.find('[');
720
			if(arrayPos!=std::string::npos){
721
				name = name.substr(0, arrayPos);
722
				uniformsCache[name] = location;
723
			}
724
		}
725

726
#ifndef TARGET_OPENGLES
727
#ifdef GLEW_ARB_uniform_buffer_object
728
		if(GLEW_ARB_uniform_buffer_object) {
729
			// Pre-cache all active uniforms blocks
730
			GLint numUniformBlocks = 0;
731
			glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
732

733
			count = -1;
734
			type = 0;
735
			vector<GLchar> uniformBlockName(uniformMaxLength);
736
			for(GLint i = 0; i < numUniformBlocks; i++) {
737
				glGetActiveUniformBlockName(program, i, uniformMaxLength, &length, uniformBlockName.data() );
738
				string name(uniformBlockName.begin(), uniformBlockName.begin()+length);
739
				uniformBlocksCache[name] = glGetUniformBlockIndex(program, name.c_str());
740
			}
741
		}
742
#endif
743
#endif
744

745
#ifdef TARGET_ANDROID
746
		ofAddListener(ofxAndroidEvents().unloadGL,this,&ofShader::unloadGL);
747
#endif
748

749
		// bLoaded means we have loaded shaders onto the graphics card;
750
		// it doesn't necessarily mean that these shaders have compiled and linked successfully.
751
		bLoaded = true;
752
	}
753
	return bLoaded;
754
}
755

756

757
//--------------------------------------------------------------
758
#ifdef TARGET_ANDROID
759
void ofShader::unloadGL(){
760
	for(auto it: shaders) {
761
		auto shader = it.second;
762
		if(shader.id) {
763
			releaseShader(program,shader.id);
764
		}
765
	}
766

767
	if (program) {
768
		releaseProgram(program);
769
		program = 0;
770
	}
771
	bLoaded = false;
772
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofShader::reloadGL);
773
}
774

775
void ofShader::reloadGL(){
776
	auto source = shaders;
777
	auto bindings = attributesBindingsCache;
778
	shaders.clear();
779
	uniformsCache.clear();
780
#ifndef TARGET_OPENGLES
781
#ifdef GLEW_ARB_uniform_buffer_object // Core in OpenGL 3.1
782
	uniformBlocksCache.clear();
783
#endif
784
#endif
785
	attributesBindingsCache.clear();
786
	for(auto & shader: source){
787
		auto source = shader.second.source;
788
		setupShaderFromSource(std::move(shader.second.source));
789
	}
790
	for(auto binding: bindings){
791
		bindAttribute(binding.second, binding.first);
792
	}
793
	linkProgram();
794
}
795
#endif
796

797
//--------------------------------------------------------------
798
void ofShader::bindAttribute(GLuint location, const string & name) const{
799
	attributesBindingsCache[name] = location;
800
	glBindAttribLocation(program,location,name.c_str());
801
}
802

803
//--------------------------------------------------------------
804
bool ofShader::bindDefaults(){
805
	if(shaders.empty()) {
806
		ofLogError("ofShader") << "bindDefaults(): trying to link GLSL program, but no shaders created yet";
807
		return false;
808
	} else {
809
		bindAttribute(ofShader::POSITION_ATTRIBUTE,::POSITION_ATTRIBUTE);
810
		bindAttribute(ofShader::COLOR_ATTRIBUTE,::COLOR_ATTRIBUTE);
811
		bindAttribute(ofShader::NORMAL_ATTRIBUTE,::NORMAL_ATTRIBUTE);
812
		bindAttribute(ofShader::TEXCOORD_ATTRIBUTE,::TEXCOORD_ATTRIBUTE);
813
		return true;
814
	}
815

816
}
817

818
//--------------------------------------------------------------
819
void ofShader::unload() {
820
	if(bLoaded) {
821
		for(auto it: shaders) {
822
			auto shader = it.second;
823
			if(shader.id) {
824
				ofLogVerbose("ofShader") << "unload(): detaching and deleting " << nameForType(shader.source.type) << " shader from program " << program;
825
				releaseShader(program,shader.id);
826
			}
827
		}
828

829
		if (program) {
830
			releaseProgram(program);
831
			program = 0;
832
		}
833

834
		shaders.clear();
835
		uniformsCache.clear();
836
#ifndef TARGET_OPENGLES
837
#ifdef GLEW_ARB_uniform_buffer_object // Core in OpenGL 3.1
838
		uniformBlocksCache.clear();
839
#endif
840
#endif
841
		attributesBindingsCache.clear();
842
#ifdef TARGET_ANDROID
843
		ofRemoveListener(ofxAndroidEvents().reloadGL,this,&ofShader::reloadGL);
844
		ofRemoveListener(ofxAndroidEvents().unloadGL,this,&ofShader::unloadGL);
845
#endif
846
	}
847
	bLoaded = false;
848
}
849

850
//--------------------------------------------------------------
851
bool ofShader::isLoaded() const{
852
	return bLoaded;
853
}
854

855
//--------------------------------------------------------------
856
void ofShader::begin()  const{
857
	ofGetGLRenderer()->bind(*this);
858
}
859

860
//--------------------------------------------------------------
861
void ofShader::end()  const{
862
	ofGetGLRenderer()->unbind(*this);
863
}
864

865
#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
866
//--------------------------------------------------------------
867
void ofShader::beginTransformFeedback(GLenum mode) const {
868
	begin();
869
    glEnable(GL_RASTERIZER_DISCARD);
870
	glBeginTransformFeedback(mode);
871
}
872

873
//--------------------------------------------------------------
874
void ofShader::beginTransformFeedback(GLenum mode, const TransformFeedbackRangeBinding & binding) const {
875
	binding.buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index, binding.offset, binding.size);
876
	beginTransformFeedback(mode);
877
}
878

879
//--------------------------------------------------------------
880
void ofShader::beginTransformFeedback(GLenum mode, const std::vector<TransformFeedbackRangeBinding> & bindings) const {
881
	for (auto & binding : bindings) {
882
		binding.buffer.bindRange(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index, binding.offset, binding.size);
883
	}
884
	beginTransformFeedback(mode);
885
}
886

887
//--------------------------------------------------------------
888
void ofShader::beginTransformFeedback(GLenum mode, const TransformFeedbackBaseBinding & binding) const {
889
	binding.buffer.bindBase(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index);
890
	beginTransformFeedback(mode);
891
}
892

893
//--------------------------------------------------------------
894
void ofShader::beginTransformFeedback(GLenum mode, const std::vector<TransformFeedbackBaseBinding> & bindings) const {
895
	for (auto & binding : bindings) {
896
		binding.buffer.bindBase(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index);
897
	}
898
	beginTransformFeedback(mode);
899
}
900

901
//--------------------------------------------------------------
902
void ofShader::endTransformFeedback() const {
903
	glEndTransformFeedback();
904
    glDisable(GL_RASTERIZER_DISCARD);
905
	end();
906
}
907

908
//--------------------------------------------------------------
909
void ofShader::endTransformFeedback(const TransformFeedbackRangeBinding & binding) const {
910
	binding.buffer.unbindRange(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index);
911
	endTransformFeedback();
912
}
913

914
//--------------------------------------------------------------
915
void ofShader::endTransformFeedback(const std::vector<TransformFeedbackRangeBinding> & bindings) const {
916
	for (auto & binding : bindings) {
917
		binding.buffer.unbindRange(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index);
918
	}
919
	endTransformFeedback();
920
}
921

922
//--------------------------------------------------------------
923
void ofShader::endTransformFeedback(const TransformFeedbackBaseBinding & binding) const {
924
	binding.buffer.unbindBase(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index);
925
	endTransformFeedback();
926
}
927

928
//--------------------------------------------------------------
929
void ofShader::endTransformFeedback(const std::vector<TransformFeedbackBaseBinding> & bindings) const {
930
	for (auto & binding : bindings) {
931
		binding.buffer.unbindBase(GL_TRANSFORM_FEEDBACK_BUFFER, binding.index);
932
	}
933
	endTransformFeedback();
934
}
935
#endif
936

937
#if !defined(TARGET_OPENGLES) && defined(glDispatchCompute)
938
//--------------------------------------------------------------
939
void ofShader::dispatchCompute(GLuint x, GLuint y, GLuint z) const{
940
	glDispatchCompute(x,y,z);
941
}
942
#endif
943

944
//--------------------------------------------------------------
945
void ofShader::setUniformTexture(const string & name, const ofBaseHasTexture& img, int textureLocation)  const{
946
	setUniformTexture(name, img.getTexture(), textureLocation);
947
}
948

949
//--------------------------------------------------------------
950
void ofShader::setUniformTexture(const string & name, int textureTarget, GLint textureID, int textureLocation) const{
951
	if(bLoaded) {
952
		glActiveTexture(GL_TEXTURE0 + textureLocation);
953
		if (!ofIsGLProgrammableRenderer()){
954
			glEnable(textureTarget);
955
			glBindTexture(textureTarget, textureID);
956
			glDisable(textureTarget);
957
		} else {
958
			glBindTexture(textureTarget, textureID);
959
		}
960
		setUniform1i(name, textureLocation);
961
		glActiveTexture(GL_TEXTURE0);
962
	}
963
}
964

965
//--------------------------------------------------------------
966
void ofShader::setUniformTexture(const string & name, const ofTexture& tex, int textureLocation)  const{
967
	if(bLoaded) {
968
		ofTextureData texData = tex.getTextureData();
969
		glActiveTexture(GL_TEXTURE0 + textureLocation);
970
		if (!ofIsGLProgrammableRenderer()){
971
			glEnable(texData.textureTarget);
972
			glBindTexture(texData.textureTarget, texData.textureID);
973
#ifndef TARGET_OPENGLES
974
			if (texData.bufferId != 0) {
975
				glTexBuffer(GL_TEXTURE_BUFFER, texData.glInternalFormat, texData.bufferId);
976
			}
977
#endif
978
			glDisable(texData.textureTarget);
979
		} else {
980
			glBindTexture(texData.textureTarget, texData.textureID);
981
#ifndef TARGET_OPENGLES
982
			if (texData.bufferId != 0) {
983
				glTexBuffer(GL_TEXTURE_BUFFER, texData.glInternalFormat, texData.bufferId);
984
			}
985
#endif
986
		}
987
		setUniform1i(name, textureLocation);
988
		glActiveTexture(GL_TEXTURE0);
989
	}
990
}
991

992
//--------------------------------------------------------------
993
void ofShader::setUniform1i(const string & name, int v1)  const{
994
	if(bLoaded) {
995
		int loc = getUniformLocation(name);
996
		if (loc != -1) glUniform1i(loc, v1);
997
	}
998
}
999

1000
//--------------------------------------------------------------
1001
void ofShader::setUniform2i(const string & name, int v1, int v2)  const{
1002
	if(bLoaded) {
1003
		int loc = getUniformLocation(name);
1004
		if (loc != -1) glUniform2i(loc, v1, v2);
1005
	}
1006
}
1007

1008
//--------------------------------------------------------------
1009
void ofShader::setUniform3i(const string & name, int v1, int v2, int v3)  const{
1010
	if(bLoaded) {
1011
		int loc = getUniformLocation(name);
1012
		if (loc != -1) glUniform3i(loc, v1, v2, v3);
1013
	}
1014
}
1015

1016
//--------------------------------------------------------------
1017
void ofShader::setUniform4i(const string & name, int v1, int v2, int v3, int v4)  const{
1018
	if(bLoaded) {
1019
		int loc = getUniformLocation(name);
1020
		if (loc != -1) 	glUniform4i(loc, v1, v2, v3, v4);
1021
	}
1022
}
1023

1024
//--------------------------------------------------------------
1025
void ofShader::setUniform1f(const string & name, float v1)  const{
1026
	if(bLoaded) {
1027
		int loc = getUniformLocation(name);
1028
		if (loc != -1) glUniform1f(loc, v1);
1029
	}
1030
}
1031

1032
//--------------------------------------------------------------
1033
void ofShader::setUniform2f(const string & name, float v1, float v2)  const{
1034
	if(bLoaded) {
1035
		int loc = getUniformLocation(name);
1036
		if (loc != -1) glUniform2f(loc, v1, v2);
1037
	}
1038
}
1039

1040
//--------------------------------------------------------------
1041
void ofShader::setUniform3f(const string & name, float v1, float v2, float v3)  const{
1042
	if(bLoaded) {
1043
		int loc = getUniformLocation(name);
1044
		if (loc != -1) glUniform3f(loc, v1, v2, v3);
1045
	}
1046
}
1047

1048
//--------------------------------------------------------------
1049
void ofShader::setUniform4f(const string & name, float v1, float v2, float v3, float v4)  const{
1050
	if(bLoaded) {
1051
		int loc = getUniformLocation(name);
1052
		if (loc != -1) glUniform4f(loc, v1, v2, v3, v4);
1053
	}
1054
}
1055

1056

1057
//--------------------------------------------------------------
1058
void ofShader::setUniform2f(const string & name, const glm::vec2 & v) const{
1059
	setUniform2f(name,v.x,v.y);
1060
}
1061

1062
//--------------------------------------------------------------
1063
void ofShader::setUniform3f(const string & name, const glm::vec3 & v) const{
1064
	setUniform3f(name,v.x,v.y,v.z);
1065
}
1066

1067
//--------------------------------------------------------------
1068
void ofShader::setUniform4f(const string & name, const glm::vec4 & v) const{
1069
	setUniform4f(name,v.x,v.y,v.z,v.w);
1070
}
1071

1072
//--------------------------------------------------------------
1073
void ofShader::setUniform4f(const string & name, const ofFloatColor & v) const{
1074
	setUniform4f(name,v.r,v.g,v.b,v.a);
1075
}
1076

1077
//--------------------------------------------------------------
1078
void ofShader::setUniform1iv(const string & name, const int* v, int count)  const{
1079
	if(bLoaded) {
1080
		int loc = getUniformLocation(name);
1081
		if (loc != -1) glUniform1iv(loc, count, v);
1082
	}
1083
}
1084

1085
//--------------------------------------------------------------
1086
void ofShader::setUniform2iv(const string & name, const int* v, int count)  const{
1087
	if(bLoaded) {
1088
		int loc = getUniformLocation(name);
1089
		if (loc != -1) glUniform2iv(loc, count, v);
1090
	}
1091
}
1092

1093
//--------------------------------------------------------------
1094
void ofShader::setUniform3iv(const string & name, const int* v, int count)  const{
1095
	if(bLoaded) {
1096
		int loc = getUniformLocation(name);
1097
		if (loc != -1) glUniform3iv(loc, count, v);
1098
	}
1099
}
1100

1101
//--------------------------------------------------------------
1102
void ofShader::setUniform4iv(const string & name, const int* v, int count)  const{
1103
	if(bLoaded) {
1104
		int loc = getUniformLocation(name);
1105
		if (loc != -1) glUniform4iv(loc, count, v);
1106
	}
1107
}
1108

1109
//--------------------------------------------------------------
1110
void ofShader::setUniform1fv(const string & name, const float* v, int count)  const{
1111
	if(bLoaded) {
1112
		int loc = getUniformLocation(name);
1113
		if (loc != -1) glUniform1fv(loc, count, v);
1114
	}
1115
}
1116

1117
//--------------------------------------------------------------
1118
void ofShader::setUniform2fv(const string & name, const float* v, int count)  const{
1119
	if(bLoaded) {
1120
		int loc = getUniformLocation(name);
1121
		if (loc != -1) glUniform2fv(loc, count, v);
1122
	}
1123
}
1124

1125
//--------------------------------------------------------------
1126
void ofShader::setUniform3fv(const string & name, const float* v, int count)  const{
1127
	if(bLoaded) {
1128
		int loc = getUniformLocation(name);
1129
		if (loc != -1) glUniform3fv(loc, count, v);
1130
	}
1131
}
1132

1133
//--------------------------------------------------------------
1134
void ofShader::setUniform4fv(const string & name, const float* v, int count)  const{
1135
	if(bLoaded) {
1136
		int loc = getUniformLocation(name);
1137
		if (loc != -1) glUniform4fv(loc, count, v);
1138
	}
1139
}
1140

1141
//--------------------------------------------------------------
1142
void ofShader::setUniforms(const ofParameterGroup & parameters) const{
1143
	for(std::size_t i=0;i<parameters.size();i++){
1144
		if(parameters[i].type()==typeid(ofParameter<int>).name()){
1145
			setUniform1i(parameters[i].getEscapedName(),parameters[i].cast<int>());
1146
		}else if(parameters[i].type()==typeid(ofParameter<float>).name()){
1147
			setUniform1f(parameters[i].getEscapedName(),parameters[i].cast<float>());
1148
		}else if(parameters[i].type()==typeid(ofParameter<glm::vec2>).name()){
1149
			setUniform2f(parameters[i].getEscapedName(),parameters[i].cast<glm::vec2>());
1150
		}else if(parameters[i].type()==typeid(ofParameter<glm::vec3>).name()){
1151
			setUniform3f(parameters[i].getEscapedName(),parameters[i].cast<glm::vec3>());
1152
		}else if(parameters[i].type()==typeid(ofParameter<glm::vec4>).name()){
1153
			setUniform4f(parameters[i].getEscapedName(),parameters[i].cast<glm::vec4>());
1154
		}else if(parameters[i].type()==typeid(ofParameter<ofVec2f>).name()){
1155
			setUniform2f(parameters[i].getEscapedName(),parameters[i].cast<glm::vec2>());
1156
		}else if(parameters[i].type()==typeid(ofParameter<ofVec3f>).name()){
1157
			setUniform3f(parameters[i].getEscapedName(),parameters[i].cast<glm::vec3>());
1158
		}else if(parameters[i].type()==typeid(ofParameter<ofVec4f>).name()){
1159
			setUniform4f(parameters[i].getEscapedName(),parameters[i].cast<glm::vec4>());
1160
		}else if(parameters[i].type()==typeid(ofParameterGroup).name()){
1161
			setUniforms((ofParameterGroup&)parameters[i]);
1162
		}
1163
	}
1164
}
1165

1166
//--------------------------------------------------------------
1167
void ofShader::setUniformMatrix3f(const string & name, const glm::mat3 & m, int count)  const{
1168
	if(bLoaded) {
1169
		int loc = getUniformLocation(name);
1170
		if (loc != -1) glUniformMatrix3fv(loc, count, GL_FALSE, glm::value_ptr(m));
1171
	}
1172
}
1173

1174
//--------------------------------------------------------------
1175
void ofShader::setUniformMatrix4f(const string & name, const glm::mat4 & m, int count) const{
1176
	if(bLoaded) {
1177
		int loc = getUniformLocation(name);
1178
		if (loc != -1) glUniformMatrix4fv(loc, count, GL_FALSE, glm::value_ptr(m));
1179
	}
1180
}
1181

1182
#ifndef TARGET_OPENGLES
1183
//--------------------------------------------------------------
1184
void ofShader::setAttribute1s(GLint location, short v1)  const{
1185
	if(bLoaded)
1186
		glVertexAttrib1s(location, v1);
1187
}
1188

1189
//--------------------------------------------------------------
1190
void ofShader::setAttribute2s(GLint location, short v1, short v2)  const{
1191
	if(bLoaded)
1192
		glVertexAttrib2s(location, v1, v2);
1193
}
1194

1195
//--------------------------------------------------------------
1196
void ofShader::setAttribute3s(GLint location, short v1, short v2, short v3)  const{
1197
	if(bLoaded)
1198
		glVertexAttrib3s(location, v1, v2, v3);
1199
}
1200

1201
//--------------------------------------------------------------
1202
void ofShader::setAttribute4s(GLint location, short v1, short v2, short v3, short v4)  const{
1203
	if(bLoaded)
1204
		glVertexAttrib4s(location, v1, v2, v3, v4);
1205
}
1206
#endif
1207

1208
//--------------------------------------------------------------
1209
void ofShader::setAttribute1f(GLint location, float v1)  const{
1210
	if(bLoaded)
1211
		glVertexAttrib1f(location, v1);
1212
}
1213

1214
//--------------------------------------------------------------
1215
void ofShader::setAttribute2f(GLint location, float v1, float v2)  const{
1216
	if(bLoaded)
1217
		glVertexAttrib2f(location, v1, v2);
1218
}
1219

1220
//--------------------------------------------------------------
1221
void ofShader::setAttribute3f(GLint location, float v1, float v2, float v3)  const{
1222
	if(bLoaded)
1223
		glVertexAttrib3f(location, v1, v2, v3);
1224
}
1225

1226
//--------------------------------------------------------------
1227
void ofShader::setAttribute4f(GLint location, float v1, float v2, float v3, float v4)  const{
1228
	if(bLoaded)
1229
		glVertexAttrib4f(location, v1, v2, v3, v4);
1230
}
1231

1232
//--------------------------------------------------------------
1233
void ofShader::setAttribute1fv(const string & name, const float* v, GLsizei stride) const{
1234
	if(bLoaded){
1235
		GLint location = getAttributeLocation(name);
1236
		if (location != -1) {
1237
			glVertexAttribPointer(location, 1, GL_FLOAT, GL_FALSE, stride, v);
1238
			glEnableVertexAttribArray(location);
1239
		}
1240
	}
1241
}
1242

1243
//--------------------------------------------------------------
1244
void ofShader::setAttribute2fv(const string & name, const float* v, GLsizei stride) const{
1245
	if(bLoaded){
1246
		GLint location = getAttributeLocation(name);
1247
		if (location != -1) {
1248
			glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, stride, v);
1249
			glEnableVertexAttribArray(location);
1250
		}
1251
	}
1252

1253
}
1254

1255
//--------------------------------------------------------------
1256
void ofShader::setAttribute3fv(const string & name, const float* v, GLsizei stride) const{
1257
	if(bLoaded){
1258
		GLint location = getAttributeLocation(name);
1259
		if (location != -1) {
1260
			glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE, stride, v);
1261
			glEnableVertexAttribArray(location);
1262
		}
1263
	}
1264
}
1265

1266
//--------------------------------------------------------------
1267
void ofShader::setAttribute4fv(const string & name, const float* v, GLsizei stride) const{
1268
	if(bLoaded){
1269
		GLint location = getAttributeLocation(name);
1270
		if (location != -1) {
1271
			glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE, stride, v);
1272
			glEnableVertexAttribArray(location);
1273
		}
1274
	}
1275
}
1276

1277
#ifndef TARGET_OPENGLES
1278
//--------------------------------------------------------------
1279
void ofShader::setAttribute1d(GLint location, double v1)  const{
1280
	if(bLoaded)
1281
		glVertexAttrib1d(location, v1);
1282
}
1283

1284
//--------------------------------------------------------------
1285
void ofShader::setAttribute2d(GLint location, double v1, double v2)  const{
1286
	if(bLoaded)
1287
		glVertexAttrib2d(location, v1, v2);
1288
}
1289

1290
//--------------------------------------------------------------
1291
void ofShader::setAttribute3d(GLint location, double v1, double v2, double v3)  const{
1292
	if(bLoaded)
1293
		glVertexAttrib3d(location, v1, v2, v3);
1294
}
1295

1296
//--------------------------------------------------------------
1297
void ofShader::setAttribute4d(GLint location, double v1, double v2, double v3, double v4)  const{
1298
	if(bLoaded)
1299
		glVertexAttrib4d(location, v1, v2, v3, v4);
1300
}
1301
#endif
1302

1303
//--------------------------------------------------------------
1304
GLint ofShader::getAttributeLocation(const string & name)  const{
1305
	return glGetAttribLocation(program, name.c_str());
1306
}
1307

1308
//--------------------------------------------------------------
1309
GLint ofShader::getUniformLocation(const string & name)  const{
1310
	if(!bLoaded) return -1;
1311
	auto it = uniformsCache.find(name);
1312
	if (it == uniformsCache.end()){
1313
		return -1;
1314
	} else {
1315
		return it->second;
1316
	}
1317
}
1318

1319
#ifndef TARGET_OPENGLES
1320
#ifdef GLEW_ARB_uniform_buffer_object
1321
//--------------------------------------------------------------
1322
GLint ofShader::getUniformBlockIndex(const string & name)  const{
1323
	if(!bLoaded) return -1;
1324

1325
	if(GLEW_ARB_uniform_buffer_object) {
1326
		auto it = uniformBlocksCache.find(name);
1327
		if (it == uniformBlocksCache.end()){
1328
			return -1;
1329
		} else {
1330
			return it->second;
1331
		}
1332
	} else {
1333
		ofLogError("ofShader::getUniformBlockIndex") << "Sorry, it looks like you can't run 'ARB_uniform_buffer_object'";
1334
		return -1;
1335
	}
1336
}
1337

1338
//--------------------------------------------------------------
1339
GLint ofShader::getUniformBlockBinding( const string & name ) const{
1340
	if(!bLoaded) return -1;
1341

1342
	if(GLEW_ARB_uniform_buffer_object) {
1343
		GLint index = getUniformBlockIndex(name);
1344
		if (index == -1) return -1;
1345

1346
		GLint blockBinding;
1347
		glGetActiveUniformBlockiv(program, index, GL_UNIFORM_BLOCK_BINDING, &blockBinding);
1348
		return blockBinding;
1349
	} else {
1350
		ofLogError("ofShader::getUniformBlockBinding") << "Sorry, it looks like you can't run 'ARB_uniform_buffer_object'";
1351
		return -1;
1352
	}
1353
}
1354

1355
//--------------------------------------------------------------
1356
void ofShader::printActiveUniformBlocks()  const{
1357
	if(GLEW_ARB_uniform_buffer_object) {
1358
		GLint numUniformBlocks = 0;
1359
		glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &numUniformBlocks);
1360
		ofLogNotice("ofShader") << numUniformBlocks << " uniform blocks";
1361

1362
		GLint uniformBlockMaxLength = 0;
1363
		glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformBlockMaxLength);
1364

1365
		GLchar* uniformBlockName = new GLchar[uniformBlockMaxLength];
1366
		stringstream line;
1367
		for(GLint i = 0; i < numUniformBlocks; i++) {
1368
			GLsizei length;
1369
			GLint blockBinding;
1370
			GLsizei blockDataSize;
1371
			glGetActiveUniformBlockName(program, i, uniformBlockMaxLength, &length, uniformBlockName );
1372
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_BINDING, &blockBinding );
1373
			glGetActiveUniformBlockiv(program, i, GL_UNIFORM_BLOCK_DATA_SIZE, &blockDataSize );
1374

1375
			line << " [" << i << "] ";
1376
			for(int j = 0; j < length; j++) {
1377
				line << uniformBlockName[j];
1378
			}
1379
			line << " @ index " << getUniformBlockIndex( uniformBlockName ) << ", binding point " << blockBinding << ", size " << blockDataSize << " bytes";
1380
			ofLogNotice("ofShader") << line.str();
1381
			line.str("");
1382
		}
1383
		delete [] uniformBlockName;
1384
	} else {
1385
		ofLogError("ofShader::printActiveUniformBlocks") << "Sorry, it looks like you can't run 'ARB_uniform_buffer_object'";
1386
	}
1387
}
1388

1389

1390
void ofShader::bindUniformBlock(GLuint binding, const string & name) const{
1391
	if(bLoaded){
1392
		if(GLEW_ARB_uniform_buffer_object) {
1393
			GLint index = getUniformBlockIndex(name);
1394
			if (index != -1) {
1395
				glUniformBlockBinding( program, index, binding );
1396
			}
1397
		} else {
1398
			ofLogError("ofShader::bindUniformBlock") << "Sorry, it looks like you can't run 'ARB_uniform_buffer_object'";
1399
		}
1400
	}
1401
}
1402
#endif
1403
#endif
1404

1405
//--------------------------------------------------------------
1406
void ofShader::printActiveUniforms()  const{
1407
	GLint numUniforms = 0;
1408
	glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &numUniforms);
1409
	ofLogNotice("ofShader") << numUniforms << " uniforms";
1410

1411
	GLint uniformMaxLength = 0;
1412
	glGetProgramiv(program, GL_ACTIVE_UNIFORM_MAX_LENGTH, &uniformMaxLength);
1413

1414
	GLint count = -1;
1415
	GLenum type = 0;
1416
	GLchar* uniformName = new GLchar[uniformMaxLength];
1417
	for(GLint i = 0; i < numUniforms; i++) {
1418
		stringstream line;
1419
		GLsizei length;
1420
		GLint location;
1421
		glGetActiveUniform(program, i, uniformMaxLength, &length, &count, &type, uniformName);
1422
		location = glGetUniformLocation(program, uniformName);
1423
		if (location == -1) continue; // ignore uniform blocks
1424

1425
		line << "[" << location << "] ";
1426
		for(int j = 0; j < length; j++) {
1427
			line << uniformName[j];
1428
		}
1429
		line << " @ index " << location;
1430
		ofLogNotice("ofShader") << line.str();
1431
	}
1432
	delete[] uniformName;
1433
}
1434

1435
//--------------------------------------------------------------
1436
void ofShader::printActiveAttributes()  const{
1437
	GLint numAttributes = 0;
1438
	glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numAttributes);
1439
	ofLogNotice("ofShader") << numAttributes << " attributes";
1440

1441
	GLint attributeMaxLength = 0;
1442
	glGetProgramiv(program, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &attributeMaxLength);
1443

1444
	GLint count = -1;
1445
	GLenum type = 0;
1446
	GLchar* attributeName = new GLchar[attributeMaxLength];
1447
	stringstream line;
1448
	for(GLint i = 0; i < numAttributes; i++) {
1449
		GLsizei length;
1450
		glGetActiveAttrib(program, i, attributeMaxLength, &length, &count, &type, attributeName);
1451
		line << " [" << i << "] ";
1452
		for(int j = 0; j < length; j++) {
1453
			line << attributeName[j];
1454
		}
1455
		line << " @ index " << getAttributeLocation(attributeName);
1456
		ofLogNotice("ofShader") << line.str();
1457
		line.str("");
1458
	}
1459
	delete [] attributeName;
1460
}
1461
	
1462
//----------------------------------------
1463
bool ofShader::setShadowUniforms( int textureLocation ) const {
1464
	if( !ofIsGLProgrammableRenderer() ) {
1465
		return false;
1466
	}
1467
	
1468
	setUniformTexture("uShadowCubeMap", ofShadow::getTextureTarget( OF_LIGHT_POINT ), ofShadow::getPointTexId(), textureLocation );
1469
	setUniformTexture("uShadowMapDirectional", ofShadow::getTextureTarget( OF_LIGHT_DIRECTIONAL ), ofShadow::getDirectionalTexId(), textureLocation+1 );
1470
	setUniformTexture("uShadowMapSpot", ofShadow::getTextureTarget( OF_LIGHT_SPOT ), ofShadow::getSpotTexId(), textureLocation+2 );
1471
	setUniformTexture("uShadowMapArea", ofShadow::getTextureTarget( OF_LIGHT_AREA ), ofShadow::getAreaTexId(), textureLocation+3 );
1472
	
1473
	for(size_t i=0;i<ofShadowsData().size();i++){
1474
		std::string idx = ofToString(i,0);
1475
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
1476
		std::string shadowAddress = "shadows["+idx+"]";
1477
		if(!shadow || !shadow->isEnabled || shadow->index < 0 ){
1478
			setUniform1f(shadowAddress+".enabled", 0 );
1479
			continue;
1480
		}
1481
		setUniform1f(shadowAddress+".enabled", 1 );
1482
		if( shadow->lightType != OF_LIGHT_POINT ) {
1483
			setUniformMatrix4f(shadowAddress+".shadowMatrix", shadow->shadowMatrix );
1484
		}
1485
		
1486
		setUniform1f(shadowAddress+".near", shadow->nearClip );
1487
		setUniform1f(shadowAddress+".far", shadow->farClip );
1488
		setUniform1f(shadowAddress+".normalBias", shadow->normalBias );
1489
		setUniform1f(shadowAddress+".bias", shadow->bias );
1490
		if( shadow->lightType != OF_LIGHT_POINT ) {
1491
			setUniform1f(shadowAddress+".sampleRadius", shadow->sampleRadius/(float)ofShadow::getDepthMapWidth(shadow->lightType) );
1492
		} else {
1493
			setUniform1f(shadowAddress+".sampleRadius", shadow->sampleRadius );
1494
		}
1495
		
1496
		setUniform3f(shadowAddress+".lightWorldPos", shadow->position );
1497
		setUniform1f(shadowAddress+".strength", shadow->strength );
1498
		setUniform3f(shadowAddress+".lightUp", shadow->up );
1499
		setUniform3f(shadowAddress+".lightRight", shadow->right );
1500
		setUniform1f(shadowAddress+".shadowType", (float)shadow->shadowType );
1501
		setUniform1i(shadowAddress+".texIndex", shadow->texIndex );
1502
	}
1503
	return true;
1504
}
1505
	
1506
//----------------------------------------
1507
bool ofShader::setPbrEnvironmentMapUniforms( int textureLocation ) const {
1508
	if( !ofIsGLProgrammableRenderer() ) {
1509
		return false;
1510
	}
1511
	
1512
	std::shared_ptr<ofCubeMap::Data> cubeMapData = ofCubeMap::getActiveData();
1513
	if( cubeMapData ) {
1514
		if( cubeMapData->bIrradianceAllocated ) {
1515
			setUniformTexture("tex_irradianceMap", GL_TEXTURE_CUBE_MAP, cubeMapData->irradianceMapId, textureLocation );
1516
		}
1517
		if(cubeMapData->bPreFilteredMapAllocated) {
1518
			setUniformTexture("tex_prefilterEnvMap", GL_TEXTURE_CUBE_MAP, cubeMapData->preFilteredMapId, textureLocation+1 );
1519
		}
1520
		if( cubeMapData->settings.useLutTex && ofCubeMap::getBrdfLutTexture().isAllocated() ) {
1521
			setUniformTexture("tex_brdfLUT", ofCubeMap::getBrdfLutTexture(), textureLocation+2 );
1522
		}
1523
	}
1524
	return true;
1525
}
1526

1527
//--------------------------------------------------------------
1528
GLuint ofShader::getProgram() const{
1529
	return program;
1530
}
1531

1532
//--------------------------------------------------------------
1533
GLuint ofShader::getShader(GLenum type) const{
1534
	auto shader = shaders.find(type);
1535
	if(shader!=shaders.end()){
1536
		return shader->second.id;
1537
	}else{
1538
		return 0;
1539
	}
1540
}
1541

1542
//--------------------------------------------------------------
1543
bool ofShader::operator==(const ofShader & other) const{
1544
	return other.program==program;
1545
}
1546

1547
//--------------------------------------------------------------
1548
bool ofShader::operator!=(const ofShader & other) const{
1549
	return other.program!=program;
1550
}
1551

1552
//--------------------------------------------------------------
1553
string ofShader::nameForType(GLenum type){
1554
	switch(type) {
1555
		case GL_VERTEX_SHADER: return "GL_VERTEX_SHADER";
1556
		case GL_FRAGMENT_SHADER: return "GL_FRAGMENT_SHADER";
1557
#ifndef TARGET_OPENGLES
1558
		case GL_GEOMETRY_SHADER_EXT: return "GL_GEOMETRY_SHADER_EXT";
1559
#ifdef glDispatchCompute
1560
		case GL_COMPUTE_SHADER: return "GL_COMPUTE_SHADER";
1561
#endif
1562
#endif
1563
		default: return "UNKNOWN SHADER TYPE";
1564
	}
1565
}
1566

1567

1568

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.