ワンクリックで
shader-graph
Create or edit custom shaders and shader graphs — `.graphShader` YAML, GLSL code nodes, and library subgraphs.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Create or edit custom shaders and shader graphs — `.graphShader` YAML, GLSL code nodes, and library subgraphs.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
Lens Studio native packages: install from Asset Library, pack/unpack `.lsc`/`.lspkg`, bump versions, attach README/`.d.ts`, author setup scripts. APIs `NativePackageDescriptor`, `exportScript`/`exportPackage`, `unpack`, `instantiate`, `SetupScript`.
Migrate a Lens project from Spectacles (2024) to SPECS 27 APIs: WebView, Remote Media, Camera, Depth, Motion Controller, SyncKit, VoiceML→ASR, RemoteReferenceAsset→Supabase. Use when migrating or porting a Lens to SPECS 27, or about deprecated APIs.
Update outdated packages/libraries (SIK, UIKit, SSK, SyncKit) in a Lens Studio project via the Editor API. Use for 'update my packages', 'upgrade SIK', 'update dependencies', 'pull latest SIK', or any package update ask. Requires Lens Studio MCP.
Generate a 3D mesh, model, or asset for a Lens — build, create, or make props, characters, scenery. Four peer backends chosen per asset: SPECS text-to-3D (static default — best texture fidelity, async minutes-long jobs), FAST3D (faster static AI props), code-authored MeshBuilder via the mesh-builder-scripting skill (articulated, animated, parametric TypeScript content), and Blender voxel (blocky aesthetic; the only source of rigged GLBs). GLB backends return the file plus AABB metadata so the caller can size colliders and place the mesh in the world.
Generate musical phrases, chord progressions, beats, jingles, and short pieces via local algorithmic synthesis. Sample-free, license-clean, fully offline. Scale-degree composition, pattern-based arrangement, frequency-separated mixing rules. Outputs 44.1 kHz stereo WAV to Assets/GeneratedSFX/.
Generate non-pitched sound effects (UI, impacts, sweeps, foley, ambient textures, retro 8-bit) via local algorithmic synthesis. Outputs 44.1 kHz WAV to Assets/GeneratedSFX/. For musical phrases or chord progressions use /build-music instead.
| name | shader-graph |
| description | Create or edit custom shaders and shader graphs — `.graphShader` YAML, GLSL code nodes, and library subgraphs. |
| user-invocable | true |
This skill is for creating or editing custom shaders — .graphShader files, GLSL code nodes, library subgraphs in shader graphs.
Don't use this skill when:
.graphVfx particle/VFX graph → vfx-graphmaterialsRead the bundled example file first. It shows the full schema in working form. This skill only covers what you can't see in that file: runtime constraints, conventions, embedding procedures, and strategic guidance.
<LS_INSTALL>Several reference files (below) and the manifest (§6) live inside the user's Lens Studio install. Run the getLensStudioInstallPath snippet from reference/resolve-ls-install.md via the ExecuteEditorCode MCP tool to get the path.
codeNode.graphShader at <LS_INSTALL>/Contents/JsPlugins/PresetsRegistry/Assets/CodeNodeMaterial/Resources/codeNode.graphShader.system.* API): reference/code-node-reference.md. VFX-specific system.* additions live in vfx-graph's reference dir.nodes.json) — every template's port set: see §6 below.vfx-graph.Node{N}CheckEnabled / CheckExists / CheckValue are siblings, not childrenThese three flags sit at the same indent level as Node{N}: — outside the node block, as sibling keys under ChildNodes:
ChildNodes:
Node3:
...
Node3CheckValue: false # sibling of Node3, NOT a child
Node6:
...
Node6CheckEnabled: true # CheckEnabled+CheckExists usually paired
Node6CheckExists: true
Defaults: CheckEnabled: false, CheckExists: false, CheckValue: true. So:
Node{N}CheckValue: false (written) means it's been toggled off from its default of true.Node{N}CheckEnabled: true + CheckExists: true (written, usually paired) means they've been toggled on from their default of false.Most defaults are stripped from the YAML — when authoring, only write the ports/fields you're actively setting; the engine fills in the rest with defaults from the manifest.
When embedding a library subgraph, copy whatever metadata the source file specifies.
IOType: 0 is never writtenOutput ports write IOType: 1. Input ports omit IOType entirely. Don't write IOType: 0 even though it'd be valid.
ClassType1 is omitted for inferable classesThe codec strips ClassType1 from YAML on save when it can re-derive the class from the port's structural shape. On load the engine re-infers it; runtime behavior is unchanged.
FLOAT, INT, BOOL, STRING, COMBO, LINK.COLOR, MATRIX, TEXT, REFUID, and anything whose stored value differs from the inferred class — e.g. typed asset refs that carry ClassType1: "" alongside BaseType.When authoring, only write ClassType1 for the preserved set. Older fixtures may show explicit ClassType1: FLOAT/LINK/etc.; those will be stripped on the next save and are not a correctness concern either way.
Connection0 only — no Connection1 or higherEach port has at most one incoming connection. The key is always Connection0: (the trailing zero is convention). Multi-input nodes use distinct port names (Input0, Input1, Value1, Value2, ...) — fan-in lives in port-name multiplicity, not connection-number multiplicity.
There is no ConnectionCount field — presence of Connection0 implies one connection, absence implies zero.
To disconnect: remove the entire Connection0 block. Don't leave a stub.
LINK ports omit Variable entirely. Other types keep Variable even when connected — it's the fallback if the connection is removed later.
# Typed (preferred when the slot has a fixed asset class)
Mesh:
ClassType1: "" # empty string when paired with BaseType
BaseType: Asset.RenderMesh # or Asset.Material, etc.
ScriptType: All
String: "" # asset GUID; "" = unbound
# REFUID (generic)
CustomCodeNodeAsset:
ClassType1: REFUID
String: ""
Texture inputs are different — they use LINK + ClassType2: TEXTURE_OBJECT_2D, not an asset ref.
ItemCount + Title0..N)nodes_inputs_parameters_droplist is the only template that uses ItemCount plus Title0/Title1/...Title<N-1> ports for its dropdown options. Regular COMBO ports use the flat ItemList: "a : b : c" string with no ItemCount or per-item title ports. Don't confuse them.
Most port defaults for node_util_custom (and the VFX container variants node_util_custom_container_spawn, _container_update) are in the manifest — look them up there. The conventions an agent needs to know that aren't obvious from the manifest:
TemplateVersionMinor is a sibling field on the node block (NOT a port). The correct value depends on the template family:
node_util_custom (regular shader code nodes) → TemplateVersionMinor: 2node_util_custom_container_* (VFX container variants: _spawn, _update, _output_pixel, _output_vertex) → TemplateVersionMinor: 1The manifest's schemaDefaults lists 0, but neither family uses the manifest default — always write the correct value above.
LastChached3 and LastCodeFormatted3 ports are engine-populated GLSL caches. Leave them at the manifest default ("") when authoring — the engine fills them in on save. Never hand-author them.
ID port — the manifest may list a per-instance value (e.g. 75); ignore that. For new nodes use 0 or the node's LevelID. Used for variable-name prefixing in the compiled cache.
Title port — display name. See reference/code-node-reference.md §5 for the port shape and its required Title1 sibling.
The Code port's GLSL block scalar uses tabs, not spaces.
Container variants (_container_spawn, _container_update) cannot declare output_* decorators — they set particle attributes via system.* calls and chain through implicit ParticleIn/ParticleOut LINK ports.
Texture input_* decorators map to LINK ports, not FLOAT. A input_texture_2d Tex; declaration in GLSL produces a host YAML port whose stored class is LINK and whose ClassType2 is TEXTURE_OBJECT_2D — not a FLOAT/vec4 port. ClassType1: LINK is stripped on save (see "ClassType1 is omitted for inferable classes"); the structural signal is the bare ClassType2. Example connecting a Texture 2D Object Parameter:
BaseTex:
ClassType2: TEXTURE_OBJECT_2D
Connection0:
NodeLevelID: 16 # the Texture 2D Object Parameter node
PortID: Texture
Same shape for _texture_2d_array, _texture_cube, _texture_3d — just ClassType2 set to the matching TEXTURE_OBJECT_*. Verify the exact value against an existing instance or the manifest.
Lens Studio reimports the asset asynchronously after the file changes. A query against the asset or its dependents (e.g. asset-graphql reads) issued within ~1s of the write may return a stale snapshot. Wait at least 1–2 seconds between the write and any verify-by-query step.
Steps:
TemplateID in the manifest (see §6) to find the available port IDs, types (ClassType1), and dimensions. Use this when you need to know a port name to set or connect.Node{N} map key under ChildNodes.LevelID = max(existing LevelIDs across the entire graph) + 1. LevelIDs must be unique anywhere a connection might cross.DependencyIndex = max(existing DependencyIndex) + 1. Sequential per file.Variable/String/ItemList+ItemIndex/etc.) and any input ports you're connecting (with Connection0). Omit ports you don't touch.The bundled example file shows how the editor saves a working graph — it may include more ports than strictly required because the editor writes the full active state. When authoring from scratch, prefer minimal.
Procedure for deleting Node{K}::
Strip every Connection0 that references the removed node's LevelID. Find every NodeLevelID: <K's LevelID> in the file and delete the enclosing Connection0: block. The remaining Variable: default takes over.
Exception — replace, don't strip. If you're swapping the deleted node for a new one in the same pipeline slot, retarget each downstream Connection0 to the replacement node's LevelID instead of stripping it. Stripping then re-adding the same connection is just busywork — and easy to forget the re-add half of.
Bypass-rewire. If the deleted node was a pass-through (one logical input wired through to its output), retarget downstream Connection0s to whatever was feeding that input port. Trace the input's Connection0 (or, for subgraphs, the outer port whose SubGraphUniqueID{N} matches the inner export node's LevelID) to find the upstream source.
Remove the Node{K}: block itself, plus its Node{K}CheckEnabled / Node{K}CheckExists / Node{K}CheckValue siblings if present.
Leave everything else alone. Don't touch other nodes' LevelIDs, DependencyIndexs, or the alphabetic Node{N}: keys — the engine resolves wiring through LevelID references, so gaps in any of these sequences load and run correctly. The editor renumbers densely when it next saves the file, but externally-edited files with gaps are fine.
Connections live on the input port of the destination:
Input0:
Connection0:
NodeLevelID: 5 # source node's LevelID
PortID: Output # source port's map key
Variable: [0.0, 0.0, 0.0, 0.0] # fallback if disconnected (kept on non-LINK ports)
(ClassType1: FLOAT is omitted here — see §1.)
Library subgraphs are .subgraphCommon, .subgraphVfxSpawn, .subgraphVfxUpdate, .subgraphVfxOutput files. Each is a complete NodeType: 3 container with internal nodes and external SubGraphUniqueID{N} ports.
.subgraphCommon is a subgraph format that's shared between shader graph and vfx graph. The other formats are specific to VFX graph.
SubGraphUniqueID{N} matches inner LevelID: the container's outer-facing port named SubGraphUniqueID{N} corresponds to the inner nodes_import_* or nodes_export_* node whose LevelID is {N}. When you remap LevelIDs, you must rename these ports.
Nodes: block is the container.max(LevelID), assign new sequential IDs starting at max + 1 to the container and all its internal nodes, update every Connection0.NodeLevelID inside the subgraph's ChildNodes, and rename the container's SubGraphUniqueID{N} port keys to match the new internal LevelIDs.Node{N} map key — pipeline ordering is enforced by the Begin/End connection chain, not map position.Node{N}CheckEnabled: true and Node{N}CheckExists: true — copy what the source file shows.DependencyIndex values past max(existing) for the container and its internals (depth-first, internals before their container). Gaps in the sequence are fine — don't renumber existing nodes.| Extension | Directory |
|---|---|
.subgraphCommon | Systems/Shaders/library/subgraph/ |
.subgraphVfxSpawn | Systems/Particles/library/subgraph_vfx_spawn/ |
.subgraphVfxUpdate | Systems/Particles/library/subgraph_vfx_update/ |
.subgraphVfxOutput | Systems/Particles/library/subgraph_vfx_output/ |
Parameter nodes (nodes_inputs_parameters_float, _color, _bool, _texture2d_object, _droplist) expose user-tweakable values in the Lens Studio Inspector and at runtime via the material's mainPass.
ScriptName rules:
Title (display label), ScriptName (runtime variable name), Default or per-output Variable (initial value), Group (optional Inspector group label), Tooltip, SortIndex (Inspector display order).
nodes.json)Authoritative port set, types, dimensions, and per-port defaults for every template, plus the schemaDefaults table.
Paths (under <LS_INSTALL>, see "Resolving <LS_INSTALL>" at the top):
Contents/Plugins/Es_ShaderGraph.bundle/GraphResources/documentation/nodes.jsonContents/Plugins/Es_VFXGraph.bundle/GraphResources/documentation/nodes.jsonRequired when authoring a template you haven't seen instances of in the project. For the jq lookup recipe, the structure of port entries, how to map manifest fields to YAML, and the schemaDefaults table, see reference/manifest.md.
SystemID| Graph type | SystemID |
|---|---|
Shader (.graphShader) | dev.snap.shaders |
VFX/Particle (.graphVfx) | dev.snap.particles |
codeNode.graphShader by defaultAlways start from the bundled codeNode.graphShader and edit the custom code node's GLSL. Code nodes are more compact and easier to reason about than large graphs. Only depart from this default when:
Always-template exceptions (no code-node equivalent exists):
nodes_main_material_brdf. Use this template node for any PBR lighting.nodes_inputs_parameters_*).nodes_main_graph for shaders) on right.