framework2

Форк
0
2019 строк · 63.8 Кб
1
#include "ofGLRenderer.h"
2
#include "ofMesh.h"
3
#include "ofPath.h"
4
#include "of3dPrimitives.h"
5
#include "ofBitmapFont.h"
6
#include "ofGLUtils.h"
7
#include "ofImage.h"
8
#include "ofFbo.h"
9
#include "ofLight.h"
10
#include "ofCamera.h"
11
#include "ofTrueTypeFont.h"
12
#include "ofNode.h"
13
#include "ofVideoBaseTypes.h"
14
#include "ofMaterial.h"
15
#include "ofVboMesh.h"
16

17
using std::shared_ptr;
18
using std::vector;
19
using std::string;
20

21
const std::string ofGLRenderer::TYPE="GL";
22

23
//----------------------------------------------------------
24
ofGLRenderer::ofGLRenderer(const ofAppBaseWindow * _window)
25
:matrixStack(_window)
26
,graphics3d(this){
27
	bBackgroundAuto = true;
28

29
	linePoints.resize(2);
30
	rectPoints.resize(4);
31
	triPoints.resize(3);
32
	normalsEnabled = false;
33
	lightingEnabled = false;
34
	materialBound = false;
35
	alphaMaskTextureTarget = GL_TEXTURE_2D;
36
	window = _window;
37
	currentFramebufferId = 0;
38
	defaultFramebufferId = 0;
39
	path.setMode(ofPath::POLYLINES);
40
	path.setUseShapeColor(false);
41
}
42

43
void ofGLRenderer::setup(){
44
#ifdef TARGET_OPENGLES
45
	// OpenGL ES might have set a default frame buffer for
46
	// MSAA rendering to the window, bypassing ofFbo, so we
47
	// can't trust ofFbo to have correctly tracked the bind
48
	// state. Therefore, we are forced to use the slower glGet() method
49
	// to be sure to get the correct default framebuffer.
50
	GLint currentFrameBuffer;
51
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFrameBuffer);
52
	defaultFramebufferId = currentFrameBuffer;
53
    currentFramebufferId = defaultFramebufferId;
54
#endif
55
	setupGraphicDefaults();
56
	viewport();
57
	setupScreenPerspective();
58
}
59

60
void ofGLRenderer::startRender(){
61
	currentFramebufferId = defaultFramebufferId;
62
	framebufferIdStack.push_back(defaultFramebufferId);
63
	matrixStack.setRenderSurface(*window);
64
	viewport();
65
	// to do non auto clear on PC for now - we do something like "single" buffering --
66
	// it's not that pretty but it work for the most part
67

68
	#ifdef TARGET_WIN32
69
	if (getBackgroundAuto() == false){
70
		glDrawBuffer (GL_FRONT);
71
	}
72
	#endif
73

74
	if ( getBackgroundAuto() ){// || ofGetFrameNum() < 3){
75
		background(currentStyle.bgColor);
76
	}
77
}
78

79
void ofGLRenderer::finishRender(){
80
	matrixStack.clearStacks();
81
	framebufferIdStack.clear();
82
}
83

84
//----------------------------------------------------------
85
void ofGLRenderer::draw(const ofMesh & vertexData, ofPolyRenderMode renderType, bool useColors, bool useTextures, bool useNormals) const{
86
		if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->startSmoothing();
87
#ifndef TARGET_OPENGLES
88
		glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
89
		if(vertexData.getNumVertices()){
90
			glEnableClientState(GL_VERTEX_ARRAY);
91
			glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &vertexData.getVerticesPointer()->x);
92
		}
93
		if(vertexData.getNumNormals() && useNormals){
94
			glEnableClientState(GL_NORMAL_ARRAY);
95
			glNormalPointer(GL_FLOAT, sizeof(glm::vec3), &vertexData.getNormalsPointer()->x);
96
		}
97
		if(vertexData.getNumColors() && useColors){
98
			glEnableClientState(GL_COLOR_ARRAY);
99
			glColorPointer(4,GL_FLOAT, sizeof(ofFloatColor), &vertexData.getColorsPointer()->r);
100
		}
101

102
		if(vertexData.getNumTexCoords() && useTextures){
103
			if(textureLocationsEnabled.size() == 0){
104
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
105
					glTexCoordPointer(2, GL_FLOAT, sizeof(glm::vec2), &vertexData.getTexCoordsPointer()->x);
106
			}else{
107
				std::set<int>::iterator textureLocation = textureLocationsEnabled.begin();
108
				for(;textureLocation!=textureLocationsEnabled.end();textureLocation++){
109
					glActiveTexture(GL_TEXTURE0+*textureLocation);
110
					glClientActiveTexture(GL_TEXTURE0+*textureLocation);
111
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
112
					glTexCoordPointer(2, GL_FLOAT, sizeof(glm::vec2), &vertexData.getTexCoordsPointer()->x);
113
				}
114
				glActiveTexture(GL_TEXTURE0);
115
				glClientActiveTexture(GL_TEXTURE0);
116
			}
117
		}
118

119
		if(vertexData.getNumIndices()){
120
	// This is never executed right now but this branch of the ifdef should be used for GLES 3 so let's keep it for future uses
121
	#ifdef TARGET_OPENGLES
122
			glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer());
123
	#else
124
			glDrawElements(ofGetGLPrimitiveMode(vertexData.getMode()), vertexData.getNumIndices(),GL_UNSIGNED_INT,vertexData.getIndexPointer());
125
	#endif
126
		}else{
127
			glDrawArrays(ofGetGLPrimitiveMode(vertexData.getMode()), 0, vertexData.getNumVertices());
128
		}
129

130
		if(vertexData.getNumColors() && useColors){
131
			glDisableClientState(GL_COLOR_ARRAY);
132
		}
133
		if(vertexData.getNumNormals() && useNormals){
134
			glDisableClientState(GL_NORMAL_ARRAY);
135
		}
136
		if(vertexData.getNumTexCoords() && useTextures){
137
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
138
		}
139
		glPolygonMode(GL_FRONT_AND_BACK, currentStyle.bFill ?  GL_FILL : GL_LINE);
140
#else
141
		if(vertexData.getNumVertices()){
142
			glEnableClientState(GL_VERTEX_ARRAY);
143
			glVertexPointer(3, GL_FLOAT, sizeof(typename ofMesh::VertexType), vertexData.getVerticesPointer());
144
		}
145
		if(vertexData.getNumNormals() && useNormals){
146
			glEnableClientState(GL_NORMAL_ARRAY);
147
			glNormalPointer(GL_FLOAT, 0, vertexData.getNormalsPointer());
148
		}
149
		if(vertexData.getNumColors() && useColors){
150
			glEnableClientState(GL_COLOR_ARRAY);
151
			glColorPointer(4,GL_FLOAT, sizeof(ofFloatColor), vertexData.getColorsPointer());
152
		}
153

154
		if(vertexData.getNumTexCoords() && useTextures){
155
			if(textureLocationsEnabled.size() == 0){
156
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
157
					glTexCoordPointer(2, GL_FLOAT, sizeof(typename ofMesh::TexCoordType), &vertexData.getTexCoordsPointer()->x);
158
			}else{
159
				std::set<int>::iterator textureLocation = textureLocationsEnabled.begin();
160
				for(;textureLocation!=textureLocationsEnabled.end();textureLocation++){
161
					glActiveTexture(GL_TEXTURE0+*textureLocation);
162
					glClientActiveTexture(GL_TEXTURE0+*textureLocation);
163
					glEnableClientState(GL_TEXTURE_COORD_ARRAY);
164
					glTexCoordPointer(2, GL_FLOAT, sizeof(typename ofMesh::TexCoordType), &vertexData.getTexCoordsPointer()->x);
165
				}
166
				glActiveTexture(GL_TEXTURE0);
167
				glClientActiveTexture(GL_TEXTURE0);
168
			}
169
		}
170

171
		GLenum drawMode;
172
		switch(renderType){
173
		case OF_MESH_POINTS:
174
			drawMode = GL_POINTS;
175
			break;
176
		case OF_MESH_WIREFRAME:
177
			drawMode = GL_LINES;
178
			break;
179
		case OF_MESH_FILL:
180
			drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
181
			break;
182
		default:
183
			drawMode = ofGetGLPrimitiveMode(vertexData.getMode());
184
			break;
185
		}
186

187
		if(vertexData.getNumIndices()){
188
			glDrawElements(drawMode, vertexData.getNumIndices(),GL_UNSIGNED_SHORT,vertexData.getIndexPointer());
189
		}else{
190
			glDrawArrays(drawMode, 0, vertexData.getNumVertices());
191
		}
192
		if(vertexData.getNumColors() && useColors){
193
			glDisableClientState(GL_COLOR_ARRAY);
194
		}
195
		if(vertexData.getNumNormals() && useNormals){
196
			glDisableClientState(GL_NORMAL_ARRAY);
197
		}
198
		if(vertexData.getNumTexCoords() && useTextures){
199
			glDisableClientState(GL_TEXTURE_COORD_ARRAY);
200
		}
201
#endif
202
		if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->endSmoothing();
203
}
204

205
//----------------------------------------------------------
206
void ofGLRenderer::draw(const ofVboMesh & mesh, ofPolyRenderMode renderType) const{
207
	drawInstanced(mesh,renderType,1);
208
}
209

210
//----------------------------------------------------------
211
void ofGLRenderer::drawInstanced(const ofVboMesh & mesh, ofPolyRenderMode renderType, int primCount) const{
212
	if(mesh.getNumVertices()==0) return;
213
	GLuint mode = ofGetGLPrimitiveMode(mesh.getMode());
214
#ifndef TARGET_OPENGLES
215
	glPolygonMode(GL_FRONT_AND_BACK, ofGetGLPolyMode(renderType));
216
	if(mesh.getNumIndices() && renderType!=OF_MESH_POINTS){
217
		if (primCount <= 1) {
218
			drawElements(mesh.getVbo(),mode,mesh.getNumIndices());
219
		} else {
220
			drawElementsInstanced(mesh.getVbo(),mode,mesh.getNumIndices(),primCount);
221
		}
222
	}else{
223
		if (primCount <= 1) {
224
			draw(mesh.getVbo(),mode,0,mesh.getNumVertices());
225
		} else {
226
			drawInstanced(mesh.getVbo(),mode,0,mesh.getNumVertices(),primCount);
227
		}
228
	}
229
	glPolygonMode(GL_FRONT_AND_BACK, currentStyle.bFill ?  GL_FILL : GL_LINE);
230
#else
231
	if(renderType == OF_MESH_POINTS){
232
		draw(mesh.getVbo(),GL_POINTS,0,mesh.getNumVertices());
233
	}else if(renderType == OF_MESH_WIREFRAME){
234
		if(mesh.getNumIndices()){
235
			drawElements(mesh.getVbo(),GL_LINES,mesh.getNumIndices());
236
		}else{
237
			draw(mesh.getVbo(),GL_LINES,0,mesh.getNumVertices());
238
		}
239
	}else{
240
		if(mesh.getNumIndices()){
241
			drawElements(mesh.getVbo(),mode,mesh.getNumIndices());
242
		}else{
243
			draw(mesh.getVbo(),mode,0,mesh.getNumVertices());
244
		}
245
	}
246
#endif
247
}
248

