diff --git a/CHANGES.md b/CHANGES.md index 9115b1783f55..a328b9eabd67 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -11,6 +11,7 @@ Change Log ##### Additions :tada: * `Resource.fetchImage` now has a `flipY` option to vertically flip an image during fetch & decode. It is only valid when `ImageBitmapOptions` is supported by the browser. [#7579](https://github.com/AnalyticalGraphicsInc/cesium/pull/7579) +* Added `backFaceCulling` and `normalShading` options to `PointCloudShading`. Both options are only applicable for point clouds containing normals. [#7399](https://github.com/AnalyticalGraphicsInc/cesium/pull/7399) ##### Fixes :wrench: * Fixed the value for `BlendFunction.ONE_MINUS_CONSTANT_COLOR`. [#7624](https://github.com/AnalyticalGraphicsInc/cesium/pull/7624) diff --git a/Source/Scene/PointCloud.js b/Source/Scene/PointCloud.js index c297f51138d3..490605e6b775 100644 --- a/Source/Scene/PointCloud.js +++ b/Source/Scene/PointCloud.js @@ -1137,6 +1137,7 @@ define([ } else { vs += ' vec3 normal = a_normal; \n'; } + vs += ' vec3 normalEC = czm_normal * normal; \n'; } else { vs += ' vec3 normal = vec3(1.0); \n'; } @@ -1163,8 +1164,7 @@ define([ vs += ' color = color * u_highlightColor; \n'; if (usesNormals && normalShading) { - vs += ' normal = czm_normal * normal; \n' + - ' float diffuseStrength = czm_getLambertDiffuse(czm_sunDirectionEC, normal); \n' + + vs += ' float diffuseStrength = czm_getLambertDiffuse(czm_sunDirectionEC, normalEC); \n' + ' diffuseStrength = max(diffuseStrength, 0.4); \n' + // Apply some ambient lighting ' color.xyz *= diffuseStrength; \n'; } @@ -1173,7 +1173,7 @@ define([ ' gl_Position = czm_modelViewProjection * vec4(position, 1.0); \n'; if (usesNormals && backFaceCulling) { - vs += ' float visible = step(-normal.z, 0.0); \n' + + vs += ' float visible = step(-normalEC.z, 0.0); \n' + ' gl_Position *= visible; \n' + ' gl_PointSize *= visible; \n'; } diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js index f9cb8caa9855..bfd994b978e3 100644 --- a/Source/Scene/PointCloud3DTileContent.js +++ b/Source/Scene/PointCloud3DTileContent.js @@ -14,6 +14,7 @@ define([ './Cesium3DTileFeature', './Cesium3DTileRefine', './PointCloud', + './PointCloudShading', './SceneMode' ], function( Color, @@ -31,6 +32,7 @@ define([ Cesium3DTileFeature, Cesium3DTileRefine, PointCloud, + PointCloudShading, SceneMode) { 'use strict'; @@ -270,9 +272,11 @@ define([ } }; + var defaultShading = new PointCloudShading(); + PointCloud3DTileContent.prototype.update = function(tileset, frameState) { var pointCloud = this._pointCloud; - var pointCloudShading = tileset.pointCloudShading; + var pointCloudShading = defaultValue(tileset.pointCloudShading, defaultShading); var tile = this._tile; var batchTable = this._batchTable; var mode = frameState.mode; @@ -300,7 +304,6 @@ define([ this._styleDirty = false; pointCloud.clippingPlanesOriginMatrix = tileset.clippingPlanesOriginMatrix; - pointCloud.style = defined(batchTable) ? undefined : tileset.style; pointCloud.styleDirty = styleDirty; pointCloud.modelMatrix = tile.computedTransform; @@ -310,9 +313,11 @@ define([ pointCloud.clippingPlanes = clippingPlanes; pointCloud.isClipped = defined(clippingPlanes) && clippingPlanes.enabled && tile._isClipped; pointCloud.clippingPlanesDirty = tile.clippingPlanesDirty; - pointCloud.attenuation = defined(pointCloudShading) ? pointCloudShading.attenuation : false; + pointCloud.attenuation = pointCloudShading.attenuation; + pointCloud.backFaceCulling = pointCloudShading.backFaceCulling; + pointCloud.normalShading = pointCloudShading.normalShading; pointCloud.geometricError = getGeometricError(this); - pointCloud.geometricErrorScale = defined(pointCloudShading) ? pointCloudShading.geometricErrorScale : 1.0; + pointCloud.geometricErrorScale = pointCloudShading.geometricErrorScale; if (defined(pointCloudShading) && defined(pointCloudShading.maximumAttenuation)) { pointCloud.maximumAttenuation = pointCloudShading.maximumAttenuation; } else if (tile.refine === Cesium3DTileRefine.ADD) { diff --git a/Source/Scene/PointCloudShading.js b/Source/Scene/PointCloudShading.js index f466c038ad8b..ba5baf55c2be 100644 --- a/Source/Scene/PointCloudShading.js +++ b/Source/Scene/PointCloudShading.js @@ -18,6 +18,8 @@ define([ * @param {Boolean} [options.eyeDomeLighting=true] When true, use eye dome lighting when drawing with point attenuation. * @param {Number} [options.eyeDomeLightingStrength=1.0] Increasing this value increases contrast on slopes and edges. * @param {Number} [options.eyeDomeLightingRadius=1.0] Increase the thickness of contours from eye dome lighting. + * @param {Boolean} [options.backFaceCulling=false] Determines whether back-facing points are hidden. This option works only if data has normals included. + * @param {Boolean} [options.normalShading=true] Determines whether a point cloud that contains normals is shaded based on the sun direction. * * @alias PointCloudShading * @constructor @@ -76,6 +78,23 @@ define([ * @default 1.0 */ this.eyeDomeLightingRadius = defaultValue(pointCloudShading.eyeDomeLightingRadius, 1.0); + + /** + * Determines whether back-facing points are hidden. + * This option works only if data has normals included. + * + * @type {Boolean} + * @default false + */ + this.backFaceCulling = defaultValue(pointCloudShading.backFaceCulling, false); + + /** + * Determines whether a point cloud that contains normals is shaded based on the sun direction. + * + * @type {Boolean} + * @default true + */ + this.normalShading = defaultValue(pointCloudShading.normalShading, true); } /** diff --git a/Source/Scene/TimeDynamicPointCloud.js b/Source/Scene/TimeDynamicPointCloud.js index 5ee29f81670f..3add0294640f 100644 --- a/Source/Scene/TimeDynamicPointCloud.js +++ b/Source/Scene/TimeDynamicPointCloud.js @@ -490,7 +490,10 @@ define([ return 10.0; } + var defaultShading = new PointCloudShading(); + function renderFrame(that, frame, updateState, frameState) { + var shading = defaultValue(that.shading, defaultShading); var pointCloud = frame.pointCloud; var transform = defaultValue(frame.transform, Matrix4.IDENTITY); pointCloud.modelMatrix = Matrix4.multiplyTransformation(that.modelMatrix, transform, scratchModelMatrix); @@ -499,14 +502,13 @@ define([ pointCloud.shadows = that.shadows; pointCloud.clippingPlanes = that._clippingPlanes; pointCloud.isClipped = updateState.isClipped; + pointCloud.attenuation = shading.attenuation; + pointCloud.backFaceCulling = shading.backFaceCulling; + pointCloud.normalShading = shading.normalShading; + pointCloud.geometricError = getGeometricError(that, pointCloud); + pointCloud.geometricErrorScale = shading.geometricErrorScale; + pointCloud.maximumAttenuation = getMaximumAttenuation(that); - var shading = that.shading; - if (defined(shading)) { - pointCloud.attenuation = shading.attenuation; - pointCloud.geometricError = getGeometricError(that, pointCloud); - pointCloud.geometricErrorScale = shading.geometricErrorScale; - pointCloud.maximumAttenuation = getMaximumAttenuation(that); - } pointCloud.update(frameState); frame.touchedFrameNumber = frameState.frameNumber; } diff --git a/Specs/Scene/PointCloud3DTileContentSpec.js b/Specs/Scene/PointCloud3DTileContentSpec.js index 4ad043335eea..c41613d0ce8b 100644 --- a/Specs/Scene/PointCloud3DTileContentSpec.js +++ b/Specs/Scene/PointCloud3DTileContentSpec.js @@ -464,7 +464,7 @@ defineSuite([ expect(scene).toPickAndCall(function(result) { // Set culling to true - content._pointCloud.backFaceCulling = true; + tileset.pointCloudShading.backFaceCulling = true; expect(scene).toPickAndCall(function(result) { picked = result; @@ -487,7 +487,7 @@ defineSuite([ } // Set culling to false - content._pointCloud.backFaceCulling = false; + tileset.pointCloudShading.backFaceCulling = false; expect(scene).toPickAndCall(function(result) { picked = result; diff --git a/Specs/Scene/PointCloudShadingSpec.js b/Specs/Scene/PointCloudShadingSpec.js index a08282804630..ffac43d24946 100644 --- a/Specs/Scene/PointCloudShadingSpec.js +++ b/Specs/Scene/PointCloudShadingSpec.js @@ -15,13 +15,17 @@ defineSuite([ expect(pointCloudShading.eyeDomeLighting).toEqual(true); expect(pointCloudShading.eyeDomeLightingStrength).toEqual(1.0); expect(pointCloudShading.eyeDomeLightingRadius).toEqual(1.0); + expect(pointCloudShading.backFaceCulling).toEqual(false); + expect(pointCloudShading.normalShading).toEqual(true); var options = { geometricErrorScale : 2.0, maximumAttenuation : 16, baseResolution : 0.1, eyeDomeLightingStrength : 0.1, - eyeDomeLightingRadius : 2.0 + eyeDomeLightingRadius : 2.0, + backFaceCulling : true, + normalShading : false }; pointCloudShading = new PointCloudShading(options); expect(pointCloudShading.attenuation).toEqual(false); @@ -31,6 +35,8 @@ defineSuite([ expect(pointCloudShading.eyeDomeLighting).toEqual(true); expect(pointCloudShading.eyeDomeLightingStrength).toEqual(options.eyeDomeLightingStrength); expect(pointCloudShading.eyeDomeLightingRadius).toEqual(options.eyeDomeLightingRadius); + expect(pointCloudShading.backFaceCulling).toEqual(options.backFaceCulling); + expect(pointCloudShading.normalShading).toEqual(options.normalShading); }); it('provides a method for checking if point cloud shading is supported', function() {