/makepad-2.0-shaders
CRITICAL: Use for Makepad 2.0 shader system. Triggers on: makepad shader, Sdf2d, pixel shader, draw_bg, draw_text, draw_quad, makepad gpu, shader function, pixel fn, vertex fn, instance, uniform, shader variable, sdf, premultiply, Pal.premul, GaussShadow, makepad graphics,
$ npx -y skills add ZhangHanDong/makepad-skills --skill makepad-2.0-shaders --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/makepad-2.0-shaders
Context preview
The summary Claude sees to decide when to auto-load this skill.
CRITICAL: Use for Makepad 2.0 shader system. Triggers on: makepad shader, Sdf2d, pixel shader, draw_bg, draw_text, draw_quad, makepad gpu, shader function, pixel fn, vertex fn, instance, uniform, shader variable, sdf, premultiply, Pal.premul, GaussShadow, makepad graphics,
SKILL.md
makepad-2.0-shaders.SKILL.mdname: makepad-2.0-shaders
description: |
CRITICAL: Use for Makepad 2.0 shader system. Triggers on:
makepad shader, Sdf2d, pixel shader, draw_bg, draw_text, draw_quad,
makepad gpu, shader function, pixel fn, vertex fn, instance, uniform,
shader variable, sdf, premultiply, Pal.premul, GaussShadow,
makepad graphics, custom draw, DrawQuad, DrawVector,
着色器, 像素, 渲染, 自定义绘制, 距离场
Makepad 2.0 Shader Skill
> **Version:** makepad-widgets (dev branch) | **Last Updated:** 2026-03-03
Overview
Makepad uses a custom GPU shader system integrated into the widget property tree. Shaders are defined inline using `pixel: fn() { ... }` and `vertex: fn() { ... }` blocks within `draw_bg`, `draw_text`, or custom draw objects.
Documentation
Refer to the local files for detailed documentation:
- `./references/shader-reference.md` - Shader syntax, variables, built-ins, custom functions
- `./references/sdf2d-reference.md` - SDF2D primitives, combinators, drawing operations
---
Shader Basics
Pixel Shader Structure
draw_bg +: {
// Declare variables
instance hover: 0.0 // Animatable per-instance
uniform accent: #4488ff // Shared across all instances
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
// ... SDF operations ...
return sdf.result
}
}Variable Types
| Type | Declaration | Animatable | Scope | |------|-------------|-----------|-------| | `instance` | `instance hover: 0.0` | Yes (via Animator) | Per-widget instance | | `uniform` | `uniform color: #fff` | No | Shared across instances | | `texture_2d` | `texture_2d tex: none` | No | Texture sampler | | `varying` | `varying uv: vec2` | No | Vertex → fragment |
Built-in Variables
| Variable | Type | Description | |----------|------|-------------| | `self.pos` | `vec2` | Normalized position (0.0 to 1.0) | | `self.rect_size` | `vec2` | Widget size in pixels | | `self.dpi_factor` | `float` | Screen DPI factor | | `self.draw_pass.time` | `float` | Time in seconds |
---
CRITICAL: Premultiply Alpha
**Every pixel shader MUST return premultiplied alpha color!**
// WRONG - non-premultiplied
pixel: fn() {
return vec4(1.0, 0.0, 0.0, 0.5)
}
// CORRECT - use Pal.premul()
pixel: fn() {
return Pal.premul(vec4(1.0, 0.0, 0.0, 0.5))
}
// ALSO CORRECT - sdf.result is already premultiplied
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
sdf.circle(cx, cy, r)
sdf.fill(#f00)
return sdf.result
}---
SDF2D Quick Reference
Setup
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
Primitives
sdf.circle(cx, cy, radius)
sdf.rect(x, y, w, h)
sdf.box(x, y, w, h, border_radius)
sdf.hexagon(cx, cy, radius)
sdf.arc(cx, cy, radius, start_angle, end_angle, thickness)
sdf.move_to(x, y)
sdf.line_to(x, y)
sdf.close_path()
Drawing
sdf.fill(color) // Filled shape
sdf.stroke(color, width) // Outlined shape
sdf.glow(color, amount) // Glow effect
sdf.clear(color) // Clear with color
Combinators
sdf.union() // Add shapes together
sdf.intersect() // Keep overlap only
sdf.subtract() // Remove second from first
sdf.gloop(radius) // Smooth union
sdf.blend(amount) // Linear blend
Transforms
sdf.translate(x, y)
sdf.rotate(angle, cx, cy)
sdf.scale(factor, cx, cy)
---
Color Operations
// Mix two colors
mix(#f00, #00f, 0.5) // 50% blend
// Premultiply alpha
Pal.premul(vec4(r, g, b, a))
// HSV conversions
Pal.hsv2rgb(vec4(h, s, v, 1.0))
Pal.rgb2hsv(color)
// Random
Math.random_2d(vec2(x, y))
---
Common Shader Patterns
Gradient Background
draw_bg +: {
pixel: fn() {
let grad = mix(#1a1a2e, #16213e, self.pos.y)
return Pal.premul(vec4(grad.xyz, 1.0))
}
}Hover Color Change
draw_bg +: {
instance hover: 0.0
color: #333
pixel: fn() {
return Pal.premul(mix(self.color, self.color * 1.3, self.hover))
}
}Box Shadow
draw_bg +: {
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
// Shadow
sdf.box(2.0, 2.0, self.rect_size.x - 4.0, self.rect_size.y - 4.0, 8.0)
sdf.fill(GaussShadow.box_shadow(sdf, 4.0, #0005))
// Card
sdf.box(0.0, 0.0, self.rect_size.x - 2.0, self.rect_size.y - 2.0, 8.0)
sdf.fill(#2a2a3d)
return sdf.result
}
}Rounded Button with States
draw_bg +: {
instance hover: 0.0
instance down: 0.0
uniform color_bg: #4488ff
uniform color_hover: #5599ff
uniform color_down: #3377ee
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
sdf.box(0.0, 0.0, self.rect_size.x, self.rect_size.y, 6.0)
let color = mix(self.color_bg, self.color_hover, self.hover)
let color = mix(color, self.color_down, self.down)
sdf.fill(color)
return sdf.result
}
}---
Custom Shader Functions
draw_bg +: {
fn wave(pos: vec2, time: float) -> float {
return sin(pos.x * 10.0 + time * 3.0) * 0.1
}
pixel: fn() {
let w = self.wave(self.pos, self.draw_pass.time)
let color = mix(#1a1a2e, #4488ff, self.pos.y + w)
return Pal.premul(vec4(color.xyz, 1.0))
}
}---
Splash Shader Capability Boundary
**Splash CAN:**
- Override `pixel: fn()`, `vertex: fn()`, `get_color: fn()` on existing draw types via `+:`
- Define helper shader functions within `+:` blocks
- Set instance/uniform variables on existing draw types
- Use all SDF2D, color, math built-ins in shader functions
**Splash CANNOT:**
- Create new DrawQuad/DrawText/DrawSvg types (must define in Rust)
- Add new instance fields to existing shaders (GPU layout is compile-time)
**Rule:** Rust defines the draw type struct + registers it; Splash overrides how it draws.
See `./references/shader-reference.md` "Splash Shader Capabilities & Boundaries" for the fu
Read more
name: makepad-2.0-shaders description: | CRITICAL: Use for Makepad 2.0 shader system. Triggers on: makepad shader, Sdf2d, pixel shader, draw_bg, draw_text, draw_quad, makepad gpu, shader function, pixel fn, vertex fn, instance, uniform, shader variable, sdf, premultiply, Pal.premul, GaussShadow, makepad graphics, custom draw, DrawQuad, DrawVector, 着色器, 像素, 渲染, 自定义绘制, 距离场
Makepad 2.0 Shader Skill
> **Version:** makepad-widgets (dev branch) | **Last Updated:** 2026-03-03
Overview
Makepad uses a custom GPU shader system integrated into the widget property tree. Shaders are defined inline using `pixel: fn() { ... }` and `vertex: fn() { ... }` blocks within `draw_bg`, `draw_text`, or custom draw objects.
Documentation
Refer to the local files for detailed documentation:
- `./references/shader-reference.md` - Shader syntax, variables, built-ins, custom functions
- `./references/sdf2d-reference.md` - SDF2D primitives, combinators, drawing operations
---
Shader Basics
Pixel Shader Structure
draw_bg +: {
// Declare variables
instance hover: 0.0 // Animatable per-instance
uniform accent: #4488ff // Shared across all instances
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
// ... SDF operations ...
return sdf.result
}
}Variable Types
| Type | Declaration | Animatable | Scope | |------|-------------|-----------|-------| | `instance` | `instance hover: 0.0` | Yes (via Animator) | Per-widget instance | | `uniform` | `uniform color: #fff` | No | Shared across instances | | `texture_2d` | `texture_2d tex: none` | No | Texture sampler | | `varying` | `varying uv: vec2` | No | Vertex → fragment |
Built-in Variables
| Variable | Type | Description | |----------|------|-------------| | `self.pos` | `vec2` | Normalized position (0.0 to 1.0) | | `self.rect_size` | `vec2` | Widget size in pixels | | `self.dpi_factor` | `float` | Screen DPI factor | | `self.draw_pass.time` | `float` | Time in seconds |
---
CRITICAL: Premultiply Alpha
**Every pixel shader MUST return premultiplied alpha color!**
// WRONG - non-premultiplied
pixel: fn() {
return vec4(1.0, 0.0, 0.0, 0.5)
}
// CORRECT - use Pal.premul()
pixel: fn() {
return Pal.premul(vec4(1.0, 0.0, 0.0, 0.5))
}
// ALSO CORRECT - sdf.result is already premultiplied
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
sdf.circle(cx, cy, r)
sdf.fill(#f00)
return sdf.result
}---
SDF2D Quick Reference
Setup
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
Primitives
sdf.circle(cx, cy, radius) sdf.rect(x, y, w, h) sdf.box(x, y, w, h, border_radius) sdf.hexagon(cx, cy, radius) sdf.arc(cx, cy, radius, start_angle, end_angle, thickness) sdf.move_to(x, y) sdf.line_to(x, y) sdf.close_path()
Drawing
sdf.fill(color) // Filled shape sdf.stroke(color, width) // Outlined shape sdf.glow(color, amount) // Glow effect sdf.clear(color) // Clear with color
Combinators
sdf.union() // Add shapes together sdf.intersect() // Keep overlap only sdf.subtract() // Remove second from first sdf.gloop(radius) // Smooth union sdf.blend(amount) // Linear blend
Transforms
sdf.translate(x, y) sdf.rotate(angle, cx, cy) sdf.scale(factor, cx, cy)
---
Color Operations
// Mix two colors mix(#f00, #00f, 0.5) // 50% blend // Premultiply alpha Pal.premul(vec4(r, g, b, a)) // HSV conversions Pal.hsv2rgb(vec4(h, s, v, 1.0)) Pal.rgb2hsv(color) // Random Math.random_2d(vec2(x, y))
---
Common Shader Patterns
Gradient Background
draw_bg +: {
pixel: fn() {
let grad = mix(#1a1a2e, #16213e, self.pos.y)
return Pal.premul(vec4(grad.xyz, 1.0))
}
}Hover Color Change
draw_bg +: {
instance hover: 0.0
color: #333
pixel: fn() {
return Pal.premul(mix(self.color, self.color * 1.3, self.hover))
}
}Box Shadow
draw_bg +: {
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
// Shadow
sdf.box(2.0, 2.0, self.rect_size.x - 4.0, self.rect_size.y - 4.0, 8.0)
sdf.fill(GaussShadow.box_shadow(sdf, 4.0, #0005))
// Card
sdf.box(0.0, 0.0, self.rect_size.x - 2.0, self.rect_size.y - 2.0, 8.0)
sdf.fill(#2a2a3d)
return sdf.result
}
}Rounded Button with States
draw_bg +: {
instance hover: 0.0
instance down: 0.0
uniform color_bg: #4488ff
uniform color_hover: #5599ff
uniform color_down: #3377ee
pixel: fn() {
let sdf = Sdf2d.viewport(self.pos * self.rect_size)
sdf.box(0.0, 0.0, self.rect_size.x, self.rect_size.y, 6.0)
let color = mix(self.color_bg, self.color_hover, self.hover)
let color = mix(color, self.color_down, self.down)
sdf.fill(color)
return sdf.result
}
}---
Custom Shader Functions
draw_bg +: {
fn wave(pos: vec2, time: float) -> float {
return sin(pos.x * 10.0 + time * 3.0) * 0.1
}
pixel: fn() {
let w = self.wave(self.pos, self.draw_pass.time)
let color = mix(#1a1a2e, #4488ff, self.pos.y + w)
return Pal.premul(vec4(color.xyz, 1.0))
}
}---
Splash Shader Capability Boundary
**Splash CAN:**
- Override `pixel: fn()`, `vertex: fn()`, `get_color: fn()` on existing draw types via `+:`
- Define helper shader functions within `+:` blocks
- Set instance/uniform variables on existing draw types
- Use all SDF2D, color, math built-ins in shader functions
**Splash CANNOT:**
- Create new DrawQuad/DrawText/DrawSvg types (must define in Rust)
- Add new instance fields to existing shaders (GPU layout is compile-time)
**Rule:** Rust defines the draw type struct + registers it; Splash overrides how it draws.
See `./references/shader-reference.md` "Splash Shader Capabilities & Boundaries" for the fu
Skills for building cross-platform UI applications with Makepad 2.0.
Other skills on makepad-skills.
- /makepad-2.0-animation
CRITICAL: Use for Makepad 2.0 animation system. Triggers on: makepad animation, makepad animator, Animator, AnimatorState, hover effect, makepad transition, animation state, Forward, Snap, Loop, ease function, makepad animate, timeline, snap(), default @off, animation group, 动画,
Open skill - /makepad-2.0-app-structure
CRITICAL: Use for Makepad 2.0 app structure and Rust integration. Triggers on: makepad app, makepad getting started, app_main!, App::run, MatchEvent, AppMain, handle_event, handle_actions, ScriptVm, from_script_mod, makepad boilerplate, makepad new project, makepad cargo,
Open skill - /makepad-2.0-design-judgment
CRITICAL: Entry-level skill for Makepad 2.0 GUI development. This is the FIRST skill to load for any Makepad task — it provides design judgment anchors ABOVE the other 13 Makepad 2.0 skills. Triggers on: makepad, makepad app, makepad project, makepad design, live_design!,
Open skill - /makepad-2.0-dsl
CRITICAL: Use for Makepad 2.0 DSL syntax and property system. Triggers on: makepad dsl, script_mod!, makepad syntax, makepad property, makepad 2.0 syntax, colon syntax, merge operator, named instance, let binding, mod.widgets, register_widget, script_component, type_default,
Open skill - /makepad-2.0-events
CRITICAL: Use for Makepad 2.0 event and action handling. Triggers on: makepad event, makepad action, MatchEvent, handle_event, handle_actions, on_click, on_render, on_return, on_startup, script_eval!, script_apply_eval!, button clicked, text changed, slider changed, checkbox
Open skill - /makepad-2.0-layout
CRITICAL: Use for Makepad 2.0 layout system. Triggers on: makepad layout, makepad width, makepad height, makepad flex, makepad flow, makepad padding, makepad margin, makepad spacing, makepad align, makepad sizing, Fill, Fit, Inset, Flow.Down, Flow.Right, ScrollXView,
Open skill

