Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor out dependency of SceneGrab on the AppBase #4901

Merged
merged 3 commits into from
Dec 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/framework/app-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import { Asset } from './asset/asset.js';
import { AssetRegistry } from './asset/asset-registry.js';
import { BundleRegistry } from './bundle/bundle-registry.js';
import { ComponentSystemRegistry } from './components/registry.js';
import { SceneGrab } from './graphics/scene-grab.js';
import { SceneGrab } from '../scene/graphics/scene-grab.js';
import { BundleHandler } from './handlers/bundle.js';
import { ResourceLoader } from './handlers/loader.js';
import { I18n } from './i18n/i18n.js';
Expand Down Expand Up @@ -371,7 +371,7 @@ class AppBase extends EventHandler {
id: LAYERID_WORLD
});

this.sceneGrab = new SceneGrab(this);
this.sceneGrab = new SceneGrab(this.graphicsDevice, this.scene);
this.defaultLayerDepth = this.sceneGrab.layer;

this.defaultLayerSkybox = new Layer({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { Debug } from '../../core/debug.js';

import {
DEVICETYPE_WEBGPU,
ADDRESS_CLAMP_TO_EDGE,
Expand All @@ -12,9 +14,9 @@ import { DebugGraphics } from '../../platform/graphics/debug-graphics.js';
import {
LAYERID_DEPTH, LAYERID_WORLD,
SHADER_DEPTH
} from '../../scene/constants.js';
} from '../constants.js';

import { Layer } from '../../scene/layer.js';
import { Layer } from '../layer.js';

// uniform names (first is current name, second one is deprecated name for compatibility)
const _depthUniformNames = ['uSceneDepthMap', 'uDepthMap'];
Expand All @@ -34,11 +36,20 @@ const _colorUniformNames = ['uSceneColorMap', 'texture_grabPass'];
* @ignore
*/
class SceneGrab {
constructor(application) {
this.application = application;
/**
* Create an instance of SceneGrab.
*
* @param {import('../../platform/graphics/graphics-device.js').GraphicsDevice} device - The
* graphics device.
* @param {import('../scene.js').Scene} scene - The scene.
*/
constructor(device, scene) {

Debug.assert(scene);
this.scene = scene;

/** @type {import('../../platform/graphics/graphics-device.js').GraphicsDevice} */
this.device = application.graphicsDevice;
Debug.assert(device);
this.device = device;

// create depth layer
this.layer = null;
Expand All @@ -52,6 +63,25 @@ class SceneGrab {
}
}

/**
* Returns true if the camera rendering scene grab textures requires a render pass to do it.
*
* @param {import('../../platform/graphics/graphics-device.js').GraphicsDevice} device - The
* graphics device used for rendering.
* @param {import('../../framework/components/camera/component.js').CameraComponent} camera - The camera that
* needs scene grab textures.
*/
static requiresRenderPass(device, camera) {

// just copy out the textures, no render pass needed
if (device.webgl2 || device.deviceType === DEVICETYPE_WEBGPU) {
return false;
}

// on WebGL1 device, only depth rendering needs render pass
return camera.renderSceneDepthMap;
}

setupUniform(device, depth, buffer) {

// assign it to scopes to expose it to shaders
Expand Down Expand Up @@ -143,7 +173,7 @@ class SceneGrab {
// main path where both color and depth is copied from existing surface
initMainPath() {

const app = this.application;
const device = this.device;
const self = this;

// WebGL 2 depth layer just copies existing color or depth
Expand All @@ -162,10 +192,7 @@ class SceneGrab {

onPreRenderOpaque: function (cameraPass) { // resize depth map if needed

/** @type {import('../../platform/graphics/graphics-device.js').GraphicsDevice} */
const device = app.graphicsDevice;

/** @type {import('../components/camera/component.js').CameraComponent} */
/** @type {import('../../framework/components/camera/component.js').CameraComponent} */
const camera = this.cameras[cameraPass];

if (camera.renderSceneColorMap) {
Expand Down Expand Up @@ -228,8 +255,9 @@ class SceneGrab {
// fallback path, where copy is not possible and the scene gets re-rendered
initFallbackPath() {

const app = this.application;
const self = this;
const device = this.device;
const scene = this.scene;

// WebGL 1 depth layer renders the same objects as in World, but with RGBA-encoded depth shader to get depth
this.layer = new Layer({
Expand All @@ -244,9 +272,9 @@ class SceneGrab {
this.depthRenderTarget = new RenderTarget({
name: 'depthRenderTarget-webgl1',
depth: true,
stencil: app.graphicsDevice.supportsStencil,
stencil: device.supportsStencil,
autoResolve: false,
graphicsDevice: app.graphicsDevice
graphicsDevice: device
});

// assign it so the render actions knows to render to it
Expand All @@ -266,10 +294,7 @@ class SceneGrab {

onPostCull: function (cameraPass) {

/** @type {import('../../platform/graphics/graphics-device.js').GraphicsDevice} */
const device = app.graphicsDevice;

/** @type {import('../components/camera/component.js').CameraComponent} */
/** @type {import('../../framework/components/camera/component.js').CameraComponent} */
const camera = this.cameras[cameraPass];

if (camera.renderSceneDepthMap) {
Expand All @@ -283,13 +308,12 @@ class SceneGrab {
// Collect all rendered mesh instances with the same render target as World has, depthWrite == true and prior to this layer to replicate blitFramebuffer on WebGL2
const visibleObjects = this.instances.visibleOpaque[cameraPass];
const visibleList = visibleObjects.list;
const layerComposition = app.scene.layers;
const layerComposition = scene.layers;
const subLayerEnabled = layerComposition.subLayerEnabled;
const isTransparent = layerComposition.subLayerList;

// can't use self.defaultLayerWorld.renderTarget because projects that use the editor override default layers
const rt = app.scene.layers.getLayerById(LAYERID_WORLD).renderTarget;
const cam = this.cameras[cameraPass];
const rt = layerComposition.getLayerById(LAYERID_WORLD).renderTarget;

let visibleLength = 0;
const layers = layerComposition.layerList;
Expand All @@ -298,7 +322,7 @@ class SceneGrab {
if (layer === this) break;
if (layer.renderTarget !== rt || !layer.enabled || !subLayerEnabled[i]) continue;

const layerCamId = layer.cameras.indexOf(cam);
const layerCamId = layer.cameras.indexOf(camera);
if (layerCamId < 0) continue;

const transparent = isTransparent[i];
Expand All @@ -320,10 +344,7 @@ class SceneGrab {

onPreRenderOpaque: function (cameraPass) {

/** @type {import('../../platform/graphics/graphics-device.js').GraphicsDevice} */
const device = app.graphicsDevice;

/** @type {import('../components/camera/component.js').CameraComponent} */
/** @type {import('../../framework/components/camera/component.js').CameraComponent} */
const camera = this.cameras[cameraPass];

if (camera.renderSceneColorMap) {
Expand Down Expand Up @@ -366,12 +387,12 @@ class SceneGrab {
},

onDrawCall: function () {
app.graphicsDevice.setColorWrite(true, true, true, true);
device.setColorWrite(true, true, true, true);
},

onPostRenderOpaque: function (cameraPass) {

/** @type {import('../components/camera/component.js').CameraComponent} */
/** @type {import('../../framework/components/camera/component.js').CameraComponent} */
const camera = this.cameras[cameraPass];

if (camera.renderSceneDepthMap) {
Expand Down
7 changes: 4 additions & 3 deletions src/scene/renderer/forward-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {
import { Renderer } from './renderer.js';
import { LightCamera } from './light-camera.js';
import { WorldClustersDebug } from '../lighting/world-clusters-debug.js';
import { SceneGrab } from '../graphics/scene-grab.js';

const webgl1DepthClearColor = new Color(254.0 / 255, 254.0 / 255, 254.0 / 255, 254.0 / 255);

Expand Down Expand Up @@ -968,15 +969,15 @@ class ForwardRenderer extends Renderer {
const camera = startLayer.cameras[startRenderAction.cameraIndex];

// depth grab pass on webgl1 is normal render pass (scene gets re-rendered)
const isWebgl1DepthGrabPass = isGrabPass && !this.device.webgl2 && camera.renderSceneDepthMap;
const isRealPass = !isGrabPass || isWebgl1DepthGrabPass;
const grabPassRequired = isGrabPass && SceneGrab.requiresRenderPass(this.device, camera);
const isRealPass = !isGrabPass || grabPassRequired;

if (isRealPass) {

renderPass.init(renderTarget);
renderPass.fullSizeClearRect = camera.camera.fullSizeClearRect;

if (isWebgl1DepthGrabPass) {
if (grabPassRequired) {

// webgl1 depth rendering clear values
renderPass.setClearColor(webgl1DepthClearColor);
Expand Down