framework2

Форк
0
1222 строки · 37.7 Кб
1
//
2
//  ofShadow.cpp
3
//  openFrameworksLib
4
//
5
//  Created by Nick Hardeman on 10/3/22.
6
//
7

8
#include "ofShadow.h"
9
#include "of3dUtils.h"
10
#include "ofGLBaseTypes.h"
11
#include "ofGLUtils.h"
12
#include "ofLight.h"
13
#include "ofGLProgrammableRenderer.h"
14
#include "ofConstants.h"
15

16
#define GLM_FORCE_CTOR_INIT
17
#include "glm/gtx/transform.hpp"
18
#include "glm/gtc/quaternion.hpp"
19

20
using std::weak_ptr;
21
using std::vector;
22
using std::shared_ptr;
23

24

25
//----------------------------------------
26
vector<weak_ptr<ofShadow::Data> > & ofShadowsData(){
27
	static vector<weak_ptr<ofShadow::Data> > * shadowsActive = ofIsGLProgrammableRenderer()?new vector<weak_ptr<ofShadow::Data> >:new vector<weak_ptr<ofShadow::Data> >(8);
28
	return *shadowsActive;
29
}
30

31
//--------------------------------------------------------------
32
static std::map< int, ofShadow::GLData > & getGLDatas(){
33
	static std::map< int,ofShadow::GLData > * idsFB = new std::map< int,ofShadow::GLData >;
34
	return *idsFB;
35
}
36

37
//--------------------------------------------------------------
38
static ofShadow::GLData& getGLData( int aLightType ) {
39
	if( getGLDatas().count(aLightType) < 1 ) {
40
		getGLDatas()[aLightType] = ofShadow::GLData();
41
	}
42
	return getGLDatas()[aLightType];
43
}
44

45
//--------------------------------------------------------------
46
static void retainFBO(int aLightType){
47
	if( !getGLData(aLightType).bAllocated ) {
48
		ofLogVerbose("ofShadow :: retainFBO : for light ") << aLightType << " | " << ofGetFrameNum();
49
		getGLData(aLightType).bAllocated = true;
50
		glGenFramebuffers(1, &getGLDatas()[aLightType].fboId);
51
		glGenTextures(1, &getGLDatas()[aLightType].texId);
52
	}
53
}
54

55
//--------------------------------------------------------------
56
static GLuint getFBOId( int aLightType ) {
57
	retainFBO(aLightType);
58
	return getGLData(aLightType).fboId;
59
}
60
//--------------------------------------------------------------
61
static GLuint getFBODepthTexId( int aLightType ) {
62
	retainFBO(aLightType);
63
	return getGLData(aLightType).texId;
64
}
65

66
//--------------------------------------------------------------
67
static void releaseFBO(int aLightType){
68
	if( getGLData(aLightType).bAllocated ){
69
		ofLogVerbose("ofShadow :: releaseFBO : for light ") << aLightType << " | " << ofGetFrameNum();
70
		glDeleteTextures(1, &getGLDatas()[aLightType].texId );
71
		glDeleteFramebuffers(1, &getGLDatas()[aLightType].fboId );
72
		getGLDatas()[aLightType].bAllocated = false;
73
		getGLDatas()[aLightType].bFboAllocated = false;
74
	}
75
}
76

77
//----------------------------------------
78
int ofShadow::getNumTotalPossibleShadows( int aLightType ) {
79
	
80
	GLenum texTarget = getTextureTarget( aLightType );
81
	if( texTarget == GL_TEXTURE_CUBE_MAP) {
82
		return 1;
83
	}
84
	if( texTarget == GL_TEXTURE_2D ) {
85
		return 1;
86
	}
87
	// a bit of an arbitrary selection here
88
	return 64;
89
}
90

91
//----------------------------------------
92
GLenum ofShadow::getTextureTarget( int aLightType ) {
93
	
94
//	#if !defined(TARGET_OPENGLES)
95
	if( aLightType == OF_LIGHT_POINT ) {
96
		#if !defined(TARGET_OPENGLES)
97
		if( ofGetGLRenderer() && ofGetGLRenderer()->getGLVersionMajor() < 4 ) {
98
			// does not support cube map arrays in openGL < 4 glsl shader
99
			return GL_TEXTURE_CUBE_MAP;
100
		}
101
		#else
102
		return GL_TEXTURE_CUBE_MAP;
103
		#endif
104
	}
105
//	#endif
106
	
107
	if( aLightType == OF_LIGHT_POINT ) {
108
		#ifdef GL_TEXTURE_CUBE_MAP_ARRAY
109
		#ifdef glTexImage3D
110
		return GL_TEXTURE_CUBE_MAP_ARRAY;
111
		#endif
112
		#endif
113
		return GL_TEXTURE_CUBE_MAP;
114
	}
115
	#ifdef GL_TEXTURE_2D_ARRAY
116
	#ifdef glTexImage3D
117
	return GL_TEXTURE_2D_ARRAY;
118
	#endif
119
	#endif
120
	return GL_TEXTURE_2D;
121
}
122

123
//--------------------------------------------------------------
124
void ofShadow::setDepthMapResolution( int aLightType, int ares ) {
125
	setDepthMapResolution( aLightType, ares, ares );
126
}
127

128
//--------------------------------------------------------------
129
void ofShadow::setDepthMapResolution( int aLightType, int awidth, int aheight ) {
130
	if( aLightType == OF_LIGHT_POINT ) {
131
		// rendering to a cube, so needs to be the same
132
		aheight = awidth;
133
	}
134
	
135
	ofLogVerbose("ofShadow :: setDepthMapResolution : incoming: " ) << awidth << " x " << aheight << " current: " << getDepthMapWidth(aLightType) << " x " << getDepthMapHeight(aLightType) << " | " << ofGetFrameNum();
136
	
137
	if( awidth != getDepthMapWidth(aLightType) || aheight != getDepthMapHeight(aLightType) ) {
138
		getGLData(aLightType).width = awidth;
139
		getGLData(aLightType).height = aheight;
140
		releaseFBO(aLightType);
141
	}
142
}
143

144
//--------------------------------------------------------------
145
int ofShadow::getDepthMapWidth(int aLightType) {
146
	return getGLData(aLightType).width;
147
}
148

149
//--------------------------------------------------------------
150
int ofShadow::getDepthMapHeight(int aLightType) {
151
	return getGLData(aLightType).height;
152
}
153

154
//--------------------------------------------------------------
155
GLuint ofShadow::getPointTexId() {
156
	_updateTexDataIds();
157
	return getFBODepthTexId(OF_LIGHT_POINT);
158
}
159

