framework2

Форк
0
478 строк · 13.3 Кб
1
/*
2
 *  ofLight.cpp
3
 *  openFrameworksLib
4
 *
5
 *  Created by Memo Akten on 14/01/2011.
6
 *  Copyright 2011 MSA Visuals Ltd. All rights reserved.
7
 *
8
 */
9

10

11
#include "ofLight.h"
12
#include "of3dUtils.h"
13
#include "ofGLBaseTypes.h"
14
#include "ofGLUtils.h"
15
#include "ofConstants.h"
16
#include "ofColor.h"
17
#include <glm/gtc/quaternion.hpp>
18
#include <map>
19

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

23
static ofFloatColor globalAmbient(0.2, 0.2, 0.2, 1.0);
24

25
//----------------------------------------
26
void ofEnableLighting() {
27
	ofGetGLRenderer()->enableLighting();
28
}
29

30
//----------------------------------------
31
void ofDisableLighting() {
32
	ofGetGLRenderer()->disableLighting();
33
}
34

35
//----------------------------------------
36
void ofEnableSeparateSpecularLight(){
37
	ofGetGLRenderer()->enableSeparateSpecularLight();
38
}
39

40
//----------------------------------------
41
void ofDisableSeparateSpecularLight(){
42
    ofGetGLRenderer()->disableSeparateSpecularLight();
43
}
44

45
//----------------------------------------
46
bool ofGetLightingEnabled() {
47
	return ofGetGLRenderer()->getLightingEnabled();
48
}
49

50
//----------------------------------------
51
void ofSetSmoothLighting(bool b) {
52
	ofGetGLRenderer()->setSmoothLighting(b);
53
}
54

55
//----------------------------------------
56
void ofSetGlobalAmbientColor(const ofFloatColor& c) {
57
	ofGetGLRenderer()->setGlobalAmbientColor(c);
58
	globalAmbient = c;
59
}
60

61
const ofFloatColor & ofGetGlobalAmbientColor(){
62
	return globalAmbient;
63
}
64

65
//----------------------------------------
66
vector<weak_ptr<ofLight::Data> > & ofLightsData(){
67
	static vector<weak_ptr<ofLight::Data> > * lightsActive = ofIsGLProgrammableRenderer()?new vector<weak_ptr<ofLight::Data> >:new vector<weak_ptr<ofLight::Data> >(8);
68
	return *lightsActive;
69
}
70

71
ofLight::Data::Data(){
72
	glIndex			= -1;
73
	isEnabled		= false;
74
	attenuation_constant = 0.000001;
75
	attenuation_linear = 0.000001;
76
	attenuation_quadratic = 0.000001;
77
	spotCutOff = 45;
78
	exponent = 16;
79
	width = 1;
80
	height = 1;
81
	lightType = OF_LIGHT_POINT;
82
}
83

84
ofLight::Data::~Data(){
85
	if(glIndex==-1) return;
86
	if ( auto r = rendererP.lock() ){
87
		r->setLightAmbientColor( glIndex, ofColor( 0, 0, 0, 255 ) );
88
		r->setLightDiffuseColor( glIndex, ofColor( 0, 0, 0, 255 ) );
89
		r->setLightSpecularColor( glIndex, ofColor( 0, 0, 0, 255 ) );
90
		r->setLightPosition( glIndex, glm::vec4( 0, 0, 1, 0 ) );
91
		r->disableLight( glIndex );
92
	}
93
}
94

95
//----------------------------------------
96
ofLight::ofLight()
97
:data(new Data){
98
    setAmbientColor(ofColor(0,0,0));
99
    setDiffuseColor(ofColor(255,255,255));
100
    setSpecularColor(ofColor(255,255,255));
101
	setPointLight();
102
    
103
    // assume default attenuation factors //
104
    setAttenuation(1.f,0.f,0.f);
105
}
106

