framework2

Форк
0
1236 строк · 39.5 Кб
1
#include "ofFbo.h"
2
#include "ofAppRunner.h"
3
#include "ofUtils.h"
4
#include "ofGraphics.h"
5
#include "ofGLRenderer.h"
6
#include "ofConstants.h"
7
#include <unordered_map>
8

9
#ifdef TARGET_OPENGLES
10
#include <dlfcn.h>
11
#endif
12
#ifdef TARGET_ANDROID
13
#include "ofxAndroidUtils.h"
14
#endif
15

16
using std::unordered_map;
17
using std::vector;
18

19
/*
20

21
 See
22
 http://www.gandogames.com/2010/07/tutorial-using-anti-aliasing-msaa-in-the-iphone/
23
 and
24
 http://stackoverflow.com/questions/3340189/how-do-you-activate-multisampling-in-opengl-es-on-the-iphone
25
 for multisampling on iphone
26

27
 */
28

29
#if defined(TARGET_OPENGLES) & !defined(TARGET_EMSCRIPTEN)
30
	bool ofFbo::bglFunctionsInitialized=false;
31
	
32
	typedef void (* glGenFramebuffersType) (GLsizei n, GLuint* framebuffers);
33
	glGenFramebuffersType glGenFramebuffersFunc;
34
	#define glGenFramebuffers								glGenFramebuffersFunc
35

36
	typedef void (* glDeleteFramebuffersType) (GLsizei n, const GLuint* framebuffers);
37
	glDeleteFramebuffersType glDeleteFramebuffersFunc;
38
	#define	glDeleteFramebuffers							glDeleteFramebuffersFunc
39

40
	typedef void (* glDeleteRenderbuffersType) (GLsizei n, const GLuint* renderbuffers);
41
	glDeleteRenderbuffersType glDeleteRenderbuffersFunc;
42
	#define	glDeleteRenderbuffers							glDeleteRenderbuffersFunc
43

44
	typedef void (* glBindFramebufferType) (GLenum target, GLuint framebuffer);
45
	glBindFramebufferType glBindFramebufferFunc;
46
	#define	glBindFramebuffer								glBindFramebufferFunc
47

48
	typedef void (* glBindRenderbufferType) (GLenum target, GLuint renderbuffer);
49
	glBindRenderbufferType glBindRenderbufferFunc;
50
	#define	glBindRenderbuffer								glBindRenderbufferFunc
51

52
	typedef void (* glRenderbufferStorageType) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
53
	glRenderbufferStorageType glRenderbufferStorageFunc;
54
	#define glRenderbufferStorage							glRenderbufferStorageFunc
55

