Shaders and Lighting - Greyscale with full-colour circle light
Asked Answered
B

6

0

Hi, I'm building my first game and learning Godot, and I have a question about how to achieve an effect I am after. I have programming experience but no game dev experience.

Goal: I want to create a lighting effect where The whole screen is greyscale, with certain elements (floor and background) visible, and certain elements (trees, etc) not visible. A small circular light that shows every element within the radius in full normal colour, and all elements are visible.

What I currently have - a simple light, which: Video here: https://imgur.com/a/LauX1Gx ( https://imgur.com/a/LauX1Gx embedded doesn't seem to work)

I'm achieving this using an approach similar to: https://github.com/godotengine/godot-demo-projects/tree/master/2d/light2d_as_mask - which uses only a white circle png with a gradient, and Light2d. The floor has CanvasItemMaterial set to Light Only. No shaders etc.

I figure I'm going to need multiple layers, and potentially shaders (which scares me) but I'm struggling to get a start on this - especially how to deal with the overlap between the greyscale background and the full-colour circle.

I'm not sure if it's a Shader Q or something else, so apologies if this is in the wrong place.

Any help would be greatly appreciated!

Thanks! Can put the repo on Github and share if needed.

Birk answered 8/8, 2021 at 19:27 Comment(0)
E
0

See if this isn't the effect you're looking for:

Extrorse answered 8/8, 2021 at 21:55 Comment(0)
B
0

Hey! Thanks so much for this, this looks awesome!2 I think I can probaby combine the two approaches to make what I want! :) Will respond back here if it works.

However, this would only work if I had one light source, right? I assume adding multiple in the shader is bad for both performance and code-quality - are there any ways of achieving this with multiple light sources, that come in and out of the window?

Birk answered 9/8, 2021 at 21:2 Comment(0)
J
0

For the shaders internal logic I would think it's performance is affected by the screen resolution more than anything else. Since it is a screen-space per-pixel shader.

For multiple light sources, if you manage to somehow batch the screen-space locations of multiple/all the lights within view bounds and pass them to the shader in one go I don't think it should be too negative of a performance hit, but how can you do that? Via array perhaps?

Far as I'm aware uniform arrays were slated for 4.0 but aren't implemented yet even there. https://github.com/godotengine/godot-proposals/issues/931 https://github.com/godotengine/godot/pull/49485 <-- Not merged yet.

Jacobinism answered 10/8, 2021 at 4:51 Comment(0)
B
0

Thank you @Megalomaniak ! I'm still playing around with this, and haven't gotten anywhere, but I have found this comment: https://github.com/godotengine/godot/issues/10751#issuecomment-480585584

I suppose it could be possible to pass in an Array of objects (? not just integers), each containing x, y coords and radius size? A script with some glue code, listening out for emitted signals could probably work, but again not sure about performance.

Would it be possible to have a shader check the brightness of a pixel, and determine whether a pixel is affected by the Light2D - if not: apply greyscale, if so then don't apply? I would like to sanity-check ask this before I spend a long time investigating.

Birk answered 11/8, 2021 at 16:10 Comment(0)
B
0

As an update: I found a comment talking about the Canvas Modulate Node - For my use case this simple solution actually works great - it's basically the same as a shader from what I can see. So it seems simpler just to use this for the time being.

https://imgur.com/a/SZswZq9 (I've changed the lantern a little, ignore the pixelation) https://imgur.com/a/SZswZq9

I can easily change the values on the CanvasModulate node programmatically - so I can enter darker or lighter areas of snowy plains.

For things dissapearing outside of view, I can simply use the light_mode property on any background layers I want using light_only on any occluding nodes. https://docs.godotengine.org/en/stable/tutorials/shading/shading_reference/canvas_item_shader.html

The only downside is that the lighting will also be affected - albeit less so than the outside area. However in my case, this asthetic actually works for me.

So I'm really happy. I might come back to this, perhaps as a nice example to learn Shaders (when Array support comes out for uniforms in Shaders) but the value doesn't seem worth the effort right now to fudge it to work.

Thanks all for your help! Amazed at how intuitive Godot it :)

Birk answered 11/8, 2021 at 19:45 Comment(0)
J
0

Yes, for some reason I thought you were aware of alternatives and were specifically looking to use a shader to solve a niche problem or something.

Jacobinism answered 12/8, 2021 at 5:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.