A light sensor node (detecting when a pixel is black or not / below a certain threshold)

Godot Version 4.2.1


Hello people !

I work on a 2d game where lights and shadows play an important part. Many objects in the game need to be activated only when standing in light (visible by the player). However, lights and shadows change dynamically, and I regularly need to change the state of each object based on its visibility state.

What I’m looking for is some sort of light sensor node, which sends signals whenever a precise pixel passes a certain threshold. In more simple words, I need to know when a pixel is almost black (or not). Each of these pixels representing clickable objects in a scene, so I need many of these light sensors.

I’ve looked into shaders and screen-reading, but it all seems rather inefficient. Do any of you know a way of building this kind of light sensor node ?

Thanks for any response !

Screen texture shader reading is the obvious choice, as the number of lights and materials etc need to be combined into the final rendered screen texture in order to determine the brightness value of an individual pixel. But I’m unsure how you would get that value back from the GPU to the CPU.

One possible alternative approach is to design a node that you attach as a child of each light that applies the same calculations, including falloff, and then instead of it actually being a light it just reports this calculated value to a ‘compositing’ system/node that sits at a higher level (perhaps an Autoload). This ‘compositing’ system could then combine the results of all lights and report the total value of a coordinate (pixel). The trick here is to not run that calculation on every pixel, but to ‘request’ a coordinate as needed and have the ‘compositor’ manager call a request, passing the coordinate, to all lights with this special light node.

But before you do that, try and think of an even simpler method like a special collider that you adjust the shape to the boundary/falloff of the light to represent the threshold where the value you are looking for is ‘almost black’. Then you could check if a coordinate is within this collider somehow.

Something like this has definitely been done before, so do some more searching, and especially look for games with a light/torch mechanic like this and see if you can find their devlog for ideas.

1 Like

I’ll try your Autoload idea (after searching for other devlogs as you suggested) ! I might even combine it with your colliders idea …

Hi, I think this would depend on how the light is generated. I am new to godot, so apologies if this is not possible, but I wonder if you could handle this with a boolean?

Logically, the light must be some kind of object, or I guess a node or scene in godot terms. So it would follow that you could attach a script to the light itself with a boolean that checks the current brightness. If this boolean is true, it would then trigger a function on the object you want to activate.

Alternatively, assuming that light spreads evenly in all directions, you could check the distance between the object and the player, and use a raycast to check if there is something between them that would block the light. If the object is close enough to the player that it would be illuminated, and nothing is blocking the light, then the object must be illuminated, so it can be activated.

finally, I went for an easier solution, as you prescribed : when the lights change, they update the status of the objects to enable/disable. I have to apply this system case by case, but it’s simple and efficient.
Thanks !

PS : If you find this topic and are interested in solving this problem for 3d, check out this : https://www.youtube.com/watch?v=3Z8hTdD79To

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.