
Shader Dev
Add believable ambient occlusion to raymarched SDF scenes in GLSL without baking lightmaps.
Overview
shader-dev is an agent skill for the Build phase that implements SDF ambient occlusion in GLSL by sampling distance fields along normals during raymarched shading.
Install
npx skills add https://github.com/minimax-ai/skills --skill shader-devWhat is this skill?
- Step-by-step SDF ambient occlusion along surface normals with expected-vs-actual distance sampling
- Weighted multi-sample occlusion factor mapped to a bright-to-dark [0, 1] range
- Finite-difference normals and raymarch intersection assumptions documented for map(p) SDFs
- Supplement reference with math derivations and variant analysis beyond the core SKILL.md
- Prerequisites spell out GLSL uniforms, raymarching loops, and vector math you need first
- Occlusion factor is normalized on a [0, 1] scale (1.0 bright open, 0.0 fully occluded).
- AO uses multiple stepped samples along the surface normal with a weighted sum of contributions.
Adoption & trust: 1.3k installs on skills.sh; 12.5k GitHub stars; 3/3 security scanners passed (skills.sh audits); trending (+100% hot-view momentum).
What problem does it solve?
Your raymarched SDF scenes look flat because corners and contact areas lack cheap, plausible ambient shadowing.
Who is it for?
Indie builders raymarching SDFs in WebGL or custom engines who want corner darkening without lightmap bakes.
Skip if: Teams needing PBR asset pipelines, baked GI, or artists who will not touch GLSL distance fields.
When should I use this skill?
Implementing or tuning SDF ambient occlusion in GLSL raymarch shaders.
What do I get? / Deliverables
You get a documented AO sampling recipe and weighted occlusion factor you can drop into fragment shaders for brighter open areas and darker occluded creases.
- AO sampling function integrated into the fragment shader
- Tuned sample distances and weights for stable crease darkening
Recommended Skills
Journey fit
Shader and SDF lighting work happens while you are implementing visual product surfaces (WebGL demos, game clients, or branded 3D hero sections). Frontend build covers GPU shaders, materials, and in-browser graphics pipelines where GLSL lives.
How it compares
Shader technique reference for SDF raymarching—not a game engine material marketplace asset.
Common Questions / FAQ
Who is shader-dev for?
Solo and indie developers writing GLSL for SDF raymarching who want ambient occlusion without offline baking.
When should I use shader-dev?
During Build when polishing WebGL demos, game prototypes, or 3D landing visuals where SDF shading needs depth in corners and contact lines.
Is shader-dev safe to install?
Review the Security Audits panel on this Prism page and inspect the skill bundle before letting an agent edit shader code in your repo.
SKILL.md
READMESKILL.md - Shader Dev
# SDF Ambient Occlusion — Detailed Reference This document is a detailed supplement to [SKILL.md](SKILL.md), containing a complete step-by-step tutorial, mathematical derivations, variant analysis, and advanced usage. ## Prerequisites - GLSL basic syntax (uniform, varying, function definitions) - **Signed Distance Field (SDF)** concept: `map(p)` returns the distance from point p to the nearest surface - **Raymarching** basic loop: marching along a ray to find surface intersections - **Surface normal computation**: Obtaining the normal direction via SDF gradient (finite differences) - Vector math fundamentals: dot product, normalization, vector addition/subtraction ## Core Principles in Detail The core idea of SDF ambient occlusion: **Sample the SDF at multiple distances along the surface normal and compare the "expected distance" with the "actual distance" to estimate the degree of occlusion.** For a point P on the surface with normal N, at distance h: - **Expected distance** = h (if the surroundings are completely open, the SDF value should equal the distance to the surface) - **Actual distance** = map(P + N × h) (real SDF value) - **Occlusion contribution** = h - map(P + N × h) (the larger the difference, the more nearby geometry is occluding) The final result is a weighted sum of occlusion contributions from multiple sample points, yielding a [0, 1] occlusion factor: - 1.0 = no occlusion (bright) - 0.0 = fully occluded (dark corner) Key mathematical formula (additive accumulation form): ``` AO = 1 - k × Σ(weight_i × max(0, h_i - map(P + N × h_i))) ``` Where `weight_i` typically decays exponentially or geometrically (closer samples have higher weight), and `k` is a global intensity coefficient. ## Implementation Steps in Detail ### Step 1: Build the Base SDF Scene **What**: Define a `map()` function that returns the signed distance value for any point in space. **Why**: AO computation relies entirely on SDF queries, so a working distance field is needed first. ```glsl float map(vec3 p) { float d = p.y; // Ground plane d = min(d, length(p - vec3(0.0, 1.0, 0.0)) - 1.0); // Sphere d = min(d, length(vec2(length(p.xz) - 1.5, p.y - 0.5)) - 0.4); // Torus return d; } ``` ### Step 2: Compute Surface Normal **What**: Compute the normal direction via finite difference approximation of the SDF gradient. **Why**: AO sampling probes outward along the normal direction; the normal determines the sampling direction. ```glsl vec3 calcNormal(vec3 p) { vec2 e = vec2(0.001, 0.0); return normalize(vec3( map(p + e.xyy) - map(p - e.xyy), map(p + e.yxy) - map(p - e.yxy), map(p + e.yyx) - map(p - e.yyx) )); } ``` ### Step 3: Implement Classic Normal-Direction AO (Additive Accumulation) **What**: Sample the SDF at 5 distances along the normal direction, accumulating occlusion. **Why**: This is a classic method — the most concise and efficient SDF-AO implementation. 5 samples strike an excellent balance between quality and performance. The weight decays at 0.95 exponentially, giving closer samples more influence (near-surface occlusion is more perceptually important). ```glsl // Classic AO float calcAO(vec3 pos, vec3 nor) { float occ = 0.0; float sca = 1.0; // Initial weight for (int i = 0; i < 5; i++) { float h = 0.01 + 0.12 * float(i) / 4.0; // Sample distance: 0.01 ~ 0.13 float d = map(pos + h * nor); // Actual SDF distance occ += (h - d) * sca; // Accumulate (expected - actual) × weight sca *= 0.95; // Weight decay } return clamp(1.0 - 3.0 * occ, 0.0, 1.0); } ``` ### Step 4: Apply AO to Lighting **What**: Multiply the AO factor into ambient and indirect light components. **Why**: AO simulates the degree to which indirect light is occluded. Physically, it should only affect ambient/indirect light, not the direct light source's diffuse and specular (direct light