minecraft-renderer 0.1.72 → 0.1.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.
Files changed (70) hide show
  1. package/README.md +1 -1
  2. package/dist/mesher.js +81 -81
  3. package/dist/mesher.js.map +3 -3
  4. package/dist/mesherWasm.js +1183 -943
  5. package/dist/minecraft-renderer.js +253 -80
  6. package/dist/minecraft-renderer.js.meta.json +1 -1
  7. package/dist/threeWorker.js +1735 -1002
  8. package/package.json +3 -3
  9. package/src/graphicsBackend/config.ts +4 -0
  10. package/src/graphicsBackend/rendererDefaultOptions.ts +2 -7
  11. package/src/graphicsBackend/rendererOptionsSync.ts +1 -1
  12. package/src/graphicsBackend/types.ts +1 -0
  13. package/src/lib/bakeLegacyLight.ts +17 -0
  14. package/src/lib/bindAbortableListener.ts +1 -1
  15. package/src/lib/blockEntityLightRegistry.test.ts +18 -0
  16. package/src/lib/blockEntityLightRegistry.ts +75 -0
  17. package/src/lib/blockEntityLighting.test.ts +30 -0
  18. package/src/lib/blockEntityLighting.ts +53 -0
  19. package/src/lib/createPlayerObject.ts +1 -1
  20. package/src/lib/worldrendererCommon.reconfigure.test.ts +4 -1
  21. package/src/lib/worldrendererCommon.removeColumn.test.ts +8 -4
  22. package/src/lib/worldrendererCommon.ts +15 -7
  23. package/src/mesher-shared/blockEntityMetadata.test.ts +33 -0
  24. package/src/mesher-shared/blockEntityMetadata.ts +19 -3
  25. package/src/mesher-shared/exportedGeometryTypes.ts +11 -0
  26. package/src/mesher-shared/models.ts +161 -92
  27. package/src/mesher-shared/shared.ts +15 -4
  28. package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +40 -0
  29. package/src/mesher-shared/world.ts +12 -0
  30. package/src/mesher-shared/worldLighting.test.ts +54 -0
  31. package/src/playground/baseScene.ts +1 -1
  32. package/src/three/bannerRenderer.ts +14 -4
  33. package/src/three/chunkMeshManager.ts +663 -69
  34. package/src/three/cubeDrawSpans.ts +74 -0
  35. package/src/three/cubeMultiDraw.ts +119 -0
  36. package/src/three/documentRenderer.ts +0 -2
  37. package/src/three/entities.ts +7 -7
  38. package/src/three/entity/EntityMesh.ts +7 -5
  39. package/src/three/entity/gltfAnimationUtils.ts +5 -3
  40. package/src/three/globalBlockBuffer.ts +208 -12
  41. package/src/three/globalLegacyBuffer.ts +701 -0
  42. package/src/three/graphicsBackendBase.ts +9 -5
  43. package/src/three/itemMesh.ts +6 -3
  44. package/src/three/legacySectionCull.ts +85 -0
  45. package/src/three/modules/rain.ts +22 -21
  46. package/src/three/modules/sciFiWorldReveal.ts +347 -703
  47. package/src/three/modules/starfield.ts +19 -6
  48. package/src/three/sectionRaycastAabb.ts +25 -0
  49. package/src/three/shaders/cubeBlockShader.ts +80 -17
  50. package/src/three/shaders/legacyBlockShader.ts +292 -0
  51. package/src/three/skyboxRenderer.ts +1 -1
  52. package/src/three/tests/chunkMeshManagerLegacy.test.ts +286 -0
  53. package/src/three/tests/cubeDrawSpans.test.ts +73 -0
  54. package/src/three/tests/globalLegacyBuffer.test.ts +360 -0
  55. package/src/three/tests/legacySectionCull.test.ts +80 -0
  56. package/src/three/tests/signTextureCache.test.ts +83 -0
  57. package/src/three/threeJsMedia.ts +2 -2
  58. package/src/three/waypointSprite.ts +2 -2
  59. package/src/three/world/cursorBlock.ts +1 -0
  60. package/src/three/world/vr.ts +2 -2
  61. package/src/three/worldGeometryExport.ts +83 -26
  62. package/src/three/worldRendererThree.ts +100 -30
  63. package/src/wasm-mesher/bridge/render-from-wasm.ts +214 -72
  64. package/src/wasm-mesher/bridge/shaderCubeBridge.ts +18 -6
  65. package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
  66. package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +20 -0
  67. package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +80 -12
  68. package/src/wasm-mesher/worker/mesherWasm.ts +70 -14
  69. package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +11 -0
  70. package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +15 -0
@@ -9,6 +9,7 @@ import { renderSign } from '../sign-renderer'
9
9
  import { DisplayWorldOptions, GraphicsInitOptions } from '../graphicsBackend/types'
10
10
  import { chunkPos, sectionPos } from '../lib/simpleUtils'
11
11
  import { WorldRendererCommon } from '../lib/worldrendererCommon'
12
+ import { calculateSkyLightSimple } from '../lib/skyLight'
12
13
  import { addNewStat, MC_RENDERER_DEBUG_OVERLAY_CLASS } from '../lib/ui/newStats'
13
14
  import { MesherGeometryOutput } from '../mesher-shared/shared'
14
15
  import { ItemSpecificContextProperties } from '../playerState/types'
@@ -43,6 +44,9 @@ type SectionKey = string
43
44
  export class WorldRendererThree extends WorldRendererCommon {
44
45
  outputFormat = 'threeJs' as const
45
46
 
47
+ /** r184 removed useLegacyLights; physical intensities ≈ legacy / π. */
48
+ private static readonly LEGACY_TO_PHYSICAL_LIGHT = Math.PI
49
+
46
50
  protected override isShaderCubeBlocksEnabled(): boolean {
47
51
  return this.worldRendererConfig.shaderCubeBlocks === true
48
52
  && !!this.renderer?.capabilities?.isWebGL2
@@ -60,8 +64,8 @@ export class WorldRendererThree extends WorldRendererCommon {
60
64
  get realScene() {
61
65
  return this.scene
62
66
  }
63
- ambientLight = new THREE.AmbientLight(0xcc_cc_cc)
64
- directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5)
67
+ ambientLight = new THREE.AmbientLight(0xcc_cc_cc, WorldRendererThree.LEGACY_TO_PHYSICAL_LIGHT)
68
+ directionalLight = new THREE.DirectionalLight(0xff_ff_ff, 0.5 * WorldRendererThree.LEGACY_TO_PHYSICAL_LIGHT)
65
69
  entities = new Entities(this, (globalThis as any).mcData)
66
70
  performanceMonitor!: PerformanceMonitor
67
71
  cameraGroupVr?: THREE.Object3D
@@ -70,6 +74,7 @@ export class WorldRendererThree extends WorldRendererCommon {
70
74
  cursorBlock: CursorBlock
71
75
  onRender: Array<(deltaTime: number) => void> = []
72
76
  private lastRenderTime = 0
77
+ private lastSciFiTickMs = 0
73
78
  private animatedFov = 0
74
79
  private lastFovAnimTime = 0
75
80
  private static readonly FOV_TRANSITION_MS = 200
@@ -176,6 +181,15 @@ export class WorldRendererThree extends WorldRendererCommon {
176
181
  this.chunkMeshManager.updateViewDistance(viewDistance)
177
182
  }
178
183
 
184
+ // Final lightmap values TBD — compare against https://v99.mcraft.fun/
185
+ if (typeof window !== 'undefined') {
186
+ (window as any).setBlockLightmap = (params: { curve?: number, minBrightness?: number, gamma?: number }) => {
187
+ this.chunkMeshManager.setBlockLightmapParams(params)
188
+ }
189
+ }
190
+
191
+ this.syncSkyLevelFromTime(this.timeOfTheDay)
192
+
179
193
  this.cursorBlock = new CursorBlock(this)
180
194
  this.holdingBlock = createHoldingBlock(this)
181
195
  this.holdingBlockLeft = createHoldingBlock(this, true)
@@ -341,6 +355,11 @@ export class WorldRendererThree extends WorldRendererCommon {
341
355
  return targetState
342
356
  }
343
357
 
358
+ setRain(enabled: boolean): void {
359
+ this.worldRendererConfig.isRaining = enabled
360
+ this.toggleModule('rain', enabled)
361
+ }
362
+
344
363
  /**
345
364
  * Dispose all modules
346
365
  */
@@ -431,6 +450,7 @@ export class WorldRendererThree extends WorldRendererCommon {
431
450
 
432
451
  worldSwitchActions() {
433
452
  this.onWorldSwitched.push(() => {
453
+ this.getModule<{ onWorldSwitched?: () => void }>('futuristicReveal')?.onWorldSwitched?.()
434
454
  // clear custom blocks
435
455
  this.protocolCustomBlocks.clear()
436
456
  // Reset section animations
@@ -441,6 +461,7 @@ export class WorldRendererThree extends WorldRendererCommon {
441
461
  this.cinimaticScript.stopScript()
442
462
  // Clear fireworks
443
463
  this.fireworks.clear()
464
+ this.syncSkyLevelFromTime(this.timeOfTheDay)
444
465
  })
445
466
  }
446
467
 
@@ -500,11 +521,11 @@ export class WorldRendererThree extends WorldRendererCommon {
500
521
  })
501
522
  this.onReactivePlayerStateUpdated('ambientLight', (value) => {
502
523
  if (!value) return
503
- this.ambientLight.intensity = value
524
+ this.ambientLight.intensity = value * WorldRendererThree.LEGACY_TO_PHYSICAL_LIGHT
504
525
  })
505
526
  this.onReactivePlayerStateUpdated('directionalLight', (value) => {
506
527
  if (!value) return
507
- this.directionalLight.intensity = value
528
+ this.directionalLight.intensity = value * WorldRendererThree.LEGACY_TO_PHYSICAL_LIGHT
508
529
  })
509
530
  this.onReactivePlayerStateUpdated('lookingAtBlock', (value) => {
510
531
  this.cursorBlock.setHighlightCursorBlock(value ? new Vec3(value.x, value.y, value.z) : null, value?.shapes)
@@ -530,6 +551,7 @@ export class WorldRendererThree extends WorldRendererCommon {
530
551
  })
531
552
  this.onReactiveConfigUpdated('shaderCubeDebugMode', () => {
532
553
  this.chunkMeshManager.syncCubeShaderUniforms()
554
+ this.chunkMeshManager.syncLegacyShaderUniforms()
533
555
  })
534
556
  this.onReactiveConfigUpdated('futuristicReveal', () => {
535
557
  this.updateModulesFromConfig()
@@ -631,6 +653,7 @@ export class WorldRendererThree extends WorldRendererCommon {
631
653
  texture.flipY = false
632
654
  this.material.map = texture
633
655
  this.chunkMeshManager.syncCubeShaderUniforms()
656
+ this.chunkMeshManager.syncLegacyShaderUniforms()
634
657
 
635
658
  const itemsTexture = loadThreeJsTextureFromBitmap(resources.itemsAtlasImage!)
636
659
  itemsTexture.needsUpdate = true
@@ -675,6 +698,16 @@ export class WorldRendererThree extends WorldRendererCommon {
675
698
  }
676
699
 
677
700
  this.skyboxRenderer.updateTime(newTime)
701
+ this.syncSkyLevelFromTime(newTime)
702
+ }
703
+
704
+ private syncSkyLevelFromTime(timeOfDay: number): void {
705
+ const skyLevel = calculateSkyLightSimple(timeOfDay) / 15
706
+ this.chunkMeshManager.setSkyLevel(skyLevel)
707
+ }
708
+
709
+ protected onDayCycleSkyLightChanged(_skyLight: number): void {
710
+ // Sky cap is driven by u_skyLevel uniform; no remesh on day/night.
678
711
  }
679
712
 
680
713
  biomeUpdated(biome: Biome): void {
@@ -764,10 +797,6 @@ export class WorldRendererThree extends WorldRendererCommon {
764
797
  }
765
798
  }
766
799
 
767
- override updateViewerPosition(pos: Vec3): void {
768
- this.viewerChunkPosition = pos
769
- }
770
-
771
800
  cameraSectionPositionUpdate() {
772
801
  // eslint-disable-next-line guard-for-in
773
802
  for (const key in this.sectionObjects) {
@@ -787,6 +816,7 @@ export class WorldRendererThree extends WorldRendererCommon {
787
816
  // "Batch Chunks Display" (`_renderByChunks`) option. No-op when the
788
817
  // option is off — `waitingChunksToDisplay` is empty in that case.
789
818
  this.chunkMeshManager.finishChunkDisplay(chunkKey)
819
+ this.getModule<{ onChunkFinished?: () => void }>('futuristicReveal')?.onChunkFinished?.()
790
820
  }
791
821
 
792
822
  private applyPendingSectionUpdates() {
@@ -847,8 +877,12 @@ export class WorldRendererThree extends WorldRendererCommon {
847
877
  continue
848
878
  }
849
879
 
850
- this.chunkMeshManager.updateSection(update.key, update.geometry)
880
+ const sectionObject = this.chunkMeshManager.updateSection(update.key, update.geometry)
851
881
  this.updatePosDataChunk(update.key)
882
+ if (sectionObject) {
883
+ this.getModule<{ onSectionMeshed?: (key: string, geometry: MesherGeometryOutput, section: typeof sectionObject) => void }>('futuristicReveal')
884
+ ?.onSectionMeshed?.(update.key, update.geometry, sectionObject)
885
+ }
852
886
  }
853
887
  }
854
888
 
@@ -885,8 +919,12 @@ export class WorldRendererThree extends WorldRendererCommon {
885
919
  this.chunkMeshManager.releaseSection(data.key)
886
920
  return
887
921
  }
888
- this.chunkMeshManager.updateSection(data.key, data.geometry)
922
+ const sectionObject = this.chunkMeshManager.updateSection(data.key, data.geometry)
889
923
  this.updatePosDataChunk(data.key)
924
+ if (sectionObject) {
925
+ this.getModule<{ onSectionMeshed?: (key: string, geometry: MesherGeometryOutput, section: typeof sectionObject) => void }>('futuristicReveal')
926
+ ?.onSectionMeshed?.(data.key, data.geometry, sectionObject)
927
+ }
890
928
  }
891
929
  }
892
930
 
@@ -975,17 +1013,9 @@ export class WorldRendererThree extends WorldRendererCommon {
975
1013
  this.debugRaycast(pos, direction, distance)
976
1014
  }
977
1015
 
978
- // Convert world position to scene-relative coordinates for raycasting
979
- const scenePos = this._tpScenePos.set(
980
- this.sceneOrigin.toSceneX(pos.x),
981
- this.sceneOrigin.toSceneY(pos.y),
982
- this.sceneOrigin.toSceneZ(pos.z)
983
- )
984
-
985
- // Perform raycast to avoid camera going through blocks
986
1016
  const raycaster = this._tpRaycaster
987
- raycaster.set(scenePos, direction)
988
- raycaster.far = distance // Limit raycast distance
1017
+ raycaster.set(pos, direction)
1018
+ raycaster.far = distance
989
1019
 
990
1020
  const maxCenterDistance = 80
991
1021
  const maxCenterDistSq = maxCenterDistance * maxCenterDistance
@@ -993,8 +1023,8 @@ export class WorldRendererThree extends WorldRendererCommon {
993
1023
  const oy = pos.y
994
1024
  const oz = pos.z
995
1025
 
996
- // Legacy / deferred-shader meshes (scene-relative raycast)
997
- const meshes: THREE.Object3D[] = []
1026
+ // Legacy section meshes: world-space raycast (static mesh.matrix translation).
1027
+ const legacyMeshes: THREE.Object3D[] = []
998
1028
  for (const obj of Object.values(this.sectionObjects)) {
999
1029
  if (obj.name !== 'chunk' || !obj.visible) continue
1000
1030
  if (obj.worldX === undefined) continue
@@ -1002,11 +1032,11 @@ export class WorldRendererThree extends WorldRendererCommon {
1002
1032
  const dcy = obj.worldY! - oy
1003
1033
  const dcz = obj.worldZ! - oz
1004
1034
  if (dcx * dcx + dcy * dcy + dcz * dcz > maxCenterDistSq) continue
1005
- const mesh = obj.children.find(child => child.name === 'mesh' || child.name === 'shaderMesh')
1006
- if (mesh) meshes.push(mesh)
1035
+ const mesh = obj.children.find(child => child.name === 'mesh')
1036
+ if (mesh) legacyMeshes.push(mesh)
1007
1037
  }
1008
1038
 
1009
- const intersects = raycaster.intersectObjects(meshes, false)
1039
+ const intersects = raycaster.intersectObjects(legacyMeshes, false)
1010
1040
 
1011
1041
  let finalDistance = distance
1012
1042
  if (intersects.length > 0) {
@@ -1024,6 +1054,15 @@ export class WorldRendererThree extends WorldRendererCommon {
1024
1054
  finalDistance = Math.max(0.5, boxHit - 0.2)
1025
1055
  }
1026
1056
 
1057
+ const legacyGlobalHit = this.chunkMeshManager.raycastGlobalLegacySections(
1058
+ raycaster,
1059
+ pos,
1060
+ maxCenterDistance,
1061
+ )
1062
+ if (legacyGlobalHit !== undefined) {
1063
+ finalDistance = Math.max(0.5, legacyGlobalHit - 0.2)
1064
+ }
1065
+
1027
1066
  const finalPos = new Vec3(
1028
1067
  pos.x + direction.x * finalDistance,
1029
1068
  pos.y + direction.y * finalDistance,
@@ -1280,12 +1319,45 @@ export class WorldRendererThree extends WorldRendererCommon {
1280
1319
 
1281
1320
  // eslint-disable-next-line @typescript-eslint/non-nullable-type-assertion-style
1282
1321
  const cam = this.cameraGroupVr instanceof THREE.Group ? this.cameraGroupVr.children.find(child => child instanceof THREE.PerspectiveCamera) as THREE.PerspectiveCamera : this.camera
1322
+ // Flush buffered section geometry before reveal tick (calls onSectionMeshed synchronously in handleWorkerMessage).
1283
1323
  this.applyPendingSectionUpdates()
1324
+ const sciFiNow = performance.now()
1325
+ const sciFiDeltaMs = sciFiNow - this.lastSciFiTickMs
1326
+ this.lastSciFiTickMs = sciFiNow
1327
+ this.getModule<{ tick?: (deltaMs: number, now?: number) => void }>('futuristicReveal')?.tick?.(sciFiDeltaMs, sciFiNow)
1328
+ const camX = this.cameraWorldPos.x
1329
+ const camY = this.cameraWorldPos.y
1330
+ const camZ = this.cameraWorldPos.z
1331
+ this.chunkMeshManager.maybeRebase({ x: camX, y: camY, z: camZ })
1332
+ const renderOrigin = this.chunkMeshManager.getRenderOrigin()
1284
1333
  const globalBuffer = this.chunkMeshManager.globalBlockBuffer
1285
1334
  if (globalBuffer) {
1286
- globalBuffer.setCameraOrigin(this.cameraWorldPos.x, this.cameraWorldPos.y, this.cameraWorldPos.z)
1335
+ globalBuffer.setCameraOrigin(renderOrigin, camX, camY, camZ)
1336
+ globalBuffer.setDebugOverlay(this.displayOptions.inWorldRenderingConfig.enableDebugOverlay)
1287
1337
  globalBuffer.compactStep()
1288
- globalBuffer.uploadDirtyRange()
1338
+ if (globalBuffer.hasPendingUploads()) {
1339
+ globalBuffer.uploadDirtyRange()
1340
+ }
1341
+ globalBuffer.suppressThreeDraw()
1342
+ }
1343
+ const globalLegacyBuffer = this.chunkMeshManager.globalLegacyBuffer
1344
+ if (globalLegacyBuffer?.hasPendingUploads()) {
1345
+ globalLegacyBuffer.uploadDirtyRange()
1346
+ }
1347
+ const globalLegacyBlendBuffer = this.chunkMeshManager.globalLegacyBlendBuffer
1348
+ if (globalLegacyBlendBuffer?.hasPendingUploads()) {
1349
+ globalLegacyBlendBuffer.uploadDirtyRange()
1350
+ }
1351
+ this.chunkMeshManager.setLegacyCameraOrigin(camX, camY, camZ)
1352
+ this.chunkMeshManager.updateCullDirtyFromCamera(cam, camX, camY, camZ)
1353
+ if (this.chunkMeshManager.cullDirty) {
1354
+ this.chunkMeshManager.updateSectionCullAndSort(
1355
+ cam,
1356
+ this.cameraWorldPos.x,
1357
+ this.cameraWorldPos.y,
1358
+ this.cameraWorldPos.z,
1359
+ )
1360
+ this.chunkMeshManager.clearCullDirty()
1289
1361
  }
1290
1362
  this.renderer.render(this.scene, cam)
1291
1363
 
@@ -1512,7 +1584,7 @@ export class WorldRendererThree extends WorldRendererCommon {
1512
1584
  this.chunkMeshManager.onChunkRemovedFromGate(`${x},${z}`)
1513
1585
  }
1514
1586
 
1515
- updateViewerPosition(pos: Vec3) {
1587
+ override updateViewerPosition(pos: Vec3) {
1516
1588
  super.updateViewerPosition(pos)
1517
1589
  if (this.chunkMeshManager.pendingNearReveal.size > 0) {
1518
1590
  this.chunkMeshManager.tryRevealPending()
@@ -1524,8 +1596,6 @@ export class WorldRendererThree extends WorldRendererCommon {
1524
1596
  }
1525
1597
 
1526
1598
  setSectionDirty(...args: Parameters<WorldRendererCommon['setSectionDirty']>) {
1527
- const [pos] = args
1528
- this.cleanChunkTextures(pos.x, pos.z) // todo don't do this!
1529
1599
  super.setSectionDirty(...args)
1530
1600
  }
1531
1601