shader-programming
gamedev-skills/awesome-gamedev-agent-skills
Write portable game shaders—vertex/fragment pipeline, coordinate spaces, UV math, and common effects (dissolve, outline, rim light) in GLSL with HLSL equivalents.
What is shader-programming?
Master cross-engine shader fundamentals: the GPU pipeline, coordinate spaces, UVs, and how to build common 2D/3D effects. Use when writing or reasoning about vertex/fragment shaders, UV transforms, or effects like dissolve, outline, and fresnel rim light. Covers GLSL with HLSL translations; defer to engine-specific syntax and built-ins (Godot, Unity, Unreal) separately.
- Explain the vertex→fragment pipeline and when each stage runs
- Teach coordinate space transforms (model → world → view → clip) and common bugs
- Build animated effects: scrolling textures, dissolve with noise, outlines, fresnel rim light, vignette, color grading
- Translate shader concepts between GLSL and HLSL dialects
- Reason about UVs, normals, and per-pixel operations on the GPU
- Identify performance pitfalls: branching, discard, precision, and coordinate-space mismatches
How to install shader-programming
npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill shader-programmingHow to use shader-programming
- 1.Identify which shader stage (vertex or fragment) your effect belongs in
- 2.Confirm all inputs (normals, view direction, UVs) are in the same coordinate space and normalized
- 3.Write the effect using GLSL patterns (tint, scroll, dissolve, rim light, etc.) from the skill
- 4.Translate to your engine's shader language using the GLSL↔HLSL mapping
- 5.Test on your target hardware (desktop and mobile have different precision and feature support)
Use cases
- Write a dissolve effect that thresholds a noise map and glows the boundary
- Implement scrolling UVs for animated textures in a frame-rate-independent way
- Add fresnel rim lighting to a 3D model to brighten silhouettes
- Debug why a shader looks correct on desktop but breaks on mobile (precision, V-flip)
- Translate a GLSL fragment shader to HLSL for a different engine
- Game developers writing custom shaders in any engine
- Graphics programmers learning portable shader patterns
- Technical artists building visual effects
- Anyone porting shaders between GLSL, HLSL, or game engines
shader-programming FAQ
Use this skill to understand portable concepts (pipeline, coordinate spaces, UV math, common effects). Use engine docs (Godot shaders, Unity ShaderLab, Unreal materials) for exact syntax, built-ins, and screen-reading functions.
Mobile GPUs have lower precision (mediump vs highp), different V-flip conventions, and missing features. Test on target hardware; use adequate precision for coordinates and time values.
Mixing coordinate spaces—e.g., lighting a world-space normal against a view-space light. Pick one space, convert everything into it, and normalize interpolated vectors in the fragment stage.
Prefer `step`, `smoothstep`, `mix`, and `clamp` over branching; GPUs run pixels in lockstep and dislike divergent branches. Reserve `if`/`discard` for cheap early-outs; note that `discard` defeats early-Z on mobile.
Pass a real `time` uniform (seconds) from the engine, not a per-frame accumulator. Multiply by speed and use `fract()` to wrap UVs into 0..1 for tiling.
Full instructions (SKILL.md)
Source of truth, from gamedev-skills/awesome-gamedev-agent-skills.
name: shader-programming description: > Write game shaders from cross-engine fundamentals — the vertex→fragment pipeline, coordinate spaces, UV math, and common 2D/3D effects (tint, UV scroll, dissolve, outline, fresnel rim, vignette) in GLSL with HLSL equivalents. Use when the user mentions shaders, fragment/pixel shader, vertex shader, UV, GLSL, HLSL, or effects like dissolve, outline, or rim light.
Shader programming (cross-engine)
Shaders are small programs that run per vertex and per pixel on the GPU.
The concepts — the pipeline, coordinate spaces, UVs, and how common effects are
built — port across engines; only the language dialect and built-in variable
names change. This skill teaches those portable fundamentals in GLSL with HLSL
equivalents; use godot-shaders (or Unity/Unreal material docs) for the exact
engine syntax and built-ins.
When to use
- Use to understand or write vertex/fragment shaders and to reason about UVs, coordinate spaces, and the GPU pipeline.
- Use to build common effects: tint/recolor, scrolling textures, dissolve, outlines, fresnel/rim light, vignette, color grading.
- Use to translate a shader concept between GLSL and HLSL, or between engines.
When not to use: for an engine's exact shader language and built-ins, use
godot-shaders (Godot shading language) or the engine's material docs. For full
particle VFX systems, see unreal-niagara. For post-process stacks, defer to
the engine's renderer settings.
Core workflow
- Know which stage you're in. The vertex shader transforms each vertex into clip space and passes data (UVs, normals) onward; the fragment/pixel shader runs per rasterized pixel and outputs a color. Most game effects live in the fragment stage.
- Track coordinate spaces. Positions move model → world → view → clip space; normals belong in world or view space. Mixing spaces is the most common bug.
- Drive effects with UVs and time. UVs are
0..1texture coordinates; offset, scale, or distort them, and animate with atimeuniform. - Work per pixel, branch-light. Prefer
mix,step,smoothstep, andclampoverifwhere possible; GPUs run pixels in lockstep and dislike divergent branches. - Pass data via uniforms (constant per draw) and varyings (interpolated vertex→fragment). Keep texture samples few; they dominate cost.
- Verify visually and on target hardware. Shaders that look right on desktop can break on mobile (precision, missing features). Test where it ships.
Patterns
GLSL-style fragment snippets (close to Godot's canvas_item/spatial
shaders and OpenGL). See references/effects.md for the HLSL equivalents and
the full outline/fresnel/vignette shaders.
1. Fragment basics: sample, tint, and combine
// Per-pixel: read the texture at this UV, multiply by a color (tint), keep alpha.
uniform sampler2D tex;
uniform vec4 tint; // e.g. (1,0,0,1) reddens; multiply is non-destructive
in vec2 uv; // interpolated 0..1 texture coordinate (a "varying")
out vec4 frag;
void main() {
vec4 c = texture(tex, uv); // HLSL: tex.Sample(samp, uv)
frag = c * tint; // component-wise multiply tints without clipping
}
2. Scrolling UVs (animated texture) — frame-rate independent
// Add time * speed to the UV to scroll. fract() wraps it into 0..1 so it tiles.
uniform sampler2D tex;
uniform float time; // seconds, supplied by the engine
uniform vec2 scroll_speed; // UV units per second, e.g. (0.1, 0.0)
in vec2 uv;
out vec4 frag;
void main() {
vec2 scrolled = fract(uv + scroll_speed * time); // HLSL: frac(...)
frag = texture(tex, scrolled);
}
// Drive with a real time uniform, not a per-frame accumulator, so speed is stable.
3. Dissolve (threshold a noise map, glow the edge)
// Hide pixels where noise < threshold; tint a thin band at the boundary.
uniform sampler2D tex;
uniform sampler2D noise_tex; // grayscale noise, 0..1
uniform float amount; // 0 = fully visible, 1 = fully dissolved
uniform float edge = 0.05; // width of the glowing edge band
uniform vec4 edge_color;
in vec2 uv;
out vec4 frag;
void main() {
vec4 c = texture(tex, uv);
float n = texture(noise_tex, uv).r;
if (n < amount) discard; // cut away dissolved pixels
float e = smoothstep(amount, amount + edge, n); // 0 at the edge -> 1 inside
frag = mix(edge_color, c, e); // HLSL: lerp(edge_color, c, e)
}
4. Fresnel rim light (3D) — brighten glancing angles
// Rim = 1 where the surface faces away from the camera (silhouette glow).
in vec3 world_normal; // normalized, world space (from the vertex stage)
in vec3 view_dir; // normalized, surface -> camera, world space
uniform float power = 3.0;
uniform vec3 rim_color;
out vec4 frag;
void main() {
float f = pow(1.0 - clamp(dot(world_normal, view_dir), 0.0, 1.0), power);
frag = vec4(rim_color * f, 1.0); // add to lighting; f peaks at the silhouette
}
// Correctness: normal and view_dir MUST be in the same space and normalized.
Pitfalls
- Mixing coordinate spaces (lighting a world-space normal against a view-space light) yields subtly wrong shading. Pick one space and convert everything into it.
- Forgetting to normalize interpolated normals/directions: interpolation
shortens vectors, so
dot()results drift.normalize()in the fragment stage. - UV assumptions across engines. Some engines flip V (top-left vs bottom-left origin); a texture may appear upside-down. Know your engine's convention.
- Heavy branching / dynamic loops stall GPUs. Prefer
step/smoothstep/mix; reserveif/discardfor genuinely cheap early-outs. discarddefeats early-Z and can hurt performance on tiled mobile GPUs; prefer alpha blending where you can.- Precision on mobile:
highpvsmediumpmatters; large UVs or time values in low precision shimmer. Use adequate precision for coordinates and time. - Assuming GLSL == HLSL.
mix↔lerp,fract↔frac,texture()↔.Sample(),vec2↔float2, column- vs row-major matrices. See the reference mapping.
References
references/effects.md— full outline (2D sprite + 3D), vignette, and color grading shaders; the GLSL↔HLSL function/type mapping table; per-engine notes (Godotcanvas_item/spatial, Unity ShaderLab/HLSL, Unreal material nodes).
Related skills
godot-shaders— Godot shading language syntax, built-ins, and screen-reading.unreal-niagara— GPU particle VFX (a different shader use).procedural-gen— the noise that drives dissolve and procedural texturing.
Related skills
More from gamedev-skills/awesome-gamedev-agent-skills and the wider catalog.

steam-publish
Publish and update games on Steam using Steamworks, SteamPipe, and steamcmd.

survival-crafting
Build survival-crafting games with resource gathering, crafting tech trees, base building, and escalating threats.

threejs-gltf-loading
Load glTF/GLB 3D models and play animations in three.js with GLTFLoader and AnimationMixer.

threejs-materials-lighting
Light and shade three.js scenes with PBR materials, shadows, and environment maps.

threejs-scene-setup
Bootstrap a three.js scene with camera, renderer, animation loop, and OrbitControls.

tower-defense
Build tower defense games with enemy pathing, wave spawning, tower targeting, and economy systems.