+2 votes

Is it possible to make field of vision like one in game Teleglitch with 2D lights in Godot (or someone has a shader solution)? Specifically to dynamically offset/shift shadows like in video below so you can see part of the occluder:
https://www.youtube.com/watch?v=adz7wJUdqrA
Does anyone know how LightShader (2D) works? I guess that you can somehow change LIGHT_VEC. Any suggestions? Thanks!

in Engine by (243 points)
edited by

Some easy ways to make it, I can think of scaling or apply transformation on the occluder, it seems to work fine with scales.

You can use a central management for all the occluders that move them away from their parents a % of the normalized vector that points to the light source or more precise transform deformations.


This is kind of a node hacky solution, I would like to know how to use light shaders on 2D too.

You can change/transform occluder, but that is gonna mess up things if you want shadows from other lights to function normaly (like lights), but one light to function like a field of vision (and in Teleglich you have "normal" lights and fiels of vision "light"). Documentation mentions possibility of changing shadow computation via
"vec2 LIGHT_VEC Vector from light to fragment, can be modified to alter shadow computation." But i have no idea how to do it.

1 Answer

+2 votes
Best answer

You can get some offset by changing the length of LIGHT_VEC, for example:
LIGHT_VEC = LIGHT_VEC - normalize(LIGHT_VEC) * min(length(LIGHT_VEC, offset);

This looks pretty good when the light is further away from the occluder, but close to an occluder it doesn't give the kind of even offset like in Teleglitch. It might be possible to use the vertex shader somehow to get a more even offset.

To have regular lights and the field-of-view light working together the only solution I found was to have a polygon (identical to the occluder polygon) as a mask on top of the wall graphics node for the field-of-view shadows to be drawn on. You can use the _draw() command in the occluder node to draw the polygon, or you can use a separate Polygon2D node. The color of the mask node should be fully transparent. The mask node and the graphics node should have different light masks that match the lights. I put the graphics node and regular lights on mask 2 and the mask node and field-of-view light on mask 1 (if you want the normal lights to cast shadows you also have to set bit 1 on them). The field-of-view light mode should be either mix or mask. The mask nodes get the light shader:

uniform float offset;
LIGHT_VEC = LIGHT_VEC - normalize(LIGHT_VEC) * min(length(LIGHT_VEC), offset);
SHADOW = vec4(0.0, 0.0, 0.0, 1.0);
LIGHT = vec4(0.0, 0.0, 0.0, 0.0);
by (1,540 points)
selected by

Thanks a lot! I will try to play with LIGHT_VEC, but I guess I have to draw polygons manuly to achive effect I need.

Welcome to Godot Engine Q&A, where you can ask questions and receive answers from other members of the community.

Please make sure to read How to use this Q&A? before posting your first questions.
Social login is currently unavailable. If you've previously logged in with a Facebook or GitHub account, use the I forgot my password link in the login box to set a password for your account. If you still can't access your account, send an email to webmaster@godotengine.org with your username.