godot
godot copied to clipboard
Add `LIGHT_VERTEX` to fragment shader
Supersedes #90881
See also https://github.com/godotengine/godot-proposals/issues/1942 , #65307 , #90115
After a good discussion in the weekly rendering meeting with @clayjohn and @BastiaanOlij the consensus was that adding a new variable for the position to use for lighting calculations was the best way to solve this class of problems.
Reconstructing the vertex from the depth buffer might not always be what the user wants, is slightly incorrect in the multi-view case, and is redundant when the shader likely already has that value available.
Making the VERTEX variable writable was considered, however there was concern user's would think writing this would change the visual appearance of the fragment.
Tested on OSX / Vulkan with the reproduction project posted in #90881 with LIGHT_VERTEX = (VIEW_MATRIX * vec4(world, 1.f)).xyz;
added to the end of the shader's fragment function.
Needs a rebase to pass CI
Thanks! And congrats for your first merged Godot contribution :tada:
Technically, I've worked on it a lot in the previous PR. But never mind...
Technically, I've worked on it a lot in the previous PR. But never mind...
That's right. You did great work in https://github.com/godotengine/godot/pull/65307 and did a good job at highlighting why this feature is needed. Ultimately we didn't go with your proposed solution, but we appreciate the work you did nonetheless!
Can I ask if this new variable will effect both real time light calculations and lightmap sampling?
Can I ask if this new variable will effect both real time light calculations and lightmap sampling?
Kind of. Lightmap sampling is mostly driven by UV2
. But when using lightmaps, the specular reflection takes VERTEX into account and LIGHT_VERTEX will impact that
Kind of. Lightmap sampling is mostly driven by
UV2
. But when using lightmaps, the specular reflection takes VERTEX into account and LIGHT_VERTEX will impact that
That's a real shame. I'm not using any specular at all. But I would like to snap the lightmap samples to the nearest texel.
Kind of. Lightmap sampling is mostly driven by
UV2
. But when using lightmaps, the specular reflection takes VERTEX into account and LIGHT_VERTEX will impact thatThat's a real shame. I'm not using any specular at all. But I would like to snap the lightmap samples to the nearest texel.
Maybe I don't understand what you trying to do, but I think this is possible. (One of the cool things unlocked by allowing LIGHT_VERTEX to fully be written instead of just using depth).
Here in the bottom object I align the LIGHT_VERTEX to the voxel grid. Here's the same scene without:
These renderings look familiar. Maybe this is a good time to make my Godot Voxel plugin compatible with LIGHT_VERTEX
, it should not be hard. Even if I've already pretty much given up on my voxel game. Maybe I should not, the time of voxel games should come soon as most GPUs will become strong enough.
This is a real time light shadow where I am modifying the VERTEX value in the fragment shader to snap it to the nearest voxel.
This baked green light is in the same scene, this baked shadow does not snap to the nearst voxel. I have tried to modify the UV2 variable in the fragment shader, but any attempt to do so causes the editor to crash instantly.
I was hoping this update to Godot might help me.
Indeed, LightmapGI seems to be not affected by the vertex changes. Might be intentional/not implemented.
Also I'm playing around with per-texel lighting, snapping the VERTEX built-in to the nearest texel.
So I'm running into an ugly artifact that affects my lights.
The artifact with spotlights, above an usually dense texel grid for pixelated textures:
Exaggerated issue with an omnilight, with a large texel, you can see how it runs along the light max distance/edge, and bends around the view space grid:
Animated:
This issue I'm not sure where it comes from, someone said that it might be related to the rendered being tiled based, but I'm using Forward+ in this case. If necessary I'll open an issue to track this, but I want to be sure this is not something done wrong at my end.
@DaniloSF you are pushing the vertex outside the boundary of the light.
Indeed the issue stems from the nature of a clustered renderer. You are moving the light vertex outside of the clusters that contain that omnilight so the impact of the light flickers in and out.
We will probably need to add some documentation about this. As this exact issue is part of the reason why we didn't expose this feature until now.
@DaniloSF You could try fudging the ATTENUATION in your shader's light() function. If this is happening only on the very edge of the light's influance, you could make the light range a little longer, and then bring down the ATTENUATION near the edge.
Something like this maybe: float atten = max(ATTENUATION * 1.1 - 0.1, 0.0);
Then use atten instead of ATTENUATION to multiply the result later.
Let me know if this helps, I'd be interested.
@clayjohn A mention in the docs would be good I agree, maybe in internal rendering architecture, or an additional Note in fragments built ins.
@zomby138 Attenuation didn't help in this case, the light calculation is being skipped by the clusters not being in range, I eventually found the cluster view and yeah, the issue is clear to me now lol
If I had one way to increase the cluster range just to test it it would be cool, I'm digging through the source code to find the omnilight cluster range definition atm