Agent skill

Visualize Physics With Shaders

by LunCoSim in LunCoSim/lunco-sim

Wire simulated values into visible WGSL material parameters in LunCoSim, such as load, heat, charge, slip, or temperature visualization.

Apache-2.0Auto-check passedGame Development

Install Visualize Physics With Shaders

skills CLI
$ npx skills add LunCoSim/lunco-sim --skill visualize-physics-with-shaders -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install LunCoSim/lunco-sim visualize-physics-with-shaders --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/LunCoSim/lunco-sim.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/visualize-physics-with-shaders .claude/skills/visualize-physics-with-shaders && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
visualize-physics-with-shaders
GitHub stars
107
Token cost
~3.6k tokens
SKILL.md length
1,904 words
Files
1
Skills in repo
40
Repo updated
First seen
Licence
Apache-2.0

At a glance

Wire simulated values into visible WGSL material parameters in LunCoSim, such as load, heat, charge, slip, or temperature visualization.

  • Shader Material inputs
  • SKILL.md covers The mechanism, Recipe, The same wire drives a LIGHT,… and Why the wire goes on the…, plus 2 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md
  • ShaderLook::live

What it does

Visualize Physics With Shaders is an agent skill from LunCoSim/lunco-sim. Wire simulated values into visible WGSL material parameters in LunCoSim, such as load, heat, charge, slip, or temperature visualization. Use for shader Material inputs, ShaderLook::live, USD connections, and values that must follow physics. Visual consequences are wired from authoritative outputs, not scripted; use compose-multidomain-twin for the physics and build-usd-scene for scene authoring.

Its SKILL.md is about 3.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Game Development, covering Shaders. The repository describes itself as: Collaborative Multiphysics Cosimulator For Space Missions 🌎🚀🌚. The licence is Apache-2.0.

When your agent uses it

  • Shader Material inputs
  • ShaderLook::live
  • USD connections
  • Values that must follow physics

Example prompts

  • “/visualize-physics-with-shaders”

What it can do on your machine

Read from SKILL.md and the folder at commit d1c6f00. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md (its code samples are usda and wgsl).

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Visualize Physics With Shaders loads about 3.6k tokens when it runs. Until then it costs about 108 tokens; SKILL.md has 1,904 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~108
When it runs · the whole SKILL.md, loaded when a task matches
~3.6k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from LunCoSim/lunco-sim at commit d1c6f00, republished under its Apache-2.0 licence (© LunCoSim). 1,904 words, ~3,593 tokens.

