Describe the camera shader (#299)
Shaders gets the camera as a wearer, its measurement and In the code. Scene editing gets the Shader switch, Concepts a pointer, Development the e2e sum 1725.
1 parent
e3775c2ae9
commit
986aad5bd7
4 files changed
+62
-5
No files matched your search
+3
-1
@@ -55,7 +55,9 @@ that is made the main one, with the game camera as an overlay. The main camera d
|
|||||||
of the picture and the zoom of the tab; an overlay camera is fitted into that picture without
|
of the picture and the zoom of the tab; an overlay camera is fitted into that picture without
|
||||||
distortion, so one of the same size and zoom covers it exactly. The mouse is reported through the
|
distortion, so one of the same size and zoom covers it exactly. The mouse is reported through the
|
||||||
main camera (#304 is about asking another). Two cameras switched on without *Overlay* draw as
|
main camera (#304 is about asking another). Two cameras switched on without *Overlay* draw as
|
||||||
before: through the first one only. The Scene tab shows every layer.
|
before: through the first one only. The Scene tab shows every layer. A camera can also wear a
|
||||||
|
shader over its picture (#299, see *Wearing a shader* in [Shaders](Shaders)); it works on that
|
||||||
|
camera's picture alone, before the pictures are laid on top of each other.
|
||||||
Measured in the checks (step 63): a green sprite of an overlay camera at `z` -10 covers a red one
|
Measured in the checks (step 63): a green sprite of an overlay camera at `z` -10 covers a red one
|
||||||
of the main camera at `z` 1000, a `UI` sprite in front of the main camera and a `Default` one in
|
of the main camera at `z` 1000, a `UI` sprite in front of the main camera and a `Default` one in
|
||||||
front of the overlay stay away, and the same holds in the running game.
|
front of the overlay stay away, and the same holds in the running game.
|
||||||
|
|||||||
+1
-1
@@ -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)
|
# 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/snapshots.test.php # the snapshot store (#231), the same way
|
||||||
php tests/php/releases.test.php # the release store (#266), 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 # 1720 editor checks, screenshots in /tmp/gm-e2e-*.png
|
node tools/seed-e2e.mjs && node tools/e2e.mjs # 1725 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
|
||||||
|
|||||||
+4
-2
@@ -78,9 +78,11 @@ side. Names off screen take their row as well, so none jumps while the view pans
|
|||||||
**The eye picks what the Scene tab shows.** Beside *Fit* in the tab's header, the eye opens a list of
|
**The eye picks what the Scene tab shows.** Beside *Fit* in the tab's header, the eye opens a list of
|
||||||
every type that can be placed, Behavior to Tilemap, and per type up to three switches: **Symbol**
|
every type that can be placed, Behavior to Tilemap, and per type up to three switches: **Symbol**
|
||||||
(its icon), **Name** (its name plate) and **Shape**: on a collider its outline, on a tilemap the
|
(its icon), **Name** (its name plate) and **Shape**: on a collider its outline, on a tilemap the
|
||||||
outline of its solid cells, while the map's tiles stay drawn. Sprite,
|
outline of its solid cells, while the map's tiles stay drawn. The Camera row has a **Shader**
|
||||||
|
switch instead, off by default: it lays the main camera's shader over its frame (#299, see
|
||||||
|
[Shaders](Shaders)). Sprite,
|
||||||
Text and Tilemap have no icon, so their Symbol switch is greyed out; their Name switch puts a plate
|
Text and Tilemap have no icon, so their Symbol switch is greyed out; their Name switch puts a plate
|
||||||
centred on the object, and it starts off. Every other switch starts on, which is what the Scene
|
centred on the object, and it starts off. Every other switch but the Shader starts on, which is what the Scene
|
||||||
tab always showed. A hidden icon takes no room on a ring and draws no owner link, and its name then
|
tab always showed. A hidden icon takes no room on a ring and draws no owner link, and its name then
|
||||||
stands centred on the object. A hidden icon or outline cannot be clicked either: the object is
|
stands centred on the object. A hidden icon or outline cannot be clicked either: the object is
|
||||||
still selected in the hierarchy. The list stays open while you switch. The switches are saved with
|
still selected in the hierarchy. The list stays open while you switch. The switches are saved with
|
||||||
|
|||||||
+54
-1
@@ -374,6 +374,35 @@ a text keeps a name it already has (`text`, `fontSize`, `align` …): a shader p
|
|||||||
gets no row. In a `Properties` node the parameters are offered under *Type: Text* as they are under
|
gets no row. In a `Properties` node the parameters are offered under *Type: Text* as they are under
|
||||||
*Type: Sprite*. A shaded text is one draw call, like a shaded sprite.
|
*Type: Sprite*. A shaded text is one draw call, like a shaded sprite.
|
||||||
|
|
||||||
|
**A camera wears one over its whole picture** (#299): post-processing such as a vignette, a colour
|
||||||
|
grade, grey, scanlines, a red flash on a hit or a fade. The camera's *Shader* row sits under
|
||||||
|
*Overlay*, its parameters below it, overridable, animatable and in a `Properties` node under
|
||||||
|
*Type: Camera* like a sprite's. A camera keeps a name it already has (`zoom`, `sees` …). The world
|
||||||
|
the camera sees is drawn into a picture of its frame first, cleared to the scene's background,
|
||||||
|
and the shader draws that picture where the frame stands, so `u`/`v` run from 0 to 1 across the
|
||||||
|
camera's picture. Each camera wears its own, so a change of camera changes the effect, and an
|
||||||
|
overlay camera (#302) wears one over its own see-through picture before it is laid on the main
|
||||||
|
one: a red flash on the game camera leaves the HUD of an overlay camera alone. The row
|
||||||
|
**Shader resolution**, shown while a shader is picked, says how many pixels that picture has:
|
||||||
|
|
||||||
|
- **Screen pixels** (default): as many as the camera's picture covers on screen, so it stays
|
||||||
|
sharp at any game scale.
|
||||||
|
- **Camera pixels**: *View width* x *View height*, scaled up to the game scale without smoothing,
|
||||||
|
for pixel art: a scanline or a blur step per game pixel.
|
||||||
|
|
||||||
|
**Either way a pixel counts as a camera pixel.** `Texture size` is *View width* x *View height*
|
||||||
|
in both, and a `Blur` of 4 reaches 4 camera pixels at any game scale and any size of the window,
|
||||||
|
the same rule a field shader follows with its frame. *Screen pixels* only looks sharper. The frame
|
||||||
|
is the edge, so `Padding` and `Vertex output` do nothing there, as on a field. The Game tab, the
|
||||||
|
running game and the game link (`play.html`) all draw it. In the Scene tab the eye in the header
|
||||||
|
has a **Shader** switch on the Camera row, off by default: switched on, the main camera's shader
|
||||||
|
lies over its frame there, under the symbols, names and gizmos. That picture holds every render
|
||||||
|
layer, since the Scene tab shows all of them. Measured in the checks (step 63): a camera shader
|
||||||
|
that hands the picture through draws the game picture byte for byte at 100%, the right way up; a
|
||||||
|
flat red fills it to the corners while the overlay camera's square keeps its green; `Texture size`
|
||||||
|
reads 640 x 360 in both resolutions with the Game tab fitted to 670 x 377 pixels; and the Scene
|
||||||
|
tab shows the red only with the switch on.
|
||||||
|
|
||||||
## What it costs, and where it stops
|
## What it costs, and where it stops
|
||||||
|
|
||||||
A shader runs in the sprite's own draw: the mesh is drawn once, with the graph's fragment in place
|
A shader runs in the sprite's own draw: the mesh is drawn once, with the graph's fragment in place
|
||||||
@@ -483,6 +512,23 @@ more than the samples save: the radius hardly matters there, at radius 4 one pas
|
|||||||
400 sprites on, and radius 16, with its third draw, is as slow at 800 sprites as radius 8 in one
|
400 sprites on, and radius 16, with its third draw, is as slow at 800 sprites as radius 8 in one
|
||||||
pass. Passes are for wide blurs and large pictures, not for every soft edge.
|
pass. Passes are for wide blurs and large pictures, not for every soft edge.
|
||||||
|
|
||||||
|
A camera shader (#299) is one pass for the whole view. Measured with `tools/perf-camera-shader.mjs`
|
||||||
|
on the same HD 630 in a 1920x1080 window, the Game tab at Fit (1310x679, the picture 1207x679 at
|
||||||
|
*Screen pixels*), plain sprites of 48x48 in the 640x360 camera, in frames per second. At that size
|
||||||
|
the editor holds well under 60 without any shader, and the scene alone moved by up to 5 frames a
|
||||||
|
second from one run to the next, so the hand-through rows are three runs each:
|
||||||
|
|
||||||
|
| sprites | 100 | 400 |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| no camera shader | 35.5 - 41.0 | 29.2 - 33.3 |
|
||||||
|
| hands through, Screen pixels | 35.0 - 41.5 | 31.1 - 34.1 |
|
||||||
|
| hands through, Camera pixels | 33.9 - 35.9 | 30.0 - 31.7 |
|
||||||
|
| Blur 4, Screen pixels (one run, its own scene 41.7 / 37.9) | 33.5 | 33.3 |
|
||||||
|
| Blur 4, Camera pixels (same run) | 33.9 | 33.6 |
|
||||||
|
|
||||||
|
A camera shader that hands the picture through costs less than the scene varies by itself. A Blur
|
||||||
|
of 4 over the whole view cost about 4 to 8 frames a second in its one run, at either resolution.
|
||||||
|
|
||||||
## In the code
|
## In the code
|
||||||
|
|
||||||
`src/core/shader/nodes.ts` is the catalogue, `src/core/shader/compile.ts` turns a graph into the
|
`src/core/shader/nodes.ts` is the catalogue, `src/core/shader/compile.ts` turns a graph into the
|
||||||
@@ -517,7 +563,14 @@ since two graphs often share a pass's program, every shader declares all 8 pass
|
|||||||
uniform group, even an empty one. Otherwise the second graph reads a placeholder and draws white.
|
uniform group, even an empty one. Otherwise the second graph reads a placeholder and draws white.
|
||||||
`Blur` and `Texture size` count the picture's size through the uniform `uPixelScale`: 1 on every
|
`Blur` and `Texture size` count the picture's size through the uniform `uPixelScale`: 1 on every
|
||||||
wearer but a field, where it is the frame's units per pixel of its picture (`unitsPerPixel` in
|
wearer but a field, where it is the frame's units per pixel of its picture (`unitsPerPixel` in
|
||||||
`src/viewport/fieldFrame.ts`).
|
`src/viewport/fieldFrame.ts`), and a camera, where it is camera pixels per pixel of its picture
|
||||||
|
(`pixelScale` in `src/viewport/cameraPicture.ts`).
|
||||||
|
A camera's shader is `CameraShade` (`src/viewport/cameraShade.ts`): every view keeps its masks and
|
||||||
|
objects in one container, which is drawn into the camera's picture with Pixi's `render` and a
|
||||||
|
transform from world units to that picture. The Game tab and the game link then take that container
|
||||||
|
off the stage and let the picture stand in for it; the Scene tab leaves it drawn, since it shows
|
||||||
|
more than the frame, and lays the picture over it below the symbols (`shadingCamera` and
|
||||||
|
`keepsWorldAroundShader` in `WorldViewport`).
|
||||||
`src/viewport/ShaderLibrary.ts` caches the compiled graph per asset, keyed by a fingerprint of what
|
`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
|
the fragment depends on — node ids, types, params, declared ports, and which port feeds which — so
|
||||||
moving, collapsing or folding compiles nothing again; a changed param or link does, once
|
moving, collapsing or folding compiles nothing again; a changed param or link does, once
|
||||||
|
|||||||
Reference in new issue
Block a user