160
//--------------------------------------------------------------
161
GLuint ofShadow::getDirectionalTexId() {
162
	_updateTexDataIds();
163
	return getFBODepthTexId(OF_LIGHT_DIRECTIONAL);
164
}
165

166
//--------------------------------------------------------------
167
GLuint ofShadow::getSpotTexId() {
168
	_updateTexDataIds();
169
	return getFBODepthTexId(OF_LIGHT_SPOT);
170
}
171

172
//--------------------------------------------------------------
173
GLuint ofShadow::getAreaTexId() {
174
	_updateTexDataIds();
175
	return getFBODepthTexId(OF_LIGHT_AREA);
176
}
177

178
//--------------------------------------------------------------
179
std::string ofShadow::getShadowTypeAsString( ofShadowType atype ) {
180
	switch( atype ) {
181
		case OF_SHADOW_TYPE_HARD:
182
			return "Hard";
183
		case OF_SHADOW_TYPE_PCF_LOW:
184
			return "PCF Low";
185
		case OF_SHADOW_TYPE_PCF_MED:
186
			return "PCF Medium";
187
		case OF_SHADOW_TYPE_PCF_HIGH:
188
			return "PCF High";
189
		case OF_SHADOW_TYPE_TOTAL:
190
			return "Total";
191
	}
192
	return "Default";
193
}
194

195
//--------------------------------------------------------------
196
bool ofShadow::hasActiveShadows() {
197
	for(size_t i=0;i< ofShadowsData().size();i++){
198
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
199
		if(shadow && shadow->isEnabled && shadow->index > -1 ){
200
			return true;
201
			break;
202
		}
203
	}
204
	return false;
205
}
206

207
//--------------------------------------------------------------
208
void ofShadow::enableAllShadows() {
209
	if( !areShadowsSupported() ) {
210
		ofLogWarning("ofShadow :: enableAllShadows : only works with programmable renderer.");
211
		return;
212
	}
213
	
214
	for(size_t i=0;i<ofShadowsData().size();i++){
215
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
216
		if(!shadow || shadow->index < 0 ){
217
			continue;
218
		}
219
		shadow->isEnabled = true;
220
	}
221
}
222

223
//--------------------------------------------------------------
224
void ofShadow::disableAllShadows() {
225
	for(size_t i=0;i<ofShadowsData().size();i++){
226
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
227
		if(!shadow || shadow->index < 0 ){
228
			continue;
229
		}
230
		shadow->isEnabled = false;
231
	}
232
}
233

234
//--------------------------------------------------------------
235
void ofShadow::setAllShadowTypes( ofShadowType atype ) {
236
	if( !ofIsGLProgrammableRenderer() ) {
237
		ofLogWarning("ofShadow :: setAllShadowTypes : only works with programmable renderer.");
238
		return;
239
	}
240
	for(size_t i=0;i<ofShadowsData().size();i++){
241
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
242
		if(!shadow || shadow->index < 0 ){
243
			continue;
244
		}
245
		shadow->shadowType = atype;
246
	}
247
}
248

249
//--------------------------------------------------------------
250
void ofShadow::setAllShadowDepthResolutions(int awidth, int aheight ) {
251
	if( !ofIsGLProgrammableRenderer() ) {
252
		ofLogWarning("ofShadow :: setAllShadowDepthResolutions : only works with programmable renderer.");
253
		return;
254
	}
255
	setDepthMapResolution( OF_LIGHT_POINT, awidth, aheight );
256
	setDepthMapResolution( OF_LIGHT_DIRECTIONAL, awidth, aheight );
257
	setDepthMapResolution( OF_LIGHT_SPOT, awidth, aheight );
258
	setDepthMapResolution( OF_LIGHT_AREA, awidth, aheight );
259
}
260

261
//--------------------------------------------------------------
262
void ofShadow::setAllShadowBias( float bias ) {
263
	if( !ofIsGLProgrammableRenderer() ) {
264
		ofLogWarning("ofShadow :: setAllShadowBias : only works with programmable renderer.");
265
		return;
266
	}
267
	for(size_t i=0;i<ofShadowsData().size();i++){
268
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
269
		if(!shadow || shadow->index < 0 ){
270
			continue;
271
		}
272
		shadow->bias = bias;
273
	}
274
}
275

276
//--------------------------------------------------------------
277
void ofShadow::setAllShadowNormalBias( float normalBias ) {
278
	if( !ofIsGLProgrammableRenderer() ) {
279
		ofLogWarning("ofShadow :: setAllShadowNormalBias : only works with programmable renderer.");
280
		return;
281
	}
282
	for(size_t i=0;i<ofShadowsData().size();i++){
283
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
284
		if(!shadow || shadow->index < 0 ){
285
			continue;
286
		}
287
		shadow->normalBias = normalBias;
288
	}
289
}
290

291
//--------------------------------------------------------------
292
void ofShadow::setAllShadowSampleRadius( float sampleRadius ) {
293
	if( !ofIsGLProgrammableRenderer() ) {
294
		ofLogWarning("ofShadow :: enableAllShadows : only works with programmable renderer.");
295
		return;
296
	}
297
	for(size_t i=0;i<ofShadowsData().size();i++){
298
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
299
		if(!shadow || shadow->index < 0 ){
300
			continue;
301
		}
302
		shadow->sampleRadius = sampleRadius;
303
	}
304
}
305

306
//--------------------------------------------------------------
307
std::string ofShadow::getShaderDefinesAsString() {
308
	std::string definesString = "";
309
	if( areShadowsSupported() ) {
310
		if( ofShadowsData().size() > 0 && ofLightsData().size() > 0) {
311
			definesString += "#define HAS_SHADOWS 1\n";
312
		}
313
		
314
		if( ofShadow::getTextureTarget( OF_LIGHT_POINT ) != GL_TEXTURE_CUBE_MAP ) {
315
			definesString += "#define SHADOWS_USE_CUBE_MAP_ARRAY 1\n";
316
		}
317
		
318
		if( ofShadow::getTextureTarget( OF_LIGHT_DIRECTIONAL ) != GL_TEXTURE_2D ) {
319
			definesString += "#define SHADOWS_USE_TEXTURE_ARRAY 1\n";
320
		}
321
	}
322
	return definesString;
323
}
324

325
//--------------------------------------------------------------
326
bool ofShadow::areShadowsSupported() {
327
	#if defined(TARGET_OPENGLES) && !defined(TARGET_EMSCRIPTEN)
328
	return false;
329
	#endif
330
	
331
	if(!ofIsGLProgrammableRenderer() ) {
332
		return false;
333
	}
334
	return true;
335
}
336