107
//----------------------------------------
108
void ofLight::setup() {
109
    if(data->glIndex==-1){
110
		bool bLightFound = false;
111
		// search for the first free block
112
		for(size_t i=0; i<ofLightsData().size(); i++) {
113
			if(ofLightsData()[i].expired()) {
114
				data->glIndex = i;
115
				data->isEnabled = true;
116
				ofLightsData()[i] = data;
117
				bLightFound = true;
118
				break;
119
			}
120
		}
121
		if(!bLightFound && ofIsGLProgrammableRenderer()){
122
			ofLightsData().push_back(data);
123
			data->glIndex = ofLightsData().size() - 1;
124
			data->isEnabled = true;
125
			bLightFound = true;
126
		}
127
		if( bLightFound ){
128
            // run this the first time, since it was not found before //
129
			data->rendererP = ofGetGLRenderer();
130
            onPositionChanged();
131
            setAmbientColor( getAmbientColor() );
132
            setDiffuseColor( getDiffuseColor() );
133
            setSpecularColor( getSpecularColor() );
134
            setAttenuation( getAttenuationConstant(), getAttenuationLinear(), getAttenuationQuadratic() );
135
            if(getIsSpotlight()) {
136
                setSpotlightCutOff(getSpotlightCutOff());
137
                setSpotConcentration(getSpotConcentration());
138
            }
139
            if(getIsSpotlight() || getIsDirectional() || getIsAreaLight()) {
140
                onOrientationChanged();
141
            }
142
        }else{
143
        	ofLogError("ofLight") << "setup(): couldn't get active GL light, maximum number of "<< ofLightsData().size() << " reached";
144
        }
145
	}
146
}
147

148
//----------------------------------------
149
void ofLight::enable() {
150
    setup();
151
	data->isEnabled = true;
152
    onPositionChanged(); // update the position //
153
	onOrientationChanged();
154
	if ( auto r = data->rendererP.lock() ){
155
		r->enableLight( data->glIndex );
156
	}
157
}
158

159
//----------------------------------------
160
void ofLight::disable() {
161
	data->isEnabled = false;
162
	if ( auto r = data->rendererP.lock() ){
163
		r->disableLight( data->glIndex );
164
	}
165
}
166

167
//----------------------------------------
168
int ofLight::getLightID() const{
169
	return data->glIndex;
170
}
171

172
//----------------------------------------
173
bool ofLight::getIsEnabled() const {
174
	return data->isEnabled;
175
}
176

177
//----------------------------------------
178
void ofLight::setDirectional() {
179
	if( data->lightType != OF_LIGHT_DIRECTIONAL ) {
180
		data->lightType	= OF_LIGHT_DIRECTIONAL;
181
		onOrientationChanged();
182
	}
183
	data->lightType	= OF_LIGHT_DIRECTIONAL;
184
	shadow.setLightType( data->lightType );
185
}
186

187
//----------------------------------------
188
bool ofLight::getIsDirectional() const {
189
	return data->lightType == OF_LIGHT_DIRECTIONAL;
190
}
191

192
//----------------------------------------
193
void ofLight::setSpotlight(float spotCutOff, float exponent) {
194
	if( data->lightType != OF_LIGHT_SPOT ) {
195
		data->lightType = OF_LIGHT_SPOT;
196
		onPositionChanged();
197
		onOrientationChanged();
198
	}
199
	data->lightType		= OF_LIGHT_SPOT;
200
	setSpotlightCutOff( spotCutOff );
201
	setSpotConcentration( exponent );
202
	shadow.setLightType( data->lightType );
203
}
204

205
//----------------------------------------
206
bool ofLight::getIsSpotlight() const{
207
	return data->lightType == OF_LIGHT_SPOT;
208
}
209

210
//----------------------------------------
211
void ofLight::setSpotlightCutOff( float spotCutOff ) {
212
    data->spotCutOff = ofClamp(spotCutOff, 0, 90);
213
	if ( auto r = data->rendererP.lock() ){
214
		r->setLightSpotlightCutOff( data->glIndex, spotCutOff );
215
	}
216
}
217

218
//----------------------------------------
219
float ofLight::getSpotlightCutOff() const{
220
    if(!getIsSpotlight()) {
221
        ofLogWarning("ofLight") << "getSpotlightCutOff(): light " << data->glIndex << " is not a spot light";
222
    }
223
    return data->spotCutOff;
224
}
225

226
//----------------------------------------
227
void ofLight::setSpotConcentration( float exponent ) {
228
    data->exponent = ofClamp(exponent, 0, 128);
229
	if ( auto r = data->rendererP.lock() ){
230
		r->setLightSpotConcentration( data->glIndex, exponent );
231
	}
232
}
233

234
//----------------------------------------
235
float ofLight::getSpotConcentration() const{
236
    if(!getIsSpotlight()) {
237
        ofLogWarning("ofLight") << "getSpotConcentration(): light " << data->glIndex << " is not a spot light";
238
    }
239
    return data->exponent;
240
}
241

