SuperAPI AI Directory

shader-basics

Design & creation

View repository

Updated 10-15 22:40

About this skill

Shaders in Godot 4.3+

All examples target Godot 4.3+ with no deprecated APIs.

Related skills: animation-system for shader-driven effects like hit flash, godot-optimization for shader performance considerations, camera-system for post-processing camera effects, 2d-essentials for 2D lighting, pixel-art shaders, and CanvasTexture normal maps, 3d-essentials for spatial shaders and environment materials, particles-vfx for custom particle shaders, tween-animation for animating shader parameters at runtime.


1. Core Concepts

Shader Types

Shader Type Applied To Use For
canvas_item 2D nodes (Sprite2D, Control, etc.) 2D effects — outlines, dissolve, color swap
spatial 3D meshes (MeshInstance3D) 3D materials — water, terrain, toon shading
particles GPUParticles2D/3D Custom particle behavior
sky WorldEnvironment Procedural sky rendering
fog FogVolume Volumetric fog effects

Shader vs ShaderMaterial

Shader (.gdshader)        → The code (GLSL-like language)
ShaderMaterial            → Instance of a shader with specific uniform values
CanvasItemMaterial / StandardMaterial3D → Built-in materials (no code needed)

Multiple nodes can share the same Shader but have different ShaderMaterial instances with different uniform values (e.g., same dissolve shader but different dissolve progress per enemy).

Creating a Shader

  1. Select a node (e.g., Sprite2D)
  2. In Inspector → Material → New ShaderMaterial
  3. On the ShaderMaterial → Shader → New Shader
  4. Edit the .gdshader file in the built-in editor

Or create a .gdshader file directly in the FileSystem dock.


2. Godot Shader Language Basics

Godot uses a GLSL ES 3.0-like language with Godot-specific additions.

Minimal Canvas Item Shader

shader_type canvas_item;

void fragment() {
    // COLOR is the output pixel color
    // TEXTURE is the sprite's texture
    // UV is the texture coordinate (0,0 top-left to 1,1 bottom-right)
    vec4 tex = texture(TEXTURE, UV);
    COLOR = tex;
}

Minimal Spatial Shader

shader_type spatial;

void fragment() {
    // ALBEDO is the base color (vec3)
    ALBEDO = vec3(0.8, 0.2, 0.2);
}

Built-in Variables (canvas_item)

Variable Type Description
UV vec2 Texture coordinates
COLOR vec4 Output color (set this in fragment())
TEXTURE sampler2D The node's texture
VERTEX vec2 Vertex position (in vertex())
TIME float Elapsed time in seconds
SCREEN_UV vec2 Screen-space UV (for screen effects)

SCREEN_TEXTURE was removed in Godot 4.0. To read the screen, declare a uniform: uniform sampler2D screen_texture : hint_screen_texture, filter_linear_mipmap;

Built-in Variables (spatial)

Variable Type Description
ALBEDO vec3 Base surface color
METALLIC float Metallic value (0.0–1.0)
ROUGHNESS float Roughness value (0.0–1.0)
NORMAL vec3 Surface normal (for normal mapping)
EMISSION vec3 Emissive color
ALPHA float Transparency (enable in render mode)
VERTEX vec3 Vertex position (in vertex())

Uniforms (Shader Parameters)

Uniforms expose shader values to the Inspector and code.

shader_type canvas_item;

uniform float speed : hint_range(0.0, 10.0, 0.1) = 1.0;
uniform vec4 tint_color : source_color = vec4(1.0, 1.0, 1.0, 1.0);
uniform sampler2D noise_texture : filter_linear_mipmap;

void fragment() {
    vec4 tex = texture(TEXTURE, UV);
    COLOR = tex * tint_color;
}

Common Uniform Hints

Hint Type Description
hint_range(min, max, step) float/int Slider in Inspector
source_color vec4 Color picker in Inspector
filter_linear_mipmap sampler2D Texture filtering mode
repeat_enable sampler2D Allow texture tiling
hint_normal sampler2D Treat as normal map

Setting Uniforms from Code

GDScript

var mat: ShaderMaterial = $Sprite2D.material
mat.set_shader_parameter("speed", 2.0)
mat.set_shader_parameter("tint_color", Color.RED)

C#

var mat = GetNode<Sprite2D>("Sprite2D").Material as ShaderMaterial;
mat.SetShaderParameter("speed", 2.0f);
mat.SetShaderParameter("tint_color", Colors.Red);

3. Common 2D Shader Recipes

The canvas_item recipes most projects need: dissolve (noise + edge glow), outline (sample neighbors, expand alpha), flash-white (uniform-driven hit effect), color swap (palette shift), scrolling UV (water/lava/clouds), wave distortion.

See references/2d-shader-recipes.md for complete shader code for all six recipes.


4. Common 3D Shader Recipes

Spatial-shader recipes: toon/cel shading (banded NdotL), rim lighting / Fresnel (1 - NdotV), simple water surface (UV scroll + normal-map blend + Fresnel).

See references/3d-shader-recipes.md for the full shader source for each recipe.


5. Visual Shaders

Visual shaders provide a node-based graph editor — no code required.

When to Use Visual Shaders

Use Visual Shaders When Use Code Shaders When
Prototyping effects quickly Complex math or branching logic
Artists need to tweak values Need precise control over every line
Learning shader concepts Performance-critical shaders
Simple effects (color adjust, UV scroll) Loops or advanced techniques

Creating a Visual Shader

  1. Select node → Inspector → Material → New ShaderMaterial
  2. Shader → New VisualShader
  3. Click the shader to open the Visual Shader editor
  4. Add nodes from the palette, connect pins
  5. Output nodes (Output, FragmentOutput) are pre-placed

Key Visual Shader Nodes

Node Purpose
Texture2D Sample a texture
ColorConstant Solid color value
VectorOp Math operations on vectors
ScalarOp Math operations on floats
Mix Lerp between two values
Step / SmoothStep Threshold / smooth threshold
Time Current time (for animation)
UV Texture coordinates
Input (custom) Expose a uniform to Inspector

Visual shaders compile to the same GPU code as written shaders. There is no performance difference.

Godot 4.7+: Two new spatial Input nodes — in_shadow_pass (vertex/fragment; maps to the IN_SHADOW_PASS built-in, true when the shader is being rendered in a shadow mapping pass — render objects differently in shadow maps than in the regular pass) and specular_amount (light(); maps to SPECULAR_AMOUNT — 2.0 × light_specular for OmniLight3D/SpotLight3D, 1.0 for DirectionalLight3D).

⚠️ Changed in Godot 4.7: The LinearToSRGB visual shader node no longer clamps its output to [0.0, 1.0] when using the Forward+ or Mobile renderer — HDR values above 1.0 now pass through. Graphs that relied on the implicit clamp produce different output; add an explicit Clamp node to restore the old behavior. See the 4.7 migration guide.


6. Post-Processing Effects

The standard pattern: full-rect ColorRect with a canvas_item shader on top of the gameplay canvas. For 3D, use a WorldEnvironment Adjustment, Glow, or custom shader. For chained effects, render the world to a SubViewport then sample its texture in a final shader pass.

See references/post-processing.md for the ColorRect overlay pattern, vignette + CRT/scanline shader source, the SubViewport pipeline, and WorldEnvironment 3D post-processing notes.


7. Compositor Effects (Godot 4.3+)

CompositorEffect runs custom render passes within Godot's render pipeline (post-tonemap or pre-tonemap). Use when ColorRect overlays aren't enough — multi-pass effects, depth-aware effects, custom AO/SSR variants. Heavier setup than a screen-space shader; reach for it only when needed.

See references/compositor-effects.md for setup, a custom CompositorEffect GDScript example, and built-in Compositor use cases.


8. Render Modes

Render modes go on the first line after shader_type and control how the shader interacts with the rendering pipeline.

Canvas Item Render Modes

shader_type canvas_item;
render_mode unshaded;           // Ignore all lighting
render_mode light_only;         // Only visible where lit
render_mode blend_add;          // Additive blending (glow, fire)
render_mode blend_mix;          // Standard alpha blending (default)
render_mode blend_premul_alpha; // Pre-multiplied alpha

Spatial Render Modes

shader_type spatial;
render_mode unshaded;              // No lighting calculations
render_mode cull_disabled;         // Render both sides of faces
render_mode depth_draw_always;     // Always write to depth buffer
render_mode specular_toon;         // Toon specular model
render_mode diffuse_toon;          // Toon diffuse model
render_mode blend_add;             // Additive blending

9. Stencil Buffer Effects (Godot 4.5+)

Godot 4.5 exposes stencil write/read in spatial shaders via the stencil_mode statement (stencil_mode write, 1; / stencil_mode read, compare_equal, 1;) and on StandardMaterial3D (Stencil: Outline / X-Ray / Custom), across all rendering backends. canvas_item shaders have no stencil modes. Enables portals, X-ray vision, outline masks, and holes-in-geometry effects that previously required compositor-level work.

See references/stencil-buffer.md for the stencil_mode reference and the X-ray vision portal worked example.


10. SMAA Antialiasing (Godot 4.5+)

Sub-pixel Morphological Antialiasing (SMAA 1x) is a built-in post-processing AA mode added in Godot 4.5. It produces clearer results than FXAA at a slightly higher performance cost, and is much cheaper than MSAA.

Enabling SMAA

  1. Open Project Settings
  2. Navigate to Rendering → Anti Aliasing → Quality
  3. Set Screen Space AA to SMAA

SMAA can be combined with MSAA (for geometry edge aliasing) or used standalone. It does not require any shader code changes.

AA Mode Sharpness GPU cost Ghosting
Disabled N/A None None
FXAA Low (blurry) Very low Low
SMAA High Low (slightly above FXAA) Very low
TAA Medium (slight blur) Medium Possible
MSAA 4x High High None

When to use SMAA: Prefer SMAA over FXAA for most desktop projects — it delivers noticeably sharper text and thin edges for a slightly higher cost. Combine SMAA + MSAA 2x for best quality at moderate cost.

The project setting is read at startup only. To switch at runtime set get_viewport().screen_space_aa = Viewport.SCREEN_SPACE_AA_SMAA (C#: GetViewport().ScreenSpaceAA = Viewport.ScreenSpaceAAEnum.Smaa). Forward+ and Mobile only — not Compatibility.


11. Shader Baker — Export-time Pre-compilation (Godot 4.5+)

The Shader Baker converts project shaders to the target driver's format at export time, which shortens first-launch load — most on macOS/iOS (Metal) and Windows (D3D12), where that conversion is slow. It does not remove pipeline-compilation stutter the first time a material renders, works only on the Forward+ and Mobile renderers, and bakes only for drivers the exporting machine's OS supports. Enable it per export preset for release builds; leave it off for development.

See references/shader-baker.md for enabling steps and the with/without comparison.


12. Common Pitfalls

Symptom Cause Fix
Shader has no visible effect Material not assigned or shader not saved Check node's Material property in Inspector
Transparent parts render as black Alpha not handled in shader Set COLOR.a = tex.a; and use appropriate blend mode
Uniform doesn't appear in Inspector Typo in uniform name or wrong type Re-save the shader; check for compilation errors
Texture appears stretched/tiled Missing repeat_enable or wrong UV scale Add repeat_enable hint to sampler2D uniform
Shader works in editor but not in game Screen texture uniform needs backbuffer Use hint_screen_texture on a sampler2D uniform (Godot 4.x)
Performance drops with many shaders Each unique shader = draw call break Share ShaderMaterial instances; use uniforms for variation
Screen-space UV is wrong SCREEN_UV not available in some contexts Ensure the node is rendered in the correct viewport
Visual shader node missing Node was renamed or removed in newer Godot version Check Godot docs for the current node name

⚠️ Changed in Godot 4.7: textureQueryLod() is available only in the fragment shader, and Godot 4.7 enforces this with a compile error — shaders calling it from vertex() stop compiling after upgrading. Move the call into fragment(). See GH-118962.


13. Implementation Checklist

  • Shader type matches the node type (canvas_item for 2D, spatial for 3D)
  • Uniforms use appropriate hints (hint_range, source_color, filter_linear_mipmap)
  • Shared visual effects use the same Shader resource with separate ShaderMaterial instances
  • Post-processing shaders are on a CanvasLayer (2D) or WorldEnvironment (3D), not on game objects
  • TEXTURE is sampled in canvas_item shaders (otherwise sprite content is lost)
  • Alpha-transparent shaders set COLOR.a correctly and use blend_mix render mode
  • Animated shader parameters (dissolve, flash) are driven by Tweens or AnimationPlayer, not _process
  • Screen-reading shaders use hint_screen_texture on a sampler2D uniform (Godot 4.x approach)
  • Complex shaders are profiled with the Godot profiler to check GPU frame time
  • Stencil effects use two-pass materials (write pass first, read pass second) with correct render priority (Godot 4.5+)
  • SMAA is preferred over FXAA for desktop builds (sharper edges, slightly higher cost) — set in Project Settings → Rendering → Anti Aliasing (Godot 4.5+)
  • Shader Baker is enabled in release presets for D3D12 and Metal targets to shorten first-launch load (Forward+/Mobile only; Godot 4.5+)