0 votes

I'm working on a game where 2D Shadows and Field of View cones generated by multiple overlapping "light sources" are a core part of the mechanics and experience. As such, I've been playing around a lot with Light2D objects, LightOccluder2D objects, and all of the various blend modes. I've certainly found some really cool effects and interactions, but I've continually been frustrated trying to get the primary lighting effect I'm looking for.

After some thinking, I've realized that what I really want is a blend mode where the maximum value of any combining light sources is taken as the "blended value", instead of adding them together, or interpolating between them.

I'm still new to Godot, though, and I'm not sure what the easiest/best way to go about doing that might be. Some thoughts I've had might be to: Modify Godot source to add a new blend mode; Do some magic with shaders?; Render something to a separate texture, then use that as the texture for a Light2D node; or, Completely implement my own 2D lighting system using raycasting.

I'm not experienced enough with Godot to know how difficult any of those might be, or even where to start, or if there might be a cleaner solution I haven't considered or am not aware of. So, before going too far down any rabbit holes, I wanted to reach out to the community to see if anyone might be able to point me in a good direction - hopefully maybe even with some resources to dig deeper into?

Godot version Godot v3.3.2 Stable Mono for Win64
in Engine by (15 points)

1 Answer

+1 vote
Best answer

Hi,
i dont think this can be archived with the build in lighting architecture of godot.

Light processor functions work differently in 2D than they do in 3D. In CanvasItem shaders, the shader is called once for the object being drawn, and then once for each light touching that object in the scene.

So ... there is no gl-blend mode GL_MAX for the 2d LIghts. I think your pretty out of luck if you dont want to modify the godot source and compile it yourself.

2D Lighting happens here
https://github.com/godotengine/godot/blob/3.3/drivers/gles/rasterizer_canvas_gles3.cpp
around line 354.

Any other attemp seems to end in very poor performance.

by (3,928 points)
selected by

Got it, so eventually all calls end at glBlendFunc(), and even if I go the route of modifying and compiling source, I'm still mostly limited to what glBlendFunc() can do - short of some serious modification.

Thanks for the link to the spot in source, that actually gives me a lot of insight. I suppose I'll have to think about whether any alternative options for glBlendFunc() will do what I want, or otherwise I'll need to write some scripts and/or shader code to do what I want.

Edit: As follow-up for anyone who may stumble upon this question in the future, there is actually a mode in OpenGL for taking the max (or min) of two textures being blended (as Light2D's do in Godot 3.x). If you go here in source:

For GLES2:
https://github.com/godotengine/godot/blob/3.3/drivers/gles2/rasterizer_canvas_gles2.cpp#L1835
and https://github.com/godotengine/godot/blob/3.3/drivers/gles2/rasterizer_canvas_gles2.cpp#L2228

For GLES3:
https://github.com/godotengine/godot/blob/3.3/drivers/gles3/rasterizer_canvas_gles3.cpp#L364
and https://github.com/godotengine/godot/blob/3.3/drivers/gles3/rasterizer_canvas_gles3.cpp#L1513

You can see where it's making the determination of how to blend. Mostly, it calls these two methods: glBlendEquation(), and glBlendFunc(). I recommend you look up documentation or a video explaining these in better detail, but there are two values you can pass to glBlendEquation() to achieve a max (or min) blending: GL_MAX, and GL_MIN. Here's a link to that documentation for more info:
https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glBlendEquation.xhtml

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.