Notes on the light function

A post for collecting my thoughts on light shaders. I will add more to it in the future

Recieving shadows

As per the docs, the shadow value is multiplied into ATTENUATION. This can be useful for achieving a mostly unshaded look while still supporting shadows

void light () {

Ambient light

Ambient lighting from the Environment can be disabled via render_mode ambient_light_disabled; or IRRADIANCE = vec4(0,0,0,1);. You probably wanted that for stylization purposes, and now everything in shadow will be rendered black. To fix it you need to add some ambient light in it’s place. It would be wise to do this in fragment() instead of light()

void fragment() {
	EMISSION = ALBEDO * vec3(0.1, 0.2, 0.3);


Operating on the final sum

Spatial shaders provide a lot of information about the light sources, but no way to get the final shading value. You may wish to create an effect based upon the final shading of the fragment, not just the individual contribution of each light. The general approach I’ve seen is to do such effects as a post-process, but that limits us to working in screen space. Luckily, it’s pretty easy to subvert the purpose of the output, and process the final shading value in addition to each light. In the example code, I treat DIFFUSE_LIGHT like a spare variable, and only allow SPECULAR_LIGHT to contribute to the final color.


Spatial light built-ins
The default light function source code

Shader code
shader_type spatial;

void light() {
	// light we wish to accumulate

	// assign the result
	SPECULAR_LIGHT = round(DIFFUSE_LIGHT*16.0 - 0.5)/16.0; // posterizes the final color
	//SPECULAR_LIGHT = DIFFUSE_LIGHT; // do nothing to the result

	// cancel all contribution of the diffuse_light variable
The shader code and all code snippets in this post are under MIT license and can be used freely. Images and videos, and assets depicted in those, do not fall under this license. For more info, see our License terms.

More from celyk

Cool 3D text

Particle based trail

Ray-box setup

Related shaders

UCBC’s Stylized Light with Light Masking

Modulate Before Light

2D Rim Light

Notify of

Newest Most Voted
Inline Feedbacks
View all comments
Spam Rakuen
Spam Rakuen
7 months ago

I’ve the same issue explained here. So I’ve modified Godot 4.1 to solve this.

spamrakuen/godot at 4.1MOD (

Spam Rakuen
Spam Rakuen
4 months ago
Reply to  Spam Rakuen

Future Shader Templetes will allow this without any MOD.

Here is a talk of Clay John were its explained

4 months ago

This is immensely helpful, keep ’em coming 🙌