249
//----------------------------------------------------------
250
void ofGLRenderer::draw( const of3dPrimitive& model, ofPolyRenderMode renderType)  const{
251
	const_cast<ofGLRenderer*>(this)->pushMatrix();
252
	const_cast<ofGLRenderer*>(this)->multMatrix(model.getGlobalTransformMatrix());
253
	if(model.isUsingVbo()){
254
		draw(static_cast<const ofVboMesh&>(model.getMesh()),renderType);
255
	}else{
256
		draw(model.getMesh(),renderType);
257
	}
258
	const_cast<ofGLRenderer*>(this)->popMatrix();
259
}
260

261
//----------------------------------------------------------
262
void ofGLRenderer::draw(const ofNode& node) const{
263
	const_cast<ofGLRenderer*>(this)->pushMatrix();
264
	const_cast<ofGLRenderer*>(this)->multMatrix(node.getGlobalTransformMatrix());
265
	node.customDraw(this);
266
	const_cast<ofGLRenderer*>(this)->popMatrix();
267
}
268

269
//----------------------------------------------------------
270
void ofGLRenderer::draw(const ofPolyline & poly) const{
271
	if(!poly.getVertices().empty()) {
272
		// use smoothness, if requested:
273
		if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->startSmoothing();
274

275
		glEnableClientState(GL_VERTEX_ARRAY);
276
		glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &poly.getVertices()[0].x);
277
		glDrawArrays(poly.isClosed()?GL_LINE_LOOP:GL_LINE_STRIP, 0, poly.size());
278

279
		// use smoothness, if requested:
280
		if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->endSmoothing();
281
	}
282
}
283

284
//----------------------------------------------------------
285
void ofGLRenderer::draw(const ofPath & shape) const{
286
	ofColor prevColor;
287
	if(shape.getUseShapeColor()){
288
		prevColor = currentStyle.color;
289
	}
290
	ofGLRenderer * mut_this = const_cast<ofGLRenderer*>(this);
291
	if(shape.isFilled()){
292
		const ofMesh & mesh = shape.getTessellation();
293
		if(shape.getUseShapeColor()){
294
			mut_this->setColor( shape.getFillColor(),shape.getFillColor().a);
295
		}
296
		draw(mesh,OF_MESH_FILL);
297
	}
298
	if(shape.hasOutline()){
299
		float lineWidth = currentStyle.lineWidth;
300
		if(shape.getUseShapeColor()){
301
			mut_this->setColor( shape.getStrokeColor(), shape.getStrokeColor().a);
302
		}
303
		mut_this->setLineWidth( shape.getStrokeWidth() );
304
		const vector<ofPolyline> & outlines = shape.getOutline();
305
		for(int i=0; i<(int)outlines.size(); i++)
306
			draw(outlines[i]);
307
		mut_this->setLineWidth(lineWidth);
308
	}
309
	if(shape.getUseShapeColor()){
310
		mut_this->setColor(prevColor);
311
	}
312
}
313

314
//----------------------------------------------------------
315
void ofGLRenderer::draw(const ofImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
316
	if(image.isUsingTexture()){
317
		const ofTexture& tex = image.getTexture();
318
		if(tex.isAllocated()) {
319
			const_cast<ofGLRenderer*>(this)->bind(tex,0);
320
			draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
321
			const_cast<ofGLRenderer*>(this)->unbind(tex,0);
322
		} else {
323
			ofLogWarning("ofGLRenderer") << "drawing an unallocated texture";
324
		}
325
	}
326
}
327

328
//----------------------------------------------------------
329
void ofGLRenderer::draw(const ofFloatImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
330
	if(image.isUsingTexture()){
331
		const ofTexture& tex = image.getTexture();
332
		if(tex.isAllocated()) {
333
			const_cast<ofGLRenderer*>(this)->bind(tex,0);
334
			draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
335
			const_cast<ofGLRenderer*>(this)->unbind(tex,0);
336
		} else {
337
			ofLogWarning("ofGLRenderer") << "draw(): texture is not allocated";
338
		}
339
	}
340
}
341

342
//----------------------------------------------------------
343
void ofGLRenderer::draw(const ofShortImage & image, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
344
	if(image.isUsingTexture()){
345
		const ofTexture& tex = image.getTexture();
346
		if(tex.isAllocated()) {
347
			const_cast<ofGLRenderer*>(this)->bind(tex,0);
348
			draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
349
			const_cast<ofGLRenderer*>(this)->unbind(tex,0);
350
		} else {
351
			ofLogWarning("ofGLRenderer") << "draw(): texture is not allocated";
352
		}
353
	}
354
}
355

356
//----------------------------------------------------------
357
void ofGLRenderer::draw(const ofTexture & tex, float x, float y, float z, float w, float h, float sx, float sy, float sw, float sh) const{
358
	if(tex.isAllocated()) {
359
		const_cast<ofGLRenderer*>(this)->bind(tex,0);
360
		draw(tex.getMeshForSubsection(x,y,z,w,h,sx,sy,sw,sh,isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
361
		const_cast<ofGLRenderer*>(this)->unbind(tex,0);
362
	} else {
363
		ofLogWarning("ofGLRenderer") << "draw(): texture is not allocated";
364
	}
365
}
366

367
//----------------------------------------------------------
368
void ofGLRenderer::draw(const ofBaseVideoDraws & video, float x, float y, float w, float h) const{
369
	if(video.isInitialized() && video.isUsingTexture()){
370
		const_cast<ofGLRenderer*>(this)->bind(video);
371
		draw(video.getTexture().getMeshForSubsection(x,y,0,w,h,0,0,video.getWidth(),video.getHeight(),isVFlipped(),currentStyle.rectMode),OF_MESH_FILL,false,true,false);
372
		const_cast<ofGLRenderer*>(this)->unbind(video);
373
	}
374
}
375

376
//----------------------------------------------------------
377
void ofGLRenderer::draw(const ofVbo & vbo, GLuint drawMode, int first, int total) const{
378
	if(vbo.getUsingVerts()) {
379
		vbo.bind();
380
		glDrawArrays(drawMode, first, total);
381
		vbo.unbind();
382
	}
383
}
384

385
//----------------------------------------------------------
386
void ofGLRenderer::drawElements(const ofVbo & vbo, GLuint drawMode, int amt, int offsetelements) const{
387
	if(vbo.getUsingVerts()) {
388
		vbo.bind();
389
#ifdef TARGET_OPENGLES
390
		glDrawElements(drawMode, amt, GL_UNSIGNED_SHORT, (void*)(sizeof(ofIndexType) * offsetelements));
391
#else
392
		glDrawElements(drawMode, amt, GL_UNSIGNED_INT, (void*)(sizeof(ofIndexType) * offsetelements));
393
#endif
394
		vbo.unbind();
395
	}
396
}
397

398
//----------------------------------------------------------
399
void ofGLRenderer::drawInstanced(const ofVbo & vbo, GLuint drawMode, int first, int total, int primCount) const{
400
	if(vbo.getUsingVerts()) {
401
		vbo.bind();
402
#ifdef TARGET_OPENGLES
403
		// todo: activate instancing once OPENGL ES supports instancing, starting with version 3.0
404
		// unfortunately there is currently no easy way within oF to query the current OpenGL version.
405
		// https://www.khronos.org/opengles/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
406
		ofLogWarning("ofVbo") << "drawInstanced(): hardware instancing is not supported on OpenGL ES < 3.0";
407
		// glDrawArraysInstanced(drawMode, first, total, primCount);
408
#else
409
		glDrawArraysInstanced(drawMode, first, total, primCount);
410
#endif
411
		vbo.unbind();
412
	}
413
}
414

415
//----------------------------------------------------------
416
void ofGLRenderer::drawElementsInstanced(const ofVbo & vbo, GLuint drawMode, int amt, int primCount) const{
417
	if(vbo.getUsingVerts()) {
418
		vbo.bind();
419
#ifdef TARGET_OPENGLES
420
		// todo: activate instancing once OPENGL ES supports instancing, starting with version 3.0
421
		// unfortunately there is currently no easy way within oF to query the current OpenGL version.
422
		// https://www.khronos.org/opengles/sdk/docs/man3/xhtml/glDrawElementsInstanced.xml
423
		ofLogWarning("ofVbo") << "drawElementsInstanced(): hardware instancing is not supported on OpenGL ES < 3.0";
424
		// glDrawElementsInstanced(drawMode, amt, GL_UNSIGNED_SHORT, nullptr, primCount);
425
#else
426
		glDrawElementsInstanced(drawMode, amt, GL_UNSIGNED_INT, nullptr, primCount);
427
#endif
428
		vbo.unbind();
429
	}
430
}
431

432
//----------------------------------------------------------
433
ofPath & ofGLRenderer::getPath(){
434
	return path;
435
}
436

437
//----------------------------------------------------------
438
void ofGLRenderer::bind(const ofBaseVideoDraws & video){
439
	if(video.isInitialized() && video.isUsingTexture()){
440
		bind(video.getTexture(),0);
441
	}
442
}
443

444
//----------------------------------------------------------
445
void ofGLRenderer::unbind(const ofBaseVideoDraws & video){
446
	if(video.isInitialized() && video.isUsingTexture()){
447
		video.getTexture().unbind();
448
	}
449
}
450

451
//----------------------------------------------------------
452
void ofGLRenderer::bind(const ofShader & shader){
453
	glUseProgram(shader.getProgram());
454
}
455

456
//----------------------------------------------------------
457
void ofGLRenderer::unbind(const ofShader & shader){
458
	glUseProgram(0);
459
}
460

461
//----------------------------------------------------------
462
void ofGLRenderer::begin(const ofFbo & fbo, ofFboMode mode){
463
	pushView();
464
	pushStyle();
465
    if(mode & OF_FBOMODE_MATRIXFLIP){
466
        matrixStack.setRenderSurface(fbo);
467
    }else{
468
        matrixStack.setRenderSurfaceNoMatrixFlip(fbo);
469
    }
470
	viewport();
471
    if(mode & OF_FBOMODE_PERSPECTIVE){
472
		setupScreenPerspective();
473
	}else{
474
		glm::mat4 m = glm::mat4(1.0);
475
		glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(m));
476
		m =  matrixStack.getOrientationMatrixInverse() * m;
477
		ofMatrixMode currentMode = matrixStack.getCurrentMatrixMode();
478
		matrixStack.matrixMode(OF_MATRIX_PROJECTION);
479
		matrixStack.loadMatrix(m);
480
		glMatrixMode(GL_PROJECTION);
481
		glLoadMatrixf(glm::value_ptr(matrixStack.getProjectionMatrix()));
482
		matrixMode(currentMode);
483
	}
484
	bind(fbo);
485
}
486

487
//----------------------------------------------------------
488
void ofGLRenderer::end(const ofFbo & fbo){
489
	unbind(fbo);
490
	matrixStack.setRenderSurface(*window);
491
	popStyle();
492
	popView();
493
}
494

495
//----------------------------------------------------------
496
void ofGLRenderer::bind(const ofFbo & fbo){
497
	if (currentFramebufferId == fbo.getId()){
498
		ofLogWarning() << "Framebuffer with id: " << fbo.getId() << " cannot be bound onto itself. \n" <<
499
			"Most probably you forgot to end() the current framebuffer before calling begin() again or you forgot to allocate() before calling begin().";
500
		return;
501
	}
502
	// this method could just as well have been placed in ofBaseGLRenderer
503
	// and shared over both programmable and fixed function renderer.
504
	// I'm keeping it here, so that if we want to do more fancyful
505
	// named framebuffers with GL 4.5+, we can have
506
	// different implementations.
507
	framebufferIdStack.push_back(currentFramebufferId);
508
	currentFramebufferId = fbo.getId();
509
	glBindFramebuffer(GL_FRAMEBUFFER, currentFramebufferId);
510
}
511

512
#ifndef TARGET_OPENGLES
513
//----------------------------------------------------------
514
void ofGLRenderer::bindForBlitting(const ofFbo & fboSrc, ofFbo & fboDst, int attachmentPoint){
515
	if (currentFramebufferId == fboSrc.getId()){
516
		ofLogWarning() << "Framebuffer with id: " << fboSrc.getId() << " cannot be bound onto itself. \n" <<
517
			"Most probably you forgot to end() the current framebuffer before calling getTexture().";
518
		return;
519
	}
520
	// this method could just as well have been placed in ofBaseGLRenderer
521
	// and shared over both programmable and fixed function renderer.
522
	// I'm keeping it here, so that if we want to do more fancyful
523
	// named framebuffers with GL 4.5+, we can have
524
	// different implementations.
525
	framebufferIdStack.push_back(currentFramebufferId);
526
	currentFramebufferId = fboSrc.getId();
527
	glBindFramebuffer(GL_READ_FRAMEBUFFER, currentFramebufferId);
528
	glReadBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);
529
	glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fboDst.getIdDrawBuffer());