Download SKILL.mdSave it as .claude/skills/visualize-physics-with-shaders/SKILL.md (or your agent's skills folder).
name
visualize-physics-with-shaders
description
Wire simulated values into visible WGSL material parameters in LunCoSim, such as load, heat, charge, slip, or temperature visualization. Use for shader `Material` inputs, `ShaderLook::live`, USD connections, and values that must follow physics. Visual consequences are wired from authoritative outputs, not scripted; use compose-multidomain-twin for the physics and build-usd-scene for scene authoring.

Visualizing physics values with shaders

A visual is a consequence of physics, not a performance of it. A strut turns red because it is carrying load, on the same tick and by the same number the solver computed. Nothing samples a clock, nothing tweens, and nothing in rhai paints anything.

The chain is three links, each owned by the layer that knows the fact:

Modelica / avian  ──►  a port  ──►  a USD connection  ──►  a WGSL uniform
   computes it        publishes it     wires it            draws it

The mechanism

There is no shader-specific plumbing. Shader parameters are ordinary port sinks: rewire_usd_connections turns any inputs:*.connect into a SimConnection without caring what the target is, propagate_connections writes it through PortRegistry, and lunco-render-bevy's SHADER_PARAM_BACKEND receives it into ShaderLook::live, which rebind_changed_shader_look drains to the GPU. Same graph as a thruster force or a battery load.

Connected names are seeded as empty slots in ShaderLook::live(). The compiled wire resolves the slot at a topology boundary and writes by handle thereafter; the first sample does not change the slot layout. Use set_value for authored parameters and set_live for engine-owned updates so topology identity changes only with the authored parameter shape.

Recipe

1. Declare the parameter in the WGSL. The engine reflects the Material struct — field names, offsets, and the //!@ annotations — straight out of the file. A field that isn't declared here does not exist.

wgsl
//!@ui      base_color  color "Strut colour"
//!@default base_color  0.55,0.57,0.60
//!@ui      load_frac   0 1   "Load fraction (driven)"
//!@default load_frac   0.0
struct Material {
    base_color: vec4<f32>,
    load_frac:  f32,
}

@fragment
fn fragment(in: VertexOutput) -> @location(0) vec4<f32> {
    // The RAMP is a look decision and belongs here. The NUMBER being ramped is a
    // physics result and does not.
    let hot = vec3<f32>(1.0, 0.15, 0.05);
    return vec4<f32>(mix(material.base_color.rgb, hot, material.load_frac), 1.0);
}

2. Find the port that already publishes the physical result. Bodies, colliders and joints expose their state as ports because they exist — a PrismaticJoint's force is the spring's own reaction, in newtons, computed by the solver that integrates it. Nothing needs authoring to make it available, and a model written to restate it would be a second copy of the same fact.

3. Wire it on the BOUND GEOMETRY, and normalise ON THE WIRE. The sink's SSP linear transformation (lunco:factor:<port> / lunco:offset:<port>) turns the raw physical quantity into the shader's 0..1 parameter, so the rating is one number sitting next to the wire that uses it. The shader saturates.

usda
def Mesh "LegPX_Strut" (prepend apiSchemas = ["MaterialBindingAPI"])
{
    rel material:binding = </Looks/StrutMat>
    float inputs:load_frac.connect = </DescentLander/LegPX_Spring.outputs:force>
    float lunco:factor:load_frac = 0.00066667   # 1 / 1500 N rated
}

A lunco:factor: is a UNIT CONVERSION, and nothing else. It carries the rating that takes newtons to a 0..1 fraction. Never put a SIGN in it. Which way a mechanism travels is a fact about the joint, authored once in its physics:localRot0; a sign in the factor states it a second time, and makes the render wiring silently depend on an orientation it never names. If a wire needs a negative factor to look right, the joint's axis is backwards — fix it there.

4. Verify. read_ports on the prim lists every declared parameter with its live value; the inspector shows driven rows greyed out. If the value moves in read_ports and the colour doesn't, the problem is the shader; if it doesn't move there, the problem is the wire.

The same wire drives a LIGHT, and a transform

A shader uniform is not the only render-side sink. lunco-render-bevy's SCENE_PROPERTY_BACKEND (scene_ports.rs) exposes the properties a simulation legitimately drives, as scalar In ports on the prim that carries the component:

ComponentPorts
PointLightlight_intensity, light_radius, light_color_r/g/b
Transformtranslation_x/y/z, scale_x/y/z
usda
def SphereLight "PlumeLight"
{
    float inputs:light_intensity.connect = </…/Photometry.outputs:intensity>
    float inputs:light_radius.connect    = </…/Photometry.outputs:radius>
}

The engine plume is the worked example end to end: propulsion and nozzle outputs feed LunCo.Propulsion.PlumePhotometry, which derives the physical free-jet length, visible length fraction, luminous power, and source radius. USD connects that length fraction and the light outputs to a fixed-capacity WGSL cone and its child light. WGSL owns the perceptual width response and flicker; Modelica owns the physical length and photometry; Rhai supplies stimulus and verdicts only. Zero thrust is therefore dark without a script-side visual mirror.

Aggregate propulsion with multiple nozzles

When a propulsion model publishes cluster-total thrust and flow but the vehicle has one visual nozzle per engine, set PlumePhotometry.engine_count to the configured nozzle count. Keep the input thrust and flow aggregate; supply each nozzle's own exit radius and area. The photometry model divides the extensive cluster values before deriving the per-nozzle momentum flux, exit pressure, and light output. Connect the same per-nozzle results to one fixed flame pair and one light at each nozzle. Source the count from the Twin's typed engine-instance configuration and verify the authored model parameter against it. Do not send the undivided cluster light to every nozzle or calculate per-engine plume state in Rhai.

Set the fixed envelope's nozzle end on the measured bell exit plane and point its narrow end down the exhaust axis. Start its throttle and light intensity at zero; the simulation's live outputs reveal the flame during a burn. Keep vehicle-specific material paths in the vehicle composition layer; a reusable nozzle component must not point at a particular vehicle's absolute material path.

Prove a plume is driven by the simulation

An authored connection proves only that a route exists. Before reporting a visible, simulation-driven flame, confirm the continuous model compiles and produces samples, then compare an idle sample with a powered sample:

  • At zero delivered thrust, render_throttle, visual_length_fraction, and intensity are zero. radius may remain at its authored idle value; zero light intensity and the shader's zero throttle keep the plume dark.
  • During a burn, those three outputs are finite and positive, and the powered values reach the cone and light through the composed USD connections.
  • Read the composed ports on the photometry model and at least one flame/light sink, then inspect the rendered vehicle to confirm the cone responds and the light affects nearby terrain. A solver sample proves the values; a rendered inspection proves the visual result.

If the model is unbalanced or has no run, report the authored wiring as present and the dynamic/visual result as unverified. Do not make Rhai animate the flame to hide a missing solver result. The Griffin status example is in its Twin's contracts/implementation_gaps.md.

A driven Transform is not a licence to animate. A transform WIRED to a port is a consequence — some model or joint published the number and the stage shows where it came from. A transform COMPUTED per tick in a script is animation, and is still forbidden. Also: drive a transform only on a prim nothing else moves, or the wire fights the USD projector, a rigid body, or a joint.

Why the wire goes on the gprim, and what it costs

A UsdShade input belongs to the material, which is shared by every prim bound to it. A driven value is the opposite — per-instance; four legs each report their own load. So the bound geometry is where the meaning lives, and the engine makes that prim's material private (ShaderLook::unshared) so one leg's glow does not paint its three siblings.

Be honest that this is a LunCo convention, not portable USD. Attribute connections are core Sdf, so this is spec-legal and round-trips — but inputs: is a UsdShade convention, and connectability is gated by UsdShadeConnectableAPIBehavior, which registers Shader/NodeGraph/Material and never a Gprim. Hydra's HdMaterialNetwork never walks this edge; usdchecker's shading validators never see it; Omniverse and MaterialX (<geompropvalue>) ignore it. The material:binding chain is portable, the drive is not.

The standard answer to "one material, varying per gprim" is primvars: plus a UsdPrimvarReader node — and it would delete unshared and the private material outright. We don't use it yet because the binder resolves a single shader, not a network, so a reader node would have nothing to evaluate it. That is a deliberate deferral with a known migration path, not the absence of a standard.

Show full SKILL.md (723 more words)Show less

Gotchas

  • DECLARE A DRIVEN PARAMETER ON THE SHADER PRIM, not only in the WGSL. This is the one that silently kills a wire. The authoring pass decides what counts as a shader drive by intersecting the gprim's connected inputs: against the parameters the bound Shader prim authors — it reads USD, not the reflected schema, which does not exist until the .wgsl asset loads. A parameter that appears in struct Material but is absent from the Shader prim is therefore not in the driven set: the port backend refuses the write and the uniform sits at its default forever. Author it with its resting value:

    usda
    def Shader "Surface" {
        uniform asset info:wgsl:sourceAsset = @lunco://shaders/strut_glow.wgsl@
        float inputs:load_frac = 0     # ← declared here, or the wire is dead
    }

    The Shader prim is the shader's interface; the WGSL is its implementation. Both must name the parameter.

  • A name neither declares is refused — and that is the feature. It surfaces as a dangling-wire warning from propagation instead of the classic silent dead uniform. If your wire logs as dangling, check the Shader prim's inputs: first, then the WGSL field list.

  • Names are snake_case, because the reflection binds WGSL struct fields. inputs:loadFrac and inputs:load_frac both reach load_frac, but a field spelled loadFrac in the WGSL is unreachable.

  • Publish the physical quantity, not the driving term. A strut fed the proximity-gated force pressed onto the leg reads fully loaded while still in the air, and glows red before touchdown. The honest number is the spring's own reaction, exactly zero until compression starts — and it comes off the joint that integrates the spring (PrismaticJoint's force port), never from a second copy of the spring law. When a visualization "happens too early", suspect something is publishing an input rather than a result.

  • A wheel diagnostic must use its realization's result. Raycast wheels may expose solved tire and normal forces; jointed wheels may expose the solver's joint reaction. The body's integration accumulator is not a per-wheel contact force. If a debug arrow is drawn from a raw velocity or force, apply an explicit unit scale and cap its render length so a transient cannot become a line across the terrain.

  • Normalise on the WIRE, not in the shader, a script, or a model. The affine lunco:factor:<port> / lunco:offset:<port> on the sink is exactly the SSP LinearTransformation — a unit conversion, never a sign or an orientation fixup — and a rating is one number: re-rating the strut is a single edit next to the connection it scales. Writing a .mo to hold one constant buys a whole solver instance and a second place for the number to drift.

  • Don't collide with an //!@engine field. Fields annotated @engine are filled by Rust every frame (sun_vis, albedo, sun_dir_world, weight_rough). A wire pointed at one of those loses the race every frame, silently. Pick a name the engine does not own.

  • Driven parameters are read-only in the inspector. An active override in ShaderLook::live() is engine-owned and its control is disabled — editing it would be a lie, since the next tick overwrites whatever was typed. Seeing the value move is the point; editing it is not.

  • inputs: is the spelling for EVERY port, not just shader parameters. A prim commonly carries simulation wires alongside its shader drives. The material layer intersects against the shader's declared inputs precisely so those simulation wires are not mistaken for shader drives — if you add a parameter to the WGSL, check you have not just shadowed a sim port name.

  • A vec parameter cannot be driven by one wire. A connection carries one f64. Drive components individually (inputs:tint_r) or ramp the colour inside the shader from a scalar — the latter is almost always what you want, because the ramp is a look decision.

