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
|
||||
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
|
||||
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
|
||||
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.
|
||||
|
||||
+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)
|
||||
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 # 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
|
||||
./e2e.sh start [GM_STEPS] # the same run detached, see below
|
||||
./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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
+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
|
||||
*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
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
`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.
|
||||
`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
|
||||
`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
|
||||
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
|
||||
|
||||
Reference in new issue
Block a user