242
//----------------------------------------
243
void ofLight::setPointLight() {
244
	if( data->lightType != OF_LIGHT_POINT ) {
245
		data->lightType= OF_LIGHT_POINT;
246
		onPositionChanged();
247
		onOrientationChanged();
248
	}
249
	data->lightType	= OF_LIGHT_POINT;
250
	shadow.setLightType( data->lightType );
251
}
252

253
//----------------------------------------
254
bool ofLight::getIsPointLight() const{
255
	return data->lightType == OF_LIGHT_POINT;
256
}
257

258
//----------------------------------------
259
void ofLight::setAttenuation( float constant, float linear, float quadratic ) {
260
    // falloff = 0 -> 1, 0 being least amount of fallof, 1.0 being most //
261
	data->attenuation_constant    = constant;
262
	data->attenuation_linear      = linear;
263
	data->attenuation_quadratic   = quadratic;
264
	if ( auto r = data->rendererP.lock() ){
265
		r->setLightAttenuation( data->glIndex, constant, linear, quadratic );
266
	}
267
}
268

269
//----------------------------------------
270
float ofLight::getAttenuationConstant() const{
271
    return data->attenuation_constant;
272
}
273

274
//----------------------------------------
275
float ofLight::getAttenuationLinear() const{
276
    return data->attenuation_linear;
277
}
278

279
//----------------------------------------
280
float ofLight::getAttenuationQuadratic() const{
281
    return data->attenuation_quadratic;
282
}
283

284
void ofLight::setAreaLight(float width, float height){
285
	if( data->lightType != OF_LIGHT_AREA ) {
286
		data->lightType = OF_LIGHT_AREA;
287
		onPositionChanged();
288
		onOrientationChanged();
289
	}
290
	data->lightType = OF_LIGHT_AREA;
291
	data->width = width;
292
	data->height = height;
293
	shadow.setLightType( data->lightType );
294
	shadow.setAreaLightSize( width, height );
295
}
296

297
bool ofLight::getIsAreaLight() const{
298
	return data->lightType == OF_LIGHT_AREA;
299
}
300

301
//----------------------------------------
302
int ofLight::getType() const{
303
	return data->lightType;
304
}
305

306
//----------------------------------------
307
void ofLight::setAmbientColor(const ofFloatColor& c) {
308
	data->ambientColor = c;
309
	if ( auto r = data->rendererP.lock() ){
310
		r->setLightAmbientColor( data->glIndex, c );
311
	}
312
}
313

314
//----------------------------------------
315
void ofLight::setDiffuseColor(const ofFloatColor& c) {
316
	data->diffuseColor = c;
317

318
	if ( auto r = data->rendererP.lock() ){
319
		r->setLightDiffuseColor( data->glIndex, c );
320
	}
321
}
322

323
//----------------------------------------
324
void ofLight::setSpecularColor(const ofFloatColor& c) {
325
	data->specularColor = c;
326
	if ( auto r = data->rendererP.lock() ){
327
		r->setLightSpecularColor( data->glIndex, c );
328
	}
329
}
330

331
//----------------------------------------
332
ofFloatColor ofLight::getAmbientColor() const {
333
	return data->ambientColor;
334
}
335

336
//----------------------------------------
337
ofFloatColor ofLight::getDiffuseColor() const {
338
	return data->diffuseColor;
339
}
340

341
//----------------------------------------
342
ofFloatColor ofLight::getSpecularColor() const {
343
	return data->specularColor;
344
}
345

346
//----------------------------------------
347
void ofLight::customDraw(const ofBaseRenderer * renderer) const{
348
    if(getIsPointLight()) {
349
        renderer->drawSphere( 0,0,0, 10);
350
		ofDrawAxis(20);
351
    } else if (getIsSpotlight()) {
352
        float coneHeight = (sin(ofDegToRad(data->spotCutOff)) * 30.f) + 1;
353
        float coneRadius = (cos(ofDegToRad(data->spotCutOff)) * 30.f) + 8;
354
		const_cast<ofBaseRenderer*>(renderer)->rotateDeg(-90,1,0,0);
355
		renderer->drawCone(0, -(coneHeight*.5), 0, coneHeight, coneRadius);
356
    } else  if (getIsAreaLight()) {
357
    	const_cast<ofBaseRenderer*>(renderer)->pushMatrix();
358
		renderer->drawPlane(data->width,data->height);
359
		const_cast<ofBaseRenderer*>(renderer)->popMatrix();
360
		ofDrawArrow( glm::vec3(0,0,0), glm::vec3(0,0,-30), 10 );
361
	} else if( getIsDirectional() ) {
362
		renderer->drawBox(10);
363
		renderer->drawArrow(glm::vec3(0,0,0),glm::vec3(0,0,-40),10);
364
    }else{
365
        renderer->drawBox(10);
366
		ofDrawAxis(20);
367
    }
368
}
369