337
//--------------------------------------------------------------
338
void ofShadow::_updateTexDataIds() {
339
	std::map<int, int> texIdMap;
340
	
341
	for(size_t i=0;i< ofShadowsData().size();i++){
342
		std::shared_ptr<ofShadow::Data> shadow = ofShadowsData()[i].lock();
343
		if(!shadow || !shadow->isEnabled || shadow->index < 0 ){
344
			continue;
345
		}
346
		
347
		if( texIdMap.count((int)shadow->lightType) < 0 ) {
348
			texIdMap[(int)shadow->lightType] = 0;
349
		}
350
		shadow->texIndex = texIdMap[(int)shadow->lightType];
351
		
352
		texIdMap[(int)shadow->lightType]++;
353
	}
354
}
355

356
//--------------------------------------------------------------
357
ofShadow::ofShadow() {
358
	data = std::make_shared<ofShadow::Data>();
359
	data->shadowMatrix = glm::mat4(1.0f);
360
	setSingleOmniPass(true);
361
#if defined(TARGET_OPENGLES)
362
	setSingleOmniPass(false);
363
#endif
364
	_checkSetup();
365
}
366

367
//--------------------------------------------------------------
368
ofShadow::~ofShadow() {
369
	clear();
370
}
371

372
//--------------------------------------------------------------
373
void ofShadow::setLightType( int atype ) {
374
	
375
	if( (ofLightType)atype != data->lightType ) {
376
		clear();
377
	}
378
	data->lightType = atype;
379
	data->numDepthPasses = getNumShadowDepthPasses();
380
	if( getIsEnabled() ) {
381
		_checkFbos();
382
		_allocate();
383
	}
384
}
385

386
//--------------------------------------------------------------
387
void ofShadow::update( const ofLight& alight ) {
388
	
389
	if( !data->isEnabled ) {
390
		return;
391
	}
392
	
393
	glm::quat rq = alight.getGlobalOrientation();
394
	glm::vec3 lookAtDir(glm::normalize( rq * glm::vec4(0.f,0.f,-1.f, 1.f)));
395
	
396
	setLightType( (ofLightType)alight.getType() );
397
	
398
	data->position = alight.getGlobalPosition();
399
	data->direction = glm::normalize(lookAtDir);
400
	data->up = rq * glm::vec3(0.0,1.0,0.0);
401
	data->right = rq * glm::vec3(1.0,0.0,0.0);
402
	
403
	unsigned int targetNumMatrices = 1;
404
	if(data->lightType == OF_LIGHT_POINT) {
405
		targetNumMatrices = 6;
406
	}
407
	
408
	if( mLookAtMats.size() != targetNumMatrices ) {
409
		mLookAtMats.clear();
410
		mLookAtMats.assign(targetNumMatrices, glm::mat4(1.0) );
411
	}
412
	if( mViewProjMats.size() != targetNumMatrices ) {
413
		mViewProjMats.clear();
414
		mViewProjMats.assign( targetNumMatrices, glm::mat4(1.0) );
415
	}
416
	
417
	if( data->lightType == OF_LIGHT_SPOT || data->lightType == OF_LIGHT_AREA ) {
418
		if(data->lightType == OF_LIGHT_SPOT) {
419
			mFov = alight.getSpotlightCutOff() * 2.0f;
420
		}
421
		float aspectRatio = (float)getDepthMapWidth() / (float)getDepthMapHeight();
422
		if( data->lightType == OF_LIGHT_AREA ) {
423
			mFov = 90;
424
			aspectRatio = mAreaLightWidth / mAreaLightHeight;
425
		}
426
		
427
		mShadowProjection = glm::perspective(glm::radians(mFov), aspectRatio, getNearClip(), getFarClip());
428
		mLookAtMats[0] = glm::lookAt( data->position, data->position + data->direction, glm::vec3(0.0, 1.0, 0.0) );
429
		mViewProjMats[0] = mShadowProjection * mLookAtMats[0];
430
		data->shadowMatrix = biasMatrix * mViewProjMats[0];
431
	} else if( data->lightType == OF_LIGHT_DIRECTIONAL ) {
432
		
433
		mOrthoScaleX = 1.0;
434
		if( mDirectionalBoundsWidth > -1 ) {
435
			mOrthoScaleX = mDirectionalBoundsWidth / (float)getDepthMapWidth();
436
		}
437
		
438
		mOrthoScaleY = 1.0;
439
		if( mDirectionalBoundsHeight > -1 ) {
440
			mOrthoScaleY = mDirectionalBoundsHeight / (float)getDepthMapHeight();
441
		}
442
		
443
		float viewWidth = getGLData(data->lightType).width;
444
		float viewHeight = getGLData(data->lightType).height;//
445
		mShadowProjection = glm::ortho(
446
				   - viewWidth/2 * mOrthoScaleX,
447
				   + viewWidth/2 * mOrthoScaleX,
448
				   - viewHeight/2 * mOrthoScaleY,
449
				   + viewHeight/2 * mOrthoScaleY,
450
									   getNearClip(),
451
									   getFarClip()
452
									   );
453
		mLookAtMats[0] = glm::lookAt( data->position, data->position + data->direction, glm::vec3(0.0, 1.0, 0.0) );
454
		mViewProjMats[0] = mShadowProjection * mLookAtMats[0];
455
		data->shadowMatrix = biasMatrix * mViewProjMats[0];
456
		
457
	} else if( data->lightType == OF_LIGHT_POINT ) {
458
		mFov = 90.f;
459
		// aspect is 1.0 since width and height should be the same
460
		mShadowProjection = glm::perspective(glm::radians(mFov), 1.0f, getNearClip(), getFarClip() );
461
		// eye, target and up vector
462
		// +x, -x, +y, -y, +z and -z direction
463
		mLookAtMats[0] = glm::lookAt( data->position, data->position + glm::vec3(1,0,0), glm::vec3(0, -1, 0) );
464
		mLookAtMats[1] = glm::lookAt( data->position, data->position + glm::vec3(-1,0,0), glm::vec3(0, -1, 0) );
465
		mLookAtMats[2] = glm::lookAt( data->position, data->position + glm::vec3(0,1,0), glm::vec3(0, 0, 1) );
466
		mLookAtMats[3] = glm::lookAt( data->position, data->position + glm::vec3(0,-1,0), glm::vec3(0, 0, -1) );
467
		mLookAtMats[4] = glm::lookAt( data->position, data->position + glm::vec3(0,0,1), glm::vec3(0, -1, 0) );
468
		mLookAtMats[5] = glm::lookAt( data->position, data->position + glm::vec3(0,0,-1), glm::vec3(0, -1, 0) );
469
		
470
		for( size_t i = 0; i < 6; i++ ) {
471
			mViewProjMats[i] = mShadowProjection * mLookAtMats[i];
472
		}
473
	}
474
}
475

