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 +4 -0
- package/client/app.js +16 -5
- package/package.json +1 -1
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
|
-
|
|
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
|
-
|
|
1082
|
-
|
|
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(() =>
|
|
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({
|