370

371
//----------------------------------------
372
void ofLight::onPositionChanged() {
373
	if(data->glIndex==-1) return;
374
	// if we are a positional light and not directional, update light position
375
	if(getIsSpotlight() || getIsPointLight() || getIsAreaLight()) {
376
		data->position = {getGlobalPosition().x, getGlobalPosition().y, getGlobalPosition().z, 1.f};
377
		if ( auto r = data->rendererP.lock() ){
378
			r->setLightPosition( data->glIndex, data->position );
379
		}
380
	}
381
}
382

383
//----------------------------------------
384
void ofLight::onOrientationChanged() {
385
	if(data->glIndex==-1) return;
386
	if(getIsDirectional()) {
387
		// if we are a directional light and not positional, update light position (direction)
388
		glm::vec3 lookAtDir(glm::normalize(getGlobalOrientation() * glm::vec4(0,0,-1, 1)));
389
		data->position = {lookAtDir.x,lookAtDir.y,lookAtDir.z,0.f};
390
		data->direction = lookAtDir;
391
		if ( auto r = data->rendererP.lock() ){
392
			r->setLightPosition( data->glIndex, data->position );
393
		}
394
	}else if(getIsSpotlight() || getIsAreaLight()) {
395
		// determines the axis of the cone light
396
		glm::vec3 lookAtDir(glm::normalize(getGlobalOrientation() * glm::vec4(0,0,-1, 1)));
397
		data->direction = lookAtDir;
398
		if ( auto r = data->rendererP.lock() ){
399
			r->setLightSpotDirection( data->glIndex, glm::vec4( data->direction, 0.0f ) );
400
		}
401
	}
402
	if(getIsAreaLight()){
403
		data->up = getUpDir();
404
		data->right = getXAxis();
405
	}
406
}
407

408
//-------------------------------
409
bool ofLight::shouldRenderShadowDepthPass() {
410
	if( !ofIsGLProgrammableRenderer() ) {
411
		return false;
412
	}
413
	return getIsEnabled() && shadow.getIsEnabled();
414
}
415

416
//-------------------------------
417
int ofLight::getNumShadowDepthPasses() {
418
	if( !ofIsGLProgrammableRenderer() ) {
419
		return 0;
420
	}
421
	return shadow.getNumShadowDepthPasses();
422
}
423

424
//-------------------------------
425
bool ofLight::beginShadowDepthPass() {
426
	if(!shouldRenderShadowDepthPass()) {
427
		return false;
428
	}
429
	shadow.update(*this);
430
	shadow.beginDepth();
431
	if( getNumShadowDepthPasses() > 1 ) {
432
		ofLogWarning("ofLight :: beginShadowDepthPass : shadow has more than one depth pass! Call beginShadowDepthPass( GLenum aPassIndex ) instead. ");
433
		return false;
434
	}
435
	return true;
436
}
437

438
//-------------------------------
439
bool ofLight::endShadowDepthPass() {
440
	if(!shouldRenderShadowDepthPass()) {
441
		return false;
442
	}
443
	shadow.endDepth();
444
	if( getNumShadowDepthPasses() > 1 ) {
445
		ofLogWarning("ofLight :: endShadowDepthPass : shadow has more than one depth pass! Call endShadowDepthPass( GLenum aPassIndex ) instead. ");
446
		return false;
447
	}
448
	return true;
449
}
450

451
//-------------------------------
452
bool ofLight::beginShadowDepthPass( GLenum aPassIndex ) {
453
	if(!shouldRenderShadowDepthPass()) {
454
		return false;
455
	}
456
	if( aPassIndex == 0 ) {
457
		shadow.update(*this);
458
	}
459
	if( getNumShadowDepthPasses() < 2 ) {
460
		shadow.beginDepth();
461
	} else {
462
		shadow.beginDepth(aPassIndex);
463
	}
464
	return true;
465
}
466

467
//-------------------------------
468
bool ofLight::endShadowDepthPass( GLenum aPassIndex ) {
469
	if(!shouldRenderShadowDepthPass()) {
470
		return false;
471
	}
472
	if( getNumShadowDepthPasses() < 2 ) {
473
		shadow.endDepth();
474
	} else {
475
		shadow.endDepth(aPassIndex);
476
	}
477
	return true;
478
}
479

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

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

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

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