476
//----------------------------------------------------
477
bool ofShadow::beginDepth() {
478
	
479
	if( !areShadowsSupported() ) {
480
		ofLogWarning("ofShadow :: beginDepth() : shadows only work with programmable renderer.");
481
		setEnabled(false);
482
	}
483
	
484
	if( !getIsEnabled() ) {
485
		return false;
486
	}
487
	
488
	_allocateFbo();
489
	
490
	auto glRenderer = ofGetGLRenderer();
491
	if(!glRenderer){
492
		return false;
493
	}
494
	
495
	if( data->lightType == OF_LIGHT_POINT ) {
496
		if( !isSingleOmniPass() ) {
497
			ofLogWarning("ofShadow :: beginDepth : must call beginDepth(cubeFace) when using point light without single pass.");
498
			return false;
499
		}
500
	}
501
	
502
	if( data->texIndex+1 > getNumTotalPossibleShadows(data->lightType) ) {
503
		ofLogWarning( "ofShadow :: too many shadows detected for light type " ) << data->lightType<<". Total supported for light type: " << getNumTotalPossibleShadows(data->lightType);
504
	}
505
	
506
//
507
	
508
	glBindFramebuffer( GL_FRAMEBUFFER, getDepthMapFboId() );
509
	if( data->lightType == OF_LIGHT_POINT ) {
510
		// handled in the depthCubeGeom shader
511
//		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, getDepthMapTexId(), 0, (data->texIndex * 6));
512
	} else {
513
		#ifdef glFramebufferTextureLayer
514
		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, getDepthMapTexId(), 0, data->texIndex );
515
		#else
516
		
517
		auto texTarget = getTextureTarget( data->lightType );
518
		if( texTarget == GL_TEXTURE_2D ) {
519
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, getDepthMapTexId(), 0);
520
		} else {
521
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, data->texIndex, getDepthMapTexId(), 0);
522
		}
523
		
524
		//glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, data->texIndex, getDepthMapTexId(), 0);
525
		#endif
526
	}
527
	
528
	ofPushView();
529
	ofViewport(0, 0, getDepthMapWidth(), getDepthMapHeight(), false);
530
	
531
	glClear(GL_DEPTH_BUFFER_BIT);
532
	
533
	glRenderer->bind(*this);
534
	
535
	if( isGlCullingEnabled() ) {
536
		glEnable(GL_CULL_FACE); // enables face culling
537
		glFrontFace(mGlFrontFaceWindingOrder);
538
		glCullFace(GL_FRONT); // tells OpenGL to cull front faces
539
	}
540
	return true;
541
}
542

543
//--------------------------------------------------------------
544
bool ofShadow::endDepth() {
545
	if( !getIsEnabled() || !areShadowsSupported() ) {
546
		return false;
547
	}
548
	if( isGlCullingEnabled() ) {
549
		glDisable(GL_CULL_FACE);
550
	}
551
	
552
	auto glRenderer = ofGetGLRenderer();
553
	if(glRenderer){
554
		glRenderer->unbind(*this);
555
	}
556
	
557
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
558
	ofPopView();
559
	return true;
560
}
561

562
//--------------------------------------------------------------
563
bool ofShadow::beginDepth(GLenum aCubeFace) {
564
	if( !areShadowsSupported() ) {
565
		ofLogWarning("ofShadow :: beginDepth(cubeFace) : shadows are only available with programmable renderer.");
566
		setEnabled(false);
567
	}
568
	
569
	if( !getIsEnabled() ) {
570
		return false;
571
	}
572
	
573
	_allocateFbo();
574
	
575
	if( data->lightType != OF_LIGHT_POINT ) {
576
		ofLogWarning("ofShadow :: beginDepth(cubeFace) called from a light that does not use cube map. Use beginDepth() instead.");
577
		return false;
578
	}
579
	if( isSingleOmniPass() ) {
580
		ofLogWarning("ofShadow :: beginDepth(cubeFace) called using single pass, should be calling beginDepth().");
581
		return false;
582
	}
583
	
584
	if( data->texIndex+1 > getNumTotalPossibleShadows(data->lightType) ) {
585
		ofLogWarning( "ofShadow :: too many shadows detected for light type " ) << data->lightType<<". Total supported for light type: " << getNumTotalPossibleShadows(data->lightType);
586
	}
587
	
588
//	if( data->lightType == OF_LIGHT_POINT ) {
589
//		glEnable(GL_TEXTURE_CUBE_MAP_ARRAY);
590
//	}
591
	
592
	const auto glRenderer = ofGetGLRenderer();
593
	if(!glRenderer){
594
		return false;
595
	}
596
	
597
	glBindFramebuffer(GL_FRAMEBUFFER, getDepthMapFboId());
598
	if( getTextureTarget(OF_LIGHT_POINT) != GL_TEXTURE_CUBE_MAP ){
599
		#ifdef glFramebufferTextureLayer
600
		glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, getDepthMapTexId(), 0, (data->texIndex * 6) + aCubeFace);
601
		#else
602
		ofLogWarning("ofShadow::beginDepth(GLenum aCubeFace) point light texture target needs to be GL_TEXTURE_CUBE_MAP");
603
		#endif
604
	} else {
605
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X + aCubeFace, getDepthMapTexId(), 0);
606
	}
607
//	glViewport(0, 0, getDepthMapWidth(), getDepthMapHeight() );
608
	ofPushView();
609
	ofViewport(0, 0, getDepthMapWidth(), getDepthMapHeight(), false);
610
	glClear(GL_DEPTH_BUFFER_BIT);
611
	
612
	glRenderer->bind(*this,aCubeFace);
613
		
614
	if( isGlCullingEnabled() ) {
615
		glEnable(GL_CULL_FACE); // enables face culling
616
		glFrontFace(mGlFrontFaceWindingOrder);
617
		glCullFace(GL_FRONT); // tells OpenGL to cull back faces (the sane default setting)
618
	}
619
	return true;
620
}
621

622
//--------------------------------------------------------------
623
bool ofShadow::endDepth(GLenum aCubeFace) {
624
	return endDepth();
625
}
626

627
//--------------------------------------------------------------
628
void ofShadow::clear() {
629
	_checkFbos();
630
	
631
	mLookAtMats.clear();
632
	mViewProjMats.clear();
633
	
634
}
635

