reze-engine 0.55.8 → 0.55.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/engine.d.ts +22 -0
- package/dist/engine.d.ts.map +1 -1
- package/dist/engine.js +193 -27
- package/dist/shaders/passes/composite.d.ts +5 -0
- package/dist/shaders/passes/composite.d.ts.map +1 -1
- package/dist/shaders/passes/composite.js +26 -4
- package/dist/shaders/scene-tap.d.ts +1 -1
- package/dist/shaders/scene-tap.d.ts.map +1 -1
- package/dist/shaders/scene-tap.js +57 -16
- package/package.json +1 -1
- package/src/engine.ts +205 -29
- package/src/shaders/passes/composite.ts +31 -4
- package/src/shaders/scene-tap.ts +62 -16
package/src/shaders/scene-tap.ts
CHANGED
|
@@ -44,10 +44,41 @@
|
|
|
44
44
|
* Clamp-to-edge is what stops a warped offset wrapping the far side of the
|
|
45
45
|
* screen into the picture.
|
|
46
46
|
*/
|
|
47
|
-
export function sceneTapApi(
|
|
47
|
+
export function sceneTapApi(
|
|
48
|
+
group: number,
|
|
49
|
+
tex: number,
|
|
50
|
+
samp: number,
|
|
51
|
+
layers: readonly [number, number, number, number],
|
|
52
|
+
): string {
|
|
48
53
|
return /* wgsl */ `
|
|
49
54
|
@group(${group}) @binding(${tex}) var _rzSceneTex: texture_2d<f32>;
|
|
50
55
|
@group(${group}) @binding(${samp}) var _rzSceneSamp: sampler;
|
|
56
|
+
// The field layers as the other effects left them — see rzSceneFrame. Bound to
|
|
57
|
+
// the pair the others drew into for a filter, and to a 1x1 transparent for
|
|
58
|
+
// everything else: an effect cannot sample the pair it is drawing into.
|
|
59
|
+
@group(${group}) @binding(${layers[0]}) var _rzLayerBgFull: texture_2d<f32>;
|
|
60
|
+
@group(${group}) @binding(${layers[1]}) var _rzLayerFgFull: texture_2d<f32>;
|
|
61
|
+
@group(${group}) @binding(${layers[2]}) var _rzLayerBgHalf: texture_2d<f32>;
|
|
62
|
+
@group(${group}) @binding(${layers[3]}) var _rzLayerFgHalf: texture_2d<f32>;
|
|
63
|
+
|
|
64
|
+
/** Premultiplied OVER, top in front — the composite's rzFieldMerge, restated so
|
|
65
|
+
* this file keeps importing nothing. A resolution boundary is a layer
|
|
66
|
+
* boundary: full res over half, exactly as the composite reads them. */
|
|
67
|
+
fn _rzLayerOver(top: vec4f, bot: vec4f) -> vec4f {
|
|
68
|
+
return vec4f(top.rgb + bot.rgb * (1.0 - top.a), top.a + bot.a * (1.0 - top.a));
|
|
69
|
+
}
|
|
70
|
+
fn _rzLayerBg(uv: vec2f) -> vec4f {
|
|
71
|
+
let p = _rzTapUv(uv);
|
|
72
|
+
return _rzLayerOver(
|
|
73
|
+
clamp(textureSampleLevel(_rzLayerBgFull, _rzSceneSamp, p, 0.0), vec4f(0.0), vec4f(1.0)),
|
|
74
|
+
clamp(textureSampleLevel(_rzLayerBgHalf, _rzSceneSamp, p, 0.0), vec4f(0.0), vec4f(1.0)));
|
|
75
|
+
}
|
|
76
|
+
fn _rzLayerFg(uv: vec2f) -> vec4f {
|
|
77
|
+
let p = _rzTapUv(uv);
|
|
78
|
+
return _rzLayerOver(
|
|
79
|
+
clamp(textureSampleLevel(_rzLayerFgFull, _rzSceneSamp, p, 0.0), vec4f(0.0), vec4f(1.0)),
|
|
80
|
+
clamp(textureSampleLevel(_rzLayerFgHalf, _rzSceneSamp, p, 0.0), vec4f(0.0), vec4f(1.0)));
|
|
81
|
+
}
|
|
51
82
|
|
|
52
83
|
/** uv as the mount gives it (y=0 at the BOTTOM, the shadertoy convention the
|
|
53
84
|
* composite documents) turned into a texture coordinate (y=0 at the top).
|
|
@@ -176,25 +207,40 @@ fn rzSceneDisplay(uv: vec2f) -> vec3f {
|
|
|
176
207
|
}
|
|
177
208
|
|
|
178
209
|
/**
|
|
179
|
-
* The
|
|
180
|
-
*
|
|
181
|
-
*
|
|
182
|
-
*
|
|
183
|
-
*
|
|
184
|
-
*
|
|
185
|
-
*
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
210
|
+
* The frame as it stands: the scene over its background, and both layers of
|
|
211
|
+
* every other field effect, laid down in the order the composite would lay
|
|
212
|
+
* them. One call, and the answer already carries the ground's fade, its
|
|
213
|
+
* opacity, the background showing through both, and whatever the other
|
|
214
|
+
* effects drew — a waveform, a caption, a glow.
|
|
215
|
+
*
|
|
216
|
+
* CALLING THIS MAKES THE EFFECT A FILTER. A filter runs after every other
|
|
217
|
+
* field effect, at full resolution, and what it returns replaces the layers it
|
|
218
|
+
* read: its own output is composed over them in its pass (buildFieldShader),
|
|
219
|
+
* so nothing drawn before it is lost and nothing is drawn twice. Two filters
|
|
220
|
+
* run in document order, each reading the one before. The layers are a
|
|
221
|
+
* pass-order fact — a filter reads the pair the others drew into while it
|
|
222
|
+
* draws into a page of its own (renderFieldPass).
|
|
223
|
+
*
|
|
224
|
+
* This is what a FILTER wants — anything re-rendering the whole frame on a
|
|
225
|
+
* tube, a low-resolution screen, or a card. Reaching for rzSceneDisplay and a
|
|
226
|
+
* depth test instead rebuilds this by hand and gets it wrong in one specific
|
|
227
|
+
* way every time: coverage is not a yes or no, and treating it as one turns
|
|
228
|
+
* every soft edge in the scene into a hard one.
|
|
229
|
+
*
|
|
230
|
+
* NOT INCLUDED: depth of field, and an equirect background (a 360 dome reads
|
|
231
|
+
* as its average rather than its texture).
|
|
192
232
|
*/
|
|
193
233
|
fn rzSceneFrame(uv: vec2f) -> vec3f {
|
|
194
234
|
let a = clamp(rzSceneAlpha(uv), 0.0, 1.0);
|
|
195
235
|
let bg = viewU[2];
|
|
196
|
-
let
|
|
197
|
-
|
|
236
|
+
let bgA = select(0.0, 1.0, bg.w > 0.5);
|
|
237
|
+
// The background layer over the base, the scene over both, the foreground
|
|
238
|
+
// layer over the frame — the composite's own order.
|
|
239
|
+
let lb = _rzLayerBg(uv);
|
|
240
|
+
let under = lb.rgb + bg.rgb * bgA * (1.0 - lb.a);
|
|
241
|
+
let frame = rzSceneDisplay(uv) * a + under * (1.0 - a);
|
|
242
|
+
let lf = _rzLayerFg(uv);
|
|
243
|
+
return lf.rgb + frame * (1.0 - lf.a);
|
|
198
244
|
}
|
|
199
245
|
|
|
200
246
|
/**
|