@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,516 @@
1
+ import './pixel-raster.mjs';
2
+ import {
3
+ cameraBasis,
4
+ } from './core-primitives.mjs';
5
+ import {
6
+ FAR,
7
+ FULLSCREEN_VS,
8
+ MAX_BOXES,
9
+ MAX_CAPS,
10
+ MAX_RAMPS,
11
+ MAX_WEDGES,
12
+ SCREEN_TILE,
13
+ fxUniforms,
14
+ resolveFx,
15
+ screenTile,
16
+ } from './effects-world.mjs';
17
+ import {
18
+ BAKE_WORLD_FS,
19
+ DEPTH_OUT_FS,
20
+ HEIGHT_FS,
21
+ INDEX_FS,
22
+ RASTER_FLOATS,
23
+ RASTER_FS,
24
+ RASTER_VS,
25
+ boxTemplate,
26
+ capsuleTemplate,
27
+ smoothDepthOutFs,
28
+ } from './pixel-raster.mjs';
29
+
30
+ var RESOLVE_FS = `#version 300 es
31
+ precision highp float;
32
+ uniform sampler2D uColour;
33
+ uniform int uSS;
34
+ out vec4 outColor;
35
+ void main() {
36
+ ivec2 p = ivec2(gl_FragCoord.xy) * uSS;
37
+ vec3 acc = vec3(0.0);
38
+ for (int y = 0; y < 4; y++) {
39
+ if (y >= uSS) break;
40
+ for (int x = 0; x < 4; x++) {
41
+ if (x >= uSS) break;
42
+ vec3 c = texelFetch(uColour, p + ivec2(x, y), 0).rgb;
43
+ acc += c * c;
44
+ }
45
+ }
46
+ outColor = vec4(sqrt(acc / float(uSS * uSS)), 1.0);
47
+ }`;
48
+ function supersampleFor(width, height, asked = "auto", budget = 11e5) {
49
+ if (asked !== "auto") return Math.max(1, Math.min(4, Math.round(asked)));
50
+ for (const k of [3, 2]) if (width * height * k * k <= budget) return k;
51
+ return 1;
52
+ }
53
+
54
+ // packages/render/src/link-program.ts
55
+ function linkProgram(gl, vertex, fragment, name = "Program") {
56
+ const shaders = [];
57
+ const attached = [];
58
+ let program2 = null;
59
+ let linked = false;
60
+ try {
61
+ for (const [type, source] of [[gl.VERTEX_SHADER, vertex], [gl.FRAGMENT_SHADER, fragment]]) {
62
+ const shader = gl.createShader(type);
63
+ if (!shader) throw new Error(`${name}: shader allocation failed`);
64
+ shaders.push(shader);
65
+ gl.shaderSource(shader, source);
66
+ gl.compileShader(shader);
67
+ }
68
+ program2 = gl.createProgram();
69
+ if (!program2) throw new Error(`${name}: program allocation failed`);
70
+ for (const shader of shaders) {
71
+ gl.attachShader(program2, shader);
72
+ attached.push(shader);
73
+ }
74
+ gl.linkProgram(program2);
75
+ if (!gl.getProgramParameter(program2, gl.LINK_STATUS)) {
76
+ const errors = [];
77
+ for (const shader of shaders) {
78
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) errors.push(gl.getShaderInfoLog(shader) || "shader compile failed");
79
+ }
80
+ throw new Error(`${name}: ${errors.join("; ") || gl.getProgramInfoLog(program2) || "program link failed"}`);
81
+ }
82
+ linked = true;
83
+ return program2;
84
+ } finally {
85
+ if (program2) for (const shader of attached) gl.detachShader(program2, shader);
86
+ for (const shader of shaders) gl.deleteShader(shader);
87
+ if (program2 && !linked) gl.deleteProgram(program2);
88
+ }
89
+ }
90
+
91
+ // packages/render/src/program.ts
92
+ function program(gl, vs, fs) {
93
+ const p = linkProgram(gl, vs, fs, "Pixel renderer");
94
+ try {
95
+ const loc = {};
96
+ const n = gl.getProgramParameter(p, gl.ACTIVE_UNIFORMS);
97
+ for (let i = 0; i < n; i += 1) {
98
+ const u = gl.getActiveUniform(p, i);
99
+ if (u) loc[u.name.replace(/\[0\]$/, "")] = gl.getUniformLocation(p, u.name);
100
+ }
101
+ return { p, loc };
102
+ } catch (error) {
103
+ gl.deleteProgram(p);
104
+ throw error;
105
+ }
106
+ }
107
+
108
+ // packages/render/src/indexed-pass.ts
109
+ var norm2 = (a) => {
110
+ const l = Math.hypot(a[0], a[1], a[2]) || 1;
111
+ return [a[0] / l, a[1] / l, a[2] / l];
112
+ };
113
+ function makeIndexedRender(env, gl, bakeMode, pass) {
114
+ return function renderIndexed({ eye, target: look, fov = 1.2, time = 0, sun = [0.4, 0.8, 0.3], waterY = 0, fogNear = 25, fogFar = 110, gap = 0.56, split, ortho = 0 }) {
115
+ const x = bakeMode();
116
+ const { forward: fwd, right, up } = cameraBasis(eye, look);
117
+ gl.bindFramebuffer(gl.FRAMEBUFFER, env.fbo);
118
+ gl.viewport(0, 0, env.width, env.height);
119
+ gl.enable(gl.DEPTH_TEST);
120
+ gl.depthFunc(gl.ALWAYS);
121
+ gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
122
+ const BW = x.world.loc;
123
+ gl.useProgram(x.world.p);
124
+ gl.uniform2f(BW.uRes, env.width, env.height);
125
+ gl.uniform3fv(BW.uEye, eye);
126
+ gl.uniform3fv(BW.uFwd, fwd);
127
+ gl.uniform3fv(BW.uRight, right);
128
+ gl.uniform3fv(BW.uUp, up);
129
+ gl.uniform1f(BW.uTan, Math.tan(fov / 2));
130
+ gl.uniform1f(BW.uTime, time);
131
+ gl.uniform1i(BW.uBoxes, env.counts.boxes);
132
+ gl.uniform1i(BW.uWedges, env.counts.wedges);
133
+ gl.uniform1i(BW.uCaps, env.counts.capsules);
134
+ for (const blk of env.blocks) gl.bindBufferBase(gl.UNIFORM_BUFFER, blk.i, blk.buf);
135
+ gl.activeTexture(gl.TEXTURE1);
136
+ gl.bindTexture(gl.TEXTURE_2D, env.matTex);
137
+ gl.uniform1i(BW.uMats, 1);
138
+ gl.uniform3fv(BW.uSun, norm2(sun));
139
+ gl.uniform1f(BW.uWaterY, waterY);
140
+ gl.uniform1f(BW.uFogNear, fogNear);
141
+ gl.uniform1f(BW.uFogFar, fogFar);
142
+ gl.uniform4f(BW.uSplit, split?.[0] ?? 0, split?.[1] ?? 0, split?.[2] ?? 0, split ? 1 : 0);
143
+ gl.uniform1f(BW.uOrthoH, ortho);
144
+ gl.bindBuffer(gl.ARRAY_BUFFER, env.quad);
145
+ const aw = gl.getAttribLocation(x.world.p, "aPos");
146
+ gl.enableVertexAttribArray(aw);
147
+ gl.vertexAttribPointer(aw, 2, gl.FLOAT, false, 0, 0);
148
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
149
+ gl.disable(gl.DEPTH_TEST);
150
+ gl.useProgram(x.index.p);
151
+ gl.uniform1f(x.index.loc.uGap, gap / FAR);
152
+ pass(x.index.p, x.fb, [[env.dataTex, x.index.loc.uData], [env.data2Tex, x.index.loc.uData2], [env.depthTex, x.index.loc.uDepth]]);
153
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
154
+ return x.fb;
155
+ };
156
+ }
157
+
158
+ function makeIndexedHeights(env, gl, bakeMode, pass) {
159
+ return function renderIndexedHeights({ eye, target: look, fov = 1.2, pixelsPerMetre, eps = 0, ortho = 0 }) {
160
+ const x = bakeMode();
161
+ if (!x.height) {
162
+ x.height = program(gl, FULLSCREEN_VS, HEIGHT_FS);
163
+ ["Boxes", "Wedges", "Capsules"].forEach((name, i) => gl.uniformBlockBinding(x.height.p, gl.getUniformBlockIndex(x.height.p, name), i));
164
+ }
165
+ const hp = x.height;
166
+ const { forward: fwd, right, up } = cameraBasis(eye, look);
167
+ gl.disable(gl.DEPTH_TEST);
168
+ gl.useProgram(hp.p);
169
+ const L = hp.loc;
170
+ gl.uniform2f(L.uRes, env.width, env.height);
171
+ gl.uniform3fv(L.uEye, eye);
172
+ gl.uniform3fv(L.uFwd, fwd);
173
+ gl.uniform3fv(L.uRight, right);
174
+ gl.uniform3fv(L.uUp, up);
175
+ gl.uniform1f(L.uTan, Math.tan(fov / 2));
176
+ gl.uniform1f(L.uScale, pixelsPerMetre);
177
+ gl.uniform1f(L.uEps, eps);
178
+ gl.uniform1f(L.uOrthoH, ortho);
179
+ gl.uniform1i(L.uBoxes, env.counts.boxes);
180
+ gl.uniform1i(L.uWedges, env.counts.wedges);
181
+ gl.uniform1i(L.uCaps, env.counts.capsules);
182
+ for (const blk of env.blocks) gl.bindBufferBase(gl.UNIFORM_BUFFER, blk.i, blk.buf);
183
+ pass(hp.p, x.fb, [[env.dataTex, L.uData], [env.depthTex, L.uDepth]]);
184
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
185
+ return x.fb;
186
+ };
187
+ }
188
+
189
+ function createIndexedPass(env, createDepth) {
190
+ const gl = env.gl;
191
+ const nearest = () => {
192
+ for (const [k, v] of [[gl.TEXTURE_MIN_FILTER, gl.NEAREST], [gl.TEXTURE_MAG_FILTER, gl.NEAREST], [gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE], [gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE]]) gl.texParameteri(gl.TEXTURE_2D, k, v);
193
+ };
194
+ let extra = null;
195
+ function bakeMode() {
196
+ if (!extra) {
197
+ const bw = program(gl, FULLSCREEN_VS, BAKE_WORLD_FS);
198
+ ["Boxes", "Wedges", "Capsules"].forEach((name, i) => gl.uniformBlockBinding(bw.p, gl.getUniformBlockIndex(bw.p, name), i));
199
+ extra = { world: bw, index: program(gl, FULLSCREEN_VS, INDEX_FS), depth: createDepth?.() ?? null, height: null, fb: gl.createFramebuffer(), tex: gl.createTexture(), w: 0, h: 0 };
200
+ }
201
+ if (extra.w !== env.width || extra.h !== env.height) {
202
+ gl.bindTexture(gl.TEXTURE_2D, extra.tex);
203
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, env.width, env.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
204
+ nearest();
205
+ gl.bindFramebuffer(gl.FRAMEBUFFER, extra.fb);
206
+ gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, extra.tex, 0);
207
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
208
+ extra.w = env.width;
209
+ extra.h = env.height;
210
+ }
211
+ return extra;
212
+ }
213
+ function pass(prog, fb, textures) {
214
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
215
+ gl.viewport(0, 0, env.width, env.height);
216
+ gl.useProgram(prog);
217
+ textures.forEach(([t, loc], i) => {
218
+ gl.activeTexture(gl.TEXTURE0 + i);
219
+ gl.bindTexture(gl.TEXTURE_2D, t);
220
+ gl.uniform1i(loc, i);
221
+ });
222
+ gl.bindBuffer(gl.ARRAY_BUFFER, env.quad);
223
+ const a = gl.getAttribLocation(prog, "aPos");
224
+ gl.enableVertexAttribArray(a);
225
+ gl.vertexAttribPointer(a, 2, gl.FLOAT, false, 0, 0);
226
+ gl.drawArrays(gl.TRIANGLES, 0, 3);
227
+ }
228
+ function readTarget(fb, attachment) {
229
+ const out = new Uint8Array(env.width * env.height * 4);
230
+ gl.bindFramebuffer(gl.FRAMEBUFFER, fb);
231
+ if (fb) gl.readBuffer(attachment);
232
+ gl.readPixels(0, 0, env.width, env.height, gl.RGBA, gl.UNSIGNED_BYTE, out);
233
+ if (fb) gl.readBuffer(gl.COLOR_ATTACHMENT0);
234
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
235
+ return out;
236
+ }
237
+ const api = {
238
+ renderIndexed: makeIndexedRender(env, gl, bakeMode, pass),
239
+ readIndexed() {
240
+ return readTarget(bakeMode().fb, gl.COLOR_ATTACHMENT0);
241
+ },
242
+ renderIndexedHeights: makeIndexedHeights(env, gl, bakeMode, pass)
243
+ };
244
+ return {
245
+ ...api,
246
+ mode: bakeMode,
247
+ pass,
248
+ readTarget,
249
+ dispose() {
250
+ if (!extra) return;
251
+ for (const p of [extra.world, extra.index, extra.depth, extra.height]) if (p) gl.deleteProgram(p.p);
252
+ gl.deleteTexture(extra.tex);
253
+ gl.deleteFramebuffer(extra.fb);
254
+ extra = null;
255
+ }
256
+ };
257
+ }
258
+
259
+ // packages/render/src/world-buffers.ts
260
+ function uploadWorld(gl, blocks, { boxes = [], wedges = [], capsules = [] }) {
261
+ const [boxBlock, wedgeBlock, capBlock] = blocks;
262
+ let nBoxes = 0, nWedges = 0, nCaps = 0;
263
+ const bx = [];
264
+ const wd = [...wedges];
265
+ for (const b of boxes) (b.kind === "wedge" ? wd : bx).push(b);
266
+ nBoxes = Math.min(MAX_BOXES, bx.length);
267
+ for (let i = 0; i < nBoxes; i += 1) {
268
+ const b = bx[i];
269
+ boxBlock.data.set([b.c[0], b.c[1], b.c[2], b.mat ?? 0, b.h[0], b.h[1], b.h[2], b.yaw ?? 0], i * 8);
270
+ }
271
+ nWedges = Math.min(MAX_WEDGES, wd.length);
272
+ for (let i = 0; i < nWedges; i += 1) {
273
+ const w = wd[i];
274
+ wedgeBlock.data.set([w.c[0], w.c[1], w.c[2], w.mat ?? 0, w.h[0], w.h[1], w.h[2], w.yaw ?? 0, Math.max(0, Math.min(0.98, w.lo ?? 0)), Math.max(0, w.skin ?? 0), Math.max(-1, Math.min(1, w.top?.[0] ?? -1)), Math.max(-1, Math.min(1, w.top?.[1] ?? 1))], i * 12);
275
+ }
276
+ nCaps = Math.min(MAX_CAPS, capsules.length);
277
+ for (let i = 0; i < nCaps; i += 1) {
278
+ const c = capsules[i];
279
+ capBlock.data.set([c.a[0], c.a[1], c.a[2], c.r, c.b[0], c.b[1], c.b[2], c.mat ?? 0], i * 8);
280
+ }
281
+ for (const [blk, n] of [[boxBlock, nBoxes * 8], [wedgeBlock, nWedges * 12], [capBlock, nCaps * 8]]) {
282
+ gl.bindBuffer(gl.UNIFORM_BUFFER, blk.buf);
283
+ if (n) gl.bufferSubData(gl.UNIFORM_BUFFER, 0, blk.data, 0, n);
284
+ }
285
+ return { boxes: nBoxes, wedges: nWedges, capsules: nCaps, dropped: bx.length - nBoxes + wd.length - nWedges + capsules.length - nCaps };
286
+ }
287
+
288
+ // packages/render/src/pixel-renderer.ts
289
+ var norm3 = (a) => {
290
+ const l = Math.hypot(a[0], a[1], a[2]) || 1;
291
+ return [a[0] / l, a[1] / l, a[2] / l];
292
+ };
293
+ var dot2 = (a, b) => a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
294
+ function targetImpl(__state, w, h) {
295
+ __state.W2 = w;
296
+ __state.H = h;
297
+ __state.canvas.width = __state.W2;
298
+ __state.canvas.height = __state.H;
299
+ for (const t of [__state.dataTex, __state.data2Tex, __state.depthTex]) if (t) __state.gl.deleteTexture(t);
300
+ if (__state.fbo) __state.gl.deleteFramebuffer(__state.fbo);
301
+ const rgba8 = () => {
302
+ const t = __state.gl.createTexture();
303
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, t);
304
+ __state.gl.texImage2D(__state.gl.TEXTURE_2D, 0, __state.gl.RGBA8, __state.W2, __state.H, 0, __state.gl.RGBA, __state.gl.UNSIGNED_BYTE, null);
305
+ __state.nearest();
306
+ return t;
307
+ };
308
+ __state.dataTex = rgba8();
309
+ __state.data2Tex = rgba8();
310
+ __state.depthTex = __state.gl.createTexture();
311
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.depthTex);
312
+ __state.gl.texImage2D(__state.gl.TEXTURE_2D, 0, __state.gl.DEPTH_COMPONENT24, __state.W2, __state.H, 0, __state.gl.DEPTH_COMPONENT, __state.gl.UNSIGNED_INT, null);
313
+ __state.nearest();
314
+ __state.fbo = __state.gl.createFramebuffer();
315
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, __state.fbo);
316
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.COLOR_ATTACHMENT0, __state.gl.TEXTURE_2D, __state.dataTex, 0);
317
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.COLOR_ATTACHMENT1, __state.gl.TEXTURE_2D, __state.data2Tex, 0);
318
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.DEPTH_ATTACHMENT, __state.gl.TEXTURE_2D, __state.depthTex, 0);
319
+ __state.gl.drawBuffers([__state.gl.COLOR_ATTACHMENT0, __state.gl.COLOR_ATTACHMENT1]);
320
+ __state.fxDirty = true;
321
+ }
322
+
323
+ function uploadRampsImpl(__state) {
324
+ __state.rampRows.fill(0);
325
+ __state.rampList.forEach(([base, len2], i) => {
326
+ __state.rampRows.set([base, len2, 0, 0], i * 4);
327
+ });
328
+ for (let i = 0; i < MAX_RAMPS; i += 1) __state.rampRows[(MAX_RAMPS + i) * 4] = -1;
329
+ if (__state.fxU) {
330
+ for (const [r, from, speed] of __state.fxU.ramps.cycle) {
331
+ __state.rampRows[r * 4 + 2] = from;
332
+ __state.rampRows[r * 4 + 3] = speed;
333
+ }
334
+ for (const [r, to] of __state.fxU.ramps.grade) __state.rampRows[(MAX_RAMPS + r) * 4] = to;
335
+ }
336
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.rampTex);
337
+ __state.gl.texSubImage2D(__state.gl.TEXTURE_2D, 0, 0, 0, MAX_RAMPS, 2, __state.gl.RGBA, __state.gl.FLOAT, __state.rampRows);
338
+ }
339
+
340
+ function refreshFxImpl(__state) {
341
+ __state.fxResolved = resolveFx(__state.fxList, { width: __state.W2, height: __state.H });
342
+ const u = fxUniforms(__state.fxResolved, { ramp: (n) => __state.rampIndex.get(n) ?? -1, rampOf: (i) => __state.rampList[i] ?? [0, 1], style: __state.style, far: FAR });
343
+ __state.fxU = u;
344
+ if (u.screen && u.screen !== __state.screenLoaded) {
345
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.screenTex);
346
+ __state.gl.pixelStorei(__state.gl.UNPACK_ALIGNMENT, 1);
347
+ __state.gl.texSubImage2D(__state.gl.TEXTURE_2D, 0, 0, 0, SCREEN_TILE, SCREEN_TILE, __state.gl.RED, __state.gl.UNSIGNED_BYTE, screenTile(u.screen, SCREEN_TILE));
348
+ __state.screenLoaded = u.screen;
349
+ }
350
+ __state.uploadRamps();
351
+ __state.fxDirty = false;
352
+ return u;
353
+ }
354
+
355
+ function fineBuffersImpl(__state, k) {
356
+ if (__state.fine && __state.fine.k === k && __state.fine.w === __state.W2 * k && __state.fine.h === __state.H * k) return __state.fine;
357
+ if (__state.fine) {
358
+ for (const t of [__state.fine.data, __state.fine.data2, __state.fine.depth, __state.fine.colour]) __state.gl.deleteTexture(t);
359
+ __state.gl.deleteFramebuffer(__state.fine.fbo);
360
+ __state.gl.deleteFramebuffer(__state.fine.colourFbo);
361
+ }
362
+ const w = __state.W2 * k, h = __state.H * k;
363
+ const tex = (internal, format, type) => {
364
+ const t = __state.gl.createTexture();
365
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, t);
366
+ __state.gl.texImage2D(__state.gl.TEXTURE_2D, 0, internal, w, h, 0, format, type, null);
367
+ __state.nearest();
368
+ return t;
369
+ };
370
+ const data = tex(__state.gl.RGBA8, __state.gl.RGBA, __state.gl.UNSIGNED_BYTE), data2 = tex(__state.gl.RGBA8, __state.gl.RGBA, __state.gl.UNSIGNED_BYTE), depth = tex(__state.gl.DEPTH_COMPONENT24, __state.gl.DEPTH_COMPONENT, __state.gl.UNSIGNED_INT);
371
+ const fb = __state.gl.createFramebuffer();
372
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, fb);
373
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.COLOR_ATTACHMENT0, __state.gl.TEXTURE_2D, data, 0);
374
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.COLOR_ATTACHMENT1, __state.gl.TEXTURE_2D, data2, 0);
375
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.DEPTH_ATTACHMENT, __state.gl.TEXTURE_2D, depth, 0);
376
+ __state.gl.drawBuffers([__state.gl.COLOR_ATTACHMENT0, __state.gl.COLOR_ATTACHMENT1]);
377
+ const colour2 = tex(__state.gl.RGBA8, __state.gl.RGBA, __state.gl.UNSIGNED_BYTE), colourFbo = __state.gl.createFramebuffer();
378
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, colourFbo);
379
+ __state.gl.framebufferTexture2D(__state.gl.FRAMEBUFFER, __state.gl.COLOR_ATTACHMENT0, __state.gl.TEXTURE_2D, colour2, 0);
380
+ __state.fine = { k, w, h, fbo: fb, data, data2, depth, colourFbo, colour: colour2 };
381
+ return __state.fine;
382
+ }
383
+
384
+ function rasterModeImpl(__state) {
385
+ if (__state.rasterState) return __state.rasterState;
386
+ const prog = program(__state.gl, RASTER_VS, RASTER_FS);
387
+ const depthOut = program(__state.gl, FULLSCREEN_VS, DEPTH_OUT_FS);
388
+ const kind = (t) => {
389
+ const vao = __state.gl.createVertexArray();
390
+ __state.gl.bindVertexArray(vao);
391
+ const vb = __state.gl.createBuffer();
392
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, vb);
393
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, t.verts, __state.gl.STATIC_DRAW);
394
+ __state.gl.enableVertexAttribArray(0);
395
+ __state.gl.vertexAttribPointer(0, 3, __state.gl.FLOAT, false, 0, 0);
396
+ const nb = __state.gl.createBuffer();
397
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, nb);
398
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, t.norms, __state.gl.STATIC_DRAW);
399
+ __state.gl.enableVertexAttribArray(1);
400
+ __state.gl.vertexAttribPointer(1, 3, __state.gl.FLOAT, false, 0, 0);
401
+ const ib = __state.gl.createBuffer();
402
+ __state.gl.bindBuffer(__state.gl.ELEMENT_ARRAY_BUFFER, ib);
403
+ __state.gl.bufferData(__state.gl.ELEMENT_ARRAY_BUFFER, t.index, __state.gl.STATIC_DRAW);
404
+ const inst = __state.gl.createBuffer();
405
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, inst);
406
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, 1024 * RASTER_FLOATS * 4, __state.gl.DYNAMIC_DRAW);
407
+ for (let k = 0; k < 4; k += 1) {
408
+ __state.gl.enableVertexAttribArray(2 + k);
409
+ __state.gl.vertexAttribPointer(2 + k, 4, __state.gl.FLOAT, false, RASTER_FLOATS * 4, k * 16);
410
+ __state.gl.vertexAttribDivisor(2 + k, 1);
411
+ }
412
+ __state.gl.bindVertexArray(null);
413
+ return { vao, inst, cap: 1024, count: t.index.length };
414
+ };
415
+ const box2 = kind(boxTemplate());
416
+ __state.rasterState = { prog, depthOut, box: box2, wedge: kind(boxTemplate()), capsule: kind(capsuleTemplate(8, 2)), meshes: /* @__PURE__ */ new Map() };
417
+ return __state.rasterState;
418
+ }
419
+
420
+ function drawRasterImpl(__state, frame, eye, fwd, right, up, tanF, sunN, waterY, fogNear, fogFar, time) {
421
+ const R = __state.rasterMode();
422
+ const RU = R.prog.loc;
423
+ __state.gl.enable(__state.gl.DEPTH_TEST);
424
+ __state.gl.depthFunc(__state.gl.LESS);
425
+ __state.gl.depthMask(true);
426
+ __state.gl.useProgram(R.prog.p);
427
+ __state.gl.uniform3fv(RU.uEye, eye);
428
+ __state.gl.uniform3fv(RU.uFwd, fwd);
429
+ __state.gl.uniform3fv(RU.uRight, right);
430
+ __state.gl.uniform3fv(RU.uUp, up);
431
+ __state.gl.uniform1f(RU.uTan, tanF);
432
+ __state.gl.uniform1f(RU.uAspect, __state.RW / __state.RH);
433
+ __state.gl.activeTexture(__state.gl.TEXTURE1);
434
+ __state.gl.bindTexture(__state.gl.TEXTURE_2D, __state.matTex);
435
+ __state.gl.uniform1i(RU.uMats, 1);
436
+ __state.gl.uniform3fv(RU.uSun, sunN);
437
+ __state.gl.uniform1f(RU.uWaterY, frame.waterY ?? waterY);
438
+ __state.gl.uniform1f(RU.uFogNear, fogNear);
439
+ __state.gl.uniform1f(RU.uFogFar, fogFar);
440
+ __state.gl.uniform2f(RU.uRes, __state.RW, __state.RH);
441
+ __state.gl.uniform1f(RU.uTime, time);
442
+ let tris = 0, insts = 0, meshes = 0;
443
+ for (const key2 of frame.meshes ?? []) {
444
+ const m = R.meshes.get(key2);
445
+ if (!m || !m.count) continue;
446
+ __state.gl.uniform1i(RU.uKind, 0);
447
+ __state.gl.bindVertexArray(m.vao);
448
+ if (m.indexed) __state.gl.drawElements(__state.gl.TRIANGLES, m.count, __state.gl.UNSIGNED_INT, 0);
449
+ else __state.gl.drawArrays(__state.gl.TRIANGLES, 0, m.count);
450
+ tris += m.count / 3;
451
+ meshes += 1;
452
+ }
453
+ const solids = frame.solids;
454
+ if (solids) {
455
+ for (const [k, buf, id] of [[R.box, solids.boxes, 1], [R.wedge, solids.wedges, 2], [R.capsule, solids.capsules, 3]]) {
456
+ if (!buf.count) continue;
457
+ __state.gl.bindVertexArray(k.vao);
458
+ __state.gl.bindBuffer(__state.gl.ARRAY_BUFFER, k.inst);
459
+ if (buf.count > k.cap) {
460
+ k.cap = Math.max(buf.count, k.cap * 2);
461
+ __state.gl.bufferData(__state.gl.ARRAY_BUFFER, k.cap * RASTER_FLOATS * 4, __state.gl.DYNAMIC_DRAW);
462
+ }
463
+ __state.gl.bufferSubData(__state.gl.ARRAY_BUFFER, 0, buf.data, 0, buf.count * RASTER_FLOATS);
464
+ __state.gl.uniform1i(RU.uKind, id);
465
+ __state.gl.drawElementsInstanced(__state.gl.TRIANGLES, k.count, __state.gl.UNSIGNED_SHORT, 0, buf.count);
466
+ tris += k.count / 3 * buf.count;
467
+ insts += buf.count;
468
+ }
469
+ }
470
+ __state.gl.bindVertexArray(null);
471
+ __state.rasterStats.meshes = meshes;
472
+ __state.rasterStats.triangles = tris;
473
+ __state.rasterStats.instances = insts;
474
+ if (frame.draw) {
475
+ frame.draw({ gl: __state.gl, eye: [eye[0], eye[1], eye[2]], forward: fwd, right, up, tan: tanF, width: __state.RW, height: __state.RH, far: FAR, time, sun: sunN });
476
+ __state.gl.bindFramebuffer(__state.gl.FRAMEBUFFER, __state.rfbo);
477
+ __state.gl.viewport(0, 0, __state.RW, __state.RH);
478
+ __state.gl.drawBuffers([__state.gl.COLOR_ATTACHMENT0, __state.gl.COLOR_ATTACHMENT1]);
479
+ __state.gl.enable(__state.gl.DEPTH_TEST);
480
+ __state.gl.depthFunc(__state.gl.LESS);
481
+ __state.gl.depthMask(true);
482
+ }
483
+ }
484
+
485
+ function writeDepthOutImpl(__state, map) {
486
+ const R = __state.rasterMode();
487
+ const scale2 = map === true ? 1 : map.scale ?? 1, bias = map === true ? 0 : map.bias ?? 0;
488
+ __state.gl.enable(__state.gl.DEPTH_TEST);
489
+ __state.gl.depthFunc(__state.gl.ALWAYS);
490
+ __state.gl.depthMask(true);
491
+ __state.gl.colorMask(false, false, false, false);
492
+ const D = __state.lastK > 1 ? __state.smoothDepthOutP ??= program(__state.gl, FULLSCREEN_VS, smoothDepthOutFs(DEPTH_OUT_FS)) : R.depthOut;
493
+ __state.gl.useProgram(D.p);
494
+ __state.gl.uniform2f(D.loc.uMap, scale2, bias);
495
+ if (__state.lastK > 1) __state.gl.uniform1i(D.loc.uSS, __state.lastK);
496
+ __state.pass(D.p, null, [[__state.lastK > 1 ? __state.fine.depth : __state.depthTex, D.loc.uDepth]]);
497
+ __state.gl.colorMask(true, true, true, true);
498
+ __state.gl.disable(__state.gl.DEPTH_TEST);
499
+ }
500
+
501
+ export {
502
+ RESOLVE_FS,
503
+ createIndexedPass,
504
+ dot2,
505
+ drawRasterImpl,
506
+ fineBuffersImpl,
507
+ norm3,
508
+ program,
509
+ rasterModeImpl,
510
+ refreshFxImpl,
511
+ supersampleFor,
512
+ targetImpl,
513
+ uploadRampsImpl,
514
+ uploadWorld,
515
+ writeDepthOutImpl,
516
+ };