Skip to content

Commit 6795351

Browse files
authored
Merge pull request #7025 from AnalyticalGraphicsInc/model-lighting-options
Model lighting options
2 parents 50d10f5 + 7dba70b commit 6795351

13 files changed

+347
-28
lines changed

CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ Change Log
77
* Shrink minified and gzipped Cesium.js by 27 KB (~3.7%) by delay loading seldom-used third-party dependencies. [#7140](https://github.com/AnalyticalGraphicsInc/cesium/pull/7140)
88
* Added WMS-T (time) support in WebMapServiceImageryProvider [#2581](https://github.com/AnalyticalGraphicsInc/cesium/issues/2581)
99
* Added `cutoutRectangle` to `ImageryLayer`, which allows cutting out rectangular areas in imagery layers to reveal underlying imagery. [#7056](https://github.com/AnalyticalGraphicsInc/cesium/pull/7056)
10+
* Added `imageBasedLightingFactor` property to `Cesium3DTileset`, `Model`, and `ModelGraphics` to scale the diffuse and specular image-based lighting contributions to the final color. [#7025](https://github.com/AnalyticalGraphicsInc/cesium/pull/7025)
11+
* Added `lightColor` property to `Cesium3DTileset`, `Model`, and `ModelGraphics` to change the intensity of the light used when shading model. [#7025](https://github.com/AnalyticalGraphicsInc/cesium/pull/7025)
1012

1113
##### Fixes :wrench:
1214
* Fixed an issue where `pickPosition` would return incorrect results when called after `sampleHeight` or `clampToHeight`. [#7113](https://github.com/AnalyticalGraphicsInc/cesium/pull/7113)

Source/DataSources/ModelGraphics.js

+25-1
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ define([
5656
* @param {Property} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] An enum Property specifying how the color blends with the model.
5757
* @param {Property} [options.colorBlendAmount=0.5] A numeric Property specifying the color strength when the <code>colorBlendMode</code> is <code>MIX</code>. A value of 0.0 results in the model's rendered color while a value of 1.0 results in a solid color, with any value in-between resulting in a mix of the two.
5858
* @param {Property} [options.clippingPlanes] A property specifying the {@link ClippingPlaneCollection} used to selectively disable rendering the model.
59+
* @param {Property} [options.imageBasedLightingFactor=new Cartesian2(1.0, 1.0)] A property specifying the contribution from diffuse and specular image-based lighting.
60+
* @param {Property} [options.lightColor] A property specifying the light color to use when shading the model. The default sun light color will be used when <code>undefined</code>.
5961
*
6062
* @see {@link https://cesiumjs.org/tutorials/3D-Models-Tutorial/|3D Models Tutorial}
6163
* @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=3D%20Models.html|Cesium Sandcastle 3D Models Demo}
@@ -96,6 +98,10 @@ define([
9698
this._colorBlendAmountSubscription = undefined;
9799
this._clippingPlanes = undefined;
98100
this._clippingPlanesSubscription = undefined;
101+
this._imageBasedLightingFactor = undefined;
102+
this._imageBasedLightingFactorSubscription = undefined;
103+
this._lightColor = undefined;
104+
this._lightColorSubscription = undefined;
99105
this._definitionChanged = new Event();
100106

101107
this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));
@@ -262,7 +268,21 @@ define([
262268
* @memberof ModelGraphics.prototype
263269
* @type {Property}
264270
*/
265-
clippingPlanes : createPropertyDescriptor('clippingPlanes')
271+
clippingPlanes : createPropertyDescriptor('clippingPlanes'),
272+
273+
/**
274+
* A property specifying the {@link Cartesian2} used to scale the diffuse and specular image-based lighting contribution to the final color.
275+
* @memberof ModelGraphics.prototype
276+
* @type {Property}
277+
*/
278+
imageBasedLightingFactor : createPropertyDescriptor('imageBasedLightingFactor'),
279+
280+
/**
281+
* A property specifying the {@link Cartesian3} color of the light source when shading the model.
282+
* @memberOf ModelGraphics.prototype
283+
* @type {Property}
284+
*/
285+
lightColor : createPropertyDescriptor('lightColor')
266286
});
267287

268288
/**
@@ -293,6 +313,8 @@ define([
293313
result.colorBlendMode = this.colorBlendMode;
294314
result.colorBlendAmount = this.colorBlendAmount;
295315
result.clippingPlanes = this.clippingPlanes;
316+
result.imageBasedLightingFactor = this.imageBasedLightingFactor;
317+
result.lightColor = this.lightColor;
296318

297319
return result;
298320
};
@@ -327,6 +349,8 @@ define([
327349
this.colorBlendMode = defaultValue(this.colorBlendMode, source.colorBlendMode);
328350
this.colorBlendAmount = defaultValue(this.colorBlendAmount, source.colorBlendAmount);
329351
this.clippingPlanes = defaultValue(this.clippingPlanes, source.clippingPlanes);
352+
this.imageBasedLightingFactor = defaultValue(this.imageBasedLightingFactor, source.imageBasedLightingFactor);
353+
this.lightColor = defaultValue(this.lightColor, source.lightColor);
330354

331355
var sourceNodeTransformations = source.nodeTransformations;
332356
if (defined(sourceNodeTransformations)) {

Source/DataSources/ModelVisualizer.js

+5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
define([
22
'../Core/AssociativeArray',
33
'../Core/BoundingSphere',
4+
'../Core/Cartesian2',
45
'../Core/Color',
56
'../Core/defined',
67
'../Core/destroyObject',
@@ -17,6 +18,7 @@ define([
1718
], function(
1819
AssociativeArray,
1920
BoundingSphere,
21+
Cartesian2,
2022
Color,
2123
defined,
2224
destroyObject,
@@ -43,6 +45,7 @@ define([
4345
var defaultColor = Color.WHITE;
4446
var defaultColorBlendMode = ColorBlendMode.HIGHLIGHT;
4547
var defaultColorBlendAmount = 0.5;
48+
var defaultImageBasedLightingFactor = new Cartesian2(1.0, 1.0);
4649

4750
var modelMatrixScratch = new Matrix4();
4851
var nodeMatrixScratch = new Matrix4();
@@ -157,6 +160,8 @@ define([
157160
model.colorBlendAmount = Property.getValueOrDefault(modelGraphics._colorBlendAmount, time, defaultColorBlendAmount);
158161
model.clippingPlanes = Property.getValueOrUndefined(modelGraphics._clippingPlanes, time);
159162
model.clampAnimations = Property.getValueOrDefault(modelGraphics._clampAnimations, time, defaultClampAnimations);
163+
model.imageBasedLightingFactor = Property.getValueOrDefault(modelGraphics._imageBasedLightingFactor, time, defaultImageBasedLightingFactor);
164+
model.lightColor = Property.getValueOrUndefined(modelGraphics._lightColor, time);
160165

161166
if (model.ready) {
162167
var runAnimations = Property.getValueOrDefault(modelGraphics._runAnimations, time, true);

Source/Scene/Batched3DModel3DTileContent.js

+5-1
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,9 @@ define([
384384
uniformMapLoaded : batchTable.getUniformMapCallback(),
385385
pickIdLoaded : getPickIdCallback(content),
386386
addBatchIdToGeneratedShaders : (batchLength > 0), // If the batch table has values in it, generated shaders will need a batchId attribute
387-
pickObject : pickObject
387+
pickObject : pickObject,
388+
imageBasedLightingFactor : tileset.imageBasedLightingFactor,
389+
lightColor : tileset.lightColor
388390
});
389391
} else {
390392
// This transcodes glTF to an internal representation for geometry so we can take advantage of the re-batching of vector data.
@@ -460,6 +462,8 @@ define([
460462
this._model.modelMatrix = this._contentModelMatrix;
461463

462464
this._model.shadows = this._tileset.shadows;
465+
this._model.imageBasedLightingFactor = this._tileset.imageBasedLightingFactor;
466+
this._model.lightColor = this._tileset.lightColor;
463467
this._model.debugWireframe = this._tileset.debugWireframe;
464468

465469
// Update clipping planes

Source/Scene/Cesium3DTileset.js

+40
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ define([
115115
* @param {ClassificationType} [options.classificationType] Determines whether terrain, 3D Tiles or both will be classified by this tileset. See {@link Cesium3DTileset#classificationType} for details about restrictions and limitations.
116116
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe.
117117
* @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
118+
* @param {Cartesian2} [options.imageBasedLightingFactor=new Cartesian2(1.0, 1.0)] Scales the diffuse and specular image-based lighting from the earth, sky, atmosphere and star skybox.
119+
* @param {Cartesian3} [options.lightColor] The color and intensity of the sunlight used to shade models.
118120
* @param {Boolean} [options.debugFreezeFrame=false] For debugging only. Determines if only the tiles from last frame should be used for rendering.
119121
* @param {Boolean} [options.debugColorizeTiles=false] For debugging only. When true, assigns a random color to each tile.
120122
* @param {Boolean} [options.debugWireframe=false] For debugging only. When true, render's each tile's content as a wireframe.
@@ -569,6 +571,21 @@ define([
569571
this._clippingPlanes = undefined;
570572
this.clippingPlanes = options.clippingPlanes;
571573

574+
this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);
575+
Cartesian2.clone(options.imageBasedLightingFactor, this._imageBasedLightingFactor);
576+
577+
/**
578+
* The color and intensity of the sunlight used to shade a model.
579+
* <p>
580+
* For example, disabling additional light sources by setting <code>model.imageBasedLightingFactor = new Cartesian2(0.0, 0.0)</code> will make the
581+
* model much darker. Here, increasing the intensity of the light source will make the model brighter.
582+
* </p>
583+
*
584+
* @type {Cartesian3}
585+
* @default undefined
586+
*/
587+
this.lightColor = options.lightColor;
588+
572589
/**
573590
* This property is for debugging only; it is not optimized for production use.
574591
* <p>
@@ -1236,6 +1253,29 @@ define([
12361253

12371254
return this._extras;
12381255
}
1256+
},
1257+
1258+
/**
1259+
* Cesium adds lighting from the earth, sky, atmosphere, and star skybox. This cartesian is used to scale the final
1260+
* diffuse and specular lighting contribution from those sources to the final color. A value of 0.0 will disable those light sources.
1261+
*
1262+
* @type {Cartesian2}
1263+
* @default Cartesian2(1.0, 1.0)
1264+
*/
1265+
imageBasedLightingFactor : {
1266+
get : function() {
1267+
return this._imageBasedLightingFactor;
1268+
},
1269+
set : function(value) {
1270+
//>>includeStart('debug', pragmas.debug);
1271+
Check.typeOf.object('imageBasedLightingFactor', value);
1272+
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.x', value.x, 0.0);
1273+
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.x', value.x, 1.0);
1274+
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.y', value.y, 0.0);
1275+
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.y', value.y, 1.0);
1276+
//>>includeEnd('debug');
1277+
Cartesian2.clone(value, this._imageBasedLightingFactor);
1278+
}
12391279
}
12401280
});
12411281

Source/Scene/Instanced3DModel3DTileContent.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ define([
272272
gltfView = new Uint8Array(uint8Array.subarray(byteOffset, byteOffset + gltfByteLength));
273273
}
274274

275+
var tileset = content._tileset;
276+
275277
// Create model instance collection
276278
var collectionOptions = {
277279
instances : new Array(instancesLength),
@@ -282,10 +284,12 @@ define([
282284
gltf : undefined,
283285
basePath : undefined,
284286
incrementallyLoadTextures : false,
285-
upAxis : content._tileset._gltfUpAxis,
287+
upAxis : tileset._gltfUpAxis,
286288
forwardAxis : Axis.X,
287289
opaquePass : Pass.CESIUM_3D_TILE, // Draw opaque portions during the 3D Tiles pass
288-
pickIdLoaded : getPickIdCallback(content)
290+
pickIdLoaded : getPickIdCallback(content),
291+
imageBasedLightingFactor : tileset.imageBasedLightingFactor,
292+
lightColor : tileset.lightColor
289293
};
290294

291295
if (gltfFormat === 0) {

Source/Scene/Model.js

+99-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
define([
22
'../Core/BoundingSphere',
3+
'../Core/Cartesian2',
34
'../Core/Cartesian3',
45
'../Core/Cartesian4',
56
'../Core/Cartographic',
7+
'../Core/Check',
68
'../Core/clone',
79
'../Core/Color',
810
'../Core/combine',
@@ -74,9 +76,11 @@ define([
7476
'./ShadowMode'
7577
], function(
7678
BoundingSphere,
79+
Cartesian2,
7780
Cartesian3,
7881
Cartesian4,
7982
Cartographic,
83+
Check,
8084
clone,
8185
Color,
8286
combine,
@@ -282,6 +286,8 @@ define([
282286
* @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels.
283287
* @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model.
284288
* @param {Boolean} [options.dequantizeInShader=true] Determines if a {@link https://github.com/google/draco|Draco} encoded model is dequantized on the GPU. This decreases total memory usage for encoded models.
289+
* @param {Cartesian2} [options.imageBasedLightingFactor=Cartesian2(1.0, 1.0)] Scales diffuse and specular image-based lighting from the earth, sky, atmosphere and star skybox.
290+
* @param {Cartesian3} [options.lightColor] The color and intensity of the sunlight used to shade the model.
285291
*
286292
* @see Model.fromGltf
287293
*
@@ -656,6 +662,11 @@ define([
656662
this._rtcCenter2D = undefined; // in projected world coordinates
657663

658664
this._keepPipelineExtras = options.keepPipelineExtras; // keep the buffers in memory for use in other applications
665+
666+
this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);
667+
Cartesian2.clone(options.imageBasedLightingFactor, this._imageBasedLightingFactor);
668+
this._lightColor = Cartesian3.clone(options.lightColor);
669+
this._regenerateShaders = false;
659670
}
660671

661672
defineProperties(Model.prototype, {
@@ -1073,6 +1084,59 @@ define([
10731084
get : function() {
10741085
return this._pickIds;
10751086
}
1087+
},
1088+
1089+
/**
1090+
* Cesium adds lighting from the earth, sky, atmosphere, and star skybox. This cartesian is used to scale the final
1091+
* diffuse and specular lighting contribution from those sources to the final color. A value of 0.0 will disable those light sources.
1092+
*
1093+
* @memberof Model.prototype
1094+
*
1095+
* @type {Cartesian2}
1096+
* @default Cartesian2(1.0, 1.0)
1097+
*/
1098+
imageBasedLightingFactor : {
1099+
get : function() {
1100+
return this._imageBasedLightingFactor;
1101+
},
1102+
set : function(value) {
1103+
//>>includeStart('debug', pragmas.debug);
1104+
Check.typeOf.object('imageBasedLightingFactor', value);
1105+
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.x', value.x, 0.0);
1106+
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.x', value.x, 1.0);
1107+
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.y', value.y, 0.0);
1108+
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.y', value.y, 1.0);
1109+
//>>includeEnd('debug');
1110+
this._regenerateShaders = this._regenerateShaders || (this._imageBasedLightingFactor.x > 0.0 && value.x === 0.0) || (this._imageBasedLightingFactor.x === 0.0 && value.x > 0.0);
1111+
this._regenerateShaders = this._regenerateShaders || (this._imageBasedLightingFactor.y > 0.0 && value.y === 0.0) || (this._imageBasedLightingFactor.y === 0.0 && value.y > 0.0);
1112+
Cartesian2.clone(value, this._imageBasedLightingFactor);
1113+
}
1114+
},
1115+
1116+
/**
1117+
* The color and intensity of the sunlight used to shade the model.
1118+
* <p>
1119+
* For example, disabling additional light sources by setting <code>model.imageBasedLightingFactor = new Cesium.Cartesian2(0.0, 0.0)</code> will make the
1120+
* model much darker. Here, increasing the intensity of the light source will make the model brighter.
1121+
* </p>
1122+
*
1123+
* @memberof Model.prototype
1124+
*
1125+
* @type {Cartesian3}
1126+
* @default undefined
1127+
*/
1128+
lightColor : {
1129+
get : function() {
1130+
return this._lightColor;
1131+
},
1132+
set : function(value) {
1133+
var lightColor = this._lightColor;
1134+
if (value === lightColor || Cartesian3.equals(value, lightColor)) {
1135+
return;
1136+
}
1137+
this._regenerateShaders = this._regenerateShaders || (defined(lightColor) && !defined(value)) || (defined(value) && !defined(lightColor));
1138+
this._lightColor = Cartesian3.clone(value, lightColor);
1139+
}
10761140
}
10771141
});
10781142

@@ -1936,6 +2000,14 @@ define([
19362000
drawFS = 'uniform vec4 czm_pickColor;\n' + drawFS;
19372001
}
19382002

2003+
if (model._imageBasedLightingFactor.x > 0.0 || model._imageBasedLightingFactor.y > 0.0) {
2004+
drawFS = '#define USE_IBL_LIGHTING \n\n' + drawFS;
2005+
}
2006+
2007+
if (defined(model._lightColor)) {
2008+
drawFS = '#define USE_CUSTOM_LIGHT_COLOR \n\n' + drawFS;
2009+
}
2010+
19392011
createAttributesAndProgram(programId, techniqueId, drawFS, drawVS, model, context);
19402012
}
19412013

@@ -1978,6 +2050,14 @@ define([
19782050
drawFS = 'uniform vec4 czm_pickColor;\n' + drawFS;
19792051
}
19802052

2053+
if (model._imageBasedLightingFactor.x > 0.0 || model._imageBasedLightingFactor.y > 0.0) {
2054+
drawFS = '#define USE_IBL_LIGHTING \n\n' + drawFS;
2055+
}
2056+
2057+
if (defined(model._lightColor)) {
2058+
drawFS = '#define USE_CUSTOM_LIGHT_COLOR \n\n' + drawFS;
2059+
}
2060+
19812061
createAttributesAndProgram(programId, techniqueId, drawFS, drawVS, model, context);
19822062
}
19832063

@@ -2846,6 +2926,18 @@ define([
28462926
};
28472927
}
28482928

2929+
function createIBLFactorFunction(model) {
2930+
return function() {
2931+
return model._imageBasedLightingFactor;
2932+
};
2933+
}
2934+
2935+
function createLightColorFunction(model) {
2936+
return function() {
2937+
return model._lightColor;
2938+
};
2939+
}
2940+
28492941
function triangleCountFromPrimitiveIndices(primitive, indicesCount) {
28502942
switch (primitive.mode) {
28512943
case PrimitiveType.TRIANGLES:
@@ -2938,7 +3030,9 @@ define([
29383030
gltf_colorBlend : createColorBlendFunction(model),
29393031
gltf_clippingPlanes: createClippingPlanesFunction(model),
29403032
gltf_clippingPlanesEdgeStyle: createClippingPlanesEdgeStyleFunction(model),
2941-
gltf_clippingPlanesMatrix: createClippingPlanesMatrixFunction(model)
3033+
gltf_clippingPlanesMatrix: createClippingPlanesMatrixFunction(model),
3034+
gltf_iblFactor : createIBLFactorFunction(model),
3035+
gltf_lightColor : createLightColorFunction(model)
29423036
});
29433037

29443038
// Allow callback to modify the uniformMap
@@ -4256,7 +4350,7 @@ define([
42564350
currentClippingPlanesState = clippingPlanes.clippingPlanesState;
42574351
}
42584352

4259-
var shouldRegenerateShaders = this._clippingPlanesState !== currentClippingPlanesState;
4353+
var shouldRegenerateShaders = this._clippingPlanesState !== currentClippingPlanesState || this._regenerateShaders;
42604354
this._clippingPlanesState = currentClippingPlanesState;
42614355

42624356
// Regenerate shaders if color shading changed from last update
@@ -4272,6 +4366,8 @@ define([
42724366
updateColor(this, frameState, false);
42734367
updateSilhouette(this, frameState, false);
42744368
}
4369+
4370+
this._regenerateShaders = false;
42754371
}
42764372

42774373
if (justLoaded) {
@@ -4365,7 +4461,7 @@ define([
43654461
destroyIfNotCached(rendererResources, cachedRendererResources);
43664462

43674463
var programId;
4368-
if (isClippingEnabled(model) || isColorShadingEnabled(model)) {
4464+
if (isClippingEnabled(model) || isColorShadingEnabled(model) || model._regenerateShaders) {
43694465
rendererResources.programs = {};
43704466
rendererResources.silhouettePrograms = {};
43714467

0 commit comments

Comments
 (0)