To achieve consistent tile appearance in CesiumJS, you must disable the default dynamic lighting by setting
scene.globe.enableLighting to false. This prevents shadows and sun angles from altering how terrain and imagery tiles look as the camera zooms or rotates. By relying on pre-shaded assets or uniform ambient illumination, you ensure that visual consistency is maintained across all viewing distances without complex shader modifications.
Understanding the Lighting Problem
When working with 3D Tiles or terrain meshes in CesiumJS, the engine applies a physically based rendering (PBR) lighting model by default. This model calculates how light interacts with surfaces based on their normal maps and material properties. While this creates realistic visuals, it introduces significant inconsistency when users zoom in and out. As the camera moves, the angle of incidence for the virtual sun changes relative to the viewer. This causes tiles to appear darker or lighter depending on their orientation to the light source, breaking the visual continuity of the map.
For applications requiring stable UI elements or specific aesthetic standards, such as architectural visualization or GIS dashboards, this dynamic behavior is often undesirable. The goal is to decouple the visual appearance of the tiles from the real-time lighting calculations. Instead of relying on the engine's automatic shadow casting and specular highlights, we want a flat, predictable illumination that remains constant regardless of the camera's position or the time of day simulated in the scene.
Disabling Dynamic Globe Lighting
The most effective way to stabilize the appearance of your globe is to turn off the global lighting effect. Cesium provides a straightforward property on the globe entity to control this behavior. By disabling lighting, you force the renderer to use a simple, unlit shading model. This eliminates shadows and ensures that every tile is rendered with its base color intact, providing a uniform look across the entire viewport.
You can implement this change directly during the initialization of your viewer. Locate the constructor options where you define your scene settings. Set the
enableLighting property within the globe configuration to
false. This single line of code removes the computational overhead of lighting calculations and guarantees that the visual output remains static relative to lighting conditions.
const viewer = new Cesium.Viewer('cesiumContainer', {
// Other configuration options...
globe: {
enableLighting: false
}
});
This approach is widely recommended for performance optimization as well. Lighting calculations require additional passes through the GPU pipeline. Disabling them reduces the load on the graphics card, which can lead to smoother frame rates, especially on mobile devices or lower-end hardware. It also simplifies debugging because you no longer have to account for shadow artifacts or inconsistent brightness levels when testing your application's visual fidelity.
Handling Terrain and Imagery Consistency
Even with global lighting disabled, you may notice variations in appearance due to the inherent properties of the data sources themselves. Terrain meshes often come with normal maps designed to enhance depth perception under directional light. When lighting is turned off, these normal maps might still influence the final color if the material system is not configured correctly. In many cases, the default terrain material will fall back to a diffuse-only shading mode, which ignores normal maps entirely.
If you are using custom imagery layers, ensure that the images themselves are evenly lit. Photorealistic textures captured at different times of day will still show contrast differences even in an unlit environment. For the best results, use orthorectified imagery that has been processed to remove atmospheric haze and lighting gradients. This preprocessing step complements the software-side solution by ensuring the input data is visually homogeneous before it ever reaches the renderer.
For advanced scenarios where you need subtle depth cues without full lighting, consider implementing a custom fragment shader. This allows you to inject a fixed ambient term into the lighting equation. However, for most standard use cases, simply disabling the globe's lighting property is sufficient and far easier to maintain. It avoids the complexity of writing GLSL code while achieving the primary goal of visual stability.
Optimizing Performance and Visuals
Disabling lighting does not just improve consistency; it also streamlines the rendering pipeline. Without the need to calculate light vectors, shadow maps, or specular reflections, the browser can process geometry more efficiently. This is particularly beneficial when loading large quantities of 3D Tiles. The reduction in GPU stress can prevent stuttering during rapid camera movements or when navigating dense urban environments.
Additionally, this setup makes your application less dependent on the user's local time or geographic location. Since the lighting is static, the map looks identical whether the user is accessing it at noon or midnight. This predictability is crucial for professional tools where accurate representation is valued over artistic realism. You can focus your development efforts on other aspects of the user experience, knowing that the visual baseline is stable and reliable.
Frequently Asked Questions
Does disabling lighting affect shadow rendering?
Yes, turning off
enableLighting completely removes all shadow calculations from the globe. Shadows are generated by the interaction between light sources and geometry, so without active lighting, no shadows will be cast. This is ideal for flat, consistent views but unsuitable for applications requiring depth cues from shadows.
Can I keep lighting for some objects but not others?
The
enableLighting property applies globally to the globe entity. To have mixed lighting effects, you would need to separate your content into different layers or use custom shaders for specific entities. However, there is no built-in toggle to selectively disable lighting for only the terrain while keeping it for other overlays.
Will this change impact my application's performance?
Generally, yes. Disabling lighting reduces the number of rendering passes required per frame. This lowers the demand on the GPU, leading to improved frame rates and reduced battery consumption on mobile devices. It is a recommended practice for high-performance web-based mapping applications.
How do I restore the default lighting behavior?
To revert to the default dynamic lighting, set
enableLighting back to
true in your globe configuration. Note that this change typically requires re-initializing the viewer or reloading the page to take effect properly, as some internal states are cached during the initial setup.
Is this approach compatible with all CesiumJS versions?
The
globe.enableLighting property has been a standard feature in CesiumJS for many years and is supported in current stable releases. It is part of the core API, so you do not need any experimental flags or additional modules to use it. Always check the documentation for your specific version if you are maintaining legacy code.