530
	glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachmentPoint);
531
}
532
#endif
533

534
//----------------------------------------------------------
535
void ofGLRenderer::unbind(const ofFbo & fbo){
536
	if(framebufferIdStack.empty()){
537
		ofLogError() << "unbalanced fbo bind/unbind binding default framebuffer";
538
		currentFramebufferId = defaultFramebufferId;
539
	}else{
540
		currentFramebufferId = framebufferIdStack.back();
541
		framebufferIdStack.pop_back();
542
	}
543
	glBindFramebuffer(GL_FRAMEBUFFER, currentFramebufferId);
544
	fbo.flagDirty();
545
}
546

547
//----------------------------------------------------------
548
void ofGLRenderer::bind(const ofBaseMaterial & material){
549
	ofFloatColor diffuse = material.getDiffuseColor();
550
	ofFloatColor specular = material.getSpecularColor();
551
	ofFloatColor ambient = material.getAmbientColor();
552
	ofFloatColor emissive = material.getEmissiveColor();
553
	float shininess = material.getShininess();
554
	glDisable(GL_COLOR_MATERIAL);
555
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &diffuse.r);
556
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &specular.r);
557
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &ambient.r);
558
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &emissive.r);
559
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &shininess);
560
	materialBound = true;
561
}
562

563
//----------------------------------------------------------
564
void ofGLRenderer::unbind(const ofBaseMaterial &){
565
	// Set default material colors and properties
566
	ofMaterial::Data defaultData;
567
	glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, &defaultData.diffuse.r);
568
	glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &defaultData.specular.r);
569
	glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, &defaultData.ambient.r);
570
	glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, &defaultData.emissive.r);
571
	glMaterialfv(GL_FRONT_AND_BACK, GL_SHININESS, &defaultData.shininess);
572
	// Re-enable global color as material ambient and diffuse
573
	materialBound = false;
574
	if(lightingEnabled){
575
		setColor(currentStyle.color);
576
	}
577
}
578

579
// does nothing, only programmable renderer supported
580
//----------------------------------------------------------
581
void ofGLRenderer::bind(const ofShadow & shadow) {
582
	ofLogWarning("ofGLRenderer::bind(const ofShadow & shadow) : shadows are only supported via programmable renderer");
583
};
584
//----------------------------------------------------------
585
void ofGLRenderer::bind(const ofShadow & shadow, GLenum aCubeFace) {
586
	ofLogWarning("ofGLRenderer::bind(const ofShadow & shadow) : shadows are only supported via programmable renderer");
587
};
588

589
// does nothing, only programmable renderer supported
590
//----------------------------------------------------------
591
void ofGLRenderer::unbind(const ofShadow & shadow) {};
592
//----------------------------------------------------------
593
void ofGLRenderer::unbind(const ofShadow & shadow, GLenum aCubeFace) {};
594

595
//----------------------------------------------------------
596
void ofGLRenderer::bind(const ofTexture & texture, int location){
597
	//we could check if it has been allocated - but we don't do that in draw()
598
	if(texture.getAlphaMask()){
599
		setAlphaMaskTex(*texture.getAlphaMask());
600
	}
601
	enableTextureTarget(texture,location);
602

603

604
	if(ofGetUsingNormalizedTexCoords()) {
605
		matrixMode(OF_MATRIX_TEXTURE);
606
		pushMatrix();
607
		glm::mat4 m = glm::mat4(1.0);
608

609
#ifndef TARGET_OPENGLES
610
		if(texture.texData.textureTarget == GL_TEXTURE_RECTANGLE_ARB)
611
			m = glm::scale(m, glm::vec3(texture.texData.width, texture.texData.height, 1.0f));
612
		else
613
#endif
614
			m = glm::scale(m, glm::vec3(texture.texData.width / texture.texData.tex_w, texture.texData.height / texture.texData.tex_h, 1.0f));
615

616
		loadMatrix(m);
617
		matrixMode(OF_MATRIX_MODELVIEW);
618
	}
619
	if(texture.isUsingTextureMatrix()){
620
		matrixMode(OF_MATRIX_TEXTURE);
621
		if(!ofGetUsingNormalizedTexCoords()) pushMatrix();
622
		multMatrix(texture.getTextureMatrix());
623
		matrixMode(OF_MATRIX_MODELVIEW);
624
	}
625
}
626

627
//----------------------------------------------------------
628
void ofGLRenderer::unbind(const ofTexture & texture, int location){
629
	disableTextureTarget(texture.texData.textureTarget,location);
630
	if(texture.getAlphaMask()){
631
		disableAlphaMask();
632
	}
633

634
	if(texture.isUsingTextureMatrix() || ofGetUsingNormalizedTexCoords()) {
635
		matrixMode(OF_MATRIX_TEXTURE);
636
		popMatrix();
637
		matrixMode(OF_MATRIX_MODELVIEW);
638
	}
639
}
640

641
//----------------------------------------------------------
642
void ofGLRenderer::bind(const ofCamera & camera, const ofRectangle & _viewport){
643
	pushView();
644
	viewport(_viewport);
645
	setOrientation(matrixStack.getOrientation(),camera.isVFlipped());
646
	matrixMode(OF_MATRIX_PROJECTION);
647
	loadMatrix(camera.getProjectionMatrix(_viewport));
648
	matrixMode(OF_MATRIX_MODELVIEW);
649
	loadViewMatrix(camera.getModelViewMatrix());
650
}
651

652
//----------------------------------------------------------
653
void ofGLRenderer::unbind(const ofCamera & camera){
654
	popView();
655
}
656

657
//----------------------------------------------------------
658
void ofGLRenderer::pushView() {
659
	getCurrentViewport();
660

661
	glm::mat4 m = glm::mat4(1.0);
662
	ofMatrixMode matrixMode = matrixStack.getCurrentMatrixMode();
663
	glGetFloatv(GL_PROJECTION_MATRIX,glm::value_ptr(m));
664
	matrixStack.matrixMode(OF_MATRIX_PROJECTION);
665
	matrixStack.loadMatrix(m);
666
	glGetFloatv(GL_MODELVIEW_MATRIX,glm::value_ptr(m));
667
	matrixStack.matrixMode(OF_MATRIX_MODELVIEW);
668
	matrixStack.loadMatrix(m);
669

670
	matrixStack.matrixMode(matrixMode);
671

672
	matrixStack.pushView();
673
}
674

675

676
//----------------------------------------------------------
677
void ofGLRenderer::popView() {
678
	matrixStack.popView();
679

680
	ofMatrixMode currentMode = matrixStack.getCurrentMatrixMode();
681

682
	matrixMode(OF_MATRIX_PROJECTION);
683
	loadMatrix(matrixStack.getProjectionMatrix());
684

685
	matrixMode(OF_MATRIX_MODELVIEW);
686
	loadMatrix(matrixStack.getModelViewMatrix());
687

688
	matrixMode(currentMode);
689

690
	viewport(matrixStack.getCurrentViewport());
691
}
692

693

694
//----------------------------------------------------------
695
void ofGLRenderer::viewport(ofRectangle viewport_){
696
	viewport(viewport_.x, viewport_.y, viewport_.width, viewport_.height, isVFlipped());
697
}
698

699
//----------------------------------------------------------
700
void ofGLRenderer::viewport(float x, float y, float width, float height, bool vflip) {
701
	matrixStack.viewport(x,y,width,height,vflip);
702
	ofRectangle nativeViewport = matrixStack.getNativeViewport();
703
	glViewport(nativeViewport.x,nativeViewport.y,nativeViewport.width,nativeViewport.height);
704
}
705

706
//----------------------------------------------------------
707
ofRectangle ofGLRenderer::getCurrentViewport() const{
708
	getNativeViewport();
709
	return matrixStack.getCurrentViewport();
710
}
711

712
//----------------------------------------------------------
713
ofRectangle ofGLRenderer::getNativeViewport() const{
714
	GLint viewport[4];					// Where The Viewport Values Will Be Stored
715
	glGetIntegerv(GL_VIEWPORT, viewport);
716

717
	ofGLRenderer * mutRenderer = const_cast<ofGLRenderer*>(this);
718
	ofRectangle nativeViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
719
	mutRenderer->matrixStack.nativeViewport(nativeViewport);
720
	return nativeViewport;
721
}
722

723
//----------------------------------------------------------
724
int ofGLRenderer::getViewportWidth() const{
725
	return getCurrentViewport().width;
726
}
727

728
//----------------------------------------------------------
729
int ofGLRenderer::getViewportHeight() const{
730
	return getCurrentViewport().height;
731
}
732

733
//----------------------------------------------------------
734
void ofGLRenderer::setCoordHandedness(ofHandednessType handedness) {
735

736
}
737

738
//----------------------------------------------------------
739
ofHandednessType ofGLRenderer::getCoordHandedness() const{
740
	return matrixStack.getHandedness();
741
}
742

743
//----------------------------------------------------------
744
void ofGLRenderer::setOrientation(ofOrientation orientation, bool vFlip){
745
	matrixStack.setOrientation(orientation,vFlip);
746
}
747

748
//----------------------------------------------------------
749
bool ofGLRenderer::isVFlipped() const{
750
	return matrixStack.isVFlipped();
751
}
752

753
//----------------------------------------------------------
754
bool ofGLRenderer::texturesNeedVFlip() const{
755
	return matrixStack.customMatrixNeedsFlip();
756
}
757

758
//----------------------------------------------------------
759
void ofGLRenderer::setupScreenPerspective(float width, float height, float fov, float nearDist, float farDist) {
760
	float viewW, viewH;
761
	if(width<0 || height<0){
762
		ofRectangle currentViewport = getCurrentViewport();
763

764
		viewW = currentViewport.width;
765
		viewH = currentViewport.height;
766
	}else{
767
		viewW = width;
768
		viewH = height;
769
	}
770

771
	float eyeX = viewW / 2;
772
	float eyeY = viewH / 2;
773
	float halfFov = glm::pi<float>() * fov / 360.0f;
774
	float theTan = tanf(halfFov);
775
	float dist = eyeY / theTan;
776
	float aspect = (float) viewW / viewH;
777

778
	if(nearDist == 0) nearDist = dist / 10.0f;
779
	if(farDist == 0) farDist = dist * 10.0f;
780

781

782
	matrixMode(OF_MATRIX_PROJECTION);
783
	glm::mat4 persp = glm::perspective(ofDegToRad(fov), aspect, nearDist, farDist);
784
	loadMatrix( persp );
785

786
	matrixMode(OF_MATRIX_MODELVIEW);
787
	glm::mat4 lookAtMat = glm::lookAt( glm::vec3(eyeX, eyeY, dist),  glm::vec3(eyeX, eyeY, 0),  glm::vec3(0, 1, 0) );
788
	loadViewMatrix(lookAtMat);
789
}
790

791
//----------------------------------------------------------
792
void ofGLRenderer::setupScreenOrtho(float width, float height, float nearDist, float farDist) {
793
	float viewW, viewH;
794
	if(width<0 || height<0){
795
		ofRectangle currentViewport = getCurrentViewport();
796

797
		viewW = currentViewport.width;
798
		viewH = currentViewport.height;
799
	}else{
800
		viewW = width;
801
		viewH = height;
802
	}
803

804
	glm::mat4 orthoMat = glm::ortho(0.f, viewW, 0.f, viewH, nearDist, farDist);
805

806
	matrixMode(OF_MATRIX_PROJECTION);
807
	loadMatrix(orthoMat); // make ortho our new projection matrix.
808

809
	matrixMode(OF_MATRIX_MODELVIEW);
810
	loadViewMatrix(glm::mat4(1.0));
811

812
}
813

814
//----------------------------------------------------------
815
//Resets openGL parameters back to OF defaults
816
void ofGLRenderer::setupGraphicDefaults(){
817
	glEnableClientState(GL_VERTEX_ARRAY);
818
	glDisableClientState(GL_NORMAL_ARRAY);
819
	glDisableClientState(GL_COLOR_ARRAY);
820
	glDisableClientState(GL_TEXTURE_COORD_ARRAY);
821
	setStyle(ofStyle());
822
	path.setMode(ofPath::POLYLINES);
823
	path.setUseShapeColor(false);
824
}
825

826
//----------------------------------------------------------
827
void ofGLRenderer::setupScreen(){
828
	setupScreenPerspective();	// assume defaults
829
}
830

831
//----------------------------------------------------------
832
void ofGLRenderer::setCircleResolution(int res){
833
	if((int)circlePolyline.size()!=res+1){
834
		circlePolyline.clear();
835
		circlePolyline.arc(0,0,0,1,1,0,360,res);
836
		circlePoints.resize(circlePolyline.size());
837
		path.setCircleResolution(res);
838
	}
839
	currentStyle.circleResolution = res;
840
}
841

842
void ofGLRenderer::setPolyMode(ofPolyWindingMode mode){
843
	currentStyle.polyMode = mode;
844
	path.setPolyWindingMode(mode);
845
}
846

847
//our openGL wrappers
848
//----------------------------------------------------------
849
void ofGLRenderer::pushMatrix(){
850
	glPushMatrix();
851
}
852

853
//----------------------------------------------------------
854
void ofGLRenderer::popMatrix(){
855
	glPopMatrix();
856
}
857

858
//----------------------------------------------------------
859
void ofGLRenderer::translate(const glm::vec3& p){
860
	glTranslatef(p.x, p.y, p.z);
861
}
862

863
//----------------------------------------------------------
864
void ofGLRenderer::translate(float x, float y, float z){
865
	glTranslatef(x, y, z);
866
}
867

868
//----------------------------------------------------------
869
void ofGLRenderer::scale(float xAmnt, float yAmnt, float zAmnt){
870
	glScalef(xAmnt, yAmnt, zAmnt);
871
}
872

873
//----------------------------------------------------------
874
void ofGLRenderer::rotateDeg(float degrees, float vecX, float vecY, float vecZ){
875
	glRotatef(degrees, vecX, vecY, vecZ);
876
}
877

878
//----------------------------------------------------------
879
void ofGLRenderer::rotateXDeg(float degrees){
880
	glRotatef(degrees, 1, 0, 0);
881
}
882

883
//----------------------------------------------------------
884
void ofGLRenderer::rotateYDeg(float degrees){
885
	glRotatef(degrees, 0, 1, 0);
886
}
887

888
//----------------------------------------------------------
889
void ofGLRenderer::rotateZDeg(float degrees){
890
	glRotatef(degrees, 0, 0, 1);
891
}
892

893
//same as ofRotateZ
894
//----------------------------------------------------------
895
void ofGLRenderer::rotateDeg(float degrees){
896
	glRotatef(degrees, 0, 0, 1);
897
}
898

899
//----------------------------------------------------------
900
void ofGLRenderer::rotateRad(float radians, float vecX, float vecY, float vecZ){
901
	glRotatef(ofRadToDeg(radians), vecX, vecY, vecZ);
902
}
903

904
//----------------------------------------------------------
905
void ofGLRenderer::rotateXRad(float radians){
906
	glRotatef(ofRadToDeg(radians), 1, 0, 0);
907
}
908

909
//----------------------------------------------------------
910
void ofGLRenderer::rotateYRad(float radians){
911
	glRotatef(ofRadToDeg(radians), 0, 1, 0);
912
}
913

914
//----------------------------------------------------------
915
void ofGLRenderer::rotateZRad(float radians){
916
	glRotatef(ofRadToDeg(radians), 0, 0, 1);
917
}
918

919
//same as ofRotateZ
920
//----------------------------------------------------------
921
void ofGLRenderer::rotateRad(float radians){
922
	glRotatef(ofRadToDeg(radians), 0, 0, 1);
923
}
924

925
//----------------------------------------------------------
926
void ofGLRenderer::matrixMode(ofMatrixMode mode){
927
	glMatrixMode(GL_MODELVIEW+mode);
928
	matrixStack.matrixMode(mode);
929
}
930

931
//----------------------------------------------------------
932
void ofGLRenderer::loadIdentityMatrix (void){
933
	loadMatrix(glm::mat4(1.0));
934
}
935

936
//----------------------------------------------------------
937
void ofGLRenderer::loadMatrix (const glm::mat4 & m){
938
	if(matrixStack.getCurrentMatrixMode()==OF_MATRIX_PROJECTION){
939
		matrixStack.loadMatrix(m);
940
		glLoadMatrixf(glm::value_ptr(matrixStack.getProjectionMatrix()));
941
	}else{
942
		glLoadMatrixf(glm::value_ptr(m));
943
	}
944
}
945

946
//----------------------------------------------------------
947
void ofGLRenderer::loadMatrix (const float *m){
948
	loadMatrix( glm::make_mat4(m) );
949
}
950

951
//----------------------------------------------------------
952

953
/** @brief	Queries the current OpenGL matrix state
954
 *  @detail Returns the specified matrix as held by the renderer's current matrix stack.
955
 *
956
 *			You can query one of the following:
957
 *
958
 *			[OF_MATRIX_MODELVIEW | OF_MATRIX_PROJECTION | OF_MATRIX_TEXTURE]
959
 *
960
 *			Each query will return the state of the matrix
961
 *			as it was uploaded to the shader currently bound.
962
 *
963
 *	@param	matrixMode_  Which matrix mode to query
964
 */
965
glm::mat4 ofGLRenderer::getCurrentMatrix(ofMatrixMode matrixMode_) const {
966
	glm::mat4 mat = glm::mat4(1.0);
967
	switch (matrixMode_) {
968
		case OF_MATRIX_MODELVIEW:
969
			glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(mat));
970
			break;
971
		case OF_MATRIX_PROJECTION:
972
			glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(mat));
