spoint 0.1.677 → 0.1.679

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.
@@ -85,8 +85,8 @@ export default {
85
85
  fillIntensity: 0.4,
86
86
  fillPosition: [-20, 30, -10],
87
87
  shadowMapSize: 1024,
88
- shadowBias: 0.0038,
89
- shadowNormalBias: 0.6,
88
+ shadowBias: -0.0005,
89
+ shadowNormalBias: 0.05,
90
90
  // shadowRadius/shadowBlurSamples are read only by three.js's VSM blur pass
91
91
  // (WebGLShadowMap.js postProcessShadowMap, gated on shadow.type===VSMShadowMap);
92
92
  // client/core/SceneSetup.js hardcodes renderer.shadowMap.type=PCFShadowMap, so
package/client/app.js CHANGED
@@ -258,7 +258,7 @@ try {
258
258
  _showBootFailureOverlay('WebGL2 is required', 'This 3D world needs a browser with WebGL2 support. Please update your browser, enable hardware acceleration, or try a different device.\n\n' + ((err && (err.stack || err.message)) || String(err)))
259
259
  throw err
260
260
  }
261
- const { ambient, studio, sun } = setupLights(scene), { gltfLoader } = createLoaders(renderer)
261
+ const { ambient, studio, sun } = setupLights(scene), { gltfLoader, ktx2Loader } = createLoaders(renderer)
262
262
  // Kick the anim-lib fetch now (idempotent, cached) so it overlaps the world import + cold worker boot instead of serializing behind them.
263
263
  preloadAnimationLibrary(gltfLoader)
264
264
  if (typeof window !== 'undefined') {
@@ -680,7 +680,7 @@ cullingHub.register('occlusionQueryBudget', () => occlusionQueryBudget.getStats(
680
680
  // client/core/WebGPUCullingHubIntegration.js's header for the full scope note); call
681
681
  // window.__runWebgpuComputeCull() from a dev console / future opt-in tier to populate it.
682
682
  window.__runWebgpuComputeCull = () => import('./core/WebGPUCullingHubIntegration.js').then(m => m.runAndRegister(cullingHub, { scene, camera }))
683
- const pm = createPlayerManager(scene, gltfLoader, cam, null, sceneGraph, modelPool)
683
+ const pm = createPlayerManager(scene, gltfLoader, cam, ktx2Loader, sceneGraph, modelPool)
684
684
  // Player LOD: real distance-tier classification (FULL/REDUCED/DOT) for the remote-player crowd -- see
685
685
  // core/PlayerLOD.js. tickPlayerAnimators (below) applies the verdict to gate VRM anim/feature updates;
686
686
  // the crowd-dot InstancedMesh2 renders everyone beyond the REDUCED ring at near-zero cost. Instantiated
@@ -2423,6 +2423,15 @@ function startInputLoop() {
2423
2423
  }, 1000/60)
2424
2424
  }
2425
2425
  renderer.domElement.addEventListener('click', ()=>{ if (inputConfig.pointerLock&&!document.pointerLockElement) renderer.domElement.requestPointerLock() })
2426
+ // requestPointerLock() is a trusted-gesture-gated browser API that can silently reject (denied
2427
+ // engagement heuristic, automation-driven click, embedded/iframe context) with no visible error --
2428
+ // the click-prompt overlay then never dismisses and gameplay looks permanently blocked even though
2429
+ // the scene itself is live. Any WASD/movement keydown is unambiguous "I am playing" intent, so treat
2430
+ // it as an implicit prompt-dismissal fallback independent of whether the lock request ever resolved.
2431
+ document.addEventListener('keydown', e => {
2432
+ if (clickPrompt.style.display==='none' || !inputConfig.pointerLock) return
2433
+ if (['KeyW','KeyA','KeyS','KeyD','Space'].includes(e.code)) clickPrompt.style.display='none'
2434
+ })
2426
2435
  document.addEventListener('pointerlockchange', ()=>{
2427
2436
  const locked=document.pointerLockElement===renderer.domElement
2428
2437
  clickPrompt.style.display=locked?'none':(inputConfig.pointerLock?'block':'none')
@@ -184,7 +184,7 @@ export async function probeOffscreenCanvasWorkerRendering() {
184
184
  function _applyCommonRendererSetup(renderer, isMobile) {
185
185
  renderer.setSize(window.innerWidth, window.innerHeight)
186
186
  renderer.setPixelRatio(isMobile ? Math.min(window.devicePixelRatio * 0.5, 1) : Math.min(window.devicePixelRatio, 2))
187
- renderer.shadowMap.enabled = true
187
+ renderer.shadowMap.enabled = false
188
188
  renderer.shadowMap.type = THREE.PCFShadowMap // not PCFSoft: this build is fragment-bound, soft kernel too costly
189
189
  // Temporal throttle: shadow map (and every InstancedMesh2 BVH cull three.js runs against the shadow
190
190
  // camera during that pass, incl. all vegetation) only re-renders when app.js's animate() loop flips
@@ -297,7 +297,7 @@ export function setupLights(scene) {
297
297
  studio.position.set(-20, 30, -10); studio.castShadow = false; scene.add(studio)
298
298
  // studio keeps matrixAutoUpdate=true (default): applySceneConfig's fillPosition can move it post-boot
299
299
  const sun = new THREE.DirectionalLight(0xffffff, 1.5)
300
- sun.position.set(21, 50, 20); sun.castShadow = true
300
+ sun.position.set(21, 50, 20); sun.castShadow = false
301
301
  sun.shadow.mapSize.set(1024, 1024)
302
302
  sun.shadow.bias = -0.0005
303
303
  sun.shadow.normalBias = 0.05
@@ -203,9 +203,9 @@ export async function createVegetation(opts = {}) {
203
203
  const recByName = new Map(meshes.map(r => [r.name, r]))
204
204
 
205
205
  // Must apply mip/alpha setup AFTER every impostor bake (leafMat renders into a non-multisampled RT during the bake, where A2C is undefined-ish).
206
- // (1) anisotropy on bark/leaf maps (ez-tree decodes at anisotropy=1, smearing to mud at grazing angles). (2) alphaToCoverage on the leaf cutout when the renderer has real MSAA; alphaTest stays 0.5 for the no-MSAA shadow pass.
206
+ // Anisotropy pinned to 1 (Performance-Mode reference: no anisotropic softening at distance); alphaToCoverage on the leaf cutout when the renderer has real MSAA, alphaTest stays 0.5 for the no-MSAA shadow pass.
207
207
  try {
208
- const maxAniso = Math.min(8, renderer.capabilities.getMaxAnisotropy() || 1)
208
+ const maxAniso = 1
209
209
  const hasMSAA = !!(renderer.getContext() && renderer.getContext().getContextAttributes && renderer.getContext().getContextAttributes().antialias)
210
210
  for (const r of meshes) {
211
211
  for (const m of [r.branch && r.branch.material, r.leaf && r.leaf.material]) {
@@ -26,7 +26,7 @@ const DEFAULTS = {
26
26
  sfxVolume: 1,
27
27
  musicVolume: 1,
28
28
  qualityPreset: 'Medium',
29
- dprAuto: true,
29
+ dprAuto: false,
30
30
  }
31
31
 
32
32
  function loadSaved() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoint",
3
- "version": "0.1.677",
3
+ "version": "0.1.679",
4
4
  "description": "Physics and netcode SDK for multiplayer game servers",
5
5
  "type": "module",
6
6
  "workspaces": [