Anti-patterns

  • ❌ Painting colour from rhai (set(me, "PbrLook.emissive.red", …)) — that is animation, not visualization; it re-derives in a script what physics already computed, and it drifts the moment the model is re-tuned.
  • ❌ Ramping against a clock, a phase, or an altitude threshold instead of a physical result. If the shader needs to know the mission timeline, the value being drawn is the wrong one.
  • ❌ Hardcoding the full-scale constant in the shader — re-rating the part then silently lies about every instance.
  • ❌ Reading a SENSOR to drive a physical part's visual. A strut's glow follows its own reaction force, not an altimeter that sits 3.3 m away; see compose-multidomain-twin.

© LunCoSim, Apache-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in skills/visualize-physics-with-shaders of LunCoSim/lunco-sim.

Open the folder on GitHubat commit d1c6f00

Compare with similar skills

Visualize Physics With Shaders next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Visualize Physics With Shaders compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Visualize Physics With Shaders this skillLunCoSim/lunco-sim107—~3.6kAutomated safety check: PassApache-2.0
PixijsRSamaium/CanvasEngine4012 repos~1.6kAutomated safety check: PassMIT
New ExperimentTresjs/tres3.8k—~782Automated safety check: PassMIT
Assets Shader List AllIvanMurzak/Unity-MCP4.4k—~435Automated safety check: PassApache-2.0
Handle Sdr Tonemap Lutclshortfuse/renodx4.5k—~7.3kAutomated safety check: PassMIT
Unreal Material and VFX Workflowflopperam/unreal-engine-mcp1.1k—~927Automated safety check: PassNone