56
	typedef void (* glFramebufferRenderbufferType) (GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
57
	glFramebufferRenderbufferType glFramebufferRenderbufferFunc;
58
	#define glFramebufferRenderbuffer						glFramebufferRenderbufferFunc
59

60
	typedef void (* glRenderbufferStorageMultisampleType) (GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
61
	glRenderbufferStorageMultisampleType glRenderbufferStorageMultisampleFunc;
62
	#define glRenderbufferStorageMultisample				glRenderbufferStorageMultisampleFunc
63

64
	typedef void (* glFramebufferTexture2DType) (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
65
	glFramebufferTexture2DType glFramebufferTexture2DFunc;
66
	#define glFramebufferTexture2D							glFramebufferTexture2DFunc
67

68
	typedef GLenum (* glCheckFramebufferStatusType)  (GLenum target);
69
	glCheckFramebufferStatusType glCheckFramebufferStatusFunc;
70
	#define glCheckFramebufferStatus						glCheckFramebufferStatusFunc
71
#endif
72

73

74

75
//-------------------------------------------------------------------------------------
76
ofFboSettings::ofFboSettings(std::shared_ptr<ofBaseGLRenderer> renderer) {
77
	width					= 0;
78
	height					= 0;
79
	numColorbuffers			= 1;
80
	useDepth				= false;
81
	useStencil				= false;
82
	depthStencilAsTexture	= false;
83
#ifndef TARGET_OPENGLES
84
	textureTarget			= ofGetUsingArbTex() ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D;
85
#else
86
	textureTarget			= GL_TEXTURE_2D;
87
#endif
88
	internalformat			= GL_RGBA;
89
	depthStencilInternalFormat = GL_DEPTH_COMPONENT24;
90
	wrapModeHorizontal		= GL_CLAMP_TO_EDGE;
91
	wrapModeVertical		= GL_CLAMP_TO_EDGE;
92
	minFilter				= GL_LINEAR;
93
	maxFilter				= GL_LINEAR;
94
	numSamples				= 0;
95
	this->renderer = renderer;
96
}
97

98
//--------------------------------------------------------------
99
bool ofFboSettings::operator!=(const ofFboSettings & other){
100
	if(width != other.width){
101
		ofLogError() << "settings width differs from source";
102
		return true;
103
	}
104
	if(height != other.height){
105
		ofLogError() << "settings height differs from source";
106
		return true;
107
	}
108
	if(numColorbuffers != other.numColorbuffers){
109
		ofLogError() << "settings numColorbuffers differs from source";
110
		return true;
111
	}
112
	if(colorFormats != other.colorFormats){
113
		ofLogError() << "settings colorFormats differs from source";
114
		return true;
115
	}
116
	if(useDepth != other.useDepth){
117
		ofLogError() << "settings useDepth differs from source";
118
		return true;
119
	}
120
	if(useStencil != other.useStencil){
121
		ofLogError() << "settings useStencil differs from source";
122
		return true;
123
	}
124
	if(depthStencilAsTexture != other.depthStencilAsTexture){
125
		ofLogError() << "settings depthStencilAsTexture differs from source";
126
		return true;
127
	}
128
	if(textureTarget != other.textureTarget){
129
		ofLogError() << "settings textureTarget differs from source";
130
		return true;
131
	}
132
	if(internalformat != other.internalformat){
133
		ofLogError() << "settings internalformat differs from source";
134
		return true;
135
	}
136
	if(depthStencilInternalFormat != other.depthStencilInternalFormat){
137
		ofLogError() << "settings depthStencilInternalFormat differs from source";
138
		return true;
139
	}
140
	if(wrapModeHorizontal != other.wrapModeHorizontal){
141
		ofLogError() << "settings wrapModeHorizontal differs from source";
142
		return true;
143
	}
144
	if(wrapModeVertical != other.wrapModeVertical){
145
		ofLogError() << "settings wrapModeVertical differs from source";
146
		return true;
147
	}
148
	if(minFilter != other.minFilter){
149
		ofLogError() << "settings minFilter differs from source";
150
		return true;
151
	}
152
	if(maxFilter != other.maxFilter){
153
		ofLogError() << "settings maxFilter differs from source";
154
		return false;
155
	}
156
	if(numSamples != other.numSamples){
157
		ofLogError() << "settings numSamples differs from source";
158
		return true;
159
	}
160
	if(renderer.lock() != other.renderer.lock()){
161
		ofLogError() << "settings renderers are different";
162
		return true;
163
	}
164
	return false;
165
}
166

167
//--------------------------------------------------------------
168
static unordered_map<GLuint,int> & getIdsFB(){
169
	static unordered_map<GLuint,int> * idsFB = new unordered_map<GLuint,int>;
170
	return *idsFB;
171
}
172

173
//--------------------------------------------------------------
174
static void retainFB(GLuint id){
175
	if(id==0) return;
176
	if(getIdsFB().find(id)!=getIdsFB().end()){
177
		getIdsFB()[id]++;
178
	}else{
179
		getIdsFB()[id]=1;
180
	}
181
}
182

183
//--------------------------------------------------------------
184
static void releaseFB(GLuint id){
185
	if(getIdsFB().find(id)!=getIdsFB().end()){
186
		getIdsFB()[id]--;
187
		if(getIdsFB()[id]==0){
188
			glDeleteFramebuffers(1, &id);
189
		}
190
	}else{
191
		ofLogWarning("ofFbo") << "releaseFB(): something's wrong here, releasing unknown frame buffer id " << id;
192
		glDeleteFramebuffers(1, &id);
193
	}
194
}
195

196
//--------------------------------------------------------------
197
static unordered_map<GLuint,int> & getIdsRB(){
198
	static unordered_map<GLuint,int> * idsRB = new unordered_map<GLuint,int>;
199
	return *idsRB;
200
}
201

202
//--------------------------------------------------------------
203
static void retainRB(GLuint id){
204
	if(id==0) return;
205
	if(getIdsRB().find(id)!=getIdsRB().end()){
206
		getIdsRB()[id]++;
207
	}else{
208
		getIdsRB()[id]=1;
209
	}
210
}
211

212
//--------------------------------------------------------------
213
static void releaseRB(GLuint id){
214
	if(getIdsRB().find(id)!=getIdsRB().end()){
215
		getIdsRB()[id]--;
216
		if(getIdsRB()[id]==0){
217
			glDeleteRenderbuffers(1, &id);
218
		}
219
	}else{
220
		ofLogWarning("ofFbo") << "releaseRB(): something's wrong here, releasing unknown render buffer id " << id;
221
		glDeleteRenderbuffers(1, &id);
222
	}
223
}
224

225
//-------------------------------------------------------------------------------------
226
int	ofFbo::_maxColorAttachments = -1;
227
int	ofFbo::_maxDrawBuffers = -1;
228
int	ofFbo::_maxSamples = -1;
229

230

231
//--------------------------------------------------------------
232
ofFbo::ofFbo():
233
fbo(0),
234
fboTextures(0),
235
depthBuffer(0),
236
stencilBuffer(0),
237
dirty(false),
238
defaultTextureIndex(0),
239
bIsAllocated(false)
240
{
241
#if defined(TARGET_OPENGLES) & !defined(TARGET_EMSCRIPTEN)
242
	if(!bglFunctionsInitialized){
243
		if(ofIsGLProgrammableRenderer()){
244
			glGenFramebuffers = (glGenFramebuffersType)dlsym(RTLD_DEFAULT, "glGenFramebuffers");
245
			glDeleteFramebuffers =  (glDeleteFramebuffersType)dlsym(RTLD_DEFAULT, "glDeleteFramebuffers");
246
			glDeleteRenderbuffers =  (glDeleteRenderbuffersType)dlsym(RTLD_DEFAULT, "glDeleteRenderbuffers");
247
			glBindFramebuffer =  (glBindFramebufferType)dlsym(RTLD_DEFAULT, "glBindFramebuffer");
248
			glBindRenderbuffer = (glBindRenderbufferType)dlsym(RTLD_DEFAULT, "glBindRenderbuffer");
249
			glRenderbufferStorage = (glRenderbufferStorageType)dlsym(RTLD_DEFAULT, "glRenderbufferStorage");
250
			glFramebufferRenderbuffer = (glFramebufferRenderbufferType)dlsym(RTLD_DEFAULT, "glFramebufferRenderbuffer");
251
			glRenderbufferStorageMultisample = (glRenderbufferStorageMultisampleType)dlsym(RTLD_DEFAULT, "glRenderbufferStorageMultisample");
252
			glFramebufferTexture2D = (glFramebufferTexture2DType)dlsym(RTLD_DEFAULT, "glFramebufferTexture2D");
253
			glCheckFramebufferStatus = (glCheckFramebufferStatusType)dlsym(RTLD_DEFAULT, "glCheckFramebufferStatus");
254
		}else{
255
			glGenFramebuffers = (glGenFramebuffersType)dlsym(RTLD_DEFAULT, "glGenFramebuffersOES");
256
			glDeleteFramebuffers = (glDeleteFramebuffersType)dlsym(RTLD_DEFAULT, "glDeleteFramebuffersOES");
257
			glDeleteRenderbuffers = (glDeleteRenderbuffersType)dlsym(RTLD_DEFAULT, "glDeleteRenderbuffersOES");
258
			glBindFramebuffer = (glBindFramebufferType)dlsym(RTLD_DEFAULT, "glBindFramebufferOES");
259
			glBindRenderbuffer = (glBindRenderbufferType)dlsym(RTLD_DEFAULT, "glBindRenderbufferOES");
260
			glRenderbufferStorage = (glRenderbufferStorageType)dlsym(RTLD_DEFAULT, "glRenderbufferStorageOES");
261
			glFramebufferRenderbuffer = (glFramebufferRenderbufferType)dlsym(RTLD_DEFAULT, "glFramebufferRenderbufferOES");
262
			glRenderbufferStorageMultisample = (glRenderbufferStorageMultisampleType)dlsym(RTLD_DEFAULT, "glRenderbufferStorageMultisampleOES");
263
			glFramebufferTexture2D = (glFramebufferTexture2DType)dlsym(RTLD_DEFAULT, "glFramebufferTexture2DOES");
264
			glCheckFramebufferStatus = (glCheckFramebufferStatusType)dlsym(RTLD_DEFAULT, "glCheckFramebufferStatusOES");
265
		}
266
	}
267
#endif
268
}
269

270
//--------------------------------------------------------------
271
ofFbo::ofFbo(const ofFbo & mom){
272
	settings = mom.settings;
273
	bIsAllocated = mom.bIsAllocated;
274

275
	fbo = mom.fbo;
276
	retainFB(fbo);
277
	fboTextures = mom.fboTextures;
278
	if(settings.numSamples){
279
		retainFB(fboTextures);
280
	}
281
	if(mom.settings.depthStencilAsTexture){
282
		depthBufferTex = mom.depthBufferTex;
283
	}else{
284
		depthBuffer = mom.depthBuffer;
285
		retainRB(depthBuffer);
286
	}
287
	stencilBuffer = mom.stencilBuffer;
288
	retainRB(stencilBuffer);
289

290
	colorBuffers = mom.colorBuffers;
291
	for(int i=0;i<(int)colorBuffers.size();i++){
292
		retainRB(colorBuffers[i]);
293
	}
294
	textures = mom.textures;
295
	dirty = mom.dirty;
296
	defaultTextureIndex = mom.defaultTextureIndex;
297
    activeDrawBuffers = mom.activeDrawBuffers;
298
    if(fbo!=0){
299
    #ifdef TARGET_ANDROID
300
        ofAddListener(ofxAndroidEvents().reloadGL,this,&ofFbo::reloadFbo);
301
    #endif
302
    }
303
}
304

305
//--------------------------------------------------------------
306
ofFbo & ofFbo::operator=(const ofFbo & mom){
307
	if(&mom==this) return *this;
308
	clear();
309
	settings = mom.settings;
310
	bIsAllocated = mom.bIsAllocated;
311

312
	fbo = mom.fbo;
313
	retainFB(fbo);
314
	fboTextures = mom.fboTextures;
315
	if(settings.numSamples){
316
		retainFB(fboTextures);
317
    }
318
    if(mom.settings.depthStencilAsTexture){
319
        depthBufferTex = mom.depthBufferTex;
320
    }else{
321
        depthBuffer = mom.depthBuffer;
322
		retainRB(depthBuffer);
323
	}
324
	stencilBuffer = mom.stencilBuffer;
325
	retainRB(stencilBuffer);
326

327
	colorBuffers = mom.colorBuffers;
328
	for(int i=0;i<(int)colorBuffers.size();i++){
329
		retainRB(colorBuffers[i]);
330
	}
331
	textures = mom.textures;
332
	dirty = mom.dirty;
333
	defaultTextureIndex = mom.defaultTextureIndex;
334
    activeDrawBuffers = mom.activeDrawBuffers;
335
    if(fbo!=0){
336
    #ifdef TARGET_ANDROID
337
        ofAddListener(ofxAndroidEvents().reloadGL,this,&ofFbo::reloadFbo);
338
    #endif
339
    }
340
	return *this;
341
}
342

343
ofFbo::ofFbo(ofFbo && mom)
344
:settings(std::move(mom.settings))
345
,fbo(mom.fbo)
346
,fboTextures(mom.fboTextures)
347
,depthBuffer(mom.depthBuffer)
348
,stencilBuffer(mom.stencilBuffer)
349
,colorBuffers(std::move(mom.colorBuffers))
350
,textures(std::move(mom.textures))
351
,depthBufferTex(std::move(mom.depthBufferTex))
352
,activeDrawBuffers(std::move(mom.activeDrawBuffers))
353
,dirty(std::move(mom.dirty))
354
,defaultTextureIndex(std::move(mom.defaultTextureIndex))
355
,bIsAllocated(std::move(mom.bIsAllocated)){
356
    if(fbo!=0){
357
    #ifdef TARGET_ANDROID
358
        ofAddListener(ofxAndroidEvents().reloadGL,this,&ofFbo::reloadFbo);
359
    #endif
360
    }
361
    mom.fbo = 0;
362
    mom.depthBuffer = 0;
363
    mom.fboTextures = 0;
364
    mom.stencilBuffer = 0;
365
}
366

367
ofFbo & ofFbo::operator=(ofFbo && mom){
368
    if(&mom==this) return *this;
369
    clear();
370
    settings = std::move(mom.settings);
371
    bIsAllocated = std::move(mom.bIsAllocated);
372

373
    fbo = mom.fbo;
374
    fboTextures = mom.fboTextures;
375
    if(mom.settings.depthStencilAsTexture){
376
        depthBufferTex = std::move(mom.depthBufferTex);
377
    }else{
378
        depthBuffer = mom.depthBuffer;
379
    }
380
    stencilBuffer = std::move(mom.stencilBuffer);
381

382
    colorBuffers = std::move(mom.colorBuffers);
383
    textures = std::move(mom.textures);
384
    dirty = std::move(mom.dirty);
385
    defaultTextureIndex = std::move(mom.defaultTextureIndex);
386

387
    if(fbo!=0){
388
    #ifdef TARGET_ANDROID
389
        ofAddListener(ofxAndroidEvents().reloadGL,this,&ofFbo::reloadFbo);
390
    #endif
391
    }
392
    mom.fbo = 0;
393
    mom.depthBuffer = 0;
394
    mom.fboTextures = 0;
395
    mom.stencilBuffer = 0;
396
    return *this;
397
}
398

399
//--------------------------------------------------------------
400
ofFbo::~ofFbo(){
401
	clear();
402
}
403

404
//--------------------------------------------------------------
405
int	ofFbo::maxColorAttachments() {
406
	if(_maxColorAttachments<0) checkGLSupport();
407
	return _maxColorAttachments;
408
}
409

410
//--------------------------------------------------------------
411
int	ofFbo::maxDrawBuffers() {
412
	if(_maxDrawBuffers<0) checkGLSupport();
413
	return _maxDrawBuffers;
414
}
415

416
//--------------------------------------------------------------
417
int	ofFbo::maxSamples() {
418
	if(_maxSamples<0) checkGLSupport();
419
	return _maxSamples;
420
}
421

422

423
//--------------------------------------------------------------
424
void ofFbo::clear() {
425
	if(fbo){
426
		releaseFB(fbo);
427
		fbo=0;
428
	}
429
	if(depthBuffer){
430
		releaseRB(depthBuffer);
431
		depthBuffer = 0;
432
	}
433
	if(depthBufferTex.isAllocated()){
434
		depthBufferTex.clear();
435
	}
436
	if(stencilBuffer){
437
		releaseRB(stencilBuffer);
438
		stencilBuffer = 0;
439
	}
440
	if(settings.numSamples && fboTextures){
441
		releaseFB(fboTextures);
442
		fboTextures = 0;
443
	}
444
	textures.clear();
445
	for (int i=0; i < (int)colorBuffers.size(); i++) {
446
		releaseRB(colorBuffers[i]);
447
	}
448
	colorBuffers.clear();
449
	activeDrawBuffers.clear();
450
	bIsAllocated = false;
451
#ifdef TARGET_ANDROID
452
	ofRemoveListener(ofxAndroidEvents().reloadGL,this,&ofFbo::reloadFbo);
453
#endif
454
}
455

456

457
#ifndef TARGET_OPENGLES
458
//--------------------------------------------------------------
459
void ofFbo::clearColorBuffer(const ofFloatColor & color){
460
	glClearBufferfv(GL_COLOR, 0, &color.r);
461
}
462

463
//--------------------------------------------------------------
464
void ofFbo::clearColorBuffer(size_t buffer_idx, const ofFloatColor & color){
465
	glClearBufferfv(GL_COLOR, buffer_idx, &color.r);
466
}
467

468
//--------------------------------------------------------------
469
void ofFbo::clearDepthBuffer(float value){
470
	glClearBufferfv(GL_DEPTH, 0, &value);
471
}
472

473
//--------------------------------------------------------------
474
void ofFbo::clearStencilBuffer(int value){
475
	glClearBufferiv(GL_STENCIL, 0, &value);
476
}
477

478
//--------------------------------------------------------------
479
void ofFbo::clearDepthStencilBuffer(float depth, int stencil){
480
	glClearBufferfi(GL_DEPTH_STENCIL, 0, depth, stencil);
481
}
482
#endif
483

484
//--------------------------------------------------------------
485
void ofFbo::destroy() {
486
	clear();
487
}
488

489
//--------------------------------------------------------------
490
bool ofFbo::checkGLSupport() {
491
#ifndef TARGET_OPENGLES
492
	
493
	if (!ofIsGLProgrammableRenderer()){
494
		if(ofGLCheckExtension("GL_EXT_framebuffer_object")){
495
			ofLogVerbose("ofFbo") << "GL frame buffer object supported";
496
		}else{
497
			ofLogError("ofFbo") << "GL frame buffer object not supported by this graphics card";
498
			return false;
499
		}
500
	}
501

502
	glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &_maxColorAttachments);
503
	glGetIntegerv(GL_MAX_DRAW_BUFFERS, &_maxDrawBuffers);
504
	glGetIntegerv(GL_MAX_SAMPLES, &_maxSamples);
505

506
	ofLogVerbose("ofFbo") << "checkGLSupport(): "
507
                          << "maxColorAttachments: " << _maxColorAttachments << ", "
508
                          << "maxDrawBuffers: " << _maxDrawBuffers << ", "
509
                          << "maxSamples: " << _maxSamples;
510
#else
511

512
	if(ofIsGLProgrammableRenderer() || ofGLCheckExtension("GL_OES_framebuffer_object")){
513
		ofLogVerbose("ofFbo") << "GL frame buffer object supported";
514
	}else{
515
		ofLogError("ofFbo") << "GL frame buffer object not supported by this graphics card";
516
		return false;
517
	}
518
#endif
519

520
	return true;
521
}
522

523

524
//--------------------------------------------------------------
525
void ofFbo::allocate(int width, int height, int internalformat, int numSamples) {
526

527
	settings.width			= width;
528
	settings.height			= height;
529
	settings.internalformat	= internalformat;
530
	settings.numSamples		= numSamples;
531
    
532
#ifdef TARGET_OPENGLES
533
	settings.useDepth		= false;
534
	settings.useStencil		= false;
535
	//we do this as the fbo and the settings object it contains could be created before the user had the chance to disable or enable arb rect.
536
    settings.textureTarget	= GL_TEXTURE_2D;
537
#else
538
	settings.useDepth		= true;
539
	settings.useStencil		= true;
540
	//we do this as the fbo and the settings object it contains could be created before the user had the chance to disable or enable arb rect. 	
541
    settings.textureTarget	= ofGetUsingArbTex() ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D;    
542
#endif 
543
    
544
	allocate(settings);
545
}
546

547
//--------------------------------------------------------------
548
void ofFbo::allocate(ofFboSettings _settings) {
549
	if(!checkGLSupport()) return;
550

551
	clear();
552
	auto renderer = _settings.renderer.lock();
553
	if(renderer){
554
		settings.renderer = renderer;
555
	}else{
556
		settings.renderer = ofGetGLRenderer();
557
	}
558

559
	// check that passed values are correct
560
	if(_settings.width <= 0 || _settings.height <= 0){
561
		ofLogError("ofFbo") << "width and height have to be more than 0";
562
	}
563
	if(_settings.numSamples > maxSamples() && maxSamples() > -1) {
564
		ofLogWarning("ofFbo") << "allocate(): clamping numSamples " << _settings.numSamples << " to maxSamples " << maxSamples() << " for frame buffer object" << fbo;
565
		_settings.numSamples = maxSamples();
566
	}
567

568
	if(_settings.depthStencilAsTexture && _settings.numSamples){
569
		ofLogWarning("ofFbo") << "allocate(): multisampling not supported with depthStencilAsTexture, setting 0 samples for frame buffer object " << fbo;
570
		_settings.numSamples = 0;
571
	}
572

573
	//currently depth only works if stencil is enabled. 
574
	// http://forum.openframeworks.cc/index.php/topic,6837.0.html
575
#ifdef TARGET_OPENGLES
576
	if(_settings.useDepth){
577
	  	_settings.useStencil = true;
578
	}
579
    if( _settings.depthStencilAsTexture ){
580
        _settings.depthStencilAsTexture = false;
581
        ofLogWarning("ofFbo") << "allocate(): depthStencilAsTexture is not available for iOS";
582
    }
583
#endif
584
    
585
	GLenum depthAttachment = GL_DEPTH_ATTACHMENT;
586

587
	if( _settings.useDepth && _settings.useStencil ){
588
		_settings.depthStencilInternalFormat = GL_DEPTH_STENCIL;
589
		#ifdef TARGET_OPENGLES
590
			depthAttachment = GL_DEPTH_ATTACHMENT;
591
		#else
592
			depthAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
593
		#endif
594
	}else if(_settings.useDepth){
595
		depthAttachment = GL_DEPTH_ATTACHMENT;
596
	}else if(_settings.useStencil){
597
		depthAttachment = GL_STENCIL_ATTACHMENT;
598
		_settings.depthStencilInternalFormat = GL_STENCIL_INDEX;
599
	}
600

601
	// set needed values for allocation on instance settings
602
	// the rest will be set by the corresponding methods during allocation
603
	settings.width = _settings.width;
604
	settings.height = _settings.height;
605
	settings.numSamples = _settings.numSamples;
606

607
	// create main fbo
608
	// this is the main one we bind for drawing into
609
	// all the renderbuffers are attached to this (whether MSAA is enabled or not)
610
	glGenFramebuffers(1, &fbo);
611
	retainFB(fbo);
612

613
	GLint previousFboId = 0;
614

615
	// note that we are using a glGetInteger method here, which may stall the pipeline.
616
	// in the allocate() method, this is not that tragic since this will not be called 
617
	// within the draw() loop. Here, we need not optimise for performance, but for 
618
	// simplicity and readability .
619

620
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &previousFboId);
621
	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
622

623
	//- USE REGULAR RENDER BUFFER
624
	if(!_settings.depthStencilAsTexture){
625
		if(_settings.useDepth && _settings.useStencil){
626
			stencilBuffer = depthBuffer = createAndAttachRenderbuffer(_settings.depthStencilInternalFormat, depthAttachment);
627
			retainRB(stencilBuffer);
628
			retainRB(depthBuffer);
629
		}else if(_settings.useDepth){
630
			depthBuffer = createAndAttachRenderbuffer(_settings.depthStencilInternalFormat, depthAttachment);
631
			retainRB(depthBuffer);
632
		}else if(_settings.useStencil){
633
			stencilBuffer = createAndAttachRenderbuffer(_settings.depthStencilInternalFormat, depthAttachment);
634
			retainRB(stencilBuffer);
635
		}
636
	//- INSTEAD USE TEXTURE
637
	}else{
638
		if(_settings.useDepth || _settings.useStencil){
639
			createAndAttachDepthStencilTexture(_settings.textureTarget,_settings.depthStencilInternalFormat,depthAttachment);
640
			#ifdef TARGET_OPENGLES
641
				// if there's depth and stencil the texture should be attached as
642
				// depth and stencil attachments
643
				// http://www.khronos.org/registry/gles/extensions/OES/OES_packed_depth_stencil.txt
644
				if(_settings.useDepth && _settings.useStencil){
645
					glFramebufferTexture2D(GL_FRAMEBUFFER,
646
										   GL_STENCIL_ATTACHMENT,
647
										   GL_TEXTURE_2D, depthBufferTex.texData.textureID, 0);
648
				}
649
			#endif
650
		}
651
	}
652
    
653
    settings.useDepth = _settings.useDepth;
654
    settings.useStencil = _settings.useStencil;
655
    settings.depthStencilInternalFormat = _settings.depthStencilInternalFormat;
656
    settings.depthStencilAsTexture = _settings.depthStencilAsTexture;
657
    settings.textureTarget = _settings.textureTarget;
658
    settings.wrapModeHorizontal = _settings.wrapModeHorizontal;
659
    settings.wrapModeVertical = _settings.wrapModeVertical;
660
    settings.maxFilter = _settings.maxFilter;
661
    settings.minFilter = _settings.minFilter;
662

663
	// if we want MSAA, create a new fbo for textures
664
	#ifndef TARGET_OPENGLES
665
		if(_settings.numSamples){
666
			glGenFramebuffers(1, &fboTextures);
667
			retainFB(fboTextures);
668
		}else{
669
			fboTextures = fbo;
670
		}
671
	#else
672
		fboTextures = fbo;
673
		if(_settings.numSamples){
674
			ofLogWarning("ofFbo") << "allocate(): multisampling not supported in OpenGL ES";
675
		}
676
	#endif
677

678
	// now create all textures and color buffers
679
	if(_settings.colorFormats.size() > 0) {
680
		for(int i=0; i<(int)_settings.colorFormats.size(); i++) createAndAttachTexture(_settings.colorFormats[i], i);
681
	} else if(_settings.numColorbuffers > 0) {
682
		for(int i=0; i<_settings.numColorbuffers; i++) createAndAttachTexture(_settings.internalformat, i);
683
		_settings.colorFormats = settings.colorFormats;
684
	} else {
685
#ifndef TARGET_OPENGLES
686
		glDrawBuffer(GL_NONE);
687
#else
688
		ofLogWarning("ofFbo") << "allocate(): no color buffers specified for frame buffer object " << fbo;
689
#endif
690
	}
691
	settings.internalformat = _settings.internalformat;
692
	
693
	dirty.resize(_settings.colorFormats.size(), true); // we start with all color buffers dirty.
694

695
	// if textures are attached to a different fbo (e.g. if using MSAA) check it's status
696
	if(fbo != fboTextures) {
697
		glBindFramebuffer(GL_FRAMEBUFFER, fboTextures);
698
	}
699

700
	// check everything is ok with this fbo
701
	bIsAllocated = checkStatus();
702

703
	// restore previous framebuffer id
704
	glBindFramebuffer(GL_FRAMEBUFFER, previousFboId);
705

706
    /* UNCOMMENT OUTSIDE OF DOING RELEASES
707
	
708
    // this should never happen
709
	if(settings != _settings) ofLogWarning("ofFbo") << "allocation not complete, passed settings not equal to created ones, this is an internal OF bug";
710
    
711
    */
712
#ifdef TARGET_ANDROID
713
	ofAddListener(ofxAndroidEvents().reloadGL,this,&ofFbo::reloadFbo);
714
#endif
715
}
716

717
//--------------------------------------------------------------
718
void ofFbo::reloadFbo(){
719
	if(bIsAllocated){
720
		allocate(settings);
721
	}
722
}
723

724
//--------------------------------------------------------------
725
bool ofFbo::isAllocated() const {
726
	return bIsAllocated;
727
}
728

729
//----------------------------------------------------------
730
GLuint ofFbo::createAndAttachRenderbuffer(GLenum internalFormat, GLenum attachmentPoint) {
731
	GLuint buffer;
732
	glGenRenderbuffers(1, &buffer);
733
	glBindRenderbuffer(GL_RENDERBUFFER, buffer);
734
#ifndef TARGET_OPENGLES
735
	if (settings.numSamples==0) {
736
		glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, settings.width, settings.height);
737
	} else {
738
		glRenderbufferStorageMultisample(GL_RENDERBUFFER, settings.numSamples, internalFormat, settings.width, settings.height);
739
	}
740
#else
741
	if(ofGLSupportsNPOTTextures()){
742
		glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, settings.width, settings.height);
743
	}else{
744
		glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, ofNextPow2(settings.width), ofNextPow2(settings.height));
