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

There are no shadows #1

Open
charliewhitfield opened this issue May 22, 2020 · 13 comments
Open

There are no shadows #1

charliewhitfield opened this issue May 22, 2020 · 13 comments
Labels
bug Something isn't working good first issue Good for newcomers

Comments

@charliewhitfield
Copy link
Member

charliewhitfield commented May 22, 2020

I, Voyager platform
All

I, Voyager version and (if applicable) Godot version
v0.0.6 and master branch; Godot 3.2.1

OS/device
Windows 10 (Chrome for HTML5 platforms)

Issue description:
There are no shadows. There should be.

Steps to reproduce
Visit Saturn. When rings are not edge-on they should cast a shadow on Saturn.
Or visit Jupiter. It should be easy to catch Io's shadow, if it existed. (You can make Io 20x bigger in the moons.tsv table to make that more obvious.)

Minimal project
N/A

Other helpful information
I don't know why we don't have them!
OmniLight.shadow_enabled = true
All of our GeometryInstances (worlds and Saturn's rings) have default cast_shadow = 1.
All of our SpatialMaterials (world & ring textures) have default flags_do_not_receive_shadows = false.

I played around with Light.shadow_bias. According to the tutorial, I ought to be able to create "self-shadow" artifacts by setting that too low. But no, I can't even create shadow artifacts...

@charliewhitfield charliewhitfield transferred this issue from another repository Feb 10, 2021
@charliewhitfield charliewhitfield added bug Something isn't working good first issue Good for newcomers labels Feb 10, 2021
@charliewhitfield charliewhitfield transferred this issue from ivoyager/ivoyager Oct 3, 2023
@AlanTheSane
Copy link

AlanTheSane commented Jul 21, 2024

Did some testing of shadow range in an empty project. It seems the upper limit for shadows cast by an OmniLight is ~10km from the light source before it completely gives out. Regardless the result is already very ugly with artifacting before hitting 10km.

A DirectionalLight could be an option, it isn't a point source so you would have to actively keep it oriented to the selected planet, but shadow cast range between objects is higher and gives a much cleaner result... unfortunately the range between objects tops out at ~1e6m which is still too low for moons. I was hoping the similarity to the camera range issue meant this could also be negated with double floating point precision, but in this case I get identical results on both builds.

As I understand it 64bit floats have a much bigger performance hit on GPUs than they do on CPUs so are rarely used, which is presumably why shadows cant utilize them here, even if you build the rest of the engine with double precision enabled.

A graphics wizard might be able to do some fakery and project a shadow from closer range while keeping everything else at a real planetary scale... Other option being to scale everything down to fit within the shadow cast range.

@charliewhitfield
Copy link
Member Author

Thanks so much for looking into this! FYI, I'm going off-line from the 27th through August 25 (hiking the John Muir Trail where I won't even have cell phone coverage). But I'll try to engage with this and your discussion post over the next couple days...

Just a quick note: We can adjust the scale of the whole sim by changing const METER = 1.0 in a units.gd file. See here for the file used by Planetarium. As noted in the comments there, other artifacts constrain us on that setting, and I have to use very different values in HTML5 export versus Windows export or editor run. (I think it's 1e-10 in the current Web app.) This has varied greatly with different Godot versions too.

I've pondered more extreme trickery with scale, given that the sim uses its own physics so doesn't really care what Godot thinks the distances are.

@AlanTheSane
Copy link

The comments indicate const METER = 1e-3 works fine for windows builds and this is just low enough to get usable shadows from some of Jupiters moons with a DirectionalLight (not Callisto). Double precision allows for lower values without having objects vanish.

directional_shadow_max_distance controls the shadow view distance but by increasing this you are also effectively reducing the shadow resolution. It will quickly turn into a blurry mess if it is more than ~1e9 times the chosen METER scale. Therefore, if
const METER = 1e-6 then use directional_shadow_max_distance = 1000

With this ratio the viewable distance of shadows is locked at 1e9m (Gannymead can just about see its own shadow). Decreasing the scale below 1e-3 (but maintaining the ratio as described above) will allow more distant bodies like Callisto to cast shadows on Jupiter even if you cant actually see the shadow at that range.

I'm not sure if this is the best solution or how any of it translates to HTML5, but here is my test setup:

Directional light is rotated to x=80, y=270. And I disabled the OmniLight during runtime.
image

Io casting a shadow:

image

Shadow close up:

image

@charliewhitfield
Copy link
Member Author

That's awesome! At least we have something to work from now. It won't be too hard to program a directional light that is camera aware (or multiple ones for a multi-star system). I'll do this for the next release for sure.

Just out of curiosity, are you seeing a shadow from Saturn's rings?

I guess we can do some dynamic trickery with directional_shadow_max_distance that is aware of the current view. I see a problem where we won't be able to have good shadows from astronomical objects (eg, rings on Saturn) at the same time the viewer is close-up to small bodies that might have a shadows.

@AlanTheSane
Copy link

Saturns rings are actually completely missing for me on my double precision build (even with default values), I haven't looked into why yet.

If I switch back to a standard build and keep within the limits Saturn casts a shadow on the ring... but no the ring isn't casting its own shadow.

@charliewhitfield
Copy link
Member Author

I wouldn't expect rings.gdshader to be affected. Probably rings.gd is passing some bad data in the double-precision build. It's possible we are exposing a Godot bug that no one else has tested.

Also, I might have broken the rings shadow casting (specifically) in rings.gd code. I was messing around with shadow modes that I don't really understand.

@AlanTheSane
Copy link

AlanTheSane commented Jul 24, 2024

I guess we can do some dynamic trickery with directional_shadow_max_distance that is aware of the current view. I see a problem where we won't be able to have good shadows from astronomical objects (eg, rings on Saturn) at the same time the viewer is close-up to small bodies that might have a shadows.

It seems you can have multiple light sources using different light_cull_mask layers and different shadow settings for each one. I first thought light would just "go through" an object if it wasn't on the same layer as the light source, but while it wont be lit by the light source it still casts a shadow from it.

A planet layer with a dynamically adjusted directional_shadow_max_distance can keep moon shadows crisp regardless of your view distance. Moons might be a bit trickier as it is possible to have multiple in view at the same time at wildly different ranges.

A reasonable scenario could have one nearby moon casting a shadow on the planet, and another on the far side in the planets own shadow. For the far side moon to be properly shadowed its light source must have a high shadow_max_distance, so if you want good shadow detail on the nearby moon you would need to further split them up onto more layers. Splitting every moon onto its own layer would likely be excessive, so if you do want more detail on a nearby moon maybe only split off the moon you currently have selected, while all others share a default moon layer / light source.

Follow a similar pattern for each size class, like a space station / space ship layer. A "default" layer with appropriately high shadow distance, and a "selected" layer for (dynamically adjusted) shadow detail if its needed.

@charliewhitfield
Copy link
Member Author

OK, I think I understand this. So maybe we can get by with two layers: one fixed that handles large "astronomical" objects and one dynamic that handles smaller objects near the camera. We can try that first and see if we need a third intermediate layer.

The scaling artifacts I noted for const METER in units.gd were lighting artifacts. So that makes me think that these won't be limiting after we replace the OmniLight. Is there a conceivable fixed METER setting that will allow shadows at all scales we are talking about, given different light_cull_mask layers?

@AlanTheSane
Copy link

AlanTheSane commented Jul 25, 2024

Kind of... other way round though. I suggest a dynamic light/shadow layer for the planet as you would mostly only ever have 1 body of that size in view at a time. Using the 4 split shadow mode is usable as shown in the screenshots above, but its a bit low resolution for such extreme viewing ranges and would benefit from a dynamically adjusted orthogonal mode rather than using splits.

Dynamic shadow distance is only really useful if you want to keep a single object "in focus", otherwise it can have weird effects on other objects that share the same layer. Using a fixed shadow distance should be the default when you have multiple objects in view, and due to the vast differences in scale you probably want a separate fixed/default layer for each size class of body. A planetary system on its own isn't a very complex scene with lots of geometry, so adding extra light/shadow layers shouldn't be very expensive (testing needed).

You can get away with not splitting the "in focus" moon onto a separate dynamic layer, but while testing some extreme shadow ranges there were artifacts when zoomed in close to a moon that was fully in Jupiters shadow. In this instance the value didn't need to be quite so high and was fine when lowered but if you do need even higher shadow distances for distant moons, or want some detail in the shadows cast on a moon, splitting it off might be necessary.

Shadow artifacting:
image

The scaling artifacts I noted for const METER in units.gd were lighting artifacts.

Oh. I'm sure I tested this on its own and had objects fully vanishing. Tried again now and I get what you describe. Maybe I messed something up.

Is there a conceivable fixed METER setting that will allow shadows at all scales we are talking about,

The limiting factor that I have found is a moon in its planets shadow. If you zoom out beyond the shadow range (hard capped at 1e6 godot units) they suddenly light up. The moon might be so small it has effectively disappeared... but depending on screen resolution it could still be a visible pixel, or several pixels. Decide what range it is acceptable to have the moon suddenly light up and use that as a baseline for the METER scale.

@charliewhitfield
Copy link
Member Author

@AlanTheSane,

By any chance do you want to implement the new directional lights? I'm eager to have other contributors working on I, Voyager so I can finally add "...and contributors" to the (c) notice. I can help with project peculiarities. OK if no -- your troubleshooting and insights have made it possible for me to solve this at last.

@AlanTheSane
Copy link

I managed to follow much of the logic of how things tie together while I was poking around, but... I have no experience of contributing actual code, I am extremely slow working on even my own stuff, and am deep in my own rabbit hole right now.

I could get over the first issue, but the other two combined will keep me busy for the foreseeable future.

@charliewhitfield
Copy link
Member Author

No problem at all! I need to spend a couple weeks on my game project... then I'll tackle this issue once an for all. I'll definitely be back here to ask questions as I go.

@charliewhitfield
Copy link
Member Author

charliewhitfield commented Jan 7, 2025

Waiting for Godot 4.4 official (or at least beta) before tackling this. If I understand the dev notes correctly, they are adding shadow masking separate from light masking (see here), which might change how I go about fixing this issue. (And I'm always hopeful that some Godot update will magically solve our shadows issue without scale hacks on our part.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants