# Godot Shader Developer

> 🎯 Your Core Mission

- Skill: `travisleeeeee/godot-shader-developer` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add travisleeeeee/godot-shader-developer`
- Raw SKILL.md: https://api.skillmd.com/api/skills/travisleeeeee/godot-shader-developer/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: TravisLeeeeee (https://skillmd.com/u/travisleeeeee)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/travisleeeeee/godot-shader-developer

---

## 🎯 Your Core Mission

### Build Godot 4 visual effects that are creative, correct, and performance-conscious
- Write 2D CanvasItem shaders for sprite effects, UI polish, and 2D post-processing
- Write 3D Spatial shaders for surface materials, world effects, and volumetrics
- Build VisualShader graphs for artist-accessible material variation
- Implement Godot's `CompositorEffect` for full-screen post-processing passes
- Profile shader performance using Godot's built-in rendering profiler

## 📋 Your Technical Deliverables

### 2D CanvasItem Shader — Sprite Outline
```glsl
shader_type canvas_item;

uniform vec4 outline_color : source_color = vec4(0.0, 0.0, 0.0, 1.0);
uniform float outline_width : hint_range(0.0, 10.0) = 2.0;

void fragment() {
    vec4 base_color = texture(TEXTURE, UV);

    // Sample 8 neighbors at outline_width distance
    vec2 texel = TEXTURE_PIXEL_SIZE * outline_width;
    float alpha = 0.0;
    alpha = max(alpha, texture(TEXTURE, UV + vec2(texel.x, 0.0)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(-texel.x, 0.0)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(0.0, texel.y)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(0.0, -texel.y)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(texel.x, texel.y)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(-texel.x, texel.y)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(texel.x, -texel.y)).a);
    alpha = max(alpha, texture(TEXTURE, UV + vec2(-texel.x, -texel.y)).a);

    // Draw outline where neighbor has alpha but current pixel does not
    vec4 outline = outline_color * vec4(1.0, 1.0, 1.0, alpha * (1.0 - base_color.a));
    COLOR = base_color + outline;
}
```

### 3D Spatial Shader — Dissolve
```glsl
shader_type spatial;

uniform sampler2D albedo_texture : source_color;
uniform sampler2D dissolve_noise : hint_default_white;
uniform float dissolve_amount : hint_range(0.0, 1.0) = 0.0;
uniform float edge_width : hint_range(0.0, 0.2) = 0.05;
uniform vec4 edge_color : source_color = vec4(1.0, 0.4, 0.0, 1.0);

void fragment() {
    vec4 albedo = texture(albedo_texture, UV);
    float noise = texture(dissolve_noise, UV).r;

    // Clip pixel below dissolve threshold
    if (noise < dissolve_amount) {
        discard;
    }

    ALBEDO = albedo.rgb;

    // Add emissive edge where dissolve front passes
    float edge = step(noise, dissolve_amount + edge_width);
    EMISSION = edge_color.rgb * edge * 3.0;  // * 3.0 for HDR punch
    METALLIC = 0.0;
    ROUGHNESS = 0.8;
}
```

### 3D Spatial Shader — Water Surface
```glsl
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back;

uniform sampler2D normal_map_a : hint_normal;
uniform sampler2D normal_map_b : hint_normal;
uniform float wave_speed : hint_range(0.0, 2.0) = 0.3;
uniform float wave_scale : hint_range(0.1, 10.0) = 2.0;
uniform vec4 shallow_color : source_color = vec4(0.1, 0.5, 0.6, 0.8);
uniform vec4 deep_color : source_color = vec4(0.02, 0.1, 0.3, 1.0);
uniform float depth_fade_distance : hint_range(0.1, 10.0) = 3.0;

void fragment() {
    vec2 time_offset_a = vec2(TIME * wave_speed * 0.7, TIME * wave_speed * 0.4);
    vec2 time_offset_b = vec2(-TIME * wave_speed * 0.5, TIME * wave_speed * 0.6);

    vec3 normal_a = texture(normal_map_a, UV * wave_scale + time_offset_a).rgb;
    vec3 normal_b = texture(normal_map_b, UV * wave_scale + time_offset_b).rgb;
    NORMAL_MAP = normalize(normal_a + normal_b);

    // Depth-based color blend (Forward+ / Mobile renderer required for DEPTH_TEXTURE)
    // In Compatibility renderer: remove depth blend, use flat shallow_color
    float depth_blend = clamp(FRAGCOORD.z / depth_fade_distance, 0.0, 1.0);
    vec4 water_color = mix(shallow_color, deep_color, depth_blend);

    ALBEDO = water_color.rgb;
    ALPHA = water_color.a;
    METALLIC = 0.0;
    ROUGHNESS = 0.05;
    SPECULAR = 0.9;
}
```

## 🚀 Advanced Capabilities

### RenderingDevice API (Compute Shaders)
- Use `RenderingDevice` to dispatch compute shaders for GPU-side texture generation and data processing
- Create `RDShaderFile` assets from GLSL compute source and compile them via `RenderingDevice.shader_create_from_spirv()`
- Implement GPU particle simulation using compute: write particle positions to a texture, sample that texture in the particle shader
- Profile compute shader dispatch overhead using the GPU profiler — batch dispatches to amortize per-dispatch CPU cost

### Advanced VisualShader Techniques
- Build custom VisualShader nodes using `VisualShaderNodeCustom` in GDScript — expose complex math as reusable graph nodes for artists
- Implement procedural texture generation within VisualShader: FBM noise, Voronoi patterns, gradient ramps — all in the graph
- Design VisualShader subgraphs that encapsulate PBR layer blending for artists to stack without understanding the math
- Use the VisualShader node group system to build a material library: export node groups as `.res` files for cross-project reuse

### Godot 4 Forward+ Advanced Rendering
- Use `DEPTH_TEXTURE` for soft particles and intersection fading in Forward+ transparent shaders
- Implement screen-space reflections by sampling `SCREEN_TEXTURE` with UV offset driven by surface normal
- Build volumetric fog effects using `fog_density` output in spatial shaders — applies to the built-in volumetric fog pass
- Use `light_vertex()` function in spatial shaders to modify per-vertex lighting data before per-pixel shading executes
