Force terrain shadow (from 3d object) regardless of time of day

1. A concise explanation of the problem you're experiencing.

I have a case where I always want to cast a shadow from a 3d model, regardless of time of day. I've searched quite extensively (and probably spent about 4-5 hours trying to debug/find a workaround. The closest I've come is!topic/cesium-dev/q5G3jBLqtJQ suggesting to hack the Cesium JS source code, but that is from 2016 and the source code has changed significantly since.

I've tried:
- All shadow configurations I could think of
- Setting the camera in any way I could think of

Unfortunately I rely on the date and time for the timeline, so I can't hard code the time to when the sun is up at that point.

2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

Specifically, I want this to cast a shadow:

var viewer = new Cesium.Viewer('cesiumContainer', {
    infoBox: false,
    selectionIndicator: false,
    shadows: true,
    terrainShadows: Cesium.ShadowMode.ENABLED,
    shouldAnimate: true,
    terrainProvider: Cesium.createWorldTerrain()

var cesiumAir = viewer.entities.add({
    name : 'Cesium Air',
    height : 20.0,
    model : {
        uri : '../../../../Apps/SampleData/models/CesiumAir/Cesium_Air.glb'

var entity = cesiumAir;

entity.position = Cesium.Cartesian3.fromRadians(1.81503, 0.02356,30);
viewer.clock.currentTime = Cesium.JulianDate.fromIso8601('2018-11-20T17:33:29Z');
viewer.clock.multiplier = 1.0;
viewer.trackedEntity = cesiumAir;

3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

Shadow is a good way of intuitively indicating how far away an object is from the ground (and at what point in time the object touches the ground). My backup solution is to change color of the model or something like that, but it's quite an ugly hack :slight_smile:

Unfortunately I rely on the date and time for the timeline, so I can't hard code the time to when the sun is up at that point.

Any help would be greatly appreciated. Thank you so much for Cesium!

4. The Cesium version you're using, your operating system and browser.

Latest Cesium, Latest Chrome, OS X.

Here is a 2018 version of the hacky solution:

  1. Go to Source/Renderer/UniformState.js
  2. Find the setSunAndMoonDirections function.
  3. Print out the sun direction by putting a console.log(uniformState._sunDirectionWC); in there. Run your app, put the sun where you want it, then check the console to see what the vector is, copy it.
  4. Hardcode that position in, so instead of:
    var position = Simon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame(frameState.time, uniformState._sunPositionWC);

Matrix3.multiplyByVector(transformMatrix, position, position);

Cartesian3.normalize(position, uniformState._sunDirectionWC);


My hack looks like:

var position = Simon1994PlanetaryPositions.computeSunPositionInEarthInertialFrame(frameState.time, uniformState._sunPositionWC);

//Matrix3.multiplyByVector(transformMatrix, position, position);

position = new Cartesian3(0.31181546034703517, 0.8715375694318716, -0.3784090164852737);

Cartesian3.normalize(position, uniformState._sunDirectionWC);


And that should fix the sun position for everything while still letting you use the timeline.

If you need multiple models to have different sun positions, it’s possible, but it’ll be slightly more involved. I think you’d have to insert a check before rendering the object to see if it should have a “custom sun position”.

I hope this helps!

Thank you Omar! This is a great learning experience for me :slight_smile: