spoint 0.1.31 → 0.1.33

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/SKILL.md CHANGED
@@ -762,6 +762,10 @@ App reloads never happen mid-tick. Queue drains at end of each tick. After each
762
762
 
763
763
  ## Client Rendering
764
764
 
765
+ ### GLB Shader Stall Prevention
766
+
767
+ The engine automatically calls `renderer.compileAsync(object, camera)` immediately after adding any GLB or procedural mesh to the scene. This prevents first-draw GPU stall for dynamically loaded entities (environment models, physics crates, power crates, smart objects, drag-and-drop models). No action is needed from app code — warmup is handled in `loadEntityModel` and `loadQueuedModels`. VRM players use a separate one-time warmup path.
768
+
765
769
  ### render(ctx) Return Value
766
770
 
767
771
  ```js
package/client/app.js CHANGED
@@ -752,7 +752,10 @@ async function createPlayerVRM(id) {
752
752
  }
753
753
  if (!_vrmWarmupDone) {
754
754
  _vrmWarmupDone = true
755
- requestAnimationFrame(() => { renderer.compile(scene, camera); console.log('[shader] vrm warmup compile done') })
755
+ renderer.compileAsync(scene, camera).then(() => console.log('[shader] vrm warmup compileAsync done')).catch(() => {
756
+ renderer.compile(scene, camera)
757
+ console.log('[shader] vrm warmup compile done (fallback)')
758
+ })
756
759
  }
757
760
  } catch (e) { console.error('[vrm]', id, e.message) }
758
761
  return group
@@ -926,6 +929,7 @@ function loadEntityModel(entityId, entityState) {
926
929
  const ep = entityState.position; group.position.set(ep[0], ep[1], ep[2])
927
930
  const er = entityState.rotation; if (er) group.quaternion.set(er[0], er[1], er[2], er[3])
928
931
  scene.add(group)
932
+ renderer.compileAsync(group, camera).catch(() => renderer.compile(group, camera))
929
933
  entityMeshes.set(entityId, group)
930
934
  pendingLoads.delete(entityId)
931
935
  if (!environmentLoaded) { environmentLoaded = true; checkAllLoaded() }
@@ -948,6 +952,7 @@ function loadEntityModel(entityId, entityState) {
948
952
  })
949
953
  model.updateMatrixWorld(true)
950
954
  scene.add(model)
955
+ renderer.compileAsync(model, camera).catch(() => renderer.compile(model, camera))
951
956
  entityMeshes.set(entityId, model)
952
957
  cam.setEnvironment(colliders)
953
958
  scene.remove(ground)
@@ -1073,13 +1078,18 @@ let lastHealth = 100
1073
1078
  let _shaderWarmupDone = false
1074
1079
  let _vrmWarmupDone = false
1075
1080
 
1076
- function warmupShaders() {
1081
+ async function warmupShaders() {
1077
1082
  if (_shaderWarmupDone) return
1078
1083
  _shaderWarmupDone = true
1079
1084
  const ext = renderer.extensions.get('KHR_parallel_shader_compile')
1080
1085
  if (ext) console.log('[shader] KHR_parallel_shader_compile active')
1081
- renderer.compile(scene, camera)
1082
- console.log('[shader] warmup compile done')
1086
+ try {
1087
+ await renderer.compileAsync(scene, camera)
1088
+ console.log('[shader] warmup compileAsync done')
1089
+ } catch {
1090
+ renderer.compile(scene, camera)
1091
+ console.log('[shader] warmup compile done (fallback)')
1092
+ }
1083
1093
  }
1084
1094
 
1085
1095
  function checkAllLoaded() {
@@ -1089,7 +1099,7 @@ function checkAllLoaded() {
1089
1099
  if (!firstSnapshotReceived) return
1090
1100
  loadingMgr.setStage('INIT')
1091
1101
  loadingMgr.complete()
1092
- loadingScreen.hide().then(() => requestAnimationFrame(warmupShaders)).catch(() => requestAnimationFrame(warmupShaders))
1102
+ loadingScreen.hide().then(() => warmupShaders()).catch(() => warmupShaders())
1093
1103
  loadingScreenHidden = true
1094
1104
  }
1095
1105
 
@@ -1324,6 +1334,7 @@ function loadQueuedModels() {
1324
1334
  group.position.set(x, y, z)
1325
1335
  group.userData.isDroppedModel = true
1326
1336
  scene.add(group)
1337
+ renderer.compileAsync(group, camera).catch(() => renderer.compile(group, camera))
1327
1338
  const envApp = appModules.get('environment')
1328
1339
  if (envApp?.onEvent) {
1329
1340
  envApp.onEvent({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spoint",
3
- "version": "0.1.31",
3
+ "version": "0.1.33",
4
4
  "description": "Physics and netcode SDK for multiplayer game servers",
5
5
  "type": "module",
6
6
  "main": "src/index.js",