Similar skills

  • Pixijs

    RSamaium/CanvasEngine

    Use this skill first for ANY PixiJS v8 task; it routes to the right specialized skill for the job.

    401 GitHub starsUsed in 2 repos~1.6k tokens
    Game DevelopmentAuto-check passed
  • New Experiment

    Tresjs/tres

    Create a new experiment in TresJS Lab with all necessary files

    3.8k GitHub stars~782 tokensUpdated yesterday
    Game DevelopmentAuto-check passed
  • Assets Shader List All

    IvanMurzak/Unity-MCP

    List all shaders available in the project assets and packages, sorted by name.

    4.4k GitHub stars~435 tokensUpdated 5 days ago
    Game DevelopmentAuto-check passed
  • Handle Sdr Tonemap Lut

    clshortfuse/renodx

    RenoDX HLSL/Slang shader workflow for proven shader-side SDR tonemap, hard clip, LUT, color grade, and HDR bridge changes.

    4.5k GitHub stars~7.3k tokensUpdated today
    Game DevelopmentAuto-check passed
  • Unreal Material and VFX Workflow

    flopperam/unreal-engine-mcp

    Walks an Unreal Engine MCP agent through building materials, Niagara particle systems, Chaos destruction, and curve assets with inspect-then-edit steps.

    1.1k GitHub stars~927 tokensUpdated 3 mo ago
    Game DevelopmentAuto-check passed
  • Rdc CLI

    BANANASJIM/rdc-cli

    A skill your agent uses when working with RenderDoc capture files (.rdc), analyzing GPU frames, tracing shaders, inspecting draw calls, or running CI assertions against GPU captures.

    182 GitHub stars~2.9k tokensUpdated today
    Game DevelopmentAuto-check passed