636
//--------------------------------------------------------------
637
void ofShadow::setEnabled( bool ab ) {
638
	if( !areShadowsSupported() ) {
639
		ofLogWarning("ofShadow :: setEnabled : shadows only work with programmable renderer");
640
		ab = false;
641
	}
642
	
643
	data->isEnabled = ab;
644
	if( data->isEnabled ) {
645
		_allocate();
646
	}
647
}
648

649
//--------------------------------------------------------------
650
const bool ofShadow::isMultiCubeFacePass() const {
651
	if( data->lightType == OF_LIGHT_POINT ) {
652
		return !isSingleOmniPass();
653
	}
654
	return false;
655
}
656

657
//--------------------------------------------------------------
658
const bool ofShadow::isSingleOmniPass() const {
659
	return mBSinglePass;
660
}
661

662
//--------------------------------------------------------------
663
const int ofShadow::getNumShadowDepthPasses() const {
664
	if(isMultiCubeFacePass()) {
665
		return 6;
666
	}
667
	return 1;
668
}
669

670
//--------------------------------------------------------------
671
void ofShadow::setSingleOmniPass( bool ab ) {
672
	
673
	if( ofGetGLRenderer() && ofGetGLRenderer()->getGLVersionMajor() < 4 ) {
674
		ab = false;
675
	}
676
	
677
#ifdef TARGET_OPENGLES
678
	// setting to false because the single pass uses a geometry shader
679
	ab = false;
680
#endif
681
	
682
	if(mBSinglePass != ab ) {
683
		clear();
684
	}
685

686
	mBSinglePass = ab;
687
	data->numDepthPasses = getNumShadowDepthPasses();
688
}
689

690
//--------------------------------------------------------------
691
int ofShadow::getDepthMapWidth() {
692
	return getDepthMapWidth( data->lightType );
693
}
694

695
//--------------------------------------------------------------
696
int ofShadow::getDepthMapHeight() {
697
	return getDepthMapHeight( data->lightType );
698
}
699

700
//--------------------------------------------------------------
701
void ofShadow::setDirectionalBounds( float aWorldWidth, float aWorldHeight ) {
702
	mDirectionalBoundsWidth = aWorldWidth;
703
	mDirectionalBoundsHeight = aWorldHeight;
704
}
705

706
//--------------------------------------------------------------
707
GLuint ofShadow::getDepthMapFboId() {
708
	return getFBOId(data->lightType);
709
}
710

711
//--------------------------------------------------------------
712
GLuint ofShadow::getDepthMapTexId() {
713
	return getFBODepthTexId(data->lightType);
714
}
715

716
//--------------------------------------------------------------
717
void ofShadow::drawFrustum() {
718
	if( data->lightType == OF_LIGHT_POINT ) {
719
		_drawFrustum( data->up, data->right, data->direction );
720
		_drawFrustum( data->up, data->right, -data->direction );
721
		_drawFrustum( data->up, data->direction, data->right );
722
		_drawFrustum( data->up, data->direction, -data->right );
723
	} else {
724
		_drawFrustum( data->up, data->right, data->direction );
725
	}
726
}
727

728
//--------------------------------------------------------------
729
void ofShadow::_drawFrustum( const glm::vec3& aup, const glm::vec3& aright, const glm::vec3& afwd ) {
730
	auto corners = getFrustumCorners(aup, aright, afwd );
731
	
732
	ofPushStyle();
733

734
	ofSetColor( ofColor::green );
735
	ofDrawArrow( data->position, data->position+data->up * 100.0, 10.0);
736
	ofSetColor( ofColor::red );
737
	ofDrawArrow( data->position, data->position+data->right * 100.0, 10.0);
738
	ofSetColor( ofColor::blue );
739
	ofDrawArrow( data->position, data->position+data->direction * 100.0, 10.0);
740
	
741
	vector<ofFloatColor> colors;
742
	
743
	ofMesh mesh;
744
	mesh.setMode(OF_PRIMITIVE_LINES);
745
	
746
	for( int i = 0; i < 4; i++ ) {
747
		mesh.addVertex( corners[i] );
748
		if( i == 3 ) {
749
			mesh.addVertex(corners[0]);
750
		} else {
751
			mesh.addVertex(corners[i+1]);
752
		}
753
	}
754
	
755
	colors.assign( 8, ofColor(220, 90, 190) );
756
	mesh.addColors(colors);
757
	
758
	for( int i = 0; i < 4; i++ ) {
759
		mesh.addVertex( corners[i+4] );
760
		if( i == 3 ) {
761
			mesh.addVertex(corners[4]);
762
		} else {
763
			mesh.addVertex(corners[i+4+1]);
764
		}
765
	}
766
	
767
	colors.assign( 8, ofColor(220, 220, 90) );
768
	mesh.addColors(colors);
769
	
770
	
771
	for( int i = 0; i < 4; i++ ) {
772
		if( data->lightType == OF_LIGHT_SPOT || data->lightType == OF_LIGHT_AREA) {
773
			mesh.addVertex(data->position);
774
		} else {
775
			mesh.addVertex(corners[i+4]);
776
		}
777
		mesh.addVertex(corners[i]);
778
	}
779
	colors.assign( 8, ofColor(220) );
780
	mesh.addColors(colors);
781
	
782
	if( data->lightType == OF_LIGHT_DIRECTIONAL ) {
783
		for( int i = 0; i < 4; i++ ) {
784
			mesh.addVertex(data->position);
785
			mesh.addVertex(corners[i+4]);
786
		}
787
		colors.assign( 8, ofColor(220) );
788
		mesh.addColors(colors);
789
	}
790
	
791
	
792
	mesh.draw();
793
	
794
	ofPopStyle();
795
}
796

797
//--------------------------------------------------------------
798
std::vector<glm::vec3> ofShadow::getFrustumCorners( const glm::vec3& aup, const glm::vec3& aright, const glm::vec3& afwd ) {
799
	
800
	if( data->lightType == OF_LIGHT_DIRECTIONAL) {
801
		
802
		glm::vec3 fc = data->position + afwd * getFarClip();
803
		glm::vec3 nc = data->position + afwd * getNearClip();
804
		
805
		float viewWidth = getGLData(data->lightType).width;
806
		float viewHeight = getGLData(data->lightType).height;
807
		if( mDirectionalBoundsWidth > 0 ) {
808
			viewWidth = mDirectionalBoundsWidth;
809
		}
810
		if( mDirectionalBoundsHeight > 0 ) {
811
			viewHeight = mDirectionalBoundsHeight;
812
		}
813
		
814
		float hw = 0.5f * viewWidth;
815
		float hh = 0.5f * viewHeight;
816
		
817
		glm::vec3 X = glm::normalize(aright);
818
		glm::vec3 Y = glm::normalize(aup);
819
		
820
		std::vector<glm::vec3> corners(8);
821
		// ftl, ftr, fbl, fbr
822
		corners[0] = fc + (Y*hh) - (X*hw);
823
		corners[1] = fc + (Y*hh) + (X*hw);
824
		corners[2] = fc + (-Y*hh) + (X*hw);
825
		corners[3] = fc + (-Y*hh) - (X*hw);
826
		
827
		corners[4] = nc + (Y*hh) - (X*hw);
828
		corners[5] = nc + (Y*hh) + (X*hw);
829
		corners[6] = nc + (-Y*hh) + (X*hw);
830
		corners[7] = nc + (-Y*hh) - (X*hw);
831
		
832
		return corners;
833
		
834
	}
835
		
836
	glm::vec3 Z = glm::normalize(afwd);
837
	glm::vec3 X = glm::normalize(aright);
838
	glm::vec3 Y = glm::normalize(aup);
839
	
840
	glm::vec3 p = data->position;
841
	
842
	glm::vec3 nc = p + Z * getNearClip();
843
	glm::vec3 fc = p + Z * getFarClip();
844
	
845
	float ratio = (float)getDepthMapWidth() / (float)getDepthMapHeight();
846
	
847
	if( data->lightType == OF_LIGHT_AREA ) {
848
		ratio = mAreaLightWidth / mAreaLightHeight;
849
	}
850
	
851
	float Hnear = 2.f * tan( ofDegToRad( mFov ) / 2.f ) * getNearClip();
852
	float Wnear = Hnear * ratio;
853
	
854
	float Hfar = 2.f * tanf( ofDegToRad( mFov ) / 2.f ) * getFarClip();
855
	float Wfar = Hfar * ratio;
856
	
857
	std::vector<glm::vec3> corners(8);
858
	
859
	corners[0] = fc + ( Y * Hfar/2) - ( X * Wfar/2.f); // ftl
860
	corners[1] = fc + ( Y * Hfar/2) + ( X * Wfar/2); // ftr
861
	corners[2] = fc - ( Y * Hfar/2) + ( X * Wfar/2); // fbl
862
	corners[3] = fc - ( Y * Hfar/2) - ( X * Wfar/2); // fbr
863
	
864
	corners[4] = nc + ( Y * Hnear/2) - ( X * Wnear/2); // ntl
865
	corners[5] = nc + ( Y * Hnear/2) + ( X * Wnear/2); // ntr
866
	corners[6] = nc - ( Y * Hnear/2) + ( X * Wnear/2); // nbl
867
	corners[7] = nc - ( Y * Hnear/2) - ( X * Wnear/2); // nbr
868
	
869
	return corners;
870
}
871

872

873

874
//--------------------------------------------------------------
875
std::string ofShadow::getShadowTypeAsString() {
876
	return ofShadow::getShadowTypeAsString(data->shadowType);
877
}
878

879
//--------------------------------------------------------------
880
const ofShader & ofShadow::getDepthShader(ofGLProgrammableRenderer & renderer) const {
881
	initShaders( renderer );
882
	if( data->lightType == OF_LIGHT_POINT ) {
883
		#ifndef TARGET_OPENGLES
884
		if(isSingleOmniPass()) {
885
			return shaders[&renderer]->depthCube;
886
		} else {
887
			return shaders[&renderer]->depthCubeMultiPass;
888
		}
889
		#else
890
		return shaders[&renderer]->depthCubeMultiPass;
891
		#endif
892
	} else if( data->lightType == OF_LIGHT_AREA ) {
893
		return shaders[&renderer]->depth;
894
	} else {
895
		return shaders[&renderer]->depth;
896
	}
897
}
898

899
//--------------------------------------------------------------
900
void ofShadow::updateDepth(const ofShader & shader,ofGLProgrammableRenderer & renderer) const {
901
	shader.setUniform3f("uLightPos", data->position );
902
	shader.setUniform1f("uNearPlane", data->nearClip );
903
	shader.setUniform1f("uFarPlane", data->farClip );
904
	
905
	if( data->lightType == OF_LIGHT_POINT ) {
906
		if( isSingleOmniPass() ) {
907
			for( unsigned int i = 0; i < 6; i++ ) {
908
				shader.setUniformMatrix4f("light["+ std::to_string(i) +"].viewProjectionMatrix", mViewProjMats[i]);
909
			}
910
			shader.setUniform1i("uStartLayer", data->texIndex );
911
		} else {
912
			ofLogWarning("Must call beginDepth(cubeFace) to render to point light in multiple passes");
913
		}
914
	} else {
915
		// just in case //
916
		if(mViewProjMats.size() > 0 ) {
917
			shader.setUniformMatrix4f("lightsViewProjectionMatrix", mViewProjMats[0]);
918
		}
919
	}
920
}
921

922
//--------------------------------------------------------------
923
void ofShadow::updateDepth(const ofShader & shader,GLenum aCubeFace,ofGLProgrammableRenderer & renderer) const {
924
//	shader.begin();
925
	shader.setUniform3f("uLightPos", data->position );
926
	shader.setUniform1f("uNearPlane", data->nearClip );
927
	shader.setUniform1f("uFarPlane", data->farClip );
928
		
929
	if( aCubeFace < mViewProjMats.size() ) {
930
		shader.setUniformMatrix4f("lightsViewProjectionMatrix", mViewProjMats[aCubeFace] );
931
	}
932
}
933

934
//--------------------------------------------------------------
935
void ofShadow::_checkSetup() {
936
	if( data->index < 0 ) {
937
		bool bShadowFound = false;
938
		// search for the first free block
939
		for(size_t i=0; i<ofShadowsData().size(); i++) {
940
			if(ofShadowsData()[i].expired()) {
941
				data->index = i;
942
				data->isEnabled = false;
943
				ofShadowsData()[i] = data;
944
				bShadowFound = true;
945
				break;
946
			}
947
		}
948
		if(!bShadowFound && ofIsGLProgrammableRenderer()){
949
			ofShadowsData().push_back(data);
950
			data->index = ofShadowsData().size() - 1;
951
			data->isEnabled = false;
952
			bShadowFound = true;
953
		}
954
	}
955
	_checkFbos(); // clean up
956
}
957

958
//--------------------------------------------------------------
959
void ofShadow::_allocate() {
960
	_checkFbos(); // clean up
961
	_allocateFbo();
962
}
963