745
	}
746
#endif
747
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER, buffer);
748
	return buffer;
749
}
750

751
//----------------------------------------------------------
752
void ofFbo::createAndAttachTexture(GLenum internalFormat, GLenum attachmentPoint) {
753
	
754
	ofTextureData texData;
755

756
	texData.textureTarget = settings.textureTarget;
757
	texData.width = settings.width;
758
	texData.height = settings.height;
759
	texData.glInternalFormat = internalFormat;
760
	texData.bFlipTexture = false;
761
	texData.wrapModeHorizontal = settings.wrapModeHorizontal;
762
	texData.wrapModeVertical = settings.wrapModeVertical;
763
	texData.magFilter = settings.maxFilter;
764
	texData.minFilter = settings.minFilter;
765

766
	ofTexture tex;
767
	tex.allocate(texData);
768

769
    attachTexture(tex, internalFormat, attachmentPoint);
770
	dirty.push_back(true);
771
	activeDrawBuffers.push_back(GL_COLOR_ATTACHMENT0 + attachmentPoint);
772
}
773

774
//----------------------------------------------------------
775
void ofFbo::attachTexture(ofTexture & tex, GLenum internalFormat, GLenum attachmentPoint) {
776
    // bind fbo for textures (if using MSAA this is the newly created fbo, otherwise its the same fbo as before)
777
	GLint temp;
778
	glGetIntegerv(GL_FRAMEBUFFER_BINDING, &temp);
779
	glBindFramebuffer(GL_FRAMEBUFFER, fboTextures);
780
    
781
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + attachmentPoint, tex.texData.textureTarget, tex.texData.textureID, 0);
782
    if(attachmentPoint >= textures.size()) {
783
        textures.resize(attachmentPoint+1);
784
    }
