minecraft-renderer 0.1.72 → 0.1.73

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 (62) 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 +249 -78
  6. package/dist/minecraft-renderer.js.meta.json +1 -1
  7. package/dist/threeWorker.js +1732 -1001
  8. package/package.json +3 -3
  9. package/src/graphicsBackend/rendererDefaultOptions.ts +2 -7
  10. package/src/graphicsBackend/rendererOptionsSync.ts +1 -1
  11. package/src/lib/bakeLegacyLight.ts +17 -0
  12. package/src/lib/blockEntityLightRegistry.test.ts +18 -0
  13. package/src/lib/blockEntityLightRegistry.ts +75 -0
  14. package/src/lib/blockEntityLighting.test.ts +30 -0
  15. package/src/lib/blockEntityLighting.ts +53 -0
  16. package/src/lib/worldrendererCommon.ts +14 -6
  17. package/src/mesher-shared/blockEntityMetadata.test.ts +33 -0
  18. package/src/mesher-shared/blockEntityMetadata.ts +19 -3
  19. package/src/mesher-shared/exportedGeometryTypes.ts +11 -0
  20. package/src/mesher-shared/models.ts +161 -92
  21. package/src/mesher-shared/shared.ts +15 -4
  22. package/src/mesher-shared/tests/liquidQuadInvariant.test.ts +40 -0
  23. package/src/mesher-shared/world.ts +12 -0
  24. package/src/mesher-shared/worldLighting.test.ts +54 -0
  25. package/src/playground/baseScene.ts +1 -1
  26. package/src/three/bannerRenderer.ts +10 -3
  27. package/src/three/chunkMeshManager.ts +663 -69
  28. package/src/three/cubeDrawSpans.ts +74 -0
  29. package/src/three/cubeMultiDraw.ts +119 -0
  30. package/src/three/documentRenderer.ts +0 -2
  31. package/src/three/entities.ts +5 -6
  32. package/src/three/entity/EntityMesh.ts +7 -5
  33. package/src/three/entity/gltfAnimationUtils.ts +5 -3
  34. package/src/three/globalBlockBuffer.ts +208 -12
  35. package/src/three/globalLegacyBuffer.ts +701 -0
  36. package/src/three/itemMesh.ts +5 -2
  37. package/src/three/legacySectionCull.ts +85 -0
  38. package/src/three/modules/sciFiWorldReveal.ts +347 -703
  39. package/src/three/modules/starfield.ts +3 -2
  40. package/src/three/sectionRaycastAabb.ts +25 -0
  41. package/src/three/shaders/cubeBlockShader.ts +80 -17
  42. package/src/three/shaders/legacyBlockShader.ts +292 -0
  43. package/src/three/skyboxRenderer.ts +1 -1
  44. package/src/three/tests/chunkMeshManagerLegacy.test.ts +286 -0
  45. package/src/three/tests/cubeDrawSpans.test.ts +73 -0
  46. package/src/three/tests/globalLegacyBuffer.test.ts +360 -0
  47. package/src/three/tests/legacySectionCull.test.ts +80 -0
  48. package/src/three/tests/signTextureCache.test.ts +83 -0
  49. package/src/three/threeJsMedia.ts +2 -2
  50. package/src/three/waypointSprite.ts +2 -2
  51. package/src/three/world/cursorBlock.ts +1 -0
  52. package/src/three/world/vr.ts +2 -2
  53. package/src/three/worldGeometryExport.ts +83 -26
  54. package/src/three/worldRendererThree.ts +94 -25
  55. package/src/wasm-mesher/bridge/render-from-wasm.ts +214 -72
  56. package/src/wasm-mesher/bridge/shaderCubeBridge.ts +18 -6
  57. package/src/wasm-mesher/runtime-build/wasm_mesher_bg.wasm +0 -0
  58. package/src/wasm-mesher/tests/sectionRaycastAabb.test.ts +20 -0
  59. package/src/wasm-mesher/tests/shaderCubeInstances.test.ts +67 -5
  60. package/src/wasm-mesher/worker/mesherWasm.ts +70 -14
  61. package/src/wasm-mesher/worker/mesherWasmLightDirty.test.ts +11 -0
  62. package/src/wasm-mesher/worker/mesherWasmLightDirty.ts +15 -0
