From 4f182f02735744565b81b7dcad0aa8d1eae0171f Mon Sep 17 00:00:00 2001 From: arorad1 Date: Fri, 19 Jul 2024 20:04:42 -0700 Subject: [PATCH 01/11] Adding basic Cascading Shadows implementation --- fission/src/systems/scene/CascadingShadows.ts | 94 +++++++++++++++++++ fission/src/systems/scene/SceneRenderer.ts | 36 ++++--- 2 files changed, 115 insertions(+), 15 deletions(-) create mode 100644 fission/src/systems/scene/CascadingShadows.ts diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts new file mode 100644 index 0000000000..f80a61f237 --- /dev/null +++ b/fission/src/systems/scene/CascadingShadows.ts @@ -0,0 +1,94 @@ +import * as THREE from 'three'; + +class CascadingShadows { + private _camera: THREE.PerspectiveCamera; + private _shadowCameras: THREE.OrthographicCamera[] = []; + private _scene: THREE.Scene; + + private _renderer: THREE.WebGLRenderer; + private _light: THREE.DirectionalLight; + private _shadowMaps: THREE.WebGLRenderTarget[] = []; // One shadow map per cascade + + private _numCascades: number; + private _cascadeSplits: number[]; + + constructor(camera: THREE.PerspectiveCamera, scene: THREE.Scene, renderer: THREE.WebGLRenderer, numCascades: number = 5) { + this._camera = camera; + this._scene = scene; + this._renderer = renderer; + this._numCascades = numCascades; + + // Creating the directional light + this._light = new THREE.DirectionalLight(0xffffff, 3); + this._light.position.set(-1, 3, 2); + this._light.castShadow = true; + scene.add(this._light); + + // Split the camera frustum into numCascades cascades + this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades); + + // Create the shadow camera and shadow maps + for (let i = 0; i < numCascades; i++) { + const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500); + shadowCamera.position.copy(this._light.position); + shadowCamera.lookAt(0, 0, 0); + this._shadowCameras.push(shadowCamera); + + const shadowMap = new THREE.WebGLRenderTarget(1024, 1024, { + minFilter: THREE.NearestFilter, + magFilter: THREE.NearestFilter, + format: THREE.RGBAFormat, + }); + this._shadowMaps.push(shadowMap); + } + } + + /** Updates the shadow maps */ + public Update() { + const frustum = new THREE.Frustum(); + const projScreenMatrix = new THREE.Matrix4(); + projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse); + frustum.setFromProjectionMatrix(projScreenMatrix); + + for (let i = 0; i < this._numCascades; i++) { + const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near); + const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near); + + const cascadeFrustum = new THREE.Frustum(); + cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)); + + const shadowCamera = this._shadowCameras[i]; + shadowCamera.position.copy(this._light.position); + shadowCamera.lookAt(0, 0, 0); + shadowCamera.updateMatrixWorld(); + shadowCamera.updateProjectionMatrix(); + + this._renderer.setRenderTarget(this._shadowMaps[i]); + this._renderer.render(this._scene, shadowCamera); + } + + this._renderer.setRenderTarget(null); + } + + /** Returns the projection matrix for the cascade */ + private GetCascadeMatrix(near: number, far: number): THREE.Matrix4 { + const matrix = new THREE.Matrix4(); + const projMatrix = new THREE.Matrix4().makePerspective( + this._camera.fov, + this._camera.aspect, + near, + far, + this._camera.near, + this._camera.far + ); + const invMatrix = this._camera.matrixWorld.invert(); + matrix.multiplyMatrices(projMatrix, invMatrix); + return matrix; + } + + public getShadowMap(index: number): THREE.WebGLRenderTarget { + return this._shadowMaps[index]; + } +} + +export default CascadingShadows; diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 1590a15c9a..6458b6508a 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -14,6 +14,7 @@ import InputSystem from "../input/InputSystem" import { PixelSpaceCoord, SceneOverlayEvent, SceneOverlayEventKey } from "@/ui/components/SceneOverlayEvents" import {} from "@/ui/components/SceneOverlayEvents" import PreferencesSystem from "../preferences/PreferencesSystem" +import CascadingShadows from "./CascadingShadows" const CLEAR_COLOR = 0x121212 const GROUND_COLOR = 0x4066c7 @@ -34,6 +35,8 @@ class SceneRenderer extends WorldSystem { private _orbitControls: OrbitControls private _transformControls: Map // maps all rendered transform controls to their size + private _light: CascadingShadows + public get sceneObjects() { return this._sceneObjects } @@ -74,23 +77,25 @@ class SceneRenderer extends WorldSystem { this._renderer.shadowMap.type = THREE.PCFSoftShadowMap this._renderer.setSize(window.innerWidth, window.innerHeight) - const directionalLight = new THREE.DirectionalLight(0xffffff, 3.0) - directionalLight.position.set(-1.0, 3.0, 2.0) - directionalLight.castShadow = true - this._scene.add(directionalLight) + // const directionalLight = new THREE.DirectionalLight(0xffffff, 3.0) + // directionalLight.position.set(-1.0, 3.0, 2.0) + // directionalLight.castShadow = true + // this._scene.add(directionalLight) + + // const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) + // const shadowCamSize = 15 + // console.debug(`Shadow Map Size: ${shadowMapSize}`) - const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) - const shadowCamSize = 15 - console.debug(`Shadow Map Size: ${shadowMapSize}`) + // directionalLight.shadow.camera.top = shadowCamSize + // directionalLight.shadow.camera.bottom = -shadowCamSize + // directionalLight.shadow.camera.left = -shadowCamSize + // directionalLight.shadow.camera.right = shadowCamSize + // directionalLight.shadow.mapSize = new THREE.Vector2(shadowMapSize, shadowMapSize) + // directionalLight.shadow.blurSamples = 16 + // directionalLight.shadow.normalBias = 0.01 + // directionalLight.shadow.bias = 0.0 - directionalLight.shadow.camera.top = shadowCamSize - directionalLight.shadow.camera.bottom = -shadowCamSize - directionalLight.shadow.camera.left = -shadowCamSize - directionalLight.shadow.camera.right = shadowCamSize - directionalLight.shadow.mapSize = new THREE.Vector2(shadowMapSize, shadowMapSize) - directionalLight.shadow.blurSamples = 16 - directionalLight.shadow.normalBias = 0.01 - directionalLight.shadow.bias = 0.0 + this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) this._scene.add(ambientLight) @@ -143,6 +148,7 @@ class SceneRenderer extends WorldSystem { this._sceneObjects.forEach(obj => { obj.Update() }) + this._light.Update() this._skybox.position.copy(this._mainCamera.position) From 323386e0b7e0900e8ed0eed854597ec81983ac20 Mon Sep 17 00:00:00 2001 From: arorad1 Date: Fri, 19 Jul 2024 20:08:16 -0700 Subject: [PATCH 02/11] Formatting --- fission/src/systems/scene/CascadingShadows.ts | 109 +++++++++--------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts index f80a61f237..65d7a11667 100644 --- a/fission/src/systems/scene/CascadingShadows.ts +++ b/fission/src/systems/scene/CascadingShadows.ts @@ -1,78 +1,83 @@ -import * as THREE from 'three'; +import * as THREE from "three" class CascadingShadows { - private _camera: THREE.PerspectiveCamera; - private _shadowCameras: THREE.OrthographicCamera[] = []; - private _scene: THREE.Scene; - - private _renderer: THREE.WebGLRenderer; - private _light: THREE.DirectionalLight; - private _shadowMaps: THREE.WebGLRenderTarget[] = []; // One shadow map per cascade - - private _numCascades: number; - private _cascadeSplits: number[]; - - constructor(camera: THREE.PerspectiveCamera, scene: THREE.Scene, renderer: THREE.WebGLRenderer, numCascades: number = 5) { - this._camera = camera; - this._scene = scene; - this._renderer = renderer; - this._numCascades = numCascades; + private _camera: THREE.PerspectiveCamera + private _shadowCameras: THREE.OrthographicCamera[] = [] + private _scene: THREE.Scene + + private _renderer: THREE.WebGLRenderer + private _light: THREE.DirectionalLight + private _shadowMaps: THREE.WebGLRenderTarget[] = [] // One shadow map per cascade + + private _numCascades: number + private _cascadeSplits: number[] + + constructor( + camera: THREE.PerspectiveCamera, + scene: THREE.Scene, + renderer: THREE.WebGLRenderer, + numCascades: number = 5 + ) { + this._camera = camera + this._scene = scene + this._renderer = renderer + this._numCascades = numCascades // Creating the directional light - this._light = new THREE.DirectionalLight(0xffffff, 3); - this._light.position.set(-1, 3, 2); - this._light.castShadow = true; - scene.add(this._light); - + this._light = new THREE.DirectionalLight(0xffffff, 3) + this._light.position.set(-1, 3, 2) + this._light.castShadow = true + scene.add(this._light) + // Split the camera frustum into numCascades cascades - this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades); + this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades) // Create the shadow camera and shadow maps for (let i = 0; i < numCascades; i++) { - const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500); - shadowCamera.position.copy(this._light.position); - shadowCamera.lookAt(0, 0, 0); - this._shadowCameras.push(shadowCamera); + const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500) + shadowCamera.position.copy(this._light.position) + shadowCamera.lookAt(0, 0, 0) + this._shadowCameras.push(shadowCamera) const shadowMap = new THREE.WebGLRenderTarget(1024, 1024, { minFilter: THREE.NearestFilter, magFilter: THREE.NearestFilter, format: THREE.RGBAFormat, - }); - this._shadowMaps.push(shadowMap); + }) + this._shadowMaps.push(shadowMap) } } /** Updates the shadow maps */ public Update() { - const frustum = new THREE.Frustum(); - const projScreenMatrix = new THREE.Matrix4(); - projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse); - frustum.setFromProjectionMatrix(projScreenMatrix); + const frustum = new THREE.Frustum() + const projScreenMatrix = new THREE.Matrix4() + projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse) + frustum.setFromProjectionMatrix(projScreenMatrix) for (let i = 0; i < this._numCascades; i++) { - const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near); - const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near); + const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near) + const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near) - const cascadeFrustum = new THREE.Frustum(); - cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)); + const cascadeFrustum = new THREE.Frustum() + cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)) - const shadowCamera = this._shadowCameras[i]; - shadowCamera.position.copy(this._light.position); - shadowCamera.lookAt(0, 0, 0); - shadowCamera.updateMatrixWorld(); - shadowCamera.updateProjectionMatrix(); + const shadowCamera = this._shadowCameras[i] + shadowCamera.position.copy(this._light.position) + shadowCamera.lookAt(0, 0, 0) + shadowCamera.updateMatrixWorld() + shadowCamera.updateProjectionMatrix() - this._renderer.setRenderTarget(this._shadowMaps[i]); - this._renderer.render(this._scene, shadowCamera); + this._renderer.setRenderTarget(this._shadowMaps[i]) + this._renderer.render(this._scene, shadowCamera) } - this._renderer.setRenderTarget(null); + this._renderer.setRenderTarget(null) } /** Returns the projection matrix for the cascade */ private GetCascadeMatrix(near: number, far: number): THREE.Matrix4 { - const matrix = new THREE.Matrix4(); + const matrix = new THREE.Matrix4() const projMatrix = new THREE.Matrix4().makePerspective( this._camera.fov, this._camera.aspect, @@ -80,15 +85,15 @@ class CascadingShadows { far, this._camera.near, this._camera.far - ); - const invMatrix = this._camera.matrixWorld.invert(); - matrix.multiplyMatrices(projMatrix, invMatrix); - return matrix; + ) + const invMatrix = this._camera.matrixWorld.invert() + matrix.multiplyMatrices(projMatrix, invMatrix) + return matrix } public getShadowMap(index: number): THREE.WebGLRenderTarget { - return this._shadowMaps[index]; + return this._shadowMaps[index] } } -export default CascadingShadows; +export default CascadingShadows From e716d0ba0c329f0ae3644981a36d0360f5536928 Mon Sep 17 00:00:00 2001 From: arorad1 Date: Mon, 22 Jul 2024 11:57:24 -0700 Subject: [PATCH 03/11] Changing light color and intensity and removing old lighting implementation --- fission/src/systems/scene/CascadingShadows.ts | 2 +- fission/src/systems/scene/SceneRenderer.ts | 18 ------------------ 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts index 65d7a11667..b1b9d5b4a2 100644 --- a/fission/src/systems/scene/CascadingShadows.ts +++ b/fission/src/systems/scene/CascadingShadows.ts @@ -24,7 +24,7 @@ class CascadingShadows { this._numCascades = numCascades // Creating the directional light - this._light = new THREE.DirectionalLight(0xffffff, 3) + this._light = new THREE.DirectionalLight(0xb6c6e3, 5.0) this._light.position.set(-1, 3, 2) this._light.castShadow = true scene.add(this._light) diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 6458b6508a..a4af554078 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -77,24 +77,6 @@ class SceneRenderer extends WorldSystem { this._renderer.shadowMap.type = THREE.PCFSoftShadowMap this._renderer.setSize(window.innerWidth, window.innerHeight) - // const directionalLight = new THREE.DirectionalLight(0xffffff, 3.0) - // directionalLight.position.set(-1.0, 3.0, 2.0) - // directionalLight.castShadow = true - // this._scene.add(directionalLight) - - // const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) - // const shadowCamSize = 15 - // console.debug(`Shadow Map Size: ${shadowMapSize}`) - - // directionalLight.shadow.camera.top = shadowCamSize - // directionalLight.shadow.camera.bottom = -shadowCamSize - // directionalLight.shadow.camera.left = -shadowCamSize - // directionalLight.shadow.camera.right = shadowCamSize - // directionalLight.shadow.mapSize = new THREE.Vector2(shadowMapSize, shadowMapSize) - // directionalLight.shadow.blurSamples = 16 - // directionalLight.shadow.normalBias = 0.01 - // directionalLight.shadow.bias = 0.0 - this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) From c85ad83d2d85e1c35346b03af05a20126e7bcdfa Mon Sep 17 00:00:00 2001 From: arorad1 Date: Wed, 24 Jul 2024 15:57:10 -0700 Subject: [PATCH 04/11] Adding changes to using the implementation built in --- fission/src/mirabuf/MirabufInstance.ts | 2 + fission/src/systems/scene/CascadingShadows.ts | 99 ------------------- fission/src/systems/scene/SceneRenderer.ts | 59 +++++++++-- 3 files changed, 54 insertions(+), 106 deletions(-) delete mode 100644 fission/src/systems/scene/CascadingShadows.ts diff --git a/fission/src/mirabuf/MirabufInstance.ts b/fission/src/mirabuf/MirabufInstance.ts index 174cbcbff3..d1a75656a6 100644 --- a/fission/src/mirabuf/MirabufInstance.ts +++ b/fission/src/mirabuf/MirabufInstance.ts @@ -149,8 +149,10 @@ class MirabufInstance { opacity: opacity, transparent: opacity < 1.0, }) + World.SceneRenderer.SetupMaterial(material) } else if (materialStyle == MaterialStyle.Normals) { material = new THREE.MeshNormalMaterial() + World.SceneRenderer.SetupMaterial(material) } else if (materialStyle == MaterialStyle.Toon) { material = World.SceneRenderer.CreateToonMaterial(hex, 5) console.debug("Toon Material") diff --git a/fission/src/systems/scene/CascadingShadows.ts b/fission/src/systems/scene/CascadingShadows.ts deleted file mode 100644 index b1b9d5b4a2..0000000000 --- a/fission/src/systems/scene/CascadingShadows.ts +++ /dev/null @@ -1,99 +0,0 @@ -import * as THREE from "three" - -class CascadingShadows { - private _camera: THREE.PerspectiveCamera - private _shadowCameras: THREE.OrthographicCamera[] = [] - private _scene: THREE.Scene - - private _renderer: THREE.WebGLRenderer - private _light: THREE.DirectionalLight - private _shadowMaps: THREE.WebGLRenderTarget[] = [] // One shadow map per cascade - - private _numCascades: number - private _cascadeSplits: number[] - - constructor( - camera: THREE.PerspectiveCamera, - scene: THREE.Scene, - renderer: THREE.WebGLRenderer, - numCascades: number = 5 - ) { - this._camera = camera - this._scene = scene - this._renderer = renderer - this._numCascades = numCascades - - // Creating the directional light - this._light = new THREE.DirectionalLight(0xb6c6e3, 5.0) - this._light.position.set(-1, 3, 2) - this._light.castShadow = true - scene.add(this._light) - - // Split the camera frustum into numCascades cascades - this._cascadeSplits = new Array(numCascades).fill(0).map((_, i) => (i + 1) / numCascades) - - // Create the shadow camera and shadow maps - for (let i = 0; i < numCascades; i++) { - const shadowCamera = new THREE.OrthographicCamera(-10, 10, 10, -10, 0.5, 500) - shadowCamera.position.copy(this._light.position) - shadowCamera.lookAt(0, 0, 0) - this._shadowCameras.push(shadowCamera) - - const shadowMap = new THREE.WebGLRenderTarget(1024, 1024, { - minFilter: THREE.NearestFilter, - magFilter: THREE.NearestFilter, - format: THREE.RGBAFormat, - }) - this._shadowMaps.push(shadowMap) - } - } - - /** Updates the shadow maps */ - public Update() { - const frustum = new THREE.Frustum() - const projScreenMatrix = new THREE.Matrix4() - projScreenMatrix.multiplyMatrices(this._camera.projectionMatrix, this._camera.matrixWorldInverse) - frustum.setFromProjectionMatrix(projScreenMatrix) - - for (let i = 0; i < this._numCascades; i++) { - const near = this._camera.near + this._cascadeSplits[i] * (this._camera.far - this._camera.near) - const far = this._camera.near + this._cascadeSplits[i + 1] * (this._camera.far - this._camera.near) - - const cascadeFrustum = new THREE.Frustum() - cascadeFrustum.setFromProjectionMatrix(this.GetCascadeMatrix(near, far)) - - const shadowCamera = this._shadowCameras[i] - shadowCamera.position.copy(this._light.position) - shadowCamera.lookAt(0, 0, 0) - shadowCamera.updateMatrixWorld() - shadowCamera.updateProjectionMatrix() - - this._renderer.setRenderTarget(this._shadowMaps[i]) - this._renderer.render(this._scene, shadowCamera) - } - - this._renderer.setRenderTarget(null) - } - - /** Returns the projection matrix for the cascade */ - private GetCascadeMatrix(near: number, far: number): THREE.Matrix4 { - const matrix = new THREE.Matrix4() - const projMatrix = new THREE.Matrix4().makePerspective( - this._camera.fov, - this._camera.aspect, - near, - far, - this._camera.near, - this._camera.far - ) - const invMatrix = this._camera.matrixWorld.invert() - matrix.multiplyMatrices(projMatrix, invMatrix) - return matrix - } - - public getShadowMap(index: number): THREE.WebGLRenderTarget { - return this._shadowMaps[index] - } -} - -export default CascadingShadows diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index a4af554078..2567e0a6b6 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -12,9 +12,9 @@ import { Theme } from "@/ui/ThemeContext" import InputSystem from "../input/InputSystem" import { PixelSpaceCoord, SceneOverlayEvent, SceneOverlayEventKey } from "@/ui/components/SceneOverlayEvents" -import {} from "@/ui/components/SceneOverlayEvents" import PreferencesSystem from "../preferences/PreferencesSystem" -import CascadingShadows from "./CascadingShadows" +import { CSM } from "three/examples/jsm/csm/CSM.js" +import { CSMHelper } from "three/examples/jsm/csm/CSMHelper.js" const CLEAR_COLOR = 0x121212 const GROUND_COLOR = 0x4066c7 @@ -35,7 +35,8 @@ class SceneRenderer extends WorldSystem { private _orbitControls: OrbitControls private _transformControls: Map // maps all rendered transform controls to their size - private _light: CascadingShadows + private _csm: CSM + // private _csmHelper: CSMHelper public get sceneObjects() { return this._sceneObjects @@ -77,7 +78,35 @@ class SceneRenderer extends WorldSystem { this._renderer.shadowMap.type = THREE.PCFSoftShadowMap this._renderer.setSize(window.innerWidth, window.innerHeight) - this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) + // this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) + const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) + this._csm = new CSM({ + maxFar: 30, + cascades: 3, + mode: 'custom', + parent: this._scene, + shadowMapSize: shadowMapSize, + lightDirection: new THREE.Vector3( 0.5, -0.5, 0.5 ).normalize(), + lightIntensity: 3, + camera: this._mainCamera, + customSplitsCallback: (cascades: number, near: number, far: number, breaks: number[]) => { + const blend = 0.4; + for (let i = 1; i < cascades; i++) { + const uniformFactor = (near + (far - near) * i / cascades) / far; + const logarithmicFactor = (near * (far / near) ** (i / cascades)) / far; + const combinedFactor = uniformFactor * (1 - blend) + logarithmicFactor * blend; + + breaks.push(combinedFactor); + } + + breaks.push(1); + } + }) + this._csm.fade = true + + // this._csmHelper = new CSMHelper(this._csm) + // this._csmHelper.visible = true + // this._scene.add(this._csmHelper) const ambientLight = new THREE.AmbientLight(0xffffff, 0.1) this._scene.add(ambientLight) @@ -85,7 +114,7 @@ class SceneRenderer extends WorldSystem { const ground = new THREE.Mesh(new THREE.BoxGeometry(10, 1, 10), this.CreateToonMaterial(GROUND_COLOR)) ground.position.set(0.0, -2.0, 0.0) ground.receiveShadow = true - ground.castShadow = true + ground.castShadow = false this._scene.add(ground) // Adding spherical skybox mesh @@ -117,6 +146,11 @@ class SceneRenderer extends WorldSystem { // Orbit controls this._orbitControls = new OrbitControls(this._mainCamera, this._renderer.domElement) this._orbitControls.update() + + const cube = new THREE.Mesh(new THREE.BoxGeometry(1, 1, 1), this.CreateToonMaterial()) + cube.castShadow = true + cube.receiveShadow = true + this._scene.add(cube) } public UpdateCanvasSize() { @@ -130,7 +164,11 @@ class SceneRenderer extends WorldSystem { this._sceneObjects.forEach(obj => { obj.Update() }) - this._light.Update() + + this._mainCamera.updateMatrixWorld() + + this._csm.update() + // this._csmHelper.update() this._skybox.position.copy(this._mainCamera.position) @@ -177,6 +215,7 @@ class SceneRenderer extends WorldSystem { public CreateSphere(radius: number, material?: THREE.Material | undefined): THREE.Mesh { const geo = new THREE.SphereGeometry(radius) if (material) { + this._csm.setupMaterial(material) return new THREE.Mesh(geo, material) } else { return new THREE.Mesh(geo, this.CreateToonMaterial()) @@ -191,10 +230,12 @@ class SceneRenderer extends WorldSystem { } const gradientMap = new THREE.DataTexture(colors, colors.length, 1, format) gradientMap.needsUpdate = true - return new THREE.MeshToonMaterial({ + const material = new THREE.MeshToonMaterial({ color: color, gradientMap: gradientMap, }) + this._csm.setupMaterial(material) + return material } /** @@ -337,6 +378,10 @@ class SceneRenderer extends WorldSystem { public RemoveObject(obj: THREE.Object3D) { this._scene.remove(obj) } + + public SetupMaterial(material: THREE.Material) { + this._csm.setupMaterial(material) + } } export default SceneRenderer From 28dab58f3782d4f929f5300ec147d5c5664c3a83 Mon Sep 17 00:00:00 2001 From: Dhruv Arora Date: Thu, 25 Jul 2024 16:24:12 -0700 Subject: [PATCH 05/11] Adding quality changing functionality Co-authored-by: BrandonPacewic --- fission/src/systems/scene/SceneRenderer.ts | 47 +++++++++++++++---- .../ui/modals/configuring/SettingsModal.tsx | 4 +- 2 files changed, 42 insertions(+), 9 deletions(-) diff --git a/fission/src/systems/scene/SceneRenderer.ts b/fission/src/systems/scene/SceneRenderer.ts index 2567e0a6b6..8905670b64 100644 --- a/fission/src/systems/scene/SceneRenderer.ts +++ b/fission/src/systems/scene/SceneRenderer.ts @@ -79,18 +79,14 @@ class SceneRenderer extends WorldSystem { this._renderer.setSize(window.innerWidth, window.innerHeight) // this._light = new CascadingShadows(this._mainCamera, this._scene, this._renderer) - const shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) this._csm = new CSM({ - maxFar: 30, - cascades: 3, - mode: 'custom', parent: this._scene, - shadowMapSize: shadowMapSize, + camera: this._mainCamera, + cascades: 3, lightDirection: new THREE.Vector3( 0.5, -0.5, 0.5 ).normalize(), lightIntensity: 3, - camera: this._mainCamera, customSplitsCallback: (cascades: number, near: number, far: number, breaks: number[]) => { - const blend = 0.4; + const blend = 0.7; for (let i = 1; i < cascades; i++) { const uniformFactor = (near + (far - near) * i / cascades) / far; const logarithmicFactor = (near * (far / near) ** (i / cascades)) / far; @@ -103,7 +99,9 @@ class SceneRenderer extends WorldSystem { } }) this._csm.fade = true - + + this.ChangeQuality(PreferencesSystem.getGlobalPreference("QualitySettings")) + // this._csmHelper = new CSMHelper(this._csm) // this._csmHelper.visible = true // this._scene.add(this._csmHelper) @@ -168,6 +166,7 @@ class SceneRenderer extends WorldSystem { this._mainCamera.updateMatrixWorld() this._csm.update() + console.log(this._csm.shadowMapSize) // this._csmHelper.update() this._skybox.position.copy(this._mainCamera.position) @@ -192,6 +191,38 @@ class SceneRenderer extends WorldSystem { this.RemoveAllSceneObjects() } + public ChangeQuality(quality: string): void { + console.log("Changing quality to", quality) + + if (quality === "Low") { + + this._csm.shadowMapSize = Math.min(1024, this._renderer.capabilities.maxTextureSize) + this._csm.mode = "uniform" + this._csm.maxFar = 10 + + } else if (quality === "Medium") { + + this.renderer.setPixelRatio(window.devicePixelRatio) + + this._csm.shadowMapSize = Math.min(2048, this._renderer.capabilities.maxTextureSize) + this._csm.mode = "practical" + this._csm.maxFar = 20 + + } else if (quality === "High") { + + this.renderer.setPixelRatio(window.devicePixelRatio) + + this._csm.shadowMapSize = Math.min(4096, this._renderer.capabilities.maxTextureSize) + this._csm.mode = "custom" + this._csm.maxFar = 30 + + } + + this._csm.initCascades() + this._csm.updateShadowBounds() + this._csm.updateFrustums() + } + public RegisterSceneObject(obj: T): number { const id = nextSceneObjectId++ obj.id = id diff --git a/fission/src/ui/modals/configuring/SettingsModal.tsx b/fission/src/ui/modals/configuring/SettingsModal.tsx index 4c001c5771..bdde73f20b 100644 --- a/fission/src/ui/modals/configuring/SettingsModal.tsx +++ b/fission/src/ui/modals/configuring/SettingsModal.tsx @@ -9,6 +9,7 @@ import Slider from "@/components/Slider" import Checkbox from "@/components/Checkbox" import PreferencesSystem from "@/systems/preferences/PreferencesSystem" import { SceneOverlayEvent, SceneOverlayEventKey } from "@/ui/components/SceneOverlayEvents" +import World from "@/systems/World" const moveElementToTop = (arr: string[], element: string | undefined) => { if (element == undefined) { @@ -20,7 +21,7 @@ const moveElementToTop = (arr: string[], element: string | undefined) => { } const screenModeOptions = ["Windowed", "Fullscreen"] -const qualitySettingsOptions = ["Low", "Medium", "High", "Ultra"] +const qualitySettingsOptions = ["Low", "Medium", "High"] const SettingsModal: React.FC = ({ modalId }) => { const { openModal } = useModalControlContext() @@ -91,6 +92,7 @@ const SettingsModal: React.FC = ({ modalId }) => { )} onSelect={selected => { setQualitySettings(selected) + World.SceneRenderer.ChangeQuality(selected) }} />