From b89e6ecf6a95461bcf38749e0a3f6ba88b8e731a Mon Sep 17 00:00:00 2001 From: meleki Date: Fri, 2 Oct 2026 16:51:06 +0200 Subject: [PATCH] Shaders: the result of an arithmetic node shows its real type (#219) Behaviors: a port group may bring its own rule; the inspector of a picked link no longer carries Hide link and Delete link. Development: 1676 e2e checks. --- Behaviors.md | 15 +++++++++------ Development.md | 2 +- Shaders.md | 23 +++++++++++++++++++++-- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/Behaviors.md b/Behaviors.md index 3874a9f..4ca70b3 100644 --- a/Behaviors.md +++ b/Behaviors.md @@ -273,7 +273,9 @@ playing use the same two words. changes: a chain of 50 resolves in about 10 ms on the slowest machine measured. An edge that a new type makes invalid is left alone and **drawn in the danger colour**; nothing is disconnected behind your back. All of this is the editor's view — at run time every value - travels the same way either way. + travels the same way either way. A group may bring its own rule (`agree`) in place of "all the + same": the arithmetic nodes of a shader graph use the compiler's, where one colour makes the + result a colour (see [Shaders](Shaders)). - **An edge can outlive its port**, because a derived list loses a key without anything touching the edges: a state deleted in its machine, the `machine` edge cut, a `Start` node or a whole asset removed. Only a setting of the node itself is cleaned up (above) — the other four reach @@ -452,11 +454,12 @@ playing use the same two words. crosses, into the same selection as the nodes and boxes it caught. `Delete` or `Backspace` removes what is picked as one undo step, and a right-click on a line offers *Hide link* and *Delete link* (it speaks about the whole selection, like a box's menu). The inspector shows a - picked link: the node and port at each end and the type it carries, with *Hide link* and - *Delete link* below; for several it says how many. A press counts within 6 screen pixels of - the line, and where two cross the one drawn last wins. A hidden link has no line and is never - picked this way: its mark at the port stays its handle. The port's own menu is unchanged, - *Disconnect* included. The hit test is `editor/graph/edgeHit.ts`, the canvas only asks it. + picked link: the node and port at each end and the type it carries; for several it says how + many. It has no buttons of its own, hiding and deleting live in that menu. A press counts + within 6 screen pixels of the line, and where two cross the one drawn last wins. A hidden link + has no line and is never picked this way: its mark at the port stays its handle. The port's + own menu is unchanged, *Disconnect* included. The hit test is `editor/graph/edgeHit.ts`, the + canvas only asks it. - **The band catches groups and comments too** (#95), and they end up in the *same* selection as the nodes: one drag then moves all of it, one `Delete` removes all of it, one undo takes it back. A box counts only when the band holds **all** of it, where a node counts on touching alone. That diff --git a/Development.md b/Development.md index 5cd71db..bde925b 100644 --- a/Development.md +++ b/Development.md @@ -18,7 +18,7 @@ php tests/php/accounts.test.php # the API's accoun # has and the web server's container has not (SKIP there) php tests/php/snapshots.test.php # the snapshot store (#231), the same way php tests/php/releases.test.php # the release store (#266), the same way -node tools/seed-e2e.mjs && node tools/e2e.mjs # 1673 editor checks, screenshots in /tmp/gm-e2e-*.png +node tools/seed-e2e.mjs && node tools/e2e.mjs # 1676 editor checks, screenshots in /tmp/gm-e2e-*.png GM_STEPS=20 node tools/e2e.mjs # or 1-12, or 6,20 — a subset while working on one step ./e2e.sh start [GM_STEPS] # the same run detached, see below ./e2e.sh status # live progress, or the last run's result diff --git a/Shaders.md b/Shaders.md index b5a0ae1..0880e5c 100644 --- a/Shaders.md +++ b/Shaders.md @@ -52,10 +52,25 @@ the pixels, not about how a sprite stretches. ## The nodes -Every value is either a **number** (a GLSL `float`) or a **colour** (a `vec3`, RGB in 0-1). Ports +Every value is either a **number** (a GLSL `float`) or a **colour** (a `vec3`, RGB in 0-1). Inputs typed `any` take both: with a colour on either side the result is a colour, per channel; a number fed to a colour port is broadcast to all three channels. A colour cannot be fed to a number port. +**A `result` shows the type that really comes out.** It is drawn as a number while only numbers go +in (an unconnected input counts as the number typed on it) and as a colour as soon as a colour +feeds one of the `any` inputs; the pin, the edge leaving it and what it may be plugged into follow. +The inputs themselves stay `any` and are painted as whatever is plugged in. The type travels along +a chain of such nodes, so a `Multiply` fed by a colour makes the `Add` and the `Sin` behind it +colours too. The number inputs of a node (`t` of Mix, `edge` of Step, `exponent` of Pow, `min` and +`max` of Clamp) have no say in it. + +What this changes when wiring: a result that is a colour **no longer lands on a number input** +(the Output's `alpha`, the `t` of a Mix); before, the edge was accepted and the graph then refused +to compile. An edge wired while the result was still a number stays where it is when a colour +arrives behind it: it is drawn in the danger colour, and the node at its end says +*"alpha" needs a number, not a color*. In the other direction nothing is lost: a number may be +plugged into a colour port, straight from a `Number` or a `Luminance` as well. + | Node | Ports | What it does | |---|---|---| | **Texture color** | out `color` | The sprite's own pixel before the shader: its texture tinted by its colour, straight (unpremultiplied). | @@ -204,7 +219,11 @@ quad has four corners and stays a quad (#79 is the vertex-side step that would c `src/core/shader/nodes.ts` is the catalogue, `src/core/shader/compile.ts` turns a graph into the fragment (every node reachable from the Output becomes one local per output, in dependency order; every Property a `uniform float u_`; the walk itself is `src/core/graph/emitGraph.ts`, shared with the -particle compiler), `src/viewport/shaders.ts` wraps the result in a Pixi +particle compiler). The type of a `result` has one source: `liftedType` in the catalogue is what +`emit` declares the local with, and `liftedPortType` (the group's `agree`, see *Ports that carry +one and the same value* in [Behaviors](Behaviors)) is the same rule for the port the editor draws. +A test runs every node with an open result through every mix of numbers and colours and compares +the two. `src/viewport/shaders.ts` wraps the result in a Pixi `Shader` for the sprite's mesh (`GraphShader`, with a vertex stage of its own) and `src/viewport/ShaderLibrary.ts` caches the compiled graph per asset, keyed by a fingerprint of what the fragment depends on — node ids, types, params, declared ports, and which port feeds which — so