Godot Version
4.5.1
Question
I’m trying to create a cell shader in godot but the issue is with the vertex function.
This Youtube Video is about Wind Waker’s cell shading and I’d like to make a similar implementation. The issue is that uses vertex lighting and generally does a lot of lighting calculations based upon vertexes. I’m trying to recreate the style but Godot’s light function calculates per pixel. Is there a way to do lighting calculations in vertex, calculate stuff with vertexes in light, am I stupid and there’s a better way to do this, or I’m screwed?
Add vertex_lighting to render_mode directive in the shader code.
So to confirm that would make it so the Light function would use vertexes or something else?
It’ll use per vertex lighting instead of per pixel lighting wherever per pixel is normally used. light() function may not run if this is enabled.
Yeah, the vertex_lighting render mode did make light not run which leads me to the issue of being unable to turn the vertex lighting into cell shading : ( Also I am a complete beginner to shader stuff so when you say where pixel is used, is that the NORMAL constant that is the current pixel?
If you only have a single (or a few) light source(s) you can disable the lighting completely, send the light position/direction via a uniform and do the lighting calculation in the vertex function.
So what you are saying is have a position that is like the sun position and get a dot product to that as a sample for a shading gradient?
Pretty much. Do the dot product in vertex function, send it to the fragment function, and there posterize the gradient and modulate the albedo with it. You can do per vertex specular/phong that way as well.
You say to send it to the fragment function but how do I do that?
Here’s an example:
shader_type spatial;
render_mode unshaded;
uniform vec4 diffuse: source_color;
uniform vec4 ambient: source_color;
uniform vec3 light_direction;
varying float illumination;
void vertex() {
illumination = dot(MODEL_NORMAL_MATRIX * NORMAL, -normalize(light_direction));
illumination = clamp(illumination, 0.0, 1.0);
}
void fragment() {
ALBEDO = diffuse.rgb * smoothstep(0.2, 0.6, illumination) + ambient.rgb;
}
Thank you so much for helping me through this shader stuff!
1 Like