973
			break;
974
		case OF_MATRIX_TEXTURE:
975
			glGetFloatv(GL_TEXTURE_MATRIX, glm::value_ptr(mat));
976
			break;
977
		default:
978
			ofLogWarning() << "Invalid getCurrentMatrix query";
979
			break;
980
	}
981
	return mat;
982
}
983

984
//----------------------------------------------------------
985
glm::mat4 ofGLRenderer::getCurrentOrientationMatrix() const {
986
	return matrixStack.getOrientationMatrix();
987
}
988

989
//----------------------------------------------------------
990
void ofGLRenderer::multMatrix (const glm::mat4 & m){
991
	if(matrixStack.getCurrentMatrixMode()==OF_MATRIX_PROJECTION){
992
		glm::mat4 current = glm::mat4(1.0);
993
		glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(current));
994
		if(matrixStack.customMatrixNeedsFlip()){
995
			current = glm::scale(current, glm::vec3(1,-1,1));
996
		}
997
		matrixStack.loadMatrix(current);
998
		matrixStack.multMatrix(m);
999
		glLoadMatrixf(glm::value_ptr(matrixStack.getProjectionMatrix()));
1000
	}else{
1001
		glMultMatrixf(glm::value_ptr(m));
1002
	}
1003
}
1004

1005
//----------------------------------------------------------
1006
void ofGLRenderer::multMatrix (const float *m){
1007
	multMatrix( glm::make_mat4(m) );
1008
}
1009

1010
//----------------------------------------------------------
1011
void ofGLRenderer::loadViewMatrix(const glm::mat4 & m){
1012
	int matrixMode;
1013
	glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1014
	matrixStack.loadViewMatrix(m);
1015
	glMatrixMode(GL_MODELVIEW);
1016
	glLoadMatrixf(glm::value_ptr(m));
1017
	glMatrixMode(matrixMode);
1018

1019
	if(lightingEnabled){
1020
		for(size_t i=0;i<ofLightsData().size();i++){
1021
			shared_ptr<ofLight::Data> lightData = ofLightsData()[i].lock();
1022
			if(lightData && lightData->isEnabled){
1023
				glLightfv(GL_LIGHT0 + lightData->glIndex, GL_POSITION, &lightData->position.x);
1024
				if(lightData->lightType == OF_LIGHT_SPOT || lightData->lightType == OF_LIGHT_AREA) {
1025
					glLightfv(GL_LIGHT0 + lightData->glIndex, GL_SPOT_DIRECTION, &lightData->direction.x);
1026
				}
1027
			}
1028
		}
1029
	}
1030
}
1031

1032
//----------------------------------------------------------
1033
void ofGLRenderer::multViewMatrix(const glm::mat4 & m){
1034
	ofLogError() << "mutlViewMatrix not implemented on fixed GL renderer";
1035
}
1036

1037
//----------------------------------------------------------
1038
glm::mat4 ofGLRenderer::getCurrentViewMatrix() const{
1039
	return matrixStack.getViewMatrix();
1040
}
1041

1042
//----------------------------------------------------------
1043
glm::mat4 ofGLRenderer::getCurrentNormalMatrix() const{
1044
	return glm::transpose(glm::inverse(getCurrentMatrix(OF_MATRIX_MODELVIEW)));
1045
}
1046

1047
//----------------------------------------------------------
1048
void ofGLRenderer::setColor(const ofColor & color){
1049
	setColor(color.r,color.g,color.b,color.a);
1050
}
1051

1052
//----------------------------------------------------------
1053
void ofGLRenderer::setColor(const ofColor & color, int _a){
1054
	setColor(color.r,color.g,color.b,_a);
1055
}
1056

1057
//----------------------------------------------------------
1058
void ofGLRenderer::setColor(int r, int g, int b){
1059
	currentStyle.color.set(r,g,b);
1060
	glColor4f(r/255.f,g/255.f,b/255.f,1.f);
1061
	if(lightingEnabled && !materialBound){
1062
#ifndef TARGET_OPENGLES
1063
		glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1064
#endif
1065
		glEnable(GL_COLOR_MATERIAL);
1066
	}
1067
}
1068

1069

1070
//----------------------------------------------------------
1071
void ofGLRenderer::setColor(int r, int g, int b, int a){
1072
	currentStyle.color.set(r,g,b,a);
1073
	glColor4f(r/255.f,g/255.f,b/255.f,a/255.f);
1074
	if(lightingEnabled && !materialBound){
1075
#ifndef TARGET_OPENGLES
1076
		glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
1077
#endif
1078
		glEnable(GL_COLOR_MATERIAL);
1079
	}
1080
}
1081

1082
//----------------------------------------------------------
1083
void ofGLRenderer::setColor(int gray){
1084
	setColor(gray, gray, gray);
1085
}
1086

1087
//----------------------------------------------------------
1088
void ofGLRenderer::setHexColor(int hexColor){
1089
	int r = (hexColor >> 16) & 0xff;
1090
	int g = (hexColor >> 8) & 0xff;
1091
	int b = (hexColor >> 0) & 0xff;
1092
	setColor(r,g,b);
1093
}
1094

1095
//----------------------------------------------------------
1096
void ofGLRenderer::clear(){
1097
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1098
}
1099

1100
//----------------------------------------------------------
1101
void ofGLRenderer::clear(float r, float g, float b, float a) {
1102
	glClearColor(r / 255., g / 255., b / 255., a / 255.);
1103
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1104
}
1105

1106
//----------------------------------------------------------
1107
void ofGLRenderer::clear(float brightness, float a) {
1108
	clear(brightness, brightness, brightness, a);
1109
}
1110

1111
//----------------------------------------------------------
1112
void ofGLRenderer::clearAlpha() {
1113
	glColorMask(0, 0, 0, 1);
1114
	glClearColor(0, 0, 0, 1);
1115
	glClear(GL_COLOR_BUFFER_BIT);
1116
	glColorMask(1, 1, 1, 1);
1117
}
1118

1119
//----------------------------------------------------------
1120
void ofGLRenderer::setBackgroundAuto(bool bAuto){
1121
	bBackgroundAuto = bAuto;
1122
}
1123

1124
//----------------------------------------------------------
1125
bool ofGLRenderer::getBackgroundAuto(){
1126
	return bBackgroundAuto;
1127
}
1128

1129
//----------------------------------------------------------
1130
ofColor ofGLRenderer::getBackgroundColor(){
1131
	return currentStyle.bgColor;
1132
}
1133

1134
//----------------------------------------------------------
1135
void ofGLRenderer::setBackgroundColor(const ofColor & color){
1136
	currentStyle.bgColor = color;
1137
	glClearColor(currentStyle.bgColor[0]/255.,currentStyle.bgColor[1]/255.,currentStyle.bgColor[2]/255., currentStyle.bgColor[3]/255.);
1138
}
1139

1140
//----------------------------------------------------------
1141
void ofGLRenderer::background(const ofColor & c){
1142
	setBackgroundColor(c);
1143
	glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
1144
}
1145

1146
//----------------------------------------------------------
1147
void ofGLRenderer::background(float brightness) {
1148
	background(ofColor(brightness));
1149
}
1150

1151
//----------------------------------------------------------
1152
void ofGLRenderer::background(int hexColor, float _a){
1153
	background ( (hexColor >> 16) & 0xff, (hexColor >> 8) & 0xff, (hexColor >> 0) & 0xff, _a);
1154
}
1155

1156
//----------------------------------------------------------
1157
void ofGLRenderer::background(int r, int g, int b, int a){
1158
	background(ofColor(r,g,b,a));
1159
}
1160

1161
//----------------------------------------------------------
1162
void ofGLRenderer::setFillMode(ofFillFlag fill){
1163
	currentStyle.bFill = (fill==OF_FILLED);
1164
	if(currentStyle.bFill){
1165
		path.setFilled(true);
1166
		path.setStrokeWidth(0);
1167
		#ifndef TARGET_OPENGLES
1168
			// GLES does not support glPolygonMode
1169
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
1170
		#endif
1171
	}else{
1172
		path.setFilled(false);
1173
		path.setStrokeWidth(currentStyle.lineWidth);
1174
		#ifndef TARGET_OPENGLES
1175
			// GLES does not support glPolygonMode
1176
			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
1177
		#endif
1178
	}
1179
}
1180

1181
//----------------------------------------------------------
1182
ofFillFlag ofGLRenderer::getFillMode(){
1183
	if(currentStyle.bFill){
1184
		return OF_FILLED;
1185
	}else{
1186
		return OF_OUTLINE;
1187
	}
1188
}
1189

1190
//----------------------------------------------------------
1191
void ofGLRenderer::setRectMode(ofRectMode mode){
1192
	currentStyle.rectMode = mode;
1193
}
1194

1195
//----------------------------------------------------------
1196
ofRectMode ofGLRenderer::getRectMode(){
1197
	return currentStyle.rectMode;
1198
}
1199

1200
//----------------------------------------------------------
1201
void ofGLRenderer::setLineWidth(float lineWidth){
1202
	currentStyle.lineWidth = lineWidth;
1203
	if(!currentStyle.bFill){
1204
		path.setStrokeWidth(lineWidth);
1205
	}
1206
	glLineWidth(lineWidth);
1207
}
1208

1209
//----------------------------------------------------------
1210
void ofGLRenderer::setDepthTest(bool depthTest){
1211
	if(depthTest) {
1212
		glEnable(GL_DEPTH_TEST);
1213
	} else {
1214
		glDisable(GL_DEPTH_TEST);
1215
	}
1216
}
1217

1218
//----------------------------------------------------------
1219
void ofGLRenderer::setLineSmoothing(bool smooth){
1220
	currentStyle.smoothing = smooth;
1221
}
1222

1223

1224
//----------------------------------------------------------
1225
void ofGLRenderer::startSmoothing(){
1226
	#ifndef TARGET_OPENGLES
1227
		glPushAttrib(GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT);
1228
	#endif
1229

1230
	glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);
1231
	glEnable(GL_LINE_SMOOTH);
1232

1233
	//why do we need this?
1234
	glEnable(GL_BLEND);
1235
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1236
}
1237

1238

1239
//----------------------------------------------------------
1240
void ofGLRenderer::endSmoothing(){
1241
	#ifndef TARGET_OPENGLES
1242
		glPopAttrib();
1243
	#endif
1244
}
1245

1246
//----------------------------------------------------------
1247
void ofGLRenderer::setBlendMode(ofBlendMode blendMode){
1248
	switch (blendMode){
1249
		case OF_BLENDMODE_DISABLED:
1250
			glDisable(GL_BLEND);
1251
			break;
1252

1253
		case OF_BLENDMODE_ALPHA:{
1254
			glEnable(GL_BLEND);
1255
			#ifndef TARGET_OPENGLES
1256
				glBlendEquation(GL_FUNC_ADD);
1257
			#endif
1258
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1259
			break;
1260
		}
1261

1262
		case OF_BLENDMODE_ADD:{
1263
			glEnable(GL_BLEND);
1264
			#ifndef TARGET_OPENGLES
1265
				glBlendEquation(GL_FUNC_ADD);
1266
			#endif
1267
			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1268
			break;
1269
		}
1270

1271
		case OF_BLENDMODE_MULTIPLY:{
1272
			glEnable(GL_BLEND);
1273
			#ifndef TARGET_OPENGLES
1274
				glBlendEquation(GL_FUNC_ADD);
1275
			#endif
1276
			glBlendFunc(GL_DST_COLOR, GL_ONE_MINUS_SRC_ALPHA /* GL_ZERO or GL_ONE_MINUS_SRC_ALPHA */);
1277
			break;
1278
		}
1279

1280
		case OF_BLENDMODE_SCREEN:{
1281
			glEnable(GL_BLEND);
1282
			#ifndef TARGET_OPENGLES
1283
				glBlendEquation(GL_FUNC_ADD);
1284
			#endif
1285
			glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ONE);
1286
			break;
1287
		}
1288

1289
		case OF_BLENDMODE_SUBTRACT:{
1290
			glEnable(GL_BLEND);
1291
		#ifndef TARGET_OPENGLES
1292
			glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
1293
		#else
1294
			ofLogWarning("ofGLRenderer") << "OF_BLENDMODE_SUBTRACT not currently supported on OpenGL ES";
1295
		#endif
1296
			glBlendFunc(GL_SRC_ALPHA, GL_ONE);
1297
			break;
1298
		}
1299

1300
		default:
1301
			break;
1302
	}
1303
	currentStyle.blendingMode = blendMode;
1304
}
1305

1306
//----------------------------------------------------------
1307
void ofGLRenderer::setBitmapTextMode(ofDrawBitmapMode mode){
1308
	currentStyle.drawBitmapMode = mode;
1309
}
1310

1311
//----------------------------------------------------------
1312
ofStyle ofGLRenderer::getStyle() const{
1313
	return currentStyle;
1314
}
1315

1316
//----------------------------------------------------------
1317
void ofGLRenderer::pushStyle(){
1318
	styleHistory.push_back(currentStyle);
1319
	//if we are over the max number of styles we have set, then delete the oldest styles.
1320
	if( styleHistory.size() > OF_MAX_STYLE_HISTORY ){
1321
		styleHistory.pop_front();
1322
		//should we warn here?
1323
		ofLogWarning("ofGraphics") << "ofPushStyle(): maximum number of style pushes << " << OF_MAX_STYLE_HISTORY << " reached, did you forget to pop somewhere?";
1324
	}
1325
}
1326

1327
//----------------------------------------------------------
1328
void ofGLRenderer::popStyle(){
1329
	if( styleHistory.size() ){
1330
		setStyle(styleHistory.back());
1331
		styleHistory.pop_back();
1332
	}
1333
}
1334

1335
//----------------------------------------------------------
1336
void ofGLRenderer::setStyle(const ofStyle & style){
1337
	//color
1338
	setColor((int)style.color.r, (int)style.color.g, (int)style.color.b, (int)style.color.a);
1339

1340
	//bg color
1341
	setBackgroundColor(style.bgColor);
1342

1343
	//circle resolution - don't worry it only recalculates the display list if the res has changed
1344
	setCircleResolution(style.circleResolution);
1345

1346
	setCurveResolution(style.curveResolution);
1347

1348
	//line width - finally!
1349
	setLineWidth(style.lineWidth);
1350

1351
	//ofSetDepthTest(style.depthTest); removed since it'll break old projects setting depth test through glEnable
1352

1353
	//rect mode: corner/center
1354
	setRectMode(style.rectMode);
1355

1356
	//poly mode: winding type
1357
	setPolyMode(style.polyMode);
1358

1359
	//fill
1360
	if(style.bFill ){
1361
		setFillMode(OF_FILLED);
1362
	}else{
1363
		setFillMode(OF_OUTLINE);
1364
	}
1365

1366
	//smoothing
1367
	/*if(style.smoothing ){
1368
		enableSmoothing();
1369
	}else{
1370
		disableSmoothing();
1371
	}*/
1372

1373
	//blending
1374
	setBlendMode(style.blendingMode);
1375

1376
	currentStyle = style;
1377
}
1378

1379
//----------------------------------------------------------
1380
void ofGLRenderer::setCurveResolution(int resolution){
1381
	currentStyle.curveResolution = resolution;
1382
	path.setCurveResolution(resolution);
1383
}
1384

1385
//----------------------------------------------------------
1386
void ofGLRenderer::enablePointSprites(){
1387

1388
#ifdef TARGET_OPENGLES
1389
	glEnable(GL_POINT_SPRITE_OES);
1390
	glTexEnvi(GL_POINT_SPRITE_OES, GL_COORD_REPLACE_OES, GL_TRUE);
1391
	// does look like this needs to be enabled in ES because
1392
	// it is always eneabled...
1393
	//glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1394

1395
#else
1396
	glEnable(GL_POINT_SPRITE);
1397
	glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, GL_TRUE);
1398
	glEnable(GL_VERTEX_PROGRAM_POINT_SIZE);
1399
#endif
1400

1401
}
1402

1403
//----------------------------------------------------------
1404
void ofGLRenderer::disablePointSprites(){
1405

1406
#ifdef TARGET_OPENGLES
1407
	glDisable(GL_POINT_SPRITE_OES);
1408
#else
1409
	glDisable(GL_POINT_SPRITE);
1410
#endif
1411
}
1412

1413
//----------------------------------------------------------
1414
void ofGLRenderer::enableAntiAliasing(){
1415
	glEnable(GL_MULTISAMPLE);
1416
}
1417

1418
//----------------------------------------------------------
1419
void ofGLRenderer::disableAntiAliasing(){
1420
	glDisable(GL_MULTISAMPLE);
1421
}
1422

1423
//----------------------------------------------------------
1424
void ofGLRenderer::drawLine(float x1, float y1, float z1, float x2, float y2, float z2) const{
1425
	linePoints[0] = {x1,y1,z1};
1426
	linePoints[1] = {x2,y2,z2};
1427

1428
	// use smoothness, if requested:
1429
	if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->startSmoothing();
1430

1431
	glEnableClientState(GL_VERTEX_ARRAY);
1432
	glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), linePoints.data());
1433
	glDrawArrays(GL_LINES, 0, 2);
1434

1435
	// use smoothness, if requested:
1436
	if (currentStyle.smoothing) const_cast<ofGLRenderer*>(this)->endSmoothing();
1437

1438
}
1439

1440
//----------------------------------------------------------
1441
void ofGLRenderer::drawRectangle(float x, float y, float z,float w, float h) const{
1442

1443
	if (currentStyle.rectMode == OF_RECTMODE_CORNER){
1444
		rectPoints[0] = {x,y,z};
1445
		rectPoints[1] = {x+w, y, z};
1446
		rectPoints[2] = {x+w, y+h, z};
1447
		rectPoints[3] = {x, y+h, z};
1448
	}else{
1449
		rectPoints[0] = {x-w/2.0f, y-h/2.0f, z};
1450
		rectPoints[1] = {x+w/2.0f, y-h/2.0f, z};
1451
		rectPoints[2] = {x+w/2.0f, y+h/2.0f, z};
1452
		rectPoints[3] = {x-w/2.0f, y+h/2.0f, z};
1453
	}
1454

1455
	// use smoothness, if requested:
1456
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1457

1458
	glEnableClientState(GL_VERTEX_ARRAY);
1459
	glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &rectPoints[0].x);
1460
	glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 4);
1461

1462
	// use smoothness, if requested:
1463
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1464

1465
}
1466

1467
//----------------------------------------------------------
1468
void ofGLRenderer::drawTriangle(float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3) const{
1469
	triPoints[0] = {x1,y1,z1};
1470
	triPoints[1] = {x2,y2,z2};
1471
	triPoints[2] = {x3,y3,z3};
1472

1473
	// use smoothness, if requested:
1474
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1475

1476
	glEnableClientState(GL_VERTEX_ARRAY);
1477
	glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &triPoints[0].x);
1478
	glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_LOOP, 0, 3);
1479

1480
	// use smoothness, if requested:
1481
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1482

1483
}
1484

1485
//----------------------------------------------------------
1486
void ofGLRenderer::drawCircle(float x, float y, float z,  float radius) const{
1487
	const auto & circleCache = circlePolyline.getVertices();
1488
	for(size_t i=0;i<circleCache.size();i++){
1489
		circlePoints[i] = {radius*circleCache[i].x+x,radius*circleCache[i].y+y,z};
1490
	}
1491

1492
	// use smoothness, if requested:
1493
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1494

1495
	glEnableClientState(GL_VERTEX_ARRAY);
1496
	glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &circlePoints[0].x);
1497
	glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_STRIP, 0, circlePoints.size());
1498

1499
	// use smoothness, if requested:
1500
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1501

1502
}
1503

1504
//----------------------------------------------------------
1505
void ofGLRenderer::drawEllipse(float x, float y, float z, float width, float height) const{
1506
	float radiusX = width*0.5;
1507
	float radiusY = height*0.5;
1508
	const auto & circleCache = circlePolyline.getVertices();
1509
	for(size_t i=0;i<circleCache.size();i++){
1510
		circlePoints[i] = {radiusX*circlePolyline[i].x+x, radiusY*circlePolyline[i].y+y, z};
1511
	}
1512

1513
	// use smoothness, if requested:
1514
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->startSmoothing();
1515

1516
	glEnableClientState(GL_VERTEX_ARRAY);
1517
	glVertexPointer(3, GL_FLOAT, sizeof(glm::vec3), &circlePoints[0].x);
1518
	glDrawArrays(currentStyle.bFill ? GL_TRIANGLE_FAN : GL_LINE_STRIP, 0, circlePoints.size());
1519

1520
	// use smoothness, if requested:
1521
	if (currentStyle.smoothing && !currentStyle.bFill) const_cast<ofGLRenderer*>(this)->endSmoothing();
1522

1523
}
1524