785
    textures[attachmentPoint] = tex;
786
    
787
	settings.colorFormats.resize(attachmentPoint + 1);
788
	settings.colorFormats[attachmentPoint] = internalFormat;
789
	settings.numColorbuffers = settings.colorFormats.size();
790
    
791
	// if MSAA, bind main fbo and attach renderbuffer
792
	if(settings.numSamples) {
793
		glBindFramebuffer(GL_FRAMEBUFFER, fbo);
794
        
795
		GLuint colorBuffer = createAndAttachRenderbuffer(internalFormat, GL_COLOR_ATTACHMENT0 + attachmentPoint);
796
		colorBuffers.push_back(colorBuffer);
797
		retainRB(colorBuffer);
798
	}
799
	glBindFramebuffer(GL_FRAMEBUFFER, temp);
800

801
}
802

803
//----------------------------------------------------------
804
void ofFbo::createAndAttachDepthStencilTexture(GLenum target, GLint internalformat, GLenum  attachment, GLenum transferFormat, GLenum transferType){
805

806

807
	// allocate depthBufferTex as depth buffer;
808
	depthBufferTex.texData.glInternalFormat = internalformat;
809
	depthBufferTex.texData.textureTarget = target;
810
	depthBufferTex.texData.bFlipTexture = false;
811
	depthBufferTex.texData.width = settings.width;
812
	depthBufferTex.texData.height = settings.height;
813
	
814
	depthBufferTex.allocate(depthBufferTex.texData,transferFormat,transferType);
815

816
	glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, target, depthBufferTex.texData.textureID, 0);
