agentleFS
ForgeAXForgeAX/forgeax-engine/skills/forgeax-engine-vfx/SKILL.md

forgeax-engine-vfx

Skill70 starsChanged 18 days agoApache-2.0View on GitHub

ForgeAX code-first GPU VFX authoring, cooking, playback, and rendering. Use when creating, loading, debugging, or extending particle, ribbon, trail, beam, billboard, or mesh effects.

The file

We split this skill into the rules it gives an agent

4 rules. About 0 are common, 2 are distinctive, and 2 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈2

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 2

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Read packages/vfx/README.md for the author ABI and lifecycle, packages/vfx-compiler/README.md for reflection and cook errors, and

    line 38
  2. Very specific:

    Every particle topology fogs at its own depth through the shared translucent_fog.

    line 57
  3. Distinctive:

    Import; sampled-visibility data cannot qualify collision.

    line 69
  4. Distinctive:

    Use RHI Debug to inspect the actual producer/consumer work before changing the collision shader.

    line 73

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

ForgeAX VFX

Choose the path first

EffectPath
Rain, snow, sparks, bubbles, dust or sandstorm, fire, smoke, magic motes; up to a few thousand particles per field; behaviour written in game TypeScriptPoints sprites on a point-list mesh, moved with writeRange each frame (particles-core). No shader, no cook.
Tens of thousands of particles, GPU scene collision, force fields, ribbons, trails, beams, mesh particles, event sub-emittersCooked GPU VFX below.

Points take a world (sizeUnits: world) or pixel size, square, circle or soft (radial glow) sprites, per-point color (alpha fades) and uv1.x size streams, the material texture across each sprite and the material's blend and depth-write state. That covers Three.js Points/PointsMaterial effects; do not fake particles with pools of small meshes. Switch to the GPU path when the CPU loop or its per-frame upload shows up in a profile, or when the behaviour needs GPU-side data.

Render happy path

VFX is a producer of a closed RenderFeaturePlan in the single RenderScene -> Standard Pipeline -> DeviceScope -> FrameReceipt path. The host performs attach and draw; use receipt-bound inspect, observe, and recover for diagnostics. VFX never owns device, queue, encoder, finish, or submit.

Use one path:

  1. Author schema-v3 emitter metadata with program: { module }, required fixed bounds, schedule, and renderer GUIDs.
  2. Author vfx_spawn and vfx_update in WGSL; import forgeax_vfx::prelude and shared shader modules with #import.
  3. Cook with createParticleCodeNativeCooker(modules); publish payload and particle-effect/program.json atomically.
  4. Ordinary DevKit games already install one VFX assembly per execution realm; consume that owner. For explicit standalone assembly, create one createVfxRuntimeHost({ camera }), attach each { world, assets }, and register host.feature through the owning App/Renderer assembly. Do not add a second host to an SDK game.
  5. Load by GUID with loadVfxGpuEffect, allocate a shared ParticleEffectAsset ref, and spawn ParticleEffectPlayer.

Read packages/vfx/README.md for the author ABI and lifecycle, packages/vfx-compiler/README.md for reflection and cook errors, and packages/vfx-render/README.md for GPU/render ownership.

One-shot bursts (sparks, hit flashes, an enemy dissipating; Three.js additive Points/Sprite, Godot GPUParticles3D.one_shot) need no extra API: give the emitter schedule: { rate: 0, bursts: [{ time: 0, count }] } and a billboard renderer with blend: 'additive', then spawn one ParticleEffectPlayer per burst (a distinct seed varies it) and despawn it after the last scheduled birth plus its particle tail. Reused effects retain their authored burst times, looping and local transform conventions; an asset name does not imply a single short flash. Inspect the timeline before adapting it, and keep gameplay hit feedback synchronous. Authorized source or parameter adaptation may change schedules and recook them while retaining stable identity and provenance. The complete files are recipe 5 of the effects cookbook.

