godot icon indicating copy to clipboard operation
godot copied to clipboard

Add `LIGHT_VERTEX` to fragment shader

Open basicer opened this issue 10 months ago • 2 comments

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.

basicer avatar Apr 25 '24 06:04 basicer

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.

basicer avatar Apr 25 '24 06:04 basicer

Needs a rebase to pass CI

AThousandShips avatar Apr 25 '24 11:04 AThousandShips

Thanks! And congrats for your first merged Godot contribution :tada:

akien-mga avatar Apr 25 '24 15:04 akien-mga

Technically, I've worked on it a lot in the previous PR. But never mind...

viktor-ferenczi avatar Apr 25 '24 17:04 viktor-ferenczi

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!

clayjohn avatar Apr 25 '24 18:04 clayjohn

Can I ask if this new variable will effect both real time light calculations and lightmap sampling?

zomby138 avatar Apr 25 '24 22:04 zomby138

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

clayjohn avatar Apr 26 '24 00:04 clayjohn

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.

zomby138 avatar Apr 26 '24 00:04 zomby138

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.

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).

image

Here in the bottom object I align the LIGHT_VERTEX to the voxel grid. Here's the same scene without:

image

basicer avatar Apr 26 '24 02:04 basicer

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.

viktor-ferenczi avatar Apr 26 '24 03:04 viktor-ferenczi

image

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.

image

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.

zomby138 avatar Apr 26 '24 09:04 zomby138

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: godot windows editor dev x86_64_2024-04-26_16-08-23

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: godot windows editor dev x86_64_2024-04-27_01-28-27

Animated: godot windows editor dev x86_64_2024-04-27_02-06-09

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.

lamenore avatar Apr 28 '24 01:04 lamenore

@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.

clayjohn avatar Apr 28 '24 06:04 clayjohn

@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.

zomby138 avatar Apr 28 '24 10:04 zomby138

@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 godot windows editor dev x86_64_2024-04-28_14-23-43 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

lamenore avatar Apr 28 '24 18:04 lamenore