Expert blueprint for shader programming (visual effects, post-processing, material customization) using Godot's GLSL-like shader language. Covers canvas_item (2D), spatial (3D), uniforms, built-in variables, and performance. Use when implementing custom effects OR stylized rendering. Keywords shader, GLSL, fragment, vertex, canvas_item, spatial, uniform, UV, COLOR, ALBEDO, post-processing.
Use this skill for custom materials, post-processing, and stylized effects.
Focus:
canvas_item shaders for 2Dspatial shaders for 3DShader template with parameter validation and common effect patterns.
Runtime shader uniform animation without AnimationPlayer.
fragment() unless the cost is justified.mix(), step(), or smoothstep() will do.UV without thinking about wrap or clamp behavior.TIME without an explicit speed factor.: source_color when you want an editor color picker.shader_type canvas_item;
void fragment() {
vec4 tex_color = texture(TEXTURE, UV);
COLOR = tex_color * vec4(1.0, 0.5, 0.5, 1.0);
}
Apply to a Sprite2D:
Material -> New ShaderMaterial.Shader -> New Shader.shader_type canvas_item;
uniform float dissolve_amount : hint_range(0.0, 1.0) = 0.0;
uniform sampler2D noise_texture;
void fragment() {
vec4 tex_color = texture(TEXTURE, UV);
float noise = texture(noise_texture, UV).r;
if (noise < dissolve_amount) {
discard;
}
COLOR = tex_color;
}
shader_type canvas_item;
uniform float wave_speed = 2.0;
uniform float wave_amount = 0.05;
void fragment() {
vec2 uv = UV;
uv.x += sin(uv.y * 10.0 + TIME * wave_speed) * wave_amount;
COLOR = texture(TEXTURE, uv);
}
shader_type canvas_item;
uniform vec4 outline_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform float outline_width = 2.0;
void fragment() {
vec4 col = texture(TEXTURE, UV);
vec2 pixel_size = TEXTURE_PIXEL_SIZE * outline_width;
float alpha = col.a;
alpha = max(alpha, texture(TEXTURE, UV + vec2(pixel_size.x, 0.0)).a);
alpha = max(alpha, texture(TEXTURE, UV + vec2(-pixel_size.x, 0.0)).a);
alpha = max(alpha, texture(TEXTURE, UV + vec2(0.0, pixel_size.y)).a);
alpha = max(alpha, texture(TEXTURE, UV + vec2(0.0, -pixel_size.y)).a);
COLOR = mix(outline_color, col, col.a);
COLOR.a = alpha;
}
shader_type spatial;
void fragment() {
ALBEDO = vec3(1.0, 0.0, 0.0);
}
shader_type spatial;
uniform vec3 base_color : source_color = vec3(1.0);
uniform int color_steps = 3;
void light() {
float ndotl = dot(NORMAL, LIGHT);
float stepped = floor(ndotl * float(color_steps)) / float(color_steps);
DIFFUSE_LIGHT = base_color * stepped;
}
shader_type canvas_item;
uniform float vignette_strength = 0.5;
void fragment() {
vec4 color = texture(TEXTURE, UV);
vec2 center = vec2(0.5, 0.5);
float dist = distance(UV, center);
float vignette = 1.0 - dist * vignette_strength;
COLOR = color * vignette;
}
uniform float intensity : hint_range(0.0, 1.0) = 0.5;
uniform vec4 tint_color : source_color = vec4(1.0);
uniform sampler2D noise_texture;
material.set_shader_parameter("intensity", 0.8)
canvas_itemUV: texture coordinatesCOLOR: output colorTEXTURE: current textureTIME: time since startSCREEN_UV: screen coordinatesspatialALBEDO: base colorNORMAL: surface normalROUGHNESS: roughness valueMETALLIC: metallic value// Good: adjustable
uniform float speed = 1.0;
void fragment() {
COLOR.r = sin(TIME * speed);
}
// Avoid hardcoded tuning values unless the effect is fixed by design
void fragment() {
COLOR.r = sin(TIME * 2.5);
}
// Water wave effect.
// Creates horizontal distortion from a sine wave.
uniform float wave_amplitude = 0.02;