From 964e75c831150cf5d550a2e02351423dc7d9d3b4 Mon Sep 17 00:00:00 2001 From: Kirill Osipov Date: Sat, 18 Jan 2025 12:52:12 +0100 Subject: [PATCH] Update the AABB during rendering only if it hasn't already been updated in the current frame. --- src/framework/lightmapper/lightmapper.js | 2 +- src/scene/mesh-instance.js | 13 ++++++++++--- src/scene/renderer/renderer.js | 7 ++++++- src/scene/renderer/shadow-renderer.js | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/framework/lightmapper/lightmapper.js b/src/framework/lightmapper/lightmapper.js index 96e806ca6a5..18dd4558e27 100644 --- a/src/framework/lightmapper/lightmapper.js +++ b/src/framework/lightmapper/lightmapper.js @@ -813,7 +813,7 @@ class Lightmapper { const meshInstances = bakeNode.meshInstances; for (let i = 0; i < meshInstances.length; i++) { - if (meshInstances[i]._isVisible(shadowCam)) { + if (meshInstances[i]._isVisible(shadowCam, this.renderer._aabbUpdateIndex)) { nodeVisible = true; break; } diff --git a/src/scene/mesh-instance.js b/src/scene/mesh-instance.js index 4b8fe23f1eb..3813a965392 100644 --- a/src/scene/mesh-instance.js +++ b/src/scene/mesh-instance.js @@ -376,6 +376,9 @@ class MeshInstance { */ _calculateSortDistance = null; + /** @private */ + _aabbUpdateIndex = 0; + /** * Create a new MeshInstance instance. * @@ -942,10 +945,11 @@ class MeshInstance { * date, which forward-renderer takes care of. This function should not be called elsewhere. * * @param {Camera} camera - The camera to test visibility against. + * @param {number} aabbUpdateIndex - An index used to detect if AABB has already been updated this frame. * @returns {boolean} - True if the mesh instance is visible by the camera, false otherwise. * @ignore */ - _isVisible(camera) { + _isVisible(camera, aabbUpdateIndex) { if (this.visible) { @@ -954,8 +958,11 @@ class MeshInstance { return this.isVisibleFunc(camera); } - _tempSphere.center = this.aabb.center; // this line evaluates aabb - _tempSphere.radius = this._aabb.halfExtents.length(); + const aabb = this._aabbUpdateIndex === aabbUpdateIndex ? this._aabb : this.aabb; // this line evaluates aabb + this._aabbUpdateIndex = aabbUpdateIndex; + + _tempSphere.center = aabb.center; + _tempSphere.radius = aabb.halfExtents.length(); return camera.frustum.containsSphere(_tempSphere) > 0; } diff --git a/src/scene/renderer/renderer.js b/src/scene/renderer/renderer.js index 945f9a44234..2c3f7e208b6 100644 --- a/src/scene/renderer/renderer.js +++ b/src/scene/renderer/renderer.js @@ -158,6 +158,9 @@ class Renderer { blueNoise = new BlueNoise(123); + /** @private */ + _aabbUpdateIndex = 0; + /** * Create a new instance. * @@ -916,7 +919,7 @@ class Renderer { const drawCall = drawCalls[i]; if (drawCall.visible) { - const visible = !doCull || !drawCall.cull || drawCall._isVisible(camera); + const visible = !doCull || !drawCall.cull || drawCall._isVisible(camera, this._aabbUpdateIndex); if (visible) { drawCall.visibleThisFrame = true; @@ -1131,6 +1134,8 @@ class Renderer { const cullTime = now(); // #endif + this._aabbUpdateIndex++; + const { scene } = this; this.processingMeshInstances.clear(); diff --git a/src/scene/renderer/shadow-renderer.js b/src/scene/renderer/shadow-renderer.js index 2b342c91802..6a80e837402 100644 --- a/src/scene/renderer/shadow-renderer.js +++ b/src/scene/renderer/shadow-renderer.js @@ -142,7 +142,7 @@ class ShadowRenderer { const meshInstance = meshInstances[i]; if (meshInstance.castShadow) { - if (!meshInstance.cull || meshInstance._isVisible(camera)) { + if (!meshInstance.cull || meshInstance._isVisible(camera, this.renderer._aabbUpdateIndex)) { meshInstance.visibleThisFrame = true; visible.push(meshInstance); }