1525
//----------------------------------------------------------
1526
void ofGLRenderer::drawString(std::string textString, float x, float y, float z) const{
1527

1528
	ofGLRenderer * mutThis = const_cast<ofGLRenderer*>(this);
1529
	float sx = 0;
1530
	float sy = 0;
1531

1532

1533
	///////////////////////////
1534
	// APPLY TRANSFORM / VIEW
1535
	///////////////////////////
1536
	//
1537

1538
	bool hasModelView = false;
1539
	bool hasProjection = false;
1540
	bool hasViewport = false;
1541

1542
	ofRectangle rViewport;
1543
	bool vflipped = isVFlipped();
1544

1545
	switch (currentStyle.drawBitmapMode) {
1546

1547
		case OF_BITMAPMODE_SIMPLE:
1548

1549
			sx += x;
1550
			sy += y;
1551
			break;
1552

1553
		case OF_BITMAPMODE_SCREEN:
1554

1555
			hasViewport = true;
1556
			mutThis->pushView();
1557

1558
			rViewport = matrixStack.getFullSurfaceViewport();
1559
			mutThis->viewport(rViewport);
1560

1561
			mutThis->matrixMode(OF_MATRIX_PROJECTION);
1562
			mutThis->loadIdentityMatrix();
1563
			mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1564
			mutThis->loadIdentityMatrix();
1565

1566
			mutThis->translate(-1, 1, 0);
1567
			mutThis->scale(2/rViewport.width, -2/rViewport.height, 1);
1568
			mutThis->translate(x, rViewport.height - y, 0);
1569
			vflipped = false;
1570
			break;
1571

1572
		case OF_BITMAPMODE_VIEWPORT:
1573

1574
			rViewport = getCurrentViewport();
1575

1576
			hasProjection = true;
1577
			mutThis->matrixMode(OF_MATRIX_PROJECTION);
1578
			mutThis->pushMatrix();
1579
			mutThis->loadIdentityMatrix();
1580

1581
			hasModelView = true;
1582
			mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1583
			mutThis->pushMatrix();
1584
			mutThis->loadIdentityMatrix();
1585

1586
			mutThis->translate(-1, 1, 0);
1587
			mutThis->scale(2/rViewport.width, -2/rViewport.height, 1);
1588
			mutThis->translate(x, rViewport.height - y, 0);
1589
			vflipped = false;
1590
			break;
1591

1592
		case OF_BITMAPMODE_MODEL:
1593

1594
			hasModelView = true;
1595
			mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1596
			mutThis->pushMatrix();
1597

1598
			mutThis->translate(x, y, z);
1599
			break;
1600

1601
		case OF_BITMAPMODE_MODEL_BILLBOARD:
1602
		{
1603
			//our aim here is to draw to screen
1604
			//at the viewport position related
1605
			//to the world position x,y,z
1606

1607
			// tig: we want to get the signed normalised screen coordinates (-1,+1) of our point (x,y,z)
1608
			// that's projection * modelview * point in GLSL multiplication order
1609
			// then doing the good old (v + 1.0) / 2. to get unsigned normalized screen (0,1) coordinates.
1610
			// we then multiply x by width and y by height to get window coordinates.
1611

1612
			// previous implementations used gluProject, which made it incompatible with GLES (and the future)
1613
			// https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/gluProject.3.html
1614
			//
1615
			// this could probably be backported to the GL2 Renderer =)
1616

1617
			rViewport = getCurrentViewport();
1618

1619
			glm::mat4 modelview = glm::mat4(1.0), projection = glm::mat4(1.0);
1620
			glGetFloatv(GL_MODELVIEW_MATRIX, glm::value_ptr(modelview));
1621
			glGetFloatv(GL_PROJECTION_MATRIX, glm::value_ptr(projection));
1622
			glm::mat4 mat = matrixStack.getOrientationMatrixInverse() * projection * modelview;
1623
			glm::vec4 dScreen4 = mat * glm::vec4(x,y,z,1.0);
1624
			glm::vec3 dScreen = glm::vec3(dScreen4) / dScreen4.w;
1625
			dScreen += glm::vec3(1.0) ;
1626
			dScreen *= 0.5;
1627

1628
			dScreen.x *= rViewport.width;
1629
			dScreen.x += rViewport.x;
1630

1631
			dScreen.y *= rViewport.height;
1632
			dScreen.y += rViewport.y;
1633

1634
			if (dScreen.z >= 1){
1635
				return;
1636
			}
1637

1638

1639
			hasProjection = true;
1640
			mutThis->matrixMode(OF_MATRIX_PROJECTION);
1641
			mutThis->pushMatrix();
1642
			mutThis->loadIdentityMatrix();
1643

1644
			hasModelView = true;
1645
			mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1646
			mutThis->pushMatrix();
1647
			mutThis->loadIdentityMatrix();
1648

1649
			mutThis->translate(-1, -1, 0);
1650

1651
			mutThis->scale(2/rViewport.width, 2/rViewport.height, 1);
1652

1653
			mutThis->translate(dScreen.x, dScreen.y, 0);
1654
		}
1655
			break;
1656

1657
		default:
1658
			break;
1659
	}
1660
	// remember the current blend mode so that we can restore it at the end of this method.
1661
	GLint blend_src, blend_dst;
1662
	glGetIntegerv( GL_BLEND_SRC, &blend_src );
1663
	glGetIntegerv( GL_BLEND_DST, &blend_dst );
1664

1665
	glEnable(GL_BLEND);
1666
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1667
#ifndef TARGET_OPENGLES
1668
	// this temporarily enables alpha testing,
1669
	// which discards pixels unless their alpha is 1.0f
1670
	glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT);
1671
	glEnable(GL_ALPHA_TEST);
1672
	glAlphaFunc(GL_GREATER, 0);
1673
#endif
1674

1675
	ofMesh charMesh = bitmapFont.getMesh(textString,sx,sy,currentStyle.drawBitmapMode,vflipped);
1676
	mutThis->bind(bitmapFont.getTexture(),0);
1677
	draw(charMesh,OF_MESH_FILL,false,true,false);
1678
	mutThis->unbind(bitmapFont.getTexture(),0);
1679

1680
#ifndef TARGET_OPENGLES
1681
	glPopAttrib();
1682
#endif
1683
	// restore blendmode
1684
	glBlendFunc(blend_src, blend_dst);
1685

1686
	if (hasModelView)
1687
		mutThis->popMatrix();
1688

1689
	if (hasProjection)
1690
	{
1691
		mutThis->matrixMode(OF_MATRIX_PROJECTION);
1692
		mutThis->popMatrix();
1693
		mutThis->matrixMode(OF_MATRIX_MODELVIEW);
1694
	}
1695

1696
	if (hasViewport)
1697
		mutThis->popView();
1698

1699
}
1700

1701
//----------------------------------------------------------
1702
void ofGLRenderer::drawString(const ofTrueTypeFont & font, std::string text, float x, float y) const{
1703
	ofGLRenderer * mutThis = const_cast<ofGLRenderer*>(this);
1704
	bool blendEnabled = glIsEnabled(GL_BLEND);
1705
	GLint blend_src, blend_dst;
1706
	glGetIntegerv( GL_BLEND_SRC, &blend_src );
1707
	glGetIntegerv( GL_BLEND_DST, &blend_dst );
1708

1709
	glEnable(GL_BLEND);
1710
	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1711

1712
	mutThis->bind(font.getFontTexture(),0);
1713
	draw(font.getStringMesh(text,x,y,isVFlipped()),OF_MESH_FILL);
1714
	mutThis->unbind(font.getFontTexture(),0);
1715

1716
	if(!blendEnabled){
1717
		glDisable(GL_BLEND);
1718
	}
1719
	glBlendFunc(blend_src, blend_dst);
1720
}
1721

1722
//----------------------------------------------------------
1723
void ofGLRenderer::enableTextureTarget(const ofTexture & tex, int textureLocation){
1724
	glActiveTexture(GL_TEXTURE0+textureLocation);
1725
	glClientActiveTexture(GL_TEXTURE0+textureLocation);
1726
	glEnable( tex.getTextureData().textureTarget);
1727
	glBindTexture( tex.getTextureData().textureTarget, (GLuint)tex.getTextureData().textureID);
1728
#ifndef TARGET_OPENGLES
1729
	if(tex.getTextureData().bufferId!=0){
1730
		glTexBuffer(GL_TEXTURE_BUFFER, tex.getTextureData().glInternalFormat, tex.getTextureData().bufferId);
1731
	}
1732
#endif
1733
	textureLocationsEnabled.insert(textureLocation);
1734
}
1735

1736
//----------------------------------------------------------
1737
void ofGLRenderer::disableTextureTarget(int textureTarget, int textureLocation){
1738
	glActiveTexture(GL_TEXTURE0+textureLocation);
1739
	glBindTexture( textureTarget, 0);
1740
	glDisable(textureTarget);
1741
	glActiveTexture(GL_TEXTURE0);
1742
	textureLocationsEnabled.erase(textureLocation);
1743
}
1744

1745
//----------------------------------------------------------
1746
void ofGLRenderer::setAlphaMaskTex(const ofTexture & tex){
1747
	enableTextureTarget(tex, 1);
1748
	alphaMaskTextureTarget = tex.getTextureData().textureTarget;
1749
}
1750

1751
//----------------------------------------------------------
1752
void ofGLRenderer::disableAlphaMask(){
1753
	disableTextureTarget(alphaMaskTextureTarget,1);
1754
}
1755