@@ -38,7 +38,7 @@ class StarfieldMaterial extends THREE.ShaderMaterial {
38
38
 
39
39
  export class StarfieldModule implements RendererModuleController {
40
40
  private points?: THREE.Points
41
- private clock = new THREE.Clock()
41
+ private timer = new THREE.Timer()
42
42
  private enabled = false
43
43
  private currentTime?: number
44
44
 
@@ -75,8 +75,9 @@ export class StarfieldModule implements RendererModuleController {
75
75
  render?: (deltaTime: number) => void = (_deltaTime) => {
76
76
  if (!this.points) return
77
77
  this.points.position.set(0, 0, 0)
78
+ this.timer.update(performance.now())
78
79
  ; (this.points.material as StarfieldMaterial).uniforms.time.value =
79
- this.clock.getElapsedTime() * 0.2
80
+ this.timer.getElapsed() * 0.2
80
81
  }
81
82
 
82
83
  /**
@@ -95,6 +95,31 @@ export function isPointInsideAabb (
95
95
  return ox >= minX && ox <= maxX && oy >= minY && oy <= maxY && oz >= minZ && oz <= maxZ
96
96
  }
97
97
 
98
+ /** True if a `far`-bounded ray from (ox,oy,oz) dir (dx,dy,dz) crosses or starts inside
99
+ * the cube-section AABB centered at (cx,cy,cz) with the given half-extent. */
100
+ export function sectionAabbIntersectsRay (
101
+ cx: number,
102
+ cy: number,
103
+ cz: number,
104
+ ox: number,
105
+ oy: number,
106
+ oz: number,
107
+ dx: number,
108
+ dy: number,
109
+ dz: number,
110
+ far: number,
111
+ halfExtent: number,
112
+ ): boolean {
113
+ const minX = cx - halfExtent
114
+ const minY = cy - halfExtent
115
+ const minZ = cz - halfExtent
116
+ const maxX = cx + halfExtent
117
+ const maxY = cy + halfExtent
118
+ const maxZ = cz + halfExtent
119
+ if (isPointInsideAabb(ox, oy, oz, minX, minY, minZ, maxX, maxY, maxZ)) return true
120
+ return raycastAabb(ox, oy, oz, dx, dy, dz, minX, minY, minZ, maxX, maxY, maxZ, far) !== undefined
121
+ }
122
+
98
123
  /** Ray–AABB entry distance, or undefined. Ignores hits when origin is inside the box. */
99
124
  export function raycastAabb (
100
125
  ox: number,
@@ -1,5 +1,12 @@
1
1
  //@ts-nocheck
2
2
  import * as THREE from 'three'
3
+ import {
4
+ APPLY_LIGHTMAP_GLSL,
5
+ DEFAULT_LIGHTMAP_PARAMS,
6
+ type BlockLightmapParams,
7
+ } from '../../lib/blockEntityLighting'
8
+
9
+ export type { BlockLightmapParams }
3
10
 
4
11
  // Face order: UP=0, DOWN=1, EAST=2, WEST=3, SOUTH=4, NORTH=5
5
12
  // matches WASM mesher face order (mesher.rs FACE_NAMES)
@@ -14,17 +21,20 @@ layout(location = 2) in uint a_w2;
14
21
  layout(location = 3) in uint a_w3;
15
22
 
16
23
  // World camera position split for stable float32 subtraction (see relativePos below).
17
- uniform vec3 u_cameraOrigin;
24
+ uniform ivec3 u_sectionOriginRel;
25
+ uniform vec3 u_originDelta;
18
26
  uniform vec3 u_cameraOriginFrac;
27
+ uniform float u_skyLevel;
19
28
 
20
- out float v_light;
29
+ out float v_blockLight;
30
+ out float v_skyLight;
21
31
  out float v_ao;
22
32
  out vec2 v_uv;
23
33
  flat out int v_texIndex;
24
34
  flat out int v_tintIndex;
25
35
  flat out int v_faceId;
26
36
 
27
- // Logarithmic depth buffer support: Three.js injects USE_LOGDEPTHBUF when the
37
+ // Logarithmic depth buffer support: Three.js injects USE_LOGARITHMIC_DEPTH_BUFFER when the
28
38
  // renderer has logarithmicDepthBuffer: true. Standard Three.js shader chunks
29
39
  // rewrite gl_FragDepth via these varyings — if we don't, our linear gl_FragCoord.z
30
40
  // fails depth test vs sibling meshes that DO write log depth (we'd be invisible).
@@ -33,7 +43,7 @@ flat out int v_faceId;
33
43
  // issue where vIsPerspective lands on 0.9999… on some pixels and silently falls
34
44
  // back to linear gl_FragCoord.z, producing a white-noise z-fight pattern against
35
45
  // neighbouring meshes.
36
- #ifdef USE_LOGDEPTHBUF
46
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
37
47
  out float vFragDepth;
38
48
  #endif
39
49
 
@@ -125,9 +135,12 @@ void main() {
125
135
  uint aoLevel = (a_w0 >> uint(23 + vi * 2)) & 0x3u;
126
136
  v_ao = (float(aoLevel) + 1.0) / 4.0;
127
137
 
128
- // --- word1: combined smooth light (8 bits per corner) ---
138
+ // --- word1: sky (high nibble) + block (low nibble) light per corner ---
129
139
  uint lightRaw = (a_w1 >> uint(vi * 8)) & 0xFFu;
130
- v_light = float(lightRaw) / 255.0;
140
+ uint sky4 = (lightRaw >> 4u) & 0xFu;
141
+ uint block4 = lightRaw & 0xFu;
142
+ v_skyLight = float(sky4) / 15.0;
143
+ v_blockLight = float(block4) / 15.0;
131
144
 
132
145
  // --- word2: texture index ---
133
146
  v_texIndex = int(a_w2 & 0xFFFu);
@@ -152,15 +165,17 @@ void main() {
152
165
  int sX = int((a_w3 & 0xFFFFu) | (((a_w2 >> 19u) & 0x3Fu) << 16u)) - 2097152;
153
166
  int sZ = int(((a_w3 >> 16u) & 0xFFFFu) | (((a_w2 >> 25u) & 0x3Fu) << 16u)) - 2097152;
154
167
  int sY = int((a_w2 >> 13u) & 0x1Fu) - 4;
155
- vec3 sectionBase = vec3(float(sX * 16), float(sY * 16), float(sZ * 16));
168
+ int sXr = sX - u_sectionOriginRel.x;
169
+ int sYr = sY - u_sectionOriginRel.y;
170
+ int sZr = sZ - u_sectionOriginRel.z;
171
+ vec3 sectionBase = vec3(float(sXr * 16), float(sYr * 16), float(sZr * 16));
156
172
  vec3 facePos = BASE[faceId] + u * DU[faceId] + v * DV[faceId];
157
173
  vec3 blockLocal = vec3(float(lx), float(ly), float(lz));
158
- // (sectionBase - u_cameraOrigin) is exact in float32; add small terms after.
159
- vec3 relativePos = (sectionBase - u_cameraOrigin) + facePos + blockLocal - u_cameraOriginFrac;
174
+ vec3 relativePos = sectionBase + u_originDelta + facePos + blockLocal - u_cameraOriginFrac;
160
175
  vec4 mvPosition = modelViewMatrix * vec4(relativePos, 1.0);
161
176
  gl_Position = projectionMatrix * mvPosition;
162
177
 
163
- #ifdef USE_LOGDEPTHBUF
178
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
164
179
  // Mirrors three.js logdepthbuf_vertex chunk (EXT path: fragment writes gl_FragDepth).
165
180
  vFragDepth = 1.0 + gl_Position.w;
166
181
  #endif
@@ -180,15 +195,20 @@ uniform sampler2D u_atlas;
180
195
  uniform sampler2D u_tintPalette;
181
196
  /** 0=normal 1=holes 2=tileIndex 3=faceId 4=atlasAlpha */
182
197
  uniform float u_debugMode;
198
+ uniform float u_skyLevel;
199
+ uniform float u_lightCurve;
200
+ uniform float u_minBrightness;
201
+ uniform float u_lightGamma;
183
202
 
184
- in float v_light;
203
+ in float v_blockLight;
204
+ in float v_skyLight;
185
205
  in float v_ao;
186
206
  in vec2 v_uv;
187
207
  flat in int v_texIndex;
188
208
  flat in int v_tintIndex;
189
209
  flat in int v_faceId;
190
210
 
191
- #ifdef USE_LOGDEPTHBUF
211
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
192
212
  uniform float logDepthBufFC;
193
213
  in float vFragDepth;
194
214
  #endif
@@ -207,7 +227,7 @@ uniform float fogFar;
207
227
  out vec4 FragColor;
208
228
 
209
229
  void writeLogDepth() {
210
- #ifdef USE_LOGDEPTHBUF
230
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
211
231
  // Camera is always perspective; skip the vIsPerspective branch from three.js
212
232
  // standard chunks to avoid float-precision z-fight against neighbouring meshes.
213
233
  gl_FragDepth = log2(vFragDepth) * logDepthBufFC * 0.5;
@@ -226,6 +246,8 @@ void applyFog() {
226
246
  #endif
227
247
  }
228
248
 
249
+ ${APPLY_LIGHTMAP_GLSL}
250
+
229
251
  void main() {
230
252
  // Atlas sample (pixelated, no filtering)
231
253
  ivec2 atlasSize = textureSize(u_atlas, 0);
@@ -270,9 +292,9 @@ void main() {
270
292
  // Tint from palette (256x1 RGBA texture, index 0 = white [1,1,1])
271
293
  vec3 tint = texelFetch(u_tintPalette, ivec2(v_tintIndex, 0), 0).rgb;
272
294
 
273
- // Combined light * AO, identity brightness curve (no mcBrightness) to match the
274
- // legacy CPU mesher output 1:1.
275
- float brightness = v_light * v_ao;
295
+ float L = max(v_blockLight, min(v_skyLight, u_skyLevel));
296
+ float Lm = applyLightmap(L);
297
+ float brightness = Lm * v_ao;
276
298
 
277
299
  // Opaque full cubes: always alpha 1 (legacy uses cutout material; avoids seeing blocks behind)
278
300
  FragColor = vec4(baseColor.rgb * tint * brightness, 1.0);
@@ -294,7 +316,12 @@ export function createCubeBlockMaterial(): THREE.ShaderMaterial {
294
316
  u_atlas: { value: null },
295
317
  u_tintPalette: { value: null },
296
318
  u_debugMode: { value: 0 },
297
- u_cameraOrigin: { value: new THREE.Vector3() },
319
+ u_skyLevel: { value: 1.0 },
320
+ u_lightCurve: { value: DEFAULT_LIGHTMAP_PARAMS.curve },
321
+ u_minBrightness: { value: DEFAULT_LIGHTMAP_PARAMS.minBrightness },
322
+ u_lightGamma: { value: DEFAULT_LIGHTMAP_PARAMS.gamma },
323
+ u_sectionOriginRel: { value: new THREE.Vector3(0, 0, 0) },
324
+ u_originDelta: { value: new THREE.Vector3() },
298
325
  u_cameraOriginFrac: { value: new THREE.Vector3() },
299
326
  },
300
327
  ]),
@@ -312,8 +339,44 @@ export function createCubeBlockMaterial(): THREE.ShaderMaterial {
312
339
  }
313
340
 
314
341
  // Three geometry constants: 6 vertices per face (2 triangles, un-indexed)
342
+ export function setCubeSkyLevel (material: THREE.ShaderMaterial, value: number): void {
343
+ const u = material.uniforms.u_skyLevel
344
+ if (u) u.value = value
345
+ }
346
+
347
+ export function setCubeLightmapParams (
348
+ material: THREE.ShaderMaterial,
349
+ params: BlockLightmapParams,
350
+ ): void {
351
+ if (params.curve !== undefined) {
352
+ const u = material.uniforms.u_lightCurve
353
+ if (u) u.value = params.curve
354
+ }
355
+ if (params.minBrightness !== undefined) {
356
+ const u = material.uniforms.u_minBrightness
357
+ if (u) u.value = params.minBrightness
358
+ }
359
+ if (params.gamma !== undefined) {
360
+ const u = material.uniforms.u_lightGamma
361
+ if (u) u.value = params.gamma
362
+ }
363
+ }
364
+
315
365
  export const VERTICES_PER_FACE = 6
316
366
 
367
+ /** Section index units for render origin R (R is always a multiple of 16). */
368
+ export function computeSectionOriginRel (renderOrigin: { x: number, y: number, z: number }): {
369
+ x: number
370
+ y: number
371
+ z: number
372
+ } {
373
+ return {
374
+ x: Math.round(renderOrigin.x / 16),
375
+ y: Math.round(renderOrigin.y / 16),
376
+ z: Math.round(renderOrigin.z / 16),
377
+ }
378
+ }
379
+
317
380
  // Word layout constants (for encoding/decoding instances)
318
381
  export const WORD0 = {
319
382
  LX_BITS: 4,
@@ -0,0 +1,292 @@
1
+ //@ts-nocheck
2
+ import * as THREE from 'three'
3
+ import {
4
+ APPLY_LIGHTMAP_GLSL,
5
+ DEFAULT_LIGHTMAP_PARAMS,
6
+ type BlockLightmapParams,
7
+ } from '../../lib/blockEntityLighting'
8
+
9
+ export type RenderOrigin = { x: number, y: number, z: number }
10
+
11
+ export function computeCameraRelativeUniforms (
12
+ renderOrigin: RenderOrigin,
13
+ x: number,
14
+ y: number,
15
+ z: number,
16
+ ): { originDelta: RenderOrigin, cameraOriginFrac: RenderOrigin } {
17
+ const ix = Math.floor(x)
18
+ const iy = Math.floor(y)
19
+ const iz = Math.floor(z)
20
+ return {
21
+ originDelta: {
22
+ x: renderOrigin.x - ix,
23
+ y: renderOrigin.y - iy,
24
+ z: renderOrigin.z - iz,
25
+ },
26
+ cameraOriginFrac: {
27
+ x: x - ix,
28
+ y: y - iy,
29
+ z: z - iz,
30
+ },
31
+ }
32
+ }
33
+
34
+ const vertexShader = /* glsl */ `
35
+ precision highp float;
36
+
37
+ uniform vec3 u_originDelta;
38
+ uniform vec3 u_cameraOriginFrac;
39
+
40
+ in float a_skyLight;
41
+ in float a_blockLight;
42
+
43
+ // position, uv, color: declared by Three.js shader chunks (vertexColors → USE_COLOR).
44
+ out vec3 vColor;
45
+ out vec2 v_uv;
46
+ out float v_skyLight;
47
+ out float v_blockLight;
48
+
49
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
50
+ out float vFragDepth;
51
+ #endif
52
+
53
+ #ifdef USE_FOG
54
+ out float vFogDepth;
55
+ #endif
56
+
57
+ void main() {
58
+ vec3 relativePos = modelMatrix[3].xyz + u_originDelta + position - u_cameraOriginFrac;
59
+ vec4 mvPosition = viewMatrix * vec4(relativePos, 1.0);
60
+ gl_Position = projectionMatrix * mvPosition;
61
+
62
+ vColor = color;
63
+ v_uv = uv;
64
+ v_skyLight = a_skyLight;
65
+ v_blockLight = a_blockLight;
66
+
67
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
68
+ vFragDepth = 1.0 + gl_Position.w;
69
+ #endif
70
+
71
+ #ifdef USE_FOG
72
+ vFogDepth = -mvPosition.z;
73
+ #endif
74
+ }
75
+ `
76
+
77
+ const fragmentShader = /* glsl */ `
78
+ precision highp float;
79
+
80
+ uniform sampler2D u_atlas;
81
+ uniform float u_skyLevel;
82
+ uniform float u_lightCurve;
83
+ uniform float u_minBrightness;
84
+ uniform float u_lightGamma;
85
+
86
+ in vec3 vColor;
87
+ in vec2 v_uv;
88
+ in float v_skyLight;
89
+ in float v_blockLight;
90
+
91
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
92
+ uniform float logDepthBufFC;
93
+ in float vFragDepth;
94
+ #endif
95
+
96
+ #ifdef USE_FOG
97
+ uniform vec3 fogColor;
98
+ in float vFogDepth;
99
+ #ifdef FOG_EXP2
100
+ uniform float fogDensity;
101
+ #else
102
+ uniform float fogNear;
103
+ uniform float fogFar;
104
+ #endif
105
+ #endif
106
+
107
+ out vec4 FragColor;
108
+
109
+ void writeLogDepth() {
110
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
111
+ gl_FragDepth = log2(vFragDepth) * logDepthBufFC * 0.5;
112
+ #endif
113
+ }
114
+
115
+ void applyFog() {
116
+ #ifdef USE_FOG
117
+ #ifdef FOG_EXP2
118
+ float fogFactor = 1.0 - exp(-fogDensity * fogDensity * vFogDepth * vFogDepth);
119
+ #else
120
+ float fogFactor = smoothstep(fogNear, fogFar, vFogDepth);
121
+ #endif
122
+ FragColor.rgb = mix(FragColor.rgb, fogColor, fogFactor);
123
+ #endif
124
+ }
125
+
126
+ ${APPLY_LIGHTMAP_GLSL}
127
+
128
+ void main() {
129
+ vec4 texColor = texture(u_atlas, v_uv);
130
+ float L = max(v_blockLight, min(v_skyLight, u_skyLevel));
131
+ float Lm = applyLightmap(L);
132
+ vec3 rgb = texColor.rgb * vColor * Lm;
133
+ float alpha = texColor.a;
134
+
135
+ if (alpha < 0.1) {
136
+ discard;
137
+ }
138
+
139
+ FragColor = vec4(rgb, alpha);
140
+ applyFog();
141
+ writeLogDepth();
142
+ }
143
+ `
144
+
145
+ const globalVertexShader = /* glsl */ `
146
+ precision highp float;
147
+
148
+ uniform vec3 u_originDelta;
149
+ uniform vec3 u_cameraOriginFrac;
150
+
151
+ in vec3 a_origin;
152
+ in float a_skyLight;
153
+ in float a_blockLight;
154
+
155
+ // position, uv, color: declared by Three.js shader chunks (vertexColors → USE_COLOR).
156
+ out vec3 vColor;
157
+ out vec2 v_uv;
158
+ out float v_skyLight;
159
+ out float v_blockLight;
160
+
161
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
162
+ out float vFragDepth;
163
+ #endif
164
+
165
+ #ifdef USE_FOG
166
+ out float vFogDepth;
167
+ #endif
168
+
169
+ void main() {
170
+ vec3 relativePos = a_origin + u_originDelta + position - u_cameraOriginFrac;
171
+ vec4 mvPosition = viewMatrix * vec4(relativePos, 1.0);
172
+ gl_Position = projectionMatrix * mvPosition;
173
+
174
+ vColor = color;
175
+ v_uv = uv;
176
+ v_skyLight = a_skyLight;
177
+ v_blockLight = a_blockLight;
178
+
179
+ #ifdef USE_LOGARITHMIC_DEPTH_BUFFER
180
+ vFragDepth = 1.0 + gl_Position.w;
181
+ #endif
182
+
183
+ #ifdef USE_FOG
184
+ vFogDepth = -mvPosition.z;
185
+ #endif
186
+ }
187
+ `
188
+
189
+ const legacyUniforms = {
190
+ u_atlas: { value: null },
191
+ u_originDelta: { value: new THREE.Vector3() },
192
+ u_cameraOriginFrac: { value: new THREE.Vector3() },
193
+ u_skyLevel: { value: 1.0 },
194
+ u_lightCurve: { value: DEFAULT_LIGHTMAP_PARAMS.curve },
195
+ u_minBrightness: { value: DEFAULT_LIGHTMAP_PARAMS.minBrightness },
196
+ u_lightGamma: { value: DEFAULT_LIGHTMAP_PARAMS.gamma },
197
+ }
198
+
199
+ export function createLegacyBlockMaterial (): THREE.ShaderMaterial {
200
+ return new THREE.ShaderMaterial({
201
+ vertexShader,
202
+ fragmentShader,
203
+ uniforms: THREE.UniformsUtils.merge([
204
+ THREE.UniformsLib.fog,
205
+ legacyUniforms,
206
+ ]),
207
+ transparent: true,
208
+ depthWrite: true,
209
+ depthTest: true,
210
+ vertexColors: true,
211
+ glslVersion: THREE.GLSL3,
212
+ fog: true,
213
+ })
214
+ }
215
+
216
+ /** Global opaque legacy buffer — per-vertex section origin via a_origin. */
217
+ export function createGlobalLegacyBlockMaterial (): THREE.ShaderMaterial {
218
+ return new THREE.ShaderMaterial({
219
+ vertexShader: globalVertexShader,
220
+ fragmentShader,
221
+ uniforms: THREE.UniformsUtils.merge([
222
+ THREE.UniformsLib.fog,
223
+ legacyUniforms,
224
+ ]),
225
+ transparent: false,
226
+ depthWrite: true,
227
+ depthTest: true,
228
+ vertexColors: true,
229
+ glslVersion: THREE.GLSL3,
230
+ fog: true,
231
+ })
232
+ }
233
+
234
+ /** Global transparent blend buffer — same shaders as opaque global, blend material flags. */
235
+ export function createGlobalLegacyBlendMaterial (): THREE.ShaderMaterial {
236
+ return new THREE.ShaderMaterial({
237
+ vertexShader: globalVertexShader,
238
+ fragmentShader,
239
+ uniforms: THREE.UniformsUtils.merge([
240
+ THREE.UniformsLib.fog,
241
+ legacyUniforms,
242
+ ]),
243
+ transparent: true,
244
+ depthWrite: true,
245
+ depthTest: true,
246
+ vertexColors: true,
247
+ glslVersion: THREE.GLSL3,
248
+ fog: true,
249
+ })
250
+ }
251
+
252
+ /** Render-origin + fractional camera split — matches GlobalBlockBuffer.setCameraOrigin. */
253
+ export function setLegacyCameraOrigin (
254
+ material: THREE.ShaderMaterial,
255
+ renderOrigin: RenderOrigin,
256
+ x: number,
257
+ y: number,
258
+ z: number,
259
+ ): void {
260
+ const { originDelta, cameraOriginFrac } = computeCameraRelativeUniforms(renderOrigin, x, y, z)
261
+ const u = material.uniforms.u_originDelta
262
+ if (u?.value?.set) {
263
+ u.value.set(originDelta.x, originDelta.y, originDelta.z)
264
+ }
265
+ const uf = material.uniforms.u_cameraOriginFrac
266
+ if (uf?.value?.set) {
267
+ uf.value.set(cameraOriginFrac.x, cameraOriginFrac.y, cameraOriginFrac.z)
268
+ }
269
+ }
270
+
271
+ export function setLegacySkyLevel (material: THREE.ShaderMaterial, value: number): void {
272
+ const u = material.uniforms.u_skyLevel
273
+ if (u) u.value = value
274
+ }
275
+
276
+ export function setLegacyLightmapParams (
277
+ material: THREE.ShaderMaterial,
278
+ params: BlockLightmapParams,
279
+ ): void {
280
+ if (params.curve !== undefined) {
281
+ const u = material.uniforms.u_lightCurve
282
+ if (u) u.value = params.curve
283
+ }
284
+ if (params.minBrightness !== undefined) {
285
+ const u = material.uniforms.u_minBrightness
286
+ if (u) u.value = params.minBrightness
287
+ }
288
+ if (params.gamma !== undefined) {
289
+ const u = material.uniforms.u_lightGamma
290
+ if (u) u.value = params.gamma
291
+ }
292
+ }
@@ -67,7 +67,7 @@ export class SkyboxRenderer {
67
67
  imageUrl,
68
68
  (texture) => {
69
69
  texture.mapping = THREE.EquirectangularReflectionMapping
70
- texture.encoding = THREE.sRGBEncoding
70
+ texture.colorSpace = THREE.SRGBColorSpace
71
71
  // Keep pixelated look
72
72
  texture.minFilter = THREE.NearestFilter
73
73
  texture.magFilter = THREE.NearestFilter