@weft-js/plugin-surface-keel 0.1.0 → 0.1.3

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.
@@ -0,0 +1,530 @@
1
+ import './indexed-render.mjs';
2
+ import {
3
+ adaptTargetPalette,
4
+ cameraBasis,
5
+ targetProfile,
6
+ } from './core-primitives.mjs';
7
+ import {
8
+ FULLSCREEN_VS,
9
+ MAX_BOXES,
10
+ MAX_CAPS,
11
+ MAX_COLOURS,
12
+ MAX_MATERIALS,
13
+ MAX_RAMPS,
14
+ MAX_WEDGES,
15
+ PALETTE_WIDTH,
16
+ POINTS_FS,
17
+ POINTS_VS,
18
+ SCREEN_TILE,
19
+ SKY_MAT,
20
+ WORLD_FS,
21
+ resolveFx,
22
+ toggleFxList,
23
+ } from './effects-world.mjs';
24
+ import {
25
+ DEPTH_FS,
26
+ DIRECT_PIXEL_FS,
27
+ PIXEL_FS,
28
+ smoothPixelFs,
29
+ unpackDepth,
30
+ } from './pixel-raster.mjs';
31
+ import {
32
+ RESOLVE_FS,
33
+ createIndexedPass,
34
+ dot2,
35
+ norm3,
36
+ program,
37
+ supersampleFor,
38
+ uploadWorld,
39
+ } from './indexed-render.mjs';
40
+
41
+
42
+ function prepareRender(__state, __frame) {
43
+ { const { world, pixel, points } = __state.colourPrograms(); __frame.world = world; __frame.pixel = pixel; __frame.points = points; }
44
+ __frame.fx = __state.fxDirty || !__state.fxU ? __state.refreshFx() : __state.fxU;
45
+ __frame.timing = false;
46
+ if (__state.timer) {
47
+ if (__state.query && __state.gl.getQueryParameter(__state.query, __state.gl.QUERY_RESULT_AVAILABLE)) {
48
+ if (!__state.gl.getParameter(__state.timer.GPU_DISJOINT_EXT)) __state.gpuMs = __state.gl.getQueryParameter(__state.query, __state.gl.QUERY_RESULT) / 1e6;
49
+ __state.gl.deleteQuery(__state.query);
50
+ __state.query = null;
51
+ }
52
+ if (!__state.query) {
53
+ __state.query = __state.gl.createQuery();
54
+ __state.gl.beginQuery(__state.timer.TIME_ELAPSED_EXT, __state.query);
55
+ __frame.timing = true;
56
+ }
57
+ }
58
+ { const { forward: fwd, right, up } = cameraBasis(__frame.eye, __frame.look); __frame.fwd = fwd; __frame.right = right; __frame.up = up; }
59
+ __frame.tanF = Math.tan(__frame.fov / 2);
60
+ __frame.sunN = norm3(__frame.sun);
61
+ __frame.k = __state.edges === "smooth" && __state.activeProfile.kind === "native" ? supersampleFor(__state.W2, __state.H, __state.supersample) : 1;
62
+ __frame.F = __frame.k > 1 ? __state.fineBuffers(__frame.k) : null;
63
+ __state.lastK = __frame.k;
64
+ __state.RW = __frame.F ? __frame.F.w : __state.W2;
65
+ __state.RH = __frame.F ? __frame.F.h : __state.H;
66
+ __state.rfbo = __frame.F ? __frame.F.fbo : __state.fbo;
67
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, __state.rfbo);
68
+ __state.gl.viewport(0, 0, __state.RW, __state.RH);
69
+ __state.gl.enable(__state.gl.DEPTH_TEST);
70
+ __state.gl.depthFunc(__state.gl.ALWAYS);
71
+ __state.gl.clear(__state.gl.COLOR_BUFFER_BIT | __state.gl.DEPTH_BUFFER_BIT);
72
+ __frame.U = __frame.world.loc;
73
+ __state.gl.useProgram(__frame.world.p);
74
+ __state.gl.uniform2f(__frame.U.uRes, __state.RW, __state.RH);
75
+ __state.gl.uniform3fv(__frame.U.uEye, __frame.eye);
76
+ __state.gl.uniform3fv(__frame.U.uFwd, __frame.fwd);
77
+ __state.gl.uniform3fv(__frame.U.uRight, __frame.right);
78
+ __state.gl.uniform3fv(__frame.U.uUp, __frame.up);
79
+ __state.gl.uniform1f(__frame.U.uTan, __frame.tanF);
80
+ __state.gl.uniform1f(__frame.U.uTime, __frame.time);
81
+ __state.gl.uniform1i(__frame.U.uBoxes, __state.nBoxes);
82
+ __state.gl.uniform1i(__frame.U.uWedges, __state.nWedges);
83
+ __state.gl.uniform1i(__frame.U.uCaps, __state.nCaps);
84
+ for (const blk of __state.blocks) __state.gl.bindBufferBase(__state.gl.UNIFORM_BUFFER, blk.i, blk.buf);
85
+ __state.gl.activeTexture(__state.gl.TEXTURE1);
86
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.matTex);
87
+ __state.gl.uniform1i(__frame.U.uMats, 1);
88
+ __state.gl.uniform3fv(__frame.U.uSun, __frame.sunN);
89
+ __state.gl.uniform1f(__frame.U.uWaterY, __frame.waterY);
90
+ __state.gl.uniform1f(__frame.U.uFogNear, __frame.fogNear);
91
+ __state.gl.uniform1f(__frame.U.uFogFar, __frame.fogFar);
92
+ }
93
+
94
+ function drawRender(__state, __frame) {
95
+ if (__frame.raster?.world === false) {
96
+ __state.gl.clearBufferfv(__state.gl.COLOR, 0, [0.5, (__state.matRows[SKY_MAT * 4] ?? 0) / 255, SKY_MAT / 255, 1]);
97
+ __state.gl.clearBufferfv(__state.gl.COLOR, 1, [0, 1, 0, 0]);
98
+ } else {
99
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, __state.quad);
100
+ const aw = __state.gl.getAttribLocation(__frame.world.p, "aPos");
101
+ __state.gl.enableVertexAttribArray(aw);
102
+ __state.gl.vertexAttribPointer(aw, 2, __state.gl.FLOAT, false, 0, 0);
103
+ __state.gl.drawArrays(__state.gl.TRIANGLES, 0, 3);
104
+ }
105
+ if (__frame.particles.length) {
106
+ __state.gl.depthFunc(__state.gl.LESS);
107
+ const data = new Float32Array(__frame.particles.length * 7);
108
+ __frame.particles.forEach((q, i) => data.set([q.p[0], q.p[1], q.p[2], q.size ?? 1, q.light ?? 0.8, (q.ramp === void 0 ? void 0 : __state.rampIndex.get(q.ramp)) ?? 0, q.glow ?? 0], i * 7));
109
+ __state.gl.useProgram(__frame.points.p);
110
+ const P = __frame.points.loc;
111
+ __state.gl.uniform3fv(P.uEye, __frame.eye);
112
+ __state.gl.uniform3fv(P.uFwd, __frame.fwd);
113
+ __state.gl.uniform3fv(P.uRight, __frame.right);
114
+ __state.gl.uniform3fv(P.uUp, __frame.up);
115
+ __state.gl.uniform1f(P.uTan, __frame.tanF);
116
+ __state.gl.uniform1f(P.uAspect, __state.RW / __state.RH);
117
+ __state.gl.uniform1f(P.uH, __state.RH);
118
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, __state.pbuf);
119
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, data, __state.gl.DYNAMIC_DRAW);
120
+ const a0 = __state.gl.getAttribLocation(__frame.points.p, "aPos");
121
+ const a1 = __state.gl.getAttribLocation(__frame.points.p, "aLook");
122
+ __state.gl.enableVertexAttribArray(a0);
123
+ __state.gl.vertexAttribPointer(a0, 4, __state.gl.FLOAT, false, 28, 0);
124
+ __state.gl.enableVertexAttribArray(a1);
125
+ __state.gl.vertexAttribPointer(a1, 3, __state.gl.FLOAT, false, 28, 16);
126
+ __state.gl.drawArrays(__state.gl.POINTS, 0, __frame.particles.length);
127
+ __state.gl.disableVertexAttribArray(a1);
128
+ }
129
+ if (__frame.raster) __state.drawRaster(__frame.raster, __frame.eye, __frame.fwd, __frame.right, __frame.up, __frame.tanF, __frame.sunN, __frame.waterY, __frame.fogNear, __frame.fogFar, __frame.time);
130
+ __state.gl.disable(__state.gl.DEPTH_TEST);
131
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, __frame.F ? __frame.F.colourFbo : null);
132
+ __state.gl.viewport(0, 0, __state.RW, __state.RH);
133
+ __frame.pass2 = __frame.F ? __frame.raster?.draw ? __state.smoothDirectP ??= program(__state.gl, FULLSCREEN_VS, smoothPixelFs(DIRECT_PIXEL_FS)) : __state.smoothPixelP ??= program(__state.gl, FULLSCREEN_VS, smoothPixelFs(PIXEL_FS)) : __frame.raster?.draw ? __state.directPixelP ??= program(__state.gl, FULLSCREEN_VS, DIRECT_PIXEL_FS) : __frame.pixel;
134
+ __state.gl.useProgram(__frame.pass2.p);
135
+ __frame.X = __frame.pass2.loc;
136
+ __frame.T = [[__frame.F ? __frame.F.data : __state.dataTex, "uData"], [__frame.F ? __frame.F.data2 : __state.data2Tex, "uData2"], [__frame.F ? __frame.F.depth : __state.depthTex, "uDepth"], [__state.palTex, "uPalette"], [__state.rampTex, "uRamps"], [__state.screenTex, "uScreenTex"]];
137
+ __frame.T.forEach(([t, name], i) => {
138
+ __state.gl.activeTexture(__state.gl.TEXTURE0 + i);
139
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, t);
140
+ __state.gl.uniform1i(__frame.X[name], i);
141
+ });
142
+ __frame.u = __frame.fx.u;
143
+ __state.gl.uniform1i(__frame.X.uScreen, __frame.u.uScreen);
144
+ __state.gl.uniform1f(__frame.X.uDither, __frame.u.uDither);
145
+ __state.gl.uniform1f(__frame.X.uTime, __frame.time);
146
+ __state.gl.uniform3fv(__frame.X.uOutline, __frame.u.uOutline);
147
+ __state.gl.uniform1i(__frame.X.uOutlineInk, __frame.u.uOutlineInk);
148
+ }
149
+
150
+ function composeRender(__state, __frame) {
151
+ __state.gl.uniform4fv(__frame.X.uFog, __frame.u.uFog);
152
+ __state.gl.uniform2fv(__frame.X.uFogLook, __frame.u.uFogLook);
153
+ __state.gl.uniform4fv(__frame.X.uGlow, __frame.u.uGlow);
154
+ __state.gl.uniform2fv(__frame.X.uGlowK, __frame.u.uGlowK);
155
+ __state.gl.uniform4fv(__frame.X.uVig, __frame.u.uVig);
156
+ __state.gl.uniform4fv(__frame.X.uScan, __frame.u.uScan);
157
+ __state.gl.uniform4fv(__frame.X.uCrt, __frame.u.uCrt);
158
+ __state.gl.uniform4fv(__frame.X.uRim, __frame.u.uRim);
159
+ __frame.rd = __frame.u.uRimDir;
160
+ if (!__frame.rd) {
161
+ const sx = dot2(__frame.sunN, __frame.right);
162
+ const sy = dot2(__frame.sunN, __frame.up);
163
+ const l = Math.hypot(sx, sy);
164
+ __frame.rd = l > 1e-3 ? [sx / l, sy / l] : [0, 1];
165
+ }
166
+ __state.gl.uniform2fv(__frame.X.uRimDir, __frame.rd);
167
+ __state.gl.uniform4fv(__frame.X.uFlash, __frame.u.uFlash);
168
+ __state.gl.uniform4iv(__frame.X.uFlashMats, __frame.u.uFlashMats);
169
+ __state.gl.uniform2fv(__frame.X.uGrade, __frame.u.uGrade);
170
+ __state.gl.uniform1i(__frame.X.uCycle, __frame.u.uCycle);
171
+ if (__frame.F) __state.gl.uniform1i(__frame.X.uSS, __frame.k);
172
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, __state.quad);
173
+ __frame.ap = __state.gl.getAttribLocation(__frame.pass2.p, "aPos");
174
+ __state.gl.enableVertexAttribArray(__frame.ap);
175
+ __state.gl.vertexAttribPointer(__frame.ap, 2, __state.gl.FLOAT, false, 0, 0);
176
+ __state.gl.drawArrays(__state.gl.TRIANGLES, 0, 3);
177
+ if (__frame.F) {
178
+ const rp = __state.resolveP ??= program(__state.gl, FULLSCREEN_VS, RESOLVE_FS);
179
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, null);
180
+ __state.gl.viewport(0, 0, __state.W2, __state.H);
181
+ __state.gl.useProgram(rp.p);
182
+ __state.gl.activeTexture(__state.gl.TEXTURE0);
183
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __frame.F.colour);
184
+ __state.gl.uniform1i(rp.loc.uColour, 0);
185
+ __state.gl.uniform1i(rp.loc.uSS, __frame.k);
186
+ const ar = __state.gl.getAttribLocation(rp.p, "aPos");
187
+ __state.gl.enableVertexAttribArray(ar);
188
+ __state.gl.vertexAttribPointer(ar, 2, __state.gl.FLOAT, false, 0, 0);
189
+ __state.gl.drawArrays(__state.gl.TRIANGLES, 0, 3);
190
+ }
191
+ if (__frame.depthOut) __state.writeDepthOut(__frame.depthOut);
192
+ if (__frame.timing && __state.timer) __state.gl.endQuery(__state.timer.TIME_ELAPSED_EXT);
193
+ }
194
+
195
+ function initializeGraphics(__state) {
196
+ __state.ctx = __state.canvas.getContext("webgl2", { antialias: false, preserveDrawingBuffer: true });
197
+ if (!__state.ctx) throw new Error("WebGL2 is not available");
198
+ __state.gl = __state.ctx;
199
+ __state.worldP = null;
200
+ __state.pixelP = null;
201
+ __state.pointsP = null;
202
+ __state.directPixelP = null;
203
+ __state.colourPrograms = () => {
204
+ if (!__state.worldP) {
205
+ const w = program(__state.gl, FULLSCREEN_VS, WORLD_FS);
206
+ if (__state.bakeOnly) ["Boxes", "Wedges", "Capsules"].forEach((name, i) => __state.gl.uniformBlockBinding(w.p, __state.gl.getUniformBlockIndex(w.p, name), i));
207
+ __state.worldP = w;
208
+ __state.pixelP = program(__state.gl, FULLSCREEN_VS, PIXEL_FS);
209
+ __state.pointsP = program(__state.gl, POINTS_VS, POINTS_FS);
210
+ }
211
+ return { world: __state.worldP, pixel: __state.pixelP, points: __state.pointsP };
212
+ };
213
+ if (!__state.bakeOnly) __state.colourPrograms();
214
+ __state.quad = __state.gl.createBuffer();
215
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, __state.quad);
216
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), __state.gl.STATIC_DRAW);
217
+ __state.pbuf = __state.gl.createBuffer();
218
+ __state.nearest = () => {
219
+ for (const [k, v] of [[__state.gl.TEXTURE_MIN_FILTER, __state.gl.NEAREST], [__state.gl.TEXTURE_MAG_FILTER, __state.gl.NEAREST], [__state.gl.TEXTURE_WRAP_S, __state.gl.CLAMP_TO_EDGE], [__state.gl.TEXTURE_WRAP_T, __state.gl.CLAMP_TO_EDGE]]) __state.gl.texParameteri(__state.gl.TEXTURE_2D, k, v);
220
+ };
221
+ __state.floatTex = (w, h, data = null) => {
222
+ const t = __state.gl.createTexture();
223
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, t);
224
+ __state.gl.texImage2D(__state.gl.TEXTURE_2D, 0, __state.gl.RGBA32F, w, h, 0, __state.gl.RGBA, __state.gl.FLOAT, data);
225
+ __state.nearest();
226
+ return t;
227
+ };
228
+ __state.W2 = __state.width;
229
+ __state.H = __state.height;
230
+ __state.fbo = null;
231
+ __state.dataTex = null;
232
+ __state.data2Tex = null;
233
+ __state.depthTex = null;
234
+ __state.blocks = [["Boxes", 2 * MAX_BOXES], ["Wedges", 3 * MAX_WEDGES], ["Capsules", 2 * MAX_CAPS]].map(([name, vecs], i) => {
235
+ const data = new Float32Array(vecs * 4);
236
+ const buf = __state.gl.createBuffer();
237
+ __state.gl.bindBuffer(__state.gl.UNIFORM_BUFFER, buf);
238
+ __state.gl.bufferData(__state.gl.UNIFORM_BUFFER, data.byteLength, __state.gl.DYNAMIC_DRAW);
239
+ if (__state.worldP) __state.gl.uniformBlockBinding(__state.worldP.p, __state.gl.getUniformBlockIndex(__state.worldP.p, name), i);
240
+ return { data, buf, i };
241
+ });
242
+ { const [boxBlock, wedgeBlock, capBlock] = __state.blocks; __state.boxBlock = boxBlock; __state.wedgeBlock = wedgeBlock; __state.capBlock = capBlock; }
243
+ __state.rampRows = new Float32Array(MAX_RAMPS * 2 * 4);
244
+ __state.rampTex = __state.floatTex(MAX_RAMPS, 2, __state.rampRows);
245
+ __state.matRows = new Float32Array(256 * 4);
246
+ __state.matTex = __state.floatTex(256, 1, __state.matRows);
247
+ __state.screenTex = __state.gl.createTexture();
248
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.screenTex);
249
+ __state.gl.texImage2D(__state.gl.TEXTURE_2D, 0, __state.gl.R8, SCREEN_TILE, SCREEN_TILE, 0, __state.gl.RED, __state.gl.UNSIGNED_BYTE, new Uint8Array(SCREEN_TILE * SCREEN_TILE));
250
+ __state.nearest();
251
+ }
252
+
253
+ function initializePaletteAndEffects(__state) {
254
+ __state.screenLoaded = null;
255
+ __state.timer = __state.gl.getExtension("EXT_disjoint_timer_query_webgl2");
256
+ __state.query = null;
257
+ __state.gpuMs = null;
258
+ __state.palTex = null;
259
+ __state.palette = [];
260
+ __state.rampIndex = new Map();
261
+ __state.rampList = [];
262
+ __state.nBoxes = 0;
263
+ __state.nWedges = 0;
264
+ __state.nCaps = 0;
265
+ __state.style = { screen: 4, dither: 0.9, outline: 1 };
266
+ __state.activeProfile = targetProfile("native");
267
+ __state.authoredSize = [__state.width, __state.height];
268
+ __state.authoredStyle = { ...__state.style };
269
+ __state.authoredPalette = [];
270
+ __state.authoredRamps = {};
271
+ __state.fxList = [];
272
+ __state.fxResolved = [];
273
+ __state.fxU = null;
274
+ __state.fxDirty = true;
275
+ __state.target(__state.W2, __state.H);
276
+ __state.edges = "smooth";
277
+ __state.supersample = "auto";
278
+ __state.lastK = 1;
279
+ __state.fine = null;
280
+ __state.smoothPixelP = null;
281
+ __state.smoothDirectP = null;
282
+ __state.resolveP = null;
283
+ __state.smoothDepthOutP = null;
284
+ __state.RW = __state.W2;
285
+ __state.RH = __state.H;
286
+ __state.rfbo = null;
287
+ }
288
+
289
+ function initializeIndexedBuffers(__state) {
290
+ __state.indexed = createIndexedPass({
291
+ gl: __state.gl,
292
+ quad: __state.quad,
293
+ matTex: __state.matTex,
294
+ blocks: __state.blocks,
295
+ get width() {
296
+ return __state.W2;
297
+ },
298
+ get height() {
299
+ return __state.H;
300
+ },
301
+ get fbo() {
302
+ return __state.fbo;
303
+ },
304
+ get dataTex() {
305
+ return __state.dataTex;
306
+ },
307
+ get data2Tex() {
308
+ return __state.data2Tex;
309
+ },
310
+ get depthTex() {
311
+ return __state.depthTex;
312
+ },
313
+ counts: { get boxes() {
314
+ return __state.nBoxes;
315
+ }, get wedges() {
316
+ return __state.nWedges;
317
+ }, get capsules() {
318
+ return __state.nCaps;
319
+ } }
320
+ }, () => program(__state.gl, FULLSCREEN_VS, DEPTH_FS));
321
+ { const { mode: bakeMode, pass, readTarget } = __state.indexed; __state.bakeMode = bakeMode; __state.pass = pass; __state.readTarget = readTarget; }
322
+ __state.rasterState = null;
323
+ __state.rasterStats = { meshes: 0, triangles: 0, instances: 0, meshBytes: 0 };
324
+ }
325
+
326
+ function makeSetTarget(__state) {
327
+ return function setTarget(w, h) {
328
+ if (__state.activeProfile.kind === "hardware" && (w !== __state.activeProfile.width || h !== __state.activeProfile.height)) throw new RangeError(`${__state.activeProfile.label} preview requires ${__state.activeProfile.width} \xD7 ${__state.activeProfile.height}`);
329
+ __state.target(Math.max(8, w | 0), Math.max(8, h | 0));
330
+ if (__state.activeProfile.kind === "native") __state.authoredSize = [__state.W2, __state.H];
331
+ };
332
+ }
333
+
334
+ function makeSetProfile(__state) {
335
+ return function setProfile(input) {
336
+ const next = targetProfile(input);
337
+ __state.activeProfile = next;
338
+ if (next.kind === "native") {
339
+ __state.target(__state.authoredSize[0], __state.authoredSize[1]);
340
+ __state.style = { ...__state.authoredStyle };
341
+ } else {
342
+ __state.target(next.width, next.height);
343
+ __state.style = { ...__state.authoredStyle, screen: next.screen, dither: next.dither };
344
+ }
345
+ if (__state.authoredPalette.length) __state.api.setPalette(__state.authoredPalette, __state.authoredRamps);
346
+ __state.fxDirty = true;
347
+ };
348
+ }
349
+
350
+ function makeSetPalette(__state) {
351
+ return function setPalette(colours, ramps) {
352
+ if (colours.length > MAX_COLOURS) throw new RangeError(`${colours.length} colours: at most ${MAX_COLOURS}`);
353
+ const sourceColours = colours.map((c) => [c[0] ?? 0, c[1] ?? 0, c[2] ?? 0]);
354
+ if (__state.activeProfile.kind !== "native") colours = adaptTargetPalette(sourceColours, __state.activeProfile.id);
355
+ __state.palette = colours.map((c) => [c[0] ?? 0, c[1] ?? 0, c[2] ?? 0]);
356
+ const rows = Math.max(1, Math.ceil(colours.length / PALETTE_WIDTH));
357
+ const bytes = new Uint8Array(PALETTE_WIDTH * rows * 4);
358
+ colours.forEach((c, i) => {
359
+ bytes[i * 4] = c[0] ?? 0;
360
+ bytes[i * 4 + 1] = c[1] ?? 0;
361
+ bytes[i * 4 + 2] = c[2] ?? 0;
362
+ bytes[i * 4 + 3] = 255;
363
+ });
364
+ if (__state.palTex) __state.gl.deleteTexture(__state.palTex);
365
+ __state.palTex = __state.gl.createTexture();
366
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.palTex);
367
+ __state.gl.pixelStorei(__state.gl.UNPACK_ALIGNMENT, 4);
368
+ __state.gl.texImage2D(__state.gl.TEXTURE_2D, 0, __state.gl.RGBA8, PALETTE_WIDTH, rows, 0, __state.gl.RGBA, __state.gl.UNSIGNED_BYTE, bytes);
369
+ __state.nearest();
370
+ const entries = Object.entries(ramps);
371
+ if (entries.length > MAX_RAMPS) throw new RangeError(`${entries.length} ramps: at most ${MAX_RAMPS}`);
372
+ __state.authoredPalette = sourceColours;
373
+ __state.authoredRamps = Object.fromEntries(entries.map(([name, slot]) => [name, [...slot]]));
374
+ __state.rampIndex = /* @__PURE__ */ new Map();
375
+ __state.rampList = entries.map(([name, [base, len2]], i) => {
376
+ __state.rampIndex.set(name, i);
377
+ return [base, len2];
378
+ });
379
+ __state.fxDirty = true;
380
+ };
381
+ }
382
+
383
+ function makeSetMaterials(__state) {
384
+ return function setMaterials(list) {
385
+ if (list.length > MAX_MATERIALS) throw new RangeError(`${list.length} materials: at most ${MAX_MATERIALS}`);
386
+ __state.matRows.fill(0);
387
+ list.forEach((m, i) => {
388
+ __state.matRows.set([__state.rampIndex.get(m.ramp) ?? 0, m.light ?? 1, m.pattern ?? 0, m.glow ?? 0], i * 4);
389
+ });
390
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.matTex);
391
+ __state.gl.texSubImage2D(__state.gl.TEXTURE_2D, 0, 0, 0, 256, 1, __state.gl.RGBA, __state.gl.FLOAT, __state.matRows);
392
+ };
393
+ }
394
+
395
+ function makeSetStyle(__state) {
396
+ return function setStyle({ screen: s = __state.style.screen, dither: d = __state.style.dither, outline: o = __state.style.outline, edges: e = __state.edges, supersample: k = __state.supersample } = {}) {
397
+ __state.style = { screen: s, dither: d, outline: o ? 1 : 0 };
398
+ __state.edges = e;
399
+ __state.supersample = k;
400
+ __state.authoredStyle = { ...__state.style };
401
+ __state.fxDirty = true;
402
+ };
403
+ }
404
+
405
+ function makeSetWorld(__state) {
406
+ return function setWorld(world) {
407
+ const counts = uploadWorld(__state.gl, __state.blocks, world);
408
+ __state.nBoxes = counts.boxes;
409
+ __state.nWedges = counts.wedges;
410
+ __state.nCaps = counts.capsules;
411
+ return counts;
412
+ };
413
+ }
414
+
415
+ function makeSetFx(__state) {
416
+ return function setFx(list = []) {
417
+ __state.fxList = list.map((e) => ({ ...e }));
418
+ resolveFx(__state.fxList, { width: __state.W2, height: __state.H });
419
+ __state.fxDirty = true;
420
+ };
421
+ }
422
+
423
+ function makeToggleFx(__state) {
424
+ return function toggleFx(name, on) {
425
+ __state.fxList = toggleFxList(__state.fxList, name, on);
426
+ __state.fxDirty = true;
427
+ };
428
+ }
429
+
430
+ function makeRender(__state) {
431
+ return function render({ eye, target: look, fov = 1.2, time = 0, sun = [0.4, 0.8, 0.3], waterY = 0, fogNear = 25, fogFar = 110, particles = [], raster, depthOut }) {
432
+ const __frame = { eye, look, fov, time, sun, waterY, fogNear, fogFar, particles, raster, depthOut };
433
+ prepareRender(__state, __frame);
434
+ drawRender(__state, __frame);
435
+ composeRender(__state, __frame);
436
+ };
437
+ }
438
+
439
+ function makeRead(__state) {
440
+ return function read() {
441
+ const out = new Uint8Array(__state.W2 * __state.H * 4);
442
+ __state.gl.readPixels(0, 0, __state.W2, __state.H, __state.gl.RGBA, __state.gl.UNSIGNED_BYTE, out);
443
+ return out;
444
+ };
445
+ }
446
+
447
+ function makeReadData(__state) {
448
+ return function readData() {
449
+ const x = __state.bakeMode();
450
+ const data = __state.readTarget(__state.fbo, __state.gl.COLOR_ATTACHMENT0);
451
+ const data2 = __state.readTarget(__state.fbo, __state.gl.COLOR_ATTACHMENT1);
452
+ __state.gl.disable(__state.gl.DEPTH_TEST);
453
+ __state.pass(x.depth.p, x.fb, [[__state.depthTex, x.depth.loc.uDepth]]);
454
+ const packed = __state.readTarget(x.fb, __state.gl.COLOR_ATTACHMENT0);
455
+ const depth = new Float32Array(__state.W2 * __state.H);
456
+ for (let i = 0; i < depth.length; i += 1) depth[i] = unpackDepth(packed[i * 4], packed[i * 4 + 1], packed[i * 4 + 2]);
457
+ return { width: __state.W2, height: __state.H, data, data2, depth };
458
+ };
459
+ }
460
+
461
+ function makeSetMesh(__state) {
462
+ return function setMesh(key2, mesh) {
463
+ const R = __state.rasterMode();
464
+ const old = R.meshes.get(key2);
465
+ if (old) {
466
+ for (const b of old.bufs) __state.gl.deleteBuffer(b);
467
+ __state.gl.deleteVertexArray(old.vao);
468
+ R.meshes.delete(key2);
469
+ __state.rasterStats.meshBytes -= old.bytes;
470
+ }
471
+ if (!mesh) return;
472
+ const vao = __state.gl.createVertexArray();
473
+ __state.gl.bindVertexArray(vao);
474
+ const bufs = [];
475
+ const attr = (loc, data, size) => {
476
+ const b = __state.gl.createBuffer();
477
+ bufs.push(b);
478
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, b);
479
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, data, __state.gl.STATIC_DRAW);
480
+ __state.gl.enableVertexAttribArray(loc);
481
+ __state.gl.vertexAttribPointer(loc, size, __state.gl.FLOAT, false, 0, 0);
482
+ };
483
+ attr(0, mesh.positions, 3);
484
+ attr(1, mesh.normals, 3);
485
+ attr(2, mesh.looks, 4);
486
+ for (let k = 3; k < 6; k += 1) {
487
+ __state.gl.disableVertexAttribArray(k);
488
+ __state.gl.vertexAttrib4f(k, 0, 0, 0, 0);
489
+ }
490
+ let bytes = mesh.positions.byteLength + mesh.normals.byteLength + mesh.looks.byteLength;
491
+ if (mesh.indices) {
492
+ const b = __state.gl.createBuffer();
493
+ bufs.push(b);
494
+ __state.gl.bindBuffer(__state.gl.ELEMENT_ARRAY_BUFFER, b);
495
+ __state.gl.bufferData(__state.gl.ELEMENT_ARRAY_BUFFER, mesh.indices, __state.gl.STATIC_DRAW);
496
+ bytes += mesh.indices.byteLength;
497
+ }
498
+ __state.gl.bindVertexArray(null);
499
+ R.meshes.set(key2, { vao, bufs, count: mesh.indices ? mesh.indices.length : mesh.positions.length / 3, indexed: !!mesh.indices, bytes });
500
+ __state.rasterStats.meshBytes += bytes;
501
+ };
502
+ }
503
+
504
+ function makeOffPalette(__state) {
505
+ return function offPalette(pixels = __state.api.read()) {
506
+ const set = new Set(__state.palette.map((c) => c[0] << 16 | c[1] << 8 | c[2]));
507
+ let off = 0;
508
+ for (let i = 0; i < pixels.length; i += 4) if (!set.has((pixels[i] ?? 0) << 16 | (pixels[i + 1] ?? 0) << 8 | (pixels[i + 2] ?? 0))) off += 1;
509
+ return off;
510
+ };
511
+ }
512
+
513
+ export {
514
+ initializeGraphics,
515
+ initializeIndexedBuffers,
516
+ initializePaletteAndEffects,
517
+ makeOffPalette,
518
+ makeRead,
519
+ makeReadData,
520
+ makeRender,
521
+ makeSetFx,
522
+ makeSetMaterials,
523
+ makeSetMesh,
524
+ makeSetPalette,
525
+ makeSetProfile,
526
+ makeSetStyle,
527
+ makeSetTarget,
528
+ makeSetWorld,
529
+ makeToggleFx,
530
+ };
@@ -0,0 +1,121 @@
1
+ import './render-passes.mjs';
2
+ import {
3
+ ALL_FX,
4
+ MAX_BOXES,
5
+ MAX_CAPS,
6
+ MAX_COLOURS,
7
+ MAX_MATERIALS,
8
+ MAX_RAMPS,
9
+ MAX_WEDGES,
10
+ } from './effects-world.mjs';
11
+ import {
12
+ drawRasterImpl,
13
+ fineBuffersImpl,
14
+ rasterModeImpl,
15
+ refreshFxImpl,
16
+ targetImpl,
17
+ uploadRampsImpl,
18
+ writeDepthOutImpl,
19
+ } from './indexed-render.mjs';
20
+ import {
21
+ initializeGraphics,
22
+ initializeIndexedBuffers,
23
+ initializePaletteAndEffects,
24
+ makeOffPalette,
25
+ makeRead,
26
+ makeReadData,
27
+ makeRender,
28
+ makeSetFx,
29
+ makeSetMaterials,
30
+ makeSetMesh,
31
+ makeSetPalette,
32
+ makeSetProfile,
33
+ makeSetStyle,
34
+ makeSetTarget,
35
+ makeSetWorld,
36
+ makeToggleFx,
37
+ } from './render-passes.mjs';
38
+
39
+
40
+ function createRendererApi(__state) {
41
+ return {
42
+ gl: __state.gl,
43
+ get width() {
44
+ return __state.W2;
45
+ },
46
+ get height() {
47
+ return __state.H;
48
+ },
49
+ limits: {
50
+ boxes: MAX_BOXES,
51
+ wedges: MAX_WEDGES,
52
+ capsules: MAX_CAPS,
53
+ ramps: MAX_RAMPS,
54
+ materials: MAX_MATERIALS,
55
+ colours: MAX_COLOURS,
56
+ fragmentUniformVectors: __state.gl.getParameter(__state.gl.MAX_FRAGMENT_UNIFORM_VECTORS),
57
+ maxTexture: __state.gl.getParameter(__state.gl.MAX_TEXTURE_SIZE)
58
+ },
59
+ setTarget: makeSetTarget(__state),
60
+ get profile() {
61
+ return __state.activeProfile;
62
+ },
63
+ setProfile: makeSetProfile(__state),
64
+ setPalette: makeSetPalette(__state),
65
+ get palette() {
66
+ return __state.palette;
67
+ },
68
+ ramp: (name) => __state.rampIndex.get(name) ?? 0,
69
+ setMaterials: makeSetMaterials(__state),
70
+ setStyle: makeSetStyle(__state),
71
+ setWorld: makeSetWorld(__state),
72
+ setFx: makeSetFx(__state),
73
+ toggleFx: makeToggleFx(__state),
74
+ get fx() {
75
+ return __state.fxList.map((e) => ({ ...e }));
76
+ },
77
+ get fxResolved() {
78
+ if (__state.fxDirty) __state.refreshFx();
79
+ return __state.fxResolved;
80
+ },
81
+ allFx: ALL_FX,
82
+ get gpuMs() {
83
+ return __state.gpuMs;
84
+ },
85
+ get supersample() {
86
+ return __state.lastK;
87
+ },
88
+ render: makeRender(__state),
89
+ read: makeRead(__state),
90
+ readData: makeReadData(__state),
91
+ renderIndexed: __state.indexed.renderIndexed,
92
+ readIndexed: __state.indexed.readIndexed,
93
+ renderIndexedHeights: __state.indexed.renderIndexedHeights,
94
+ setMesh: makeSetMesh(__state),
95
+ get rasterStats() {
96
+ return { ...__state.rasterStats };
97
+ },
98
+ offPalette: makeOffPalette(__state),
99
+ };
100
+ }
101
+
102
+ function createPixelRenderer(canvas, { width = 128, height = 128, bakeOnly = false, profile: profile2 } = {}) {
103
+ const __state = { canvas, width, height, bakeOnly, profile2 };
104
+ __state.target = (...args) => targetImpl(__state, ...args);
105
+ __state.uploadRamps = (...args) => uploadRampsImpl(__state, ...args);
106
+ __state.refreshFx = (...args) => refreshFxImpl(__state, ...args);
107
+ __state.fineBuffers = (...args) => fineBuffersImpl(__state, ...args);
108
+ __state.rasterMode = (...args) => rasterModeImpl(__state, ...args);
109
+ __state.drawRaster = (...args) => drawRasterImpl(__state, ...args);
110
+ __state.writeDepthOut = (...args) => writeDepthOutImpl(__state, ...args);
111
+ initializeGraphics(__state);
112
+ initializePaletteAndEffects(__state);
113
+ initializeIndexedBuffers(__state);
114
+ __state.api = createRendererApi(__state);
115
+ if (profile2 !== void 0) __state.api.setProfile(profile2);
116
+ return __state.api;
117
+ }
118
+
119
+ export {
120
+ createPixelRenderer,
121
+ };