-
-
Notifications
You must be signed in to change notification settings - Fork 18.8k
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
Allow depth-writing shaders to work with shadow maps #65307
Conversation
You can add the conditional by adding a godot/servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.cpp Line 717 in b6d102c
You would just have to add a similar line for the Vulkan Mobile renderer and the GLES3 renderer as well. |
servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if we could just handle this automatically. For example after the user fragment shader code (in pseduocode):
#if FRAG_DEPTH_USED
vertex.z = in_view_space(-gl_FragDepth);
#ifdef USE_MULTIVIEW
view = -normalize(vertex - scene_data.eye_offset[ViewIndex].xyz);
#else
view = -normalize(vertex);
#endif
#endif
I am worried that if people are able to write to VERTEX
they will expect that they can write to it to modify the actual location of the pixel, when instead they are just modifying the position for the purpose of lighting/shadow code.
Additionally, on mobile devices it is very important for shadow code to be able to read directly from input variables rather than local variables as it enables a lot of optimizations. So I want to discourage writing to VERTEX
as much as possible.
servers/rendering/renderer_rd/shaders/scene_forward_clustered.glsl
Outdated
Show resolved
Hide resolved
vertex.z = in_view_space(-gl_FragDepth); It would indeed solve the problem in a compatible way. But performance and precision may not be optimal. Such a fragment shader would likely have the Relevant part of such a user fragment shader: vec3 vertex;
// Comes up with view space vertex position based on the carved out geometry (changes only the depth)
vec4 ndc = PROJECTION_MATRIX * vec4(vertex, 1.0);
DEPTH = ndc.z / ndc.w; We could introduce a new
We would encourage the use of It would also reduce any confusion about how to set The value is Any problems with this approach? |
@clayjohn Implement your suggestion: In actions.usage_defines["DEPTH"] = "#define DEPTH_USED\n"; In #ifdef DEPTH_USED
vec3 ndc = vec3(screen_uv * 2.0 - 1.0, gl_FragDepth);
vec4 view_pos = inv_projection_matrix * vec4(ndc, 1.0);
vertex.z = view_pos.z / view_pos.w;
#ifdef USE_MULTIVIEW
view = -normalize(vertex - scene_data.eye_offset[ViewIndex].xyz);
#else
view = -normalize(vertex);
#endif
#endif The depth calculation is based on the advanced post-processing documentation. Tested with the same good result, but without having to set Also reverted the As you can see it takes a lot of work to calculate the |
Now the PR has both a compatible shadow fix (requires writing the It has not been ported to the mobile Vulkan renderer and the GLES3 driver yet. I will do the porting and the documentation update once we agree about this solution in general. Thank you for reviewing it. Preliminary fragment shader documentation update: +----------------------------------------+--------------------------------------------------------------------------------------------------+
| out float **DEPTH** | Custom depth value (0..1). Consider setting LINEAR_DEPTH instead if that is easier to produce. |
+----------------------------------------+--------------------------------------------------------------------------------------------------+
| out float **LINEAR_DEPTH** | Custom linear depth value. Replaces the Z coordinate in view space for lighting calculations. |
| | Sets DEPTH as well by projecting the updated surface coordinate. Usually has a negative value. |
+----------------------------------------+--------------------------------------------------------------------------------------------------+ |
0730546
to
19c5307
Compare
Do you agree with the above solution? (Compatible fix if only DEPTH is set. Providing LINEAR_DEPTH as an alternative.) If you do agree, then I would go ahead and complete the PR by porting the change to GLES3 and mobile Vulkan. |
I'm not sure I agree, exposing both Ultimately, the only benefit of using Also, there is no point in doing a full matrix multiplication and then immediately throwing out the xy and w components. It is likely more efficient to only do the calculations necessary to calculate the z-channel. That way you can reduce the overhead to as few instructions as possible and maintain a simple API for users. |
I'm a bit unsure if clayjohn's approach might cause floating point precision errors. I'd only be worried about z-fighting between two shaders which had different view matrices but tried to write the same depth value. But I'd rather try @clayjohn's approach of only using (If we're going to bring up performance, the first thing to implement would be this: https://registry.khronos.org/OpenGL/extensions/ARB/ARB_conservative_depth.txt with a |
I have to disagree here. My last VisualShader PR added the Linear Depth node anyway. (I would have added it in my other PR before as well in as a built-in if I knew this workaround.) So currently we have Depth Texture and Linear Depth in Visual Shaders. I do not see why having both DEPTH and Linear Depth can't be there (as long as both are useful). I asked myself before already why this wasn't simplified since I have never encountered a usecase for using a different depth value scale (except for internal uses perhaps). |
Do you agree that not receiving shadow (correctly) in case of depth writing shaders is actually a bug? I think fixing this at least for the DEPTH case should go into Godot 4.0. That would not need the LINEAR_DEPTH, although I would really like to have it for my case to avoid the extra calculations. As a compromise, I suggest restricting this PR to fix the shadow with no change to the shader variables.
Later we can have another PR to rework the depth as mentioned by @lyuma above. That could include a linear depth option.
The compiler's optimizer is expected to take care of such cases, so we can have more readable code closer to the math involved. Sorry if I have been naïve in this regard. I need to read-up on how good GLSL optimizers are these days. |
Yes, I do agree this is a bug and should be fixed for the After that, we can certainly discuss adding |
362e4cd
to
80fb296
Compare
On the other hand, it should be kept in mind that this PR allows improving the quality of some built-in effects such as parallax mapping. This will have a performance cost, so it needs to be disableable in the project settings though (or on a per-material basis with a render mode). The feature could also be disabled by default if we're worried about lowering performance out of the box. I'd recommend running benchmarks to compare the before/after performance with this PR. I suppose SDF rendering shaders will also benefit a lot from this change. The +116/-33 diff from this pull request doesn't seem too large compared to the number of use cases this opens (and the possible quality increase for parallax mapping). |
@viktor-ferenczi I agree with your on your second and third points. The compile times from editing the base shader GLSL are horrendous, the error reporting is broken on windows (I usually have to hack the Changes to the shader system are planned in the 4.x timeline, and some basic improvements may make it in at the end of the 4.0 beta cycle, but serious refactoring of the type you ask will not be in 4.0 With that out of the way, regarding your first point, you are making the claim that this would not work if "this PR would be stripped down". I respectfully disagree.
I believe there is a way to structure this change, so that it can resolve your usecase when I think making a serious effort to try and make this review concise and not affect performance when not |
649df5b
to
9f160ad
Compare
15e28f9
to
dc6a9c9
Compare
dc6a9c9
to
35c6869
Compare
Released the first version of the Voxel plugin today, it works only on Godot 4. Certainly the received shadows and lighting calculations are wrong without this PR being merged. Users are advised by the documentation to make a custom build of Godot to include the changes from the PR branch, but this is far from ideal. Could you please reconsider this PR or an equivalent solution for the 4.1 release? Since voxel rendering is resource intensive, most likely it will only be used on desktop platforms in the short term. Maybe applying this fix only to the Forward+ desktop renderer would work as a temporary solution, accepting that the lighting would be incorrect on mobile if the official Godot build is used. |
Any chance getting this PR reconsidered? (Sorry for the bump.) |
35c6869
to
70e4025
Compare
…s if the fragment shader wrote into DEPTH. Fixes lighting, shadows, projector and decals in case of using a depth writing shader to override the shape of the mesh on a per-fragment basis.
70e4025
to
6ddb888
Compare
We really need to discuss this once we start PR review meetings again. Previously we were unable to reach consensus on whether this was better to include as-is, or if the engine should provide better tools to write custom shaders so that the built in shader doesn't need to support this use-case. Since there was no consensus we can't really move forward until we have a chance to re-discuss it |
Has this been discussed on a PR review meeting? The Voxel plugin is a good use case and test case for this issue. I will rebase the changes to resolve the conflicts. |
Is there still interest on this PR? the changes here provide non-trivial improvements on final render and also allow for alot of flexibility on implementations of new shaders. |
Is there a reason to do this vs. just allowing VERTEX to be writable in the fragment shader? I needed that for doing per texel lighting. That can be done by simply changing |
If the user knows how to set DEPTH correcty, surely they can handle VERTEX, right? Let's not forget that DEPTH is actually gl_FragDepth being exposed to the user, and you SHOULD assume that they know how it works. When the user sets POSITION (gl_Position), you don't automatically adjust VERTEX just so the lighting looks right... Fact is, those variables have nothing to do with lighting! Allow setting of VERTEX and I'll be happy. :) |
There is interest, but the core devs don't seem to care anymore. I gave up TBH, but it would still be nice to see my Voxel plugin working properly with the default Godot build. |
I really hope that this gets approved someday as I currently port my voxel based game, which uses raymarching, from Unity to Godot and need this to get shadows and lighting to work correctly. @viktor-ferenczi really nice work you did there :) |
Thank you. You may find some reusable shader code here for voxel rendering: I got the Magica Voxel import and rendering working during the Godot 4 Beta as a GDExtension. But then the extension logic changed and this PR was not approved on a timely manner, so I ended up not maintaining and publishing that code, unfortunately. If anybody wants it being finished please reach out directly. Thanks. |
My concerns from one year ago have not been addressed: This PR is changing the functioning of shadow biases even in the non- I can only think of two possibilities for this:
Finally, if this change is better justified or simplified / put behind preprocessor flags, it will still need to go through a review meeting as clayjohn noted. |
Ughhh, this is such bullshit. What is it in your PR meetings that made you say "adding this functionality long before the scene shader editing is a bad idea"?! |
@Firepal please keep your feedback constructive, consider the code of conduct The concerns raised haven't been resolved, as far as I can tell, so there's no merging it until that's done, and OP haven't responded or done any changes |
Superseded by #91136. Thanks for the contribution! |
Solution to Proposal-1942
Tested only on Windows with the Vulkan renderer. Please see the test results in my comment on the proposal above.