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/browser/index.d.mts +9 -1
- package/dist/browser/index.d.ts +9 -1
- package/dist/browser/index.js +97 -19
- package/dist/browser/index.js.map +1 -1
- package/dist/browser/index.mjs +97 -19
- package/dist/browser/index.mjs.map +1 -1
- package/dist/bundle.js +97 -19
- package/dist/bundle.js.map +1 -1
- package/dist/node/index.d.mts +9 -1
- package/dist/node/index.d.ts +9 -1
- package/dist/node/index.js +97 -19
- package/dist/node/index.js.map +1 -1
- package/dist/node/index.mjs +97 -19
- package/dist/node/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/node/index.d.mts
CHANGED
|
@@ -292,7 +292,7 @@ declare class Materials {
|
|
|
292
292
|
*/
|
|
293
293
|
static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode?: EntityRenderMode, tint?: ColorRepresentation): MeshBasicMaterial;
|
|
294
294
|
static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial;
|
|
295
|
-
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean): Material;
|
|
295
|
+
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean, boundUvs?: boolean): Material;
|
|
296
296
|
static getImage(key: MaterialKey): Material;
|
|
297
297
|
static needsUpdate(mat: Material): void;
|
|
298
298
|
}
|
|
@@ -694,6 +694,8 @@ declare class UVMapper {
|
|
|
694
694
|
static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void;
|
|
695
695
|
static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[];
|
|
696
696
|
static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute;
|
|
697
|
+
/** Bounds texture sampling to texel centres without changing cropped face UVs. */
|
|
698
|
+
static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void;
|
|
697
699
|
static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void;
|
|
698
700
|
static getAtlas(model: Model): Promise<Maybe<TextureAtlas>>;
|
|
699
701
|
static fillMissingTextureKeys<T>(textures: ModelTextures, target: {
|
|
@@ -2516,6 +2518,12 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
2516
2518
|
private placeBlocks;
|
|
2517
2519
|
/** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
|
|
2518
2520
|
placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
|
|
2521
|
+
/**
|
|
2522
|
+
* Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
|
|
2523
|
+
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
2524
|
+
*/
|
|
2525
|
+
unloadChunkColumn(x: number, z: number): Promise<void>;
|
|
2526
|
+
private clearChunkColumn;
|
|
2519
2527
|
clear(): Promise<void>;
|
|
2520
2528
|
private updateCulling;
|
|
2521
2529
|
private getOrCreateChunkAt;
|
package/dist/node/index.d.ts
CHANGED
|
@@ -292,7 +292,7 @@ declare class Materials {
|
|
|
292
292
|
*/
|
|
293
293
|
static createEntityCanvasMaterial(canvas: HTMLCanvasElement, mode?: EntityRenderMode, tint?: ColorRepresentation): MeshBasicMaterial;
|
|
294
294
|
static createGuiCanvasMaterial(canvas: HTMLCanvasElement): MeshBasicMaterial;
|
|
295
|
-
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean): Material;
|
|
295
|
+
static createShadedCanvasMaterial(canvas: HTMLCanvasElement, transparent?: boolean, shade?: boolean, boundUvs?: boolean): Material;
|
|
296
296
|
static getImage(key: MaterialKey): Material;
|
|
297
297
|
static needsUpdate(mat: Material): void;
|
|
298
298
|
}
|
|
@@ -694,6 +694,8 @@ declare class UVMapper {
|
|
|
694
694
|
static setCubeUvs(geometry: BoxGeometry, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray, faces: ModelFaces): void;
|
|
695
695
|
static facesToUvArray(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): number[];
|
|
696
696
|
static facesToUv(faces: ModelFaces, originalTextureSize: DoubleArray, actualTextureSize: DoubleArray): Float32BufferAttribute;
|
|
697
|
+
/** Bounds texture sampling to texel centres without changing cropped face UVs. */
|
|
698
|
+
static setAtlasUvBounds(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas): void;
|
|
697
699
|
static lockUvs(geometry: BoxGeometry, faces: ModelFaces, atlas: TextureAtlas, rotation: Euler): void;
|
|
698
700
|
static getAtlas(model: Model): Promise<Maybe<TextureAtlas>>;
|
|
699
701
|
static fillMissingTextureKeys<T>(textures: ModelTextures, target: {
|
|
@@ -2516,6 +2518,12 @@ declare class MineRenderWorld<SectionMeshing extends boolean = false> {
|
|
|
2516
2518
|
private placeBlocks;
|
|
2517
2519
|
/** Replaces one chunk column's blocks. Entity NBT remains available on the parsed chunk. */
|
|
2518
2520
|
placeChunk(chunk: AnvilChunk, executor?: BatchedExecutor): Promise<void>;
|
|
2521
|
+
/**
|
|
2522
|
+
* Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
|
|
2523
|
+
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
2524
|
+
*/
|
|
2525
|
+
unloadChunkColumn(x: number, z: number): Promise<void>;
|
|
2526
|
+
private clearChunkColumn;
|
|
2519
2527
|
clear(): Promise<void>;
|
|
2520
2528
|
private updateCulling;
|
|
2521
2529
|
private getOrCreateChunkAt;
|
package/dist/node/index.js
CHANGED
|
@@ -1032,7 +1032,7 @@ var init_Materials = __esm({
|
|
|
1032
1032
|
};
|
|
1033
1033
|
return material;
|
|
1034
1034
|
}
|
|
1035
|
-
static createShadedCanvasMaterial(canvas, transparent = false, shade = false) {
|
|
1035
|
+
static createShadedCanvasMaterial(canvas, transparent = false, shade = false, boundUvs = false) {
|
|
1036
1036
|
const vertShader = `
|
|
1037
1037
|
uniform bool SHADE;
|
|
1038
1038
|
|
|
@@ -1042,6 +1042,10 @@ var init_Materials = __esm({
|
|
|
1042
1042
|
#else
|
|
1043
1043
|
varying vec2 vUv;
|
|
1044
1044
|
#endif
|
|
1045
|
+
#ifdef BOUND_UVS
|
|
1046
|
+
attribute vec4 uvBounds;
|
|
1047
|
+
flat out vec4 vUvBounds;
|
|
1048
|
+
#endif
|
|
1045
1049
|
varying vec3 vTint;
|
|
1046
1050
|
varying float light;
|
|
1047
1051
|
varying float lift;
|
|
@@ -1077,13 +1081,17 @@ var init_Materials = __esm({
|
|
|
1077
1081
|
}
|
|
1078
1082
|
|
|
1079
1083
|
vUv = uv;
|
|
1084
|
+
#ifdef BOUND_UVS
|
|
1085
|
+
vUvBounds = uvBounds;
|
|
1086
|
+
#endif
|
|
1080
1087
|
vTint = color;
|
|
1081
1088
|
|
|
1089
|
+
vec4 mvPosition = vec4(position, 1.0);
|
|
1082
1090
|
#ifdef USE_INSTANCING
|
|
1083
|
-
|
|
1084
|
-
#else
|
|
1085
|
-
gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );
|
|
1091
|
+
mvPosition = instanceMatrix * mvPosition;
|
|
1086
1092
|
#endif
|
|
1093
|
+
mvPosition = modelViewMatrix * mvPosition;
|
|
1094
|
+
gl_Position = projectionMatrix * mvPosition;
|
|
1087
1095
|
|
|
1088
1096
|
}
|
|
1089
1097
|
`;
|
|
@@ -1103,13 +1111,22 @@ var init_Materials = __esm({
|
|
|
1103
1111
|
#else
|
|
1104
1112
|
varying vec2 vUv;
|
|
1105
1113
|
#endif
|
|
1114
|
+
#ifdef BOUND_UVS
|
|
1115
|
+
flat in vec4 vUvBounds;
|
|
1116
|
+
#endif
|
|
1106
1117
|
varying vec3 vTint;
|
|
1107
1118
|
varying float light;
|
|
1108
1119
|
varying float lift;
|
|
1109
1120
|
|
|
1110
1121
|
void main(void)
|
|
1111
1122
|
{
|
|
1112
|
-
|
|
1123
|
+
#ifdef BOUND_UVS
|
|
1124
|
+
// Keep edge samples inside their texture even without centroid interpolation.
|
|
1125
|
+
vec2 mapUv = clamp(vUv, vUvBounds.xy, vUvBounds.zw);
|
|
1126
|
+
#else
|
|
1127
|
+
vec2 mapUv = vUv;
|
|
1128
|
+
#endif
|
|
1129
|
+
vec4 color = texture2D(map, mapUv);
|
|
1113
1130
|
color.rgb *= vTint;
|
|
1114
1131
|
|
|
1115
1132
|
if (color.a < 0.01) discard;
|
|
@@ -1130,7 +1147,8 @@ var init_Materials = __esm({
|
|
|
1130
1147
|
}
|
|
1131
1148
|
`;
|
|
1132
1149
|
try {
|
|
1133
|
-
|
|
1150
|
+
const material = new import_three5.ShaderMaterial({
|
|
1151
|
+
defines: boundUvs ? { BOUND_UVS: true } : {},
|
|
1134
1152
|
uniforms: {
|
|
1135
1153
|
SHADE: { value: true },
|
|
1136
1154
|
BRIGHTNESS: { value: 1 },
|
|
@@ -1148,6 +1166,8 @@ var init_Materials = __esm({
|
|
|
1148
1166
|
side: transparent ? import_three5.DoubleSide : import_three5.FrontSide,
|
|
1149
1167
|
alphaTest: 0.5
|
|
1150
1168
|
});
|
|
1169
|
+
Object.assign(material.defaultAttributeValues, { uvBounds: [0, 0, 1, 1] });
|
|
1170
|
+
return material;
|
|
1151
1171
|
} catch (e) {
|
|
1152
1172
|
console.warn(e);
|
|
1153
1173
|
}
|
|
@@ -3068,6 +3088,37 @@ var init_UVMapper = __esm({
|
|
|
3068
3088
|
static facesToUv(faces, originalTextureSize, actualTextureSize) {
|
|
3069
3089
|
return new import_three9.Float32BufferAttribute(this.facesToUvArray(faces, originalTextureSize, actualTextureSize), 2);
|
|
3070
3090
|
}
|
|
3091
|
+
/** Bounds texture sampling to texel centres without changing cropped face UVs. */
|
|
3092
|
+
static setAtlasUvBounds(geometry, faces, atlas) {
|
|
3093
|
+
const uv = geometry.getAttribute("uv");
|
|
3094
|
+
const bounds = new Float32Array(uv.count * 4);
|
|
3095
|
+
for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
|
|
3096
|
+
const texture = faces[faceName]?.texture?.substring(1);
|
|
3097
|
+
const position = texture && atlas.positions[texture];
|
|
3098
|
+
const size = texture && atlas.sizes[texture];
|
|
3099
|
+
let minU = Infinity, minV = Infinity, maxU = -Infinity, maxV = -Infinity;
|
|
3100
|
+
if (position && size) {
|
|
3101
|
+
minU = position[0] / atlas.image.width;
|
|
3102
|
+
maxU = (position[0] + size[0]) / atlas.image.width;
|
|
3103
|
+
minV = 1 - (position[1] + size[1]) / atlas.image.height;
|
|
3104
|
+
maxV = 1 - position[1] / atlas.image.height;
|
|
3105
|
+
} else {
|
|
3106
|
+
for (let corner = 0; corner < 4; corner++) {
|
|
3107
|
+
const index = faceIndex * 4 + corner;
|
|
3108
|
+
minU = Math.min(minU, uv.getX(index));
|
|
3109
|
+
minV = Math.min(minV, uv.getY(index));
|
|
3110
|
+
maxU = Math.max(maxU, uv.getX(index));
|
|
3111
|
+
maxV = Math.max(maxV, uv.getY(index));
|
|
3112
|
+
}
|
|
3113
|
+
}
|
|
3114
|
+
const insetU = Math.min(0.5 / atlas.image.width, (maxU - minU) / 2);
|
|
3115
|
+
const insetV = Math.min(0.5 / atlas.image.height, (maxV - minV) / 2);
|
|
3116
|
+
for (let corner = 0; corner < 4; corner++) {
|
|
3117
|
+
bounds.set([minU + insetU, minV + insetV, maxU - insetU, maxV - insetV], (faceIndex * 4 + corner) * 4);
|
|
3118
|
+
}
|
|
3119
|
+
}
|
|
3120
|
+
geometry.setAttribute("uvBounds", new import_three9.Float32BufferAttribute(bounds, 4));
|
|
3121
|
+
}
|
|
3071
3122
|
static lockUvs(geometry, faces, atlas, rotation) {
|
|
3072
3123
|
const uv = geometry.getAttribute("uv");
|
|
3073
3124
|
for (let faceIndex = 0; faceIndex < CUBE_FACES.length; faceIndex++) {
|
|
@@ -5470,6 +5521,7 @@ var init_ModelObject = __esm({
|
|
|
5470
5521
|
if (this.options.uvLockRotation) {
|
|
5471
5522
|
UVMapper.lockUvs(elGeo, el.faces, this.atlas, new import_three25.Euler(...this.options.uvLockRotation));
|
|
5472
5523
|
}
|
|
5524
|
+
UVMapper.setAtlasUvBounds(elGeo, el.faces, this.atlas);
|
|
5473
5525
|
if (this.options.tints) {
|
|
5474
5526
|
const colors = new Float32Array(elGeo.getAttribute("position").count * 3).fill(1);
|
|
5475
5527
|
for (const [faceIndex, faceName] of CUBE_FACES.entries()) {
|
|
@@ -5535,7 +5587,7 @@ var init_ModelObject = __esm({
|
|
|
5535
5587
|
}
|
|
5536
5588
|
applyTextures() {
|
|
5537
5589
|
if (this.atlas) {
|
|
5538
|
-
const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false);
|
|
5590
|
+
const mat = Materials.createShadedCanvasMaterial(this.atlas.image.canvas, this.atlas.hasTransparency, false, true);
|
|
5539
5591
|
this.atlasMaterial = mat;
|
|
5540
5592
|
this.atlasTexture = mat.uniforms?.map?.value ?? mat.map;
|
|
5541
5593
|
this.iterateAllMeshes((mesh) => {
|
|
@@ -15411,13 +15463,7 @@ var MineRenderWorld = class {
|
|
|
15411
15463
|
async placeChunk(chunk, executor) {
|
|
15412
15464
|
const changes = /* @__PURE__ */ new Map();
|
|
15413
15465
|
try {
|
|
15414
|
-
|
|
15415
|
-
for (const [key, section] of previous) {
|
|
15416
|
-
this._chunks.delete(key);
|
|
15417
|
-
await section.clear(async (positions) => {
|
|
15418
|
-
for (const pos of positions) changes.set(pos.toArray().join(","), pos);
|
|
15419
|
-
});
|
|
15420
|
-
}
|
|
15466
|
+
await this.clearChunkColumn(chunk.x, chunk.z, changes);
|
|
15421
15467
|
for (const section of chunk.sections) {
|
|
15422
15468
|
const blocks = [];
|
|
15423
15469
|
for (let index = 0; index < 4096; index++) {
|
|
@@ -15437,6 +15483,31 @@ var MineRenderWorld = class {
|
|
|
15437
15483
|
await this.updateCulling([...changes.values()]);
|
|
15438
15484
|
}
|
|
15439
15485
|
}
|
|
15486
|
+
/**
|
|
15487
|
+
* Removes all sections at integer chunk-column coordinates, then refreshes neighboring faces and fluids.
|
|
15488
|
+
* Coordinates match AnvilChunk.x/z, not block positions. Missing columns are ignored.
|
|
15489
|
+
*/
|
|
15490
|
+
async unloadChunkColumn(x, z) {
|
|
15491
|
+
if (!Number.isInteger(x) || !Number.isInteger(z)) {
|
|
15492
|
+
throw new RangeError("Chunk column coordinates must be integers");
|
|
15493
|
+
}
|
|
15494
|
+
await this.culling;
|
|
15495
|
+
const changes = /* @__PURE__ */ new Map();
|
|
15496
|
+
try {
|
|
15497
|
+
await this.clearChunkColumn(x, z, changes);
|
|
15498
|
+
} finally {
|
|
15499
|
+
await this.updateCulling([...changes.values()]);
|
|
15500
|
+
}
|
|
15501
|
+
}
|
|
15502
|
+
async clearChunkColumn(x, z, changes) {
|
|
15503
|
+
const previous = [...this._chunks.entries()].filter(([, section]) => section.x === x && section.z === z);
|
|
15504
|
+
for (const [key, section] of previous) {
|
|
15505
|
+
this._chunks.delete(key);
|
|
15506
|
+
await section.clear(async (positions) => {
|
|
15507
|
+
for (const pos of positions) changes.set(pos.toArray().join(","), pos);
|
|
15508
|
+
});
|
|
15509
|
+
}
|
|
15510
|
+
}
|
|
15440
15511
|
async clear() {
|
|
15441
15512
|
await this.culling;
|
|
15442
15513
|
const chunks = [...this._chunks.values()];
|
|
@@ -15605,14 +15676,17 @@ var SectionMesh = class _SectionMesh extends import_three40.Group {
|
|
|
15605
15676
|
for (const { atlas, x, y } of page.placements) {
|
|
15606
15677
|
context.drawImage(atlas.image.canvas, x, y);
|
|
15607
15678
|
}
|
|
15608
|
-
const positions = [], normals = [], uvs = [], colors = [], indices = [];
|
|
15679
|
+
const positions = [], normals = [], uvs = [], uvBounds = [], colors = [], indices = [];
|
|
15609
15680
|
for (const { index, template, cullMask } of page.entries) {
|
|
15610
15681
|
const position = template.geometry.getAttribute("position");
|
|
15611
15682
|
const normal = template.geometry.getAttribute("normal");
|
|
15612
15683
|
const uv = template.geometry.getAttribute("uv");
|
|
15684
|
+
const bounds = template.geometry.getAttribute("uvBounds");
|
|
15613
15685
|
const color = template.geometry.getAttribute("color");
|
|
15614
15686
|
const sourceIndices = template.geometry.getIndex();
|
|
15615
15687
|
const placement = locations.get(template.atlas).placement;
|
|
15688
|
+
const mapU = (u) => (placement.x + u * template.atlas.image.width) / page.width;
|
|
15689
|
+
const mapV = (v) => 1 - (placement.y + (1 - v) * template.atlas.image.height) / page.height;
|
|
15616
15690
|
const offsetX = index % 16 * 16;
|
|
15617
15691
|
const offsetY = Math.floor(index / 256) * 16;
|
|
15618
15692
|
const offsetZ = Math.floor(index / 16) % 16 * 16;
|
|
@@ -15623,9 +15697,12 @@ var SectionMesh = class _SectionMesh extends import_three40.Group {
|
|
|
15623
15697
|
const vertex = face * 4 + corner;
|
|
15624
15698
|
positions.push(position.getX(vertex) + offsetX, position.getY(vertex) + offsetY, position.getZ(vertex) + offsetZ);
|
|
15625
15699
|
normals.push(normal.getX(vertex), normal.getY(vertex), normal.getZ(vertex));
|
|
15626
|
-
uvs.push(
|
|
15627
|
-
|
|
15628
|
-
|
|
15700
|
+
uvs.push(mapU(uv.getX(vertex)), mapV(uv.getY(vertex)));
|
|
15701
|
+
uvBounds.push(
|
|
15702
|
+
mapU(bounds?.getX(vertex) ?? 0),
|
|
15703
|
+
mapV(bounds?.getY(vertex) ?? 0),
|
|
15704
|
+
mapU(bounds?.getZ(vertex) ?? 1),
|
|
15705
|
+
mapV(bounds?.getW(vertex) ?? 1)
|
|
15629
15706
|
);
|
|
15630
15707
|
colors.push(color?.getX(vertex) ?? 1, color?.getY(vertex) ?? 1, color?.getZ(vertex) ?? 1);
|
|
15631
15708
|
}
|
|
@@ -15636,11 +15713,12 @@ var SectionMesh = class _SectionMesh extends import_three40.Group {
|
|
|
15636
15713
|
geometry.setAttribute("position", new import_three40.Float32BufferAttribute(positions, 3));
|
|
15637
15714
|
geometry.setAttribute("normal", new import_three40.Float32BufferAttribute(normals, 3));
|
|
15638
15715
|
geometry.setAttribute("uv", new import_three40.Float32BufferAttribute(uvs, 2));
|
|
15716
|
+
geometry.setAttribute("uvBounds", new import_three40.Float32BufferAttribute(uvBounds, 4));
|
|
15639
15717
|
geometry.setAttribute("color", new import_three40.Float32BufferAttribute(colors, 3));
|
|
15640
15718
|
geometry.setIndex(indices);
|
|
15641
15719
|
geometry.computeBoundingBox();
|
|
15642
15720
|
geometry.computeBoundingSphere();
|
|
15643
|
-
const material = Materials.createShadedCanvasMaterial(canvas, false);
|
|
15721
|
+
const material = Materials.createShadedCanvasMaterial(canvas, false, false, true);
|
|
15644
15722
|
material.vertexColors = true;
|
|
15645
15723
|
const texture = material.uniforms?.map?.value ?? material.map;
|
|
15646
15724
|
const mesh = new import_three40.Mesh(geometry, material);
|