Skip to content

Commit

Permalink
Merge pull request #7025 from AnalyticalGraphicsInc/model-lighting-op…
Browse files Browse the repository at this point in the history
…tions

Model lighting options
  • Loading branch information
lilleyse authored Oct 19, 2018
2 parents 50d10f5 + 7dba70b commit 6795351
Show file tree
Hide file tree
Showing 13 changed files with 347 additions and 28 deletions.
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ Change Log
* 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)
* Added WMS-T (time) support in WebMapServiceImageryProvider [#2581](https://github.com/AnalyticalGraphicsInc/cesium/issues/2581)
* 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)
* 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)
* 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)

##### Fixes :wrench:
* Fixed an issue where `pickPosition` would return incorrect results when called after `sampleHeight` or `clampToHeight`. [#7113](https://github.com/AnalyticalGraphicsInc/cesium/pull/7113)
Expand Down
26 changes: 25 additions & 1 deletion Source/DataSources/ModelGraphics.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ define([
* @param {Property} [options.colorBlendMode=ColorBlendMode.HIGHLIGHT] An enum Property specifying how the color blends with the model.
* @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.
* @param {Property} [options.clippingPlanes] A property specifying the {@link ClippingPlaneCollection} used to selectively disable rendering the model.
* @param {Property} [options.imageBasedLightingFactor=new Cartesian2(1.0, 1.0)] A property specifying the contribution from diffuse and specular image-based lighting.
* @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>.
*
* @see {@link https://cesiumjs.org/tutorials/3D-Models-Tutorial/|3D Models Tutorial}
* @demo {@link https://cesiumjs.org/Cesium/Apps/Sandcastle/index.html?src=3D%20Models.html|Cesium Sandcastle 3D Models Demo}
Expand Down Expand Up @@ -96,6 +98,10 @@ define([
this._colorBlendAmountSubscription = undefined;
this._clippingPlanes = undefined;
this._clippingPlanesSubscription = undefined;
this._imageBasedLightingFactor = undefined;
this._imageBasedLightingFactorSubscription = undefined;
this._lightColor = undefined;
this._lightColorSubscription = undefined;
this._definitionChanged = new Event();

this.merge(defaultValue(options, defaultValue.EMPTY_OBJECT));
Expand Down Expand Up @@ -262,7 +268,21 @@ define([
* @memberof ModelGraphics.prototype
* @type {Property}
*/
clippingPlanes : createPropertyDescriptor('clippingPlanes')
clippingPlanes : createPropertyDescriptor('clippingPlanes'),

/**
* A property specifying the {@link Cartesian2} used to scale the diffuse and specular image-based lighting contribution to the final color.
* @memberof ModelGraphics.prototype
* @type {Property}
*/
imageBasedLightingFactor : createPropertyDescriptor('imageBasedLightingFactor'),

/**
* A property specifying the {@link Cartesian3} color of the light source when shading the model.
* @memberOf ModelGraphics.prototype
* @type {Property}
*/
lightColor : createPropertyDescriptor('lightColor')
});

/**
Expand Down Expand Up @@ -293,6 +313,8 @@ define([
result.colorBlendMode = this.colorBlendMode;
result.colorBlendAmount = this.colorBlendAmount;
result.clippingPlanes = this.clippingPlanes;
result.imageBasedLightingFactor = this.imageBasedLightingFactor;
result.lightColor = this.lightColor;

return result;
};
Expand Down Expand Up @@ -327,6 +349,8 @@ define([
this.colorBlendMode = defaultValue(this.colorBlendMode, source.colorBlendMode);
this.colorBlendAmount = defaultValue(this.colorBlendAmount, source.colorBlendAmount);
this.clippingPlanes = defaultValue(this.clippingPlanes, source.clippingPlanes);
this.imageBasedLightingFactor = defaultValue(this.imageBasedLightingFactor, source.imageBasedLightingFactor);
this.lightColor = defaultValue(this.lightColor, source.lightColor);

var sourceNodeTransformations = source.nodeTransformations;
if (defined(sourceNodeTransformations)) {
Expand Down
5 changes: 5 additions & 0 deletions Source/DataSources/ModelVisualizer.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
define([
'../Core/AssociativeArray',
'../Core/BoundingSphere',
'../Core/Cartesian2',
'../Core/Color',
'../Core/defined',
'../Core/destroyObject',
Expand All @@ -17,6 +18,7 @@ define([
], function(
AssociativeArray,
BoundingSphere,
Cartesian2,
Color,
defined,
destroyObject,
Expand All @@ -43,6 +45,7 @@ define([
var defaultColor = Color.WHITE;
var defaultColorBlendMode = ColorBlendMode.HIGHLIGHT;
var defaultColorBlendAmount = 0.5;
var defaultImageBasedLightingFactor = new Cartesian2(1.0, 1.0);

var modelMatrixScratch = new Matrix4();
var nodeMatrixScratch = new Matrix4();
Expand Down Expand Up @@ -157,6 +160,8 @@ define([
model.colorBlendAmount = Property.getValueOrDefault(modelGraphics._colorBlendAmount, time, defaultColorBlendAmount);
model.clippingPlanes = Property.getValueOrUndefined(modelGraphics._clippingPlanes, time);
model.clampAnimations = Property.getValueOrDefault(modelGraphics._clampAnimations, time, defaultClampAnimations);
model.imageBasedLightingFactor = Property.getValueOrDefault(modelGraphics._imageBasedLightingFactor, time, defaultImageBasedLightingFactor);
model.lightColor = Property.getValueOrUndefined(modelGraphics._lightColor, time);

if (model.ready) {
var runAnimations = Property.getValueOrDefault(modelGraphics._runAnimations, time, true);
Expand Down
6 changes: 5 additions & 1 deletion Source/Scene/Batched3DModel3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,9 @@ define([
uniformMapLoaded : batchTable.getUniformMapCallback(),
pickIdLoaded : getPickIdCallback(content),
addBatchIdToGeneratedShaders : (batchLength > 0), // If the batch table has values in it, generated shaders will need a batchId attribute
pickObject : pickObject
pickObject : pickObject,
imageBasedLightingFactor : tileset.imageBasedLightingFactor,
lightColor : tileset.lightColor
});
} else {
// This transcodes glTF to an internal representation for geometry so we can take advantage of the re-batching of vector data.
Expand Down Expand Up @@ -460,6 +462,8 @@ define([
this._model.modelMatrix = this._contentModelMatrix;

this._model.shadows = this._tileset.shadows;
this._model.imageBasedLightingFactor = this._tileset.imageBasedLightingFactor;
this._model.lightColor = this._tileset.lightColor;
this._model.debugWireframe = this._tileset.debugWireframe;

// Update clipping planes
Expand Down
40 changes: 40 additions & 0 deletions Source/Scene/Cesium3DTileset.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,8 @@ define([
* @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.
* @param {Ellipsoid} [options.ellipsoid=Ellipsoid.WGS84] The ellipsoid determining the size and shape of the globe.
* @param {Object} [options.pointCloudShading] Options for constructing a {@link PointCloudShading} object to control point attenuation based on geometric error and lighting.
* @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.
* @param {Cartesian3} [options.lightColor] The color and intensity of the sunlight used to shade models.
* @param {Boolean} [options.debugFreezeFrame=false] For debugging only. Determines if only the tiles from last frame should be used for rendering.
* @param {Boolean} [options.debugColorizeTiles=false] For debugging only. When true, assigns a random color to each tile.
* @param {Boolean} [options.debugWireframe=false] For debugging only. When true, render's each tile's content as a wireframe.
Expand Down Expand Up @@ -569,6 +571,21 @@ define([
this._clippingPlanes = undefined;
this.clippingPlanes = options.clippingPlanes;

this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);
Cartesian2.clone(options.imageBasedLightingFactor, this._imageBasedLightingFactor);

/**
* The color and intensity of the sunlight used to shade a model.
* <p>
* For example, disabling additional light sources by setting <code>model.imageBasedLightingFactor = new Cartesian2(0.0, 0.0)</code> will make the
* model much darker. Here, increasing the intensity of the light source will make the model brighter.
* </p>
*
* @type {Cartesian3}
* @default undefined
*/
this.lightColor = options.lightColor;

/**
* This property is for debugging only; it is not optimized for production use.
* <p>
Expand Down Expand Up @@ -1236,6 +1253,29 @@ define([

return this._extras;
}
},

/**
* Cesium adds lighting from the earth, sky, atmosphere, and star skybox. This cartesian is used to scale the final
* diffuse and specular lighting contribution from those sources to the final color. A value of 0.0 will disable those light sources.
*
* @type {Cartesian2}
* @default Cartesian2(1.0, 1.0)
*/
imageBasedLightingFactor : {
get : function() {
return this._imageBasedLightingFactor;
},
set : function(value) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('imageBasedLightingFactor', value);
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.x', value.x, 0.0);
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.x', value.x, 1.0);
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.y', value.y, 0.0);
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.y', value.y, 1.0);
//>>includeEnd('debug');
Cartesian2.clone(value, this._imageBasedLightingFactor);
}
}
});

Expand Down
8 changes: 6 additions & 2 deletions Source/Scene/Instanced3DModel3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ define([
gltfView = new Uint8Array(uint8Array.subarray(byteOffset, byteOffset + gltfByteLength));
}

var tileset = content._tileset;

// Create model instance collection
var collectionOptions = {
instances : new Array(instancesLength),
Expand All @@ -282,10 +284,12 @@ define([
gltf : undefined,
basePath : undefined,
incrementallyLoadTextures : false,
upAxis : content._tileset._gltfUpAxis,
upAxis : tileset._gltfUpAxis,
forwardAxis : Axis.X,
opaquePass : Pass.CESIUM_3D_TILE, // Draw opaque portions during the 3D Tiles pass
pickIdLoaded : getPickIdCallback(content)
pickIdLoaded : getPickIdCallback(content),
imageBasedLightingFactor : tileset.imageBasedLightingFactor,
lightColor : tileset.lightColor
};

if (gltfFormat === 0) {
Expand Down
102 changes: 99 additions & 3 deletions Source/Scene/Model.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
define([
'../Core/BoundingSphere',
'../Core/Cartesian2',
'../Core/Cartesian3',
'../Core/Cartesian4',
'../Core/Cartographic',
'../Core/Check',
'../Core/clone',
'../Core/Color',
'../Core/combine',
Expand Down Expand Up @@ -74,9 +76,11 @@ define([
'./ShadowMode'
], function(
BoundingSphere,
Cartesian2,
Cartesian3,
Cartesian4,
Cartographic,
Check,
clone,
Color,
combine,
Expand Down Expand Up @@ -282,6 +286,8 @@ define([
* @param {Number} [options.silhouetteSize=0.0] The size of the silhouette in pixels.
* @param {ClippingPlaneCollection} [options.clippingPlanes] The {@link ClippingPlaneCollection} used to selectively disable rendering the model.
* @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.
* @param {Cartesian2} [options.imageBasedLightingFactor=Cartesian2(1.0, 1.0)] Scales diffuse and specular image-based lighting from the earth, sky, atmosphere and star skybox.
* @param {Cartesian3} [options.lightColor] The color and intensity of the sunlight used to shade the model.
*
* @see Model.fromGltf
*
Expand Down Expand Up @@ -656,6 +662,11 @@ define([
this._rtcCenter2D = undefined; // in projected world coordinates

this._keepPipelineExtras = options.keepPipelineExtras; // keep the buffers in memory for use in other applications

this._imageBasedLightingFactor = new Cartesian2(1.0, 1.0);
Cartesian2.clone(options.imageBasedLightingFactor, this._imageBasedLightingFactor);
this._lightColor = Cartesian3.clone(options.lightColor);
this._regenerateShaders = false;
}

defineProperties(Model.prototype, {
Expand Down Expand Up @@ -1073,6 +1084,59 @@ define([
get : function() {
return this._pickIds;
}
},

/**
* Cesium adds lighting from the earth, sky, atmosphere, and star skybox. This cartesian is used to scale the final
* diffuse and specular lighting contribution from those sources to the final color. A value of 0.0 will disable those light sources.
*
* @memberof Model.prototype
*
* @type {Cartesian2}
* @default Cartesian2(1.0, 1.0)
*/
imageBasedLightingFactor : {
get : function() {
return this._imageBasedLightingFactor;
},
set : function(value) {
//>>includeStart('debug', pragmas.debug);
Check.typeOf.object('imageBasedLightingFactor', value);
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.x', value.x, 0.0);
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.x', value.x, 1.0);
Check.typeOf.number.greaterThanOrEquals('imageBasedLightingFactor.y', value.y, 0.0);
Check.typeOf.number.lessThanOrEquals('imageBasedLightingFactor.y', value.y, 1.0);
//>>includeEnd('debug');
this._regenerateShaders = this._regenerateShaders || (this._imageBasedLightingFactor.x > 0.0 && value.x === 0.0) || (this._imageBasedLightingFactor.x === 0.0 && value.x > 0.0);
this._regenerateShaders = this._regenerateShaders || (this._imageBasedLightingFactor.y > 0.0 && value.y === 0.0) || (this._imageBasedLightingFactor.y === 0.0 && value.y > 0.0);
Cartesian2.clone(value, this._imageBasedLightingFactor);
}
},

/**
* The color and intensity of the sunlight used to shade the model.
* <p>
* For example, disabling additional light sources by setting <code>model.imageBasedLightingFactor = new Cesium.Cartesian2(0.0, 0.0)</code> will make the
* model much darker. Here, increasing the intensity of the light source will make the model brighter.
* </p>
*
* @memberof Model.prototype
*
* @type {Cartesian3}
* @default undefined
*/
lightColor : {
get : function() {
return this._lightColor;
},
set : function(value) {
var lightColor = this._lightColor;
if (value === lightColor || Cartesian3.equals(value, lightColor)) {
return;
}
this._regenerateShaders = this._regenerateShaders || (defined(lightColor) && !defined(value)) || (defined(value) && !defined(lightColor));
this._lightColor = Cartesian3.clone(value, lightColor);
}
}
});

Expand Down Expand Up @@ -1936,6 +2000,14 @@ define([
drawFS = 'uniform vec4 czm_pickColor;\n' + drawFS;
}

if (model._imageBasedLightingFactor.x > 0.0 || model._imageBasedLightingFactor.y > 0.0) {
drawFS = '#define USE_IBL_LIGHTING \n\n' + drawFS;
}

if (defined(model._lightColor)) {
drawFS = '#define USE_CUSTOM_LIGHT_COLOR \n\n' + drawFS;
}

createAttributesAndProgram(programId, techniqueId, drawFS, drawVS, model, context);
}

Expand Down Expand Up @@ -1978,6 +2050,14 @@ define([
drawFS = 'uniform vec4 czm_pickColor;\n' + drawFS;
}

if (model._imageBasedLightingFactor.x > 0.0 || model._imageBasedLightingFactor.y > 0.0) {
drawFS = '#define USE_IBL_LIGHTING \n\n' + drawFS;
}

if (defined(model._lightColor)) {
drawFS = '#define USE_CUSTOM_LIGHT_COLOR \n\n' + drawFS;
}

createAttributesAndProgram(programId, techniqueId, drawFS, drawVS, model, context);
}

Expand Down Expand Up @@ -2846,6 +2926,18 @@ define([
};
}

function createIBLFactorFunction(model) {
return function() {
return model._imageBasedLightingFactor;
};
}

function createLightColorFunction(model) {
return function() {
return model._lightColor;
};
}

function triangleCountFromPrimitiveIndices(primitive, indicesCount) {
switch (primitive.mode) {
case PrimitiveType.TRIANGLES:
Expand Down Expand Up @@ -2938,7 +3030,9 @@ define([
gltf_colorBlend : createColorBlendFunction(model),
gltf_clippingPlanes: createClippingPlanesFunction(model),
gltf_clippingPlanesEdgeStyle: createClippingPlanesEdgeStyleFunction(model),
gltf_clippingPlanesMatrix: createClippingPlanesMatrixFunction(model)
gltf_clippingPlanesMatrix: createClippingPlanesMatrixFunction(model),
gltf_iblFactor : createIBLFactorFunction(model),
gltf_lightColor : createLightColorFunction(model)
});

// Allow callback to modify the uniformMap
Expand Down Expand Up @@ -4256,7 +4350,7 @@ define([
currentClippingPlanesState = clippingPlanes.clippingPlanesState;
}

var shouldRegenerateShaders = this._clippingPlanesState !== currentClippingPlanesState;
var shouldRegenerateShaders = this._clippingPlanesState !== currentClippingPlanesState || this._regenerateShaders;
this._clippingPlanesState = currentClippingPlanesState;

// Regenerate shaders if color shading changed from last update
Expand All @@ -4272,6 +4366,8 @@ define([
updateColor(this, frameState, false);
updateSilhouette(this, frameState, false);
}

this._regenerateShaders = false;
}

if (justLoaded) {
Expand Down Expand Up @@ -4365,7 +4461,7 @@ define([
destroyIfNotCached(rendererResources, cachedRendererResources);

var programId;
if (isClippingEnabled(model) || isColorShadingEnabled(model)) {
if (isClippingEnabled(model) || isColorShadingEnabled(model) || model._regenerateShaders) {
rendererResources.programs = {};
rendererResources.silhouettePrograms = {};

Expand Down
Loading

0 comments on commit 6795351

Please sign in to comment.