More from LunCoSim/lunco-sim

All 40 skills in this repo
  • Nightly Changelog

    LunCoSim/lunco-sim

    Generate concise LunCoSim nightly GitHub release notes with platform downloads, installation guidance, an AI-agent mission prompt, and a changelog link.

    107 GitHub stars~1.1k tokensUpdated today
    Auto-check passed
  • Build or repair a reusable scene component through a live LunCoSim Editor session.

    107 GitHub stars~4.4k tokensUpdated today
    Auto-check passed
  • Assembly Quality

    LunCoSim/lunco-sim

    Build or review a componentized LunCoSim USD assembly with a realistic, dimensionally checkable presentation.

    107 GitHub stars~1.6k tokensUpdated today
    Auto-check passed
  • Author Rhai Tests

    LunCoSim/lunco-sim

    Author and review LunCoSim behavioral, asset-backed, component, mission, visual, and requirements-verification tests.

    107 GitHub stars~3.5k tokensUpdated today
    Auto-check passed
  • Author Rhai Tool

    LunCoSim/lunco-sim

    Create, extend, register, or debug a reusable LunCoSim Rhai tool library for live USD authoring, component linting, inspection, or test support.

    107 GitHub stars~5.2k tokensUpdated today
    Auto-check passed
  • Author Tutorial

    LunCoSim/lunco-sim

    Author an interactive tutorial, guided lesson, onboarding flow, coach-mark tour, or objectives checklist in LunCoSim.

    107 GitHub stars~1.4k tokensUpdated today
    Auto-check passed

Questions about Visualize Physics With Shaders

What does Visualize Physics With Shaders do?

Wire simulated values into visible WGSL material parameters in LunCoSim, such as load, heat, charge, slip, or temperature visualization. Visualize Physics With Shaders is an agent skill from LunCoSim/lunco-sim. Wire simulated values into visible WGSL material parameters in LunCoSim, such as load, heat, charge, slip, or temperature visualization.

When should I use Visualize Physics With Shaders?

Visualize Physics With Shaders fits situations like: shader Material inputs; shaderLook::live; USD connections; values that must follow physics.

How do I install Visualize Physics With Shaders in Claude Code?

Run `npx skills add LunCoSim/lunco-sim --skill visualize-physics-with-shaders -a claude-code`. Or copy the skill folder (skills/visualize-physics-with-shaders in LunCoSim/lunco-sim) into .claude/skills/visualize-physics-with-shaders in your project. Claude Code loads it when a task matches its description.

How do I install Visualize Physics With Shaders in Codex?

Run `npx skills add LunCoSim/lunco-sim --skill visualize-physics-with-shaders -a codex`. Or copy the skill folder (skills/visualize-physics-with-shaders in LunCoSim/lunco-sim) into .agents/skills/visualize-physics-with-shaders in your project. Codex loads it when a task matches its description.

Can I use Visualize Physics With Shaders in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add LunCoSim/lunco-sim --skill visualize-physics-with-shaders -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/visualize-physics-with-shaders, .gemini/skills/visualize-physics-with-shaders, .github/skills/visualize-physics-with-shaders and .opencode/skills/visualize-physics-with-shaders in your project.

What does Visualize Physics With Shaders need to run?

SKILL.md names no scripts, command-line tools or credentials: Visualize Physics With Shaders is instructions for the agent only.

Does Visualize Physics With Shaders access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Visualize Physics With Shaders safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Visualize Physics With Shaders use?

Visualize Physics With Shaders is published under the Apache-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Visualize Physics With Shaders use?

About 3.6k tokens (SKILL.md is roughly 14k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Visualize Physics With Shaders?

Skills that share tags, products or a category with Visualize Physics With Shaders: Pixijs (RSamaium/CanvasEngine, 401 stars), New Experiment (Tresjs/tres, 3.8k stars), Assets Shader List All (IvanMurzak/Unity-MCP, 4.4k stars) and Handle Sdr Tonemap Lut (clshortfuse/renodx, 4.5k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Visualize Physics With Shaders?

LunCoSim (a GitHub organization) maintains it in LunCoSim/lunco-sim, which has 107 GitHub stars. The repository holds 40 skills in this directory. The repository was last updated on October 9, 2026.

Source: LunCoSim/lunco-sim on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.