817
}
818

819
//----------------------------------------------------------
820
void ofFbo::createAndAttachDepthStencilTexture(GLenum target, GLint internalformat, GLenum  attachment){
821

822
	// allocate depthBufferTex as depth buffer;
823
	depthBufferTex.texData.glInternalFormat = internalformat;
824
	depthBufferTex.texData.textureTarget = target;
825
	depthBufferTex.texData.bFlipTexture = false;
826
	depthBufferTex.texData.width = settings.width;
827
	depthBufferTex.texData.height = settings.height;
828
	
829
	depthBufferTex.allocate(depthBufferTex.texData);
830

831
	glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, target, depthBufferTex.texData.textureID, 0);
832
}
833

834
//----------------------------------------------------------
835
void ofFbo::begin(bool setupScreen) const{
836
	auto renderer = settings.renderer.lock();
837
	if(renderer){
838
        if(setupScreen){
839
            renderer->begin(*this, OF_FBOMODE_PERSPECTIVE | OF_FBOMODE_MATRIXFLIP);
840
        }else{
841
            renderer->begin(*this, OF_FBOMODE_NODEFAULTS);
842
        }
843
	}
844
}
845

846

847
void ofFbo::begin(ofFboMode mode) const{
848
    auto renderer = settings.renderer.lock();
849
    if(renderer){
850
        renderer->begin(*this, mode);
851
    }
852
}
853

