Open EnlightenedOne opened 8 months ago
Here is a side by side comparison modifying a Light shader with the shadows sampling code exposed:
if (LIGHT_IS_DIRECTIONAL) { attenuation = ATTENUATION; }
if (LIGHT_IS_DIRECTIONAL) { attenuation = sample_directional_shadow(LIGHT_INDEX, verty + vec3(normal_uv.x, 0.0, normal_uv.y)); }
I am going to raise a PR on this if only to get a feel for the feasibility of having the changes merged. The LIGHT_INDEX is exposed conditionally on all compute_light flows for the light shader and is cheap and cheerful to add with no cost if not used. The biggest impact is a fairly sensible reshuffle of the scene_forward_lights_inc.glsl so its easier to tap into stuff in the light shader.
I'm not sure why the specular of the directional light is visible through the shadow on your example (with the default shader). Logically, it should not be visible. Does it happen if the water material is fully opaque?
It is the Light's Shadow Opacity, if its reduced at all from 1.00 then you get specular leaking in.
Here is a still with the shadow opacity at 1, this clears specular but in many lighting conditions the shadows can be harsh:
For reference in the gif above it is set at 0.75 opacity.
Describe the project you are working on
I am working on a tutorial sample game that serves as both a collation of all my shaders and also a testament to what is feasible with Vanilla Godot. My goal is to run it on a Steam Deck.
I really want to stress that my goal is to not recompile the engine as part of this challenge. No rule against merging fixes into vanilla along the way. The question is what can be done by the hobbyist who doesn't want to drift from the core engine? I think Godot is fantastic so far but the inbuilt lighting (whilst pretty) is inflexible and without recompiling Godot stylisation is limited.
Describe the problem or limitation you are having in your project
Here is a screenshot showing a flat water surface with vertex displacement only from the reflection and the specular channel of the shadow to colour the shadow in red on the water surface (just to highlight it, all vanilla Godot 4.2):
Now compare the shadow to the planar reflection with fragment noise added (diffuse_lambert, specular_schlick_ggx):
Note the significant improvement breaking up the edges of shapes in the reflection texture brings. What I want is to apply the similar treatment to the shadow map in realtime.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
I want to displace the sampling of the Directional Light's PSSM Shadow texture in the spatial light function to break up shadows and create a parallax effect on the surface of water.
Essentially this link details a proof of how I would approach the issue https://medium.com/@ShaderError/godot-custom-shader-built-ins-functions-part-2-3-4a1772c12dfe:
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
A minimum viable product for this is to add a light id passthrough and move the directional shadow logic into a reusable function that can be called from the light fragment as a built in method as specified in the custom shader guide. The link here described the proposed changes necessary to the engine https://medium.com/@ShaderError/godot-custom-shader-built-ins-functions-part-2-3-4a1772c12dfe if there is any interest I am happy to roll a PR for this. I appreciate the lighting is strict for a reason, lightest touch, smallest overhead is the goal.
I think long term exposing more lighting functions so they are reachable from the spatial light function greatly enhances the core offering of Godot and enables easier stylisation.
Once devs can access shadow data from the light fragment they can:
If this enhancement will not be used often, can it be worked around with a few lines of script?
No workaround exists.
Is there a reason why this should be core and not an add-on in the asset library?
Adding inbuilt functions to sample and reuse stages of glsl pipeline is core. It might potentially be useful as a starting point for moving the inbuilt light calculations into a more reusable space and allowing users to tap into the built in light functions.