Skip to content

Commit

Permalink
Merge branch 'main' into remove-unbundled-sourcemapping
Browse files Browse the repository at this point in the history
  • Loading branch information
mvaligursky authored Mar 7, 2024
2 parents 3b64718 + 67a55f5 commit c9fef33
Show file tree
Hide file tree
Showing 27 changed files with 660 additions and 126 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,8 @@ jobs:
- name: Install dependencies
run: npm clean-install --progress=false --no-fund

- name: Build PlayCanvas (ES5-only)
run: npm run build:es5
- name: Build PlayCanvas (ES6-only)
run: npm run build:es6

- name: Build PlayCanvas Extras
run: npm run build:extras
Expand Down
Binary file added examples/assets/models/pbr-house.glb
Binary file not shown.
5 changes: 5 additions & 0 deletions examples/assets/models/pbr-house.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
The house model has been obtained from this address:
https://sketchfab.com/3d-models/house-03-pbr-c56521b89188460a99235dec8bcd0ed3

It's distributed under CC license:
https://creativecommons.org/licenses/by/4.0/
14 changes: 9 additions & 5 deletions examples/src/examples/graphics/post-processing/example.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const createOptions = new pc.AppOptions();
createOptions.graphicsDevice = device;
createOptions.mouse = new pc.Mouse(document.body);
createOptions.touch = new pc.TouchDevice(document.body);
createOptions.keyboard = new pc.Keyboard(window);