854

855
//----------------------------------------------------------
856
/*void ofFbo::begin() const {
857
	auto renderer = settings.renderer.lock();
858
	if (renderer) {
859
		renderer->begin(*this, true);
860
	}
861
}
862

863
//----------------------------------------------------------
864
void ofFbo::beginNoPerspective() const {
865
	auto renderer = settings.renderer.lock();
866
	if (renderer) {
867
		renderer->begin(*this, false);
868
	}
869
}
870

871
//----------------------------------------------------------
872
void ofFbo::beginNoMatrixFlip() const {
873
	auto renderer = settings.renderer.lock();
874
	if (renderer) {
875
		renderer->beginNoMatrixFlip(*this);
876
	}
877
}
878

879
//----------------------------------------------------------
880
void ofFbo::beginNoMatrixFlipNoPerspective() const {
881
	auto renderer = settings.renderer.lock();
882
	if (renderer) {
883
		renderer->beginNoMatrixFlipNoPerspective(*this);
884
	}
885
}*/
886

887
//----------------------------------------------------------
888
void ofFbo::end() const{
889
	auto renderer = settings.renderer.lock();
890
	if(renderer){
891
		renderer->end(*this);
892
	}
893
}
894

895
//----------------------------------------------------------
896
void ofFbo::bind() const{
897
	auto renderer = settings.renderer.lock();
898
	if(renderer){
899
		renderer->bind(*this);
900
	}
901
}
902

