perf(nexus): implement performance tier optimization for low-end devices
This commit is contained in:
65
app.js
65
app.js
@@ -644,19 +644,31 @@ async function init() {
|
|||||||
playerPos = new THREE.Vector3(0, 2, 12);
|
playerPos = new THREE.Vector3(0, 2, 12);
|
||||||
playerRot = new THREE.Euler(0, 0, 0, 'YXZ');
|
playerRot = new THREE.Euler(0, 0, 0, 'YXZ');
|
||||||
|
|
||||||
|
// Detect performance tier BEFORE creating renderer (antialias cannot be changed after)
|
||||||
|
performanceTier = detectPerformanceTier();
|
||||||
|
|
||||||
const canvas = document.getElementById('nexus-canvas');
|
const canvas = document.getElementById('nexus-canvas');
|
||||||
renderer = new THREE.WebGLRenderer({ canvas, antialias: true });
|
const antialias = performanceTier !== 'low';
|
||||||
|
renderer = new THREE.WebGLRenderer({ canvas, antialias });
|
||||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||||
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
renderer.toneMapping = THREE.ACESFilmicToneMapping;
|
||||||
renderer.toneMappingExposure = 1.2;
|
renderer.toneMappingExposure = 1.2;
|
||||||
renderer.shadowMap.enabled = true;
|
renderer.shadowMap.enabled = performanceTier !== 'low';
|
||||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
renderer.shadowMap.type = performanceTier === 'high' ? THREE.PCFSoftShadowMap : THREE.BasicShadowMap;
|
||||||
|
|
||||||
performanceTier = detectPerformanceTier();
|
|
||||||
updateLoad(10);
|
updateLoad(10);
|
||||||
|
|
||||||
scene = new THREE.Scene();
|
scene = new THREE.Scene();
|
||||||
scene.fog = new THREE.FogExp2(0x050510, 0.012);
|
|
||||||
|
// Fog density based on performance tier
|
||||||
|
if (performanceTier === 'low') {
|
||||||
|
// No fog for low tier
|
||||||
|
scene.fog = null;
|
||||||
|
} else if (performanceTier === 'medium') {
|
||||||
|
scene.fog = new THREE.FogExp2(0x050510, 0.008);
|
||||||
|
} else {
|
||||||
|
scene.fog = new THREE.FogExp2(0x050510, 0.012);
|
||||||
|
}
|
||||||
|
|
||||||
setupGOFAI();
|
setupGOFAI();
|
||||||
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
|
camera = new THREE.PerspectiveCamera(65, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||||
@@ -710,14 +722,29 @@ async function init() {
|
|||||||
fetchGiteaData();
|
fetchGiteaData();
|
||||||
setInterval(fetchGiteaData, 30000); // Refresh every 30s
|
setInterval(fetchGiteaData, 30000); // Refresh every 30s
|
||||||
|
|
||||||
composer = new EffectComposer(renderer);
|
// Initialize post-processing based on performance tier
|
||||||
composer.addPass(new RenderPass(scene, camera));
|
// Low tier: No post-processing (avoids GPU stalls from readPixels)
|
||||||
const bloom = new UnrealBloomPass(
|
// Medium tier: RenderPass + SMAA only (no bloom)
|
||||||
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
// High tier: Full post-processing with bloom
|
||||||
0.6, 0.4, 0.85
|
if (performanceTier === 'low') {
|
||||||
);
|
// No composer for low tier - use direct renderer.render()
|
||||||
composer.addPass(bloom);
|
composer = null;
|
||||||
composer.addPass(new SMAAPass(window.innerWidth, window.innerHeight));
|
} else if (performanceTier === 'medium') {
|
||||||
|
composer = new EffectComposer(renderer);
|
||||||
|
composer.addPass(new RenderPass(scene, camera));
|
||||||
|
// Skip UnrealBloomPass to avoid GPU stalls from readPixels
|
||||||
|
composer.addPass(new SMAAPass(window.innerWidth, window.innerHeight));
|
||||||
|
} else {
|
||||||
|
// High tier: Full post-processing with bloom
|
||||||
|
composer = new EffectComposer(renderer);
|
||||||
|
composer.addPass(new RenderPass(scene, camera));
|
||||||
|
const bloom = new UnrealBloomPass(
|
||||||
|
new THREE.Vector2(window.innerWidth, window.innerHeight),
|
||||||
|
0.6, 0.4, 0.85
|
||||||
|
);
|
||||||
|
composer.addPass(bloom);
|
||||||
|
composer.addPass(new SMAAPass(window.innerWidth, window.innerHeight));
|
||||||
|
}
|
||||||
|
|
||||||
updateLoad(95);
|
updateLoad(95);
|
||||||
|
|
||||||
@@ -2495,7 +2522,12 @@ function gameLoop() {
|
|||||||
core.material.emissiveIntensity = 1.5 + Math.sin(elapsed * 2) * 0.5;
|
core.material.emissiveIntensity = 1.5 + Math.sin(elapsed * 2) * 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
composer.render();
|
// Render based on performance tier (low tier bypasses composer to avoid GPU stalls)
|
||||||
|
if (composer) {
|
||||||
|
composer.render();
|
||||||
|
} else {
|
||||||
|
renderer.render(scene, camera);
|
||||||
|
}
|
||||||
|
|
||||||
updateAshStorm(delta, elapsed);
|
updateAshStorm(delta, elapsed);
|
||||||
updatePortalTunnel(delta, elapsed);
|
updatePortalTunnel(delta, elapsed);
|
||||||
@@ -2528,7 +2560,10 @@ function onResize() {
|
|||||||
camera.aspect = w / h;
|
camera.aspect = w / h;
|
||||||
camera.updateProjectionMatrix();
|
camera.updateProjectionMatrix();
|
||||||
renderer.setSize(w, h);
|
renderer.setSize(w, h);
|
||||||
composer.setSize(w, h);
|
// Only resize composer if it exists (low tier has no composer)
|
||||||
|
if (composer) {
|
||||||
|
composer.setSize(w, h);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ═══ AGENT SIMULATION ═══
|
// ═══ AGENT SIMULATION ═══
|
||||||
|
|||||||
Reference in New Issue
Block a user