From a27eeaad63699b323b0255447ef5e8ffd9e40d9b Mon Sep 17 00:00:00 2001 From: Martin Valigursky Date: Thu, 21 Sep 2023 11:25:30 +0100 Subject: [PATCH] Small internal refactor of the way camera is passed around for rendering --- src/scene/composition/layer-composition.js | 36 +++++++++++++--------- src/scene/composition/render-action.js | 3 -- src/scene/layer.js | 25 ++++++++++----- src/scene/renderer/forward-renderer.js | 16 +++++----- src/scene/renderer/renderer.js | 9 +++--- 5 files changed, 50 insertions(+), 39 deletions(-) diff --git a/src/scene/composition/layer-composition.js b/src/scene/composition/layer-composition.js index c28650d157e..8ca7fdab847 100644 --- a/src/scene/composition/layer-composition.js +++ b/src/scene/composition/layer-composition.js @@ -65,6 +65,14 @@ class LayerComposition extends EventHandler { */ cameras = []; + /** + * A mapping of {@link CameraComponent} to its index in {@link LayerComposition#cameras}. + * + * @type {Map} + * @ignore + */ + camerasMap = new Map(); + /** * The actual rendering sequence, generated based on layers and cameras * @@ -134,6 +142,12 @@ class LayerComposition extends EventHandler { sortPriority(this.cameras); } + // update camera map + this.camerasMap.clear(); + for (let i = 0; i < this.cameras.length; i++) { + this.camerasMap.set(this.cameras[i], i); + } + // collect a list of layers this camera renders const cameraLayers = []; @@ -181,16 +195,11 @@ class LayerComposition extends EventHandler { } } - // camera index in the layer array - const cameraIndex = layer.cameras.indexOf(camera); - if (cameraIndex >= 0) { - - // add render action to describe rendering step - lastRenderAction = this.addRenderAction(this._renderActions, renderActionCount, layer, j, cameraIndex, - cameraFirstRenderAction, postProcessMarked); - renderActionCount++; - cameraFirstRenderAction = false; - } + // add render action to describe rendering step + lastRenderAction = this.addRenderAction(this._renderActions, renderActionCount, layer, j, camera, + cameraFirstRenderAction, postProcessMarked); + renderActionCount++; + cameraFirstRenderAction = false; } } } @@ -226,7 +235,7 @@ class LayerComposition extends EventHandler { } // function adds new render action to a list, while trying to limit allocation and reuse already allocated objects - addRenderAction(renderActions, renderActionIndex, layer, layerIndex, cameraIndex, cameraFirstRenderAction, postProcessMarked) { + addRenderAction(renderActions, renderActionIndex, layer, layerIndex, camera, cameraFirstRenderAction, postProcessMarked) { // try and reuse object, otherwise allocate new /** @type {RenderAction} */ @@ -237,8 +246,6 @@ class LayerComposition extends EventHandler { // render target from the camera takes precedence over the render target from the layer let rt = layer.renderTarget; - /** @type {import('../../framework/components/camera/component.js').CameraComponent} */ - const camera = layer.cameras[cameraIndex]; if (camera && camera.renderTarget) { if (layer.id !== LAYERID_DEPTH) { // ignore depth layer rt = camera.renderTarget; @@ -276,7 +283,6 @@ class LayerComposition extends EventHandler { renderAction.triggerPostprocess = false; renderAction.layerIndex = layerIndex; renderAction.layer = layer; - renderAction.cameraIndex = cameraIndex; renderAction.camera = camera; renderAction.renderTarget = rt; renderAction.clearColor = clearColor; @@ -333,7 +339,7 @@ class LayerComposition extends EventHandler { const layer = this.layerList[layerIndex]; const enabled = layer.enabled && this.subLayerEnabled[layerIndex]; const transparent = this.subLayerList[layerIndex]; - const camera = layer.cameras[ra.cameraIndex]; + const camera = ra.camera; const clear = (ra.clearColor ? 'Color ' : '..... ') + (ra.clearDepth ? 'Depth ' : '..... ') + (ra.clearStencil ? 'Stencil' : '.......'); Debug.trace(TRACEID_RENDER_ACTION, i + diff --git a/src/scene/composition/render-action.js b/src/scene/composition/render-action.js index 25a73e61873..e3a99b90c9e 100644 --- a/src/scene/composition/render-action.js +++ b/src/scene/composition/render-action.js @@ -13,9 +13,6 @@ class RenderAction { // the layer this.layer = null; - // index into a camera array of the layer, stored in Layer.cameras - this.cameraIndex = 0; - // camera of type CameraComponent this.camera = null; diff --git a/src/scene/layer.js b/src/scene/layer.js index 7810cf81618..02c9152a0b1 100644 --- a/src/scene/layer.js +++ b/src/scene/layer.js @@ -151,9 +151,18 @@ class Layer { * True if the objects rendered on the layer require light cube (emitters with lighting do). * * @type {boolean} + * @ignore */ requiresLightCube = false; + /** + * @type {import('../framework/components/camera/component.js').CameraComponent[]} + * @ignore + */ + cameras = []; + + _dirtyCameras = false; + /** * Create a new Layer instance. * @@ -275,6 +284,7 @@ class Layer { * @type {Function} */ this.onPreCull = options.onPreCull; + /** * Custom function that is called before this layer is rendered. Useful, for example, for * reacting on screen size changes. This function is called before the first occurrence of @@ -285,6 +295,7 @@ class Layer { * @type {Function} */ this.onPreRender = options.onPreRender; + /** * Custom function that is called before opaque mesh instances (not semi-transparent) in * this layer are rendered. This function will receive camera index as the only argument. @@ -294,6 +305,7 @@ class Layer { * @type {Function} */ this.onPreRenderOpaque = options.onPreRenderOpaque; + /** * Custom function that is called before semi-transparent mesh instances in this layer are * rendered. This function will receive camera index as the only argument. You can get the @@ -313,6 +325,7 @@ class Layer { * @type {Function} */ this.onPostCull = options.onPostCull; + /** * Custom function that is called after this layer is rendered. Useful to revert changes * made in {@link Layer#onPreRender}. This function is called after the last occurrence of this @@ -323,6 +336,7 @@ class Layer { * @type {Function} */ this.onPostRender = options.onPostRender; + /** * Custom function that is called after opaque mesh instances (not semi-transparent) in * this layer are rendered. This function will receive camera index as the only argument. @@ -332,6 +346,7 @@ class Layer { * @type {Function} */ this.onPostRenderOpaque = options.onPostRenderOpaque; + /** * Custom function that is called after semi-transparent mesh instances in this layer are * rendered. This function will receive camera index as the only argument. You can get the @@ -349,6 +364,7 @@ class Layer { * @type {Function} */ this.onDrawCall = options.onDrawCall; + /** * Custom function that is called after the layer has been enabled. This happens when: * @@ -361,6 +377,7 @@ class Layer { * @type {Function} */ this.onEnable = options.onEnable; + /** * Custom function that is called after the layer has been disabled. This happens when: * @@ -395,14 +412,6 @@ class Layer { */ this.customCalculateSortValues = null; - /** - * @type {import('../framework/components/camera/component.js').CameraComponent[]} - * @ignore - */ - this.cameras = []; - - this._dirtyCameras = false; - // light hash based on the light keys this._lightHash = 0; this._lightHashDirty = false; diff --git a/src/scene/renderer/forward-renderer.js b/src/scene/renderer/forward-renderer.js index d5b59a74d3a..fcdbf2723e0 100644 --- a/src/scene/renderer/forward-renderer.js +++ b/src/scene/renderer/forward-renderer.js @@ -785,7 +785,7 @@ class ForwardRenderer extends Renderer { const renderAction = renderActions[i]; const layer = layerComposition.layerList[renderAction.layerIndex]; - const camera = layer.cameras[renderAction.cameraIndex]; + const camera = renderAction.camera; // skip disabled layers if (!renderAction.isLayerEnabled(layerComposition)) { @@ -835,7 +835,7 @@ class ForwardRenderer extends Renderer { // postprocessing if (renderAction.triggerPostprocess && camera?.onPostprocessing) { const renderPass = new RenderPass(this.device, () => { - this.renderPassPostprocessing(renderAction, layerComposition); + this.renderPassPostprocessing(renderAction); }); renderPass.requiresCubemaps = false; DebugHelper.setName(renderPass, `Postprocess`); @@ -863,8 +863,7 @@ class ForwardRenderer extends Renderer { const renderActions = layerComposition._renderActions; const startRenderAction = renderActions[startIndex]; const endRenderAction = renderActions[endIndex]; - const startLayer = layerComposition.layerList[startRenderAction.layerIndex]; - const camera = startLayer.cameras[startRenderAction.cameraIndex]; + const camera = startRenderAction.camera; if (camera) { @@ -948,10 +947,9 @@ class ForwardRenderer extends Renderer { this.gpuUpdate(this.processingMeshInstances); } - renderPassPostprocessing(renderAction, layerComposition) { + renderPassPostprocessing(renderAction) { - const layer = layerComposition.layerList[renderAction.layerIndex]; - const camera = layer.cameras[renderAction.cameraIndex]; + const camera = renderAction.camera; Debug.assert(renderAction.triggerPostprocess && camera.onPostprocessing); // trigger postprocessing for camera @@ -990,8 +988,8 @@ class ForwardRenderer extends Renderer { const layer = comp.layerList[layerIndex]; const transparent = comp.subLayerList[layerIndex]; - const cameraPass = renderAction.cameraIndex; - const camera = layer.cameras[cameraPass]; + const camera = renderAction.camera; + const cameraPass = comp.camerasMap.get(camera); if (!renderAction.isLayerEnabled(comp)) { return; diff --git a/src/scene/renderer/renderer.js b/src/scene/renderer/renderer.js index 4ff5007bdd9..d762718e723 100644 --- a/src/scene/renderer/renderer.js +++ b/src/scene/renderer/renderer.js @@ -1082,9 +1082,8 @@ class Renderer { if (!layer.enabled || !comp.subLayerEnabled[layerIndex]) continue; // camera - const cameraPass = renderAction.cameraIndex; /** @type {import('../../framework/components/camera/component.js').CameraComponent} */ - const camera = layer.cameras[cameraPass]; + const camera = renderAction.camera; if (camera) { @@ -1101,13 +1100,15 @@ class Renderer { this.cullLights(camera.camera, layer._lights); // cull mesh instances - layer.onPreCull?.(cameraPass); + if (layer.onPreCull) + layer.onPreCull(comp.camerasMap.get(camera)); const culledInstances = layer.getCulledInstances(camera.camera); const drawCalls = layer.meshInstances; this.cull(camera.camera, drawCalls, culledInstances); - layer.onPostCull?.(cameraPass); + if (layer.onPostCull) + layer.onPostCull(comp.camerasMap.get(camera)); } }