903
//----------------------------------------------------------
904
void ofFbo::unbind() const{
905
	auto renderer = settings.renderer.lock();
906
	if(renderer){
907
		renderer->unbind(*this);
908
	}
909
}
910

911
//----------------------------------------------------------
912
void ofFbo::flagDirty() const{
913
	if (fbo != fboTextures){
914
		// ---------| if fbo != fboTextures, we are dealing with an MSAA enabled FBO.
915
		//
916
		// All currently active draw buffers need to be flagged dirty
917
		//
918
		// If a draw buffer has been activated and then de-activated, it has been 
919
		// flagged dirty at activation, so we can be sure all buffers which have 
920
		// been rendered to are flagged dirty.
921
		// 
922
		int numBuffersToFlag = std::min(dirty.size(), activeDrawBuffers.size());
923
		for(int i=0; i < numBuffersToFlag; i++){
924
			dirty[i] = true;
925
		}
926
	}
927
}
928

929
//----------------------------------------------------------
930
int ofFbo::getNumTextures() const {
931
	return textures.size();
932
}
933

934
//----------------------------------------------------------
935
void ofFbo::setActiveDrawBuffer(int i){
936
	if(!bIsAllocated) return;
937
#ifndef TARGET_OPENGLES
938
	vector<int> activebuffers(1, i);
939
	setActiveDrawBuffers(activebuffers);
940
#endif
941
}
942

943
//----------------------------------------------------------
944
void ofFbo::setActiveDrawBuffers(const vector<int>& ids){
945
	if(!bIsAllocated) return;
946
#ifndef TARGET_OPENGLES
947
    int numBuffers = activeDrawBuffers.size();
948
	activeDrawBuffers.clear();
949
	activeDrawBuffers.resize(numBuffers, GL_NONE); // we initialise the vector with GL_NONE, so a buffer will not be written to unless activated.
950
    for(int i=0; i < (int)ids.size(); i++){
951
      int id = ids[i];
952
        if (id < getNumTextures()){
953
            GLenum e = GL_COLOR_ATTACHMENT0 + id;
954
            activeDrawBuffers[id] = e; // activate requested buffers
955
			dirty[id] = true; // dirty activated draw buffers.
956
        }else{
957
            ofLogWarning("ofFbo") << "setActiveDrawBuffers(): fbo " << fbo << " couldn't set texture " << i << ", only " << getNumTextures() << "allocated";
958
        }
959
    }
960
    glDrawBuffers(activeDrawBuffers.size(),&activeDrawBuffers[0]);
961
#endif
962
}
963

964
//----------------------------------------------------------
965
void ofFbo::activateAllDrawBuffers(){
966
	if(!bIsAllocated) return;
967
#ifndef TARGET_OPENGLES
968
    vector<int> activeBuffers(getNumTextures(),0);
969
    for(int i=0; i < getNumTextures(); i++){
970
    	activeBuffers[i] = i;
971
    }
972
    setActiveDrawBuffers(activeBuffers);
973
#endif
974
}
975

976
//----------------------------------------------------------
977
void ofFbo::setDefaultTextureIndex(int defaultTexture)
978
{
979
	defaultTextureIndex = defaultTexture;
980
}
981

982
//----------------------------------------------------------
983
int ofFbo::getDefaultTextureIndex() const
984
{
985
	return defaultTextureIndex;
986
}
987

988
//----------------------------------------------------------
989
ofTexture& ofFbo::getTextureReference(){
990
	return getTexture();
991
}
992

993
//----------------------------------------------------------
994
ofTexture& ofFbo::getTextureReference(int attachmentPoint) {
995
	return getTexture(attachmentPoint);
996
}
997

998
//----------------------------------------------------------
999
const ofTexture& ofFbo::getTextureReference() const{
1000
	return getTexture();
1001
}
1002

1003
//----------------------------------------------------------
1004
const ofTexture& ofFbo::getTextureReference(int attachmentPoint) const{
1005
	return getTexture(attachmentPoint);
1006
}
1007

1008
//----------------------------------------------------------
1009
ofTexture& ofFbo::getTexture(){
1010
	return getTexture(defaultTextureIndex);
1011
}
1012

1013
//----------------------------------------------------------
1014
ofTexture& ofFbo::getTexture(int attachmentPoint) {
1015
	updateTexture(attachmentPoint);
1016
    
1017
    return textures[attachmentPoint];
1018
}
1019

1020
//----------------------------------------------------------
1021
const ofTexture& ofFbo::getTexture() const{
1022
	return getTexture(defaultTextureIndex);
1023
}
1024

1025
//----------------------------------------------------------
1026
const ofTexture& ofFbo::getTexture(int attachmentPoint) const{
1027
	ofFbo * mutThis = const_cast<ofFbo*>(this);
1028
	mutThis->updateTexture(attachmentPoint);
1029

1030
    return textures[attachmentPoint];
1031
}
1032

1033
//----------------------------------------------------------
1034
void ofFbo::setAnchorPercent(float xPct, float yPct){
1035
	getTexture().setAnchorPercent(xPct, yPct);
1036
}
1037

1038
//----------------------------------------------------------
1039
void ofFbo::setAnchorPoint(float x, float y){
1040
	getTexture().setAnchorPoint(x, y);
1041
}
1042

1043
//----------------------------------------------------------
1044
void ofFbo::resetAnchor(){
1045
	getTexture().resetAnchor();
1046
}
1047

1048
//----------------------------------------------------------
1049
void ofFbo::readToPixels(ofPixels & pixels, int attachmentPoint) const{
1050
	if(!bIsAllocated) return;
1051
#ifndef TARGET_OPENGLES
1052
	getTexture(attachmentPoint).readToPixels(pixels);
1053
#else
1054
	pixels.allocate(settings.width,settings.height,ofGetImageTypeFromGLType(settings.internalformat));
1055
	bind();
1056
	int format = ofGetGLFormatFromInternal(settings.internalformat);
1057
	glReadPixels(0,0,settings.width, settings.height, format, GL_UNSIGNED_BYTE, pixels.getData());
1058
	unbind();
1059
#endif
1060
}
1061

1062
//----------------------------------------------------------
1063
void ofFbo::readToPixels(ofShortPixels & pixels, int attachmentPoint) const{
1064
	if(!bIsAllocated) return;
1065
#ifndef TARGET_OPENGLES
1066
	getTexture(attachmentPoint).readToPixels(pixels);
1067
#else
1068
	pixels.allocate(settings.width,settings.height,ofGetImageTypeFromGLType(settings.internalformat));
1069
	bind();
1070
	int format = ofGetGLFormatFromInternal(settings.internalformat);
1071
	glReadPixels(0,0,settings.width, settings.height, format, GL_UNSIGNED_SHORT, pixels.getData());
1072
	unbind();
1073
#endif
1074
}
1075

