poppygl 0.0.2 → 0.0.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.
- package/dist/index.js +87 -38
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10,14 +10,23 @@ function computeWorldAABB(drawCalls) {
|
|
|
10
10
|
for (const dc of drawCalls) {
|
|
11
11
|
const { positions, model } = dc;
|
|
12
12
|
for (let i = 0; i < positions.length; i += 3) {
|
|
13
|
-
vec4.set(
|
|
13
|
+
vec4.set(
|
|
14
|
+
tmp,
|
|
15
|
+
positions[i],
|
|
16
|
+
positions[i + 1],
|
|
17
|
+
positions[i + 2],
|
|
18
|
+
1
|
|
19
|
+
);
|
|
14
20
|
vec4.transformMat4(tmp, tmp, model);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
+
const x = tmp[0];
|
|
22
|
+
const y = tmp[1];
|
|
23
|
+
const z = tmp[2];
|
|
24
|
+
min[0] = Math.min(min[0], x);
|
|
25
|
+
min[1] = Math.min(min[1], y);
|
|
26
|
+
min[2] = Math.min(min[2], z);
|
|
27
|
+
max[0] = Math.max(max[0], x);
|
|
28
|
+
max[1] = Math.max(max[1], y);
|
|
29
|
+
max[2] = Math.max(max[2], z);
|
|
21
30
|
}
|
|
22
31
|
}
|
|
23
32
|
return { min, max };
|
|
@@ -128,20 +137,31 @@ function computeSmoothNormals(positions, indices) {
|
|
|
128
137
|
positions[i2 * 3 + 1],
|
|
129
138
|
positions[i2 * 3 + 2]
|
|
130
139
|
];
|
|
131
|
-
const v10 = [
|
|
132
|
-
|
|
140
|
+
const v10 = [
|
|
141
|
+
p1[0] - p0[0],
|
|
142
|
+
p1[1] - p0[1],
|
|
143
|
+
p1[2] - p0[2]
|
|
144
|
+
];
|
|
145
|
+
const v20 = [
|
|
146
|
+
p2[0] - p0[0],
|
|
147
|
+
p2[1] - p0[1],
|
|
148
|
+
p2[2] - p0[2]
|
|
149
|
+
];
|
|
133
150
|
const nx = v10[1] * v20[2] - v10[2] * v20[1];
|
|
134
151
|
const ny = v10[2] * v20[0] - v10[0] * v20[2];
|
|
135
152
|
const nz = v10[0] * v20[1] - v10[1] * v20[0];
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
normals[
|
|
140
|
-
normals[
|
|
141
|
-
normals[
|
|
142
|
-
normals[
|
|
143
|
-
normals[
|
|
144
|
-
normals[
|
|
153
|
+
const base0 = i0 * 3;
|
|
154
|
+
const base1 = i1 * 3;
|
|
155
|
+
const base2 = i2 * 3;
|
|
156
|
+
normals[base0 + 0] = normals[base0 + 0] + nx;
|
|
157
|
+
normals[base0 + 1] = normals[base0 + 1] + ny;
|
|
158
|
+
normals[base0 + 2] = normals[base0 + 2] + nz;
|
|
159
|
+
normals[base1 + 0] = normals[base1 + 0] + nx;
|
|
160
|
+
normals[base1 + 1] = normals[base1 + 1] + ny;
|
|
161
|
+
normals[base1 + 2] = normals[base1 + 2] + nz;
|
|
162
|
+
normals[base2 + 0] = normals[base2 + 0] + nx;
|
|
163
|
+
normals[base2 + 1] = normals[base2 + 1] + ny;
|
|
164
|
+
normals[base2 + 2] = normals[base2 + 2] + nz;
|
|
145
165
|
}
|
|
146
166
|
for (let i = 0; i < vertexCount; i++) {
|
|
147
167
|
const nx = normals[i * 3 + 0];
|
|
@@ -218,11 +238,14 @@ var SoftwareRenderer = class {
|
|
|
218
238
|
];
|
|
219
239
|
}
|
|
220
240
|
perspInterp(attrs, invWs, lambdas) {
|
|
221
|
-
const
|
|
222
|
-
const
|
|
241
|
+
const [lambda0, lambda1, lambda2] = lambdas;
|
|
242
|
+
const [invW0, invW1, invW2] = invWs;
|
|
243
|
+
const [attr0, attr1, attr2] = attrs;
|
|
244
|
+
const denom = lambda0 * invW0 + lambda1 * invW1 + lambda2 * invW2;
|
|
245
|
+
const n = attr0.length;
|
|
223
246
|
const out = new Array(n).fill(0);
|
|
224
247
|
for (let j = 0; j < n; j++) {
|
|
225
|
-
out[j] = (
|
|
248
|
+
out[j] = (lambda0 * attr0[j] * invW0 + lambda1 * attr1[j] * invW1 + lambda2 * attr2[j] * invW2) / denom;
|
|
226
249
|
}
|
|
227
250
|
return out;
|
|
228
251
|
}
|
|
@@ -276,9 +299,9 @@ var SoftwareRenderer = class {
|
|
|
276
299
|
vWorldN[i] = [nw[0], nw[1], nw[2]];
|
|
277
300
|
}
|
|
278
301
|
for (let i = 0; i < idx.length; i += 3) {
|
|
279
|
-
const i0 = idx[i + 0]
|
|
280
|
-
const i1 = idx[i + 1]
|
|
281
|
-
const i2 = idx[i + 2]
|
|
302
|
+
const i0 = idx[i + 0];
|
|
303
|
+
const i1 = idx[i + 1];
|
|
304
|
+
const i2 = idx[i + 2];
|
|
282
305
|
if (!(isFinite(vInvW[i0]) && isFinite(vInvW[i1]) && isFinite(vInvW[i2])))
|
|
283
306
|
continue;
|
|
284
307
|
const v0 = vScreen[i0];
|
|
@@ -291,9 +314,21 @@ var SoftwareRenderer = class {
|
|
|
291
314
|
let maxX = Math.min(this.width - 1, Math.max(v0[0], v1[0], v2[0]) | 0);
|
|
292
315
|
let minY = Math.max(0, Math.min(v0[1], v1[1], v2[1]) | 0);
|
|
293
316
|
let maxY = Math.min(this.height - 1, Math.max(v0[1], v1[1], v2[1]) | 0);
|
|
294
|
-
const invW = [
|
|
295
|
-
|
|
296
|
-
|
|
317
|
+
const invW = [
|
|
318
|
+
vInvW[i0],
|
|
319
|
+
vInvW[i1],
|
|
320
|
+
vInvW[i2]
|
|
321
|
+
];
|
|
322
|
+
const ndcZ = [
|
|
323
|
+
vNDCz[i0],
|
|
324
|
+
vNDCz[i1],
|
|
325
|
+
vNDCz[i2]
|
|
326
|
+
];
|
|
327
|
+
const nws = [
|
|
328
|
+
vWorldN[i0],
|
|
329
|
+
vWorldN[i1],
|
|
330
|
+
vWorldN[i2]
|
|
331
|
+
];
|
|
297
332
|
const uv = uvs ? [
|
|
298
333
|
[uvs[i0 * 2 + 0], uvs[i0 * 2 + 1]],
|
|
299
334
|
[uvs[i1 * 2 + 0], uvs[i1 * 2 + 1]],
|
|
@@ -313,8 +348,9 @@ var SoftwareRenderer = class {
|
|
|
313
348
|
const zndc = l0 * ndcZ[0] + l1 * ndcZ[1] + l2 * ndcZ[2];
|
|
314
349
|
const z01 = zndc * 0.5 + 0.5;
|
|
315
350
|
const di = y * this.width + x;
|
|
316
|
-
|
|
317
|
-
|
|
351
|
+
const depth = this.depth;
|
|
352
|
+
if (z01 >= depth[di]) continue;
|
|
353
|
+
depth[di] = z01;
|
|
318
354
|
let baseColor = [
|
|
319
355
|
material.baseColorFactor[0],
|
|
320
356
|
material.baseColorFactor[1],
|
|
@@ -330,9 +366,13 @@ var SoftwareRenderer = class {
|
|
|
330
366
|
);
|
|
331
367
|
baseColor = mulColor(baseColor, texel);
|
|
332
368
|
}
|
|
333
|
-
const
|
|
334
|
-
const nlen = Math.hypot(
|
|
335
|
-
const nrm = [
|
|
369
|
+
const [np0, np1, np2] = this.perspInterp(nws, invW, [l0, l1, l2]);
|
|
370
|
+
const nlen = Math.hypot(np0, np1, np2) || 1;
|
|
371
|
+
const nrm = [
|
|
372
|
+
np0 / nlen,
|
|
373
|
+
np1 / nlen,
|
|
374
|
+
np2 / nlen
|
|
375
|
+
];
|
|
336
376
|
const lightDir = light.dir ?? DEFAULT_LIGHT_DIR;
|
|
337
377
|
const ambient = clamp(
|
|
338
378
|
light.ambient ?? DEFAULT_RENDER_OPTIONS.ambient,
|
|
@@ -467,6 +507,8 @@ function getBufferViewSlice(ctx, bufferViewIndex, byteOffset) {
|
|
|
467
507
|
const bufferView = gltf.bufferViews?.[bufferViewIndex];
|
|
468
508
|
if (!bufferView)
|
|
469
509
|
throw new Error(`Invalid bufferView index ${bufferViewIndex}`);
|
|
510
|
+
if (typeof bufferView.buffer !== "number")
|
|
511
|
+
throw new Error(`bufferView ${bufferViewIndex} missing buffer reference`);
|
|
470
512
|
const bufferIndex = bufferView.buffer;
|
|
471
513
|
const buffer = buffers[bufferIndex];
|
|
472
514
|
if (!buffer) throw new Error(`Missing buffer at index ${bufferIndex}`);
|
|
@@ -500,6 +542,8 @@ function readAccessorAsFloat32(ctx, accessorIndex) {
|
|
|
500
542
|
`Unsupported accessor componentType ${accessor.componentType}`
|
|
501
543
|
);
|
|
502
544
|
const byteOffset = accessor.byteOffset ?? 0;
|
|
545
|
+
if (typeof accessor.bufferView !== "number")
|
|
546
|
+
throw new Error(`Accessor ${accessorIndex} missing bufferView`);
|
|
503
547
|
const {
|
|
504
548
|
array: src,
|
|
505
549
|
stride: bufferViewStride,
|
|
@@ -574,6 +618,8 @@ function readIndices(ctx, accessorIndex) {
|
|
|
574
618
|
throw new Error("Index componentType must be UNSIGNED_BYTE/SHORT/INT");
|
|
575
619
|
}
|
|
576
620
|
const byteOffset = accessor.byteOffset ?? 0;
|
|
621
|
+
if (typeof accessor.bufferView !== "number")
|
|
622
|
+
throw new Error(`Index accessor ${accessorIndex} missing bufferView`);
|
|
577
623
|
const {
|
|
578
624
|
array: src,
|
|
579
625
|
stride: bufferViewStride,
|
|
@@ -630,9 +676,11 @@ function getMaterial(gltf, textures, images, materialIndex) {
|
|
|
630
676
|
const factor = pbr.baseColorFactor || [1, 1, 1, 1];
|
|
631
677
|
let texImg = null;
|
|
632
678
|
if (pbr.baseColorTexture && Number.isInteger(pbr.baseColorTexture.index)) {
|
|
633
|
-
const
|
|
679
|
+
const texIndex = pbr.baseColorTexture.index;
|
|
680
|
+
const tex = textures[texIndex];
|
|
634
681
|
if (tex && Number.isInteger(tex.source)) {
|
|
635
|
-
|
|
682
|
+
const imageIndex = tex.source;
|
|
683
|
+
texImg = images[imageIndex] || null;
|
|
636
684
|
}
|
|
637
685
|
}
|
|
638
686
|
return { baseColorFactor: factor, baseColorTexture: texImg };
|
|
@@ -695,7 +743,7 @@ function createSceneFromGLTF(gltf, resources) {
|
|
|
695
743
|
|
|
696
744
|
// lib/gltf/resourceUtils.ts
|
|
697
745
|
import { PassThrough } from "stream";
|
|
698
|
-
import PImage from "pureimage";
|
|
746
|
+
import * as PImage from "pureimage";
|
|
699
747
|
function bufferFromDataURI(uri) {
|
|
700
748
|
const match = uri.match(/^data:.*?;base64,(.*)$/);
|
|
701
749
|
if (!match) throw new Error(`Unsupported data URI: ${uri.slice(0, 64)}...`);
|
|
@@ -872,12 +920,12 @@ async function loadGLTFWithResourcesFromURL(url, options = {}) {
|
|
|
872
920
|
}
|
|
873
921
|
|
|
874
922
|
// lib/image/pureImageFactory.ts
|
|
875
|
-
import PImage2 from "pureimage";
|
|
923
|
+
import * as PImage2 from "pureimage";
|
|
876
924
|
var pureImageFactory = (width, height) => PImage2.make(width, height);
|
|
877
925
|
|
|
878
926
|
// lib/image/encodePNGToBuffer.ts
|
|
879
927
|
import { PassThrough as PassThrough2 } from "stream";
|
|
880
|
-
import PImage3 from "pureimage";
|
|
928
|
+
import * as PImage3 from "pureimage";
|
|
881
929
|
async function encodePNGToBuffer(image) {
|
|
882
930
|
const passThrough = new PassThrough2();
|
|
883
931
|
const chunks = [];
|
|
@@ -911,7 +959,8 @@ async function renderGLTFToPNGBufferFromURL(url, options = {}) {
|
|
|
911
959
|
function normalizeToArrayBuffer(source) {
|
|
912
960
|
if (source instanceof ArrayBuffer) return source;
|
|
913
961
|
const { buffer, byteOffset, byteLength } = source;
|
|
914
|
-
|
|
962
|
+
const viewBuffer = buffer;
|
|
963
|
+
return viewBuffer.slice(byteOffset, byteOffset + byteLength);
|
|
915
964
|
}
|
|
916
965
|
async function renderGLTFToPNGBufferFromGLBBuffer(glb, options = {}) {
|
|
917
966
|
const arrayBuffer = normalizeToArrayBuffer(glb);
|