Die Farbe traegt heute kein Alpha, an keiner Stelle der Kette:
Sprite-color und der Color-Node sind 24-Bit-RGB: colorOf (src/core/model/Properties.ts) klemmt auf 0xffffff, der ColorPicker hat keinen Alpha-Kanal.
Der Shader-Typ vec3 hat drei Kanaele; vec3Literal schreibt RGB.
Alpha kommt nur aus der Textur: der Prelude entpremultipliziert mit texel.a, der Epilog schreibt vec4(clamp(c) * texel.a, texel.a) (src/core/shader/compile.ts). Der Output-Node hat nur color, das Wiki sagt "Its alpha stays the texture's".
Das Sprite selbst hat keine Opacity-Eigenschaft (Schema: width, height, color, texture, shader). Ein Sprite ausblenden geht heute nur ueber Brightness nach Schwarz.
Entscheidung (User)
Klein, Farbe bleibt vec3:
alpha-Eingang (number) am Output-Node. Unverbunden liest er das Texel-Alpha, wie der color-Eingang das Texel liest. Der Epilog wird vec4(clamp(c) * a, a) mit a = clamp(alpha, 0, 1); die Premultiplikation bleibt korrekt.
Texture alpha-Node (out value, number): das Alpha des Texels, damit es in Rechnungen eingehen kann (z. B. Multiply mit einer Property opacity als Fade).
Nicht Teil dieses Issues: vec4-Farbtyp, Sprite-Farbe mit Alpha, eine Sprite-Zeile opacity ohne Render-Pass (waere die billigere Loesung fuer den haeufigsten Fall "Fade" und ein eigenes Thema).
Beweis
Unit-Tests in shaders.test.ts: Epilog mit und ohne verbundenem alpha; Texture alpha emittiert texel.a.
e2e in Modul 28: Property opacity 0.5 an Texture alpha -> Multiply -> Output.alpha, Pixel ueber Hintergrund halb gemischt; auf 1 zurueck byte-gleich mit vorher.
Wiki Shaders: Node-Tabelle und der Satz am Output.
## Befund (gemessen 2026-09-13)
Die Farbe traegt heute **kein Alpha**, an keiner Stelle der Kette:
- Sprite-`color` und der `Color`-Node sind 24-Bit-RGB: `colorOf` (`src/core/model/Properties.ts`) klemmt auf `0xffffff`, der `ColorPicker` hat keinen Alpha-Kanal.
- Der Shader-Typ `vec3` hat drei Kanaele; `vec3Literal` schreibt RGB.
- Alpha kommt nur aus der Textur: der Prelude entpremultipliziert mit `texel.a`, der Epilog schreibt `vec4(clamp(c) * texel.a, texel.a)` (`src/core/shader/compile.ts`). Der `Output`-Node hat nur `color`, das Wiki sagt "Its alpha stays the texture's".
- Das Sprite selbst hat keine Opacity-Eigenschaft (Schema: width, height, color, texture, shader). Ein Sprite ausblenden geht heute nur ueber Brightness nach Schwarz.
## Entscheidung (User)
**Klein, Farbe bleibt `vec3`:**
1. **`alpha`-Eingang (number) am `Output`-Node.** Unverbunden liest er das Texel-Alpha, wie der `color`-Eingang das Texel liest. Der Epilog wird `vec4(clamp(c) * a, a)` mit `a = clamp(alpha, 0, 1)`; die Premultiplikation bleibt korrekt.
2. **`Texture alpha`-Node** (out `value`, number): das Alpha des Texels, damit es in Rechnungen eingehen kann (z. B. `Multiply` mit einer Property `opacity` als Fade).
Nicht Teil dieses Issues: vec4-Farbtyp, Sprite-Farbe mit Alpha, eine Sprite-Zeile `opacity` ohne Render-Pass (waere die billigere Loesung fuer den haeufigsten Fall "Fade" und ein eigenes Thema).
## Beweis
- Unit-Tests in `shaders.test.ts`: Epilog mit und ohne verbundenem `alpha`; `Texture alpha` emittiert `texel.a`.
- e2e in Modul 28: Property `opacity` 0.5 an `Texture alpha` -> `Multiply` -> `Output.alpha`, Pixel ueber Hintergrund halb gemischt; auf 1 zurueck byte-gleich mit vorher.
- Wiki *Shaders*: Node-Tabelle und der Satz am Output.
meleki
added the shader label 2026-09-13 11:29:47 +02:00
Built, exactly the cut from the issue, colour stays vec3:
Output gains a number input alpha. Unconnected it reads the texel's alpha, like color reads the texel. Epilogue: float alpha = clamp(..., 0, 1); finalColor = vec4(clamp(c) * alpha, alpha) - premultiplication stays correct.
New Texture alpha node (out value = texel.a) so alpha can enter maths.
Wiki Shaders: fade recipe (property opacity 0-1 default 1, times Texture alpha, into Output.alpha; a behavior writes opacity per frame).
Not part of this issue, as agreed: a sprite row opacity without a render pass.
One finding that shaped the build:isInlinePort makes every number port inline, only vec3 hangs off the field. An alpha port without a field would have got an input box defaulting to 0 and the compiler would have read that 0 - every shaded sprite invisible. Hence PortDef.inline?: boolean (false = nothing to type, the node's own rule applies) and a typed texel fallback in the compiler: colour port -> rgb, number port -> texel.a.
Proof:
./check.sh: === CHECK EXIT 0 ===, 851 tests (was 850); inlineInputs(ShaderOutput) is empty is pinned by a test.
e2e step 28 alone: ALL PASSED - 33 checks (was 29) against the final bundle.
Pixels: red shader over background #22252c: opacity 0 -> #22252c, opacity 0.5 -> #901216 vs computed #911316, opacity 1 -> byte-identical with before.
Counter-checks, each bites at its own spot: inline: false removed -> field test fails (['alpha']); fallback colour-only -> two tests fail (rgb slides into the epilogue as alpha); alpha input ignored in the browser -> "opacity 0 shows what is behind" fails with behind: #ff0000.
Full suite runs on CI after the push; the 703 in README/wiki is computed (699 + 4) and gets read against the run.
Done in `3da0ef1` (repo) and `7eac624` (wiki).
**Built, exactly the cut from the issue, colour stays `vec3`:**
- `Output` gains a number input `alpha`. Unconnected it reads the texel's alpha, like `color` reads the texel. Epilogue: `float alpha = clamp(..., 0, 1); finalColor = vec4(clamp(c) * alpha, alpha)` - premultiplication stays correct.
- New `Texture alpha` node (out `value` = `texel.a`) so alpha can enter maths.
- Wiki *Shaders*: fade recipe (property `opacity` 0-1 default 1, times `Texture alpha`, into `Output.alpha`; a behavior writes `opacity` per frame).
- Not part of this issue, as agreed: a sprite row `opacity` without a render pass.
**One finding that shaped the build:** `isInlinePort` makes every `number` port inline, only `vec3` hangs off the `field`. An `alpha` port without a field would have got an input box defaulting to 0 and the compiler would have read that 0 - every shaded sprite invisible. Hence `PortDef.inline?: boolean` (`false` = nothing to type, the node's own rule applies) and a typed texel fallback in the compiler: colour port -> `rgb`, number port -> `texel.a`.
**Proof:**
- `./check.sh`: `=== CHECK EXIT 0 ===`, 851 tests (was 850); `inlineInputs(ShaderOutput)` is empty is pinned by a test.
- e2e step 28 alone: `ALL PASSED - 33 checks` (was 29) against the final bundle.
- Pixels: red shader over background `#22252c`: opacity 0 -> `#22252c`, opacity 0.5 -> `#901216` vs computed `#911316`, opacity 1 -> byte-identical with before.
- Counter-checks, each bites at its own spot: `inline: false` removed -> field test fails (`['alpha']`); fallback colour-only -> two tests fail (rgb slides into the epilogue as alpha); alpha input ignored in the browser -> "opacity 0 shows what is behind" fails with `behind: #ff0000`.
- Full suite runs on CI after the push; the 703 in README/wiki is computed (699 + 4) and gets read against the run.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Befund (gemessen 2026-09-13)
Die Farbe traegt heute kein Alpha, an keiner Stelle der Kette:
colorund derColor-Node sind 24-Bit-RGB:colorOf(src/core/model/Properties.ts) klemmt auf0xffffff, derColorPickerhat keinen Alpha-Kanal.vec3hat drei Kanaele;vec3Literalschreibt RGB.texel.a, der Epilog schreibtvec4(clamp(c) * texel.a, texel.a)(src/core/shader/compile.ts). DerOutput-Node hat nurcolor, das Wiki sagt "Its alpha stays the texture's".Entscheidung (User)
Klein, Farbe bleibt
vec3:alpha-Eingang (number) amOutput-Node. Unverbunden liest er das Texel-Alpha, wie dercolor-Eingang das Texel liest. Der Epilog wirdvec4(clamp(c) * a, a)mita = clamp(alpha, 0, 1); die Premultiplikation bleibt korrekt.Texture alpha-Node (outvalue, number): das Alpha des Texels, damit es in Rechnungen eingehen kann (z. B.Multiplymit einer Propertyopacityals Fade).Nicht Teil dieses Issues: vec4-Farbtyp, Sprite-Farbe mit Alpha, eine Sprite-Zeile
opacityohne Render-Pass (waere die billigere Loesung fuer den haeufigsten Fall "Fade" und ein eigenes Thema).Beweis
shaders.test.ts: Epilog mit und ohne verbundenemalpha;Texture alphaemittierttexel.a.opacity0.5 anTexture alpha->Multiply->Output.alpha, Pixel ueber Hintergrund halb gemischt; auf 1 zurueck byte-gleich mit vorher.Done in
3da0ef1(repo) and7eac624(wiki).Built, exactly the cut from the issue, colour stays
vec3:Outputgains a number inputalpha. Unconnected it reads the texel's alpha, likecolorreads the texel. Epilogue:float alpha = clamp(..., 0, 1); finalColor = vec4(clamp(c) * alpha, alpha)- premultiplication stays correct.Texture alphanode (outvalue=texel.a) so alpha can enter maths.opacity0-1 default 1, timesTexture alpha, intoOutput.alpha; a behavior writesopacityper frame).opacitywithout a render pass.One finding that shaped the build:
isInlinePortmakes everynumberport inline, onlyvec3hangs off thefield. Analphaport without a field would have got an input box defaulting to 0 and the compiler would have read that 0 - every shaded sprite invisible. HencePortDef.inline?: boolean(false= nothing to type, the node's own rule applies) and a typed texel fallback in the compiler: colour port ->rgb, number port ->texel.a.Proof:
./check.sh:=== CHECK EXIT 0 ===, 851 tests (was 850);inlineInputs(ShaderOutput)is empty is pinned by a test.ALL PASSED - 33 checks(was 29) against the final bundle.#22252c: opacity 0 ->#22252c, opacity 0.5 ->#901216vs computed#911316, opacity 1 -> byte-identical with before.inline: falseremoved -> field test fails (['alpha']); fallback colour-only -> two tests fail (rgb slides into the epilogue as alpha); alpha input ignored in the browser -> "opacity 0 shows what is behind" fails withbehind: #ff0000.