Skip to content

Commit

Permalink
Camera callbacks replaced by the events (#7156)
Browse files Browse the repository at this point in the history
* Camera callbacks replaced by the events

* lint

* types

* updates back on feedback

* strings

* don’t export event names

---------

Co-authored-by: Martin Valigursky <[email protected]>
  • Loading branch information
mvaligursky and Martin Valigursky authored Nov 29, 2024
1 parent 1395786 commit 5268fe3
Show file tree
Hide file tree
Showing 11 changed files with 211 additions and 114 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ pc.WasmModule.setConfig('DracoDecoderModule', {
const assets = {
laboratory: new pc.Asset('statue', 'container', { url: `${rootPath}/static/assets/models/laboratory.glb` }),
orbit: new pc.Asset('orbit', 'script', { url: `${rootPath}/static/scripts/camera/orbit-camera.js` }),
ssao: new pc.Asset('ssao', 'script', { url: `${rootPath}/static/scripts/posteffects/posteffect-ssao.js` }),
helipad: new pc.Asset(
'helipad-env-atlas',
'texture',
Expand Down
36 changes: 24 additions & 12 deletions scripts/utils/cubemap-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ CubemapRenderer.prototype.initialize = function () {
];

// set up rendering for all 6 faces
let firstCamera = null;
let lastCamera = null;
for (var i = 0; i < 6; i++) {

// render target, connected to cubemap texture face
Expand Down Expand Up @@ -109,19 +111,29 @@ CubemapRenderer.prototype.initialize = function () {
// set up its rotation
e.setRotation(cameraRotations[i]);

// Before the first camera renders, trigger onCubemapPreRender event on the entity.
if (i === 0) {
e.camera.onPreRender = () => {
this.entity.fire('onCubemapPreRender');
};
// keep the first and last camera
if (i === 0) firstCamera = e.camera;
if (i === 5) lastCamera = e.camera;
}

// Before the first camera renders, trigger onCubemapPreRender event on the entity.
this.evtPreRender = this.app.scene.on('prerender', (cameraComponent) => {
if (cameraComponent === firstCamera) {
this.entity.fire('onCubemapPreRender');
}
});

// When last camera is finished rendering, trigger onCubemapPostRender event on the entity.
// This can be listened to by the user, and the resulting cubemap can be further processed (e.g prefiltered)
if (i === 5) {
e.camera.onPostRender = () => {
this.entity.fire('onCubemapPostRender');
};
// When last camera is finished rendering, trigger onCubemapPostRender event on the entity.
// This can be listened to by the user, and the resulting cubemap can be further processed (e.g pre-filtering)
this.evtPostRender = this.app.scene.on('postrender', (cameraComponent) => {
if (cameraComponent === lastCamera) {
this.entity.fire('onCubemapPostRender');
}
}
});

// when the script is destroyed, remove event listeners
this.on('destroy', () => {
this.evtPreRender.off();
this.evtPostRender.off();
});
};
13 changes: 10 additions & 3 deletions scripts/utils/planar-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,16 @@ PlanarRenderer.prototype.initialize = function () {

// When the camera is finished rendering, trigger onPlanarPostRender event on the entity.
// This can be listened to by the user, and the resulting texture can be further processed (e.g prefiltered)
planarCamera.onPostRender = () => {
this.entity.fire('onPlanarPostRender');
};
this.evtPostRender = this.app.scene.on('postrender', (cameraComponent) => {
if (planarCamera === cameraComponent) {
this.entity.fire('onPlanarPostRender');
}
});

// when the script is destroyed, remove event listeners
this.on('destroy', () => {
this.evtPostRender.off();
});
};

PlanarRenderer.prototype.updateRenderTarget = function () {
Expand Down
40 changes: 24 additions & 16 deletions src/deprecated/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ import { RigidBodyComponent } from '../framework/components/rigid-body/component
import { RigidBodyComponentSystem } from '../framework/components/rigid-body/system.js';
import { LitShader } from '../scene/shader-lib/programs/lit-shader.js';
import { Geometry } from '../scene/geometry/geometry.js';
import { CameraComponent } from '../framework/components/camera/component.js';

// MATH

Expand Down Expand Up @@ -564,30 +565,37 @@ Object.defineProperty(Scene.prototype, 'models', {
}
});

// A helper function to add deprecated set and get property on a Layer
function _removedLayerProperty(name) {
Object.defineProperty(Layer.prototype, name, {
// A helper function to add deprecated set and get property on a class
function _removedClassProperty(targetClass, name, comment = '') {
Object.defineProperty(targetClass.prototype, name, {
set: function (value) {
Debug.errorOnce(`pc.Layer#${name} has been removed.`);
Debug.errorOnce(`${targetClass.name}#${name} has been removed. ${comment}`);
},
get: function () {
Debug.errorOnce(`pc.Layer#${name} has been removed.`);
Debug.errorOnce(`${targetClass.name}#${name} has been removed. ${comment}`);
return undefined;
}
});
}

_removedLayerProperty('renderTarget');
_removedLayerProperty('onPreCull');
_removedLayerProperty('onPreRender');
_removedLayerProperty('onPreRenderOpaque');
_removedLayerProperty('onPreRenderTransparent');
_removedLayerProperty('onPostCull');
_removedLayerProperty('onPostRender');
_removedLayerProperty('onPostRenderOpaque');
_removedLayerProperty('onPostRenderTransparent');
_removedLayerProperty('onDrawCall');
_removedLayerProperty('layerReference');
_removedClassProperty(Layer, 'renderTarget');
_removedClassProperty(Layer, 'onPreCull');
_removedClassProperty(Layer, 'onPreRender');
_removedClassProperty(Layer, 'onPreRenderOpaque');
_removedClassProperty(Layer, 'onPreRenderTransparent');
_removedClassProperty(Layer, 'onPostCull');
_removedClassProperty(Layer, 'onPostRender');
_removedClassProperty(Layer, 'onPostRenderOpaque');
_removedClassProperty(Layer, 'onPostRenderTransparent');
_removedClassProperty(Layer, 'onDrawCall');
_removedClassProperty(Layer, 'layerReference');

_removedClassProperty(CameraComponent, 'onPreCull', 'Use Scene#EVENT_PRECULL event instead.');
_removedClassProperty(CameraComponent, 'onPostCull', 'Use Scene#EVENT_POSTCULL event instead.');
_removedClassProperty(CameraComponent, 'onPreRender', 'Use Scene#EVENT_PRERENDER event instead.');
_removedClassProperty(CameraComponent, 'onPostRender', 'Use Scene#EVENT_POSTRENDER event instead.');
_removedClassProperty(CameraComponent, 'onPreRenderLayer', 'Use Scene#EVENT_PRERENDER_LAYER event instead.');
_removedClassProperty(CameraComponent, 'onPostRenderLayer', 'Use Scene#EVENT_POSTRENDER_LAYER event instead.');

ForwardRenderer.prototype.renderComposition = function (comp) {
Debug.deprecated('pc.ForwardRenderer#renderComposition is deprecated. Use pc.AppBase.renderComposition instead.');
Expand Down
19 changes: 9 additions & 10 deletions src/extras/renderers/outline-renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,11 @@ class OutlineRenderer {
this.outlineShaderPass = this.outlineCameraEntity.camera.setShaderPass('OutlineShaderPass');

// function called after the camera has rendered the outline objects to the texture
this.outlineCameraEntity.camera.onPostRender = () => {
this.onPostRender();
};
app.scene.on('postrender', (cameraComponent) => {
if (this.outlineCameraEntity.camera === cameraComponent) {
this.onPostRender();
}
});

// add the camera to the scene
this.app.root.addChild(this.outlineCameraEntity);
Expand Down Expand Up @@ -331,15 +333,12 @@ class OutlineRenderer {
this.updateRenderTarget(sceneCamera);

// function called before the scene camera renders a layer
sceneCameraEntity.camera.onPreRenderLayer = (layer, transparent) => {

// when specified blend layer is rendered, add outline before its rendering
if (transparent === blendLayerTransparent && layer === blendLayer) {
const evt = this.app.scene.on('prerender:layer', (cameraComponent, layer, transparent) => {
if (sceneCamera === cameraComponent && transparent === blendLayerTransparent && layer === blendLayer) {
this.blendOutlines();

sceneCameraEntity.camera.onPreRenderLayer = null;
evt.off();
}
};
});

// copy the transform
this.outlineCameraEntity.setLocalPosition(sceneCameraEntity.getPosition());
Expand Down
54 changes: 0 additions & 54 deletions src/framework/components/camera/component.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,6 @@ import { PostEffectQueue } from './post-effect-queue.js';
* @param {number} view - Type of view. Can be {@link VIEW_CENTER}, {@link VIEW_LEFT} or {@link VIEW_RIGHT}. Left and right are only used in stereo rendering.
*/

/**
* Callback used by {@link CameraComponent#onPreRenderLayer} and {@link CameraComponent#onPostRenderLayer}.
*
* @callback RenderLayerCallback
* @param {Layer} layer - The layer.
* @param {boolean} transparent - True for transparent sublayer, otherwise opaque sublayer.
*/

/**
* The Camera Component enables an Entity to render the scene. A scene requires at least one
* enabled camera component to be rendered. Note that multiple camera components can be enabled
Expand Down Expand Up @@ -69,52 +61,6 @@ class CameraComponent extends Component {
*/
onPostprocessing = null;

/**
* Custom function that is called before the camera renders the scene.
*
* @type {Function|null}
*/
onPreRender = null;

/**
* Custom function that is called before the camera renders a layer. This is called during
* rendering to a render target or a default framebuffer, and additional rendering can be
* performed here, for example using ${@link QuadRender#render}.
*
* @type {RenderLayerCallback|null}
*/
onPreRenderLayer = null;

/**
* Custom function that is called after the camera renders the scene.
*
* @type {Function|null}
*/
onPostRender = null;

/**
* Custom function that is called after the camera renders a layer. This is called during
* rendering to a render target or a default framebuffer, and additional rendering can be
* performed here, for example using ${@link QuadRender#render}.
*
* @type {RenderLayerCallback|null}
*/
onPostRenderLayer = null;

/**
* Custom function that is called before visibility culling is performed for this camera.
*
* @type {Function|null}
*/
onPreCull = null;

/**
* Custom function that is called after visibility culling is performed for this camera.
*
* @type {Function|null}
*/
onPostCull = null;

/**
* A counter of requests of depth map rendering.
*
Expand Down
48 changes: 48 additions & 0 deletions src/scene/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -1054,3 +1054,51 @@ export const DITHER_BLUENOISE = 'bluenoise';
* @category Graphics
*/
export const DITHER_IGNNOISE = 'ignnoise';

/**
* Name of event fired before the camera renders the scene.
*
* @type {string}
* @ignore
*/
export const EVENT_PRERENDER = 'prerender';

/**
* Name of event fired after the camera renders the scene.
*
* @type {string}
* @ignore
*/
export const EVENT_POSTRENDER = 'postrender';

/**
* Name of event fired before a layer is rendered by a camera.
*
* @type {string}
* @ignore
*/
export const EVENT_PRERENDER_LAYER = 'prerender:layer';

/**
* Name of event fired after a layer is rendered by a camera.
*
* @type {string}
* @ignore
*/
export const EVENT_POSTRENDER_LAYER = 'postrender:layer';

/**
* Name of event fired before visibility culling is performed for the camera
*
* @type {string}
* @ignore
*/
export const EVENT_PRECULL = 'precull';

/**
* Name of event after before visibility culling is performed for the camera
*
* @type {string}
* @ignore
*/
export const EVENT_POSTCULL = 'postcull';
4 changes: 2 additions & 2 deletions src/scene/mesh-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,8 +225,8 @@ class MeshInstance {
visible = true;

/**
* Read this value in {@link CameraComponent#onPostCull} to determine if the object is actually going to
* be rendered.
* Read this value in {@link Scene#EVENT_POSTCULL} event to determine if the object is actually
* going to be rendered.
*
* @type {boolean}
*/
Expand Down
20 changes: 10 additions & 10 deletions src/scene/renderer/render-pass-forward.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { BlendState } from '../../platform/graphics/blend-state.js';
import { DebugGraphics } from '../../platform/graphics/debug-graphics.js';
import { RenderPass } from '../../platform/graphics/render-pass.js';
import { RenderAction } from '../composition/render-action.js';
import { SHADER_FORWARD } from '../constants.js';
import { EVENT_POSTRENDER, EVENT_POSTRENDER_LAYER, EVENT_PRERENDER, EVENT_PRERENDER_LAYER, SHADER_FORWARD } from '../constants.js';

/**
* @import { CameraComponent } from '../../framework/components/camera/component.js'
Expand Down Expand Up @@ -201,11 +201,11 @@ class RenderPassForward extends RenderPass {
before() {
const { renderActions } = this;

// onPreRender callbacks
// onPreRender events
for (let i = 0; i < renderActions.length; i++) {
const ra = renderActions[i];
if (ra.firstCameraUse) {
ra.camera.onPreRender?.();
this.scene.fire(EVENT_PRERENDER, ra.camera);
}
}
}
Expand All @@ -231,11 +231,11 @@ class RenderPassForward extends RenderPass {

after() {

// onPostRender callbacks
// onPostRender events
for (let i = 0; i < this.renderActions.length; i++) {
const ra = this.renderActions[i];
if (ra.lastCameraUse) {
ra.camera.onPostRender?.();
this.scene.fire(EVENT_POSTRENDER, ra.camera);
}
}

Expand All @@ -249,7 +249,7 @@ class RenderPassForward extends RenderPass {
*/
renderRenderAction(renderAction, firstRenderAction) {

const { renderer } = this;
const { renderer, scene } = this;
const device = renderer.device;

// layer
Expand All @@ -263,8 +263,8 @@ class RenderPassForward extends RenderPass {

if (camera) {

// layer pre render callback
camera.onPreRenderLayer?.(layer, transparent);
// layer pre render event
scene.fire(EVENT_PRERENDER_LAYER, camera, layer, transparent);

const options = {
lightClusters: renderAction.lightClusters
Expand Down Expand Up @@ -292,8 +292,8 @@ class RenderPassForward extends RenderPass {
device.setStencilState(null, null);
device.setAlphaToCoverage(false);

// layer post render callback
camera.onPostRenderLayer?.(layer, transparent);
// layer post render event
scene.fire(EVENT_POSTRENDER_LAYER, camera, layer, transparent);
}

DebugGraphics.popGpuMarker(this.device);
Expand Down
Loading

0 comments on commit 5268fe3

Please sign in to comment.