Players advance once per World frame: the vfx-gpu-runtime Update system runs after FixedUpdate and steps each simulating player by Time.delta times its timeScale, so particles move at render rate. Bound hitches with TimePolicy.maxDeltaSeconds; do not add a VFX-side step clock. Each intent records delta, initialDelta and cycle elapsed; device recovery replays the same dispatch count and cycle time over even steps. Presentation retirement must use the same frame time and timeScale as playback. A fixed-tick counter does not measure VFX progress when fixed work is dropped.

Every particle topology fogs at its own depth through the shared translucent_fog; alpha blending adds in-scattering and additive blending only attenuates. Particles never need an effect-side fog term.

[!IMPORTANT] Behavior belongs in WGSL code, not a node/operator graph. Do not add CPU mirrors, runtime compilation, backend-name checks, direct RHI access, particle readback, or demo-side render workarounds.

Switch on structured error codes and use detail plus hint. Unknown source fields fail closed. Batch B accepts executable billboard advanced fields and independent ribbon, trail, and beam topologies. It does not add CPU fallback, runtime compilation, raw author bindings, CPU particle mirrors, gameplay readback, graph authoring, or VFX RPC.

For static-scene collision, import forgeax_vfx::data::scene_sdf and supply createVfxRuntimeHost({ camera, sceneSdf: { read(world) } }) with a fixed World range and explicit budgets. Cook geometric fields on ordinary Mesh GUIDs through Import; sampled-visibility data cannot qualify collision. Renderer owns retained scene projection, sharing, graph production and fence retirement. Follow the host contract for bounded response, approximation error and structured unavailable results. Use RHI Debug to inspect the actual producer/consumer work before changing the collision shader; a successful replay alone does not establish collision quality.

For editor/tool inspection, narrow registry payloads with isVfxGpuEffectAsset and project them through describeVfxGpuEffect. The immutable descriptor owns the emitter tree, timeline, dependencies and executable/partial/unavailable capability truth without exposing compiler objects or raw WGSL bytes.

For wind, attraction or vortex motion, declare emitter forceFields and import forgeax_vfx::data::force_fields; call vfx_apply_force_fields before the authored integration. Produce saved constant/radial/vortex textures with build-time createVfxVectorFieldTexture from @forgeax/engine/vfx-compiler, publish ordinary texture GUIDs, and load the effect GUID. The owning field contract defines transforms, units, sampling and limits. Diagnose a failed field through its structured plan cause and the ordinary asset producer. Run smoke:fields for the bounded independent trajectory/capture probe and scripts/smoke-fields-browser.mjs against the prepared DEV/build server for transport and paired pixels; use the maintained per-owner GPU lease entry.

Inspect runtime state with host.inspect(world). The aggregate is keyed by host generation, player handle, asset GUID and emitter ID; do not collapse it back to one latest intent or treat a realm-local handle as cross-World identity. Recover through the owning generation/LKG path. For asset changes, run node scripts/asset-cook-contract.mjs; a package-local scripts path is invalid. For a live, same-generation preview control, acquire host.acquireControl(world) and use its typed patchPlayerParameters or submitChannel methods. Their generation and structured errors are the evidence boundary; do not reach through VFX_GPU_RUNTIME_RESOURCE_KEY to mutate an instance directly. Verify with:

pnpm --filter @forgeax/hello-boss-lightning smoke:browser
pnpm --filter @forgeax/hello-boss-lightning smoke
pnpm --filter @forgeax/hello-boss-lightning smoke:falsify
node apps/hello/boss-lightning/scripts/smoke-public-only.mjs
pnpm metrics:check
pnpm metrics:run

Browser and Dawn are required because Null structural success cannot prove compute validation, topology draws, or pixels. Visual evidence records advanced-renderers-visible, live-patch-continuity, event-sub-emitter-visible, and hmr-last-known-good-visible with a PNG and falsifier result. Program v3 custom billboard sorting is executable only when the source declares one typed VfxCustom sort field; the compiler and managed GPU pass reject ambiguity instead of silently falling back to emitter order.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.