Install
$ agentstack add skill-nebulavenus-forge-gpu-forge-cascaded-shadow-maps ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Add directional-light cascaded shadow maps (CSM) with 3x3 PCF soft shadows to an SDL3 GPU application. Based on Lesson 15.
When to use
- You need directional light shadows covering a large area
- Single shadow maps lack resolution for your scene
- You want soft shadow edges without expensive techniques
Key API calls
SDL_CreateGPUTexture— shadow map textures (D32FLOAT, DEPTHSTENCIL_TARGET | SAMPLER)SDL_CreateGPUSampler— NEAREST filter, CLAMPTOEDGE for shadow map samplingSDL_CreateGPUGraphicsPipeline— shadow pipeline (depth-only, front-face cull, depth bias)SDL_BeginGPURenderPass/SDL_EndGPURenderPass— one pass per cascade (depth only)SDL_BindGPUFragmentSamplers— bind shadow maps + sampler for scene passSDL_PushGPUVertexUniformData/SDL_PushGPUFragmentUniformData— per-draw uniforms
Correct order
- Create shadow map textures + sampler (in
SDL_AppInit) - Create shadow pipeline — depth-only, front-face culling, depth bias
- Create scene pipeline — binds shadow maps as fragment samplers
- Each frame:
a. Compute cascade split depths (logarithmic-linear blend) b. Compute light VP matrix per cascade (frustum corners → light-space AABB) c. Shadow pass: render all casters into each cascade's depth map d. Scene pass: render with shadow maps bound, fragment shader selects cascade by view-space depth
Key concepts
- Shadow map textures need
DEPTH_STENCIL_TARGET | SAMPLERusage flags - Depth-only render pass: no color targets, only depth attachment
- Cascade splits: logarithmic-linear blend for practical depth ranges
- Light VP matrices: tight orthographic projection from frustum corners
- PCF sampling: 3x3 grid averages shadow/lit for soft edges
- Store op MUST be STORE (not DONT_CARE) for shadow map depth passes
Pipeline setup
Shadow pipeline (depth-only)
/* No color targets — depth only */
pipe.target_info.num_color_targets = 0;
pipe.target_info.has_depth_stencil_target = true;
pipe.target_info.depth_stencil_format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
/* Front-face culling reduces peter-panning */
pipe.rasterizer_state.cull_mode = SDL_GPU_CULLMODE_FRONT;
/* Depth bias reduces shadow acne */
pipe.rasterizer_state.depth_bias_constant_factor = 2;
pipe.rasterizer_state.depth_bias_slope_factor = 2.0f;
Shadow map texture
SDL_GPUTextureCreateInfo info;
SDL_zero(info);
info.type = SDL_GPU_TEXTURETYPE_2D;
info.format = SDL_GPU_TEXTUREFORMAT_D32_FLOAT;
info.usage = SDL_GPU_TEXTUREUSAGE_DEPTH_STENCIL_TARGET |
SDL_GPU_TEXTUREUSAGE_SAMPLER; /* key: both flags */
info.width = 2048;
info.height = 2048;
info.layer_count_or_depth = 1;
info.num_levels = 1;
Shadow sampler
SDL_GPUSamplerCreateInfo smp;
SDL_zero(smp);
smp.min_filter = SDL_GPU_FILTER_NEAREST;
smp.mag_filter = SDL_GPU_FILTER_NEAREST;
smp.address_mode_u = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
smp.address_mode_v = SDL_GPU_SAMPLERADDRESSMODE_CLAMP_TO_EDGE;
Cascade split algorithm
/* Lengyel's logarithmic-linear blend */
for (int i = 0; i = current_depth - bias) ? 1.0 : 0.0;
}
}
return shadow / 9.0;
}
Common mistakes
- Forgetting SAMPLER usage flag on shadow map texture — it will not be
readable in fragment shaders without it
- Using DONTCARE for shadow pass storeop — depth data is discarded
and shadow maps will be empty
- Not flipping Y when converting NDC to UV:
shadow_uv.y = 1.0 - shadow_uv.y - Missing depth bias — causes shadow acne (moire self-shadowing pattern)
- Culling back faces in shadow pass — should cull FRONT faces instead
to reduce peter-panning
- Not expanding Z range of the light AABB — shadow casters behind the
frustum slice won't cast shadows into it
HLSL register map
Vertex uniform slot 0 → register(b0, space1)
Vertex uniform slot 1 → register(b1, space1)
Fragment sampler slot N → register(tN, space2) + register(sN, space2)
Fragment uniform slot 0 → register(b0, space3)
Reference
See: [Lesson 15 — Cascaded Shadow Maps](../../../lessons/gpu/15-cascaded-shadow-maps/)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: Nebulavenus
- Source: Nebulavenus/forge-gpu
- License: Zlib
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.