Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consider adding an unlit mode for 3D Tilesets #7870

Open
OmarShehata opened this issue May 28, 2019 · 9 comments
Open

Consider adding an unlit mode for 3D Tilesets #7870

OmarShehata opened this issue May 28, 2019 · 9 comments

Comments

@OmarShehata
Copy link
Contributor

All 3D models in CesiumJS will use the PBR shader. This works great for models that define PBR materials and/or have metallic/roughness texture etc.

But for simple, untextured geometry, as is common when representing 3D buildings in CityGML, the buildings often blend together and it's hard to discern any boundaries. Below is the default view in the NYC Sandcastle at 9:13 pm.

NYC_default

It looks better if you move the timeline so the sun angle changes, but there's always going to be an angle at which things look washed out this way.

I was playing around with the idea of having an unlit mode, where the building colors are just based on their normals (I think this is why the untextured buildings in Google Maps look nice, plus heavily constraining the camera angle). I added a small modification to the PBR shader to do this, which can be turned on in the tileset constructor:

var tileset = new Cesium.Cesium3DTileset({
    url: '<url>',
    useSimpleLighting: true
});

Here's a few comparison shots of what it looks like:

one

two

three

I think drawing lines around the edges would help a lot, but I'm not sure how easy that is here/if the batched geometry makes it harder. This would be a step towards supporting custom shaders on 3D Tiles (#7652), or perhaps, this use case is a reason to add support for custom shaders on 3D Tiles.

Potentially related to #7803.

@OmarShehata
Copy link
Contributor Author

OmarShehata commented May 28, 2019

Full git diff for the above lighting model, it's just about 4 lines of code in 4 files:

diff --git a/Source/Scene/Batched3DModel3DTileContent.js b/Source/Scene/Batched3DModel3DTileContent.js
index 7429d7cf2c..970345f26b 100644
--- a/Source/Scene/Batched3DModel3DTileContent.js
+++ b/Source/Scene/Batched3DModel3DTileContent.js
@@ -364,6 +364,7 @@ define([
         content._contentModelMatrix = Matrix4.multiply(tile.computedTransform, content._rtcCenterTransform, new Matrix4());
 
         if (!defined(tileset.classificationType)) {
             // PERFORMANCE_IDEA: patch the shader on demand, e.g., the first time show/color changes.
             // The pick shader still needs to be patched.
             content._model = new Model({
@@ -391,6 +392,7 @@ define([
                 sphericalHarmonicCoefficients : tileset.sphericalHarmonicCoefficients,
                 specularEnvironmentMaps : tileset.specularEnvironmentMaps
             });
+            content._model.useSimpleLighting = tileset.useSimpleLighting;
         } else {
             // This transcodes glTF to an internal representation for geometry so we can take advantage of the re-batching of vector data.
             // For a list of limitations on the input glTF, see the documentation for classificationType of Cesium3DTileset.
diff --git a/Source/Scene/Cesium3DTileset.js b/Source/Scene/Cesium3DTileset.js
index 555461ce74..00147d7aa2 100644
--- a/Source/Scene/Cesium3DTileset.js
+++ b/Source/Scene/Cesium3DTileset.js
@@ -217,6 +217,7 @@ define([
         this._updatedVisibilityFrame = 0;
         this._extras = undefined;
         this._credits = undefined;
+        this.useSimpleLighting = options.useSimpleLighting;
 
         this._cullWithChildrenBounds = defaultValue(options.cullWithChildrenBounds, true);
         this._allTilesAdditive = true;
diff --git a/Source/Scene/Model.js b/Source/Scene/Model.js
index 1892df92f7..1395688895 100644
--- a/Source/Scene/Model.js
+++ b/Source/Scene/Model.js
@@ -4453,6 +4453,8 @@ define([
                             addBatchIdToGeneratedShaders: this._addBatchIdToGeneratedShaders
                         };
 
+                        options.useSimpleLighting = this.useSimpleLighting;
+
                         processModelMaterialsCommon(gltf, options);
                         processPbrMaterials(gltf, options);
                     }
diff --git a/Source/Scene/processPbrMaterials.js b/Source/Scene/processPbrMaterials.js
index b9eeb0af8f..b99ce54400 100644
--- a/Source/Scene/processPbrMaterials.js
+++ b/Source/Scene/processPbrMaterials.js
@@ -837,7 +837,13 @@ define([
         } else {
             fragmentShader += '    vec3 color = baseColor;\n';
         }
+        if (options.useSimpleLighting) {
+            fragmentShader += 'float lightingFactor = clamp(abs(dot(normalize(czm_inverseViewRotation * n), normalize(vec3(0.25, 0.2, -0.2)))), 0.001, 1.0);\n';
+            fragmentShader += 'color = vec3(lightingFactor + 0.25);\n';
+        }
+        
         // Ignore occlusion and emissive when unlit
         if (!isUnlit) {
             if (defined(generatedMaterialValues.u_occlusionTexture)) {

An implementation of this would I think just use a separate shader instead of tacking onto the PBR shader.

@OmarShehata
Copy link
Contributor Author

Another situation where unlit makes sense in this forum thread where the timeline is used to advance a dynamic simulation, but the sun's day/night cycle creates an undesirable lighting effect.

@astroschen
Copy link

Very supportive, will this be included in the new version?

@OmarShehata
Copy link
Contributor Author

@astroschen glad to hear it! Is your use case also for untextured 3D buildings or other things?

It's unlikely to make it into the release on Monday but if we can reach consensus on a good approach here it's very likely to make it into the release right after that.

@astroschen
Copy link

ok Thanks @OmarShehata !

@agilliland
Copy link

I would definitely be in support of some improvements to the shading on untextured geometries. My primary use case is to use cesium for buildings and I have noticed this problem on several occasions where the lighting looks very flat and it's hard to distinguish between the different features in the scene.

Anything that would provide a nicer looking default with a bit more contrast would be welcomed.

@OmarShehata
Copy link
Contributor Author

This came up again on the forum. Here the requested solution is to be able to render outlines.

@dzungpng
Copy link
Contributor

dzungpng commented Feb 5, 2021

Rendering outlines is also requested again here on the forum.

@Kennnyoung
Copy link

this feature would be a very nice addon to the existing features, currently in need of this as well

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment