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.
- package/README.md +1 -1
- package/dist/mesher.js +81 -81
- package/dist/mesher.js.map +3 -3
- package/dist/mesherWasm.js +1183 -943
- package/dist/minecraft-renderer.js +253 -80
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +1735 -1002
- package/package.json +3 -3
- package/src/graphicsBackend/config.ts +4 -0
- package/src/graphicsBackend/rendererDefaultOptions.ts +2 -7
- package/src/graphicsBackend/rendererOptionsSync.ts +1 -1
- package/src/graphicsBackend/types.ts +1 -0
- package/src/lib/bakeLegacyLight.ts +17 -0
- package/src/lib/bindAbortableListener.ts +1 -1
- package/src/lib/blockEntityLightRegistry.test.ts +18 -0
- package/src/lib/blockEntityLightRegistry.ts +75 -0
- package/src/lib/blockEntityLighting.test.ts +30 -0
- package/src/lib/blockEntityLighting.ts +53 -0
- package/src/lib/createPlayerObject.ts +1 -1
- package/src/lib/worldrendererCommon.reconfigure.test.ts +4 -1
- package/src/lib/worldrendererCommon.removeColumn.test.ts +8 -4
- package/src/lib/worldrendererCommon.ts +15 -7
- package/src/mesher-shared/blockEntityMetadata.test.ts +33 -0
- package/src/mesher-shared/blockEntityMetadata.ts +19 -3
- package/src/mesher-shared/exportedGeometryTypes.ts +11 -0
- package/src/mesher-shared/models.ts +161 -92
- package/src/mesher-shared/shared.ts +15 -4
- package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +40 -0
- package/src/mesher-shared/world.ts +12 -0
- package/src/mesher-shared/worldLighting.test.ts +54 -0
- package/src/playground/baseScene.ts +1 -1
- package/src/three/bannerRenderer.ts +14 -4
- package/src/three/chunkMeshManager.ts +663 -69
- package/src/three/cubeDrawSpans.ts +74 -0
- package/src/three/cubeMultiDraw.ts +119 -0
- package/src/three/documentRenderer.ts +0 -2
- package/src/three/entities.ts +7 -7
- package/src/three/entity/EntityMesh.ts +7 -5
- package/src/three/entity/gltfAnimationUtils.ts +5 -3
- package/src/three/globalBlockBuffer.ts +208 -12
- package/src/three/globalLegacyBuffer.ts +701 -0
- package/src/three/graphicsBackendBase.ts +9 -5
- package/src/three/itemMesh.ts +6 -3
- package/src/three/legacySectionCull.ts +85 -0
- package/src/three/modules/rain.ts +22 -21
- package/src/three/modules/sciFiWorldReveal.ts +347 -703
- package/src/three/modules/starfield.ts +19 -6
- package/src/three/sectionRaycastAabb.ts +25 -0
- package/src/three/shaders/cubeBlockShader.ts +80 -17
- package/src/three/shaders/legacyBlockShader.ts +292 -0
- package/src/three/skyboxRenderer.ts +1 -1
- package/src/three/tests/chunkMeshManagerLegacy.test.ts +286 -0
- package/src/three/tests/cubeDrawSpans.test.ts +73 -0
- package/src/three/tests/globalLegacyBuffer.test.ts +360 -0
- package/src/three/tests/legacySectionCull.test.ts +80 -0
- package/src/three/tests/signTextureCache.test.ts +83 -0
- package/src/three/threeJsMedia.ts +2 -2
- package/src/three/waypointSprite.ts +2 -2
- package/src/three/world/cursorBlock.ts +1 -0
- package/src/three/world/vr.ts +2 -2
- package/src/three/worldGeometryExport.ts +83 -26
- package/src/three/worldRendererThree.ts +100 -30
- package/src/wasm-mesher/bridge/render-from-wasm.ts +214 -72
- package/src/wasm-mesher/bridge/shaderCubeBridge.ts +18 -6
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
- package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +20 -0
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +80 -12
- package/src/wasm-mesher/worker/mesherWasm.ts +70 -14
- package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +11 -0
- package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +15 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minecraft-renderer",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.74",
|
|
4
4
|
"description": "The most Modular Minecraft world renderer with Three.js WebGL backend",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"skinview3d": "^3.4.1",
|
|
56
56
|
"stats-gl": "^1.0.5",
|
|
57
57
|
"stats.js": "^0.17.0",
|
|
58
|
-
"three": "0.
|
|
58
|
+
"three": "0.184.0",
|
|
59
59
|
"three-stdlib": "^2.36.1",
|
|
60
60
|
"type-fest": "^5.3.0",
|
|
61
61
|
"typed-emitter": "^2.1.0",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
"@types/lodash": "^4.17.21",
|
|
71
71
|
"@types/react": "^19.2.7",
|
|
72
72
|
"@types/stats.js": "^0.17.1",
|
|
73
|
-
"@types/three": "0.
|
|
73
|
+
"@types/three": "0.184.0",
|
|
74
74
|
"@zardoy/react-util": "^0.2.7",
|
|
75
75
|
"@zardoy/tsconfig": "^1.5.1",
|
|
76
76
|
"contro-max": "*",
|
|
@@ -81,6 +81,10 @@ export const defaultWorldRendererConfig = {
|
|
|
81
81
|
isPlayground: false,
|
|
82
82
|
instantCameraUpdate: false,
|
|
83
83
|
isRaining: false,
|
|
84
|
+
// rainColor: 'rgb(64, 87, 148)', // original minecraft blue
|
|
85
|
+
rainColor: 'rgb(118, 148, 226)',
|
|
86
|
+
/** Rain particle opacity 0–1. */
|
|
87
|
+
rainOpacity: 0.5,
|
|
84
88
|
|
|
85
89
|
// Module states: 'enabled' = force on, 'disabled' = force off, 'auto' = use autoEnableCheck
|
|
86
90
|
moduleStates: {} as Record<string, 'enabled' | 'disabled' | 'auto'>
|
|
@@ -63,7 +63,6 @@ export const RENDERER_DEFAULT_OPTIONS = {
|
|
|
63
63
|
rendererPerfDebugOverlay: false as boolean,
|
|
64
64
|
disableBlockEntityTextures: false as boolean,
|
|
65
65
|
rendererMesher: 'wasm' as RendererMesherPipeline,
|
|
66
|
-
rendererShaderCubeBlocks: false as boolean,
|
|
67
66
|
rendererShaderCubeDebugMode: 'off' as RendererShaderCubeDebugMode,
|
|
68
67
|
showChunkBorders: false as boolean,
|
|
69
68
|
renderEntities: true as boolean,
|
|
@@ -110,6 +109,7 @@ export function migrateRendererOptions(saved: Record<string, unknown>): void {
|
|
|
110
109
|
}
|
|
111
110
|
delete saved.wasmExperimentalMesher
|
|
112
111
|
delete saved.rendererWasmMesher
|
|
112
|
+
delete saved.rendererShaderCubeBlocks
|
|
113
113
|
|
|
114
114
|
if (saved.menuBackgroundMode === 'futuristic') {
|
|
115
115
|
saved.menuBackgroundMode = 'v2'
|
|
@@ -196,11 +196,6 @@ export const RENDERER_OPTIONS_META: Partial<Record<RendererDefaultOptionKey, Ren
|
|
|
196
196
|
tooltip: 'Browser technology for processing world geometry before render. WASM is the fastest; if you see a dead tab icon, reloads, or other errors, switch to Legacy JS.',
|
|
197
197
|
requiresChunksReload: true,
|
|
198
198
|
},
|
|
199
|
-
rendererShaderCubeBlocks: {
|
|
200
|
-
text: '(UNSTABLE) Instanced shader cubes',
|
|
201
|
-
tooltip: 'Render full blocks through the global GPU instanced path. Requires WASM mesher and WebGL2.',
|
|
202
|
-
requiresChunksReload: true,
|
|
203
|
-
},
|
|
204
199
|
rendererShaderCubeDebugMode: {
|
|
205
200
|
text: 'Shader cube debug',
|
|
206
201
|
tooltip: 'Instanced cube path visualization (requires shader cubes enabled).',
|
|
@@ -341,7 +336,7 @@ export const RENDERER_RENDER_GUI_SECTIONS: ReadonlyArray<{
|
|
|
341
336
|
},
|
|
342
337
|
{
|
|
343
338
|
title: 'Mesher',
|
|
344
|
-
keys: ['rendererMesher'
|
|
339
|
+
keys: ['rendererMesher']
|
|
345
340
|
},
|
|
346
341
|
{
|
|
347
342
|
title: 'Renderer debug',
|
|
@@ -163,7 +163,7 @@ export function applyRendererOptions(
|
|
|
163
163
|
cfg.fetchPlayerSkins = o.loadPlayerSkins
|
|
164
164
|
cfg.highlightBlockColor = o.highlightBlockColor
|
|
165
165
|
cfg.wasmMesher = wasmActive
|
|
166
|
-
cfg.shaderCubeBlocks =
|
|
166
|
+
cfg.shaderCubeBlocks = wasmActive
|
|
167
167
|
cfg.disableMesherConversionCache = !!ctx.isSafari
|
|
168
168
|
|
|
169
169
|
setSkinsConfig({ apiEnabled: o.loadPlayerSkins })
|
|
@@ -101,6 +101,7 @@ export interface GraphicsInitOptions<S = any> {
|
|
|
101
101
|
/** Live app options (e.g. valtio proxy); used for WebGL `gpuPreference` at context creation. */
|
|
102
102
|
getRendererOptions?: () => RendererStorageOptions
|
|
103
103
|
rendererSpecificSettings: S
|
|
104
|
+
hello?: boolean
|
|
104
105
|
callbacks: {
|
|
105
106
|
displayCriticalError: (error: Error) => void
|
|
106
107
|
setRendererSpecificSettings: (key: string, value: any) => void
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
/** Bake tint×AO colors with sky/block channels for static export (no live u_skyLevel uniform). */
|
|
3
|
+
export function bakeLegacyVertexColors (
|
|
4
|
+
colors: ArrayLike<number>,
|
|
5
|
+
skyLights: ArrayLike<number>,
|
|
6
|
+
blockLights: ArrayLike<number>,
|
|
7
|
+
skyLevel: number,
|
|
8
|
+
): number[] {
|
|
9
|
+
const vertCount = colors.length / 3
|
|
10
|
+
const out: number[] = []
|
|
11
|
+
for (let v = 0; v < vertCount; v++) {
|
|
12
|
+
const L = Math.max(blockLights[v] ?? 0, Math.min(skyLights[v] ?? 1, skyLevel))
|
|
13
|
+
const i = v * 3
|
|
14
|
+
out.push(colors[i]! * L, colors[i + 1]! * L, colors[i + 2]! * L)
|
|
15
|
+
}
|
|
16
|
+
return out
|
|
17
|
+
}
|
|
@@ -10,7 +10,7 @@ import type { WorldViewWorker } from '../worldView'
|
|
|
10
10
|
export function bindAbortableListener<E extends keyof WorldViewEvents>(
|
|
11
11
|
emitter: Pick<WorldViewWorker, 'on' | 'off'>,
|
|
12
12
|
event: E,
|
|
13
|
-
handler: (...args: WorldViewEvents[E]) => void,
|
|
13
|
+
handler: (...args: Parameters<WorldViewEvents[E]>) => void,
|
|
14
14
|
signal: AbortSignal
|
|
15
15
|
): void {
|
|
16
16
|
emitter.on(event, handler as (...args: any[]) => void)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import * as THREE from 'three'
|
|
4
|
+
import { blockEntityBrightness } from './blockEntityLighting'
|
|
5
|
+
import { BlockEntityLightRegistry } from './blockEntityLightRegistry'
|
|
6
|
+
|
|
7
|
+
describe('BlockEntityLightRegistry', () => {
|
|
8
|
+
it('refreshes overlay brightness when sky level changes', () => {
|
|
9
|
+
const registry = new BlockEntityLightRegistry()
|
|
10
|
+
const material = new THREE.MeshBasicMaterial()
|
|
11
|
+
registry.register({ material, blockLightNorm: 0, skyLightNorm: 1 })
|
|
12
|
+
const nightSky = 4 / 15
|
|
13
|
+
registry.setSkyLevel(nightSky)
|
|
14
|
+
expect(material.color.r).toBeCloseTo(blockEntityBrightness(0, 1, nightSky), 5)
|
|
15
|
+
registry.setSkyLevel(1)
|
|
16
|
+
expect(material.color.r).toBe(1)
|
|
17
|
+
})
|
|
18
|
+
})
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import * as THREE from 'three'
|
|
3
|
+
import {
|
|
4
|
+
blockEntityBrightness,
|
|
5
|
+
DEFAULT_LIGHTMAP_PARAMS,
|
|
6
|
+
type BlockLightmapParams,
|
|
7
|
+
} from './blockEntityLighting'
|
|
8
|
+
|
|
9
|
+
export type BlockEntityOverlayLight = {
|
|
10
|
+
material: THREE.MeshBasicMaterial
|
|
11
|
+
blockLightNorm: number
|
|
12
|
+
skyLightNorm: number
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export class BlockEntityLightRegistry {
|
|
16
|
+
private readonly entries = new Set<BlockEntityOverlayLight>()
|
|
17
|
+
private skyLevel = 1
|
|
18
|
+
private lightmapParams: BlockLightmapParams = { ...DEFAULT_LIGHTMAP_PARAMS }
|
|
19
|
+
|
|
20
|
+
register (entry: BlockEntityOverlayLight): void {
|
|
21
|
+
this.entries.add(entry)
|
|
22
|
+
this.applyBrightness(entry)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
unregister (material: THREE.Material): void {
|
|
26
|
+
for (const entry of this.entries) {
|
|
27
|
+
if (entry.material === material) {
|
|
28
|
+
this.entries.delete(entry)
|
|
29
|
+
break
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
setSkyLevel (value: number): void {
|
|
35
|
+
this.skyLevel = value
|
|
36
|
+
this.refreshAll()
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
setLightmapParams (params: BlockLightmapParams): void {
|
|
40
|
+
this.lightmapParams = { ...this.lightmapParams, ...params }
|
|
41
|
+
this.refreshAll()
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getSkyLevel (): number {
|
|
45
|
+
return this.skyLevel
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
private refreshAll (): void {
|
|
49
|
+
for (const entry of this.entries) {
|
|
50
|
+
this.applyBrightness(entry)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private applyBrightness (entry: BlockEntityOverlayLight): void {
|
|
55
|
+
const brightness = blockEntityBrightness(
|
|
56
|
+
entry.blockLightNorm,
|
|
57
|
+
entry.skyLightNorm,
|
|
58
|
+
this.skyLevel,
|
|
59
|
+
this.lightmapParams,
|
|
60
|
+
)
|
|
61
|
+
entry.material.color.setScalar(brightness)
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function tintBannerMaterial (
|
|
66
|
+
material: THREE.MeshBasicMaterial,
|
|
67
|
+
blockLightNorm: number,
|
|
68
|
+
skyLightNorm: number,
|
|
69
|
+
skyLevel: number,
|
|
70
|
+
lightmapParams: BlockLightmapParams = DEFAULT_LIGHTMAP_PARAMS,
|
|
71
|
+
): number {
|
|
72
|
+
const brightness = blockEntityBrightness(blockLightNorm, skyLightNorm, skyLevel, lightmapParams)
|
|
73
|
+
material.color.setScalar(brightness)
|
|
74
|
+
return brightness
|
|
75
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import {
|
|
4
|
+
applyLightmap,
|
|
5
|
+
blockEntityBrightness,
|
|
6
|
+
combinedBlockLight,
|
|
7
|
+
DEFAULT_LIGHTMAP_PARAMS,
|
|
8
|
+
} from './blockEntityLighting'
|
|
9
|
+
|
|
10
|
+
describe('blockEntityLighting', () => {
|
|
11
|
+
it('applyLightmap(1) === 1 for default params', () => {
|
|
12
|
+
expect(applyLightmap(1, DEFAULT_LIGHTMAP_PARAMS)).toBe(1)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
it('combinedBlockLight caps sky by skyLevel', () => {
|
|
16
|
+
expect(combinedBlockLight(0, 1, 4 / 15)).toBeCloseTo(4 / 15, 5)
|
|
17
|
+
expect(combinedBlockLight(0.5, 1, 4 / 15)).toBeCloseTo(0.5, 5)
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
it('night outdoor blockEntityBrightness matches cap + lightmap', () => {
|
|
21
|
+
const skyLevel = 4 / 15
|
|
22
|
+
const L = combinedBlockLight(0, 1, skyLevel)
|
|
23
|
+
expect(blockEntityBrightness(0, 1, skyLevel)).toBeCloseTo(applyLightmap(L), 5)
|
|
24
|
+
})
|
|
25
|
+
|
|
26
|
+
it('linear curve matches raw L at minBrightness 0', () => {
|
|
27
|
+
const p = { curve: 0, minBrightness: 0, gamma: 1 }
|
|
28
|
+
expect(applyLightmap(0.5, p)).toBeCloseTo(0.5, 5)
|
|
29
|
+
})
|
|
30
|
+
})
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
/**
|
|
3
|
+
* Shared block lighting math — keep in sync with APPLY_LIGHTMAP_GLSL in shaders.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export type BlockLightmapParams = {
|
|
7
|
+
curve?: number
|
|
8
|
+
minBrightness?: number
|
|
9
|
+
gamma?: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const DEFAULT_LIGHTMAP_PARAMS: Required<BlockLightmapParams> = {
|
|
13
|
+
curve: 0,
|
|
14
|
+
minBrightness: 0.12,
|
|
15
|
+
gamma: 1,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** GLSL body for applyLightmap — requires u_lightCurve, u_minBrightness, u_lightGamma uniforms. */
|
|
19
|
+
export const APPLY_LIGHTMAP_GLSL = /* glsl */ `
|
|
20
|
+
float applyLightmap(float L) {
|
|
21
|
+
float curved = L / (4.0 - 3.0 * L);
|
|
22
|
+
float shaped = mix(L, curved, u_lightCurve);
|
|
23
|
+
shaped = mix(u_minBrightness, 1.0, shaped);
|
|
24
|
+
return clamp(pow(shaped, u_lightGamma), 0.0, 1.0);
|
|
25
|
+
}
|
|
26
|
+
`
|
|
27
|
+
|
|
28
|
+
export function applyLightmap (L: number, params: BlockLightmapParams = DEFAULT_LIGHTMAP_PARAMS): number {
|
|
29
|
+
const curve = params.curve ?? DEFAULT_LIGHTMAP_PARAMS.curve
|
|
30
|
+
const minBrightness = params.minBrightness ?? DEFAULT_LIGHTMAP_PARAMS.minBrightness
|
|
31
|
+
const gamma = params.gamma ?? DEFAULT_LIGHTMAP_PARAMS.gamma
|
|
32
|
+
|
|
33
|
+
const curved = L / (4 - 3 * L)
|
|
34
|
+
let shaped = L * (1 - curve) + curved * curve
|
|
35
|
+
shaped = minBrightness + shaped * (1 - minBrightness)
|
|
36
|
+
return Math.min(1, Math.max(0, shaped ** gamma))
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/** Same cap as block shaders: max(block, min(sky, skyLevel)). */
|
|
40
|
+
export function combinedBlockLight (block: number, sky: number, skyLevel: number): number {
|
|
41
|
+
return Math.max(block, Math.min(sky, skyLevel))
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** 0..1 brightness for MeshBasicMaterial.color.setScalar on block-entity overlays. */
|
|
45
|
+
export function blockEntityBrightness (
|
|
46
|
+
blockNorm: number,
|
|
47
|
+
skyNorm: number,
|
|
48
|
+
skyLevel: number,
|
|
49
|
+
lightmapParams: BlockLightmapParams = DEFAULT_LIGHTMAP_PARAMS,
|
|
50
|
+
): number {
|
|
51
|
+
const L = combinedBlockLight(blockNorm, skyNorm, skyLevel)
|
|
52
|
+
return applyLightmap(L, lightmapParams)
|
|
53
|
+
}
|
|
@@ -12,7 +12,7 @@ export type PlayerObjectType = PlayerObject & {
|
|
|
12
12
|
|
|
13
13
|
/** Starfield + log-depth world: cutout skin mats need alphaTest and depthWrite (not mesh traverse). */
|
|
14
14
|
export function configurePlayerSkinMaterials (playerObject: PlayerObject): void {
|
|
15
|
-
const skin = playerObject.skin
|
|
15
|
+
const skin = playerObject.skin as any
|
|
16
16
|
const materials = [
|
|
17
17
|
skin.layer1Material,
|
|
18
18
|
skin.layer1MaterialBiased,
|
|
@@ -6,6 +6,7 @@ import { proxy } from 'valtio'
|
|
|
6
6
|
import * as worldRendererModule from './worldrendererCommon'
|
|
7
7
|
import { WorldRendererCommon } from './worldrendererCommon'
|
|
8
8
|
import { defaultWorldRendererConfig } from '../graphicsBackend/config'
|
|
9
|
+
import { defaultPerformanceInstabilityFactors } from '../performanceMonitor'
|
|
9
10
|
import { getInitialPlayerState } from '../playerState/playerState'
|
|
10
11
|
import type { DisplayWorldOptions, GraphicsInitOptions } from '../graphicsBackend/types'
|
|
11
12
|
|
|
@@ -46,6 +47,8 @@ class TestWorldRenderer extends WorldRendererCommon {
|
|
|
46
47
|
updateCamera() {}
|
|
47
48
|
render() {}
|
|
48
49
|
updateShowChunksBorder() {}
|
|
50
|
+
updatePlayerEntity() {}
|
|
51
|
+
worldStop() {}
|
|
49
52
|
}
|
|
50
53
|
|
|
51
54
|
function createRenderer(workerCount = 2, worldView?: DisplayWorldOptions['worldView']) {
|
|
@@ -56,7 +59,7 @@ function createRenderer(workerCount = 2, worldView?: DisplayWorldOptions['worldV
|
|
|
56
59
|
heightmaps: {} as Record<string, Int16Array>,
|
|
57
60
|
allChunksLoaded: false,
|
|
58
61
|
mesherWork: false,
|
|
59
|
-
instabilityFactors:
|
|
62
|
+
instabilityFactors: defaultPerformanceInstabilityFactors(),
|
|
60
63
|
intersectMedia: null,
|
|
61
64
|
},
|
|
62
65
|
renderer: '',
|
|
@@ -5,6 +5,7 @@ import { Vec3 } from 'vec3'
|
|
|
5
5
|
import { proxy } from 'valtio'
|
|
6
6
|
import { WorldRendererCommon } from './worldrendererCommon'
|
|
7
7
|
import { defaultWorldRendererConfig } from '../graphicsBackend/config'
|
|
8
|
+
import { defaultPerformanceInstabilityFactors } from '../performanceMonitor'
|
|
8
9
|
import { getInitialPlayerState } from '../playerState/playerState'
|
|
9
10
|
import type { DisplayWorldOptions, GraphicsInitOptions } from '../graphicsBackend/types'
|
|
10
11
|
|
|
@@ -45,16 +46,18 @@ class TestWorldRenderer extends WorldRendererCommon {
|
|
|
45
46
|
updateCamera() {}
|
|
46
47
|
render() {}
|
|
47
48
|
updateShowChunksBorder() {}
|
|
49
|
+
updatePlayerEntity() {}
|
|
50
|
+
worldStop() {}
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
function createRenderer() {
|
|
51
54
|
const rendererState = proxy({
|
|
52
55
|
world: {
|
|
53
|
-
chunksLoaded:
|
|
54
|
-
heightmaps:
|
|
56
|
+
chunksLoaded: {} as Record<string, true>,
|
|
57
|
+
heightmaps: {} as Record<string, Int16Array>,
|
|
55
58
|
allChunksLoaded: false,
|
|
56
59
|
mesherWork: false,
|
|
57
|
-
instabilityFactors:
|
|
60
|
+
instabilityFactors: defaultPerformanceInstabilityFactors(),
|
|
58
61
|
intersectMedia: null,
|
|
59
62
|
},
|
|
60
63
|
renderer: '',
|
|
@@ -73,6 +76,7 @@ function createRenderer() {
|
|
|
73
76
|
avgRenderTime: 0,
|
|
74
77
|
world: {
|
|
75
78
|
chunksLoaded: new Set<string>(),
|
|
79
|
+
chunksLoadedCount: 0,
|
|
76
80
|
chunksTotalNumber: 0,
|
|
77
81
|
chunksFullInfo: '',
|
|
78
82
|
},
|
|
@@ -93,7 +97,7 @@ function createRenderer() {
|
|
|
93
97
|
},
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
const renderer = new TestWorldRenderer(displayOptions.resourcesManager, displayOptions, initOptions)
|
|
100
|
+
const renderer = new TestWorldRenderer(displayOptions.resourcesManager, displayOptions as DisplayWorldOptions, initOptions)
|
|
97
101
|
renderer.active = true
|
|
98
102
|
renderer.workers = [{ postMessage: vi.fn() }, { postMessage: vi.fn() }]
|
|
99
103
|
renderer.viewDistance = 16
|
|
@@ -33,6 +33,7 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|
|
33
33
|
worldReadyResolvers = Promise.withResolvers<void>()
|
|
34
34
|
worldReadyPromise = this.worldReadyResolvers.promise
|
|
35
35
|
timeOfTheDay = 0
|
|
36
|
+
lastMesherSkyLight = 15
|
|
36
37
|
worldSizeParams = { minY: 0, worldHeight: 256 }
|
|
37
38
|
reactiveDebugParams = proxy({
|
|
38
39
|
stopRendering: false,
|
|
@@ -695,6 +696,9 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|
|
695
696
|
|
|
696
697
|
timeUpdated?(newTime: number): void
|
|
697
698
|
|
|
699
|
+
/** Called when day-cycle sky-light bucket changes; Three.js overrides to remesh. */
|
|
700
|
+
protected onDayCycleSkyLightChanged?(_skyLight: number): void
|
|
701
|
+
|
|
698
702
|
biomeUpdated?(biome: any): void
|
|
699
703
|
|
|
700
704
|
biomeReset?(): void
|
|
@@ -1064,16 +1068,20 @@ export abstract class WorldRendererCommon<WorkerSend = any, WorkerReceive = any>
|
|
|
1064
1068
|
}, signal)
|
|
1065
1069
|
|
|
1066
1070
|
bindAbortableListener(worldEmitter, 'time', (timeOfDay) => {
|
|
1067
|
-
if (!this.worldRendererConfig.dayCycle)
|
|
1071
|
+
if (!this.worldRendererConfig.dayCycle) {
|
|
1072
|
+
return
|
|
1073
|
+
}
|
|
1068
1074
|
this.timeUpdated?.(timeOfDay)
|
|
1069
1075
|
|
|
1070
1076
|
this.timeOfTheDay = timeOfDay
|
|
1071
1077
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1078
|
+
const skyLight = (timeOfDay < 0 || timeOfDay > 24_000) ? 15 : calculateSkyLightSimple(timeOfDay)
|
|
1079
|
+
if (this.lastMesherSkyLight === skyLight) return
|
|
1080
|
+
this.lastMesherSkyLight = skyLight
|
|
1081
|
+
if (this.workers.length > 0) {
|
|
1082
|
+
this.sendWorkers({ config: { skyLight } } as WorkerSend)
|
|
1083
|
+
}
|
|
1084
|
+
this.onDayCycleSkyLightChanged?.(skyLight)
|
|
1077
1085
|
}, signal)
|
|
1078
1086
|
|
|
1079
1087
|
bindAbortableListener(worldEmitter, 'biomeUpdate', ({ biome }) => {
|
|
@@ -1435,7 +1443,7 @@ export const initMesherWorker = (onGotMessage: (data: any) => void, workerName =
|
|
|
1435
1443
|
let mesherMcDataTintsMissingWarned = false
|
|
1436
1444
|
|
|
1437
1445
|
export const meshersSendMcData = (workers: Worker[], version: string, mcDataKeys = dynamicMcDataFiles, mcDataFull: IndexedData) => {
|
|
1438
|
-
const mcData = {
|
|
1446
|
+
const mcData: { version: IndexedData['version']; tints?: unknown; [key: string]: unknown } = {
|
|
1439
1447
|
version: JSON.parse(JSON.stringify(mcDataFull.version))
|
|
1440
1448
|
}
|
|
1441
1449
|
for (const [finalKey, sourceKey] of Object.entries(mcDataKeys)) {
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import { describe, expect, it } from 'vitest'
|
|
3
|
+
import { Vec3 } from 'vec3'
|
|
4
|
+
import { collectBlockEntityMetadata } from './blockEntityMetadata'
|
|
5
|
+
|
|
6
|
+
describe('collectBlockEntityMetadata', () => {
|
|
7
|
+
it('stores channel light norms on banner metadata', () => {
|
|
8
|
+
const target = { signs: {}, heads: {}, banners: {} }
|
|
9
|
+
const block = {
|
|
10
|
+
name: 'pink_banner',
|
|
11
|
+
getProperties: () => ({ rotation: 0 }),
|
|
12
|
+
}
|
|
13
|
+
collectBlockEntityMetadata(
|
|
14
|
+
block,
|
|
15
|
+
1, 2, 3,
|
|
16
|
+
target,
|
|
17
|
+
{},
|
|
18
|
+
{
|
|
19
|
+
getChannelLightNorm: (pos: Vec3) => {
|
|
20
|
+
expect(pos).toBeInstanceOf(Vec3)
|
|
21
|
+
return { block: 0.4, sky: 0.8 }
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
)
|
|
25
|
+
expect(target.banners['1,2,3']).toEqual({
|
|
26
|
+
isWall: false,
|
|
27
|
+
blockName: 'pink_banner',
|
|
28
|
+
rotation: 0,
|
|
29
|
+
blockLightNorm: 0.4,
|
|
30
|
+
skyLightNorm: 0.8,
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
})
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
//@ts-nocheck
|
|
2
|
+
import { Vec3 } from 'vec3'
|
|
3
|
+
|
|
2
4
|
export interface SignMeta { isWall: boolean; isHanging: boolean; rotation: number }
|
|
3
5
|
export interface HeadMeta { isWall: boolean; rotation: number }
|
|
4
|
-
export interface BannerMeta {
|
|
6
|
+
export interface BannerMeta {
|
|
7
|
+
isWall: boolean
|
|
8
|
+
blockName: string
|
|
9
|
+
rotation: number
|
|
10
|
+
blockLightNorm: number
|
|
11
|
+
skyLightNorm: number
|
|
12
|
+
}
|
|
5
13
|
|
|
6
14
|
export interface BlockEntityMetadataTarget {
|
|
7
15
|
signs: Record<string, SignMeta>
|
|
@@ -15,11 +23,16 @@ export interface BlockEntityMetadataOptions {
|
|
|
15
23
|
|
|
16
24
|
type BlockLike = { name: string; getProperties(): any }
|
|
17
25
|
|
|
26
|
+
type LightSampler = {
|
|
27
|
+
getChannelLightNorm(pos: Vec3): { block: number, sky: number }
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
export function collectBlockEntityMetadata(
|
|
19
31
|
block: BlockLike,
|
|
20
32
|
x: number, y: number, z: number,
|
|
21
33
|
target: BlockEntityMetadataTarget,
|
|
22
|
-
options: BlockEntityMetadataOptions
|
|
34
|
+
options: BlockEntityMetadataOptions,
|
|
35
|
+
world?: LightSampler,
|
|
23
36
|
): void {
|
|
24
37
|
if ((block.name.includes('_sign') || block.name === 'sign') && !options.disableBlockEntityTextures) {
|
|
25
38
|
const key = `${x},${y},${z}`
|
|
@@ -61,10 +74,13 @@ export function collectBlockEntityMetadata(
|
|
|
61
74
|
'east': 3
|
|
62
75
|
}
|
|
63
76
|
const isWall = block.name.endsWith('_wall_banner')
|
|
77
|
+
const light = world?.getChannelLightNorm(new Vec3(x, y, z)) ?? { block: 0, sky: 1 }
|
|
64
78
|
target.banners[key] = {
|
|
65
79
|
isWall,
|
|
66
80
|
blockName: block.name, // Pass block name for base color extraction
|
|
67
|
-
rotation: isWall ? facingRotationMap[props.facing] : (props.rotation === undefined ? 0 : +props.rotation)
|
|
81
|
+
rotation: isWall ? facingRotationMap[props.facing] : (props.rotation === undefined ? 0 : +props.rotation),
|
|
82
|
+
blockLightNorm: light.block,
|
|
83
|
+
skyLightNorm: light.sky,
|
|
68
84
|
}
|
|
69
85
|
}
|
|
70
86
|
}
|
|
@@ -8,6 +8,17 @@ export interface ExportedSection {
|
|
|
8
8
|
positions: number[]
|
|
9
9
|
normals: number[]
|
|
10
10
|
colors: number[]
|
|
11
|
+
skyLights: number[]
|
|
12
|
+
blockLights: number[]
|
|
13
|
+
uvs: number[]
|
|
14
|
+
indices: number[]
|
|
15
|
+
}
|
|
16
|
+
blendGeometry?: {
|
|
17
|
+
positions: number[]
|
|
18
|
+
normals: number[]
|
|
19
|
+
colors: number[]
|
|
20
|
+
skyLights: number[]
|
|
21
|
+
blockLights: number[]
|
|
11
22
|
uvs: number[]
|
|
12
23
|
indices: number[]
|
|
13
24
|
}
|