From 3ca9ed785de3e97192cf1b48c28b8e098f8be778 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Sat, 16 Dec 2023 19:27:16 +0100 Subject: [PATCH 1/2] faster XR experience --- src/ts/playground.ts | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/src/ts/playground.ts b/src/ts/playground.ts index df36f9c69..6384bbc66 100644 --- a/src/ts/playground.ts +++ b/src/ts/playground.ts @@ -5,9 +5,6 @@ import { Vector3 } from "@babylonjs/core/Maths/math.vector"; import { OceanPostProcess } from "./postProcesses/oceanPostProcess"; import { UberScene } from "./uberCore/uberScene"; import { translate } from "./uberCore/transforms/basicTransform"; -import { PointLightWrapper, TransformNodeWrapper } from "./utils/wrappers"; -import { MeshBuilder } from "@babylonjs/core/Meshes/meshBuilder"; -import { PointLight } from "@babylonjs/core/Lights/pointLight"; import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera"; import { Engine } from "@babylonjs/core/Engines/engine"; @@ -22,8 +19,9 @@ import { Quaternion } from "@babylonjs/core/Maths/math"; import { FlatCloudsPostProcess } from "./postProcesses/clouds/flatCloudsPostProcess"; import { AtmosphericScatteringPostProcess } from "./postProcesses/atmosphericScatteringPostProcess"; import { Star } from "./stellarObjects/star/star"; -import { VolumetricLight } from "./postProcesses/volumetricLight"; import { LensFlarePostProcess } from "./postProcesses/lensFlarePostProcess"; +import { Settings } from "./settings"; +import { ScenePerformancePriority } from "@babylonjs/core"; const canvas = document.getElementById("renderer") as HTMLCanvasElement; canvas.width = window.innerWidth; @@ -32,13 +30,15 @@ canvas.height = window.innerHeight; const engine = new Engine(canvas, true); engine.useReverseDepthBuffer = true; +Settings.VERTEX_RESOLUTION = 32; + // Init Havok physics engine const havokInstance = await HavokPhysics(); const havokPlugin = new HavokPlugin(true, havokInstance); setMaxLinVel(havokPlugin, 10000, 10000); console.log(`Havok initialized`); -const scene = new UberScene(engine); +const scene = new UberScene(engine, ScenePerformancePriority.Intermediate); scene.useRightHandedSystem = true; scene.enablePhysics(Vector3.Zero(), havokPlugin); @@ -89,7 +89,7 @@ const planet = new TelluricPlanemo("xrPlanet", scene, 0.51, undefined); translate(planet.getTransform(), new Vector3(0, 0, sphereRadius * 4)); const star = new Star("star", scene, 0.2); //PointLightWrapper(new PointLight("dir01", new Vector3(0, 1, 0), scene)); -translate(star.getTransform(), new Vector3(0, 0, -sphereRadius * 1000)); +translate(star.getTransform(), new Vector3(0, 0, -sphereRadius * 5000)); const starfield = new StarfieldPostProcess(scene, [star], [planet], Quaternion.Identity()); camera.attachPostProcess(starfield); @@ -107,19 +107,15 @@ FlatCloudsPostProcess.CreateAsync("clouds", planet, planet.model.cloudsUniforms, const atmosphere = new AtmosphericScatteringPostProcess("atmosphere", planet, 100e3, scene, [star]); camera.attachPostProcess(atmosphere); xrCamera.attachPostProcess(atmosphere); -}); -const volumetricLight = new VolumetricLight(star, scene); -camera.attachPostProcess(volumetricLight); -xrCamera.attachPostProcess(volumetricLight); - -const lensflare = new LensFlarePostProcess(star, scene); -camera.attachPostProcess(lensflare); -xrCamera.attachPostProcess(lensflare); + const lensflare = new LensFlarePostProcess(star, scene); + camera.attachPostProcess(lensflare); + xrCamera.attachPostProcess(lensflare); +}); -const chunkForge = new ChunkForge(64); +const chunkForge = new ChunkForge(Settings.VERTEX_RESOLUTION); -scene.onBeforePhysicsObservable.add(() => { +scene.onBeforeRenderObservable.add(() => { const deltaTime = scene.deltaTime / 1000; if (scene.activeCamera === null) throw new Error("Active camera is null"); @@ -131,7 +127,6 @@ scene.onBeforePhysicsObservable.add(() => { } planet.updateLOD(scene.activeCamera.globalPosition, chunkForge); - planet.computeCulling(camera); planet.updateMaterial(camera, [star], deltaTime); chunkForge.update(); From f9d9a114267cdca8e26fe855f430e30f9eaf8e22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Barth=C3=A9lemy?= <31370477+BarthPaleologue@users.noreply.github.com> Date: Sat, 16 Dec 2023 19:32:46 +0100 Subject: [PATCH 2/2] made xr its own entrypoint - removed xr from playground --- src/ts/playground.ts | 41 ------------ src/ts/xr.ts | 148 +++++++++++++++++++++++++++++++++++++++++++ webpack.config.js | 12 ++-- 3 files changed, 156 insertions(+), 45 deletions(-) create mode 100644 src/ts/xr.ts diff --git a/src/ts/playground.ts b/src/ts/playground.ts index 6384bbc66..cb7823189 100644 --- a/src/ts/playground.ts +++ b/src/ts/playground.ts @@ -8,7 +8,6 @@ import { translate } from "./uberCore/transforms/basicTransform"; import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera"; import { Engine } from "@babylonjs/core/Engines/engine"; -import "@babylonjs/core"; import HavokPhysics from "@babylonjs/havok"; import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin"; import { setMaxLinVel } from "./utils/havok"; @@ -30,8 +29,6 @@ canvas.height = window.innerHeight; const engine = new Engine(canvas, true); engine.useReverseDepthBuffer = true; -Settings.VERTEX_RESOLUTION = 32; - // Init Havok physics engine const havokInstance = await HavokPhysics(); const havokPlugin = new HavokPlugin(true, havokInstance); @@ -52,39 +49,6 @@ camera.speed *= sphereRadius * 0.1; scene.setActiveCamera(camera); camera.attachControl(canvas, true); -const xr = await scene.createDefaultXRExperienceAsync(); -if (!xr.baseExperience) { - // no xr support - throw new Error("No XR support"); -} else { - // all good, ready to go - console.log("XR support"); -} - -const webXRInput = xr.input; // if using the experience helper, otherwise, an instance of WebXRInput -webXRInput.onControllerAddedObservable.add((xrController) => { - console.log("Controller added"); - xrController.onMotionControllerInitObservable.add((motionController) => { - console.log("Motion controller initialized"); - - const mainComponent = motionController.getMainComponent(); - - mainComponent.onButtonStateChangedObservable.add((component) => { - if (component.changes.pressed) { - if (component.changes.pressed.current) { - console.log("Pressed"); - } - if (component.pressed) { - console.log("Pressed"); - } - } - }); - }); -}); - -const xrCamera = xr.baseExperience.camera; -xrCamera.setTransformationFromNonVRCamera(camera); - const planet = new TelluricPlanemo("xrPlanet", scene, 0.51, undefined); translate(planet.getTransform(), new Vector3(0, 0, sphereRadius * 4)); @@ -93,24 +57,19 @@ translate(star.getTransform(), new Vector3(0, 0, -sphereRadius * 5000)); const starfield = new StarfieldPostProcess(scene, [star], [planet], Quaternion.Identity()); camera.attachPostProcess(starfield); -xrCamera.attachPostProcess(starfield); const ocean = new OceanPostProcess("ocean", planet, scene, [star]); camera.attachPostProcess(ocean); -xrCamera.attachPostProcess(ocean); if (planet.model.cloudsUniforms === null) throw new Error("Clouds uniforms are null"); FlatCloudsPostProcess.CreateAsync("clouds", planet, planet.model.cloudsUniforms, scene, [star]).then((clouds) => { camera.attachPostProcess(clouds); - xrCamera.attachPostProcess(clouds); const atmosphere = new AtmosphericScatteringPostProcess("atmosphere", planet, 100e3, scene, [star]); camera.attachPostProcess(atmosphere); - xrCamera.attachPostProcess(atmosphere); const lensflare = new LensFlarePostProcess(star, scene); camera.attachPostProcess(lensflare); - xrCamera.attachPostProcess(lensflare); }); const chunkForge = new ChunkForge(Settings.VERTEX_RESOLUTION); diff --git a/src/ts/xr.ts b/src/ts/xr.ts new file mode 100644 index 000000000..271f7d265 --- /dev/null +++ b/src/ts/xr.ts @@ -0,0 +1,148 @@ +import "../styles/index.scss"; + +import { Assets } from "./assets"; +import { Vector3 } from "@babylonjs/core/Maths/math.vector"; +import { OceanPostProcess } from "./postProcesses/oceanPostProcess"; +import { UberScene } from "./uberCore/uberScene"; +import { translate } from "./uberCore/transforms/basicTransform"; +import { FreeCamera } from "@babylonjs/core/Cameras/freeCamera"; +import { Engine } from "@babylonjs/core/Engines/engine"; + +import HavokPhysics from "@babylonjs/havok"; +import { HavokPlugin } from "@babylonjs/core/Physics/v2/Plugins/havokPlugin"; +import { setMaxLinVel } from "./utils/havok"; +import { TelluricPlanemo } from "./planemos/telluricPlanemo/telluricPlanemo"; +import { ChunkForge } from "./planemos/telluricPlanemo/terrain/chunks/chunkForge"; +import { StarfieldPostProcess } from "./postProcesses/starfieldPostProcess"; +import { Quaternion } from "@babylonjs/core/Maths/math"; +import { FlatCloudsPostProcess } from "./postProcesses/clouds/flatCloudsPostProcess"; +import { AtmosphericScatteringPostProcess } from "./postProcesses/atmosphericScatteringPostProcess"; +import { Star } from "./stellarObjects/star/star"; +import { LensFlarePostProcess } from "./postProcesses/lensFlarePostProcess"; +import { Settings } from "./settings"; +import { ScenePerformancePriority } from "@babylonjs/core"; + +const canvas = document.getElementById("renderer") as HTMLCanvasElement; +canvas.width = window.innerWidth; +canvas.height = window.innerHeight; + +const engine = new Engine(canvas, true); +engine.useReverseDepthBuffer = true; + +Settings.VERTEX_RESOLUTION = 32; + +// Init Havok physics engine +const havokInstance = await HavokPhysics(); +const havokPlugin = new HavokPlugin(true, havokInstance); +setMaxLinVel(havokPlugin, 10000, 10000); +console.log(`Havok initialized`); + +const scene = new UberScene(engine, ScenePerformancePriority.Intermediate); +scene.useRightHandedSystem = true; +scene.enablePhysics(Vector3.Zero(), havokPlugin); + +await Assets.Init(scene); + +const sphereRadius = Settings.EARTH_RADIUS; + +const camera = new FreeCamera("camera", new Vector3(0, 0, 0), scene); +camera.maxZ = 1e9; +camera.speed *= sphereRadius * 0.1; +scene.setActiveCamera(camera); +camera.attachControl(canvas, true); + +const xr = await scene.createDefaultXRExperienceAsync(); +if (!xr.baseExperience) { + // no xr support + throw new Error("No XR support"); +} else { + // all good, ready to go + console.log("XR support"); +} + +const webXRInput = xr.input; // if using the experience helper, otherwise, an instance of WebXRInput +webXRInput.onControllerAddedObservable.add((xrController) => { + console.log("Controller added"); + xrController.onMotionControllerInitObservable.add((motionController) => { + console.log("Motion controller initialized"); + + const mainComponent = motionController.getMainComponent(); + + mainComponent.onButtonStateChangedObservable.add((component) => { + if (component.changes.pressed) { + if (component.changes.pressed.current) { + console.log("Pressed"); + } + if (component.pressed) { + console.log("Pressed"); + } + } + }); + }); +}); + +const xrCamera = xr.baseExperience.camera; +xrCamera.setTransformationFromNonVRCamera(camera); + +const planet = new TelluricPlanemo("xrPlanet", scene, 0.51, undefined); +translate(planet.getTransform(), new Vector3(0, 0, sphereRadius * 4)); + +const star = new Star("star", scene, 0.2); //PointLightWrapper(new PointLight("dir01", new Vector3(0, 1, 0), scene)); +translate(star.getTransform(), new Vector3(0, 0, -sphereRadius * 5000)); + +const starfield = new StarfieldPostProcess(scene, [star], [planet], Quaternion.Identity()); +camera.attachPostProcess(starfield); +xrCamera.attachPostProcess(starfield); + +const ocean = new OceanPostProcess("ocean", planet, scene, [star]); +camera.attachPostProcess(ocean); +xrCamera.attachPostProcess(ocean); + +if (planet.model.cloudsUniforms === null) throw new Error("Clouds uniforms are null"); +FlatCloudsPostProcess.CreateAsync("clouds", planet, planet.model.cloudsUniforms, scene, [star]).then((clouds) => { + camera.attachPostProcess(clouds); + xrCamera.attachPostProcess(clouds); + + const atmosphere = new AtmosphericScatteringPostProcess("atmosphere", planet, 100e3, scene, [star]); + camera.attachPostProcess(atmosphere); + xrCamera.attachPostProcess(atmosphere); + + const lensflare = new LensFlarePostProcess(star, scene); + camera.attachPostProcess(lensflare); + xrCamera.attachPostProcess(lensflare); +}); + +const chunkForge = new ChunkForge(Settings.VERTEX_RESOLUTION); + +scene.onBeforeRenderObservable.add(() => { + const deltaTime = scene.deltaTime / 1000; + + if (scene.activeCamera === null) throw new Error("Active camera is null"); + + if (camera.globalPosition.length() > 0) { + translate(planet.getTransform(), camera.globalPosition.negate()); + translate(star.getTransform(), camera.globalPosition.negate()); + camera.position.set(0, 0, 0); + } + + planet.updateLOD(scene.activeCamera.globalPosition, chunkForge); + planet.updateMaterial(camera, [star], deltaTime); + + chunkForge.update(); + + star.updateMaterial(); + + ocean.update(deltaTime); +}); + +scene.executeWhenReady(() => { + engine.runRenderLoop(() => { + scene.render(); + }); +}); + +window.addEventListener("resize", () => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + engine.resize(true); +}); diff --git a/webpack.config.js b/webpack.config.js index 6b7213c90..5969200a9 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,7 +8,6 @@ const isProduction = process.env.NODE_ENV === "production"; const htmlPath = path.join(__dirname, "/src/html/"); const config = { - entry: { showcase: "./src/ts/index.ts", random: "./src/ts/randomizer.ts", @@ -16,6 +15,7 @@ const config = { physicSpaceship: "./src/ts/physicSpaceship.ts", planetWalk: "./src/ts/planetWalk.ts", playground: "./src/ts/playground.ts", + xr: "./src/ts/xr.ts", debugAssets: "./src/ts/debugAssets.ts" }, output: { @@ -27,7 +27,7 @@ const config = { historyApiFallback: false, headers: { "Cross-Origin-Opener-Policy": "same-origin", - "Cross-Origin-Embedder-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "same-origin" } }, @@ -68,6 +68,12 @@ const config = { template: path.join(htmlPath, "index.html"), chunks: ["playground"] }), + new HtmlWebpackPlugin({ + title: "XR", + filename: "xr.html", + template: path.join(htmlPath, "index.html"), + chunks: ["xr"] + }), new HtmlWebpackPlugin({ title: "Debug Texture", filename: "debugassets.html", @@ -77,7 +83,6 @@ const config = { new MiniCssExtractPlugin() ], - module: { rules: [ { @@ -111,7 +116,6 @@ const config = { use: ["ts-shader-loader"] } - // Add your rules for custom modules here // Learn more about loaders from https://webpack.js.org/loaders/ ]