createOptions.componentSystems = [
pc.RenderComponentSystem,
Expand Down Expand Up @@ -81,7 +82,8 @@ assetListLoader.load(() => {
// disable skydome rendering itself, we don't need it as we use camera clear color
app.scene.layers.getLayerByName('Skybox').enabled = false;

// render in HDR mode
// the render passes render in HDR format, and so disable output tone mapping and gamma correction,
// as that is applied in the final compose pass
app.scene.toneMapping = pc.TONEMAP_LINEAR;
app.scene.gammaCorrection = pc.GAMMA_NONE;

Expand Down Expand Up @@ -143,7 +145,9 @@ assetListLoader.load(() => {

// add orbit camera script with a mouse and a touch support
cameraEntity.addComponent('script');
cameraEntity.script.create('orbitCamera', {

// add orbit camera script with a mouse and a touch support
cameraEntity.script.create("orbitCamera", {
attributes: {
inertiaFactor: 0.2,
focusEntity: mosquitoEntity,
Expand All @@ -154,7 +158,6 @@ assetListLoader.load(() => {
cameraEntity.script.create('orbitCameraInputMouse');
cameraEntity.script.create('orbitCameraInputTouch');

// position the camera in the world
cameraEntity.setLocalPosition(0, 40, -220);
cameraEntity.lookAt(0, 0, 100);
app.root.addChild(cameraEntity);
Expand Down Expand Up @@ -218,9 +221,9 @@ assetListLoader.load(() => {
samples: 0, // number of samples for multi-sampling
sceneColorMap: true, // true if the scene color should be captured

// disabled by default as this is WIP
// disabled TAA as it currently does not handle dynamic objects
prepassEnabled: false,
taaEnabled: false // true if temporal anti-aliasing should be used
taaEnabled: false
};

const setupRenderPass = () => {
Expand All @@ -245,6 +248,7 @@ assetListLoader.load(() => {
const taaEnabled = data.get('data.taa.enabled');
if (noPasses || taaEnabled !== currentOptions.taaEnabled) {
currentOptions.taaEnabled = taaEnabled;
currentOptions.prepassEnabled = taaEnabled;

// create new pass
setupRenderPass();
Expand Down
6 changes: 6 additions & 0 deletions examples/src/examples/graphics/taa/config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @type {import('../../../../types.mjs').ExampleConfig}
*/
export default {
WEBGPU_ENABLED: true
};
59 changes: 59 additions & 0 deletions examples/src/examples/graphics/taa/controls.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import * as pc from 'playcanvas';

/**
* @param {import('../../../app/components/Example.mjs').ControlOptions} options - The options.
* @returns {JSX.Element} The returned JSX Element.
*/
export function controls({ observer, ReactPCUI, React, jsx, fragment }) {
const { BindingTwoWay, BooleanInput, LabelGroup, Panel, SliderInput } = ReactPCUI;
return fragment(
jsx(
Panel,
{ headerText: 'Scene Rendering' },
jsx(
LabelGroup,
{ text: 'resolution' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'data.scene.scale' },
min: 0.5,
max: 1,
precision: 1
})
),
jsx(
LabelGroup,
{ text: 'Bloom' },
jsx(BooleanInput, {
type: 'toggle',
binding: new BindingTwoWay(),
link: { observer, path: 'data.scene.bloom' }
})
)
),
jsx(
Panel,
{ headerText: 'TAA' },
jsx(
LabelGroup,
{ text: 'enabled' },
jsx(BooleanInput, {
type: 'toggle',
binding: new BindingTwoWay(),
link: { observer, path: 'data.taa.enabled' }
})
),
jsx(
LabelGroup,
{ text: 'jitter' },
jsx(SliderInput, {
binding: new BindingTwoWay(),
link: { observer, path: 'data.taa.jitter' },
min: 0,
max: 1,
precision: 2
})
)
)
);
}
204 changes: 204 additions & 0 deletions examples/src/examples/graphics/taa/example.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
import * as pc from 'playcanvas';
import * as pcx from 'playcanvas-extras';
import { data } from '@examples/observer';
import { deviceType, rootPath } from '@examples/utils';

const canvas = document.getElementById('application-canvas');
if (!(canvas instanceof HTMLCanvasElement)) {
throw new Error('No canvas found');
}

const assets = {
orbit: new pc.Asset('script', 'script', { url: rootPath + '/static/scripts/camera/orbit-camera.js' }),
house: new pc.Asset('house', 'container', { url: rootPath + '/static/assets/models/pbr-house.glb' }),
envatlas: new pc.Asset(
'env-atlas',
'texture',
{ url: rootPath + '/static/assets/cubemaps/table-mountain-env-atlas.png' },
{ type: pc.TEXTURETYPE_RGBP, mipmaps: false }
)
};

const gfxOptions = {
deviceTypes: [deviceType],
glslangUrl: rootPath + '/static/lib/glslang/glslang.js',
twgslUrl: rootPath + '/static/lib/twgsl/twgsl.js',

// disable anti-aliasing as TAA is used to smooth edges
antialias: false
};

const device = await pc.createGraphicsDevice(canvas, gfxOptions);
const createOptions = new pc.AppOptions();
createOptions.graphicsDevice = device;
createOptions.mouse = new pc.Mouse(document.body);
createOptions.touch = new pc.TouchDevice(document.body);

createOptions.componentSystems = [
pc.RenderComponentSystem,
pc.CameraComponentSystem,
pc.LightComponentSystem,
pc.ScriptComponentSystem
];
createOptions.resourceHandlers = [
pc.TextureHandler,
pc.ContainerHandler,
pc.ScriptHandler
];

const app = new pc.AppBase(canvas);
app.init(createOptions);

// Set the canvas to fill the window and automatically change resolution to be the same as the canvas size
app.setCanvasFillMode(pc.FILLMODE_FILL_WINDOW);
app.setCanvasResolution(pc.RESOLUTION_AUTO);

// Ensure canvas is resized when window changes size
const resize = () => app.resizeCanvas();
window.addEventListener('resize', resize);
app.on('destroy', () => {
window.removeEventListener('resize', resize);
});

const assetListLoader = new pc.AssetListLoader(Object.values(assets), app.assets);
assetListLoader.load(() => {
app.start();

// setup skydome with low intensity
app.scene.envAtlas = assets.envatlas.resource;
app.scene.skyboxMip = 0;
app.scene.exposure = 1.0;

// the render passes render in HDR format, and so disable output tone mapping and gamma correction,
// as that is applied in the final compose pass
app.scene.toneMapping = pc.TONEMAP_LINEAR;
app.scene.gammaCorrection = pc.GAMMA_NONE;

// create an instance of the house and add it to the scene
const houseEntity = assets.house.resource.instantiateRenderEntity();
houseEntity.setLocalScale(100, 100, 100);
app.root.addChild(houseEntity);

// Create an Entity with a camera component
const cameraEntity = new pc.Entity();
cameraEntity.addComponent('camera', {
nearClip: 10,
farClip: 600,
fov: 80
});

// add orbit camera script with a mouse and a touch support
cameraEntity.addComponent('script');
cameraEntity.script.create("orbitCamera", {
attributes: {
inertiaFactor: 0.2,
focusEntity: houseEntity,
distanceMax: 400,
frameOnStart: true
}
});
cameraEntity.script.create("orbitCameraInputMouse");
cameraEntity.script.create("orbitCameraInputTouch");
cameraEntity.setLocalPosition(0, 40, -220);
cameraEntity.lookAt(0, 0, 100);
app.root.addChild(cameraEntity);

// add a shadow casting directional light
const lightColor = new pc.Color(1, 1, 1);
const light = new pc.Entity();
light.addComponent('light', {
type: 'directional',
color: lightColor,
intensity: 0.2,
range: 700,
shadowResolution: 4096,
shadowDistance: 600,
castShadows: true,
shadowBias: 0.2,
normalOffsetBias: 0.05
});
app.root.addChild(light);
light.setLocalEulerAngles(40, 10, 0);

// ------ Custom render passes set up ------

const currentOptions = {
camera: cameraEntity.camera, // camera used to render those passes
samples: 0, // number of samples for multi-sampling
// sceneColorMap: true, // true if the scene color should be captured
sceneColorMap: false,

// enable the pre-pass to generate the depth buffer, which is needed by the TAA
prepassEnabled: true,

// enable temporal anti-aliasing
taaEnabled: true
};

const setupRenderPass = () => {
// destroy existing pass if any
if (cameraEntity.camera.renderPasses.length > 0) {
cameraEntity.camera.renderPasses[0].destroy();
}

// Use a render pass camera frame, which is a render pass that implements typical rendering of a camera.
// Internally this sets up additional passes it needs, based on the options passed to it.
const renderPassCamera = new pcx.RenderPassCameraFrame(app, currentOptions);

const composePass = renderPassCamera.composePass;
composePass.toneMapping = data.get('data.scene.tonemapping');
composePass.bloomIntensity = 0.02;

// and set up these rendering passes to be used by the camera, instead of its default rendering
cameraEntity.camera.renderPasses = [renderPassCamera];
};

// ------

const applySettings = () => {

// if settings require render passes to be re-created
const noPasses = cameraEntity.camera.renderPasses.length === 0;
const taaEnabled = data.get('data.taa.enabled');
if (noPasses || taaEnabled !== currentOptions.taaEnabled) {
currentOptions.taaEnabled = taaEnabled;

// create new pass
setupRenderPass();
}


// apply all runtime settings
const renderPassCamera = cameraEntity.camera.renderPasses[0];
renderPassCamera.renderTargetScale = data.get('data.scene.scale');
renderPassCamera.bloomEnabled = data.get('data.scene.bloom');

// taa - enable camera jitter if taa is enabled
cameraEntity.camera.jitter = taaEnabled ? data.get('data.taa.jitter') : 0;
};

// apply UI changes
let initialValuesSetup = false;
data.on('*:set', () => {
if (initialValuesSetup) applySettings();
});

// set initial values
data.set('data', {
scene: {
scale: 1,
bloom: true,
tonemapping: pc.TONEMAP_ACES
},
taa: {
enabled: currentOptions.taaEnabled,
jitter: 1
}
});

// apply initial settings after all values are set
initialValuesSetup = true;
applySettings();
});

export { app };
Binary file added examples/thumbnails/graphics_taa_large.webp
Binary file not shown.
Binary file added examples/thumbnails/graphics_taa_small.webp
Binary file not shown.
Binary file added examples/thumbnails/loaders_bundle_large.webp
Binary file not shown.
Binary file added examples/thumbnails/loaders_bundle_small.webp
Binary file not shown.
Loading

0 comments on commit c9fef33

Please sign in to comment.