poppygl 0.0.28 → 0.0.30

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.
Files changed (2) hide show
  1. package/dist/index.js +96 -4
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -503,9 +503,86 @@ function srgbEncodeLinear01(linear) {
503
503
  return 1.055 * Math.pow(linear, 1 / 2.4) - 0.055;
504
504
  }
505
505
 
506
+ // lib/utils/srgbDecodeToLinear01.ts
507
+ function srgbDecodeToLinear01(srgb) {
508
+ if (srgb <= 0.04045) return srgb / 12.92;
509
+ return ((srgb + 0.055) / 1.055) ** 2.4;
510
+ }
511
+
506
512
  // lib/utils/clamp.ts
507
513
  var clamp = (value, min, max) => Math.max(min, Math.min(max, value));
508
514
 
515
+ // lib/render/clipMeshToNearPlane.ts
516
+ function clipMeshToNearPlane(mesh, mvp) {
517
+ const count = mesh.positions.length / 3;
518
+ const distances = new Float64Array(count);
519
+ let needsClipping = false;
520
+ for (let i = 0; i < count; i++) {
521
+ const distance = (mvp[2] + mvp[3]) * mesh.positions[i * 3] + (mvp[6] + mvp[7]) * mesh.positions[i * 3 + 1] + (mvp[10] + mvp[11]) * mesh.positions[i * 3 + 2] + mvp[14] + mvp[15];
522
+ distances[i] = distance;
523
+ if (!(distance >= 0)) needsClipping = true;
524
+ }
525
+ if (!needsClipping) return mesh;
526
+ const positions = Array.from(mesh.positions);
527
+ const normals = mesh.normals ? Array.from(mesh.normals) : null;
528
+ const uvs = mesh.uvs ? Array.from(mesh.uvs) : null;
529
+ const colors = mesh.colors ? Array.from(mesh.colors) : null;
530
+ const indices = [];
531
+ const sourceIndices = mesh.indices ?? Uint32Array.from({ length: count }, (_, i) => i);
532
+ const intersections = /* @__PURE__ */ new Map();
533
+ const intersect = (a, b) => {
534
+ if (a > b) [a, b] = [b, a];
535
+ if (distances[a] === 0) return a;
536
+ if (distances[b] === 0) return b;
537
+ const key = `${a}:${b}`;
538
+ const cached = intersections.get(key);
539
+ if (cached !== void 0) return cached;
540
+ const t = distances[a] / (distances[a] - distances[b]);
541
+ const index = positions.length / 3;
542
+ const interpolate = (values, size) => {
543
+ if (!values) return;
544
+ for (let k = 0; k < size; k++) {
545
+ const start = values[a * size + k];
546
+ values.push(start + t * (values[b * size + k] - start));
547
+ }
548
+ };
549
+ interpolate(positions, 3);
550
+ interpolate(normals, 3);
551
+ interpolate(uvs, 2);
552
+ interpolate(colors, 3);
553
+ intersections.set(key, index);
554
+ return index;
555
+ };
556
+ for (let i = 0; i < sourceIndices.length; i += 3) {
557
+ const triangle = [
558
+ sourceIndices[i],
559
+ sourceIndices[i + 1],
560
+ sourceIndices[i + 2]
561
+ ];
562
+ if (triangle.some((vertex) => !Number.isFinite(distances[vertex]))) continue;
563
+ const polygon = [];
564
+ for (let j = 0; j < 3; j++) {
565
+ const a = triangle[j];
566
+ const b = triangle[(j + 1) % 3];
567
+ const aInside = distances[a] >= 0;
568
+ const bInside = distances[b] >= 0;
569
+ if (aInside) polygon.push(a);
570
+ if (aInside !== bInside) polygon.push(intersect(a, b));
571
+ }
572
+ for (let j = 1; j + 1 < polygon.length; j++) {
573
+ indices.push(polygon[0], polygon[j], polygon[j + 1]);
574
+ }
575
+ }
576
+ return {
577
+ ...mesh,
578
+ positions: new Float32Array(positions),
579
+ normals: normals ? new Float32Array(normals) : null,
580
+ uvs: uvs ? new Float32Array(uvs) : null,
581
+ colors: colors ? new Float32Array(colors) : null,
582
+ indices: new Uint32Array(indices)
583
+ };
584
+ }
585
+
509
586
  // lib/render/SoftwareRenderer.ts
510
587
  var SoftwareRenderer = class {
511
588
  width;
@@ -676,15 +753,15 @@ var SoftwareRenderer = class {
676
753
  return out;
677
754
  }
678
755
  drawMesh(mesh, camera, light, material, cullBackFaces = true, gammaOut = true) {
679
- const { positions, normals, uvs, indices, model, colors } = mesh;
756
+ let { positions, normals, uvs, indices, model, colors } = mesh;
680
757
  const view = camera.view;
681
758
  const proj = camera.proj;
682
759
  const mvp = mat43.create();
683
760
  mat43.multiply(mvp, proj, mat43.multiply(mat43.create(), view, model));
684
761
  const normalMat = mat3.create();
685
762
  mat3.normalFromMat4(normalMat, model);
686
- const vertexCount = positions.length / 3 | 0;
687
- const idx = indices ?? (() => {
763
+ let vertexCount = positions.length / 3 | 0;
764
+ let idx = indices ?? (() => {
688
765
  const a = new Uint32Array(vertexCount);
689
766
  for (let i = 0; i < vertexCount; i++) a[i] = i;
690
767
  return a;
@@ -693,6 +770,16 @@ var SoftwareRenderer = class {
693
770
  if (!useNormals) {
694
771
  useNormals = computeSmoothNormals(positions, idx);
695
772
  }
773
+ const clipped = clipMeshToNearPlane(
774
+ { ...mesh, normals: useNormals, indices: idx },
775
+ mvp
776
+ );
777
+ positions = clipped.positions;
778
+ useNormals = clipped.normals;
779
+ uvs = clipped.uvs;
780
+ colors = clipped.colors;
781
+ idx = clipped.indices;
782
+ vertexCount = positions.length / 3;
696
783
  const vScreen = new Array(vertexCount);
697
784
  const vInvW = new Float32Array(vertexCount);
698
785
  const vNDCz = new Float32Array(vertexCount);
@@ -808,7 +895,12 @@ var SoftwareRenderer = class {
808
895
  uvp[0],
809
896
  uvp[1]
810
897
  );
811
- baseColor = mulColor(baseColor, texel);
898
+ baseColor = mulColor(baseColor, [
899
+ srgbDecodeToLinear01(texel[0]),
900
+ srgbDecodeToLinear01(texel[1]),
901
+ srgbDecodeToLinear01(texel[2]),
902
+ texel[3]
903
+ ]);
812
904
  }
813
905
  const [cr, cg, cb] = this.perspInterp(cs, invW, [l0, l1, l2]);
814
906
  baseColor = [
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "poppygl",
3
3
  "main": "dist/index.js",
4
- "version": "0.0.28",
4
+ "version": "0.0.30",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "https://github.com/tscircuit/poppygl.git"