minerender 2.1.0-alpha.73 → 2.1.0-alpha.74

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.
@@ -981,7 +981,7 @@ var init_Materials = __esm({
981
981
  };
982
982
  return material;
983
983
  }
984
- static createShadedCanvasMaterial(canvas, transparent = false, shade = false) {
984
+ static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
985
985
  const vertShader = `
986
986
  uniform bool SHADE;
987
987
 
@@ -991,6 +991,10 @@ var init_Materials = __esm({
991
991
  #else
992
992
  varying vec2 vUv;
993
993
  #endif
994
+ #ifdef BOUND_UVS
995
+ attribute vec4 uvBounds;
996
+ flat out vec4 vUvBounds;
997
+ #endif
994
998
  varying vec3 vTint;
995
999
  varying float light;
996
1000
  varying float lift;
@@ -1026,13 +1030,17 @@ var init_Materials = __esm({
1026
1030
  }
1027
1031
 
1028
1032
  vUv = uv;
1033
+ #ifdef BOUND_UVS
1034
+ vUvBounds = uvBounds;
1035
+ #endif
1029
1036
  vTint = color;
1030
1037
 
1038
+ vec4 mvPosition = vec4(position, 1.0);
1031
1039
  #ifdef USE_INSTANCING
1032
- gl_Position = projectionMatrix * viewMatrix * modelMatrix * instanceMatrix * vec4(position, 1.0);
1033
- #else
1034
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
1040
+ mvPosition = instanceMatrix * mvPosition;
1035
1041
  #endif
1042
+ mvPosition = modelViewMatrix * mvPosition;
1043
+ gl_Position = projectionMatrix * mvPosition;
1036
1044
 
1037
1045
  }
1038
1046
  `;
@@ -1052,13 +1060,22 @@ var init_Materials = __esm({
1052
1060
  #else
1053
1061
  varying vec2 vUv;
1054
1062
  #endif
1063
+ #ifdef BOUND_UVS
1064
+ flat in vec4 vUvBounds;
1065
+ #endif
1055
1066
  varying vec3 vTint;
1056
1067
  varying float light;
1057
1068
  varying float lift;
1058
1069
 
1059
1070
  void main(void)
1060
1071
  {
1061
- vec4 color = texture2D(map, vUv);
1072
+ #ifdef BOUND_UVS
1073
+ // Keep edge samples inside their texture even without centroid interpolation.
1074
+ vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
1075
+ #else
1076
+ vec2 mapUv = vUv;
1077
+ #endif
1078
+ vec4 color = texture2D(map, mapUv);
1062
1079
  color.rgb *= vTint;
1063
1080
 
1064
1081
  if (color.a < 0.01) discard;
@@ -1079,7 +1096,8 @@ var init_Materials = __esm({
1079
1096
  }
1080
1097
  `;
1081
1098
  try {
1082
- return new ShaderMaterial({
1099
+ const material = new ShaderMaterial({
1100
+ defines: boundUvs ? { BOUND_UVS: true } : {},
1083
1101
  uniforms: {
1084
1102
  SHADE: { value: true },
1085
1103
  BRIGHTNESS: { value: 1 },
@@ -1097,6 +1115,8 @@ var init_Materials = __esm({
1097
1115
  side: transparent ? DoubleSide : FrontSide,
1098
1116
  alphaTest: 0.5
1099
1117
  });
1118
+ Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
1119
+ return material;
1100
1120
  } catch (e) {
1101
1121
  console.warn(e);
1102
1122
  }
@@ -2977,6 +2997,37 @@ var init_UVMapper = __esm({
2977
2997
  static facesToUv(faces, originalTextureSize, actualTextureSize) {
2978
2998
  return new Float32BufferAttribute2(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
2979
2999
  }
3000
+ /** Bounds texture sampling to texel centres without changing cropped face UVs. */
3001
+ static setAtlasUvBounds(geometry, faces, atlas) {
3002
+ const uv = geometry.getAttribute("uv");
3003
+ const bounds = new Float32Array(uv.count * 4);
3004
+ for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
3005
+ const texture = faces[faceName]?.texture?.substring(1);
3006
+ const position = texture && atlas.positions[texture];
3007
+ const size = texture && atlas.sizes[texture];
3008
+ let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;
3009
+ if (position && size) {
3010
+ minU = position[0] / atlas.image.width;
3011
+ maxU = (position[0] + size[0]) / atlas.image.width;
3012
+ minV = 1 - (position[1] + size[1]) / atlas.image.height;
3013
+ maxV = 1 - position[1] / atlas.image.height;
3014
+ } else {
3015
+ for (let corner = 0; corner < 4; corner++) {
3016
+ const index = faceIndex * 4 + corner;
3017
+ minU = Math.min(minU, uv.getX(index));
3018
+ minV = Math.min(minV, uv.getY(index));
3019
+ maxU = Math.max(maxU, uv.getX(index));
3020
+ maxV = Math.max(maxV, uv.getY(index));
3021
+ }
3022
+ }
3023
+ const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);
3024
+ const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);
3025
+ for (let corner = 0; corner < 4; corner++) {
3026
+ bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);
3027
+ }
3028
+ }
3029
+ geometry.setAttribute("uvBounds", new Float32BufferAttribute2(bounds, 4));
3030
+ }
2980
3031
  static lockUvs(geometry, faces, atlas, rotation) {
2981
3032
  const uv = geometry.getAttribute("uv");
2982
3033
  for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
@@ -5383,6 +5434,7 @@ var init_ModelObject = __esm({
5383
5434
  if (this.options.uvLockRotation) {
5384
5435
  UVMapper.lockUvs(elGeo, el.faces, this.atlas, new Euler7(...this.options.uvLockRotation));
5385
5436
  }
5437
+ UVMapper.setAtlasUvBounds(elGeo, el.faces, this.atlas);
5386
5438
  if (this.options.tints) {
5387
5439
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
5388
5440
  for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
@@ -5448,7 +5500,7 @@ var init_ModelObject = __esm({
5448
5500
  }
5449
5501
  applyTextures() {
5450
5502
  if (this.atlas) {
5451
- const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false);
5503
+ const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false, true);
5452
5504
  this.atlasMaterial = mat;
5453
5505
  this.atlasTexture = mat.uniforms?.map?.value ?? mat.map;
5454
5506
  this.iterateAllMeshes((mesh) => {
@@ -15421,14 +15473,17 @@ var SectionMesh = class _SectionMesh extends Group2 {
15421
15473
  for (const { atlas, x, y } of page.placements) {
15422
15474
  context.drawImage(atlas.image.canvas, x, y);
15423
15475
  }
15424
- const positions = [], normals = [], uvs = [], colors = [], indices = [];
15476
+ const positions = [], normals = [], uvs = [], uvBounds = [], colors = [], indices = [];
15425
15477
  for (const { index, template, cullMask } of page.entries) {
15426
15478
  const position = template.geometry.getAttribute("position");
15427
15479
  const normal = template.geometry.getAttribute("normal");
15428
15480
  const uv = template.geometry.getAttribute("uv");
15481
+ const bounds = template.geometry.getAttribute("uvBounds");
15429
15482
  const color = template.geometry.getAttribute("color");
15430
15483
  const sourceIndices = template.geometry.getIndex();
15431
15484
  const placement = locations.get(template.atlas).placement;
15485
+ const mapU = (u) => (placement.x + u * template.atlas.image.width) / page.width;
15486
+ const mapV = (v) => 1 - (placement.y + (1 - v) * template.atlas.image.height) / page.height;
15432
15487
  const offsetX = index % 16 * 16;
15433
15488
  const offsetY = Math.floor(index / 256) * 16;
15434
15489
  const offsetZ = Math.floor(index / 16) % 16 * 16;
@@ -15439,9 +15494,12 @@ var SectionMesh = class _SectionMesh extends Group2 {
15439
15494
  const vertex = face * 4 + corner;
15440
15495
  positions.push(position.getX(vertex) + offsetX, position.getY(vertex) + offsetY, position.getZ(vertex) + offsetZ);
15441
15496
  normals.push(normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex));
15442
- uvs.push(
15443
- (placement.x + uv.getX(vertex) * template.atlas.image.width) / page.width,
15444
- 1 - (placement.y + (1 - uv.getY(vertex)) * template.atlas.image.height) / page.height
15497
+ uvs.push(mapU(uv.getX(vertex)), mapV(uv.getY(vertex)));
15498
+ uvBounds.push(
15499
+ mapU(bounds?.getX(vertex) ?? 0),
15500
+ mapV(bounds?.getY(vertex) ?? 0),
15501
+ mapU(bounds?.getZ(vertex) ?? 1),
15502
+ mapV(bounds?.getW(vertex) ?? 1)
15445
15503
  );
15446
15504
  colors.push(color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1);
15447
15505
  }
@@ -15452,11 +15510,12 @@ var SectionMesh = class _SectionMesh extends Group2 {
15452
15510
  geometry.setAttribute("position", new Float32BufferAttribute8(positions, 3));
15453
15511
  geometry.setAttribute("normal", new Float32BufferAttribute8(normals, 3));
15454
15512
  geometry.setAttribute("uv", new Float32BufferAttribute8(uvs, 2));
15513
+ geometry.setAttribute("uvBounds", new Float32BufferAttribute8(uvBounds, 4));
15455
15514
  geometry.setAttribute("color", new Float32BufferAttribute8(colors, 3));
15456
15515
  geometry.setIndex(indices);
15457
15516
  geometry.computeBoundingBox();
15458
15517
  geometry.computeBoundingSphere();
15459
- const material = Materials.createShadedCanvasMaterial(canvas, false);
15518
+ const material = Materials.createShadedCanvasMaterial(canvas, false, false, true);
15460
15519
  material.vertexColors = true;
15461
15520
  const texture = material.uniforms?.map?.value ?? material.map;
15462
15521
  const mesh = new Mesh9(geometry, material);