project-darkwood
Saturday, February 21, 2026
Cedric 3:09 AM
Now update the maskBlend node to use auto-detection:
Cedric 3:09 AM
Deploying now. Dropped the dropdown — Mask Blend now auto-detects:
• Only A + mask: A visible where mask is white, transparent where black
• Only B + mask: B visible where mask is black, transparent where white
• A + B + mask: blends between them like before
Also added a generic
• Only A + mask: A visible where mask is white, transparent where black
• Only B + mask: B visible where mask is black, transparent where white
• A + B + mask: blends between them like before
Also added a generic
${connected:inputName} template any node can use going forward.Cedric 3:09 AM
Building and deploying. Should be live in about a minute.
Marian 3:10 AM
Good. can we put some background for the transparency to show through? Like the iconic photoshop checkers?
Cedric 3:11 AM
The simplest approach: add the checkerboard as a CSS background on the canvas element. The canvas has transparency support already (alpha channel is preserved in
readTextureToCanvas), so a CSS checkerboard behind it will show through automatically.Cedric 3:11 AM
Done — Photoshop-style dark checkerboard behind all node previews. Transparency shows through naturally since the canvas alpha channel is already preserved. Deploying now.
Marian 10:03 AM
SDF arrow sucks. fix it. add more params
image.pngCedric 10:05 AM
Yeah, this is a crude box+triangle combo. Let me rewrite it with proper params — head length, shaft length, rounding, rotation angle, and a better SDF construction:
Cedric 10:05 AM
Wait, the glslHelpers has
${helpers} without the backslash escape. Let me fix:Cedric 10:05 AM
Rewrote the arrow from scratch. New params:
• Length — overall arrow size
• Shaft Width — thickness of the stem
• Head Length — how much of the arrow is the arrowhead (proportion, 0.05–0.8)
• Head Width — how wide the arrowhead spreads
• Rounding — rounds all corners
• Tail — Flat (default), Notched (V-cut at bottom), or Pointed (tapers to a point)
Uses a proper general triangle SDF now instead of the isosceles hack. Deploying.
• Length — overall arrow size
• Shaft Width — thickness of the stem
• Head Length — how much of the arrow is the arrowhead (proportion, 0.05–0.8)
• Head Width — how wide the arrowhead spreads
• Rounding — rounds all corners
• Tail — Flat (default), Notched (V-cut at bottom), or Pointed (tapers to a point)
Uses a proper general triangle SDF now instead of the isosceles hack. Deploying.
Marian 10:50 AM
Double check that base parameters are correctly present only on nodes where it makes sense and that it is wired up correctly
Cedric 10:52 AM
Good. So
isGeneratorNode checks: not in EXCLUDED_TYPES, and has no non-mod texture inputs. Let me verify which nodes get classified as generators vs operators:Cedric 10:52 AM
Now let me check for issues:
1. SDF shape nodes (generators) — These get universal params. Makes sense: you'd want to rotate/scale/offset an SDF circle.
2. SDF operator nodes —
3.
4.
5.
Let me check a few more edge cases:
1. SDF shape nodes (generators) — These get universal params. Makes sense: you'd want to rotate/scale/offset an SDF circle.
2. SDF operator nodes —
sdfAnnular, sdfIntersect, sdfOffset, sdfOnion, sdfOutline, sdfRepeat, sdfRound, sdfSmoothIntersect/Subtract/Union, sdfSubtract, sdfUnion — These are operators (have non-mod inputs). They do NOT get universal params. Correct.3.
colorConstant — Generator (no inputs). Gets universal params... but rotating/scaling a constant color is meaningless. Should be excluded.4.
imageInput — Generator. Gets universal params. Makes sense (offset/scale an image).5.
sdfText, sdfIcon — Generators with customRender. They already handle universal params via the post-process transform in evaluator. Need to verify the compiler handles them too... but customRender nodes are always bitmap (no glslFunction), so they're never in composed segments. Fine.Let me check a few more edge cases:
Cedric 10:52 AM
Good —
Now let me check that the SDF shape nodes'
sdfText and sdfIcon are forced to texture mode (customRender). Universal params work via the post-process transform shader in the evaluator.Now let me check that the SDF shape nodes'
glslFunction properly uses the transformed UV (universal params). The compiler wraps generators with UV transform code. Let me verify with sdfCircle:Cedric 10:52 AM
The
Let me also verify that
glslFunction uses uv — and in the compiler, generator nodes get their uv replaced with _tuv (transformed UV). That's correct.Let me also verify that
seed is wired up correctly for nodes that have it:Cedric 10:52 AM
These are all generators. The seed param is additive: node's own
The only fix needed: exclude
seed + uBase_seed. Correct.The only fix needed: exclude
colorConstant from universal params.Cedric 10:52 AM
Checked everything. Here's the audit:
Generators (67 nodes) — get universal params (rotation, offset, scale, amplitude, seed):
All correctly classified. These have no non-mod texture inputs, so transform/scale/rotate makes sense.
Operators (62 nodes) — NO universal params:
All correctly classified. These take texture inputs and process them — no spatial transform needed at this level.
One fix applied:
SDF nodes verified:
• Shape generators (circle, box, star, etc.) → universal params :whitecheckmark:
• SDF operators (union, subtract, intersect, etc.) → no universal params :whitecheckmark:
•
Seed wiring: 15 noise-based nodes have own
Generators (67 nodes) — get universal params (rotation, offset, scale, amplitude, seed):
All correctly classified. These have no non-mod texture inputs, so transform/scale/rotate makes sense.
Operators (62 nodes) — NO universal params:
All correctly classified. These take texture inputs and process them — no spatial transform needed at this level.
One fix applied:
colorConstant was incorrectly getting universal params (rotating a solid color is pointless). Now excluded alongside constant and output.SDF nodes verified:
• Shape generators (circle, box, star, etc.) → universal params :whitecheckmark:
• SDF operators (union, subtract, intersect, etc.) → no universal params :whitecheckmark:
•
sdfText/sdfIcon → customRender + pipelineHint: 'texture', universal params via post-process transform :whitecheckmark:Seed wiring: 15 noise-based nodes have own
seed param, additively combined with uBase_seed. Correct.Marian 10:56 AM
are you sure no operators are sensitive to position/rotation, etc?
Cedric 10:56 AM
Good catch. Let me think about this...
Cedric 10:56 AM
You're right. These operators do UV manipulation — twirl, kaleidoscope, spherize, pinchBulge, lensDistortion all work relative to a center point. Being able to offset/rotate their effect center would be useful. Same for
But the current universal params system transforms the input UV before the node runs, which makes sense for generators (they generate from UV space). For operators, it would mean transforming the source texture sampling, which is different — it would shift/rotate the input rather than the effect itself.
Actually, that's still useful.
However — adding universal params to ALL operators would clutter the UI and add unnecessary overhead. The real question is: which operators would benefit?
Operators that are position/rotation sensitive:
•
•
•
•
•
•
•
These already have their own center/angle params though. Universal params would be redundant.
The ones that don't have built-in position control and could benefit:
•
•
•
I think the current split is actually correct. The spatial operators already have their own position controls built into their specific params. Adding universal params on top would be confusing (two layers of transform).
What do you think — is there a specific operator where you're missing position/rotation control?
transform2d — which is literally a spatial transform operator.But the current universal params system transforms the input UV before the node runs, which makes sense for generators (they generate from UV space). For operators, it would mean transforming the source texture sampling, which is different — it would shift/rotate the input rather than the effect itself.
Actually, that's still useful.
transform2d is literally that — it already has its own offset/rotation/scale params. But for something like twirl, universal params would let you shift the whole twirl effect.However — adding universal params to ALL operators would clutter the UI and add unnecessary overhead. The real question is: which operators would benefit?
Operators that are position/rotation sensitive:
•
twirl — has centerX/centerY already•
kaleidoscope — center-dependent•
spherize, pinchBulge — center-dependent•
polarCoordinates — center-dependent•
radialBlur — center-dependent•
directionalBlur — angle-dependent•
directionalWarp — angle-dependentThese already have their own center/angle params though. Universal params would be redundant.
The ones that don't have built-in position control and could benefit:
•
pixelate — grid alignment is position-sensitive•
tile — tiling origin matters•
halftone — wait, that's already a generatorI think the current split is actually correct. The spatial operators already have their own position controls built into their specific params. Adding universal params on top would be confusing (two layers of transform).
What do you think — is there a specific operator where you're missing position/rotation control?
Marian 11:16 AM
Good, fix all
Cedric 11:18 AM
Let me check exactly which operators are missing position/rotation controls:
Cedric 11:18 AM
Missing center controls:
• kaleidoscope — no center, no rotation offset
• spherize — no center
• pinchBulge — no center (has radius)
• polarCoordinates — no center
Already have them:
• radialBlur — has centerX/Y ✓
• directionalBlur — has angle ✓
• directionalWarp — has angle ✓
• twirl — has centerX/Y ✓
Let me also check
• kaleidoscope — no center, no rotation offset
• spherize — no center
• pinchBulge — no center (has radius)
• polarCoordinates — no center
Already have them:
• radialBlur — has centerX/Y ✓
• directionalBlur — has angle ✓
• directionalWarp — has angle ✓
• twirl — has centerX/Y ✓
Let me also check
pixelate and tile — these could use offset for grid alignment:Cedric 11:18 AM
Now let me add centerX/centerY and rotation to the ones that need it. I'll also add offsetX/Y to pixelate and tile.
Cedric 11:18 AM
Now pixelate (add offset) and tile (add offset):
Cedric 11:18 AM
Done. Here's what got added:
Operators that already had proper controls were left alone: radialBlur (centerX/Y), directionalBlur (angle), directionalWarp (angle), twirl (centerX/Y).
| Node | Added params |
| ----------------- | --------------------------------------------------- |
| Kaleidoscope | Center X/Y, Rotation |
| Spherize | Center X/Y, Radius |
| Pinch/Bulge | Center X/Y |
| Polar Coordinates | Center X/Y, Rotation |
| Pixelate | Offset X/Y |
| Tile | Offset X/Y, Mirror mode (repeat vs mirrored tiling) |
Operators that already had proper controls were left alone: radialBlur (centerX/Y), directionalBlur (angle), directionalWarp (angle), twirl (centerX/Y).
Marian 2:00 PM
good, make sure basic params are moddable by params as well
Cedric 2:02 PM
Let me check how mod inputs work on operators currently:
Cedric 2:02 PM
None of them have mod inputs yet. Let me check how an existing operator with mod inputs works — like
twirl:Cedric 2:02 PM
All generators. No operators have mod inputs yet. The mod system works by adding
mod<paramName> inputs and umodAmount_<paramName> uniforms. The shader reads the mod texture and applies it. Let me add mod inputs for the spatial params on all 6 operators.Cedric 2:02 PM
Done. All 6 operators now have mod inputs on their spatial params:
• Kaleidoscope: center X/Y mod, rotation mod
• Spherize: strength mod, center X/Y mod
• Pinch/Bulge: strength mod, center X/Y mod
• Polar Coordinates: center X/Y mod, rotation mod
• Pixelate: scale mod, offset X/Y mod
• Tile: tiles X/Y mod, offset X/Y mod
Connect any grayscale texture to the mod ports and use the mod amount slider to control intensity. Deploying now.
• Kaleidoscope: center X/Y mod, rotation mod
• Spherize: strength mod, center X/Y mod
• Pinch/Bulge: strength mod, center X/Y mod
• Polar Coordinates: center X/Y mod, rotation mod
• Pixelate: scale mod, offset X/Y mod
• Tile: tiles X/Y mod, offset X/Y mod
Connect any grayscale texture to the mod ports and use the mod amount slider to control intensity. Deploying now.
Marian 2:43 PM
arrow still looks very very shitty
Cedric 2:45 PM
Let me look at it myself.
Cedric 2:45 PM
Let me add an SDF Arrow node to see it:
Cedric 2:45 PM
Let me just look at the actual arrow code. The issue is probably the geometry — let me rewrite with a cleaner approach using Inigo Quilez's exact SDF primitives:
Cedric 2:45 PM
I see the problem — the defaults produce a weirdly proportioned arrow.
Let me completely rewrite this with better defaults and a cleaner construction — a proper vector arrow like you'd see in design tools:
headLength: 0.35 means 35% of the total length is head, with the rest being a thin shaft (shaftWidth: 0.025). It looks like a stick with a small triangle on top, not a proper arrow.Let me completely rewrite this with better defaults and a cleaner construction — a proper vector arrow like you'd see in design tools:
Cedric 2:45 PM
Completely rebuilt the arrow. Key changes:
Better defaults: shaft width 0.04 (was 0.025), head length 0.12 as absolute value (was 0.35 as proportion of total — confusing), head width 0.1. Should look like a proper arrow out of the box now.
4 styles:
• Chevron (default) — classic arrow with rectangular shaft + triangular head
• Filled — same but fills the gap between shaft and head wings
• Thin — stroke-only: line shaft with chevron tip (uses sdSegment for clean strokes)
• Double — two stacked chevron heads with a shaft
Head length is now absolute, not a proportion. Much more intuitive to control.
Deploying now.
Better defaults: shaft width 0.04 (was 0.025), head length 0.12 as absolute value (was 0.35 as proportion of total — confusing), head width 0.1. Should look like a proper arrow out of the box now.
4 styles:
• Chevron (default) — classic arrow with rectangular shaft + triangular head
• Filled — same but fills the gap between shaft and head wings
• Thin — stroke-only: line shaft with chevron tip (uses sdSegment for clean strokes)
• Double — two stacked chevron heads with a shaft
Head length is now absolute, not a proportion. Much more intuitive to control.
Deploying now.
Marian 4:06 PM
hate it. delete
Cedric 4:07 PM
Gone. Deploying.
Marian 4:12 PM
Blur and other operators have almost no inputs. Like why can i not modulate blur radius by some input?
Cedric 4:13 PM
Fair point. Let me audit all operators and add mod inputs where they make sense.
Cedric 4:13 PM
Big list. Let me prioritize — the most impactful ones to modulate are the ones where spatial variation creates interesting effects. I'll spawn a sub-agent for this bulk work:
Cedric 4:13 PM
Spawned a sub-agent to add mod inputs to 26 operator nodes. This covers:
• Filters: blur, boxBlur, sharpen, edgeDetect, emboss, directionalBlur
• Color: hslAdjust, levels, posterize, threshold
• Distortion: warp, twirl, lensDistortion, directionalWarp, radialBlur
• Compositing: blend, normalMap
• Transform: transform2d
• SDF ops: smoothUnion/Subtract/Intersect, outline, annular, offset, repeat, toMask
Every float param on these nodes will get a grayscale mod input. Should be done in ~5 min, then auto-deploys.
• Filters: blur, boxBlur, sharpen, edgeDetect, emboss, directionalBlur
• Color: hslAdjust, levels, posterize, threshold
• Distortion: warp, twirl, lensDistortion, directionalWarp, radialBlur
• Compositing: blend, normalMap
• Transform: transform2d
• SDF ops: smoothUnion/Subtract/Intersect, outline, annular, offset, repeat, toMask
Every float param on these nodes will get a grayscale mod input. Should be done in ~5 min, then auto-deploys.
Cedric 4:19 PM
All 26 operators now have mod inputs on their float params — blur radius, warp strength, HSL adjustments, SDF smoothness, everything. Live on darkwood.sandscape.cc.
Marian 4:45 PM
Go through this channels message including threads. Collect everything important and store in you memories
Cedric 4:47 PM
Let me continue where I left off — reading more channel messages and threads to capture everything important.
Cedric 4:47 PM
No more messages before that — the channel history starts from around Feb 20-21. Let me check for any thread messages I might have missed.
Cedric 4:47 PM
I've now read through the entire channel history. The summary already captured the key points well. Let me update the memory files with everything important.
Cedric 4:47 PM
Now let me push these memory updates.
Cedric 4:47 PM
Done. I've gone through the entire #project-darkwood Slack channel (about 80+ messages from Feb 21) and stored everything important in
Key topics:
• Full timeline of SDF system implementation (auto-conversion, pipeline toggle, dual mask output)
• WebGL state corruption bug (getSdfAsMask clobbering GL state) and fix
• Mask Blend auto-detection enhancement (no dropdown, auto-detect connected inputs)
• Checkerboard transparency background
• Universal params audit (colorConstant exclusion)
• Operator position params added to 6 nodes
• Mod inputs added to all 26 operators
• SDF Arrow saga (3 rewrites → deleted)
• Deploy lesson (always deploy after push)
• Marian's feedback patterns (prefers auto-detection, quick to reject poor quality, expects immediate deploys)
memory/2026-02-21.md. Here's what I captured:Key topics:
• Full timeline of SDF system implementation (auto-conversion, pipeline toggle, dual mask output)
• WebGL state corruption bug (getSdfAsMask clobbering GL state) and fix
• Mask Blend auto-detection enhancement (no dropdown, auto-detect connected inputs)
• Checkerboard transparency background
• Universal params audit (colorConstant exclusion)
• Operator position params added to 6 nodes
• Mod inputs added to all 26 operators
• SDF Arrow saga (3 rewrites → deleted)
• Deploy lesson (always deploy after push)
• Marian's feedback patterns (prefers auto-detection, quick to reject poor quality, expects immediate deploys)
Page 1 of 24 Older