964
//--------------------------------------------------------------
965
void ofShadow::_allocateFbo() {
966
	if(getGLData(data->lightType).bFboAllocated) {
967
		return;
968
	}
969
	
970
	GLenum gl_read_status = GL_FRAMEBUFFER_UNSUPPORTED;
971
	
972
	GLenum textureTarget = getTextureTarget(data->lightType);
973
#if !defined(TARGET_OPENGLES)
974
	int depthComponent = GL_DEPTH_COMPONENT32F;
975
	int glType = GL_FLOAT;
976
#elif defined(TARGET_EMSCRIPTEN)
977
	int depthComponent = GL_DEPTH_COMPONENT24;
978
	int glType = GL_UNSIGNED_INT;
979
#else
980
	int depthComponent = GL_DEPTH_COMPONENT;
981
	int glType = GL_UNSIGNED_SHORT;
982
#endif
983
	
984
	glBindTexture(textureTarget, getDepthMapTexId() );
985
	
986
	if( data->lightType == OF_LIGHT_POINT ) {
987
		// Create the cube map depth buffer
988
		#if !defined(TARGET_OPENGLES)
989
		glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS);
990
		#endif
991
		
992
		// OES_depth_texture_cube_map
993
		
994
		if( textureTarget == GL_TEXTURE_CUBE_MAP ) {
995
			for (GLint i = 0 ; i < 6 ; i++) {
996
				glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, depthComponent, getDepthMapWidth(), getDepthMapWidth(), 0, GL_DEPTH_COMPONENT, glType, NULL);
997
			}
998
		}
999
		
1000
		glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1001
		glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1002
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1003
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1004
		#ifdef GL_TEXTURE_WRAP_R
1005
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1006
		#endif
1007
		#if defined( GL_TEXTURE_CUBE_MAP_ARRAY ) && defined(glTexImage3D)
1008
		if( textureTarget == GL_TEXTURE_CUBE_MAP_ARRAY ) {
1009
			
1010
			glTexImage3D(GL_TEXTURE_CUBE_MAP_ARRAY, 0, depthComponent, getDepthMapWidth(), getDepthMapWidth(), getGLData(data->lightType).totalShadows * 6, 0, GL_DEPTH_COMPONENT, glType, NULL);
1011
		}
1012
		#endif
1013
	} else {
1014
		if( textureTarget == GL_TEXTURE_2D ) {
1015
			glTexImage2D(GL_TEXTURE_2D, 0, depthComponent, getDepthMapWidth(), getDepthMapHeight(), 0, GL_DEPTH_COMPONENT, glType, NULL);
1016
		}
1017
		
1018
		glTexParameteri(textureTarget, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1019
		glTexParameteri(textureTarget, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1020
		
1021
		//-- This is to allow usage of shadow2DProj function in the shader --//
1022
		if( data->lightType != OF_LIGHT_AREA ) {
1023
			#ifdef GL_TEXTURE_COMPARE_MODE
1024
			glTexParameteri(textureTarget, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
1025
			glTexParameteri(textureTarget, GL_TEXTURE_COMPARE_FUNC, GL_LESS);
1026
			#endif
1027
		}
1028
		//--! This is to allow usage of shadow2DProj function in the shader !--//
1029
		#ifdef GL_TEXTURE_2D_ARRAY
1030
		if( textureTarget == GL_TEXTURE_2D_ARRAY ) {
1031
			#ifdef GL_TEXTURE_WRAP_R
1032
			glTexParameteri(textureTarget, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1033
			#endif
1034
		}
1035
		#endif
1036
		
1037
		#if defined(GL_CLAMP_TO_BORDER) && !defined(TARGET_EMSCRIPTEN)
1038
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
1039
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
1040
		float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
1041
		glTexParameterfv(textureTarget, GL_TEXTURE_BORDER_COLOR, borderColor);
1042
		#else
1043
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1044
		glTexParameteri(textureTarget, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1045
		#endif
1046
		
1047
		#ifdef GL_TEXTURE_2D_ARRAY
1048
		if( textureTarget == GL_TEXTURE_2D_ARRAY ) {
1049
			#ifdef glTexImage3D
1050
			glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, depthComponent, getDepthMapWidth(), getDepthMapHeight(), getGLData(data->lightType).totalShadows, 0, GL_DEPTH_COMPONENT, GL_FLOAT, 0);
1051
			#endif
1052
		}
1053
		#endif
1054
	}
1055
	glBindTexture(textureTarget, 0);
1056
	
1057
	
1058
	// Create the fbo
1059
	glBindFramebuffer(GL_FRAMEBUFFER, getDepthMapFboId() );
1060
	#if defined(TARGET_OPENGLES)
1061
	
1062
	if( textureTarget == GL_TEXTURE_CUBE_MAP ) {
1063
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, NULL, 0);
1064
		for(int c = 0; c < 6; c++) {
1065
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X+c, getDepthMapTexId(), 0);
1066
		}
1067
	} else {
1068
		glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, textureTarget, getDepthMapTexId(), 0);
1069
	}
1070
	#else
1071
	glFramebufferTexture(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, getDepthMapTexId(), 0);
1072
	#endif
1073
	
1074
	#ifndef TARGET_OPENGLES
1075
	// Disable writes to the color buffer
1076
	glDrawBuffer(GL_NONE);
1077
	
1078
	// Disable reads from the color buffer
1079
	glReadBuffer(GL_NONE);
1080
	#endif
1081
	
1082
	gl_read_status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
1083
	
1084
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
1085
	
1086
	if (gl_read_status != GL_FRAMEBUFFER_COMPLETE) {
1087
		releaseFBO(data->lightType);
1088
		ofLogError("ofShadow :: _allocateFbo : Frame buffer error, status") << gl_read_status;
1089
	} else {
1090
		getGLData(data->lightType).bFboAllocated = true;
1091
	}
1092
	
1093
	
1094
	ofLogVerbose("xxxxx ofShadow::_allocateFbo xxxxxxxxxxxxxxxxxxxxxxxxx") << std::endl;
1095
}
1096

1097
//--------------------------------------------------------------
1098
void ofShadow::_checkFbos() {
1099
	// count the number of shadows here //
1100
	std::map<int, int> preNumShadows;
1101
	preNumShadows[OF_LIGHT_POINT] = getGLData(OF_LIGHT_POINT).totalShadows;
1102
	preNumShadows[OF_LIGHT_DIRECTIONAL] = getGLData(OF_LIGHT_DIRECTIONAL).totalShadows;
1103
	preNumShadows[OF_LIGHT_SPOT] = getGLData(OF_LIGHT_SPOT).totalShadows;
1104
	preNumShadows[OF_LIGHT_AREA] = getGLData(OF_LIGHT_AREA).totalShadows;
1105
	_updateNumShadows();
1106
	
1107
	if(getGLData(OF_LIGHT_POINT).totalShadows != preNumShadows[OF_LIGHT_POINT]) {
1108
		releaseFBO((int)OF_LIGHT_POINT);
1109
	}
1110
	if(getGLData(OF_LIGHT_DIRECTIONAL).totalShadows != preNumShadows[OF_LIGHT_DIRECTIONAL]) {
1111
		releaseFBO((int)OF_LIGHT_DIRECTIONAL);
1112
	}
1113
	if(getGLData(OF_LIGHT_SPOT).totalShadows != preNumShadows[OF_LIGHT_SPOT]) {
1114
		releaseFBO((int)OF_LIGHT_SPOT);
1115
	}
1116
	if(getGLData(OF_LIGHT_AREA).totalShadows != preNumShadows[OF_LIGHT_AREA]) {
1117
		releaseFBO((int)OF_LIGHT_AREA);
1118
	}
1119
}
1120

