minecraft-renderer 0.1.48 → 0.1.50
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/mesher.js +1 -1
- package/dist/mesher.js.map +2 -2
- package/dist/mesherWasm.js +3740 -183
- package/dist/minecraft-renderer.js +332 -60
- package/dist/minecraft-renderer.js.meta.json +1 -1
- package/dist/threeWorker.js +705 -433
- package/package.json +1 -1
- package/src/graphicsBackend/config.ts +4 -0
- package/src/graphicsBackend/playerState.ts +1 -0
- package/src/graphicsBackend/rendererOptionsSync.ts +2 -0
- package/src/lib/worldrendererCommon.ts +13 -0
- package/src/mesher-shared/exportedGeometryTypes.ts +5 -1
- package/src/mesher-shared/shared.ts +8 -0
- package/src/three/chunkMeshManager.ts +312 -39
- package/src/three/globalBlockBuffer.ts +292 -0
- package/src/three/menuBackground/config.ts +1 -1
- package/src/three/menuBackground/defaultOptions.ts +52 -19
- package/src/three/menuBackground/index.ts +5 -1
- package/src/three/modules/sciFiWorldReveal.ts +162 -68
- package/src/three/modules/starfield.ts +9 -1
- package/src/three/sectionRaycastAabb.ts +167 -0
- package/src/three/shaderCubeMesh.ts +93 -0
- package/src/three/shaders/cubeBlockShader.ts +354 -0
- package/src/three/shaders/textureIndexMapping.ts +122 -0
- package/src/three/shaders/tintPalette.ts +198 -0
- package/src/three/worldGeometryExport.ts +53 -25
- package/src/three/worldRendererThree.ts +56 -23
- package/src/wasm-mesher/bridge/render-from-wasm.ts +62 -185
- package/src/wasm-mesher/bridge/shaderCubeBridge.ts +399 -0
- package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
- package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +58 -0
- package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +360 -0
- package/src/wasm-mesher/tests/splitColumnWasmOutput.test.ts +11 -4
- package/src/wasm-mesher/worker/mesherWasm.ts +17 -2
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
//@ts-nocheck
|
|
2
|
+
import * as THREE from 'three'
|
|
3
|
+
import { VERTICES_PER_FACE } from './shaders/cubeBlockShader'
|
|
4
|
+
import { packWord2Empty } from '../wasm-mesher/bridge/shaderCubeBridge'
|
|
5
|
+
|
|
6
|
+
const INITIAL_CAPACITY_FACES = 2_000_000
|
|
7
|
+
const EMPTY_W2 = packWord2Empty()
|
|
8
|
+
|
|
9
|
+
export type GlobalBlockBufferShaderData = {
|
|
10
|
+
words: Uint32Array
|
|
11
|
+
count: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Single GPU instanced mesh for all shader-cube faces in the world.
|
|
16
|
+
* Camera-relative positioning via u_cameraOrigin; no sceneOrigin tracking.
|
|
17
|
+
*/
|
|
18
|
+
export class GlobalBlockBuffer {
|
|
19
|
+
readonly mesh: THREE.Mesh<THREE.InstancedBufferGeometry, THREE.ShaderMaterial>
|
|
20
|
+
|
|
21
|
+
private capacityFaces: number
|
|
22
|
+
private w0: Uint32Array
|
|
23
|
+
private w1: Uint32Array
|
|
24
|
+
private w2: Uint32Array
|
|
25
|
+
private w3: Uint32Array
|
|
26
|
+
private readonly sectionSlots = new Map<string, { start: number, count: number }>()
|
|
27
|
+
private freeList: Array<{ start: number, count: number }> = []
|
|
28
|
+
private highWatermark = 0
|
|
29
|
+
private dirtyMin = Infinity
|
|
30
|
+
private dirtyMax = -1
|
|
31
|
+
|
|
32
|
+
constructor (
|
|
33
|
+
material: THREE.ShaderMaterial,
|
|
34
|
+
scene: THREE.Object3D,
|
|
35
|
+
) {
|
|
36
|
+
this.capacityFaces = INITIAL_CAPACITY_FACES
|
|
37
|
+
this.w0 = new Uint32Array(this.capacityFaces)
|
|
38
|
+
this.w1 = new Uint32Array(this.capacityFaces)
|
|
39
|
+
this.w2 = new Uint32Array(this.capacityFaces)
|
|
40
|
+
this.w3 = new Uint32Array(this.capacityFaces)
|
|
41
|
+
|
|
42
|
+
const geometry = new THREE.InstancedBufferGeometry()
|
|
43
|
+
const positions = new Float32Array(VERTICES_PER_FACE * 3)
|
|
44
|
+
geometry.setAttribute('position', new THREE.BufferAttribute(positions, 3))
|
|
45
|
+
|
|
46
|
+
const mkAttr = (arr: Uint32Array) => {
|
|
47
|
+
const attr = new THREE.InstancedBufferAttribute(arr, 1)
|
|
48
|
+
attr.setUsage(THREE.DynamicDrawUsage)
|
|
49
|
+
return attr
|
|
50
|
+
}
|
|
51
|
+
geometry.setAttribute('a_w0', mkAttr(this.w0))
|
|
52
|
+
geometry.setAttribute('a_w1', mkAttr(this.w1))
|
|
53
|
+
geometry.setAttribute('a_w2', mkAttr(this.w2))
|
|
54
|
+
geometry.setAttribute('a_w3', mkAttr(this.w3))
|
|
55
|
+
|
|
56
|
+
geometry.instanceCount = 0
|
|
57
|
+
|
|
58
|
+
this.mesh = new THREE.Mesh(geometry, material)
|
|
59
|
+
this.mesh.name = 'globalShaderCubes'
|
|
60
|
+
this.mesh.frustumCulled = false
|
|
61
|
+
this.mesh.matrixAutoUpdate = false
|
|
62
|
+
this.mesh.matrix.identity()
|
|
63
|
+
this.mesh.position.set(0, 0, 0)
|
|
64
|
+
scene.add(this.mesh)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
addSection (sectionKey: string, words: Uint32Array, faceCount: number): void {
|
|
68
|
+
if (faceCount <= 0) {
|
|
69
|
+
this.removeSection(sectionKey)
|
|
70
|
+
return
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (this.sectionSlots.has(sectionKey)) {
|
|
74
|
+
this.removeSection(sectionKey)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (faceCount > this.capacityFaces) {
|
|
78
|
+
this.growCapacity(faceCount)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let slot = this.takeFreeSlot(faceCount)
|
|
82
|
+
if (!slot) {
|
|
83
|
+
if (this.highWatermark + faceCount > this.capacityFaces) {
|
|
84
|
+
this.growCapacity(this.highWatermark + faceCount)
|
|
85
|
+
}
|
|
86
|
+
slot = { start: this.highWatermark, count: faceCount }
|
|
87
|
+
this.highWatermark += faceCount
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const stride = 4
|
|
91
|
+
for (let i = 0; i < faceCount; i++) {
|
|
92
|
+
const dst = slot.start + i
|
|
93
|
+
const src = i * stride
|
|
94
|
+
this.w0[dst] = words[src]!
|
|
95
|
+
this.w1[dst] = words[src + 1]!
|
|
96
|
+
this.w2[dst] = words[src + 2]!
|
|
97
|
+
this.w3[dst] = words[src + 3]!
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
this.sectionSlots.set(sectionKey, slot)
|
|
101
|
+
this.markDirty(slot.start, slot.start + faceCount - 1)
|
|
102
|
+
this.mesh.geometry.instanceCount = this.highWatermark
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
hasSection (sectionKey: string): boolean {
|
|
106
|
+
return this.sectionSlots.has(sectionKey)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** Copy live GPU words and remove the section (sci-fi reveal hide / restore). */
|
|
110
|
+
takeSectionData (sectionKey: string): GlobalBlockBufferShaderData | undefined {
|
|
111
|
+
const slot = this.sectionSlots.get(sectionKey)
|
|
112
|
+
if (!slot) return undefined
|
|
113
|
+
|
|
114
|
+
const stride = 4
|
|
115
|
+
const words = new Uint32Array(slot.count * stride)
|
|
116
|
+
for (let i = 0; i < slot.count; i++) {
|
|
117
|
+
const dst = slot.start + i
|
|
118
|
+
const src = i * stride
|
|
119
|
+
words[src] = this.w0[dst]!
|
|
120
|
+
words[src + 1] = this.w1[dst]!
|
|
121
|
+
words[src + 2] = this.w2[dst]!
|
|
122
|
+
words[src + 3] = this.w3[dst]!
|
|
123
|
+
}
|
|
124
|
+
this.removeSection(sectionKey)
|
|
125
|
+
return { words, count: slot.count }
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
removeSection (sectionKey: string): void {
|
|
129
|
+
const slot = this.sectionSlots.get(sectionKey)
|
|
130
|
+
if (!slot) return
|
|
131
|
+
|
|
132
|
+
for (let i = slot.start; i < slot.start + slot.count; i++) {
|
|
133
|
+
this.w0[i] = 0
|
|
134
|
+
this.w1[i] = 0
|
|
135
|
+
this.w2[i] = EMPTY_W2
|
|
136
|
+
this.w3[i] = 0
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.markDirty(slot.start, slot.start + slot.count - 1)
|
|
140
|
+
this.sectionSlots.delete(sectionKey)
|
|
141
|
+
this.insertFreeSlot(slot)
|
|
142
|
+
this.shrinkHighWatermark()
|
|
143
|
+
this.mesh.geometry.instanceCount = this.highWatermark
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
uploadDirtyRange (): void {
|
|
147
|
+
if (this.dirtyMin > this.dirtyMax) return
|
|
148
|
+
|
|
149
|
+
const offset = this.dirtyMin
|
|
150
|
+
const count = this.dirtyMax - this.dirtyMin + 1
|
|
151
|
+
const geometry = this.mesh.geometry
|
|
152
|
+
|
|
153
|
+
for (const name of ['a_w0', 'a_w1', 'a_w2', 'a_w3'] as const) {
|
|
154
|
+
const attr = geometry.getAttribute(name) as THREE.InstancedBufferAttribute
|
|
155
|
+
attr.updateRange.offset = offset
|
|
156
|
+
attr.updateRange.count = count
|
|
157
|
+
attr.needsUpdate = true
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
this.dirtyMin = Infinity
|
|
161
|
+
this.dirtyMax = -1
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
setCameraOrigin (x: number, y: number, z: number): void {
|
|
165
|
+
// Integer + fractional parts — see cubeBlockShader position math.
|
|
166
|
+
const ix = Math.floor(x)
|
|
167
|
+
const iy = Math.floor(y)
|
|
168
|
+
const iz = Math.floor(z)
|
|
169
|
+
const u = this.mesh.material.uniforms.u_cameraOrigin
|
|
170
|
+
if (u?.value?.set) {
|
|
171
|
+
u.value.set(ix, iy, iz)
|
|
172
|
+
}
|
|
173
|
+
const uf = this.mesh.material.uniforms.u_cameraOriginFrac
|
|
174
|
+
if (uf?.value?.set) {
|
|
175
|
+
uf.value.set(x - ix, y - iy, z - iz)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
reset (): void {
|
|
180
|
+
this.sectionSlots.clear()
|
|
181
|
+
this.freeList.length = 0
|
|
182
|
+
this.highWatermark = 0
|
|
183
|
+
this.dirtyMin = Infinity
|
|
184
|
+
this.dirtyMax = -1
|
|
185
|
+
this.w0.fill(0)
|
|
186
|
+
this.w1.fill(0)
|
|
187
|
+
this.w2.fill(EMPTY_W2)
|
|
188
|
+
this.w3.fill(0)
|
|
189
|
+
this.mesh.geometry.instanceCount = 0
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
dispose (): void {
|
|
193
|
+
this.mesh.parent?.remove(this.mesh)
|
|
194
|
+
this.mesh.geometry.dispose()
|
|
195
|
+
this.reset()
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
private markDirty (start: number, end: number): void {
|
|
199
|
+
if (start < this.dirtyMin) this.dirtyMin = start
|
|
200
|
+
if (end > this.dirtyMax) this.dirtyMax = end
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
private takeFreeSlot (count: number): { start: number, count: number } | undefined {
|
|
204
|
+
for (let i = 0; i < this.freeList.length; i++) {
|
|
205
|
+
const slot = this.freeList[i]!
|
|
206
|
+
if (slot.count >= count) {
|
|
207
|
+
this.freeList.splice(i, 1)
|
|
208
|
+
if (slot.count === count) return slot
|
|
209
|
+
const used = { start: slot.start, count }
|
|
210
|
+
this.insertFreeSlot({ start: slot.start + count, count: slot.count - count })
|
|
211
|
+
return used
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
return undefined
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private insertFreeSlot (slot: { start: number, count: number }): void {
|
|
218
|
+
this.freeList.push(slot)
|
|
219
|
+
this.freeList.sort((a, b) => a.start - b.start)
|
|
220
|
+
this.mergeFreeList()
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
private mergeFreeList (): void {
|
|
224
|
+
if (this.freeList.length < 2) return
|
|
225
|
+
const merged: Array<{ start: number, count: number }> = []
|
|
226
|
+
let cur = this.freeList[0]!
|
|
227
|
+
for (let i = 1; i < this.freeList.length; i++) {
|
|
228
|
+
const next = this.freeList[i]!
|
|
229
|
+
if (cur.start + cur.count === next.start) {
|
|
230
|
+
cur = { start: cur.start, count: cur.count + next.count }
|
|
231
|
+
} else {
|
|
232
|
+
merged.push(cur)
|
|
233
|
+
cur = next
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
merged.push(cur)
|
|
237
|
+
this.freeList = merged
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
private shrinkHighWatermark (): void {
|
|
241
|
+
while (this.highWatermark > 0) {
|
|
242
|
+
const tail = this.highWatermark - 1
|
|
243
|
+
const free = this.freeList.find(s => s.start <= tail && s.start + s.count > tail)
|
|
244
|
+
if (!free || free.start + free.count !== this.highWatermark) break
|
|
245
|
+
this.highWatermark = free.start
|
|
246
|
+
const idx = this.freeList.indexOf(free)
|
|
247
|
+
this.freeList.splice(idx, 1)
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
private growCapacity (minFaces: number): void {
|
|
252
|
+
let newCap = this.capacityFaces
|
|
253
|
+
while (newCap < minFaces) newCap *= 2
|
|
254
|
+
|
|
255
|
+
const nw0 = new Uint32Array(newCap)
|
|
256
|
+
const nw1 = new Uint32Array(newCap)
|
|
257
|
+
const nw2 = new Uint32Array(newCap)
|
|
258
|
+
const nw3 = new Uint32Array(newCap)
|
|
259
|
+
nw0.set(this.w0)
|
|
260
|
+
nw1.set(this.w1)
|
|
261
|
+
nw2.set(this.w2)
|
|
262
|
+
nw3.set(this.w3)
|
|
263
|
+
nw2.fill(EMPTY_W2, this.w0.length)
|
|
264
|
+
|
|
265
|
+
this.w0 = nw0
|
|
266
|
+
this.w1 = nw1
|
|
267
|
+
this.w2 = nw2
|
|
268
|
+
this.w3 = nw3
|
|
269
|
+
this.capacityFaces = newCap
|
|
270
|
+
|
|
271
|
+
const geometry = this.mesh.geometry
|
|
272
|
+
const mkAttr = (arr: Uint32Array, name: string) => {
|
|
273
|
+
const prev = geometry.getAttribute(name)
|
|
274
|
+
if (prev) {
|
|
275
|
+
geometry.deleteAttribute(name)
|
|
276
|
+
if ('dispose' in prev && typeof (prev as { dispose?: () => void }).dispose === 'function') {
|
|
277
|
+
(prev as { dispose: () => void }).dispose()
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
const attr = new THREE.InstancedBufferAttribute(arr, 1)
|
|
281
|
+
attr.setUsage(THREE.DynamicDrawUsage)
|
|
282
|
+
geometry.setAttribute(name, attr)
|
|
283
|
+
}
|
|
284
|
+
mkAttr(this.w0, 'a_w0')
|
|
285
|
+
mkAttr(this.w1, 'a_w1')
|
|
286
|
+
mkAttr(this.w2, 'a_w2')
|
|
287
|
+
mkAttr(this.w3, 'a_w3')
|
|
288
|
+
|
|
289
|
+
this.dirtyMin = 0
|
|
290
|
+
this.dirtyMax = this.highWatermark - 1
|
|
291
|
+
}
|
|
292
|
+
}
|
|
@@ -5,7 +5,7 @@ import type { FuturisticCameraId, FuturisticSceneId, MinecraftBlockGroupId } fro
|
|
|
5
5
|
/** Single source of truth for menu-background defaults (settings + runtime fallbacks). */
|
|
6
6
|
export const MENU_BACKGROUND_OPTION_DEFAULTS = {
|
|
7
7
|
mode: 'futuristic' as MenuBackgroundMode,
|
|
8
|
-
minecraftTextures: true,
|
|
8
|
+
minecraftTextures: true as boolean,
|
|
9
9
|
futuristicScene: 'light' as FuturisticSceneId,
|
|
10
10
|
futuristicCamera: 'dive' as FuturisticCameraId,
|
|
11
11
|
futuristicBlockGroup: 'stainedGlass' as MinecraftBlockGroupId,
|
|
@@ -26,6 +26,26 @@ export type RendererMesherPipeline = 'wasm' | 'legacy-js'
|
|
|
26
26
|
|
|
27
27
|
export type RendererGpuPreference = 'default' | 'high-performance' | 'low-power'
|
|
28
28
|
|
|
29
|
+
export type RendererShaderCubeDebugMode =
|
|
30
|
+
| 'off'
|
|
31
|
+
| 'holes'
|
|
32
|
+
| 'texIndex'
|
|
33
|
+
| 'faces'
|
|
34
|
+
| 'atlasAlpha'
|
|
35
|
+
|
|
36
|
+
const SHADER_CUBE_DEBUG_MODE_TO_VALUE: Record<RendererShaderCubeDebugMode, number> = {
|
|
37
|
+
off: 0,
|
|
38
|
+
holes: 1,
|
|
39
|
+
texIndex: 2,
|
|
40
|
+
faces: 3,
|
|
41
|
+
atlasAlpha: 4,
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Maps stored option → `inWorldRenderingConfig.shaderCubeDebugMode` (0–4). */
|
|
45
|
+
export function rendererShaderCubeDebugModeToValue(mode: RendererShaderCubeDebugMode): number {
|
|
46
|
+
return SHADER_CUBE_DEBUG_MODE_TO_VALUE[mode]
|
|
47
|
+
}
|
|
48
|
+
|
|
29
49
|
/** Maps stored `gpuPreference` to WebGL `powerPreference` (undefined = browser default). */
|
|
30
50
|
export function gpuPreferenceToWebGLPowerPreference(
|
|
31
51
|
preference: RendererGpuPreference
|
|
@@ -41,36 +61,37 @@ const MB = MENU_BACKGROUND_OPTION_DEFAULTS
|
|
|
41
61
|
export const RENDERER_DEFAULT_OPTIONS = {
|
|
42
62
|
rendererWorldPerformance: 'normal' as 'low-energy' | 'normal' | 'maximum',
|
|
43
63
|
rendererMeshersCountOverride: null as number | null,
|
|
44
|
-
starfieldRendering: true,
|
|
45
|
-
defaultSkybox: true,
|
|
64
|
+
starfieldRendering: true as boolean,
|
|
65
|
+
defaultSkybox: true as boolean,
|
|
46
66
|
menuBackgroundMode: MB.mode,
|
|
47
|
-
menuBackgroundMinecraftTextures: MB.minecraftTextures,
|
|
67
|
+
menuBackgroundMinecraftTextures: MB.minecraftTextures as boolean,
|
|
48
68
|
menuBackgroundFuturisticScene: MB.futuristicScene,
|
|
49
69
|
menuBackgroundFuturisticCamera: MB.futuristicCamera,
|
|
50
70
|
menuBackgroundFuturisticBlockGroup: MB.futuristicBlockGroup,
|
|
51
71
|
menuBackgroundFuturisticCameraSpeed: MB.futuristicCameraSpeedPercent,
|
|
52
72
|
menuBackgroundFuturisticBlockSpeed: MB.futuristicBlockSpeedPercent,
|
|
53
|
-
rendererFuturisticReveal: false,
|
|
54
|
-
rendererPerfDebugOverlay: false,
|
|
55
|
-
disableBlockEntityTextures: false,
|
|
73
|
+
rendererFuturisticReveal: false as boolean,
|
|
74
|
+
rendererPerfDebugOverlay: false as boolean,
|
|
75
|
+
disableBlockEntityTextures: false as boolean,
|
|
56
76
|
rendererMesher: 'wasm' as RendererMesherPipeline,
|
|
57
|
-
|
|
58
|
-
|
|
77
|
+
rendererShaderCubeDebugMode: 'off' as RendererShaderCubeDebugMode,
|
|
78
|
+
showChunkBorders: false as boolean,
|
|
79
|
+
renderEntities: true as boolean,
|
|
59
80
|
renderDebug: 'basic' as 'none' | 'basic' | 'advanced',
|
|
60
81
|
frameLimit: false as number | false,
|
|
61
82
|
backgroundRendering: '20fps' as 'full' | '20fps' | '5fps',
|
|
62
|
-
vanillaLook: false,
|
|
63
|
-
smoothLighting: true,
|
|
64
|
-
newVersionsLighting: false,
|
|
65
|
-
vrSupport: true,
|
|
66
|
-
vrPageGameRendering: false,
|
|
83
|
+
vanillaLook: false as boolean,
|
|
84
|
+
smoothLighting: true as boolean,
|
|
85
|
+
newVersionsLighting: false as boolean,
|
|
86
|
+
vrSupport: true as boolean,
|
|
87
|
+
vrPageGameRendering: false as boolean,
|
|
67
88
|
clipWorldBelowY: undefined as number | undefined,
|
|
68
89
|
highlightBlockColor: 'auto' as 'auto' | 'blue' | 'classic',
|
|
69
|
-
loadPlayerSkins: true,
|
|
70
|
-
renderEars: true,
|
|
71
|
-
showHand: true,
|
|
72
|
-
viewBobbing: true,
|
|
73
|
-
dayCycleAndLighting: true,
|
|
90
|
+
loadPlayerSkins: true as boolean,
|
|
91
|
+
renderEars: true as boolean,
|
|
92
|
+
showHand: true as boolean,
|
|
93
|
+
viewBobbing: true as boolean,
|
|
94
|
+
dayCycleAndLighting: true as boolean,
|
|
74
95
|
keepChunksDistance: 1,
|
|
75
96
|
gpuPreference: 'default' as RendererGpuPreference,
|
|
76
97
|
fov: 75
|
|
@@ -166,6 +187,17 @@ export const RENDERER_OPTIONS_META: Partial<Record<RendererDefaultOptionKey, Ren
|
|
|
166
187
|
tooltip: 'WASM is faster. Use JS if WASM is not working. Requires reload.',
|
|
167
188
|
requiresRestart: true
|
|
168
189
|
},
|
|
190
|
+
rendererShaderCubeDebugMode: {
|
|
191
|
+
text: 'Shader cube debug',
|
|
192
|
+
tooltip: 'Instanced cube path visualization (requires shader cubes enabled).',
|
|
193
|
+
possibleValues: [
|
|
194
|
+
['off', 'Off'],
|
|
195
|
+
['holes', 'Hole test (red)'],
|
|
196
|
+
['texIndex', 'Tile index colors'],
|
|
197
|
+
['faces', 'Face id colors'],
|
|
198
|
+
['atlasAlpha', 'Atlas alpha'],
|
|
199
|
+
],
|
|
200
|
+
},
|
|
169
201
|
showChunkBorders: {
|
|
170
202
|
text: 'Chunk borders'
|
|
171
203
|
},
|
|
@@ -301,7 +333,8 @@ export const RENDERER_RENDER_GUI_SECTIONS: ReadonlyArray<{
|
|
|
301
333
|
title: 'Renderer debug',
|
|
302
334
|
keys: [
|
|
303
335
|
'rendererFuturisticReveal',
|
|
304
|
-
'rendererPerfDebugOverlay'
|
|
336
|
+
'rendererPerfDebugOverlay',
|
|
337
|
+
'rendererShaderCubeDebugMode',
|
|
305
338
|
]
|
|
306
339
|
}
|
|
307
340
|
]
|
|
@@ -38,7 +38,11 @@ export type {
|
|
|
38
38
|
RendererDefaultOptionKey,
|
|
39
39
|
RendererGpuPreference,
|
|
40
40
|
RendererMesherPipeline,
|
|
41
|
+
RendererShaderCubeDebugMode,
|
|
41
42
|
RendererOptionMeta,
|
|
42
43
|
RendererStorageOptions
|
|
43
44
|
} from './defaultOptions'
|
|
44
|
-
export {
|
|
45
|
+
export {
|
|
46
|
+
gpuPreferenceToWebGLPowerPreference,
|
|
47
|
+
rendererShaderCubeDebugModeToValue
|
|
48
|
+
} from './defaultOptions'
|