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.
@@ -1031,7 +1031,7 @@ var init_Materials = __esm({
1031
1031
  };
1032
1032
  return material;
1033
1033
  }
1034
- static createShadedCanvasMaterial(canvas, transparent = false, shade = false) {
1034
+ static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
1035
1035
  const vertShader = `
1036
1036
  uniform bool SHADE;
1037
1037
 
@@ -1041,6 +1041,10 @@ var init_Materials = __esm({
1041
1041
  #else
1042
1042
  varying vec2 vUv;
1043
1043
  #endif
1044
+ #ifdef BOUND_UVS
1045
+ attribute vec4 uvBounds;
1046
+ flat out vec4 vUvBounds;
1047
+ #endif
1044
1048
  varying vec3 vTint;
1045
1049
  varying float light;
1046
1050
  varying float lift;
@@ -1076,13 +1080,17 @@ var init_Materials = __esm({
1076
1080
  }
1077
1081
 
1078
1082
  vUv = uv;
1083
+ #ifdef BOUND_UVS
1084
+ vUvBounds = uvBounds;
1085
+ #endif
1079
1086
  vTint = color;
1080
1087
 
1088
+ vec4 mvPosition = vec4(position, 1.0);
1081
1089
  #ifdef USE_INSTANCING
1082
- gl_Position = projectionMatrix * viewMatrix * modelMatrix * instanceMatrix * vec4(position, 1.0);
1083
- #else
1084
- gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
1090
+ mvPosition = instanceMatrix * mvPosition;
1085
1091
  #endif
1092
+ mvPosition = modelViewMatrix * mvPosition;
1093
+ gl_Position = projectionMatrix * mvPosition;
1086
1094
 
1087
1095
  }
1088
1096
  `;
@@ -1102,13 +1110,22 @@ var init_Materials = __esm({
1102
1110
  #else
1103
1111
  varying vec2 vUv;
1104
1112
  #endif
1113
+ #ifdef BOUND_UVS
1114
+ flat in vec4 vUvBounds;
1115
+ #endif
1105
1116
  varying vec3 vTint;
1106
1117
  varying float light;
1107
1118
  varying float lift;
1108
1119
 
1109
1120
  void main(void)
1110
1121
  {
1111
- vec4 color = texture2D(map, vUv);
1122
+ #ifdef BOUND_UVS
1123
+ // Keep edge samples inside their texture even without centroid interpolation.
1124
+ vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
1125
+ #else
1126
+ vec2 mapUv = vUv;
1127
+ #endif
1128
+ vec4 color = texture2D(map, mapUv);
1112
1129
  color.rgb *= vTint;
1113
1130
 
1114
1131
  if (color.a < 0.01) discard;
@@ -1129,7 +1146,8 @@ var init_Materials = __esm({
1129
1146
  }
1130
1147
  `;
1131
1148
  try {
1132
- return new ShaderMaterial({
1149
+ const material = new ShaderMaterial({
1150
+ defines: boundUvs ? { BOUND_UVS: true } : {},
1133
1151
  uniforms: {
1134
1152
  SHADE: { value: true },
1135
1153
  BRIGHTNESS: { value: 1 },
@@ -1147,6 +1165,8 @@ var init_Materials = __esm({
1147
1165
  side: transparent ? DoubleSide : FrontSide,
1148
1166
  alphaTest: 0.5
1149
1167
  });
1168
+ Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
1169
+ return material;
1150
1170
  } catch (e) {
1151
1171
  console.warn(e);
1152
1172
  }
@@ -3066,6 +3086,37 @@ var init_UVMapper = __esm({
3066
3086
  static facesToUv(faces, originalTextureSize, actualTextureSize) {
3067
3087
  return new Float32BufferAttribute2(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
3068
3088
  }
3089
+ /** Bounds texture sampling to texel centres without changing cropped face UVs. */
3090
+ static setAtlasUvBounds(geometry, faces, atlas) {
3091
+ const uv = geometry.getAttribute("uv");
3092
+ const bounds = new Float32Array(uv.count * 4);
3093
+ for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
3094
+ const texture = faces[faceName]?.texture?.substring(1);
3095
+ const position = texture && atlas.positions[texture];
3096
+ const size = texture && atlas.sizes[texture];
3097
+ let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;
3098
+ if (position && size) {
3099
+ minU = position[0] / atlas.image.width;
3100
+ maxU = (position[0] + size[0]) / atlas.image.width;
3101
+ minV = 1 - (position[1] + size[1]) / atlas.image.height;
3102
+ maxV = 1 - position[1] / atlas.image.height;
3103
+ } else {
3104
+ for (let corner = 0; corner < 4; corner++) {
3105
+ const index = faceIndex * 4 + corner;
3106
+ minU = Math.min(minU, uv.getX(index));
3107
+ minV = Math.min(minV, uv.getY(index));
3108
+ maxU = Math.max(maxU, uv.getX(index));
3109
+ maxV = Math.max(maxV, uv.getY(index));
3110
+ }
3111
+ }
3112
+ const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);
3113
+ const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);
3114
+ for (let corner = 0; corner < 4; corner++) {
3115
+ bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);
3116
+ }
3117
+ }
3118
+ geometry.setAttribute("uvBounds", new Float32BufferAttribute2(bounds, 4));
3119
+ }
3069
3120
  static lockUvs(geometry, faces, atlas, rotation) {
3070
3121
  const uv = geometry.getAttribute("uv");
3071
3122
  for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
@@ -5477,6 +5528,7 @@ var init_ModelObject = __esm({
5477
5528
  if (this.options.uvLockRotation) {
5478
5529
  UVMapper.lockUvs(elGeo, el.faces, this.atlas, new Euler7(...this.options.uvLockRotation));
5479
5530
  }
5531
+ UVMapper.setAtlasUvBounds(elGeo, el.faces, this.atlas);
5480
5532
  if (this.options.tints) {
5481
5533
  const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
5482
5534
  for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
@@ -5542,7 +5594,7 @@ var init_ModelObject = __esm({
5542
5594
  }
5543
5595
  applyTextures() {
5544
5596
  if (this.atlas) {
5545
- const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false);
5597
+ const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false, true);
5546
5598
  this.atlasMaterial = mat;
5547
5599
  this.atlasTexture = mat.uniforms?.map?.value ?? mat.map;
5548
5600
  this.iterateAllMeshes((mesh) => {
@@ -15478,14 +15530,17 @@ var SectionMesh = class _SectionMesh extends Group2 {
15478
15530
  for (const { atlas, x, y } of page.placements) {
15479
15531
  context.drawImage(atlas.image.canvas, x, y);
15480
15532
  }
15481
- const positions = [], normals = [], uvs = [], colors = [], indices = [];
15533
+ const positions = [], normals = [], uvs = [], uvBounds = [], colors = [], indices = [];
15482
15534
  for (const { index, template, cullMask } of page.entries) {
15483
15535
  const position = template.geometry.getAttribute("position");
15484
15536
  const normal = template.geometry.getAttribute("normal");
15485
15537
  const uv = template.geometry.getAttribute("uv");
15538
+ const bounds = template.geometry.getAttribute("uvBounds");
15486
15539
  const color = template.geometry.getAttribute("color");
15487
15540
  const sourceIndices = template.geometry.getIndex();
15488
15541
  const placement = locations.get(template.atlas).placement;
15542
+ const mapU = (u) => (placement.x + u * template.atlas.image.width) / page.width;
15543
+ const mapV = (v) => 1 - (placement.y + (1 - v) * template.atlas.image.height) / page.height;
15489
15544
  const offsetX = index % 16 * 16;
15490
15545
  const offsetY = Math.floor(index / 256) * 16;
15491
15546
  const offsetZ = Math.floor(index / 16) % 16 * 16;
@@ -15496,9 +15551,12 @@ var SectionMesh = class _SectionMesh extends Group2 {
15496
15551
  const vertex = face * 4 + corner;
15497
15552
  positions.push(position.getX(vertex) + offsetX, position.getY(vertex) + offsetY, position.getZ(vertex) + offsetZ);
15498
15553
  normals.push(normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex));
15499
- uvs.push(
15500
- (placement.x + uv.getX(vertex) * template.atlas.image.width) / page.width,
15501
- 1 - (placement.y + (1 - uv.getY(vertex)) * template.atlas.image.height) / page.height
15554
+ uvs.push(mapU(uv.getX(vertex)), mapV(uv.getY(vertex)));
15555
+ uvBounds.push(
15556
+ mapU(bounds?.getX(vertex) ?? 0),
15557
+ mapV(bounds?.getY(vertex) ?? 0),
15558
+ mapU(bounds?.getZ(vertex) ?? 1),
15559
+ mapV(bounds?.getW(vertex) ?? 1)
15502
15560
  );
15503
15561
  colors.push(color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1);
15504
15562
  }
@@ -15509,11 +15567,12 @@ var SectionMesh = class _SectionMesh extends Group2 {
15509
15567
  geometry.setAttribute("position", new Float32BufferAttribute8(positions, 3));
15510
15568
  geometry.setAttribute("normal", new Float32BufferAttribute8(normals, 3));
15511
15569
  geometry.setAttribute("uv", new Float32BufferAttribute8(uvs, 2));
15570
+ geometry.setAttribute("uvBounds", new Float32BufferAttribute8(uvBounds, 4));
15512
15571
  geometry.setAttribute("color", new Float32BufferAttribute8(colors, 3));
15513
15572
  geometry.setIndex(indices);
15514
15573
  geometry.computeBoundingBox();
15515
15574
  geometry.computeBoundingSphere();
15516
- const material = Materials.createShadedCanvasMaterial(canvas, false);
15575
+ const material = Materials.createShadedCanvasMaterial(canvas, false, false, true);
15517
15576
  material.vertexColors = true;
15518
15577
  const texture = material.uniforms?.map?.value ?? material.map;
15519
15578
  const mesh = new Mesh9(geometry, material);