1121
//--------------------------------------------------------------
1122
void ofShadow::_updateNumShadows() {
1123
	
1124
	getGLData(OF_LIGHT_POINT).totalShadows = 0;
1125
	getGLData(OF_LIGHT_DIRECTIONAL).totalShadows = 0;
1126
	getGLData(OF_LIGHT_SPOT).totalShadows = 0;
1127
	getGLData(OF_LIGHT_AREA).totalShadows = 0;
1128
	
1129
	for(size_t i=0; i < ofShadowsData().size(); i++){
1130
		if(!ofShadowsData()[i].expired()) {
1131
			auto shadow = ofShadowsData()[i].lock();
1132
			if( shadow ) {
1133
				getGLData(shadow->lightType).totalShadows++;
1134
			}
1135
		}
1136
	}
1137
}
1138

1139
#include "shaders/shadowDepth.vert"
1140
#include "shaders/shadowDepth.frag"
1141
#include "shaders/shadowDepthCubeGeom.glsl"
1142

1143
bool ofShadow::setupShadowDepthShader(ofShader& ashader, const std::string aShaderMain) {
1144
	return setupShadowDepthShader( ashader, data->lightType, aShaderMain );
1145
}
1146

1147
bool ofShadow::setupShadowDepthShader(ofShader& ashader, int aLightType, const std::string aShaderMain) {
1148
	std::string gversion = "#version 150\n";
1149
	#ifdef TARGET_OPENGLES
1150
	gversion = "#version 300 es\nprecision highp float;\n";
1151
	#endif
1152
	std::string tdefines = "#define SINGLE_PASS\n";
1153

1154
	bool bDepthCubeSinglePass = false;
1155

1156
	if( aLightType == OF_LIGHT_POINT ) {
1157
		#ifndef TARGET_OPENGLES
1158
		if(isSingleOmniPass()) {
1159
			//return shaders[&renderer]->depthCube;
1160
			tdefines = "#define CUBE_MAP_SINGLE_PASS\n";
1161
			bDepthCubeSinglePass = true;
1162
		} else {
1163
			//return shaders[&renderer]->depthCubeMultiPass;
1164
			tdefines = "#define CUBE_MAP_MULTI_PASS\n";
1165
		}
1166
		#else
1167
		//return shaders[&renderer]->depthCubeMultiPass;
1168
		tdefines = "#define CUBE_MAP_MULTI_PASS\n";
1169
		#endif
1170
	} else if( aLightType == OF_LIGHT_AREA ) {
1171
		//return shaders[&renderer]->depth;
1172
	} else {
1173
		//return shaders[&renderer]->depth;
1174
	}
1175

1176
	ashader.setupShaderFromSource(GL_VERTEX_SHADER,gversion+tdefines+depthVertexShaderSource+aShaderMain);
1177
	ashader.setupShaderFromSource(GL_FRAGMENT_SHADER,gversion+tdefines+depthFragShaderSource);
1178

1179
	#ifndef TARGET_OPENGLES
1180
	if(bDepthCubeSinglePass) {
1181
		ashader.setupShaderFromSource(GL_GEOMETRY_SHADER_EXT,depthCubeGeometryShaderSource);
1182
	}
1183
	#endif
1184

1185
	ashader.bindDefaults();
1186
	return ashader.linkProgram();
1187
}
1188

1189

1190
void ofShadow::initShaders(ofGLProgrammableRenderer & renderer) const{
1191
	auto rendererShaders = shaders.find(&renderer);
1192
	
1193
	if(rendererShaders == shaders.end() ){
1194
		shaders[&renderer] = std::make_shared<ofShadow::Shaders>();
1195
				
1196
		std::string gversion = "#version 150\n";
1197
		#ifdef TARGET_OPENGLES
1198
		gversion = "#version 300 es\nprecision highp float;\n";
1199
		#endif
1200
		
1201
		std::string vertString = depthVertexShaderSource+depthVertexShader_Main;
1202
		
1203
		shaders[&renderer]->depth.setupShaderFromSource(GL_VERTEX_SHADER,gversion+"#define SINGLE_PASS\n"+vertString);
1204
		shaders[&renderer]->depth.setupShaderFromSource(GL_FRAGMENT_SHADER,gversion+"#define SINGLE_PASS\n"+depthFragShaderSource);
1205
		shaders[&renderer]->depth.bindDefaults();
1206
		shaders[&renderer]->depth.linkProgram();
1207
		
1208
		#ifndef TARGET_OPENGLES
1209
		shaders[&renderer]->depthCube.setupShaderFromSource(GL_VERTEX_SHADER,gversion+"#define CUBE_MAP_SINGLE_PASS\n"+vertString);
1210
		shaders[&renderer]->depthCube.setupShaderFromSource(GL_FRAGMENT_SHADER,gversion+"#define CUBE_MAP_SINGLE_PASS\n"+depthFragShaderSource);
1211
		shaders[&renderer]->depthCube.setupShaderFromSource(GL_GEOMETRY_SHADER_EXT,depthCubeGeometryShaderSource);
1212
		shaders[&renderer]->depthCube.bindDefaults();
1213
		shaders[&renderer]->depthCube.linkProgram();
1214
		#endif
1215
		shaders[&renderer]->depthCubeMultiPass.setupShaderFromSource(GL_VERTEX_SHADER,gversion+"#define CUBE_MAP_MULTI_PASS\n"+vertString);
1216
		shaders[&renderer]->depthCubeMultiPass.setupShaderFromSource(GL_FRAGMENT_SHADER,gversion+"#define CUBE_MAP_MULTI_PASS\n"+depthFragShaderSource);
1217
		shaders[&renderer]->depthCubeMultiPass.bindDefaults();
1218
		shaders[&renderer]->depthCubeMultiPass.linkProgram();
1219
				
1220
	}
1221
	
1222
}
1223

1224

1225

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

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

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

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