Shaders: Clamp is the default edge, and what the sheet itself carries (#81)
1 parent
8916a38cd6
commit
7ed7bc85b5
2 files changed
+15
-7
No files matched your search
+2
-2
@@ -12,7 +12,7 @@ npm run check # typecheck + lint + format:check + tests, the gate CI runs
|
|||||||
# code is lost (tail's is reported), so a red run reads as green
|
# code is lost (tail's is reported), so a red run reads as green
|
||||||
npm run build # writes dist/ and regenerates index.html
|
npm run build # writes dist/ and regenerates index.html
|
||||||
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
./build.sh # the same under `set -o pipefail`, for callers that pipe the output
|
||||||
node tools/seed-e2e.mjs && node tools/e2e.mjs # 784 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 785 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
|
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 start [GM_STEPS] # the same run detached, see below
|
||||||
./e2e.sh status # live progress, or the last run's result
|
./e2e.sh status # live progress, or the last run's result
|
||||||
@@ -151,4 +151,4 @@ widths to find click points. The **render device is not in this repo** — `/dev
|
|||||||
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
|
and a 1 GB `/dev/shm` come from `container.options` in the runner's own `config.yaml`, which
|
||||||
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
|
applies to every job on that runner. Without them chromium falls back to llvmpipe, which gets
|
||||||
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
|
WebGL 1.0 only. Measured in the job container: `ANGLE (Intel, Vulkan 1.3.230, HD Graphics 630)`,
|
||||||
WebGL 2.0, and the same 784 checks as here.
|
WebGL 2.0, and the same 785 checks as here.
|
||||||
+13
-5
@@ -31,7 +31,7 @@ fed to a colour port is broadcast to all three channels. A colour cannot be fed
|
|||||||
| **Sample texture** | in `u`, `v` (number) · out `color`, `alpha` | The picture at another spot, tinted like Texture color. Unconnected, `u` and `v` are this pixel's own. Past the border the picture continues as the Output's *Edge* says. |
|
| **Sample texture** | in `u`, `v` (number) · out `color`, `alpha` | The picture at another spot, tinted like Texture color. Unconnected, `u` and `v` are this pixel's own. Past the border the picture continues as the Output's *Edge* says. |
|
||||||
| **Texture size** | out `width`, `height` | The picture in pixels: of the frame, when the sprite wears one. |
|
| **Texture size** | out `width`, `height` | The picture in pixels: of the frame, when the sprite wears one. |
|
||||||
| **Time** | out `value` | Seconds since the editor started; see *Coordinates and time* below. |
|
| **Time** | out `value` | Seconds since the editor started; see *Coordinates and time* below. |
|
||||||
| **Output** | in `color`, `alpha` (number) | What the sprite is drawn with: the colour, clamped to 0-1, and the opacity, clamped too. Each input left unconnected stays the texture's. One per graph. Its *Edge* setting says how the picture continues past its border when sampled outside it: *Mirror* (the default, and what every picture has without a shader), *Repeat* for tiles, *Clamp* to stretch the border pixel. |
|
| **Output** | in `color`, `alpha` (number) | What the sprite is drawn with: the colour, clamped to 0-1, and the opacity, clamped too. Each input left unconnected stays the texture's. One per graph. Its *Edge* setting says how the picture continues past its border when sampled outside it: *Clamp* (the default) holds the border pixel, *Mirror* turns the picture back on itself, *Repeat* starts it over for tiles. |
|
||||||
| **Property** | out `value` | Declares a number the sprite sets: `Name` is the row below the sprite's Shader dropdown and the uniform in the fragment; `Default`, `Min`, `Max` are the row's range. A name is one word (letters, digits, `_`), unique in the graph. |
|
| **Property** | out `value` | Declares a number the sprite sets: `Name` is the row below the sprite's Shader dropdown and the uniform in the fragment; `Default`, `Min`, `Max` are the row's range. A name is one word (letters, digits, `_`), unique in the graph. |
|
||||||
| **Color** | out `color` | A constant colour, picked in the inspector. |
|
| **Color** | out `color` | A constant colour, picked in the inspector. |
|
||||||
| **Number** | out `value` | A constant number, typed on the node. Handy where the same value feeds more than one input, or where an input has nothing to type on (Luminance, the Output's alpha). |
|
| **Number** | out `value` | A constant number, typed on the node. Handy where the same value feeds more than one input, or where an input has nothing to type on (Luminance, the Output's alpha). |
|
||||||
@@ -81,7 +81,7 @@ behavior can write.
|
|||||||
- **Flip:** `Subtract` with 1 typed in as `a` and `UV.u` as `b`, into `Sample texture.u`.
|
- **Flip:** `Subtract` with 1 typed in as `a` and `UV.u` as `b`, into `Sample texture.u`.
|
||||||
- **Scroll:** `Add` `UV.u` and a Property *offset* (or `Time` times a speed), into
|
- **Scroll:** `Add` `UV.u` and a Property *offset* (or `Time` times a speed), into
|
||||||
`Sample texture.u`. Set the Output's Edge to *Repeat*, so the picture comes round again; with
|
`Sample texture.u`. Set the Output's Edge to *Repeat*, so the picture comes round again; with
|
||||||
*Mirror* it turns back on itself, with *Clamp* the border pixel stretches.
|
*Clamp* (the default) the border pixel stretches, with *Mirror* the picture turns back on itself.
|
||||||
- **Wave:** `UV.u` times 20, `Add` `Time` times 4, `Sin`, times 0.02, `Add` `UV.v`, into
|
- **Wave:** `UV.u` times 20, `Add` `Time` times 4, `Sin`, times 0.02, `Add` `UV.v`, into
|
||||||
`Sample texture.v`.
|
`Sample texture.v`.
|
||||||
- **Pixelate:** `UV.u` times `Texture size.width`, `Divide` by the cell size, `Floor`, times the
|
- **Pixelate:** `UV.u` times `Texture size.width`, `Divide` by the cell size, `Floor`, times the
|
||||||
@@ -97,7 +97,9 @@ once, like any other.
|
|||||||
Measured in the checks (step 28): a `Step` at 0.5 on `u` is red left of the middle and blue right
|
Measured in the checks (step 28): a `Step` at 0.5 on `u` is red left of the middle and blue right
|
||||||
of it, on `v` red above and blue below; on a picture red on the left and green on the right,
|
of it, on `v` red above and blue below; on a picture red on the left and green on the right,
|
||||||
sampling at `1 - u` swaps the halves; `u + 0.5` with Edge *Repeat* shows green on the left and,
|
sampling at `1 - u` swaps the halves; `u + 0.5` with Edge *Repeat* shows green on the left and,
|
||||||
past the border, red again on the right, with *Mirror* green on both sides; with the clock held at
|
past the border, red again on the right, with *Mirror* green on both sides; `u + 0.8` reaches far
|
||||||
|
enough to separate the two remaining modes — with nothing set on the Output the right side is green
|
||||||
|
(*Clamp*), with *Mirror* it is red; with the clock held at
|
||||||
0.2 s and 0.7 s a `Fract` into a `Step` gives red and then blue; released, the pixel of a
|
0.2 s and 0.7 s a `Fract` into a `Step` gives red and then blue; released, the pixel of a
|
||||||
`Fract(Time)` mix changes between two reads with nothing running.
|
`Fract(Time)` mix changes between two reads with nothing running.
|
||||||
|
|
||||||
@@ -142,7 +144,9 @@ and it does not resample. Only sprites wear shaders; text objects do not. The no
|
|||||||
small — no channel split, no colour-typed property, no second picture; each is one node in
|
small — no channel split, no colour-typed property, no second picture; each is one node in
|
||||||
`src/core/shader/nodes.ts` (a `ShaderNodeDef` with an `emit`) and one row in the table above. A
|
`src/core/shader/nodes.ts` (a `ShaderNodeDef` with an `emit`) and one row in the table above. A
|
||||||
picture sampled past its border shows what Edge says, never the sprite's neighbour on the sheet: a
|
picture sampled past its border shows what Edge says, never the sprite's neighbour on the sheet: a
|
||||||
frame is a texture of its own. What no shader can do is draw outside the sprite's rectangle: the
|
frame is a texture of its own. Without a shader the question never comes up — the quad's own
|
||||||
|
coordinates run 0 to 1 and never leave the picture — which is why the default is the mode that
|
||||||
|
matches what you see there: *Clamp*. What no shader can do is draw outside the sprite's rectangle: the
|
||||||
quad has four corners and stays a quad (#79 is the vertex-side step that would change that).
|
quad has four corners and stays a quad (#79 is the vertex-side step that would change that).
|
||||||
|
|
||||||
## In the code
|
## In the code
|
||||||
@@ -165,7 +169,11 @@ The fragment starts with `#version 300 es`: that line is what makes Pixi compile
|
|||||||
GLSL ES 3.00 (`GlProgram` looks for it in the fragment); without it `texture()` is only a
|
GLSL ES 3.00 (`GlProgram` looks for it in the fragment); without it `texture()` is only a
|
||||||
`#define` and `textureSize` does not exist. The Output's Edge is a second cut of the picture with
|
`#define` and `textureSize` does not exist. The Output's Edge is a second cut of the picture with
|
||||||
that address mode (`TextureLibrary.get(ref, edge)`), because WebGL takes the sampler state from the
|
that address mode (`TextureLibrary.get(ref, edge)`), because WebGL takes the sampler state from the
|
||||||
texture source, not from a style the shader hands over. Time is `ShaderLibrary.now()`, held still
|
texture source, not from a style the shader hands over. That cut is only made where it can show:
|
||||||
|
a graph whose `Sample texture` reads nothing but its own pixel draws with the plain sheet, whatever
|
||||||
|
the Edge says, so the common shader costs no second copy of the picture. The sheet itself carries
|
||||||
|
`mirror-repeat` (`SHEET_EDGE`) and cannot carry `clamp-to-edge`: Pixi rewrites that to `repeat` on
|
||||||
|
every texture a Graphics fill draws with. Time is `ShaderLibrary.now()`, held still
|
||||||
by `__gm.shaderTime(seconds)` for the checks; a view that drew a Time shader redraws on every
|
by `__gm.shaderTime(seconds)` for the checks; a view that drew a Time shader redraws on every
|
||||||
editor tick (`WorldViewport.animate`). The rows come from
|
editor tick (`WorldViewport.animate`). The rows come from
|
||||||
`shaderParamDefs(graph)` in `src/core/properties/shaders.ts`; `schemaForAsset` and
|
`shaderParamDefs(graph)` in `src/core/properties/shaders.ts`; `schemaForAsset` and
|
||||||
|
|||||||
Reference in new issue
Block a user