minecraft-renderer 0.1.79 → 0.1.80
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/README.md +29 -25
- package/dist/mesher.js +36 -36
- package/dist/mesher.js.map +4 -4
- package/dist/mesherWasm.js +217 -217
- package/dist/minecraft-renderer.js +27 -27
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +133 -133
- package/package.json +5 -2
- package/src/bundler/bundlePrepare.ts +3 -8
- package/src/graphicsBackend/appViewer.ts +10 -7
- package/src/graphicsBackend/config.ts +1 -5
- package/src/graphicsBackend/playerState.ts +35 -34
- package/src/graphicsBackend/preloadWorkers.ts +43 -41
- package/src/graphicsBackend/rendererDefaultOptions.ts +68 -70
- package/src/graphicsBackend/rendererOptionsSync.ts +24 -50
- package/src/graphicsBackend/types.ts +2 -2
- package/src/index.ts +6 -27
- package/src/lib/DebugGui.ts +34 -31
- package/src/lib/animationController.ts +9 -9
- package/src/lib/bakeLegacyLight.ts +1 -6
- package/src/lib/bindAbortableListener.test.ts +32 -12
- package/src/lib/bindAbortableListener.ts +14 -6
- package/src/lib/blockEntityLightRegistry.ts +11 -20
- package/src/lib/blockEntityLighting.test.ts +1 -6
- package/src/lib/blockEntityLighting.ts +5 -5
- package/src/lib/buildSharedConfig.mjs +4 -4
- package/src/lib/buildWorkerMcDataIndexes.test.ts +4 -4
- package/src/lib/buildWorkerMcDataIndexes.ts +11 -19
- package/src/lib/cameraBobbing.ts +1 -1
- package/src/lib/canvas2DOverlay.example.ts +13 -33
- package/src/lib/canvas2DOverlay.quickstart.ts +24 -54
- package/src/lib/canvas2DOverlay.ts +28 -47
- package/src/lib/cleanupDecorator.ts +2 -2
- package/src/lib/createPlayerObject.test.ts +2 -7
- package/src/lib/createPlayerObject.ts +18 -25
- package/src/lib/frameTimingCollector.ts +2 -5
- package/src/lib/guiRenderer.ts +57 -42
- package/src/lib/items.ts +15 -9
- package/src/lib/mesherlogReader.ts +5 -6
- package/src/lib/simpleUtils.ts +5 -5
- package/src/lib/skyLight.ts +3 -3
- package/src/lib/smoothSwitcher.ts +11 -18
- package/src/lib/ui/newStats.ts +10 -12
- package/src/lib/utils/proxy.ts +7 -1
- package/src/lib/utils/skins.ts +4 -4
- package/src/lib/utils.ts +1 -1
- package/src/lib/workerMessageSanitize.ts +5 -12
- package/src/lib/workerProxy.ts +52 -42
- package/src/lib/workerSyncOps.test.ts +58 -41
- package/src/lib/worldrendererCommon.reconfigure.test.ts +24 -21
- package/src/lib/worldrendererCommon.removeColumn.test.ts +11 -13
- package/src/lib/worldrendererCommon.ts +338 -211
- package/src/mesher-legacy/mesher.ts +9 -4
- package/src/mesher-legacy/test/a.ts +1 -1
- package/src/mesher-legacy/test/mesherTester.ts +2 -2
- package/src/mesher-legacy/test/playground.ts +1 -1
- package/src/mesher-legacy/test/run/test-js.ts +1 -1
- package/src/mesher-legacy/test/snapshotUtils.ts +3 -8
- package/src/mesher-legacy/test/test-perf.ts +1 -1
- package/src/mesher-legacy/test/tests.test.ts +2 -2
- package/src/mesher-shared/blockEntityMetadata.test.ts +7 -5
- package/src/mesher-shared/blockEntityMetadata.ts +28 -19
- package/src/mesher-shared/blockPropertiesForMeshing.ts +2 -2
- package/src/mesher-shared/computeHeightmap.ts +2 -4
- package/src/mesher-shared/exportedGeometryTypes.ts +3 -3
- package/src/mesher-shared/faceOcclusion.ts +324 -0
- package/src/mesher-shared/models.ts +80 -131
- package/src/mesher-shared/modelsGeometryCommon.ts +30 -15
- package/src/mesher-shared/shared.ts +46 -46
- package/src/mesher-shared/standaloneRenderer.ts +40 -44
- package/src/mesher-shared/tests/faceOcclusion.test.ts +179 -0
- package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +12 -8
- package/src/mesher-shared/vertexShading.ts +2 -11
- package/src/mesher-shared/world.ts +19 -19
- package/src/mesher-shared/worldLighting.test.ts +2 -2
- package/src/performanceMonitor/PerformanceMonitor.ts +4 -13
- package/src/performanceMonitor/formatPerformanceFactorsDebug.ts +2 -2
- package/src/performanceMonitor/index.ts +1 -5
- package/src/performanceMonitor/types.ts +1 -1
- package/src/playerState/playerState.ts +55 -50
- package/src/playerState/types.ts +2 -8
- package/src/playground/allEntitiesDebug.ts +19 -16
- package/src/playground/baseScene.ts +29 -32
- package/src/playground/mobileControls.tsx +133 -129
- package/src/playground/playground.html +76 -73
- package/src/playground/playground.ts +14 -1
- package/src/playground/playgroundUi.tsx +100 -74
- package/src/playground/reactUtils.ts +3 -7
- package/src/playground/scenes/entities.ts +10 -7
- package/src/playground/scenes/frequentUpdates.ts +5 -5
- package/src/playground/scenes/geometryExport.ts +6 -20
- package/src/playground/scenes/highPosEntityUpdates.ts +2 -10
- package/src/playground/scenes/index.ts +1 -1
- package/src/playground/scenes/lightingStarfield.ts +18 -12
- package/src/playground/scenes/main.ts +15 -11
- package/src/playground/scenes/partialBlockCulling.ts +31 -0
- package/src/playground/scenes/railsCobweb.ts +1 -1
- package/src/playground/scenes/rotationIssue.ts +1 -1
- package/src/playground/scenes/slabsOptimization.ts +1 -2
- package/src/playground/scenes/transparencyIssue.ts +1 -1
- package/src/playground/shared.ts +2 -2
- package/src/resourcesManager/resourcesManager.ts +29 -54
- package/src/resourcesManager/resourcesManager.worker.test.ts +6 -10
- package/src/shims/minecraftData.ts +70 -24
- package/src/sign-renderer/index.html +10 -12
- package/src/sign-renderer/index.ts +29 -29
- package/src/sign-renderer/playground.ts +22 -15
- package/src/sign-renderer/tests.test.ts +16 -13
- package/src/sign-renderer/vite.config.ts +2 -2
- package/src/three/appShared.ts +46 -25
- package/src/three/bannerRenderer.ts +33 -61
- package/src/three/cameraShake.ts +15 -6
- package/src/three/chunkMeshManager.ts +239 -282
- package/src/three/cinimaticScript.ts +26 -15
- package/src/three/cubeDrawSpans.ts +27 -37
- package/src/three/cubeMultiDraw.ts +9 -22
- package/src/three/documentRenderer.ts +15 -18
- package/src/three/entities.ts +175 -150
- package/src/three/entity/EntityMesh.ts +114 -108
- package/src/three/entity/animations.js +3 -3
- package/src/three/entity/armorModels.ts +15 -15
- package/src/three/entity/gltfAnimationUtils.ts +2 -5
- package/src/three/fireworks.ts +34 -32
- package/src/three/fireworksRenderer.ts +32 -29
- package/src/three/globalBlockBuffer.ts +167 -100
- package/src/three/globalLegacyBuffer.ts +257 -166
- package/src/three/graphicsBackendBase.ts +19 -25
- package/src/three/graphicsBackendOffThread.ts +12 -15
- package/src/three/hand.ts +21 -21
- package/src/three/handLegacy.ts +3 -13
- package/src/three/holdingBlock.ts +116 -79
- package/src/three/holdingBlockFactory.ts +1 -4
- package/src/three/holdingBlockItemIdentity.test.ts +25 -17
- package/src/three/holdingBlockItemIdentity.ts +9 -6
- package/src/three/holdingBlockLegacy.ts +113 -132
- package/src/three/itemMesh.ts +20 -29
- package/src/three/legacyMultiDraw.ts +10 -16
- package/src/three/legacySectionCull.ts +8 -14
- package/src/three/menuBackground/activeView.ts +1 -4
- package/src/three/menuBackground/assetUrl.ts +1 -1
- package/src/three/menuBackground/classic.ts +4 -12
- package/src/three/menuBackground/gpuPreference.ts +1 -3
- package/src/three/menuBackground/index.ts +2 -11
- package/src/three/menuBackground/renderer.ts +1 -5
- package/src/three/menuBackground/types.ts +1 -4
- package/src/three/menuBackground/v2.ts +196 -96
- package/src/three/menuBackground/v2Meta.ts +3 -3
- package/src/three/menuBackground/worldBlocks.ts +37 -35
- package/src/three/modules/blockBreakParticles.ts +59 -28
- package/src/three/modules/cameraBobbing.ts +3 -6
- package/src/three/modules/index.ts +1 -1
- package/src/three/modules/rain.ts +10 -23
- package/src/three/modules/sciFiWorldReveal.ts +11 -25
- package/src/three/modules/starfield.ts +7 -13
- package/src/three/renderSlot.ts +28 -16
- package/src/three/rendererModuleSystem.ts +1 -3
- package/src/three/sceneOrigin.ts +96 -33
- package/src/three/sectionRaycastAabb.ts +30 -18
- package/src/three/shaderCubeMesh.ts +6 -17
- package/src/three/shaders/cubeBlockShader.ts +85 -96
- package/src/three/shaders/legacyBlockShader.ts +21 -43
- package/src/three/shaders/textureIndexMapping.ts +89 -95
- package/src/three/shaders/tintPalette.ts +156 -170
- package/src/three/signTextureCache.ts +9 -12
- package/src/three/skyboxRenderer.ts +62 -70
- package/src/three/tests/chunkMeshManagerLegacy.test.ts +34 -34
- package/src/three/tests/cubeDrawSpans.test.ts +55 -25
- package/src/three/tests/globalBlockBuffer.test.ts +217 -0
- package/src/three/tests/globalLegacyBuffer.test.ts +300 -41
- package/src/three/tests/legacyMultiDraw.test.ts +8 -29
- package/src/three/tests/pr3PerFrameCpuCuts.test.ts +106 -29
- package/src/three/tests/signTextureCache.test.ts +4 -4
- package/src/three/threeJsMedia.ts +55 -72
- package/src/three/threeJsParticles.ts +32 -41
- package/src/three/threeJsSound.ts +3 -3
- package/src/three/threeJsUtils.ts +3 -3
- package/src/three/threeWorker.ts +2 -2
- package/src/three/waypointSprite.ts +55 -82
- package/src/three/waypoints.ts +20 -23
- package/src/three/world/cursorBlock.ts +25 -12
- package/src/three/world/vr.ts +11 -17
- package/src/three/worldGeometryExport.ts +15 -34
- package/src/three/worldRendererThree.ts +117 -129
- package/src/wasm-mesher/bridge/convertChunk.ts +3 -9
- package/src/wasm-mesher/bridge/render-from-wasm.ts +204 -229
- package/src/wasm-mesher/bridge/shaderCubeBridge.ts +26 -67
- package/src/wasm-mesher/tests/cullingRegression.test.ts +307 -0
- package/src/wasm-mesher/tests/heightmapParity.test.ts +8 -18
- package/src/wasm-mesher/tests/mesherWasmConversionCache.test.ts +2 -2
- package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +17 -4
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +103 -141
- package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +14 -22
- package/src/wasm-mesher/worker/mesherWasm.ts +150 -141
- package/src/wasm-mesher/worker/mesherWasmConversionCache.ts +2 -8
- package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +1 -3
- package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +1 -5
- package/src/wasm-mesher/worker/mesherWasmRequestTracker.ts +42 -42
- package/src/worldView/worldView.spiral.test.ts +1 -1
- package/src/worldView/worldView.ts +34 -39
- package/src/worldView/worldViewWorkerBridge.test.ts +4 -4
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
packWord2Empty,
|
|
14
14
|
packWord3,
|
|
15
15
|
SHADER_CUBES_FORMAT_VERSION,
|
|
16
|
-
SHADER_CUBES_WORDS_PER_FACE
|
|
16
|
+
SHADER_CUBES_WORDS_PER_FACE
|
|
17
17
|
} from '../bridge/shaderCubeBridge'
|
|
18
18
|
import { GlobalBlockBuffer } from '../../three/globalBlockBuffer'
|
|
19
19
|
import { buildVisibleCubeSpans } from '../../three/cubeDrawSpans'
|
|
@@ -54,20 +54,22 @@ test('packWord2: AO diagonal flip sets bit 12', () => {
|
|
|
54
54
|
visible_faces: 1 << 0, // up only
|
|
55
55
|
ao_data: [[0, 1, 2, 3]], // 0+3 >= 1+2 → flip
|
|
56
56
|
light_data: [[1, 1, 1, 1]],
|
|
57
|
-
light_combined: [[255, 255, 255, 255]]
|
|
57
|
+
light_combined: [[255, 255, 255, 255]]
|
|
58
58
|
}
|
|
59
59
|
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
60
60
|
const model = {
|
|
61
|
-
elements: [
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
61
|
+
elements: [
|
|
62
|
+
{
|
|
63
|
+
faces: {
|
|
64
|
+
up: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
65
|
+
down: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
66
|
+
east: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
67
|
+
west: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
68
|
+
south: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
69
|
+
north: { texture: { u: 0, v: 0, su: 16, sv: 16 } }
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
]
|
|
71
73
|
}
|
|
72
74
|
const ok = tryBuildShaderCubeInstances(
|
|
73
75
|
block,
|
|
@@ -77,9 +79,9 @@ test('packWord2: AO diagonal flip sets bit 12', () => {
|
|
|
77
79
|
sectionOrigin: { x: 0, y: 0, z: 0 },
|
|
78
80
|
sectionHeight: 16,
|
|
79
81
|
tintPalette,
|
|
80
|
-
textureIndexMapping
|
|
82
|
+
textureIndexMapping
|
|
81
83
|
},
|
|
82
|
-
words
|
|
84
|
+
words
|
|
83
85
|
)
|
|
84
86
|
expect(ok).toBe(true)
|
|
85
87
|
expect(words.length).toBe(SHADER_CUBES_WORDS_PER_FACE)
|
|
@@ -93,20 +95,22 @@ test('packWord0: section-local lx/ly/lz and face id', () => {
|
|
|
93
95
|
visible_faces: 1 << 2, // east
|
|
94
96
|
ao_data: [[3, 3, 3, 3]],
|
|
95
97
|
light_data: [[0.5, 0.5, 0.5, 0.5]],
|
|
96
|
-
light_combined: [[128, 128, 128, 128]]
|
|
98
|
+
light_combined: [[128, 128, 128, 128]]
|
|
97
99
|
}
|
|
98
100
|
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
99
101
|
const model = {
|
|
100
|
-
elements: [
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
102
|
+
elements: [
|
|
103
|
+
{
|
|
104
|
+
faces: {
|
|
105
|
+
up: { texture: { u: 16, v: 0, su: 16, sv: 16 } },
|
|
106
|
+
down: { texture: { u: 16, v: 0, su: 16, sv: 16 } },
|
|
107
|
+
east: { texture: { u: 16, v: 0, su: 16, sv: 16 } },
|
|
108
|
+
west: { texture: { u: 16, v: 0, su: 16, sv: 16 } },
|
|
109
|
+
south: { texture: { u: 16, v: 0, su: 16, sv: 16 } },
|
|
110
|
+
north: { texture: { u: 16, v: 0, su: 16, sv: 16 } }
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
]
|
|
110
114
|
}
|
|
111
115
|
tryBuildShaderCubeInstances(
|
|
112
116
|
block,
|
|
@@ -116,9 +120,9 @@ test('packWord0: section-local lx/ly/lz and face id', () => {
|
|
|
116
120
|
sectionOrigin: { x: 0, y: 16, z: 0 },
|
|
117
121
|
sectionHeight: 16,
|
|
118
122
|
tintPalette,
|
|
119
|
-
textureIndexMapping
|
|
123
|
+
textureIndexMapping
|
|
120
124
|
},
|
|
121
|
-
words
|
|
125
|
+
words
|
|
122
126
|
)
|
|
123
127
|
const w0 = words[0]!
|
|
124
128
|
expect(w0 & 0xf).toBe(10) // lx
|
|
@@ -130,35 +134,24 @@ test('packWord0: section-local lx/ly/lz and face id', () => {
|
|
|
130
134
|
test('isShaderCubeBlock: rejects model rotation and sectionHeight !== 16', () => {
|
|
131
135
|
const { textureIndexMapping } = requireShaderCubeResources()
|
|
132
136
|
const baseModel = {
|
|
133
|
-
elements: [
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
137
|
+
elements: [
|
|
138
|
+
{
|
|
139
|
+
faces: {
|
|
140
|
+
up: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
141
|
+
down: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
142
|
+
east: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
143
|
+
west: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
144
|
+
south: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
145
|
+
north: { texture: { u: 0, v: 0, su: 16, sv: 16 } }
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
]
|
|
143
149
|
}
|
|
144
|
-
expect(isShaderCubeBlock(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
16,
|
|
148
|
-
|
|
149
|
-
)).toBe(true)
|
|
150
|
-
expect(isShaderCubeBlock(
|
|
151
|
-
{ blockName: 'stone', blockProps: {}, isCube: true, model: baseModel },
|
|
152
|
-
baseModel,
|
|
153
|
-
24,
|
|
154
|
-
textureIndexMapping,
|
|
155
|
-
)).toBe(false)
|
|
156
|
-
expect(isShaderCubeBlock(
|
|
157
|
-
{ blockName: 'stone', blockProps: {}, isCube: true, model: { ...baseModel, y: 90 } },
|
|
158
|
-
{ ...baseModel, y: 90 },
|
|
159
|
-
16,
|
|
160
|
-
textureIndexMapping,
|
|
161
|
-
)).toBe(false)
|
|
150
|
+
expect(isShaderCubeBlock({ blockName: 'stone', blockProps: {}, isCube: true, model: baseModel }, baseModel, 16, textureIndexMapping)).toBe(true)
|
|
151
|
+
expect(isShaderCubeBlock({ blockName: 'stone', blockProps: {}, isCube: true, model: baseModel }, baseModel, 24, textureIndexMapping)).toBe(false)
|
|
152
|
+
expect(
|
|
153
|
+
isShaderCubeBlock({ blockName: 'stone', blockProps: {}, isCube: true, model: { ...baseModel, y: 90 } }, { ...baseModel, y: 90 }, 16, textureIndexMapping)
|
|
154
|
+
).toBe(false)
|
|
162
155
|
})
|
|
163
156
|
|
|
164
157
|
test('renderWasmOutputToGeometry: stone emits shaderCubes and skips legacy vertices when enabled', () => {
|
|
@@ -168,16 +161,11 @@ test('renderWasmOutputToGeometry: stone emits shaderCubes and skips legacy verti
|
|
|
168
161
|
visible_faces: (1 << 0) | (1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5),
|
|
169
162
|
ao_data: Array.from({ length: 6 }, () => [3, 3, 3, 3]),
|
|
170
163
|
light_data: Array.from({ length: 6 }, () => [1, 1, 1, 1]),
|
|
171
|
-
light_combined: Array.from({ length: 6 }, () => [255, 255, 255, 255])
|
|
164
|
+
light_combined: Array.from({ length: 6 }, () => [255, 255, 255, 255])
|
|
172
165
|
}
|
|
173
|
-
const out = renderWasmOutputToGeometry(
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
'0,0,0',
|
|
177
|
-
{ x: 8, y: 8, z: 8 },
|
|
178
|
-
undefined,
|
|
179
|
-
{ shaderCubes: true },
|
|
180
|
-
)
|
|
166
|
+
const out = renderWasmOutputToGeometry({ blocks: [block], block_count: 1, block_iterations: 0 }, VERSION, '0,0,0', { x: 8, y: 8, z: 8 }, undefined, {
|
|
167
|
+
shaderCubes: true
|
|
168
|
+
})
|
|
181
169
|
expect(out.shaderCubes?.count).toBe(6)
|
|
182
170
|
expect(out.shaderCubes?.formatVersion).toBe(SHADER_CUBES_FORMAT_VERSION)
|
|
183
171
|
expect(out.shaderCubes?.words.length).toBe(6 * SHADER_CUBES_WORDS_PER_FACE)
|
|
@@ -195,16 +183,11 @@ test('renderWasmOutputToGeometry: shaderCubes false keeps legacy path for stone'
|
|
|
195
183
|
block_state_id: STONE,
|
|
196
184
|
visible_faces: 1 << 0,
|
|
197
185
|
ao_data: [[3, 3, 3, 3]],
|
|
198
|
-
light_data: [[1, 1, 1, 1]]
|
|
186
|
+
light_data: [[1, 1, 1, 1]]
|
|
199
187
|
}
|
|
200
|
-
const out = renderWasmOutputToGeometry(
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
'0,0,0',
|
|
204
|
-
{ x: 8, y: 8, z: 8 },
|
|
205
|
-
undefined,
|
|
206
|
-
{ shaderCubes: false },
|
|
207
|
-
)
|
|
188
|
+
const out = renderWasmOutputToGeometry({ blocks: [block], block_count: 1, block_iterations: 0 }, VERSION, '0,0,0', { x: 8, y: 8, z: 8 }, undefined, {
|
|
189
|
+
shaderCubes: false
|
|
190
|
+
})
|
|
208
191
|
expect(out.shaderCubes).toBeUndefined()
|
|
209
192
|
expect(out.geometry.positions.length).toBeGreaterThan(0)
|
|
210
193
|
})
|
|
@@ -223,7 +206,7 @@ const SIX_FACE_TEXTURES = {
|
|
|
223
206
|
east: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
224
207
|
west: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
225
208
|
south: { texture: { u: 0, v: 0, su: 16, sv: 16 } },
|
|
226
|
-
north: { texture: { u: 0, v: 0, su: 16, sv: 16 } }
|
|
209
|
+
north: { texture: { u: 0, v: 0, su: 16, sv: 16 } }
|
|
227
210
|
}
|
|
228
211
|
|
|
229
212
|
function aoCorner0FromWord0(w0: number): number {
|
|
@@ -237,7 +220,7 @@ test('south face: AO corners remapped to shader order (elemFaces [0,3,1,2] → s
|
|
|
237
220
|
visible_faces: 1 << 4, // south
|
|
238
221
|
ao_data: [[0, 3, 1, 2]],
|
|
239
222
|
light_data: [[1, 1, 1, 1]],
|
|
240
|
-
light_combined: [[10, 20, 30, 40]]
|
|
223
|
+
light_combined: [[10, 20, 30, 40]]
|
|
241
224
|
}
|
|
242
225
|
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
243
226
|
const model = { elements: [{ faces: SIX_FACE_TEXTURES }] }
|
|
@@ -246,7 +229,7 @@ test('south face: AO corners remapped to shader order (elemFaces [0,3,1,2] → s
|
|
|
246
229
|
{ blockName: 'stone', blockProps: {}, isCube: true, model },
|
|
247
230
|
model,
|
|
248
231
|
{ sectionOrigin: { x: 0, y: 0, z: 0 }, sectionHeight: 16, tintPalette, textureIndexMapping },
|
|
249
|
-
words
|
|
232
|
+
words
|
|
250
233
|
)
|
|
251
234
|
// Shader vi=0 must get elemFaces ao[2]=1, not ao[0]=0
|
|
252
235
|
expect(aoCorner0FromWord0(words[0]!)).toBe(1)
|
|
@@ -263,7 +246,7 @@ test('south face: diagonal flip uses remapped AO (differs from raw elemFaces for
|
|
|
263
246
|
visible_faces: 1 << 4,
|
|
264
247
|
ao_data: [ao],
|
|
265
248
|
light_data: [[1, 1, 1, 1]],
|
|
266
|
-
light_combined: [[255, 255, 255, 255]]
|
|
249
|
+
light_combined: [[255, 255, 255, 255]]
|
|
267
250
|
}
|
|
268
251
|
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
269
252
|
const model = { elements: [{ faces: SIX_FACE_TEXTURES }] }
|
|
@@ -271,25 +254,13 @@ test('south face: diagonal flip uses remapped AO (differs from raw elemFaces for
|
|
|
271
254
|
sectionOrigin: { x: 0, y: 0, z: 0 },
|
|
272
255
|
sectionHeight: 16,
|
|
273
256
|
tintPalette,
|
|
274
|
-
textureIndexMapping
|
|
257
|
+
textureIndexMapping
|
|
275
258
|
}
|
|
276
|
-
tryBuildShaderCubeInstances(
|
|
277
|
-
block,
|
|
278
|
-
{ blockName: 'stone', blockProps: {}, isCube: true, model },
|
|
279
|
-
model,
|
|
280
|
-
opts,
|
|
281
|
-
wordsFlip,
|
|
282
|
-
)
|
|
259
|
+
tryBuildShaderCubeInstances(block, { blockName: 'stone', blockProps: {}, isCube: true, model }, model, opts, wordsFlip)
|
|
283
260
|
expect(wordsFlip[2]! & (1 << WORD2.DIAGONAL_FLAG_SHIFT)).not.toBe(0)
|
|
284
261
|
|
|
285
262
|
// elemFaces [3,0,0,3] → remapped [0,3,3,0]: 0+0 < 3+3 → no diagonal flip
|
|
286
|
-
tryBuildShaderCubeInstances(
|
|
287
|
-
{ ...block, ao_data: [[3, 0, 0, 3]] },
|
|
288
|
-
{ blockName: 'stone', blockProps: {}, isCube: true, model },
|
|
289
|
-
model,
|
|
290
|
-
opts,
|
|
291
|
-
wordsNoFlip,
|
|
292
|
-
)
|
|
263
|
+
tryBuildShaderCubeInstances({ ...block, ao_data: [[3, 0, 0, 3]] }, { blockName: 'stone', blockProps: {}, isCube: true, model }, model, opts, wordsNoFlip)
|
|
293
264
|
expect(wordsNoFlip[2]! & (1 << WORD2.DIAGONAL_FLAG_SHIFT)).toBe(0)
|
|
294
265
|
})
|
|
295
266
|
|
|
@@ -300,7 +271,7 @@ test('doAO false: full bright AO/light and no diagonal flip', () => {
|
|
|
300
271
|
visible_faces: 1 << 0,
|
|
301
272
|
ao_data: [[0, 0, 0, 0]],
|
|
302
273
|
light_data: [[0, 0, 0, 0]],
|
|
303
|
-
light_combined: [[0, 0, 0, 0]]
|
|
274
|
+
light_combined: [[0, 0, 0, 0]]
|
|
304
275
|
}
|
|
305
276
|
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
306
277
|
const model = { elements: [{ faces: SIX_FACE_TEXTURES }] }
|
|
@@ -313,9 +284,9 @@ test('doAO false: full bright AO/light and no diagonal flip', () => {
|
|
|
313
284
|
sectionHeight: 16,
|
|
314
285
|
tintPalette,
|
|
315
286
|
textureIndexMapping,
|
|
316
|
-
doAO: false
|
|
287
|
+
doAO: false
|
|
317
288
|
},
|
|
318
|
-
words
|
|
289
|
+
words
|
|
319
290
|
)
|
|
320
291
|
expect(aoCorner0FromWord0(words[0]!)).toBe(3)
|
|
321
292
|
for (let i = 0; i < 4; i++) {
|
|
@@ -324,7 +295,7 @@ test('doAO false: full bright AO/light and no diagonal flip', () => {
|
|
|
324
295
|
expect(words[2]! & (1 << WORD2.DIAGONAL_FLAG_SHIFT)).toBe(0)
|
|
325
296
|
})
|
|
326
297
|
|
|
327
|
-
const SECTION_ORIGIN_ROUND_TRIP_CASES: Array<{ x: number
|
|
298
|
+
const SECTION_ORIGIN_ROUND_TRIP_CASES: Array<{ x: number; y: number; z: number }> = [
|
|
328
299
|
{ x: 0, y: 16, z: 32 },
|
|
329
300
|
{ x: 0, y: 0, z: 0 },
|
|
330
301
|
{ x: 524288, y: 0, z: 524288 },
|
|
@@ -332,33 +303,30 @@ const SECTION_ORIGIN_ROUND_TRIP_CASES: Array<{ x: number, y: number, z: number }
|
|
|
332
303
|
{ x: 33000000, y: 0, z: 33000000 },
|
|
333
304
|
{ x: -524288, y: 0, z: -524288 },
|
|
334
305
|
{ x: -1000000, y: 0, z: -1000000 },
|
|
335
|
-
{ x: 1000000, y: 0, z: -1000000 }
|
|
306
|
+
{ x: 1000000, y: 0, z: -1000000 }
|
|
336
307
|
]
|
|
337
308
|
|
|
338
|
-
test.each(SECTION_ORIGIN_ROUND_TRIP_CASES)(
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
expect(base).toEqual(sectionOrigin)
|
|
360
|
-
},
|
|
361
|
-
)
|
|
309
|
+
test.each(SECTION_ORIGIN_ROUND_TRIP_CASES)('section base coords round-trip in word2/word3 at origin (%#)', sectionOrigin => {
|
|
310
|
+
const words: number[] = []
|
|
311
|
+
const block = {
|
|
312
|
+
position: [10, 17, 4] as [number, number, number],
|
|
313
|
+
visible_faces: 1 << 2,
|
|
314
|
+
ao_data: [[3, 3, 3, 3]],
|
|
315
|
+
light_data: [[1, 1, 1, 1]],
|
|
316
|
+
light_combined: [[255, 255, 255, 255]]
|
|
317
|
+
}
|
|
318
|
+
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
319
|
+
const model = { elements: [{ faces: SIX_FACE_TEXTURES }] }
|
|
320
|
+
tryBuildShaderCubeInstances(
|
|
321
|
+
block,
|
|
322
|
+
{ blockName: 'stone', blockProps: {}, isCube: true, model },
|
|
323
|
+
model,
|
|
324
|
+
{ sectionOrigin, sectionHeight: 16, tintPalette, textureIndexMapping },
|
|
325
|
+
words
|
|
326
|
+
)
|
|
327
|
+
const base = decodeSectionBaseFromWords(words[2]!, words[3]!)
|
|
328
|
+
expect(base).toEqual(sectionOrigin)
|
|
329
|
+
})
|
|
362
330
|
|
|
363
331
|
test('packWord2Empty: bit 18 set regardless of high X/Z bits in word2', () => {
|
|
364
332
|
const empty = packWord2Empty()
|
|
@@ -376,7 +344,7 @@ test('section index relative decode past 2^20: exact integer subtract', () => {
|
|
|
376
344
|
visible_faces: 1 << 2,
|
|
377
345
|
ao_data: [[3, 3, 3, 3]],
|
|
378
346
|
light_data: [[1, 1, 1, 1]],
|
|
379
|
-
light_combined: [[255, 255, 255, 255]]
|
|
347
|
+
light_combined: [[255, 255, 255, 255]]
|
|
380
348
|
}
|
|
381
349
|
const { textureIndexMapping, tintPalette } = requireShaderCubeResources()
|
|
382
350
|
const model = { elements: [{ faces: SIX_FACE_TEXTURES }] }
|
|
@@ -388,9 +356,9 @@ test('section index relative decode past 2^20: exact integer subtract', () => {
|
|
|
388
356
|
sectionOrigin: { x: sectionBlockX, y: 0, z: 0 },
|
|
389
357
|
sectionHeight: 16,
|
|
390
358
|
tintPalette,
|
|
391
|
-
textureIndexMapping
|
|
359
|
+
textureIndexMapping
|
|
392
360
|
},
|
|
393
|
-
words
|
|
361
|
+
words
|
|
394
362
|
)
|
|
395
363
|
const base = decodeSectionBaseFromWords(words[2]!, words[3]!)
|
|
396
364
|
const sX = base.x / 16
|
|
@@ -404,10 +372,7 @@ test('GlobalBlockBuffer: free-list reuses slot with EMPTY sentinel', () => {
|
|
|
404
372
|
const mat = createCubeBlockMaterial()
|
|
405
373
|
const buffer = new GlobalBlockBuffer(mat, scene)
|
|
406
374
|
|
|
407
|
-
const words = new Uint32Array([
|
|
408
|
-
1, 2, 0, packWord3(0, 0),
|
|
409
|
-
3, 4, 0, packWord3(0, 0),
|
|
410
|
-
])
|
|
375
|
+
const words = new Uint32Array([1, 2, 0, packWord3(0, 0), 3, 4, 0, packWord3(0, 0)])
|
|
411
376
|
buffer.addSection('a', words, 2)
|
|
412
377
|
expect(buffer.mesh.geometry.instanceCount).toBe(2)
|
|
413
378
|
|
|
@@ -425,24 +390,24 @@ test('GlobalBlockBuffer: free-list reuses slot with EMPTY sentinel', () => {
|
|
|
425
390
|
})
|
|
426
391
|
|
|
427
392
|
type BufferInternals = {
|
|
428
|
-
pendingRanges: Array<{ start: number
|
|
429
|
-
pendingMove: { key: string
|
|
393
|
+
pendingRanges: Array<{ start: number; end: number }>
|
|
394
|
+
pendingMove: { key: string; oldStart: number; newStart: number; count: number } | null
|
|
430
395
|
}
|
|
431
396
|
|
|
432
397
|
/** True if some queued (not-yet-uploaded) dirty range covers [start, end] — i.e. it WILL hit the GPU. */
|
|
433
|
-
function rangeQueuedForUpload
|
|
398
|
+
function rangeQueuedForUpload(buffer: GlobalBlockBuffer, start: number, end: number): boolean {
|
|
434
399
|
return getBufferInternals(buffer).pendingRanges.some(r => r.start <= end && r.end >= start)
|
|
435
400
|
}
|
|
436
401
|
|
|
437
|
-
function getBufferInternals
|
|
402
|
+
function getBufferInternals(buffer: GlobalBlockBuffer): BufferInternals {
|
|
438
403
|
return buffer as unknown as BufferInternals
|
|
439
404
|
}
|
|
440
405
|
|
|
441
|
-
function drainAllUploads
|
|
406
|
+
function drainAllUploads(buffer: GlobalBlockBuffer): void {
|
|
442
407
|
while (getBufferInternals(buffer).pendingRanges.length) buffer.uploadDirtyRange()
|
|
443
408
|
}
|
|
444
409
|
|
|
445
|
-
function makeSectionWords
|
|
410
|
+
function makeSectionWords(faceW0: number[]): Uint32Array {
|
|
446
411
|
const words = new Uint32Array(faceW0.length * 4)
|
|
447
412
|
for (let i = 0; i < faceW0.length; i++) {
|
|
448
413
|
words[i * 4] = faceW0[i]!
|
|
@@ -453,7 +418,7 @@ function makeSectionWords (faceW0: number[]): Uint32Array {
|
|
|
453
418
|
return words
|
|
454
419
|
}
|
|
455
420
|
|
|
456
|
-
function readSectionFaceWords
|
|
421
|
+
function readSectionFaceWords(buffer: GlobalBlockBuffer, key: string): number[] {
|
|
457
422
|
const slot = buffer.getSectionSlot(key)
|
|
458
423
|
if (!slot) throw new Error(`missing section ${key}`)
|
|
459
424
|
const geo = buffer.mesh.geometry
|
|
@@ -469,12 +434,12 @@ function readSectionFaceWords (buffer: GlobalBlockBuffer, key: string): number[]
|
|
|
469
434
|
return out
|
|
470
435
|
}
|
|
471
436
|
|
|
472
|
-
function finishCurrentMove
|
|
437
|
+
function finishCurrentMove(buffer: GlobalBlockBuffer): void {
|
|
473
438
|
drainAllUploads(buffer)
|
|
474
439
|
buffer.compactStep()
|
|
475
440
|
}
|
|
476
441
|
|
|
477
|
-
function isEmptyFace
|
|
442
|
+
function isEmptyFace(buffer: GlobalBlockBuffer, index: number): boolean {
|
|
478
443
|
const w2 = (buffer.mesh.geometry.getAttribute('a_w2') as THREE.InstancedBufferAttribute).array as Uint32Array
|
|
479
444
|
return (w2[index]! & (1 << WORD2.EMPTY_SHIFT)) !== 0
|
|
480
445
|
}
|
|
@@ -730,10 +695,7 @@ test('GlobalBlockBuffer: pendingMove draw start uses oldStart for visible spans'
|
|
|
730
695
|
expect(buffer.getSectionDrawStart('c')).toBe(move!.oldStart)
|
|
731
696
|
expect(buffer.getSectionDrawStart('c')).not.toBe(slotStart)
|
|
732
697
|
|
|
733
|
-
const spans = buildVisibleCubeSpans(
|
|
734
|
-
[{ start: buffer.getSectionDrawStart('c')!, count: 1 }],
|
|
735
|
-
buffer.getHighWatermark(),
|
|
736
|
-
)
|
|
698
|
+
const spans = buildVisibleCubeSpans([{ start: buffer.getSectionDrawStart('c')!, count: 1 }], buffer.getHighWatermark())
|
|
737
699
|
expect(spans[0]?.start).toBe(move!.oldStart)
|
|
738
700
|
|
|
739
701
|
buffer.dispose()
|
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
2
|
import { test, expect } from 'vitest'
|
|
3
|
-
import {
|
|
4
|
-
splitColumnWasmOutputToSections,
|
|
5
|
-
renderWasmOutputToGeometry,
|
|
6
|
-
WasmGeometryOutput,
|
|
7
|
-
} from '../bridge/render-from-wasm'
|
|
3
|
+
import { splitColumnWasmOutputToSections, renderWasmOutputToGeometry, WasmGeometryOutput } from '../bridge/render-from-wasm'
|
|
8
4
|
|
|
9
5
|
const VERSION = '1.16.5'
|
|
10
6
|
const STONE = 1 // 1.16.5 stone state id
|
|
@@ -38,7 +34,7 @@ function makeSeamFixture(): WasmGeometryOutput {
|
|
|
38
34
|
// info is baked in here at the per-block level.
|
|
39
35
|
visible_faces: FACE_DOWN | SIDE_FACES,
|
|
40
36
|
ao_data: [],
|
|
41
|
-
light_data: []
|
|
37
|
+
light_data: []
|
|
42
38
|
})
|
|
43
39
|
blocks.push({
|
|
44
40
|
position: [x, 16, z],
|
|
@@ -47,7 +43,7 @@ function makeSeamFixture(): WasmGeometryOutput {
|
|
|
47
43
|
// other side).
|
|
48
44
|
visible_faces: FACE_UP | SIDE_FACES,
|
|
49
45
|
ao_data: [],
|
|
50
|
-
light_data: []
|
|
46
|
+
light_data: []
|
|
51
47
|
})
|
|
52
48
|
}
|
|
53
49
|
}
|
|
@@ -58,12 +54,12 @@ function makeSeamFixture(): WasmGeometryOutput {
|
|
|
58
54
|
block_state_id: STONE,
|
|
59
55
|
visible_faces: FACE_UP | FACE_DOWN | SIDE_FACES,
|
|
60
56
|
ao_data: [],
|
|
61
|
-
light_data: []
|
|
57
|
+
light_data: []
|
|
62
58
|
})
|
|
63
59
|
return {
|
|
64
60
|
blocks,
|
|
65
61
|
block_count: blocks.length,
|
|
66
|
-
block_iterations: 0
|
|
62
|
+
block_iterations: 0
|
|
67
63
|
}
|
|
68
64
|
}
|
|
69
65
|
|
|
@@ -71,15 +67,15 @@ test('splitColumnWasmOutputToSections: per-section split is equivalent to manual
|
|
|
71
67
|
const fullColumn = makeSeamFixture()
|
|
72
68
|
|
|
73
69
|
const requested = [
|
|
74
|
-
{ x: 0, y: 0, z: 0 },
|
|
75
|
-
{ x: 0, y: 16, z: 0 },
|
|
76
|
-
{ x: 0, y: 32, z: 0 },
|
|
77
|
-
{ x: 0, y: 64, z: 0 }
|
|
70
|
+
{ x: 0, y: 0, z: 0 }, // contains Y=15 row only
|
|
71
|
+
{ x: 0, y: 16, z: 0 }, // contains Y=16 row only
|
|
72
|
+
{ x: 0, y: 32, z: 0 }, // empty section
|
|
73
|
+
{ x: 0, y: 64, z: 0 } // contains the isolated block at Y=64
|
|
78
74
|
]
|
|
79
75
|
|
|
80
76
|
const split = splitColumnWasmOutputToSections(fullColumn, requested, {
|
|
81
77
|
version: VERSION,
|
|
82
|
-
shaderCubes: false
|
|
78
|
+
shaderCubes: false
|
|
83
79
|
})
|
|
84
80
|
|
|
85
81
|
expect(split.size).toBe(4)
|
|
@@ -98,13 +94,13 @@ test('splitColumnWasmOutputToSections: per-section split is equivalent to manual
|
|
|
98
94
|
{
|
|
99
95
|
blocks: sectionBlocks,
|
|
100
96
|
block_count: sectionBlocks.length,
|
|
101
|
-
block_iterations: fullColumn.block_iterations
|
|
97
|
+
block_iterations: fullColumn.block_iterations
|
|
102
98
|
},
|
|
103
99
|
VERSION,
|
|
104
100
|
`${r.x},${r.y},${r.z}`,
|
|
105
101
|
{ x: r.x + 8, y: r.y + 8, z: r.z + 8 },
|
|
106
102
|
undefined,
|
|
107
|
-
{ shaderCubes: false }
|
|
103
|
+
{ shaderCubes: false }
|
|
108
104
|
)
|
|
109
105
|
const got = split.get(`${r.x},${r.y},${r.z}`)!.exported
|
|
110
106
|
expect(got.key).toBe(reference.key)
|
|
@@ -149,7 +145,7 @@ test('splitColumnWasmOutputToSections: empty requested-keys list returns empty m
|
|
|
149
145
|
const fullColumn = makeSeamFixture()
|
|
150
146
|
const out = splitColumnWasmOutputToSections(fullColumn, [], {
|
|
151
147
|
version: VERSION,
|
|
152
|
-
shaderCubes: false
|
|
148
|
+
shaderCubes: false
|
|
153
149
|
})
|
|
154
150
|
expect(out.size).toBe(0)
|
|
155
151
|
})
|
|
@@ -158,11 +154,7 @@ test('splitColumnWasmOutputToSections: blocks outside requested sections are dro
|
|
|
158
154
|
const fullColumn = makeSeamFixture()
|
|
159
155
|
// Only request the empty Y=32 section. Y=15/16/64 blocks must NOT
|
|
160
156
|
// leak into it.
|
|
161
|
-
const out = splitColumnWasmOutputToSections(
|
|
162
|
-
fullColumn,
|
|
163
|
-
[{ x: 0, y: 32, z: 0 }],
|
|
164
|
-
{ version: VERSION, shaderCubes: false },
|
|
165
|
-
)
|
|
157
|
+
const out = splitColumnWasmOutputToSections(fullColumn, [{ x: 0, y: 32, z: 0 }], { version: VERSION, shaderCubes: false })
|
|
166
158
|
const empty = out.get('0,32,0')!
|
|
167
159
|
expect(empty.exported.geometry.positions).toEqual([])
|
|
168
160
|
expect(empty.exported.geometry.indices).toEqual([])
|