1076
//----------------------------------------------------------
1077
void ofFbo::readToPixels(ofFloatPixels & pixels, int attachmentPoint) const{
1078
	if(!bIsAllocated) return;
1079
#ifndef TARGET_OPENGLES
1080
	getTexture(attachmentPoint).readToPixels(pixels);
1081
#else
1082
	pixels.allocate(settings.width,settings.height,ofGetImageTypeFromGLType(settings.internalformat));
1083
	bind();
1084
	int format = ofGetGLFormatFromInternal(settings.internalformat);
1085
	glReadPixels(0,0,settings.width, settings.height, format, GL_FLOAT, pixels.getData());
1086
	unbind();
1087
#endif
1088
}
1089

1090
#ifndef TARGET_OPENGLES
1091
//----------------------------------------------------------
1092
void ofFbo::copyTo(ofBufferObject & buffer) const{
1093
	if(!bIsAllocated) return;
1094
	bind();
1095
	buffer.bind(GL_PIXEL_PACK_BUFFER);
1096
	glReadPixels(0, 0, settings.width, settings.height, ofGetGLFormatFromInternal(settings.internalformat), ofGetGLTypeFromInternal(settings.internalformat), NULL);
1097
	buffer.unbind(GL_PIXEL_PACK_BUFFER);
1098
	unbind();
1099
}
1100
#endif
1101

1102
//----------------------------------------------------------
1103
void ofFbo::updateTexture(int attachmentPoint) {
1104
	if(!bIsAllocated) return;
1105
#ifndef TARGET_OPENGLES
1106
	if(fbo != fboTextures && dirty[attachmentPoint]) {
1107
		
1108
		// if fbo != fboTextures, we are dealing with an MSAA enabled FBO.
1109
		// and we need to blit one fbo into another to see get the texture
1110
		// content
1111

1112
		if (!ofIsGLProgrammableRenderer()){
1113
			// save current drawbuffer
1114
			glPushAttrib(GL_COLOR_BUFFER_BIT);
1115
		}
1116

1117
		auto renderer = settings.renderer.lock();
1118
		if(renderer){
1119
			GLint readBuffer;
1120
			glGetIntegerv(GL_READ_BUFFER, &readBuffer);
1121
			
1122
			renderer->bindForBlitting(*this,*this,attachmentPoint);
1123
			glBlitFramebuffer(0, 0, settings.width, settings.height, 0, 0, settings.width, settings.height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1124
			renderer->unbind(*this);
1125
			
1126
			glReadBuffer(readBuffer);
1127
		}
1128

1129
		if(!ofIsGLProgrammableRenderer()){
1130
			// restore current drawbuffer
1131
			glPopAttrib();
1132
		}
1133
		dirty[attachmentPoint] = false;
1134
	}
1135
#endif
1136
}
1137

1138
//----------------------------------------------------------
1139
void ofFbo::draw(float x, float y) const{
1140
	draw(x, y, settings.width, settings.height);
1141
}
1142

1143
//----------------------------------------------------------
1144
void ofFbo::draw(float x, float y, float width, float height) const{
1145
	if(!bIsAllocated || settings.numColorbuffers==0) return;
1146
    getTexture().draw(x, y, width, height);
1147
}
1148

1149
//----------------------------------------------------------
1150
GLuint ofFbo::getFbo() const {
1151
	return fbo;
1152
}
1153

1154
//----------------------------------------------------------
1155
GLuint ofFbo::getId() const {
1156
	return fbo;
1157
}
1158

1159
//----------------------------------------------------------
1160
GLuint ofFbo::getIdDrawBuffer() const{
1161
	return fboTextures;
1162
}
1163

1164
//----------------------------------------------------------
1165
float ofFbo::getWidth() const {
1166
	return settings.width;
1167
}
1168

1169

1170
//----------------------------------------------------------
1171
float ofFbo::getHeight() const {
1172
	return settings.height;
1173
}
1174

1175

1176
//----------------------------------------------------------
1177
bool ofFbo::checkStatus() const {
1178
	GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1179
	switch(status) {
1180
		case GL_FRAMEBUFFER_COMPLETE:
1181
			ofLogVerbose("ofFbo") << "FRAMEBUFFER_COMPLETE - OK";
1182
			return true;
1183
		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
1184
			ofLogError("ofFbo") << "FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
1185
			break;
1186
		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
1187
			ofLogError("ofFbo") << "FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
1188
			break;
1189
		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
1190
			ofLogError("ofFbo") << "FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
1191
			break;
1192
#ifndef TARGET_PROGRAMMABLE_GL
1193
		case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
1194
			ofLogError("ofFbo") << "FRAMEBUFFER_INCOMPLETE_FORMATS";
1195
			break;
1196
#endif
1197
		case GL_FRAMEBUFFER_UNSUPPORTED:
1198
			ofLogError("ofFbo") << "FRAMEBUFFER_UNSUPPORTED";
1199
			break;
1200
#ifndef TARGET_OPENGLES
1201
		case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
1202
			ofLogWarning("ofFbo") << "FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER";
1203
			break;
1204
		case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
1205
			ofLogError("ofFbo") << "FRAMEBUFFER_INCOMPLETE_READ_BUFFER";
1206
			break;
1207
		case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
1208
			ofLogError("ofFbo") << "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE";
1209
			break;
1210
#endif
1211
		default:
1212
			ofLogError("ofFbo") << "UNKNOWN ERROR " << status;
1213
			break;
1214

1215
	}
1216

1217
	return false;
1218
}
1219

1220
//----------------------------------------------------------
1221
ofTexture & ofFbo::getDepthTexture(){
1222
	if(!settings.depthStencilAsTexture){
1223
		ofLogError("ofFbo") << "getDepthTexture(): frame buffer object " << fbo << " not allocated with depthStencilAsTexture";
1224
	}
1225
	return depthBufferTex;
1226
}
1227

1228
//----------------------------------------------------------
1229
const ofTexture & ofFbo::getDepthTexture() const{
1230
	if(!settings.depthStencilAsTexture){
1231
		ofLogError("ofFbo") << "getDepthTexture(): frame buffer object " << fbo << " not allocated with depthStencilAsTexture";
1232
	}
1233
	return depthBufferTex;
1234
}
1235

1236
//#endif
1237

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

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

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

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