minerender 2.1.0-alpha.73 → 2.1.0-alpha.75

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/bundle.js CHANGED
@@ -42539,7 +42539,7 @@ void main() {
42539
42539
  };
42540
42540
  return material;
42541
42541
  }
42542
- static createShadedCanvasMaterial(canvas, transparent = false, shade = false) {
42542
+ static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
42543
42543
  const vertShader = `
42544
42544
  uniform bool SHADE;
42545
42545
 
@@ -42549,6 +42549,10 @@ void main() {
42549
42549
  #else
42550
42550
  varying vec2 vUv;
42551
42551
  #endif
42552
+ #ifdef BOUND_UVS
42553
+ attribute vec4 uvBounds;
42554
+ flat out vec4 vUvBounds;
42555
+ #endif
42552
42556
  varying vec3 vTint;
42553
42557
  varying float light;
42554
42558
  varying float lift;
@@ -42584,13 +42588,17 @@ void main() {
42584
42588
  }
42585
42589
 
42586
42590
  vUv = uv;
42591
+ #ifdef BOUND_UVS
42592
+ vUvBounds = uvBounds;
42593
+ #endif
42587
42594
  vTint = color;
42588
42595
 
42596
+ vec4 mvPosition = vec4(position, 1.0);
42589
42597
  #ifdef USE_INSTANCING
42590
- gl_Position = projectionMatrix * viewMatrix * modelMatrix * instanceMatrix * vec4(position, 1.0);
42591
- #else
42592
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
42598
+ mvPosition = instanceMatrix * mvPosition;
42593
42599
  #endif
42600
+ mvPosition = modelViewMatrix * mvPosition;
42601
+ gl_Position = projectionMatrix * mvPosition;
42594
42602
 
42595
42603
  }
42596
42604
  `;
@@ -42610,13 +42618,22 @@ void main() {
42610
42618
  #else
42611
42619
  varying vec2 vUv;
42612
42620
  #endif
42621
+ #ifdef BOUND_UVS
42622
+ flat in vec4 vUvBounds;
42623
+ #endif
42613
42624
  varying vec3 vTint;
42614
42625
  varying float light;
42615
42626
  varying float lift;
42616
42627
 
42617
42628
  void main(void)
42618
42629
  {
42619
- vec4 color = texture2D(map, vUv);
42630
+ #ifdef BOUND_UVS
42631
+ // Keep edge samples inside their texture even without centroid interpolation.
42632
+ vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
42633
+ #else
42634
+ vec2 mapUv = vUv;
42635
+ #endif
42636
+ vec4 color = texture2D(map, mapUv);
42620
42637
  color.rgb *= vTint;
42621
42638
 
42622
42639
  if (color.a < 0.01) discard;
@@ -42637,7 +42654,8 @@ void main() {
42637
42654
  }
42638
42655
  `;
42639
42656
  try {
42640
- return new ShaderMaterial({
42657
+ const material = new ShaderMaterial({
42658
+ defines: boundUvs ? { BOUND_UVS: true } : {},
42641
42659
  uniforms: {
42642
42660
  SHADE: { value: true },
42643
42661
  BRIGHTNESS: { value: 1 },
@@ -42655,6 +42673,8 @@ void main() {
42655
42673
  side: transparent ? DoubleSide : FrontSide,
42656
42674
  alphaTest: 0.5
42657
42675
  });
42676
+ Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
42677
+ return material;
42658
42678
  } catch (e6) {
42659
42679
  console.warn(e6);
42660
42680
  }
@@ -87904,6 +87924,37 @@ ${key}` : key;
87904
87924
  static facesToUv(faces, originalTextureSize, actualTextureSize) {
87905
87925
  return new Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
87906
87926
  }
87927
+ /** Bounds texture sampling to texel centres without changing cropped face UVs. */
87928
+ static setAtlasUvBounds(geometry, faces, atlas) {
87929
+ const uv = geometry.getAttribute("uv");
87930
+ const bounds = new Float32Array(uv.count * 4);
87931
+ for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
87932
+ const texture = faces[faceName]?.texture?.substring(1);
87933
+ const position = texture && atlas.positions[texture];
87934
+ const size = texture && atlas.sizes[texture];
87935
+ let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;
87936
+ if (position && size) {
87937
+ minU = position[0] / atlas.image.width;
87938
+ maxU = (position[0] + size[0]) / atlas.image.width;
87939
+ minV = 1 - (position[1] + size[1]) / atlas.image.height;
87940
+ maxV = 1 - position[1] / atlas.image.height;
87941
+ } else {
87942
+ for (let corner = 0; corner < 4; corner++) {
87943
+ const index = faceIndex * 4 + corner;
87944
+ minU = Math.min(minU, uv.getX(index));
87945
+ minV = Math.min(minV, uv.getY(index));
87946
+ maxU = Math.max(maxU, uv.getX(index));
87947
+ maxV = Math.max(maxV, uv.getY(index));
87948
+ }
87949
+ }
87950
+ const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);
87951
+ const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);
87952
+ for (let corner = 0; corner < 4; corner++) {
87953
+ bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);
87954
+ }
87955
+ }
87956
+ geometry.setAttribute("uvBounds", new Float32BufferAttribute(bounds, 4));
87957
+ }
87907
87958
  static lockUvs(geometry, faces, atlas, rotation) {
87908
87959
  const uv = geometry.getAttribute("uv");
87909
87960
  for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
@@ -90345,6 +90396,7 @@ ${shader.fragmentShader}`.replace(
90345
90396
  if (this.options.uvLockRotation) {
90346
90397
  UVMapper.lockUvs(elGeo, el.faces, this.atlas, new Euler(...this.options.uvLockRotation));
90347
90398
  }
90399
+ UVMapper.setAtlasUvBounds(elGeo, el.faces, this.atlas);
90348
90400
  if (this.options.tints) {
90349
90401
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
90350
90402
  for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
@@ -90410,7 +90462,7 @@ ${shader.fragmentShader}`.replace(
90410
90462
  }
90411
90463
  applyTextures() {
90412
90464
  if (this.atlas) {
90413
- const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false);
90465
+ const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false, true);
90414
90466
  this.atlasMaterial = mat;
90415
90467
  this.atlasTexture = mat.uniforms?.map?.value ?? mat.map;
90416
90468
  this.iterateAllMeshes((mesh) => {
@@ -105471,13 +105523,7 @@ gl_FragDepth=readDepth(vUv);
105471
105523
  async placeChunk(chunk, executor) {
105472
105524
  const changes = /* @__PURE__ */ new Map();
105473
105525
  try {
105474
- const previous = [...this._chunks.entries()].filter(([, section]) => section.x === chunk.x && section.z === chunk.z);
105475
- for (const [key, section] of previous) {
105476
- this._chunks.delete(key);
105477
- await section.clear(async (positions) => {
105478
- for (const pos of positions) changes.set(pos.toArray().join(","), pos);
105479
- });
105480
- }
105526
+ await this.clearChunkColumn(chunk.x, chunk.z, changes);
105481
105527
  for (const section of chunk.sections) {
105482
105528
  const blocks = [];
105483
105529
  for (let index = 0; index < 4096; index++) {
@@ -105497,6 +105543,31 @@ gl_FragDepth=readDepth(vUv);
105497
105543
  await this.updateCulling([...changes.values()]);
105498
105544
  }
105499
105545
  }
105546
+ /**
105547
+ * Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
105548
+ * Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
105549
+ */
105550
+ async unloadChunkColumn(x4, z4) {
105551
+ if (!Number.isInteger(x4) || !Number.isInteger(z4)) {
105552
+ throw new RangeError("Chunk column coordinates must be integers");
105553
+ }
105554
+ await this.culling;
105555
+ const changes = /* @__PURE__ */ new Map();
105556
+ try {
105557
+ await this.clearChunkColumn(x4, z4, changes);
105558
+ } finally {
105559
+ await this.updateCulling([...changes.values()]);
105560
+ }
105561
+ }
105562
+ async clearChunkColumn(x4, z4, changes) {
105563
+ const previous = [...this._chunks.entries()].filter(([, section]) => section.x === x4 && section.z === z4);
105564
+ for (const [key, section] of previous) {
105565
+ this._chunks.delete(key);
105566
+ await section.clear(async (positions) => {
105567
+ for (const pos of positions) changes.set(pos.toArray().join(","), pos);
105568
+ });
105569
+ }
105570
+ }
105500
105571
  async clear() {
105501
105572
  await this.culling;
105502
105573
  const chunks = [...this._chunks.values()];
@@ -105668,14 +105739,17 @@ gl_FragDepth=readDepth(vUv);
105668
105739
  for (const { atlas, x: x4, y: y5 } of page.placements) {
105669
105740
  context.drawImage(atlas.image.canvas, x4, y5);
105670
105741
  }
105671
- const positions = [], normals = [], uvs = [], colors = [], indices = [];
105742
+ const positions = [], normals = [], uvs = [], uvBounds = [], colors = [], indices = [];
105672
105743
  for (const { index, template, cullMask } of page.entries) {
105673
105744
  const position = template.geometry.getAttribute("position");
105674
105745
  const normal = template.geometry.getAttribute("normal");
105675
105746
  const uv = template.geometry.getAttribute("uv");
105747
+ const bounds = template.geometry.getAttribute("uvBounds");
105676
105748
  const color2 = template.geometry.getAttribute("color");
105677
105749
  const sourceIndices = template.geometry.getIndex();
105678
105750
  const placement = locations.get(template.atlas).placement;
105751
+ const mapU = (u4) => (placement.x + u4 * template.atlas.image.width) / page.width;
105752
+ const mapV = (v5) => 1 - (placement.y + (1 - v5) * template.atlas.image.height) / page.height;
105679
105753
  const offsetX = index % 16 * 16;
105680
105754
  const offsetY = Math.floor(index / 256) * 16;
105681
105755
  const offsetZ = Math.floor(index / 16) % 16 * 16;
@@ -105686,9 +105760,12 @@ gl_FragDepth=readDepth(vUv);
105686
105760
  const vertex2 = face * 4 + corner;
105687
105761
  positions.push(position.getX(vertex2) + offsetX, position.getY(vertex2) + offsetY, position.getZ(vertex2) + offsetZ);
105688
105762
  normals.push(normal.getX(vertex2), normal.getY(vertex2), normal.getZ(vertex2));
105689
- uvs.push(
105690
- (placement.x + uv.getX(vertex2) * template.atlas.image.width) / page.width,
105691
- 1 - (placement.y + (1 - uv.getY(vertex2)) * template.atlas.image.height) / page.height
105763
+ uvs.push(mapU(uv.getX(vertex2)), mapV(uv.getY(vertex2)));
105764
+ uvBounds.push(
105765
+ mapU(bounds?.getX(vertex2) ?? 0),
105766
+ mapV(bounds?.getY(vertex2) ?? 0),
105767
+ mapU(bounds?.getZ(vertex2) ?? 1),
105768
+ mapV(bounds?.getW(vertex2) ?? 1)
105692
105769
  );
105693
105770
  colors.push(color2?.getX(vertex2) ?? 1, color2?.getY(vertex2) ?? 1, color2?.getZ(vertex2) ?? 1);
105694
105771
  }
@@ -105699,11 +105776,12 @@ gl_FragDepth=readDepth(vUv);
105699
105776
  geometry.setAttribute("position", new Float32BufferAttribute(positions, 3));
105700
105777
  geometry.setAttribute("normal", new Float32BufferAttribute(normals, 3));
105701
105778
  geometry.setAttribute("uv", new Float32BufferAttribute(uvs, 2));
105779
+ geometry.setAttribute("uvBounds", new Float32BufferAttribute(uvBounds, 4));
105702
105780
  geometry.setAttribute("color", new Float32BufferAttribute(colors, 3));
105703
105781
  geometry.setIndex(indices);
105704
105782
  geometry.computeBoundingBox();
105705
105783
  geometry.computeBoundingSphere();
105706
- const material = Materials.createShadedCanvasMaterial(canvas, false);
105784
+ const material = Materials.createShadedCanvasMaterial(canvas, false, false, true);
105707
105785
  material.vertexColors = true;
105708
105786
  const texture = material.uniforms?.map?.value ?? material.map;
105709
105787
  const mesh = new Mesh(geometry, material);