From 7608392439e18b0bc97f892bd253ce93bfefea08 Mon Sep 17 00:00:00 2001 From: Martin Valigursky <mvaligursky@snapchat.com> Date: Fri, 2 Feb 2024 11:33:39 +0000 Subject: [PATCH 1/2] Small refactor to ForwardRenderer.renderForwardLayer to allow additional options --- .../lightmapper/render-pass-lightmapper.js | 18 ++--- src/scene/renderer/forward-renderer.js | 75 ++++++++++++------- src/scene/renderer/render-pass-forward.js | 2 +- 3 files changed, 53 insertions(+), 42 deletions(-) diff --git a/src/framework/lightmapper/render-pass-lightmapper.js b/src/framework/lightmapper/render-pass-lightmapper.js index 02abe4755d2..c780959c4be 100644 --- a/src/framework/lightmapper/render-pass-lightmapper.js +++ b/src/framework/lightmapper/render-pass-lightmapper.js @@ -34,19 +34,11 @@ class RenderPassLightmapper extends RenderPass { const { renderer, camera, receivers, renderTarget, worldClusters, lightArray } = this; - // prepare clustered lighting - if (worldClusters) { - worldClusters.activate(); - } - - renderer.setCameraUniforms(camera, renderTarget); - if (device.supportsUniformBuffers) { - renderer.setupViewUniformBuffers(this.viewBindGroups, renderer.viewUniformFormat, renderer.viewBindGroupFormat, 1); - } - - renderer._forwardTime = 0; - renderer._shadowMapTime = 0; - renderer.renderForward(camera, receivers, lightArray, SHADER_FORWARDHDR); + renderer.renderForwardLayer(camera, renderTarget, null, undefined, SHADER_FORWARDHDR, this.viewBindGroups, { + meshInstances: receivers, + splitLights: lightArray, + lightClusters: worldClusters + }); DebugGraphics.popGpuMarker(device); } diff --git a/src/scene/renderer/forward-renderer.js b/src/scene/renderer/forward-renderer.js index c9e2eab0401..987d6f8339f 100644 --- a/src/scene/renderer/forward-renderer.js +++ b/src/scene/renderer/forward-renderer.js @@ -676,7 +676,7 @@ class ForwardRenderer extends Renderer { * Forward render mesh instances on a specified layer, using a camera and a render target. * Shaders used are based on the shaderPass provided, with optional clustered lighting support. * - * @param {import('../../framework/components/camera/component.js').CameraComponent} camera - The + * @param {import('../camera.js').Camera} camera - The * camera. * @param {import('../../platform/graphics/render-target.js').RenderTarget} renderTarget - The * render target. @@ -693,77 +693,96 @@ class ForwardRenderer extends Renderer { * @param {boolean} [options.clearStencil] - True if the stencil buffer should be cleared. * @param {import('../lighting/world-clusters.js').WorldClusters} [options.lightClusters] - The * world clusters object to be used for clustered lighting. + * @param {import('../mesh-instance.js').MeshInstance[]} [options.meshInstances] - The mesh + * instances to be rendered. Use when layer is not provided. + * @param {object} [options.splitLights] - The split lights to be used for clustered lighting. + * @param {import('../lighting/world-clusters.js').WorldClusters} [options.lightClusters] - The + * clustered lighting object to be used when clustered lighting is specified. */ renderForwardLayer(camera, renderTarget, layer, transparent, shaderPass, viewBindGroups, options = {}) { const { scene, device } = this; const clusteredLightingEnabled = scene.clusteredLightingEnabled; - this.setupViewport(camera.camera, renderTarget); + this.setupViewport(camera, renderTarget); // clearing const clearColor = options.clearColors ?? false; const clearDepth = options.clearDepth ?? false; const clearStencil = options.clearStencil ?? false; if (clearColor || clearDepth || clearStencil) { - this.clear(camera.camera, clearColor, clearDepth, clearStencil); + this.clear(camera, clearColor, clearDepth, clearStencil); } - // #if _PROFILER - const sortTime = now(); - // #endif + let visible, splitLights; + if (layer) { + // #if _PROFILER + const sortTime = now(); + // #endif - layer.sortVisible(camera.camera, transparent); + layer.sortVisible(camera, transparent); - // #if _PROFILER - this._sortTime += now() - sortTime; - // #endif + // #if _PROFILER + this._sortTime += now() - sortTime; + // #endif + + const culledInstances = layer.getCulledInstances(camera); + visible = transparent ? culledInstances.transparent : culledInstances.opaque; - const culledInstances = layer.getCulledInstances(camera.camera); - const visible = transparent ? culledInstances.transparent : culledInstances.opaque; + // add debug mesh instances to visible list + scene.immediate.onPreRenderLayer(layer, visible, transparent); + + // set up layer uniforms + if (layer.requiresLightCube) { + this.lightCube.update(scene.ambientLight, layer._lights); + this.constantLightCube.setValue(this.lightCube.colors); + } - // add debug mesh instances to visible list - scene.immediate.onPreRenderLayer(layer, visible, transparent); + splitLights = layer.splitLights; - // set up layer uniforms - if (layer.requiresLightCube) { - this.lightCube.update(scene.ambientLight, layer._lights); - this.constantLightCube.setValue(this.lightCube.colors); + } else { + visible = options.meshInstances; + splitLights = options.splitLights; } + Debug.assert(visible, 'Either layer or options.meshInstances must be provided'); + // upload clustered lights uniforms const { lightClusters } = options; if (clusteredLightingEnabled && lightClusters) { lightClusters.activate(); // debug rendering of clusters - if (!this.clustersDebugRendered && scene.lighting.debugLayer === layer.id) { - this.clustersDebugRendered = true; - WorldClustersDebug.render(lightClusters, this.scene); + if (layer) { + if (!this.clustersDebugRendered && scene.lighting.debugLayer === layer.id) { + this.clustersDebugRendered = true; + WorldClustersDebug.render(lightClusters, this.scene); + } } } // Set the not very clever global variable which is only useful when there's just one camera - scene._activeCamera = camera.camera; + scene._activeCamera = camera; - const viewCount = this.setCameraUniforms(camera.camera, renderTarget); + const viewCount = this.setCameraUniforms(camera, renderTarget); if (device.supportsUniformBuffers) { this.setupViewUniformBuffers(viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, viewCount); } // enable flip faces if either the camera has _flipFaces enabled or the render target has flipY enabled - const flipFaces = !!(camera.camera._flipFaces ^ renderTarget?.flipY); + const flipFaces = !!(camera._flipFaces ^ renderTarget?.flipY); const forwardDrawCalls = this._forwardDrawCalls; - this.renderForward(camera.camera, + this.renderForward(camera, visible, - layer.splitLights, + splitLights, shaderPass, - layer.onDrawCall, + layer?.onDrawCall, layer, flipFaces); - layer._forwardDrawCalls += this._forwardDrawCalls - forwardDrawCalls; + if (layer) + layer._forwardDrawCalls += this._forwardDrawCalls - forwardDrawCalls; } setSceneConstants() { diff --git a/src/scene/renderer/render-pass-forward.js b/src/scene/renderer/render-pass-forward.js index e966ee9719b..7fcbdc14743 100644 --- a/src/scene/renderer/render-pass-forward.js +++ b/src/scene/renderer/render-pass-forward.js @@ -268,7 +268,7 @@ class RenderPassForward extends RenderPass { options.clearStencil = renderAction.clearStencil; } - renderer.renderForwardLayer(camera, renderAction.renderTarget, layer, transparent, + renderer.renderForwardLayer(camera.camera, renderAction.renderTarget, layer, transparent, shaderPass, renderAction.viewBindGroups, options); // Revert temp frame stuff From 423895de76bf6fa2f6f5134d208c550a9b814b57 Mon Sep 17 00:00:00 2001 From: Martin Valigursky <mvaligursky@snapchat.com> Date: Fri, 2 Feb 2024 11:37:07 +0000 Subject: [PATCH 2/2] jsdocs cleanup --- src/scene/renderer/forward-renderer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/scene/renderer/forward-renderer.js b/src/scene/renderer/forward-renderer.js index 987d6f8339f..6fe80591219 100644 --- a/src/scene/renderer/forward-renderer.js +++ b/src/scene/renderer/forward-renderer.js @@ -696,8 +696,6 @@ class ForwardRenderer extends Renderer { * @param {import('../mesh-instance.js').MeshInstance[]} [options.meshInstances] - The mesh * instances to be rendered. Use when layer is not provided. * @param {object} [options.splitLights] - The split lights to be used for clustered lighting. - * @param {import('../lighting/world-clusters.js').WorldClusters} [options.lightClusters] - The - * clustered lighting object to be used when clustered lighting is specified. */ renderForwardLayer(camera, renderTarget, layer, transparent, shaderPass, viewBindGroups, options = {}) {