diff --git a/CHANGES.md b/CHANGES.md index 42cc192c3c53..58b2630c92ff 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -30,7 +30,7 @@ Change Log * Only one mesh per node is supported. * Only one primitive per mesh is supported. * Updated documentation links to reflect new locations on cesiumjs.org and cesium.com. -* Updated 'Viewer.zoomTo' and 'Viewer.flyTo' to take in Cesium3DTilesets as a target and updated sandcastle 3DTileset examples to reflect this change +* Updated `Viewer.zoomTo` and `Viewer.flyTo` to take in Cesium3DTilesets as a target and updated sandcastle 3DTileset examples to reflect this change * Fixed a glTF animation bug that caused certain animations to jitter. [#5740](https://github.com/AnalyticalGraphicsInc/cesium/pull/5740) * Fixed a bug when creating billboard and model entities without a globe. [#6109](https://github.com/AnalyticalGraphicsInc/cesium/pull/6109) * Added support for vertex shader uniforms when `tileset.colorBlendMode` is `MIX` or `REPLACE`. [#5874](https://github.com/AnalyticalGraphicsInc/cesium/pull/5874) @@ -40,6 +40,7 @@ Change Log * Fixed sandcastle Particle System example for better visual [#6132](https://github.com/AnalyticalGraphicsInc/cesium/pull/6132) * Fixed camera movement and look functions for 2D mode [#5884](https://github.com/AnalyticalGraphicsInc/cesium/issues/5884) * Fixed discrepancy between default value used and commented value for default value for halfAxes of OrientedBoundingBox. [#6147](https://github.com/AnalyticalGraphicsInc/cesium/pull/6147) +* Added `sunLighting` option to `Cesium3DTileset`, `Model`, and `Model.fromGltf` to control whether the tileset or model is shaded based on the sun direction. This option is ignored if the model has built-in shaders. [#6160](https://github.com/AnalyticalGraphicsInc/cesium/pull/6160) * Added `Cartographic.toCartesian` to convert from Cartographic to Cartesian3. [#6163](https://github.com/AnalyticalGraphicsInc/cesium/pull/6163) ### 1.41 - 2018-01-02 diff --git a/Source/DataSources/ModelGraphics.js b/Source/DataSources/ModelGraphics.js index 5dedd97c6f94..5aff5676a473 100644 --- a/Source/DataSources/ModelGraphics.js +++ b/Source/DataSources/ModelGraphics.js @@ -48,6 +48,7 @@ define([ * @param {Property} [options.clampAnimations=true] A boolean Property specifying if glTF animations should hold the last pose for time durations with no keyframes. * @param {Property} [options.nodeTransformations] An object, where keys are names of nodes, and values are {@link TranslationRotationScale} Properties describing the transformation to apply to that node. * @param {Property} [options.shadows=ShadowMode.ENABLED] An enum Property specifying whether the model casts or receives shadows from each light source. + * @param {Property} [options.sunLighting=true] An boolean Property specifying whether to enable lighting the model with the sun as a light source. This value is ignored if the model has built-in shaders. * @param {Property} [options.heightReference=HeightReference.NONE] A Property specifying what the height is relative to. * @param {Property} [options.distanceDisplayCondition] A Property specifying at what distance from the camera that this model will be displayed. * @param {Property} [options.silhouetteColor=Color.RED] A Property specifying the {@link Color} of the silhouette. @@ -73,6 +74,8 @@ define([ this._incrementallyLoadTexturesSubscription = undefined; this._shadows = undefined; this._shadowsSubscription = undefined; + this._sunLighting = undefined; + this._sunLightingSubsciption = undefined; this._uri = undefined; this._uriSubscription = undefined; this._runAnimations = undefined; @@ -169,6 +172,16 @@ define([ */ shadows : createPropertyDescriptor('shadows'), + /** + * Get or sets the boolean Property specifying whether to + * enable lighting the model with the sun as a light source. + * This value is ignored if the model has built-in shaders. + * @memberof ModelGraphics.prototype + * @type {Property} + * @default true + */ + sunLighting : createPropertyDescriptor('sunLighting'), + /** * Gets or sets the string Property specifying the URI of the glTF asset. * @memberof ModelGraphics.prototype @@ -281,6 +294,7 @@ define([ result.maximumScale = this.maximumScale; result.incrementallyLoadTextures = this.incrementallyLoadTextures; result.shadows = this.shadows; + result.sunLighting = this.sunLighting; result.uri = this.uri; result.runAnimations = this.runAnimations; result.clampAnimations = this.clampAnimations; @@ -316,6 +330,7 @@ define([ this.maximumScale = defaultValue(this.maximumScale, source.maximumScale); this.incrementallyLoadTextures = defaultValue(this.incrementallyLoadTextures, source.incrementallyLoadTextures); this.shadows = defaultValue(this.shadows, source.shadows); + this.sunLighting = defaultValue(this.sunLighting, source.sunLighting); this.uri = defaultValue(this.uri, source.uri); this.runAnimations = defaultValue(this.runAnimations, source.runAnimations); this.clampAnimations = defaultValue(this.clampAnimations, source.clampAnimations); diff --git a/Source/DataSources/ModelVisualizer.js b/Source/DataSources/ModelVisualizer.js index 68779e161e51..030a4606c9d5 100644 --- a/Source/DataSources/ModelVisualizer.js +++ b/Source/DataSources/ModelVisualizer.js @@ -37,6 +37,7 @@ define([ var defaultIncrementallyLoadTextures = true; var defaultClampAnimations = true; var defaultShadows = ShadowMode.ENABLED; + var defaultSunLighting = true; var defaultHeightReference = HeightReference.NONE; var defaultSilhouetteColor = Color.RED; var defaultSilhouetteSize = 0.0; @@ -124,6 +125,7 @@ define([ model = Model.fromGltf({ url : resource, incrementallyLoadTextures : Property.getValueOrDefault(modelGraphics._incrementallyLoadTextures, time, defaultIncrementallyLoadTextures), + sunLighting : Property.getValueOrDefault(modelGraphics._sunLighting, time, defaultSunLighting), scene : this._scene }); @@ -148,6 +150,7 @@ define([ model.maximumScale = Property.getValueOrUndefined(modelGraphics._maximumScale, time); model.modelMatrix = Matrix4.clone(modelMatrix, model.modelMatrix); model.shadows = Property.getValueOrDefault(modelGraphics._shadows, time, defaultShadows); + model.sunLighting = Property.getValueOrDefault(modelGraphics._sunLighting, time, defaultSunLighting); model.heightReference = Property.getValueOrDefault(modelGraphics._heightReference, time, defaultHeightReference); model.distanceDisplayCondition = Property.getValueOrUndefined(modelGraphics._distanceDisplayCondition, time); model.silhouetteColor = Property.getValueOrDefault(modelGraphics._silhouetteColor, time, defaultSilhouetteColor, model._silhouetteColor); diff --git a/Source/Scene/Batched3DModel3DTileContent.js b/Source/Scene/Batched3DModel3DTileContent.js index 5ecb891e1a73..bb22427fe2ab 100644 --- a/Source/Scene/Batched3DModel3DTileContent.js +++ b/Source/Scene/Batched3DModel3DTileContent.js @@ -402,6 +402,7 @@ define([ shadows: tileset.shadows, debugWireframe: tileset.debugWireframe, incrementallyLoadTextures : false, + sunLighting : tileset._sunLighting, vertexShaderLoaded : getVertexShaderCallback(content), fragmentShaderLoaded : getFragmentShaderCallback(content), uniformMapLoaded : batchTable.getUniformMapCallback(), diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js index 8be43d98e100..e448198947fb 100644 --- a/Source/Scene/Cesium3DTileset.js +++ b/Source/Scene/Cesium3DTileset.js @@ -98,6 +98,7 @@ define([ * @param {Boolean} [options.show=true] Determines if the tileset will be shown. * @param {Matrix4} [options.modelMatrix=Matrix4.IDENTITY] A 4x4 transformation matrix that transforms the tileset's root tile. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the tileset casts or receives shadows from each light source. + * @param {Boolean} [options.sunLighting=true] Enable lighting the tileset with the sun as a light source. * @param {Number} [options.maximumScreenSpaceError=16] The maximum screen space error used to drive level of detail refinement. * @param {Number} [options.maximumMemoryUsage=512] The maximum amount of memory in MB that can be used by the tileset. * @param {Boolean} [options.cullWithChildrenBounds=true] Optimization option. Whether to cull tiles using the union of their children bounding volumes. @@ -223,6 +224,8 @@ define([ this._modelMatrix = defined(options.modelMatrix) ? Matrix4.clone(options.modelMatrix) : Matrix4.clone(Matrix4.IDENTITY); + this._sunLighting = defaultValue(options.sunLighting, true); + this._statistics = new Cesium3DTilesetStatistics(); this._statisticsLastColor = new Cesium3DTilesetStatistics(); this._statisticsLastPick = new Cesium3DTilesetStatistics(); diff --git a/Source/Scene/Instanced3DModel3DTileContent.js b/Source/Scene/Instanced3DModel3DTileContent.js index 1373144e21bb..b0cffab7ad4b 100644 --- a/Source/Scene/Instanced3DModel3DTileContent.js +++ b/Source/Scene/Instanced3DModel3DTileContent.js @@ -313,6 +313,7 @@ define([ url : undefined, requestType : RequestType.TILES3D, gltf : undefined, + sunLighting : content._tileset._sunLighting, basePath : undefined, incrementallyLoadTextures : false, upAxis : content._tileset._gltfUpAxis, diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js index 6457c7006e52..9ae8ad91051e 100644 --- a/Source/Scene/Model.js +++ b/Source/Scene/Model.js @@ -263,6 +263,7 @@ define([ * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded. * @param {Boolean} [options.clampAnimations=true] Determines if the model's animations should hold a pose over frames where no keyframes are specified. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from each light source. + * @param {Boolean} [options.sunLighting=true] Enable lighting the model with the sun as a light source. This value is ignored if the model has built-in shaders. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each draw command in the model. * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe. * @param {HeightReference} [options.heightReference] Determines how the model is drawn relative to terrain. @@ -474,6 +475,7 @@ define([ this._defaultTexture = undefined; this._incrementallyLoadTextures = defaultValue(options.incrementallyLoadTextures, true); + this._sunLighting = defaultValue(options.sunLighting, true); this._asynchronous = defaultValue(options.asynchronous, true); /** @@ -1056,6 +1058,7 @@ define([ * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded. * @param {Boolean} [options.clampAnimations=true] Determines if the model's animations should hold a pose over frames where no keyframes are specified. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the model casts or receives shadows from each light source. + * @param {Boolean} [options.sunLighting=true] Enable lighting the model with the sun as a light source. This value is ignored if the model has built-in shaders. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for each {@link DrawCommand} in the model. * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the model in wireframe. * @param {HeightReference} [options.heightReference] Determines how the model is drawn relative to terrain. @@ -4102,6 +4105,7 @@ define([ if (!this._updatedGltfVersion) { var options = { optimizeForCesium: true, + sunLighting: this._sunLighting, addBatchIdToGeneratedShaders : this._addBatchIdToGeneratedShaders }; frameState.brdfLutGenerator.update(frameState); diff --git a/Source/Scene/ModelInstanceCollection.js b/Source/Scene/ModelInstanceCollection.js index 061abb675f32..80025c8c53a7 100644 --- a/Source/Scene/ModelInstanceCollection.js +++ b/Source/Scene/ModelInstanceCollection.js @@ -86,6 +86,7 @@ define([ * @param {Boolean} [options.asynchronous=true] Determines if model WebGL resource creation will be spread out over several frames or block until completion once all glTF files are loaded. * @param {Boolean} [options.incrementallyLoadTextures=true] Determine if textures may continue to stream in after the model is loaded. * @param {ShadowMode} [options.shadows=ShadowMode.ENABLED] Determines whether the collection casts or receives shadows from each light source. + * @param {Boolean} [options.sunLighting=true] Enable lighting the instances with the sun as a light source. * @param {Boolean} [options.debugShowBoundingVolume=false] For debugging only. Draws the bounding sphere for the collection. * @param {Boolean} [options.debugWireframe=false] For debugging only. Draws the instances in wireframe. * @@ -155,6 +156,7 @@ define([ this._asynchronous = options.asynchronous; this._incrementallyLoadTextures = options.incrementallyLoadTextures; this._upAxis = options.upAxis; // Undocumented option + this._sunLighting = defaultValue(options.sunLighting, true); this.shadows = defaultValue(options.shadows, ShadowMode.ENABLED); this._shadows = this.shadows; @@ -605,6 +607,7 @@ define([ asynchronous : collection._asynchronous, allowPicking : allowPicking, incrementallyLoadTextures : collection._incrementallyLoadTextures, + sunLighting : collection._sunLighting, upAxis : collection._upAxis, precreatedAttributes : undefined, vertexShaderLoaded : undefined, diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index 587ad19dbe3e..d56945386ca2 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -818,6 +818,7 @@ define([ var backFaceCulling = content._backFaceCulling; var vertexArray = content._drawCommand.vertexArray; var clippingPlanes = content._tileset.clippingPlanes; + var sunLighting = content._tileset._sunLighting; var colorStyleFunction; var showStyleFunction; @@ -1039,8 +1040,13 @@ define([ vs += ' color = color * u_highlightColor; \n'; if (hasNormals) { - vs += ' normal = czm_normal * normal; \n' + - ' float diffuseStrength = czm_getLambertDiffuse(czm_sunDirectionEC, normal); \n' + + vs += ' normal = czm_normal * normal; \n'; + if (sunLighting) { + vs += ' vec3 lightDirection = normalize(czm_sunDirectionEC);\n'; + } else { + vs += ' vec3 lightDirection = vec3(0.0, 0.0, 1.0);\n'; + } + vs += ' float diffuseStrength = czm_getLambertDiffuse(lightDirection, normal); \n' + ' diffuseStrength = max(diffuseStrength, 0.4); \n' + // Apply some ambient lighting ' color *= diffuseStrength; \n'; } diff --git a/Source/ThirdParty/GltfPipeline/processModelMaterialsCommon.js b/Source/ThirdParty/GltfPipeline/processModelMaterialsCommon.js index 8420675e78e2..0ccfc22d56a6 100644 --- a/Source/ThirdParty/GltfPipeline/processModelMaterialsCommon.js +++ b/Source/ThirdParty/GltfPipeline/processModelMaterialsCommon.js @@ -70,7 +70,7 @@ define([ ForEach.material(gltf, function(material) { if (defined(material.extensions) && defined(material.extensions.KHR_materials_common)) { var khrMaterialsCommon = material.extensions.KHR_materials_common; - var techniqueKey = getTechniqueKey(khrMaterialsCommon); + var techniqueKey = getTechniqueKey(khrMaterialsCommon, options); var technique = techniques[techniqueKey]; if (!defined(technique)) { technique = generateTechnique(gltf, khrMaterialsCommon, lightParameters, options); @@ -228,6 +228,7 @@ define([ function generateTechnique(gltf, khrMaterialsCommon, lightParameters, options) { var optimizeForCesium = defaultValue(options.optimizeForCesium, false); + var sunLighting = defaultValue(options.sunLighting, true); var hasCesiumRTCExtension = defined(gltf.extensions) && defined(gltf.extensions.CESIUM_RTC); var addBatchIdToGeneratedShaders = defaultValue(options.addBatchIdToGeneratedShaders, false); @@ -547,7 +548,7 @@ define([ } if (!hasNonAmbientLights && (lightingModel !== 'CONSTANT')) { - if (optimizeForCesium) { + if (optimizeForCesium && sunLighting) { fragmentLightingBlock += ' vec3 l = normalize(czm_sunDirectionEC);\n'; } else { fragmentLightingBlock += ' vec3 l = vec3(0.0, 0.0, 1.0);\n'; @@ -766,7 +767,7 @@ define([ } } - function getTechniqueKey(khrMaterialsCommon) { + function getTechniqueKey(khrMaterialsCommon, options) { var techniqueKey = ''; techniqueKey += 'technique:' + khrMaterialsCommon.technique + ';'; @@ -792,7 +793,8 @@ define([ if (jointCount > 0) { techniqueKey += skinningInfo.type + ';'; } - techniqueKey += primitiveInfo.hasVertexColors; + techniqueKey += primitiveInfo.hasVertexColors + ';'; + techniqueKey += options.sunLighting; return techniqueKey; } diff --git a/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js b/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js index e207d52e7d8f..7fe08f7454b0 100644 --- a/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js +++ b/Source/ThirdParty/GltfPipeline/processPbrMetallicRoughness.js @@ -70,6 +70,7 @@ define([ function generateTechnique(gltf, material, options) { var optimizeForCesium = defaultValue(options.optimizeForCesium, false); + var sunLighting = defaultValue(options.sunLighting, true); var hasCesiumRTCExtension = defined(gltf.extensions) && defined(gltf.extensions.CESIUM_RTC); var addBatchIdToGeneratedShaders = defaultValue(options.addBatchIdToGeneratedShaders, false); @@ -504,7 +505,7 @@ define([ // Generate fragment shader's lighting block fragmentShader += ' vec3 lightColor = vec3(1.0, 1.0, 1.0);\n'; - if (optimizeForCesium) { + if (optimizeForCesium && sunLighting) { fragmentShader += ' vec3 l = normalize(czm_sunDirectionEC);\n'; } else { fragmentShader += ' vec3 l = vec3(0.0, 0.0, 1.0);\n'; diff --git a/Specs/DataSources/ModelGraphicsSpec.js b/Specs/DataSources/ModelGraphicsSpec.js index fbcaf606ffc1..98bb619706db 100644 --- a/Specs/DataSources/ModelGraphicsSpec.js +++ b/Specs/DataSources/ModelGraphicsSpec.js @@ -39,6 +39,7 @@ defineSuite([ runAnimations : false, clampAnimations : false, shadows : ShadowMode.DISABLED, + sunLighting : false, heightReference : HeightReference.CLAMP_TO_GROUND, distanceDisplayCondition : new DistanceDisplayCondition(), silhouetteColor : new Color(1.0, 0.0, 0.0, 1.0), @@ -64,6 +65,7 @@ defineSuite([ expect(model.maximumScale).toBeInstanceOf(ConstantProperty); expect(model.incrementallyLoadTextures).toBeInstanceOf(ConstantProperty); expect(model.shadows).toBeInstanceOf(ConstantProperty); + expect(model.sunLighting).toBeInstanceOf(ConstantProperty); expect(model.heightReference).toBeInstanceOf(ConstantProperty); expect(model.distanceDisplayCondition).toBeInstanceOf(ConstantProperty); expect(model.silhouetteColor).toBeInstanceOf(ConstantProperty); @@ -84,6 +86,7 @@ defineSuite([ expect(model.maximumScale.getValue()).toEqual(options.maximumScale); expect(model.incrementallyLoadTextures.getValue()).toEqual(options.incrementallyLoadTextures); expect(model.shadows.getValue()).toEqual(options.shadows); + expect(model.sunLighting.getValue()).toEqual(options.sunLighting); expect(model.heightReference.getValue()).toEqual(options.heightReference); expect(model.distanceDisplayCondition.getValue()).toEqual(options.distanceDisplayCondition); expect(model.silhouetteColor.getValue()).toEqual(options.silhouetteColor); @@ -113,6 +116,7 @@ defineSuite([ source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.sunLighting = new ConstantProperty(true); source.heightReference = new ConstantProperty(HeightReference.CLAMP_TO_GROUND); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.silhouetteColor = new ConstantProperty(new Color(1.0, 0.0, 0.0, 1.0)); @@ -144,6 +148,7 @@ defineSuite([ expect(target.maximumScale).toBe(source.maximumScale); expect(target.incrementallyLoadTextures).toBe(source.incrementallyLoadTextures); expect(target.shadows).toBe(source.shadows); + expect(target.sunLighting).toBe(source.sunLighting); expect(target.heightReference).toBe(source.heightReference); expect(target.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(target.silhouetteColor).toEqual(source.silhouetteColor); @@ -166,6 +171,7 @@ defineSuite([ source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.sunLighting = new ConstantProperty(true); source.heightReference = new ConstantProperty(HeightReference.CLAMP_TO_GROUND); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.silhouetteColor = new ConstantProperty(new Color()); @@ -187,6 +193,7 @@ defineSuite([ var maximumScale = new ConstantProperty(200.0); var incrementallyLoadTextures = new ConstantProperty(true); var shadows = new ConstantProperty(ShadowMode.ENABLED); + var sunLighting = new ConstantProperty(true); var heightReference = new ConstantProperty(HeightReference.CLAMP_TO_GROUND); var distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); var silhouetteColor = new ConstantProperty(new Color()); @@ -209,6 +216,7 @@ defineSuite([ target.maximumScale = maximumScale; target.incrementallyLoadTextures = incrementallyLoadTextures; target.shadows = shadows; + target.sunLighting = sunLighting; target.heightReference = heightReference; target.distanceDisplayCondition = distanceDisplayCondition; target.silhouetteColor = silhouetteColor; @@ -230,6 +238,7 @@ defineSuite([ expect(target.maximumScale).toBe(maximumScale); expect(target.incrementallyLoadTextures).toBe(incrementallyLoadTextures); expect(target.shadows).toBe(shadows); + expect(target.sunLighting).toBe(sunLighting); expect(target.heightReference).toBe(heightReference); expect(target.distanceDisplayCondition).toBe(distanceDisplayCondition); expect(target.silhouetteColor).toBe(silhouetteColor); @@ -252,6 +261,7 @@ defineSuite([ source.maximumScale = new ConstantProperty(200.0); source.incrementallyLoadTextures = new ConstantProperty(true); source.shadows = new ConstantProperty(ShadowMode.ENABLED); + source.sunLighting = new ConstantProperty(true); source.heightReference = new ConstantProperty(HeightReference.CLAMP_TO_GROUND); source.distanceDisplayCondition = new ConstantProperty(new DistanceDisplayCondition()); source.silhouetteColor = new ConstantProperty(new Color()); @@ -275,6 +285,7 @@ defineSuite([ expect(result.maximumScale).toBe(source.maximumScale); expect(result.incrementallyLoadTextures).toBe(source.incrementallyLoadTextures); expect(result.shadows).toBe(source.shadows); + expect(result.sunLighting).toBe(source.sunLighting); expect(result.heightReference).toBe(source.heightReference); expect(result.distanceDisplayCondition).toBe(source.distanceDisplayCondition); expect(result.silhouetteColor).toEqual(source.silhouetteColor); diff --git a/Specs/Scene/Batched3DModel3DTileContentSpec.js b/Specs/Scene/Batched3DModel3DTileContentSpec.js index 2183b62f39e4..4fa8f017d8b2 100644 --- a/Specs/Scene/Batched3DModel3DTileContentSpec.js +++ b/Specs/Scene/Batched3DModel3DTileContentSpec.js @@ -8,7 +8,8 @@ defineSuite([ 'Core/Plane', 'Core/Transforms', 'Specs/Cesium3DTilesTester', - 'Specs/createScene' + 'Specs/createScene', + 'ThirdParty/when' ], function( Batched3DModel3DTileContent, Cartesian3, @@ -19,7 +20,8 @@ defineSuite([ Plane, Transforms, Cesium3DTilesTester, - createScene) { + createScene, + when) { 'use strict'; var scene; @@ -323,6 +325,16 @@ defineSuite([ }); }); + it('sets sunLighting', function() { + return when.all([ + Cesium3DTilesTester.loadTileset(scene, withKHRMaterialsCommonUrl, {sunLighting : true}), + Cesium3DTilesTester.loadTileset(scene, withKHRMaterialsCommonUrl, {sunLighting : false}) + ]).then(function(tilesets) { + expect(tilesets[0]._root.content._model._sunLighting).toBe(true); + expect(tilesets[1]._root.content._model._sunLighting).toBe(false); + }); + }); + it('destroys', function() { return Cesium3DTilesTester.tileDestroys(scene, withoutBatchTableUrl); }); diff --git a/Specs/Scene/Instanced3DModel3DTileContentSpec.js b/Specs/Scene/Instanced3DModel3DTileContentSpec.js index 7b520df17c43..1a36aec82554 100644 --- a/Specs/Scene/Instanced3DModel3DTileContentSpec.js +++ b/Specs/Scene/Instanced3DModel3DTileContentSpec.js @@ -8,7 +8,8 @@ defineSuite([ 'Core/Transforms', 'Scene/TileBoundingSphere', 'Specs/Cesium3DTilesTester', - 'Specs/createScene' + 'Specs/createScene', + 'ThirdParty/when' ], 'Scene/Instanced3DModel3DTileContent', function( Cartesian3, ClippingPlaneCollection, @@ -19,7 +20,8 @@ defineSuite([ Transforms, TileBoundingSphere, Cesium3DTilesTester, - createScene) { + createScene, + when) { 'use strict'; var scene; @@ -336,6 +338,16 @@ defineSuite([ }); }); + it('sets sunLighting', function() { + return when.all([ + Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl, {sunLighting : true}), + Cesium3DTilesTester.loadTileset(scene, withBatchTableUrl, {sunLighting : false}) + ]).then(function(tilesets) { + expect(tilesets[0]._root.content._modelInstanceCollection._model._sunLighting).toBe(true); + expect(tilesets[1]._root.content._modelInstanceCollection._model._sunLighting).toBe(false); + }); + }); + it('destroys', function() { return Cesium3DTilesTester.tileDestroys(scene, withoutBatchTableUrl); }); diff --git a/Specs/Scene/ModelInstanceCollectionSpec.js b/Specs/Scene/ModelInstanceCollectionSpec.js index bb51e7e8f93e..9a75fe64d87e 100644 --- a/Specs/Scene/ModelInstanceCollectionSpec.js +++ b/Specs/Scene/ModelInstanceCollectionSpec.js @@ -555,6 +555,24 @@ defineSuite([ }); }); + it('sunLighting', function() { + return when.all([ + loadCollection({ + gltf : boxGltf, + instances : createInstances(4), + sunLighting : true + }), + loadCollection({ + gltf : boxGltf, + instances : createInstances(4), + sunLighting : false + }) + ]).then(function(collections) { + expect(collections[0]._model._sunLighting).toBe(true); + expect(collections[1]._model._sunLighting).toBe(false); + }); + }); + it('picks', function() { return loadCollection({ gltf : boxGltf, diff --git a/Specs/Scene/ModelSpec.js b/Specs/Scene/ModelSpec.js index e9eb234bdadd..ca0e53deecfa 100644 --- a/Specs/Scene/ModelSpec.js +++ b/Specs/Scene/ModelSpec.js @@ -236,6 +236,76 @@ defineSuite([ model.show = false; } + function verifyDoubleSided(model, doubleSided) { + var camera = scene.camera; + var center = Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, new Cartesian3()); + var range = 4.0 * model.boundingSphere.radius; + + camera.lookAt(center, new HeadingPitchRange(0, -CesiumMath.PI_OVER_TWO, range)); + expect(scene).notToRender([0, 0, 0, 255]); + camera.lookAt(center, new HeadingPitchRange(0, CesiumMath.PI_OVER_TWO, range)); + if (doubleSided) { + expect(scene).notToRender([0, 0, 0, 255]); + } else { + expect(scene).toRender([0, 0, 0, 255]); + } + } + + function verifyVertexColors(model) { + model.zoomTo(); + scene.camera.moveUp(0.1); + // Red + scene.camera.moveLeft(0.5); + expect(scene).toRenderAndCall(function(rgba) { + expect(rgba[0]).toBeGreaterThan(10); + expect(rgba[1]).toBeLessThan(10); + expect(rgba[2]).toBeLessThan(10); + }); + // Green + scene.camera.moveRight(0.5); + expect(scene).toRenderAndCall(function(rgba) { + expect(rgba[0]).toBeLessThan(10); + expect(rgba[1]).toBeGreaterThan(20); + expect(rgba[2]).toBeLessThan(10); + }); + // Blue + scene.camera.moveRight(0.5); + expect(scene).toRenderAndCall(function(rgba) { + expect(rgba[0]).toBeLessThan(10); + expect(rgba[1]).toBeLessThan(10); + expect(rgba[2]).toBeGreaterThan(20); + }); + } + + function verifySunLighting(modelUrl) { + return when.all([ + loadModel(boxLambertUrl, {sunLighting : true, cacheKey : modelUrl + '-sunLighting-true'}), + loadModel(boxLambertUrl, {sunLighting : false, cacheKey : modelUrl + '-sunLighting-false'}) + ]).then(function(models) { + var time = JulianDate.fromDate(new Date('January 1, 2014 23:30:00 UTC')); + var renderOptions = { + scene : scene, + time : time + }; + var rgbaLighting; + models[0].show = true; + models[0].zoomTo(); + expect(renderOptions).toRenderAndCall(function(rgba) { + rgbaLighting = rgba; + }); + models[0].show = false; + models[1].show = true; + models[1].zoomTo(); + expect(renderOptions).toRenderAndCall(function(rgbaNoLighting) { + expect(rgbaLighting).not.toEqual([0, 0, 0, 255]); + expect(rgbaNoLighting).not.toEqual([0, 0, 0, 255]); + expect(rgbaLighting).not.toEqual(rgbaNoLighting); + }); + primitives.remove(models[0]); + primitives.remove(models[1]); + }); + } + it('fromGltf throws without options', function() { expect(function() { Model.fromGltf(); @@ -1942,6 +2012,10 @@ defineSuite([ }); }); + it('loads a glTF with KHR_material_common with sunLighting true and false', function() { + return verifySunLighting(boxLambertUrl); + }); + it('loads a glTF with WEB3D_quantized_attributes POSITION and NORMAL', function() { return loadModel(boxQuantizedUrl).then(function(m) { verifyRender(m); @@ -2089,53 +2163,12 @@ defineSuite([ }); }); - function checkDoubleSided(model, doubleSided) { - var camera = scene.camera; - var center = Matrix4.multiplyByPoint(model.modelMatrix, model.boundingSphere.center, new Cartesian3()); - var range = 4.0 * model.boundingSphere.radius; - - camera.lookAt(center, new HeadingPitchRange(0, -CesiumMath.PI_OVER_TWO, range)); - expect(scene).notToRender([0, 0, 0, 255]); - camera.lookAt(center, new HeadingPitchRange(0, CesiumMath.PI_OVER_TWO, range)); - if (doubleSided) { - expect(scene).notToRender([0, 0, 0, 255]); - } else { - expect(scene).toRender([0, 0, 0, 255]); - } - } - - function checkVertexColors(model) { - model.zoomTo(); - scene.camera.moveUp(0.1); - // Red - scene.camera.moveLeft(0.5); - expect(scene).toRenderAndCall(function(rgba) { - expect(rgba[0]).toBeGreaterThan(10); - expect(rgba[1]).toBeLessThan(10); - expect(rgba[2]).toBeLessThan(10); - }); - // Green - scene.camera.moveRight(0.5); - expect(scene).toRenderAndCall(function(rgba) { - expect(rgba[0]).toBeLessThan(10); - expect(rgba[1]).toBeGreaterThan(20); - expect(rgba[2]).toBeLessThan(10); - }); - // Blue - scene.camera.moveRight(0.5); - expect(scene).toRenderAndCall(function(rgba) { - expect(rgba[0]).toBeLessThan(10); - expect(rgba[1]).toBeLessThan(10); - expect(rgba[2]).toBeGreaterThan(20); - }); - } - it('loads a glTF 2.0 with doubleSided set to false', function() { return loadJson(twoSidedPlaneUrl).then(function(gltf) { gltf.materials[0].doubleSided = false; return loadModelJson(gltf).then(function(m) { m.show = true; - checkDoubleSided(m, false); + verifyDoubleSided(m, false); primitives.remove(m); }); }); @@ -2145,7 +2178,7 @@ defineSuite([ it('loads a glTF 2.0 with doubleSided set to true', function() { return loadModel(twoSidedPlaneUrl).then(function(m) { m.show = true; - checkDoubleSided(m, true); + verifyDoubleSided(m, true); primitives.remove(m); }); }); @@ -2153,11 +2186,15 @@ defineSuite([ it('load a glTF 2.0 with vertex colors', function() { return loadModel(vertexColorTestUrl).then(function(m) { m.show = true; - checkVertexColors(m); + verifyVertexColors(m); primitives.remove(m); }); }); + it('loads a glTF 2.0 with sunLighting true and false', function() { + return verifySunLighting(boxPbrUrl); + }); + function testBoxSideColors(m) { var rotateX = Matrix3.fromRotationX(CesiumMath.toRadians(90.0)); var rotateY = Matrix3.fromRotationY(CesiumMath.toRadians(90.0)); diff --git a/Specs/Scene/PointCloud3DTileContentSpec.js b/Specs/Scene/PointCloud3DTileContentSpec.js index 89a368150578..690d82bd4ccf 100644 --- a/Specs/Scene/PointCloud3DTileContentSpec.js +++ b/Specs/Scene/PointCloud3DTileContentSpec.js @@ -6,6 +6,7 @@ defineSuite([ 'Core/defined', 'Core/HeadingPitchRange', 'Core/HeadingPitchRoll', + 'Core/JulianDate', 'Core/Math', 'Core/Matrix4', 'Core/PerspectiveFrustum', @@ -25,6 +26,7 @@ defineSuite([ defined, HeadingPitchRange, HeadingPitchRoll, + JulianDate, CesiumMath, Matrix4, PerspectiveFrustum, @@ -826,6 +828,32 @@ defineSuite([ }); }); + it('sets sunLighting', function() { + return when.all([ + Cesium3DTilesTester.loadTileset(scene, pointCloudNormalsUrl, {sunLighting : true}), + Cesium3DTilesTester.loadTileset(scene, pointCloudNormalsUrl, {sunLighting : false}) + ]).then(function(tilesets) { + var time = JulianDate.fromDate(new Date('January 1, 2014 12:30:00 UTC')); + var renderOptions = { + scene : scene, + time : time + }; + tilesets[0].show = true; + tilesets[1].show = false; + var rgbaLighting; + expect(renderOptions).toRenderAndCall(function(rgba) { + rgbaLighting = rgba; + }); + tilesets[0].show = false; + tilesets[1].show = true; + expect(renderOptions).toRenderAndCall(function(rgbaNoLighting) { + expect(rgbaLighting).not.toEqual([0, 0, 0, 255]); + expect(rgbaNoLighting).not.toEqual([0, 0, 0, 255]); + expect(rgbaLighting).not.toEqual(rgbaNoLighting); + }); + }); + }); + it('destroys', function() { return Cesium3DTilesTester.tileDestroys(scene, pointCloudRGBUrl); });