1756
//----------------------------------------------------------
1757
void ofGLRenderer::enableLighting(){
1758
	glEnable(GL_LIGHTING);
1759
	lightingEnabled = true;
1760
	setColor(currentStyle.color);
1761
	// FIXME: we do this so the 3d ofDraw* functions work with lighting
1762
	// but if someone enables it between ofEnableLighting it'll be disabled
1763
	// on ofDisableLighting. by now it seems the best option to not loose
1764
	// performance when drawing lots of primitives
1765
	normalsEnabled = glIsEnabled( GL_NORMALIZE );
1766
	glEnable(GL_NORMALIZE);
1767

1768
	int matrixMode;
1769
	glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1770
	glMatrixMode(GL_MODELVIEW);
1771
	glPushMatrix();
1772
	glLoadMatrixf(glm::value_ptr(matrixStack.getViewMatrix()));
1773
	for(size_t i=0;i<ofLightsData().size();i++){
1774
		std::shared_ptr<ofLight::Data> lightData = ofLightsData()[i].lock();
1775
		if(lightData && lightData->isEnabled){
1776
			glLightfv(GL_LIGHT0 + lightData->glIndex, GL_POSITION, &lightData->position.x);
1777
			if(lightData->lightType == OF_LIGHT_SPOT || lightData->lightType == OF_LIGHT_AREA) {
1778
				glLightfv(GL_LIGHT0 + lightData->glIndex, GL_SPOT_DIRECTION, &lightData->direction.x);
1779
			}
1780
		}
1781
	}
1782
	glPopMatrix();
1783
	glMatrixMode(matrixMode);
1784
}
1785

1786
//----------------------------------------------------------
1787
void ofGLRenderer::disableLighting(){
1788
	glDisable(GL_LIGHTING);
1789
	if(!normalsEnabled){
1790
		glDisable(GL_NORMALIZE);
1791
	}
1792
	lightingEnabled = false;
1793
}
1794

1795
//----------------------------------------------------------
1796
void ofGLRenderer::enableSeparateSpecularLight(){
1797
#ifndef TARGET_OPENGLES
1798
	glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR);
1799
#endif
1800
}
1801

1802
//----------------------------------------------------------
1803
void ofGLRenderer::disableSeparateSpecularLight(){
1804
#ifndef TARGET_OPENGLES
1805
	glLightModeli (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR);
1806
#endif
1807
}
1808

1809
//----------------------------------------------------------
1810
bool ofGLRenderer::getLightingEnabled(){
1811
	return glIsEnabled(GL_LIGHTING);
1812
}
1813

1814
//----------------------------------------------------------
1815
void ofGLRenderer::setSmoothLighting(bool b){
1816
	if (b) glShadeModel(GL_SMOOTH);
1817
	else glShadeModel(GL_FLAT);
1818
}
1819

1820
//----------------------------------------------------------
1821
void ofGLRenderer::setGlobalAmbientColor(const ofColor& c){
1822
	GLfloat cc[] = {c.r/255.f, c.g/255.f, c.b/255.f, c.a/255.f};
1823
	glLightModelfv(GL_LIGHT_MODEL_AMBIENT, cc);
1824
}
1825

1826
//----------------------------------------------------------
1827
void ofGLRenderer::enableLight(int lightIndex){
1828
	enableLighting();
1829
	glEnable(GL_LIGHT0 + lightIndex);
1830
}
1831

1832
//----------------------------------------------------------
1833
void ofGLRenderer::disableLight(int lightIndex){
1834
	if(lightIndex!=-1) {
1835
		glDisable(GL_LIGHT0 + lightIndex);
1836
	}
1837
}
1838

1839
//----------------------------------------------------------
1840
void ofGLRenderer::setLightSpotlightCutOff(int lightIndex, float spotCutOff){
1841
	glLightf(GL_LIGHT0 + lightIndex, GL_SPOT_CUTOFF, spotCutOff );
1842
}
1843

1844
//----------------------------------------------------------
1845
void ofGLRenderer::setLightSpotConcentration(int lightIndex, float exponent){
1846
	glLightf(GL_LIGHT0 + lightIndex, GL_SPOT_EXPONENT, exponent);
1847
}
1848

1849
//----------------------------------------------------------
1850
void ofGLRenderer::setLightAttenuation(int lightIndex, float constant, float linear, float quadratic ){
1851
	if(lightIndex==-1) return;
1852
	glLightf(GL_LIGHT0 + lightIndex, GL_CONSTANT_ATTENUATION, constant);
1853
	glLightf(GL_LIGHT0 + lightIndex, GL_LINEAR_ATTENUATION, linear);
1854
	glLightf(GL_LIGHT0 + lightIndex, GL_QUADRATIC_ATTENUATION, quadratic);
1855
}
1856

1857
//----------------------------------------------------------
1858
void ofGLRenderer::setLightAmbientColor(int lightIndex, const ofFloatColor& c){
1859
	if(lightIndex==-1) return;
1860
	glLightfv(GL_LIGHT0 + lightIndex, GL_AMBIENT, &c.r);
1861
}
1862

1863
//----------------------------------------------------------
1864
void ofGLRenderer::setLightDiffuseColor(int lightIndex, const ofFloatColor& c){
1865
	if(lightIndex==-1) return;
1866
	glLightfv(GL_LIGHT0 + lightIndex, GL_DIFFUSE, &c.r);
1867
}
1868

1869
//----------------------------------------------------------
1870
void ofGLRenderer::setLightSpecularColor(int lightIndex, const ofFloatColor& c){
1871
	if(lightIndex==-1) return;
1872
	glLightfv(GL_LIGHT0 + lightIndex, GL_SPECULAR, &c.r);
1873
}
1874

1875
//----------------------------------------------------------
1876
void ofGLRenderer::setLightPosition(int lightIndex, const glm::vec4 & position){
1877
	if(lightIndex==-1) return;
1878
	int matrixMode;
1879
	glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1880
	glMatrixMode(GL_MODELVIEW);
1881
	glPushMatrix();
1882
	glLoadMatrixf(glm::value_ptr(matrixStack.getViewMatrix()));
1883
	glLightfv(GL_LIGHT0 + lightIndex, GL_POSITION, glm::value_ptr(position));
1884
	glPopMatrix();
1885
	glMatrixMode(matrixMode);
1886
}
1887

1888
//----------------------------------------------------------
1889
void ofGLRenderer::setLightSpotDirection(int lightIndex, const glm::vec4 & direction){
1890
	if(lightIndex==-1) return;
1891
	int matrixMode;
1892
	glGetIntegerv(GL_MATRIX_MODE,&matrixMode);
1893
	glMatrixMode(GL_MODELVIEW);
1894
	glPushMatrix();
1895
	glLoadMatrixf(glm::value_ptr(matrixStack.getViewMatrix()));
1896
	glLightfv(GL_LIGHT0 + lightIndex, GL_SPOT_DIRECTION, glm::value_ptr(direction));
1897
	glPopMatrix();
1898
	glMatrixMode(matrixMode);
1899
}
1900

1901
//----------------------------------------------------------
1902
int ofGLRenderer::getGLVersionMajor(){
1903
#ifdef TARGET_OPENGLES
1904
	return 1;
1905
#else
1906
	return 2;
1907
#endif
1908
}
1909

1910
//----------------------------------------------------------
1911
int ofGLRenderer::getGLVersionMinor(){
1912
#ifdef TARGET_OPENGLES
1913
	return 0;
1914
#else
1915
	return 1;
1916
#endif
1917
}
1918

1919
//----------------------------------------------------------
1920
void ofGLRenderer::saveFullViewport(ofPixels & pixels){
1921
	ofRectangle v = getCurrentViewport();
1922
	saveScreen(v.x,v.y,v.width,v.height,pixels);
1923
}
1924

1925
//----------------------------------------------------------
1926
void ofGLRenderer::saveScreen(int x, int y, int w, int h, ofPixels & pixels){
1927
	int sh = getViewportHeight();
1928

1929

1930
	#ifndef TARGET_OPENGLES
1931
	if(isVFlipped()){
1932
		y = sh - y;
1933
		y -= h; // top, bottom issues
1934
	}
1935
	auto pixelFormat = OF_PIXELS_BGRA;
1936
	pixels.allocate(w, h, pixelFormat);
1937
	auto glFormat = ofGetGLFormat(pixels);
1938

1939

1940
	glReadPixels(x, y, w, h, glFormat, GL_UNSIGNED_BYTE, pixels.begin()); // read the memory....
1941
	pixels.mirror(true, false);
1942
	#else
1943

1944
	int sw = getViewportWidth();
1945
	int numPixels   = w*h;
1946
	if( numPixels == 0 ){
1947
		ofLogError("ofImage") << "grabScreen(): unable to grab screen, image width and/or height are 0: " << w << "x" << h;
1948
		return;
1949
	}
1950
	pixels.allocate(w, h, OF_PIXELS_RGBA);
1951

1952
	switch(matrixStack.getOrientation()){
1953
	case OF_ORIENTATION_UNKNOWN:
1954
	case OF_ORIENTATION_DEFAULT:
1955

1956
		if(isVFlipped()){
1957
			y = sh - y;   // screen is flipped vertically.
1958
			y -= h;
1959
		}
1960

1961
		glPixelStorei(GL_PACK_ALIGNMENT, 1);
1962
		glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
1963
		pixels.mirror(true,false);
1964
		break;
1965
	case OF_ORIENTATION_180:
1966

1967
		if(isVFlipped()){
1968
			x = sw - x;   // screen is flipped horizontally.
1969
			x -= w;
1970
		}
1971

1972
		glPixelStorei(GL_PACK_ALIGNMENT, 1);
1973
		glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
1974
		pixels.mirror(false,true);
1975
		break;
1976
	case OF_ORIENTATION_90_RIGHT:
1977
		std::swap(w,h);
1978
		std::swap(x,y);
1979
		if(!isVFlipped()){
1980
			x = sw - x;   // screen is flipped horizontally.
1981
			x -= w;
1982

1983
			y = sh - y;   // screen is flipped vertically.
1984
			y -= h;
1985
		}
1986

1987
		glPixelStorei(GL_PACK_ALIGNMENT, 1);
1988
		glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
1989
		pixels.mirror(true,true);
1990
		break;
1991
	case OF_ORIENTATION_90_LEFT:
1992
		std::swap(w, h);
1993
		std::swap(x, y);
1994
		if(isVFlipped()){
1995
			x = sw - x;   // screen is flipped horizontally.
1996
			x -= w;
1997

1998
			y = sh - y;   // screen is flipped vertically.
1999
			y -= h;
2000
		}
2001

2002
		glPixelStorei(GL_PACK_ALIGNMENT, 1);
2003
		glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixels.getData());
2004
		pixels.mirror(true,true);
2005
		break;
2006
	}
2007

2008
	#endif
2009
}
2010

2011
//----------------------------------------------------------
2012
const of3dGraphics & ofGLRenderer::get3dGraphics() const{
2013
	return graphics3d;
2014
}
2015

2016
//----------------------------------------------------------
2017
of3dGraphics & ofGLRenderer::get3dGraphics(){
2018
	return graphics3d;
2019
}
2020

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

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

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

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