From a611fe2ac0da8e89f0adb9d059c91a68a2f2f750 Mon Sep 17 00:00:00 2001 From: Martin Valigursky <59932779+mvaligursky@users.noreply.github.com> Date: Thu, 14 Nov 2024 14:00:02 +0000 Subject: [PATCH] [BREAKING] Refactor API for gammaCorrection, toneMapping and Fog settings (#7101) * [BREAKING] Refactor API for gammaCorrection, toneMapping and Fog settings * lint --------- Co-authored-by: Martin Valigursky --- examples/assets/scripts/misc/camera-frame.mjs | 51 +--------- .../examples/animation/locomotion.example.mjs | 4 +- .../examples/compute/histogram.example.mjs | 6 +- .../examples/compute/particles.example.mjs | 5 +- .../examples/compute/texture-gen.example.mjs | 5 +- .../examples/graphics/area-lights.example.mjs | 6 +- .../graphics/asset-viewer.example.mjs | 5 +- .../graphics/clustered-lighting.example.mjs | 10 +- .../clustered-omni-shadows.example.mjs | 6 +- .../contact-hardening-shadows.example.mjs | 4 +- .../examples/graphics/dispersion.example.mjs | 4 +- .../examples/graphics/grab-pass.example.mjs | 5 +- .../examples/graphics/ground-fog.example.mjs | 4 +- .../graphics/instancing-basic.example.mjs | 7 +- .../graphics/instancing-custom.example.mjs | 5 +- .../graphics/instancing-glb.example.mjs | 4 +- .../graphics/instancing-gooch.example.mjs | 7 +- .../graphics/light-physical-units.example.mjs | 4 +- .../graphics/material-anisotropic.example.mjs | 5 +- .../graphics/material-clear-coat.example.mjs | 5 +- .../graphics/material-physical.example.mjs | 5 +- .../material-translucent-specular.example.mjs | 5 +- .../material-transparency.example.mjs | 5 +- .../examples/graphics/mesh-decals.example.mjs | 10 +- .../graphics/multi-render-targets.example.mjs | 2 +- .../examples/graphics/multi-view.example.mjs | 10 +- .../graphics/normals-and-tangents.example.mjs | 5 +- .../examples/graphics/paint-mesh.example.mjs | 7 +- .../src/examples/graphics/portal.example.mjs | 4 +- .../graphics/reflection-cubemap.example.mjs | 10 +- .../graphics/reflection-planar.example.mjs | 9 +- .../graphics/render-asset.example.mjs | 4 +- .../graphics/render-to-texture.example.mjs | 6 +- .../graphics/shader-compile.example.mjs | 6 +- .../graphics/shader-hatch.example.mjs | 10 +- .../graphics/shadow-cascades.example.mjs | 4 +- .../src/examples/graphics/sky.example.mjs | 10 +- .../graphics/texture-basis.example.mjs | 4 +- .../src/examples/input/gamepad.example.mjs | 4 +- .../src/examples/input/keyboard.example.mjs | 4 +- examples/src/examples/input/mouse.example.mjs | 4 +- .../examples/loaders/gltf-export.example.mjs | 4 +- .../examples/loaders/gsplat-many.example.mjs | 5 +- .../src/examples/loaders/gsplat.example.mjs | 5 +- .../examples/loaders/usdz-export.example.mjs | 4 +- package-lock.json | 4 +- src/core/debug.js | 2 +- src/deprecated/deprecated.js | 67 +++++++------ .../render-passes/render-pass-camera-frame.js | 15 +-- src/framework/app-base.js | 4 +- src/framework/components/camera/component.js | 78 ++++++++++++--- src/framework/components/camera/system.js | 8 +- src/framework/lightmapper/lightmapper.js | 14 +-- src/index.js | 2 +- ...ring-params.js => camera-shader-params.js} | 94 +++---------------- src/scene/camera.js | 16 +++- src/scene/fog-params.js | 56 +++++++++++ .../gsplat/gsplat-compressed-material.js | 4 +- src/scene/gsplat/gsplat-material.js | 4 +- src/scene/materials/lit-material.js | 2 +- src/scene/materials/material.js | 4 +- src/scene/materials/shader-material.js | 6 +- .../standard-material-options-builder.js | 18 ++-- src/scene/materials/standard-material.js | 4 +- src/scene/mesh-instance.js | 12 +-- .../particle-system/particle-material.js | 8 +- src/scene/renderer/forward-renderer.js | 31 +++--- src/scene/renderer/shadow-renderer.js | 13 +-- src/scene/scene.js | 26 +++-- src/scene/shader-lib/program-library.js | 6 +- src/scene/skybox/sky-mesh.js | 6 +- 71 files changed, 393 insertions(+), 409 deletions(-) rename src/scene/{renderer/rendering-params.js => camera-shader-params.js} (55%) create mode 100644 src/scene/fog-params.js diff --git a/examples/assets/scripts/misc/camera-frame.mjs b/examples/assets/scripts/misc/camera-frame.mjs index 59beb2e5996..494982fefc0 100644 --- a/examples/assets/scripts/misc/camera-frame.mjs +++ b/examples/assets/scripts/misc/camera-frame.mjs @@ -4,21 +4,11 @@ import { Script, Color, math, - RenderingParams, CameraFrameOptions, RenderPassCameraFrame, - FOG_NONE, SSAOTYPE_NONE } from 'playcanvas'; -/** @enum {string} */ -const FogType = { - NONE: 'none', // FOG_NONE - LINEAR: 'linear', // FOG_LINEAR - EXP: 'exp', // FOG_EXP - EXP2: 'exp2' // FOG_EXP2 -}; - /** @enum {number} */ const ToneMapping = { LINEAR: 0, // TONEMAP_LINEAR @@ -98,32 +88,6 @@ class Rendering { * @step 0.001 */ sharpness = 0.0; - - /** - * @attribute - * @type {FogType} - */ - fog = FogType.NONE; - - /** - * @attribute - */ - fogColor = new Color(1, 1, 1, 1); - - /** - * @attribute - */ - fogStart = 0; - - /** - * @attribute - */ - fogEnd = 100; - - /** - * @attribute - */ - fogDensity = 0.01; } /** @interface */ @@ -332,8 +296,6 @@ class CameraFrame extends Script { options = new CameraFrameOptions(); - renderingParams = new RenderingParams(); - initialize() { this.updateOptions(); @@ -354,8 +316,6 @@ class CameraFrame extends Script { createRenderPass() { const cameraComponent = this.entity.camera; - cameraComponent.rendering = this.renderingParams; - this.renderPassCamera = new RenderPassCameraFrame(this.app, cameraComponent, this.options); cameraComponent.renderPasses = [this.renderPassCamera]; } @@ -388,21 +348,12 @@ class CameraFrame extends Script { postUpdate(dt) { const cameraComponent = this.entity.camera; - const { options, renderPassCamera, renderingParams, rendering, bloom, grading, vignette, fringing, taa, ssao } = this; + const { options, renderPassCamera, rendering, bloom, grading, vignette, fringing, taa, ssao } = this; // options that can cause the passes to be re-created this.updateOptions(); renderPassCamera.update(options); - // renderingParams - renderingParams.fog = rendering.fog; - if (renderingParams.fog !== FOG_NONE) { - renderingParams.fogColor.copy(rendering.fogColor); - renderingParams.fogStart = rendering.fogStart; - renderingParams.fogEnd = rendering.fogEnd; - renderingParams.fogDensity = rendering.fogDensity; - } - // update parameters of individual render passes const { composePass, bloomPass, ssaoPass } = renderPassCamera; diff --git a/examples/src/examples/animation/locomotion.example.mjs b/examples/src/examples/animation/locomotion.example.mjs index 545910d2569..6a87adb94d6 100644 --- a/examples/src/examples/animation/locomotion.example.mjs +++ b/examples/src/examples/animation/locomotion.example.mjs @@ -85,13 +85,13 @@ assetListLoader.load(() => { app.scene.skyboxMip = 2; app.scene.skyboxIntensity = 0.7; app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; // Create an Entity with a camera component const cameraEntity = new pc.Entity(); cameraEntity.name = 'Camera'; cameraEntity.addComponent('camera', { - clearColor: new pc.Color(0.1, 0.15, 0.2) + clearColor: new pc.Color(0.1, 0.15, 0.2), + toneMapping: pc.TONEMAP_ACES }); cameraEntity.translateLocal(0.5, 3, 8); diff --git a/examples/src/examples/compute/histogram.example.mjs b/examples/src/examples/compute/histogram.example.mjs index 518d29783f5..9b7e062bfc8 100644 --- a/examples/src/examples/compute/histogram.example.mjs +++ b/examples/src/examples/compute/histogram.example.mjs @@ -57,8 +57,6 @@ app.on('destroy', () => { const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets); assetListLoader.load(() => { - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; // setup skydome app.scene.skyboxMip = 2; @@ -67,7 +65,9 @@ assetListLoader.load(() => { // create camera entity const camera = new pc.Entity('camera'); - camera.addComponent('camera'); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); app.root.addChild(camera); camera.setPosition(0, 0, 5); diff --git a/examples/src/examples/compute/particles.example.mjs b/examples/src/examples/compute/particles.example.mjs index 87534a0e6d5..591a8b94779 100644 --- a/examples/src/examples/compute/particles.example.mjs +++ b/examples/src/examples/compute/particles.example.mjs @@ -51,14 +51,15 @@ app.on('destroy', () => { const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets); assetListLoader.load(() => { // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 2; app.scene.skyboxIntensity = 0.2; app.scene.envAtlas = assets.helipad.resource; // create camera entity const cameraEntity = new pc.Entity('camera'); - cameraEntity.addComponent('camera'); + cameraEntity.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); app.root.addChild(cameraEntity); cameraEntity.setPosition(-150, -60, 190); diff --git a/examples/src/examples/compute/texture-gen.example.mjs b/examples/src/examples/compute/texture-gen.example.mjs index 7eda16656a0..41211c180e5 100644 --- a/examples/src/examples/compute/texture-gen.example.mjs +++ b/examples/src/examples/compute/texture-gen.example.mjs @@ -54,8 +54,6 @@ app.on('destroy', () => { const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets); assetListLoader.load(() => { - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; // setup skydome app.scene.skyboxMip = 1; @@ -65,7 +63,8 @@ assetListLoader.load(() => { // create camera entity const camera = new pc.Entity('camera'); camera.addComponent('camera', { - clearColor: new pc.Color(0.5, 0.6, 0.9) + clearColor: new pc.Color(0.5, 0.6, 0.9), + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(camera); camera.setPosition(0.6, 0, 5); diff --git a/examples/src/examples/graphics/area-lights.example.mjs b/examples/src/examples/graphics/area-lights.example.mjs index 26f45a9e100..faa6c60455d 100644 --- a/examples/src/examples/graphics/area-lights.example.mjs +++ b/examples/src/examples/graphics/area-lights.example.mjs @@ -183,9 +183,6 @@ assetListLoader.load(() => { const luts = assets.luts.resource; app.setAreaLightLuts(luts.LTC_MAT_1, luts.LTC_MAT_2); - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // setup skydome app.scene.skyboxMip = 1; // use top mipmap level of cubemap (full resolution) app.scene.skyboxIntensity = 0.4; // make it darker @@ -204,7 +201,8 @@ assetListLoader.load(() => { camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.2, 0.2), fov: 60, - farClip: 100000 + farClip: 100000, + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(camera); camera.setLocalPosition(0, 2.5, 12); diff --git a/examples/src/examples/graphics/asset-viewer.example.mjs b/examples/src/examples/graphics/asset-viewer.example.mjs index 5452ef37f86..e84aad07346 100644 --- a/examples/src/examples/graphics/asset-viewer.example.mjs +++ b/examples/src/examples/graphics/asset-viewer.example.mjs @@ -165,7 +165,9 @@ assetListLoader.load(() => { // Create an Entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera', {}); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_NEUTRAL + }); camera.setLocalPosition(0, 55, 160); camera.camera.requestSceneColorMap(true); @@ -195,7 +197,6 @@ assetListLoader.load(() => { app.root.addChild(directionalLight); app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_NEUTRAL; app.scene.skyboxMip = 1; app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, 70, 0); app.scene.skyboxIntensity = 1.5; diff --git a/examples/src/examples/graphics/clustered-lighting.example.mjs b/examples/src/examples/graphics/clustered-lighting.example.mjs index 75b770b733e..69989fae006 100644 --- a/examples/src/examples/graphics/clustered-lighting.example.mjs +++ b/examples/src/examples/graphics/clustered-lighting.example.mjs @@ -53,10 +53,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - // if the device renders in HDR mode, disable tone mapping to output HDR values without any processing - app.scene.rendering.toneMapping = device.isHdr ? pc.TONEMAP_NONE : pc.TONEMAP_ACES; - app.scene.rendering.gammaCorrection = pc.GAMMA_SRGB; - /** @type {Array} */ const pointLightList = []; /** @type {Array} */ @@ -196,7 +192,11 @@ assetListLoader.load(() => { camera.addComponent('camera', { clearColor: new pc.Color(0.05, 0.05, 0.05), farClip: 500, - nearClip: 0.1 + nearClip: 0.1, + + // if the device renders in HDR mode, disable tone mapping to output HDR values without any processing + toneMapping: device.isHdr ? pc.TONEMAP_NONE : pc.TONEMAP_ACES, + gammaCorrection: pc.GAMMA_SRGB }); camera.setLocalPosition(140, 140, 140); camera.lookAt(new pc.Vec3(0, 40, 0)); diff --git a/examples/src/examples/graphics/clustered-omni-shadows.example.mjs b/examples/src/examples/graphics/clustered-omni-shadows.example.mjs index a829aa973e4..f9ce3482bda 100644 --- a/examples/src/examples/graphics/clustered-omni-shadows.example.mjs +++ b/examples/src/examples/graphics/clustered-omni-shadows.example.mjs @@ -68,9 +68,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - data.set('settings', { shadowAtlasResolution: 1300, // shadow map resolution storing all shadows shadowType: pc.SHADOW_PCF3, // shadow filter type @@ -225,7 +222,8 @@ assetListLoader.load(() => { camera.addComponent('camera', { fov: 80, clearColor: new pc.Color(0.1, 0.1, 0.1), - farClip: 1500 + farClip: 1500, + toneMapping: pc.TONEMAP_ACES }); // and position it in the world diff --git a/examples/src/examples/graphics/contact-hardening-shadows.example.mjs b/examples/src/examples/graphics/contact-hardening-shadows.example.mjs index 4ff969aa6c8..5002d5d72a4 100644 --- a/examples/src/examples/graphics/contact-hardening-shadows.example.mjs +++ b/examples/src/examples/graphics/contact-hardening-shadows.example.mjs @@ -78,7 +78,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; app.scene.ambientLight.set(0, 0, 0); app.scene.ambientLuminance = 0; @@ -235,7 +234,8 @@ assetListLoader.load(() => { // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.4, 0.45, 0.5) + clearColor: new pc.Color(0.4, 0.45, 0.5), + toneMapping: pc.TONEMAP_ACES }); camera.setLocalPosition(0, 5, 11); diff --git a/examples/src/examples/graphics/dispersion.example.mjs b/examples/src/examples/graphics/dispersion.example.mjs index 9644a39c38c..f431eb0dc79 100644 --- a/examples/src/examples/graphics/dispersion.example.mjs +++ b/examples/src/examples/graphics/dispersion.example.mjs @@ -59,7 +59,6 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; // get the instance of the cube it set up with render component and add it to scene @@ -71,7 +70,8 @@ assetListLoader.load(() => { camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.2, 0.2), nearClip: 0.01, - farClip: 2 + farClip: 2, + toneMapping: pc.TONEMAP_ACES }); // the color grab pass is needed diff --git a/examples/src/examples/graphics/grab-pass.example.mjs b/examples/src/examples/graphics/grab-pass.example.mjs index 29de6b087aa..556836491e0 100644 --- a/examples/src/examples/graphics/grab-pass.example.mjs +++ b/examples/src/examples/graphics/grab-pass.example.mjs @@ -56,8 +56,6 @@ assetListLoader.load(() => { app.scene.exposure = 2; app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // Depth layer is where the framebuffer is copied to a texture to be used in the following layers. // Move the depth layer to take place after World and Skydome layers, to capture both of them. const depthLayer = app.scene.layers.getLayerById(pc.LAYERID_DEPTH); @@ -115,7 +113,8 @@ assetListLoader.load(() => { // Create the camera, which renders entities const camera = new pc.Entity('SceneCamera'); camera.addComponent('camera', { - clearColor: new pc.Color(0.2, 0.2, 0.2) + clearColor: new pc.Color(0.2, 0.2, 0.2), + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(camera); camera.setLocalPosition(0, 10, 20); diff --git a/examples/src/examples/graphics/ground-fog.example.mjs b/examples/src/examples/graphics/ground-fog.example.mjs index 210c342b35e..cb0099f90a2 100644 --- a/examples/src/examples/graphics/ground-fog.example.mjs +++ b/examples/src/examples/graphics/ground-fog.example.mjs @@ -66,7 +66,6 @@ assetListLoader.load(() => { app.scene.skyboxMip = 3; app.scene.envAtlas = assets.helipad.resource; app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, -70, 0); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; // disable skydome rendering const skyLayer = app.scene.layers.getLayerById(pc.LAYERID_SKYBOX); @@ -84,7 +83,8 @@ assetListLoader.load(() => { const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(150 / 255, 213 / 255, 63 / 255), - farClip: 1000 + farClip: 1000, + toneMapping: pc.TONEMAP_ACES }); // and position it in the world diff --git a/examples/src/examples/graphics/instancing-basic.example.mjs b/examples/src/examples/graphics/instancing-basic.example.mjs index c691ad214e1..a0847ea17ce 100644 --- a/examples/src/examples/graphics/instancing-basic.example.mjs +++ b/examples/src/examples/graphics/instancing-basic.example.mjs @@ -52,14 +52,13 @@ assetListLoader.load(() => { app.scene.exposure = 0.3; app.scene.envAtlas = assets.helipad.resource; - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - app.scene.ambientLight = new pc.Color(0.1, 0.1, 0.1); // Create an Entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera', {}); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); app.root.addChild(camera); // Move the camera back to see the cubes diff --git a/examples/src/examples/graphics/instancing-custom.example.mjs b/examples/src/examples/graphics/instancing-custom.example.mjs index f55268838f1..6f9f183d0e1 100644 --- a/examples/src/examples/graphics/instancing-custom.example.mjs +++ b/examples/src/examples/graphics/instancing-custom.example.mjs @@ -53,12 +53,13 @@ assetListLoader.load(() => { app.scene.envAtlas = assets.helipad.resource; // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.ambientLight = new pc.Color(0.1, 0.1, 0.1); // Create an Entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera', {}); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); app.root.addChild(camera); // create static vertex buffer containing the instancing data diff --git a/examples/src/examples/graphics/instancing-glb.example.mjs b/examples/src/examples/graphics/instancing-glb.example.mjs index 30925dc8405..0757069b789 100644 --- a/examples/src/examples/graphics/instancing-glb.example.mjs +++ b/examples/src/examples/graphics/instancing-glb.example.mjs @@ -68,7 +68,8 @@ assetListLoader.load(() => { const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.1, 0.1), - farClip: 100 + farClip: 100, + toneMapping: pc.TONEMAP_ACES }); camera.translate(25, 15, 25); @@ -89,7 +90,6 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; }); diff --git a/examples/src/examples/graphics/instancing-gooch.example.mjs b/examples/src/examples/graphics/instancing-gooch.example.mjs index b19d33f5af1..66bab6e0405 100644 --- a/examples/src/examples/graphics/instancing-gooch.example.mjs +++ b/examples/src/examples/graphics/instancing-gooch.example.mjs @@ -78,12 +78,11 @@ assetListLoader.load(() => { app.scene.skyboxMip = 2; app.scene.envAtlas = assets.helipad.resource; - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // Create an Entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera', {}); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); app.root.addChild(camera); // number of instanced trees to render diff --git a/examples/src/examples/graphics/light-physical-units.example.mjs b/examples/src/examples/graphics/light-physical-units.example.mjs index d0a58a777c2..425bf429ad6 100644 --- a/examples/src/examples/graphics/light-physical-units.example.mjs +++ b/examples/src/examples/graphics/light-physical-units.example.mjs @@ -62,7 +62,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; app.scene.ambientLight.set(1, 0, 0); app.scene.ambientLuminance = 20000; @@ -144,7 +143,8 @@ assetListLoader.load(() => { aperture: 16.0, shutter: 1000, sensitivity: 1000, - animate: false + animate: false, + toneMapping: pc.TONEMAP_ACES }, scene: { physicalUnits: true, diff --git a/examples/src/examples/graphics/material-anisotropic.example.mjs b/examples/src/examples/graphics/material-anisotropic.example.mjs index d5ef9bc1349..9f335a730f2 100644 --- a/examples/src/examples/graphics/material-anisotropic.example.mjs +++ b/examples/src/examples/graphics/material-anisotropic.example.mjs @@ -54,13 +54,14 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; app.scene.envAtlas = assets.helipad.resource; // Create an entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera'); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); camera.translate(0, 6, 6); camera.rotate(-48, 0, 0); app.root.addChild(camera); diff --git a/examples/src/examples/graphics/material-clear-coat.example.mjs b/examples/src/examples/graphics/material-clear-coat.example.mjs index 3fd34ed0415..bb3359e0f91 100644 --- a/examples/src/examples/graphics/material-clear-coat.example.mjs +++ b/examples/src/examples/graphics/material-clear-coat.example.mjs @@ -51,13 +51,14 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.envAtlas = assets.helipad.resource; app.scene.skyboxMip = 1; // Create an entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera'); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); camera.translate(0, 0, 3); app.root.addChild(camera); diff --git a/examples/src/examples/graphics/material-physical.example.mjs b/examples/src/examples/graphics/material-physical.example.mjs index cb9e6ba05c0..f670410a2cf 100644 --- a/examples/src/examples/graphics/material-physical.example.mjs +++ b/examples/src/examples/graphics/material-physical.example.mjs @@ -48,12 +48,13 @@ assetListLoader.load(() => { app.start(); app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; // Create an entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera'); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); camera.translate(0, 0, 9); app.root.addChild(camera); diff --git a/examples/src/examples/graphics/material-translucent-specular.example.mjs b/examples/src/examples/graphics/material-translucent-specular.example.mjs index 258cf06b274..0525de81242 100644 --- a/examples/src/examples/graphics/material-translucent-specular.example.mjs +++ b/examples/src/examples/graphics/material-translucent-specular.example.mjs @@ -52,14 +52,15 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.envAtlas = assets.helipad.resource; app.scene.skyboxMip = 1; app.scene.skyboxIntensity = 1; // Create an entity with a camera component const camera = new pc.Entity(); - camera.addComponent('camera'); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); camera.translate(0, 0, 8); camera.rotate(0, 0, 0); app.root.addChild(camera); diff --git a/examples/src/examples/graphics/material-transparency.example.mjs b/examples/src/examples/graphics/material-transparency.example.mjs index 9a45bd8b247..b9c396779ba 100644 --- a/examples/src/examples/graphics/material-transparency.example.mjs +++ b/examples/src/examples/graphics/material-transparency.example.mjs @@ -57,12 +57,11 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_LINEAR; - // Create an entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: pc.Color.BLACK + clearColor: pc.Color.BLACK, + toneMapping: pc.TONEMAP_LINEAR }); camera.translate(0, -0.5, 14); camera.rotate(0, 0, 0); diff --git a/examples/src/examples/graphics/mesh-decals.example.mjs b/examples/src/examples/graphics/mesh-decals.example.mjs index 3e77ce57528..e6df95f26d0 100644 --- a/examples/src/examples/graphics/mesh-decals.example.mjs +++ b/examples/src/examples/graphics/mesh-decals.example.mjs @@ -46,10 +46,6 @@ assetListLoader.load(() => { app.scene.ambientLight = new pc.Color(0.2, 0.2, 0.2); - // if the device renders in HDR mode, disable tone mapping to output HDR values without any processing - app.scene.rendering.toneMapping = device.isHdr ? pc.TONEMAP_NONE : pc.TONEMAP_ACES; - app.scene.rendering.gammaCorrection = pc.GAMMA_SRGB; - // create material for the plane const planeMaterial = new pc.StandardMaterial(); planeMaterial.gloss = 0.6; @@ -86,7 +82,11 @@ assetListLoader.load(() => { // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.2, 0.2, 0.2) + clearColor: new pc.Color(0.2, 0.2, 0.2), + + // if the device renders in HDR mode, disable tone mapping to output HDR values without any processing + toneMapping: device.isHdr ? pc.TONEMAP_NONE : pc.TONEMAP_ACES, + gammaCorrection: pc.GAMMA_SRGB }); // Add the camera to the hierarchy diff --git a/examples/src/examples/graphics/multi-render-targets.example.mjs b/examples/src/examples/graphics/multi-render-targets.example.mjs index d7afc8e8f4c..485201df84f 100644 --- a/examples/src/examples/graphics/multi-render-targets.example.mjs +++ b/examples/src/examples/graphics/multi-render-targets.example.mjs @@ -66,7 +66,6 @@ assetListLoader.load(() => { // setup skydome app.scene.envAtlas = assets.helipad.resource; app.scene.skyboxMip = 1; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; // get existing layers const worldLayer = app.scene.layers.getLayerByName('World'); @@ -118,6 +117,7 @@ assetListLoader.load(() => { textureCamera.addComponent('camera', { layers: [rtLayer.id], farClip: 500, + toneMapping: pc.TONEMAP_ACES, // set the priority of textureCamera to lower number than the priority of the main camera (which is at default 0) // to make it rendered first each frame diff --git a/examples/src/examples/graphics/multi-view.example.mjs b/examples/src/examples/graphics/multi-view.example.mjs index efdd77ccad5..051f0268ccc 100644 --- a/examples/src/examples/graphics/multi-view.example.mjs +++ b/examples/src/examples/graphics/multi-view.example.mjs @@ -92,7 +92,8 @@ assetListLoader.load(() => { const cameraLeft = new pc.Entity('LeftCamera'); cameraLeft.addComponent('camera', { farClip: 500, - rect: new pc.Vec4(0, 0, 0.5, 0.5) + rect: new pc.Vec4(0, 0, 0.5, 0.5), + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(cameraLeft); @@ -104,7 +105,8 @@ assetListLoader.load(() => { farClip: 500, rect: new pc.Vec4(0.5, 0, 0.5, 0.5), projection: pc.PROJECTION_ORTHOGRAPHIC, - orthoHeight: 150 + orthoHeight: 150, + toneMapping: pc.TONEMAP_ACES }); cameraRight.translate(0, 150, 0); cameraRight.lookAt(pc.Vec3.ZERO, pc.Vec3.RIGHT); @@ -114,7 +116,8 @@ assetListLoader.load(() => { const cameraTop = new pc.Entity('TopCamera'); cameraTop.addComponent('camera', { farClip: 500, - rect: new pc.Vec4(0, 0.5, 1, 0.5) + rect: new pc.Vec4(0, 0.5, 1, 0.5), + toneMapping: pc.TONEMAP_ACES }); cameraTop.translate(-100, 75, 100); cameraTop.lookAt(0, 7, 0); @@ -168,7 +171,6 @@ assetListLoader.load(() => { // set skybox - this DDS file was 'prefiltered' in the PlayCanvas Editor and then downloaded. app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; // handle HUD changes - update the debug mode for the top and right cameras diff --git a/examples/src/examples/graphics/normals-and-tangents.example.mjs b/examples/src/examples/graphics/normals-and-tangents.example.mjs index 419749467e3..bf6780eecf6 100644 --- a/examples/src/examples/graphics/normals-and-tangents.example.mjs +++ b/examples/src/examples/graphics/normals-and-tangents.example.mjs @@ -59,7 +59,6 @@ assetListLoader.load(() => { // Setup skydome app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, 70, 0); app.scene.skyboxIntensity = 1.5; @@ -77,7 +76,9 @@ assetListLoader.load(() => { // Create a camera with an orbit camera script const camera = new pc.Entity(); - camera.addComponent('camera'); + camera.addComponent('camera', { + toneMapping: pc.TONEMAP_ACES + }); camera.addComponent('script'); camera.script.create('orbitCamera', { attributes: { diff --git a/examples/src/examples/graphics/paint-mesh.example.mjs b/examples/src/examples/graphics/paint-mesh.example.mjs index f3e25a3814c..a12e3f7244d 100644 --- a/examples/src/examples/graphics/paint-mesh.example.mjs +++ b/examples/src/examples/graphics/paint-mesh.example.mjs @@ -51,7 +51,6 @@ assetListLoader.load(() => { app.start(); app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxIntensity = 1; app.scene.skyboxMip = 2; @@ -103,14 +102,16 @@ assetListLoader.load(() => { clearColorBuffer: false, layers: [decalLayer.id], renderTarget: renderTarget, - priority: -1 + priority: -1, + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(decalCamera); // Create main camera, which renders entities in world layer - this is where we show mesh with decals const camera = new pc.Entity('MainCamera'); camera.addComponent('camera', { - clearColor: new pc.Color(0.1, 0.1, 0.1, 1) + clearColor: new pc.Color(0.1, 0.1, 0.1, 1), + toneMapping: pc.TONEMAP_ACES }); camera.translate(20, 10, 40); camera.lookAt(new pc.Vec3(0, -7, 0)); diff --git a/examples/src/examples/graphics/portal.example.mjs b/examples/src/examples/graphics/portal.example.mjs index c0cb14f0cf7..6ec2b42f93e 100644 --- a/examples/src/examples/graphics/portal.example.mjs +++ b/examples/src/examples/graphics/portal.example.mjs @@ -58,7 +58,6 @@ assetListLoader.load(() => { // set skybox - this DDS file was 'prefiltered' in the PlayCanvas Editor and then downloaded. app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; app.scene.skyboxIntensity = 0.7; @@ -151,7 +150,8 @@ assetListLoader.load(() => { // this camera renders both world and portal layers const camera = new pc.Entity(); camera.addComponent('camera', { - layers: [worldLayer.id, portalLayer.id, skyboxLayer.id, uiLayer.id] + layers: [worldLayer.id, portalLayer.id, skyboxLayer.id, uiLayer.id], + toneMapping: pc.TONEMAP_ACES }); camera.setLocalPosition(7, 5.5, 7.1); camera.setLocalEulerAngles(-27, 45, 0); diff --git a/examples/src/examples/graphics/reflection-cubemap.example.mjs b/examples/src/examples/graphics/reflection-cubemap.example.mjs index 4f6fad84b7f..ca7c59a43fd 100644 --- a/examples/src/examples/graphics/reflection-cubemap.example.mjs +++ b/examples/src/examples/graphics/reflection-cubemap.example.mjs @@ -52,9 +52,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // setup skydome app.scene.envAtlas = assets.helipad.resource; app.scene.skyboxMip = 0; // use top mipmap level of cubemap (full resolution) @@ -152,7 +149,9 @@ assetListLoader.load(() => { priority: -1, // disable as this is not a camera that renders cube map but only a container for properties for cube map rendering - enabled: false + enabled: false, + + toneMapping: pc.TONEMAP_ACES }); // add cubemapRenderer script component which takes care of rendering dynamic cubemap @@ -199,7 +198,8 @@ assetListLoader.load(() => { const camera = new pc.Entity('MainCamera'); camera.addComponent('camera', { fov: 60, - layers: [worldLayer.id, excludedLayer.id, skyboxLayer.id, immediateLayer.id, uiLayer.id] + layers: [worldLayer.id, excludedLayer.id, skyboxLayer.id, immediateLayer.id, uiLayer.id], + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(camera); diff --git a/examples/src/examples/graphics/reflection-planar.example.mjs b/examples/src/examples/graphics/reflection-planar.example.mjs index 5ef734f8150..93e279e6c55 100644 --- a/examples/src/examples/graphics/reflection-planar.example.mjs +++ b/examples/src/examples/graphics/reflection-planar.example.mjs @@ -49,9 +49,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // setup skydome app.scene.envAtlas = assets.envatlas.resource; app.scene.skyboxMip = 1; @@ -146,7 +143,8 @@ assetListLoader.load(() => { const camera = new pc.Entity('MainCamera'); camera.addComponent('camera', { fov: 60, - layers: [worldLayer.id, excludedLayer.id, skyboxLayer.id, uiLayer.id] + layers: [worldLayer.id, excludedLayer.id, skyboxLayer.id, uiLayer.id], + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(camera); @@ -155,7 +153,8 @@ assetListLoader.load(() => { reflectionCamera.addComponent('camera', { fov: 60, layers: [worldLayer.id, skyboxLayer.id], - priority: -1 // render reflections before the main camera + priority: -1, // render reflections before the main camera + toneMapping: pc.TONEMAP_ACES }); // add planarRenderer script which renders the reflection texture diff --git a/examples/src/examples/graphics/render-asset.example.mjs b/examples/src/examples/graphics/render-asset.example.mjs index 4b4f30e3653..5e5530b1a86 100644 --- a/examples/src/examples/graphics/render-asset.example.mjs +++ b/examples/src/examples/graphics/render-asset.example.mjs @@ -71,7 +71,8 @@ assetListLoader.load(() => { const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.1, 0.1), - farClip: 100 + farClip: 100, + toneMapping: pc.TONEMAP_ACES }); camera.translate(-20, 15, 20); camera.lookAt(0, 7, 0); @@ -79,7 +80,6 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; // spin the meshes diff --git a/examples/src/examples/graphics/render-to-texture.example.mjs b/examples/src/examples/graphics/render-to-texture.example.mjs index 8ea4e0cd245..7e7e490449f 100644 --- a/examples/src/examples/graphics/render-to-texture.example.mjs +++ b/examples/src/examples/graphics/render-to-texture.example.mjs @@ -189,7 +189,8 @@ assetListLoader.load(() => { const camera = new pc.Entity('Camera'); camera.addComponent('camera', { fov: 100, - layers: [worldLayer.id, excludedLayer.id, skyboxLayer.id, uiLayer.id] + layers: [worldLayer.id, excludedLayer.id, skyboxLayer.id, uiLayer.id], + toneMapping: pc.TONEMAP_ACES }); camera.translate(0, 9, 15); camera.lookAt(1, 4, 0); @@ -212,6 +213,7 @@ assetListLoader.load(() => { const textureCamera = new pc.Entity('TextureCamera'); textureCamera.addComponent('camera', { layers: [worldLayer.id, skyboxLayer.id], + toneMapping: pc.TONEMAP_ACES, // set the priority of textureCamera to lower number than the priority of the main camera (which is at default 0) // to make it rendered first each frame @@ -258,8 +260,6 @@ assetListLoader.load(() => { app.scene.skyboxMip = 0; app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // update things each frame let time = 0; let switchTime = 0; diff --git a/examples/src/examples/graphics/shader-compile.example.mjs b/examples/src/examples/graphics/shader-compile.example.mjs index 70ad5258303..b94fc5a3f5c 100644 --- a/examples/src/examples/graphics/shader-compile.example.mjs +++ b/examples/src/examples/graphics/shader-compile.example.mjs @@ -114,9 +114,6 @@ assetListLoader.load(() => { const luts = assets.luts.resource; app.setAreaLightLuts(luts.LTC_MAT_1, luts.LTC_MAT_2); - // set up some general scene rendering properties - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // setup skydome app.scene.skyboxMip = 1; app.scene.skyboxIntensity = 0.7; @@ -130,7 +127,8 @@ assetListLoader.load(() => { camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.2, 0.2), fov: 60, - farClip: 100000 + farClip: 100000, + toneMapping: pc.TONEMAP_ACES }); app.root.addChild(camera); camera.setLocalPosition(0, 15, 40); diff --git a/examples/src/examples/graphics/shader-hatch.example.mjs b/examples/src/examples/graphics/shader-hatch.example.mjs index ef8a4f628f3..2a14c08f107 100644 --- a/examples/src/examples/graphics/shader-hatch.example.mjs +++ b/examples/src/examples/graphics/shader-hatch.example.mjs @@ -204,14 +204,14 @@ assetListLoader.load(() => { } if (propertyName === 'tonemapping') { // set up selected tone-mapping - app.scene.rendering.toneMapping = value; + camera.camera.toneMapping = value; } if (propertyName === 'fog') { // turn on/off fog and set up its properties - app.scene.rendering.fog = value ? pc.FOG_LINEAR : pc.FOG_NONE; - app.scene.rendering.fogColor = new pc.Color(0.8, 0.8, 0.8); - app.scene.rendering.fogStart = 100; - app.scene.rendering.fogEnd = 300; + app.scene.fog.type = value ? pc.FOG_LINEAR : pc.FOG_NONE; + app.scene.fog.color = new pc.Color(0.8, 0.8, 0.8); + app.scene.fog.start = 100; + app.scene.fog.end = 300; } if (propertyName === 'metalness') { materials.forEach((mat) => { diff --git a/examples/src/examples/graphics/shadow-cascades.example.mjs b/examples/src/examples/graphics/shadow-cascades.example.mjs index 153806d72a8..0797500be81 100644 --- a/examples/src/examples/graphics/shadow-cascades.example.mjs +++ b/examples/src/examples/graphics/shadow-cascades.example.mjs @@ -75,7 +75,6 @@ assetListLoader.load(() => { app.scene.skyboxMip = 3; app.scene.envAtlas = assets.helipad.resource; app.scene.skyboxRotation = new pc.Quat().setFromEulerAngles(0, -70, 0); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; // instantiate the terrain /** @type {pc.Entity} */ @@ -121,7 +120,8 @@ assetListLoader.load(() => { const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(0.9, 0.9, 0.9), - farClip: 1000 + farClip: 1000, + toneMapping: pc.TONEMAP_ACES }); // and position it in the world diff --git a/examples/src/examples/graphics/sky.example.mjs b/examples/src/examples/graphics/sky.example.mjs index d0e7239dc11..a077c3ff024 100644 --- a/examples/src/examples/graphics/sky.example.mjs +++ b/examples/src/examples/graphics/sky.example.mjs @@ -60,10 +60,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - // if the device renders in HDR mode, disable tone mapping to output HDR values without any processing - app.scene.rendering.toneMapping = device.isHdr ? pc.TONEMAP_NONE : pc.TONEMAP_ACES; - app.scene.rendering.gammaCorrection = pc.GAMMA_SRGB; - // add an instance of the statue const statueEntity = assets.statue.resource.instantiateRenderEntity(); app.root.addChild(statueEntity); @@ -72,7 +68,11 @@ assetListLoader.load(() => { const cameraEntity = new pc.Entity(); cameraEntity.addComponent('camera', { farClip: 500, - fov: 60 + fov: 60, + + // if the device renders in HDR mode, disable tone mapping to output HDR values without any processing + toneMapping: device.isHdr ? pc.TONEMAP_NONE : pc.TONEMAP_ACES, + gammaCorrection: pc.GAMMA_SRGB }); // add orbit camera script with a mouse and a touch support diff --git a/examples/src/examples/graphics/texture-basis.example.mjs b/examples/src/examples/graphics/texture-basis.example.mjs index 164e488ce30..dbc12af2b60 100644 --- a/examples/src/examples/graphics/texture-basis.example.mjs +++ b/examples/src/examples/graphics/texture-basis.example.mjs @@ -63,7 +63,6 @@ assetListLoader.load(() => { app.start(); // Set skybox - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; app.scene.skyboxIntensity = 1.4; app.scene.envAtlas = assets.helipad.resource; @@ -109,7 +108,8 @@ assetListLoader.load(() => { // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.4, 0.45, 0.5) + clearColor: new pc.Color(0.4, 0.45, 0.5), + toneMapping: pc.TONEMAP_ACES }); // Adjust the camera position diff --git a/examples/src/examples/input/gamepad.example.mjs b/examples/src/examples/input/gamepad.example.mjs index dfffb81c2ff..b85fe31f977 100644 --- a/examples/src/examples/input/gamepad.example.mjs +++ b/examples/src/examples/input/gamepad.example.mjs @@ -52,14 +52,14 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.exposure = 1.6; app.scene.skyboxMip = 1; // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.4, 0.45, 0.5) + clearColor: new pc.Color(0.4, 0.45, 0.5), + toneMapping: pc.TONEMAP_ACES }); camera.translate(0, 7, 25); app.root.addChild(camera); diff --git a/examples/src/examples/input/keyboard.example.mjs b/examples/src/examples/input/keyboard.example.mjs index 660c3ab033f..8e0305ebc87 100644 --- a/examples/src/examples/input/keyboard.example.mjs +++ b/examples/src/examples/input/keyboard.example.mjs @@ -49,14 +49,14 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.exposure = 1.6; app.scene.skyboxMip = 1; // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.4, 0.45, 0.5) + clearColor: new pc.Color(0.4, 0.45, 0.5), + toneMapping: pc.TONEMAP_ACES }); camera.translate(0, 7, 25); app.root.addChild(camera); diff --git a/examples/src/examples/input/mouse.example.mjs b/examples/src/examples/input/mouse.example.mjs index 7986669a46e..24cd054c849 100644 --- a/examples/src/examples/input/mouse.example.mjs +++ b/examples/src/examples/input/mouse.example.mjs @@ -49,14 +49,14 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.exposure = 1.6; app.scene.skyboxMip = 1; // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.4, 0.45, 0.5) + clearColor: new pc.Color(0.4, 0.45, 0.5), + toneMapping: pc.TONEMAP_ACES }); camera.translate(0, 7, 25); app.root.addChild(camera); diff --git a/examples/src/examples/loaders/gltf-export.example.mjs b/examples/src/examples/loaders/gltf-export.example.mjs index fcfc3dc4f3f..fc61797319e 100644 --- a/examples/src/examples/loaders/gltf-export.example.mjs +++ b/examples/src/examples/loaders/gltf-export.example.mjs @@ -121,7 +121,8 @@ assetListLoader.load(() => { const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.1, 0.1), - farClip: 100 + farClip: 100, + toneMapping: pc.TONEMAP_ACES }); camera.translate(-3, 1, 2); camera.lookAt(0, 0.5, 0); @@ -129,7 +130,6 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; app.scene.exposure = 1.5; diff --git a/examples/src/examples/loaders/gsplat-many.example.mjs b/examples/src/examples/loaders/gsplat-many.example.mjs index eb2dd5e5eb9..8925628c90f 100644 --- a/examples/src/examples/loaders/gsplat-many.example.mjs +++ b/examples/src/examples/loaders/gsplat-many.example.mjs @@ -57,8 +57,6 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // get the instance of the gallery and set up with render component const galleryEntity = assets.gallery.resource.instantiateRenderEntity(); app.root.addChild(galleryEntity); @@ -66,7 +64,8 @@ assetListLoader.load(() => { // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.2, 0.2, 0.2) + clearColor: new pc.Color(0.2, 0.2, 0.2), + toneMapping: pc.TONEMAP_ACES }); camera.setLocalPosition(-3, 1, 2); diff --git a/examples/src/examples/loaders/gsplat.example.mjs b/examples/src/examples/loaders/gsplat.example.mjs index 26cdc8fbd85..86d0c59b867 100644 --- a/examples/src/examples/loaders/gsplat.example.mjs +++ b/examples/src/examples/loaders/gsplat.example.mjs @@ -53,12 +53,11 @@ const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets assetListLoader.load(() => { app.start(); - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; - // Create an Entity with a camera component const camera = new pc.Entity(); camera.addComponent('camera', { - clearColor: new pc.Color(0.2, 0.2, 0.2) + clearColor: new pc.Color(0.2, 0.2, 0.2), + toneMapping: pc.TONEMAP_ACES }); camera.setLocalPosition(2, 1, 1); diff --git a/examples/src/examples/loaders/usdz-export.example.mjs b/examples/src/examples/loaders/usdz-export.example.mjs index 8a7aebe1e21..4ce4cacdf1e 100644 --- a/examples/src/examples/loaders/usdz-export.example.mjs +++ b/examples/src/examples/loaders/usdz-export.example.mjs @@ -67,7 +67,8 @@ assetListLoader.load(() => { const camera = new pc.Entity(); camera.addComponent('camera', { clearColor: new pc.Color(0.2, 0.1, 0.1), - farClip: 100 + farClip: 100, + toneMapping: pc.TONEMAP_ACES }); camera.translate(-3, 1, 2); camera.lookAt(0, 0.5, 0); @@ -75,7 +76,6 @@ assetListLoader.load(() => { // set skybox app.scene.envAtlas = assets.helipad.resource; - app.scene.rendering.toneMapping = pc.TONEMAP_ACES; app.scene.skyboxMip = 1; // a link element, created in the html part of the examples. diff --git a/package-lock.json b/package-lock.json index 4065bfef31d..55ceb5c697b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "playcanvas", - "version": "2.1.0-dev", + "version": "2.3.0-dev", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "playcanvas", - "version": "2.1.0-dev", + "version": "2.3.0-dev", "license": "MIT", "dependencies": { "@types/webxr": "^0.5.16", diff --git a/src/core/debug.js b/src/core/debug.js index 87370921a95..df7fccd4418 100644 --- a/src/core/debug.js +++ b/src/core/debug.js @@ -33,7 +33,7 @@ class Debug { static removed(message) { if (!Debug._loggedMessages.has(message)) { Debug._loggedMessages.add(message); - console.warn(`REMOVED: ${message}`); + console.error(`REMOVED: ${message}`); } } diff --git a/src/deprecated/deprecated.js b/src/deprecated/deprecated.js index 65a006fa671..1084144cf1f 100644 --- a/src/deprecated/deprecated.js +++ b/src/deprecated/deprecated.js @@ -452,80 +452,77 @@ Object.defineProperty(Scene.prototype, 'defaultMaterial', { } }); -Object.defineProperty(Scene.prototype, 'fog', { - set: function (value) { - Debug.deprecated('Scene#fog is deprecated. Use Scene#rendering.fog instead.'); - this.rendering.fog = value; - }, - get: function () { - Debug.deprecated('Scene#fog is deprecated. Use Scene#rendering.fog instead.'); - return this.rendering.fog; - } -}); - Object.defineProperty(Scene.prototype, 'fogColor', { set: function (value) { - Debug.deprecated('Scene#fogColor is deprecated. Use Scene#rendering.fogColor instead.'); - this.rendering.fogColor = value; + Debug.deprecated('Scene#fogColor is deprecated. Use Scene#fog.color instead.'); + this.fog.color = value; }, get: function () { - Debug.deprecated('Scene#fogColor is deprecated. Use Scene#rendering.fogColor instead.'); - return this.rendering.fogColor; + Debug.deprecated('Scene#fogColor is deprecated. Use Scene#fog.color instead.'); + return this.fog.color; } }); Object.defineProperty(Scene.prototype, 'fogEnd', { set: function (value) { - Debug.deprecated('Scene#fogEnd is deprecated. Use Scene#rendering.fogEnd instead.'); - this.rendering.fogEnd = value; + Debug.deprecated('Scene#fogEnd is deprecated. Use Scene#fog.end instead.'); + this.fog.end = value; }, get: function () { - Debug.deprecated('Scene#fogEnd is deprecated. Use Scene#rendering.fogEnd instead.'); - return this.rendering.fogEnd; + Debug.deprecated('Scene#fogEnd is deprecated. Use Scene#fog.end instead.'); + return this.fog.end; } }); Object.defineProperty(Scene.prototype, 'fogStart', { set: function (value) { - Debug.deprecated('Scene#fogStart is deprecated. Use Scene#rendering.fogStart instead.'); - this.rendering.fogStart = value; + Debug.deprecated('Scene#fogStart is deprecated. Use Scene#fog.start instead.'); + this.fog.start = value; }, get: function () { - Debug.deprecated('Scene#fogStart is deprecated. Use Scene#rendering.fogStart instead.'); - return this.rendering.fogStart; + Debug.deprecated('Scene#fogStart is deprecated. Use Scene#fog.start instead.'); + return this.fog.start; } }); Object.defineProperty(Scene.prototype, 'fogDensity', { set: function (value) { - Debug.deprecated('Scene#fogDensity is deprecated. Use Scene#rendering.fogDensity instead.'); - this.rendering.fogDensity = value; + Debug.deprecated('Scene#fogDensity is deprecated. Use Scene#fog.density instead.'); + this.fog.density = value; }, get: function () { - Debug.deprecated('Scene#fogDensity is deprecated. Use Scene#rendering.fogDensity instead.'); - return this.rendering.fogDensity; + Debug.deprecated('Scene#fogDensity is deprecated. Use Scene#fog.density instead.'); + return this.fog.density; } }); Object.defineProperty(Scene.prototype, 'toneMapping', { set: function (value) { - Debug.deprecated('Scene#toneMapping is deprecated. Use Scene#rendering.toneMapping instead.'); - this.rendering.toneMapping = value; + Debug.removed('Scene#toneMapping is removed. Use CameraComponent#toneMapping instead.'); }, get: function () { - Debug.deprecated('Scene#toneMapping is deprecated. Use Scene#rendering.toneMapping instead.'); - return this.rendering.toneMapping; + Debug.removed('Scene#toneMapping is removed. Use CameraComponent#toneMapping instead.'); + return undefined; } }); Object.defineProperty(Scene.prototype, 'gammaCorrection', { set: function (value) { - Debug.deprecated('Scene#gammaCorrection is deprecated. Use Scene#rendering.gammaCorrection instead.'); - this.rendering.gammaCorrection = value; + Debug.removed('Scene#gammaCorrection is removed. Use CameraComponent#gammaCorrection instead.'); + }, + get: function () { + Debug.removed('Scene#gammaCorrection is removed. Use CameraComponent#gammaCorrection instead.'); + return undefined; + } +}); + +Object.defineProperty(Scene.prototype, 'rendering', { + set: function (value) { + Debug.removed('Scene#rendering is removed. Use Scene#fog or CameraComponent#gammaCorrection or CameraComponent#toneMapping instead.'); }, get: function () { - Debug.deprecated('Scene#gammaCorrection is deprecated. Use Scene#rendering.gammaCorrection instead.'); - return this.rendering.gammaCorrection; + Debug.removed('Scene#rendering is removed. Use Scene#fog or CameraComponent#gammaCorrection or CameraComponent#toneMapping instead.'); + return undefined; } }); diff --git a/src/extras/render-passes/render-pass-camera-frame.js b/src/extras/render-passes/render-pass-camera-frame.js index 903e33a536d..5a83d8abb41 100644 --- a/src/extras/render-passes/render-pass-camera-frame.js +++ b/src/extras/render-passes/render-pass-camera-frame.js @@ -14,7 +14,6 @@ import { RenderPassCompose } from './render-pass-compose.js'; import { RenderPassTAA } from './render-pass-taa.js'; import { RenderPassPrepass } from './render-pass-prepass.js'; import { RenderPassSsao } from './render-pass-ssao.js'; -import { RenderingParams } from '../../scene/renderer/rendering-params.js'; export const SSAOTYPE_NONE = 'none'; export const SSAOTYPE_LIGHTING = 'lighting'; @@ -195,17 +194,11 @@ class RenderPassCameraFrame extends RenderPass { this.hdrFormat = device.getRenderableHdrFormat(options.formats, true, options.samples) || PIXELFORMAT_RGBA8; // camera renders in HDR mode (linear output, no tonemapping) - if (!cameraComponent.rendering) { - cameraComponent.rendering = new RenderingParams(); - } - - // set HDR rendering parameters - const rendering = cameraComponent.rendering; - rendering.gammaCorrection = GAMMA_NONE; - rendering.toneMapping = TONEMAP_NONE; + cameraComponent.gammaCorrection = GAMMA_NONE; + cameraComponent.toneMapping = TONEMAP_NONE; - // set up internal rendering parameters - rendering.ssaoEnabled = options.ssaoType === SSAOTYPE_LIGHTING; + // set up internal rendering parameters - this affect the shader generation to apply SSAO during forward pass + cameraComponent.shaderParams.ssaoEnabled = options.ssaoType === SSAOTYPE_LIGHTING; // create a render target to render the scene into this.sceneTexture = new Texture(device, { diff --git a/src/framework/app-base.js b/src/framework/app-base.js index 4ee1b93a006..954b4ffb7bd 100644 --- a/src/framework/app-base.js +++ b/src/framework/app-base.js @@ -322,8 +322,8 @@ class AppBase extends EventHandler { * * @type {Scene} * @example - * // Set the tone mapping property of the application's scene - * this.app.scene.rendering.toneMapping = pc.TONEMAP_FILMIC; + * // Set the fog type property of the application's scene + * this.app.scene.fog.type = pc.FOG_LINEAR; */ scene; diff --git a/src/framework/components/camera/component.js b/src/framework/components/camera/component.js index 887aaedc944..c323dc244c3 100644 --- a/src/framework/components/camera/component.js +++ b/src/framework/components/camera/component.js @@ -15,7 +15,7 @@ import { PostEffectQueue } from './post-effect-queue.js'; * @import { Mat4 } from '../../../core/math/mat4.js' * @import { RenderPass } from '../../../platform/graphics/render-pass.js' * @import { RenderTarget } from '../../../platform/graphics/render-target.js' - * @import { RenderingParams } from '../../../scene/renderer/rendering-params.js' + * @import { FogParams } from '../../../scene/fog-params.js' * @import { Vec3 } from '../../../core/math/vec3.js' * @import { Vec4 } from '../../../core/math/vec4.js' * @import { XrErrorCallback } from '../../xr/xr-manager.js' @@ -223,7 +223,7 @@ class CameraComponent extends Component { /** * Shader pass name. * - * @returns {string} The name of the shader pass, or undefined if no shader pass is set. + * @returns {string|undefined} The name of the shader pass, or undefined if no shader pass is set. */ getShaderPass() { return this._camera.shaderPassInfo?.name; @@ -252,25 +252,77 @@ class CameraComponent extends Component { return this._camera.renderPasses; } + get shaderParams() { + return this._camera.shaderParams; + } + + /** + * Sets the gamma correction to apply when rendering the scene. Can be: + * + * - {@link GAMMA_NONE} + * - {@link GAMMA_SRGB} + * + * Defaults to {@link GAMMA_SRGB}. + * + * @type {number} + */ + set gammaCorrection(value) { + this.camera.shaderParams.gammaCorrection = value; + } + + /** + * Gets the gamma correction used when rendering the scene. + * + * @type {number} + */ + get gammaCorrection() { + return this.camera.shaderParams.gammaCorrection; + } + + /** + * Sets the tonemapping transform to apply to the rendered color buffer. Can be: + * + * - {@link TONEMAP_LINEAR} + * - {@link TONEMAP_FILMIC} + * - {@link TONEMAP_HEJL} + * - {@link TONEMAP_ACES} + * - {@link TONEMAP_ACES2} + * - {@link TONEMAP_NEUTRAL} + * + * Defaults to {@link TONEMAP_LINEAR}. + * + * @type {number} + */ + set toneMapping(value) { + this.camera.shaderParams.toneMapping = value; + } + + /** + * Gets the tonemapping transform applied to the rendered color buffer. + * + * @type {number} + */ + get toneMapping() { + return this.camera.shaderParams.toneMapping; + } + /** - * Sets the rendering parameters. If this is not null, the camera will use these rendering - * parameters instead of those specified in the scene's rendering parameters - * {@link Scene#rendering}. + * Sets the fog parameters. If this is not null, the camera will use these fog parameters + * instead of those specified on the {@link Scene#fog}. * - * @type {RenderingParams|null} + * @type {FogParams|null} */ - set rendering(value) { - this._camera.renderingParams = value; + set fog(value) { + this._camera.fogParams = value; } /** - * Gets a {@link RenderingParams} that defines rendering parameters, or null if those are not - * set. + * Gets a {@link FogParams} that defines fog parameters, or null if those are not set. * - * @type {RenderingParams|null} + * @type {FogParams|null} */ - get rendering() { - return this._camera.renderingParams; + get fog() { + return this._camera.fogParams; } /** diff --git a/src/framework/components/camera/system.js b/src/framework/components/camera/system.js index 84d872a04f5..21ae340e601 100644 --- a/src/framework/components/camera/system.js +++ b/src/framework/components/camera/system.js @@ -76,7 +76,9 @@ class CameraComponentSystem extends ComponentSystem { 'scissorRect', 'aperture', 'shutter', - 'sensitivity' + 'sensitivity', + 'gammaCorrection', + 'toneMapping' ]; for (let i = 0; i < properties.length; i++) { @@ -139,7 +141,9 @@ class CameraComponentSystem extends ComponentSystem { scissorRect: c.scissorRect, aperture: c.aperture, sensitivity: c.sensitivity, - shutter: c.shutter + shutter: c.shutter, + gammaCorrection: c.gammaCorrection, + toneMapping: c.toneMapping }); } diff --git a/src/framework/lightmapper/lightmapper.js b/src/framework/lightmapper/lightmapper.js index 3fa1c654891..4b3147b3d44 100644 --- a/src/framework/lightmapper/lightmapper.js +++ b/src/framework/lightmapper/lightmapper.js @@ -19,7 +19,7 @@ import { drawQuadWithShader } from '../../scene/graphics/quad-render-utils.js'; import { Texture } from '../../platform/graphics/texture.js'; import { BAKE_COLORDIR, - FOG_NONE, GAMMA_NONE, TONEMAP_LINEAR, + GAMMA_NONE, TONEMAP_LINEAR, LIGHTTYPE_DIRECTIONAL, LIGHTTYPE_OMNI, LIGHTTYPE_SPOT, PROJECTION_ORTHOGRAPHIC, PROJECTION_PERSPECTIVE, SHADERDEF_DIRLM, SHADERDEF_LM, SHADERDEF_LMAMBIENT, @@ -30,7 +30,6 @@ import { import { MeshInstance } from '../../scene/mesh-instance.js'; import { LightingParams } from '../../scene/lighting/lighting-params.js'; import { WorldClusters } from '../../scene/lighting/world-clusters.js'; -import { RenderingParams } from '../../scene/renderer/rendering-params.js'; import { shaderChunks } from '../../scene/shader-lib/chunks/chunks.js'; import { shaderChunksLightmapper } from '../../scene/shader-lib/chunks/chunks-lightmapper.js'; import { Camera } from '../../scene/camera.js'; @@ -166,10 +165,8 @@ class Lightmapper { this.camera = camera; // baking uses HDR (no gamma / tone mapping) - const rp = new RenderingParams(); - rp.gammaCorrection = GAMMA_NONE; - rp.toneMapping = TONEMAP_LINEAR; - this.camera.renderingParams = rp; + this.camera.shaderParams.gammaCorrection = GAMMA_NONE; + this.camera.shaderParams.toneMapping = TONEMAP_LINEAR; } // create light cluster structure @@ -684,12 +681,8 @@ class Lightmapper { setupScene() { // backup - this.fog = this.scene.rendering.fog; this.ambientLight.copy(this.scene.ambientLight); - // set up scene - this.scene.rendering.fog = FOG_NONE; - // if not baking ambient, set it to black if (!this.scene.ambientBake) { this.scene.ambientLight.set(0, 0, 0); @@ -701,7 +694,6 @@ class Lightmapper { restoreScene() { - this.scene.rendering.fog = this.fog; this.scene.ambientLight.copy(this.ambientLight); } diff --git a/src/index.js b/src/index.js index d1b8ac94408..ed25fb9ce51 100644 --- a/src/index.js +++ b/src/index.js @@ -182,7 +182,7 @@ export { SphereGeometry } from './scene/geometry/sphere-geometry.js'; export { TorusGeometry } from './scene/geometry/torus-geometry.js'; // SCENE / RENDERER -export { RenderingParams } from './scene/renderer/rendering-params.js'; +export { FogParams } from './scene/fog-params.js'; export { RenderPassForward } from './scene/renderer/render-pass-forward.js'; // SCENE / SHADER-LIB diff --git a/src/scene/renderer/rendering-params.js b/src/scene/camera-shader-params.js similarity index 55% rename from src/scene/renderer/rendering-params.js rename to src/scene/camera-shader-params.js index 8eb3db3681d..9e2158bfa72 100644 --- a/src/scene/renderer/rendering-params.js +++ b/src/scene/camera-shader-params.js @@ -1,13 +1,12 @@ -import { hashCode } from '../../core/hash.js'; -import { Color } from '../../core/math/color.js'; -import { FOG_NONE, GAMMA_NONE, GAMMA_SRGB, TONEMAP_LINEAR } from '../constants.js'; +import { hashCode } from '../core/hash.js'; +import { FOG_NONE, GAMMA_NONE, GAMMA_SRGB, TONEMAP_LINEAR } from './constants.js'; /** - * Rendering parameters, allow configuration of the rendering parameters. + * Internal camera shader parameters, used to generate and use matching shaders. * - * @category Graphics + * @ignore */ -class RenderingParams { +class CameraShaderParams { /** @private */ _gammaCorrection = GAMMA_SRGB; @@ -23,37 +22,6 @@ class RenderingParams { /** @private */ _fog = FOG_NONE; - /** - * The color of the fog (if enabled), specified in sRGB color space. Defaults to black (0, 0, 0). - * - * @type {Color} - */ - fogColor = new Color(0, 0, 0); - - /** - * The density of the fog (if enabled). This property is only valid if the fog property is set - * to {@link FOG_EXP} or {@link FOG_EXP2}. Defaults to 0. - * - * @type {number} - */ - fogDensity = 0; - - /** - * The distance from the viewpoint where linear fog reaches its maximum. This property is only - * valid if the fog property is set to {@link FOG_LINEAR}. Defaults to 1000. - * - * @type {number} - */ - fogEnd = 1000; - - /** - * The distance from the viewpoint where linear fog begins. This property is only valid if the - * fog property is set to {@link FOG_LINEAR}. Defaults to 1. - * - * @type {number} - */ - fogStart = 1; - /** * The hash of the rendering parameters, or undefined if the hash has not been computed yet. * @@ -76,22 +44,18 @@ class RenderingParams { return this._hash; } + initDefaults() { + this._gammaCorrection = GAMMA_SRGB; + this._toneMapping = TONEMAP_LINEAR; + this._srgbRenderTarget = false; + this._ssaoEnabled = false; + this._fog = FOG_NONE; + } + markDirty() { this._hash = undefined; } - /** - * Sets the type of fog used by the scene. Can be: - * - * - {@link FOG_NONE} - * - {@link FOG_LINEAR} - * - {@link FOG_EXP} - * - {@link FOG_EXP2} - * - * Defaults to {@link FOG_NONE}. - * - * @type {string} - */ set fog(type) { if (this._fog !== type) { this._fog = type; @@ -99,11 +63,6 @@ class RenderingParams { } } - /** - * Gets the type of fog used by the scene. - * - * @type {string} - */ get fog() { return this._fog; } @@ -119,17 +78,8 @@ class RenderingParams { return this._ssaoEnabled; } - /** - * The gamma correction to apply when rendering the scene. Can be: - * - * - {@link GAMMA_NONE} - * - {@link GAMMA_SRGB} - * - * Defaults to {@link GAMMA_SRGB}. - * - * @type {number} - */ set gammaCorrection(value) { + this._gammaCorrectionAssigned = true; if (this._gammaCorrection !== value) { this._gammaCorrection = value; this.markDirty(); @@ -140,20 +90,6 @@ class RenderingParams { return this._gammaCorrection; } - /** - * The tonemapping transform to apply to the rendered color buffer. Can be: - * - * - {@link TONEMAP_LINEAR} - * - {@link TONEMAP_FILMIC} - * - {@link TONEMAP_HEJL} - * - {@link TONEMAP_ACES} - * - {@link TONEMAP_ACES2} - * - {@link TONEMAP_NEUTRAL} - * - * Defaults to {@link TONEMAP_LINEAR}. - * - * @type {number} - */ set toneMapping(value) { if (this._toneMapping !== value) { this._toneMapping = value; @@ -191,4 +127,4 @@ class RenderingParams { } } -export { RenderingParams }; +export { CameraShaderParams }; diff --git a/src/scene/camera.js b/src/scene/camera.js index 546e3a4c1d2..f03a8fe6240 100644 --- a/src/scene/camera.js +++ b/src/scene/camera.js @@ -10,10 +10,11 @@ import { } from './constants.js'; import { RenderPassColorGrab } from './graphics/render-pass-color-grab.js'; import { RenderPassDepthGrab } from './graphics/render-pass-depth-grab.js'; +import { CameraShaderParams } from './camera-shader-params.js'; /** * @import { RenderPass } from '../platform/graphics/render-pass.js' - * @import { RenderingParams } from './renderer/rendering-params.js' + * @import { FogParams } from './fog-params.js' * @import { ShaderPassInfo } from './shader-pass.js' */ @@ -46,11 +47,18 @@ class Camera { renderPassDepthGrab = null; /** - * The rendering parameters. + * The fog parameters. * - * @type {RenderingParams|null} + * @type {FogParams|null} */ - renderingParams = null; + fogParams = null; + + /** + * Shader parameters used to generate and use matching shaders. + * + * @type {CameraShaderParams} + */ + shaderParams = new CameraShaderParams(); /** * Render passes used to render this camera. If empty, the camera will render using the default diff --git a/src/scene/fog-params.js b/src/scene/fog-params.js new file mode 100644 index 00000000000..5867c2dd589 --- /dev/null +++ b/src/scene/fog-params.js @@ -0,0 +1,56 @@ +import { Color } from '../core/math/color.js'; +import { FOG_NONE } from './constants.js'; + +/** + * Fog parameters. + * + * @category Graphics + */ +class FogParams { + /** + * The type of fog used by the scene. Can be: + * + * - {@link FOG_NONE} + * - {@link FOG_LINEAR} + * - {@link FOG_EXP} + * - {@link FOG_EXP2} + * + * Defaults to {@link FOG_NONE}. + * + * @type {string} + */ + type = FOG_NONE; + + /** + * The color of the fog (if enabled), specified in sRGB color space. Defaults to black (0, 0, 0). + * + * @type {Color} + */ + color = new Color(0, 0, 0); + + /** + * The density of the fog (if enabled). This property is only valid if the fog property is set + * to {@link FOG_EXP} or {@link FOG_EXP2}. Defaults to 0. + * + * @type {number} + */ + density = 0; + + /** + * The distance from the viewpoint where linear fog begins. This property is only valid if the + * fog property is set to {@link FOG_LINEAR}. Defaults to 1. + * + * @type {number} + */ + start = 1; + + /** + * The distance from the viewpoint where linear fog reaches its maximum. This property is only + * valid if the fog property is set to {@link FOG_LINEAR}. Defaults to 1000. + * + * @type {number} + */ + end = 1000; +} + +export { FogParams }; diff --git a/src/scene/gsplat/gsplat-compressed-material.js b/src/scene/gsplat/gsplat-compressed-material.js index 232587eec18..00b0b64fec3 100644 --- a/src/scene/gsplat/gsplat-compressed-material.js +++ b/src/scene/gsplat/gsplat-compressed-material.js @@ -383,8 +383,8 @@ const createGSplatCompressedMaterial = (options = {}) => { const programOptions = { defines: material.defines, pass: params.pass, - gamma: params.renderParams.shaderOutputGamma, - toneMapping: params.renderParams.toneMapping, + gamma: params.cameraShaderParams.shaderOutputGamma, + toneMapping: params.cameraShaderParams.toneMapping, vertex: options.vertex ?? splatMainVS, fragment: options.fragment ?? splatMainFS, dither: ditherEnum diff --git a/src/scene/gsplat/gsplat-material.js b/src/scene/gsplat/gsplat-material.js index 53be5150244..666879bc340 100644 --- a/src/scene/gsplat/gsplat-material.js +++ b/src/scene/gsplat/gsplat-material.js @@ -113,8 +113,8 @@ const createGSplatMaterial = (options = {}) => { const programOptions = { defines: material.defines, pass: params.pass, - gamma: params.renderParams.shaderOutputGamma, - toneMapping: params.renderParams.toneMapping, + gamma: params.cameraShaderParams.shaderOutputGamma, + toneMapping: params.cameraShaderParams.toneMapping, vertex: options.vertex ?? splatMainVS, fragment: options.fragment ?? splatMainFS, dither: ditherEnum diff --git a/src/scene/materials/lit-material.js b/src/scene/materials/lit-material.js index aeb236ee487..1c38bae1057 100644 --- a/src/scene/materials/lit-material.js +++ b/src/scene/materials/lit-material.js @@ -90,7 +90,7 @@ class LitMaterial extends Material { options.shaderChunk = this.shaderChunk; options.defines = this.defines; - LitMaterialOptionsBuilder.update(options.litOptions, this, params.scene, params.renderParams, params.objDefs, params.pass, params.sortedLights); + LitMaterialOptionsBuilder.update(options.litOptions, this, params.scene, params.cameraShaderParams, params.objDefs, params.pass, params.sortedLights); const processingOptions = new ShaderProcessorOptions(params.viewUniformFormat, params.viewBindGroupFormat, params.vertexFormat); const library = getProgramLibrary(params.device); library.register('lit', lit); diff --git a/src/scene/materials/material.js b/src/scene/materials/material.js index 81c1c76a1e7..2fa53e926f2 100644 --- a/src/scene/materials/material.js +++ b/src/scene/materials/material.js @@ -21,7 +21,7 @@ import { getDefaultMaterial } from './default-material.js'; * @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js' * @import { Light } from '../light.js'; * @import { MeshInstance } from '../mesh-instance.js' - * @import { RenderingParams } from '../renderer/rendering-params.js' + * @import { CameraShaderParams } from '../camera-shader-params.js' * @import { Scene } from '../scene.js' * @import { Shader } from '../../platform/graphics/shader.js' * @import { StencilParameters } from '../../platform/graphics/stencil-parameters.js' @@ -52,7 +52,7 @@ let id = 0; * @property {GraphicsDevice} device - The graphics device. * @property {Scene} scene - The scene. * @property {number} objDefs - The object definitions. - * @property {RenderingParams} renderParams - The render parameters. + * @property {CameraShaderParams} cameraShaderParams - The camera shader parameters. * @property {number} pass - The shader pass. * @property {Light[][]} sortedLights - The sorted lights. * @property {UniformBufferFormat|undefined} viewUniformFormat - The view uniform format. diff --git a/src/scene/materials/shader-material.js b/src/scene/materials/shader-material.js index 7221ae18dc7..c01d7ec981b 100644 --- a/src/scene/materials/shader-material.js +++ b/src/scene/materials/shader-material.js @@ -106,9 +106,9 @@ class ShaderMaterial extends Material { useMorphTextureBasedInt: (objDefs & SHADERDEF_MORPH_TEXTURE_BASED_INT) !== 0, pass: params.pass, - gamma: params.renderParams.shaderOutputGamma, - toneMapping: params.renderParams.toneMapping, - fog: params.renderParams.fog, + gamma: params.cameraShaderParams.shaderOutputGamma, + toneMapping: params.cameraShaderParams.toneMapping, + fog: params.cameraShaderParams.fog, shaderDesc: this.shaderDesc }; diff --git a/src/scene/materials/standard-material-options-builder.js b/src/scene/materials/standard-material-options-builder.js index ad3d227867f..5d92dee9d99 100644 --- a/src/scene/materials/standard-material-options-builder.js +++ b/src/scene/materials/standard-material-options-builder.js @@ -49,13 +49,13 @@ class StandardMaterialOptionsBuilder { this._updateUVOptions(options, stdMat, objDefs, true); } - updateRef(options, scene, renderParams, stdMat, objDefs, pass, sortedLights) { + updateRef(options, scene, cameraShaderParams, stdMat, objDefs, pass, sortedLights) { this._updateSharedOptions(options, scene, stdMat, objDefs, pass); - this._updateEnvOptions(options, stdMat, scene, renderParams); + this._updateEnvOptions(options, stdMat, scene, cameraShaderParams); this._updateMaterialOptions(options, stdMat); options.litOptions.hasTangents = objDefs && ((objDefs & SHADERDEF_TANGENTS) !== 0); this._updateLightOptions(options, scene, stdMat, objDefs, sortedLights); - this._updateUVOptions(options, stdMat, objDefs, false, renderParams); + this._updateUVOptions(options, stdMat, objDefs, false, cameraShaderParams); } _updateSharedOptions(options, scene, stdMat, objDefs, pass) { @@ -96,7 +96,7 @@ class StandardMaterialOptionsBuilder { } } - _updateUVOptions(options, stdMat, objDefs, minimalOptions, renderParams) { + _updateUVOptions(options, stdMat, objDefs, minimalOptions, cameraShaderParams) { let hasUv0 = false; let hasUv1 = false; let hasVcolor = false; @@ -116,7 +116,7 @@ class StandardMaterialOptionsBuilder { this._mapXForms = null; // true if ssao is applied directly in the lit shaders. Also ensure the AO part is generated in the front end - options.litOptions.ssao = renderParams?.ssaoEnabled; + options.litOptions.ssao = cameraShaderParams?.ssaoEnabled; options.useAO = options.litOptions.ssao; // All texture related lit options @@ -282,10 +282,10 @@ class StandardMaterialOptionsBuilder { options.litOptions.dispersion = stdMat.dispersion > 0; } - _updateEnvOptions(options, stdMat, scene, renderParams) { - options.litOptions.fog = stdMat.useFog ? renderParams.fog : FOG_NONE; - options.litOptions.gamma = renderParams.shaderOutputGamma; - options.litOptions.toneMap = stdMat.useTonemap ? renderParams.toneMapping : TONEMAP_NONE; + _updateEnvOptions(options, stdMat, scene, cameraShaderParams) { + options.litOptions.fog = stdMat.useFog ? cameraShaderParams.fog : FOG_NONE; + options.litOptions.gamma = cameraShaderParams.shaderOutputGamma; + options.litOptions.toneMap = stdMat.useTonemap ? cameraShaderParams.toneMapping : TONEMAP_NONE; let usingSceneEnv = false; diff --git a/src/scene/materials/standard-material.js b/src/scene/materials/standard-material.js index 64319c48c28..8190a86879d 100644 --- a/src/scene/materials/standard-material.js +++ b/src/scene/materials/standard-material.js @@ -850,7 +850,7 @@ class StandardMaterial extends Material { getShaderVariant(params) { - const { device, scene, pass, objDefs, sortedLights, renderParams } = params; + const { device, scene, pass, objDefs, sortedLights, cameraShaderParams } = params; // update prefiltered lighting data this.updateEnvUniforms(device, scene); @@ -864,7 +864,7 @@ class StandardMaterial extends Material { if (minimalOptions) { this.shaderOptBuilder.updateMinRef(options, scene, this, objDefs, pass, sortedLights); } else { - this.shaderOptBuilder.updateRef(options, scene, renderParams, this, objDefs, pass, sortedLights); + this.shaderOptBuilder.updateRef(options, scene, cameraShaderParams, this, objDefs, pass, sortedLights); } // execute user callback to modify the options diff --git a/src/scene/mesh-instance.js b/src/scene/mesh-instance.js index e9810ebfb33..d4827f4f7fd 100644 --- a/src/scene/mesh-instance.js +++ b/src/scene/mesh-instance.js @@ -25,10 +25,10 @@ import { array } from '../core/array-utils.js'; * @import { Camera } from './camera.js' * @import { GSplatInstance } from './gsplat/gsplat-instance.js' * @import { GraphicsDevice } from '../platform/graphics/graphics-device.js' - * @import { Material, ShaderVariantParams } from './materials/material.js' + * @import { Material } from './materials/material.js' * @import { Mesh } from './mesh.js' * @import { MorphInstance } from './morph-instance.js' - * @import { RenderingParams } from './renderer/rendering-params.js' + * @import { CameraShaderParams } from './camera-shader-params.js' * @import { Scene } from './scene.js' * @import { ScopeId } from '../platform/graphics/scope-id.js' * @import { Shader } from '../platform/graphics/shader.js' @@ -590,14 +590,14 @@ class MeshInstance { * @param {number} shaderPass - The shader pass index. * @param {number} lightHash - The hash value of the lights that are affecting this mesh instance. * @param {Scene} scene - The scene. - * @param {RenderingParams} renderParams - The rendering parameters. + * @param {CameraShaderParams} cameraShaderParams - The camera shader parameters. * @param {UniformBufferFormat} [viewUniformFormat] - The format of the view uniform buffer. * @param {BindGroupFormat} [viewBindGroupFormat] - The format of the view bind group. * @param {any} [sortedLights] - Array of arrays of lights. * @returns {ShaderInstance} - the shader instance. * @ignore */ - getShaderInstance(shaderPass, lightHash, scene, renderParams, viewUniformFormat, viewBindGroupFormat, sortedLights) { + getShaderInstance(shaderPass, lightHash, scene, cameraShaderParams, viewUniformFormat, viewBindGroupFormat, sortedLights) { const shaderDefs = this._shaderDefs; @@ -605,7 +605,7 @@ class MeshInstance { lookupHashes[0] = shaderPass; lookupHashes[1] = lightHash; lookupHashes[2] = shaderDefs; - lookupHashes[3] = renderParams.hash; + lookupHashes[3] = cameraShaderParams.hash; const hash = hash32Fnv1a(lookupHashes); // look up the cache @@ -631,7 +631,7 @@ class MeshInstance { device: this.mesh.device, scene: scene, objDefs: shaderDefs, - renderParams: renderParams, + cameraShaderParams: cameraShaderParams, pass: shaderPass, sortedLights: sortedLights, viewUniformFormat: viewUniformFormat, diff --git a/src/scene/particle-system/particle-material.js b/src/scene/particle-system/particle-material.js index f005378c7aa..cf8072f6bc4 100644 --- a/src/scene/particle-system/particle-material.js +++ b/src/scene/particle-system/particle-material.js @@ -36,7 +36,7 @@ class ParticleMaterial extends Material { getShaderVariant(params) { - const { device, scene, renderParams } = params; + const { device, scene, cameraShaderParams } = params; const { emitter } = this; const options = { defines: this.defines, @@ -48,9 +48,9 @@ class ParticleMaterial extends Material { alignToMotion: this.emitter.alignToMotion, soft: this.emitter.depthSoftening, mesh: this.emitter.useMesh, - gamma: renderParams?.shaderOutputGamma ?? GAMMA_NONE, - toneMap: renderParams?.toneMapping ?? TONEMAP_LINEAR, - fog: (scene && !this.emitter.noFog) ? scene.rendering.fog : 'none', + gamma: cameraShaderParams?.shaderOutputGamma ?? GAMMA_NONE, + toneMap: cameraShaderParams?.toneMapping ?? TONEMAP_LINEAR, + fog: (scene && !this.emitter.noFog) ? scene.fog.type : 'none', wrap: this.emitter.wrap && this.emitter.wrapBounds, localSpace: this.emitter.localSpace, diff --git a/src/scene/renderer/forward-renderer.js b/src/scene/renderer/forward-renderer.js index 6123811d92b..a8df39a58bf 100644 --- a/src/scene/renderer/forward-renderer.js +++ b/src/scene/renderer/forward-renderer.js @@ -474,11 +474,13 @@ class ForwardRenderer extends Renderer { // execute first pass over draw calls, in order to update materials / shaders renderForwardPrepareMaterials(camera, renderTarget, drawCalls, sortedLights, layer, pass) { - // rendering params from the scene, or overridden by the camera - const renderParams = camera.renderingParams ?? this.scene.rendering; + // fog params from the scene, or overridden by the camera + const fogParams = camera.fog ?? this.scene.fog; - // output gamma correction is determined by the render target - renderParams.srgbRenderTarget = renderTarget?.isColorBufferSrgb(0) ?? false; + // camera shader params + const shaderParams = camera.shaderParams; + shaderParams.fog = fogParams.type; + shaderParams.srgbRenderTarget = renderTarget?.isColorBufferSrgb(0) ?? false; // output gamma correction is determined by the render target const addCall = (drawCall, shaderInstance, isNewMaterial, lightMaskChanged) => { _drawCallList.drawCalls.push(drawCall); @@ -539,7 +541,7 @@ class ForwardRenderer extends Renderer { } } - const shaderInstance = drawCall.getShaderInstance(pass, lightHash, scene, renderParams, this.viewUniformFormat, this.viewBindGroupFormat, sortedLights); + const shaderInstance = drawCall.getShaderInstance(pass, lightHash, scene, shaderParams, this.viewUniformFormat, this.viewBindGroupFormat, sortedLights); addCall(drawCall, shaderInstance, material !== prevMaterial, !prevMaterial || lightMask !== prevLightMask); @@ -757,8 +759,9 @@ class ForwardRenderer extends Renderer { // Set the not very clever global variable which is only useful when there's just one camera scene._activeCamera = camera; - const renderParams = camera.renderingParams ?? scene.rendering; - this.setFogConstants(renderParams); + const fogParams = camera.fog ?? this.scene.fog; + this.setFogConstants(fogParams); + const viewCount = this.setCameraUniforms(camera, renderTarget); if (device.supportsUniformBuffers) { this.setupViewUniformBuffers(viewBindGroups, this.viewUniformFormat, this.viewBindGroupFormat, viewCount); @@ -790,23 +793,23 @@ class ForwardRenderer extends Renderer { } } - setFogConstants(renderParams) { + setFogConstants(fogParams) { - if (renderParams.fog !== FOG_NONE) { + if (fogParams.type !== FOG_NONE) { // color in linear space - tmpColor.linear(renderParams.fogColor); + tmpColor.linear(fogParams.color); const fogUniform = this.fogColor; fogUniform[0] = tmpColor.r; fogUniform[1] = tmpColor.g; fogUniform[2] = tmpColor.b; this.fogColorId.setValue(fogUniform); - if (renderParams.fog === FOG_LINEAR) { - this.fogStartId.setValue(renderParams.fogStart); - this.fogEndId.setValue(renderParams.fogEnd); + if (fogParams.type === FOG_LINEAR) { + this.fogStartId.setValue(fogParams.start); + this.fogEndId.setValue(fogParams.end); } else { - this.fogDensityId.setValue(renderParams.fogDensity); + this.fogDensityId.setValue(fogParams.density); } } } diff --git a/src/scene/renderer/shadow-renderer.js b/src/scene/renderer/shadow-renderer.js index a9654c09790..11303128fa8 100644 --- a/src/scene/renderer/shadow-renderer.js +++ b/src/scene/renderer/shadow-renderer.js @@ -22,7 +22,6 @@ import { LightCamera } from './light-camera.js'; import { UniformBufferFormat, UniformFormat } from '../../platform/graphics/uniform-buffer-format.js'; import { BindUniformBufferFormat, BindGroupFormat } from '../../platform/graphics/bind-group-format.js'; import { BlendState } from '../../platform/graphics/blend-state.js'; -import { RenderingParams } from './rendering-params.js'; /** * @import { Camera } from '../camera.js' @@ -111,9 +110,6 @@ class ShadowRenderer { this.blendStateWrite = new BlendState(); this.blendStateNoWrite = new BlendState(); this.blendStateNoWrite.setColorWrite(false, false, false, false); - - // shadow rendering parameters - this.shadowRenderingParams = new RenderingParams(); } // creates shadow camera for a light and sets up its constant properties @@ -272,15 +268,16 @@ class ShadowRenderer { /** * @param {MeshInstance[]} visibleCasters - Visible mesh instances. * @param {Light} light - The light. + * @param {Camera} camera - The camera. */ - submitCasters(visibleCasters, light) { + submitCasters(visibleCasters, light, camera) { const device = this.device; const renderer = this.renderer; const scene = renderer.scene; const passFlags = 1 << SHADER_SHADOW; const shadowPass = this.getShadowPass(light); - const renderParams = this.shadowRenderingParams; + const cameraShaderParams = camera.shaderParams; // Render const count = visibleCasters.length; @@ -311,7 +308,7 @@ class ShadowRenderer { meshInstance.setParameters(device, passFlags); } - const shaderInstance = meshInstance.getShaderInstance(shadowPass, 0, scene, renderParams, this.viewUniformFormat, this.viewBindGroupFormat); + const shaderInstance = meshInstance.getShaderInstance(shadowPass, 0, scene, cameraShaderParams, this.viewUniformFormat, this.viewBindGroupFormat); const shadowShader = shaderInstance.shader; Debug.assert(shadowShader, `no shader for pass ${shadowPass}`, material); @@ -431,7 +428,7 @@ class ShadowRenderer { this.setupRenderState(device, light); // render mesh instances - this.submitCasters(lightRenderData.visibleCasters, light); + this.submitCasters(lightRenderData.visibleCasters, light, shadowCam); DebugGraphics.popGpuMarker(device); diff --git a/src/scene/scene.js b/src/scene/scene.js index dad5a714431..e4d3a7bcc5e 100644 --- a/src/scene/scene.js +++ b/src/scene/scene.js @@ -12,7 +12,7 @@ import { LightingParams } from './lighting/lighting-params.js'; import { Sky } from './skybox/sky.js'; import { Immediate } from './immediate/immediate.js'; import { EnvLighting } from './graphics/env-lighting.js'; -import { RenderingParams } from './renderer/rendering-params.js'; +import { FogParams } from './fog-params.js'; /** * @import { Entity } from '../framework/entity.js' @@ -192,11 +192,11 @@ class Scene extends EventHandler { _skyboxCubeMap = null; /** - * The rendering parameters. + * The fog parameters. * * @private */ - _renderingParams = new RenderingParams(); + _fogParams = new FogParams(); /** * Create a new Scene instance. @@ -436,12 +436,12 @@ class Scene extends EventHandler { } /** - * A {@link RenderingParams} that defines rendering parameters. + * Gets the {@link FogParams} that define fog parameters. * - * @type {RenderingParams} + * @type {FogParams} */ - get rendering() { - return this._renderingParams; + get fog() { + return this._fogParams; } /** @@ -700,13 +700,11 @@ class Scene extends EventHandler { this._gravity.set(physics.gravity[0], physics.gravity[1], physics.gravity[2]); this.ambientLight.set(render.global_ambient[0], render.global_ambient[1], render.global_ambient[2]); this.ambientLuminance = render.ambientLuminance; - this._renderingParams.fog = render.fog; - this._renderingParams.fogColor.set(render.fog_color[0], render.fog_color[1], render.fog_color[2]); - this._renderingParams.fogStart = render.fog_start; - this._renderingParams.fogEnd = render.fog_end; - this._renderingParams.fogDensity = render.fog_density; - this._renderingParams.gammaCorrection = render.gamma_correction; - this._renderingParams.toneMapping = render.tonemapping; + this.fog.type = render.fog; + this.fog.color.set(render.fog_color[0], render.fog_color[1], render.fog_color[2]); + this.fog.start = render.fog_start; + this.fog.end = render.fog_end; + this.fog.density = render.fog_density; this.lightmapSizeMultiplier = render.lightmapSizeMultiplier; this.lightmapMaxResolution = render.lightmapMaxResolution; this.lightmapMode = render.lightmapMode; diff --git a/src/scene/shader-lib/program-library.js b/src/scene/shader-lib/program-library.js index 441ddb90f2e..54d99b50c74 100644 --- a/src/scene/shader-lib/program-library.js +++ b/src/scene/shader-lib/program-library.js @@ -5,7 +5,7 @@ import { Shader } from '../../platform/graphics/shader.js'; import { SHADER_FORWARD, SHADER_DEPTH, SHADER_PICK, SHADER_SHADOW, SHADER_PREPASS_VELOCITY } from '../constants.js'; import { ShaderPass } from '../shader-pass.js'; import { StandardMaterialOptions } from '../materials/standard-material-options.js'; -import { RenderingParams } from '../renderer/rendering-params.js'; +import { CameraShaderParams } from '../camera-shader-params.js'; /** * @import { ShaderGenerator } from './programs/shader-generator.js' @@ -51,9 +51,9 @@ class ProgramLibrary { this._defaultStdMatOption = new StandardMaterialOptions(); this._defaultStdMatOptionMin = new StandardMaterialOptions(); - const defaultRenderParams = new RenderingParams(); + const defaultCameraShaderParams = new CameraShaderParams(); standardMaterial.shaderOptBuilder.updateRef( - this._defaultStdMatOption, {}, defaultRenderParams, standardMaterial, null, [], SHADER_FORWARD, null); + this._defaultStdMatOption, {}, defaultCameraShaderParams, standardMaterial, null, [], SHADER_FORWARD, null); standardMaterial.shaderOptBuilder.updateMinRef( this._defaultStdMatOptionMin, {}, standardMaterial, null, SHADER_SHADOW, null); diff --git a/src/scene/skybox/sky-mesh.js b/src/scene/skybox/sky-mesh.js index 485b7bbfe5a..4edcad216fd 100644 --- a/src/scene/skybox/sky-mesh.js +++ b/src/scene/skybox/sky-mesh.js @@ -39,13 +39,13 @@ class SkyMesh { material.getShaderVariant = function (params) { - const { scene, renderParams } = params; + const { scene, cameraShaderParams } = params; const options = { defines: this.defines, pass: params.pass, encoding: texture.encoding, - gamma: renderParams.shaderOutputGamma, - toneMapping: renderParams.toneMapping, + gamma: cameraShaderParams.shaderOutputGamma, + toneMapping: cameraShaderParams.toneMapping, skymesh: type };