From 78bfd15d20c7ceb74df4a0a8360030c41ea91e69 Mon Sep 17 00:00:00 2001 From: FMS-Cat Date: Mon, 15 Mar 2021 14:25:33 +0900 Subject: [PATCH] refactor: separate scene from main --- src/entities/FlickyParticles.ts | 48 +++---- src/main.ts | 177 +------------------------ src/scene.ts | 222 ++++++++++++++++++++++++++++++++ src/utils/arraySetDelete.ts | 8 ++ 4 files changed, 251 insertions(+), 204 deletions(-) create mode 100644 src/scene.ts create mode 100644 src/utils/arraySetDelete.ts diff --git a/src/entities/FlickyParticles.ts b/src/entities/FlickyParticles.ts index a7a4221..1d1270d 100644 --- a/src/entities/FlickyParticles.ts +++ b/src/entities/FlickyParticles.ts @@ -1,4 +1,3 @@ -import { GLCatTexture } from '@fms-cat/glcat-ts'; import { Entity } from '../heck/Entity'; import { GPUParticles } from './GPUParticles'; import { Geometry } from '../heck/Geometry'; @@ -12,9 +11,8 @@ import { TRIANGLE_STRIP_QUAD } from '@fms-cat/experimental'; import { gl, glCat } from '../globals/canvas'; import { randomTexture, randomTextureStatic } from '../globals/randomTexture'; -export interface FlickyParticlesOptions { - particlesSqrt: number; -} +const PARTICLES_SQRT = 8; +const PARTICLES = PARTICLES_SQRT * PARTICLES_SQRT; export class FlickyParticles { public get entity(): Entity { @@ -31,25 +29,22 @@ export class FlickyParticles { return this.__gpuParticles.materialRender; } - public constructor( options: FlickyParticlesOptions ) { + public constructor() { this.__gpuParticles = new GPUParticles( { - materialCompute: this.__createMaterialCompute( options ), - geometryRender: this.__createGeometryRender( options ), - materialRender: this.__createMaterialRender( options ), - computeWidth: options.particlesSqrt, - computeHeight: options.particlesSqrt, + materialCompute: this.__createMaterialCompute(), + geometryRender: this.__createGeometryRender(), + materialRender: this.__createMaterialRender(), + computeWidth: PARTICLES_SQRT, + computeHeight: PARTICLES_SQRT, computeNumBuffers: 1, namePrefix: process.env.DEV && 'FlickyParticles', } ); } - private __createMaterialCompute( options: FlickyParticlesOptions ): Material { - const { particlesSqrt } = options; - const particles = particlesSqrt * particlesSqrt; - + private __createMaterialCompute(): Material { const material = new Material( quadVert, flickyParticleComputeFrag ); - material.addUniform( 'particlesSqrt', '1f', particlesSqrt ); - material.addUniform( 'particles', '1f', particles ); + material.addUniform( 'particlesSqrt', '1f', PARTICLES_SQRT ); + material.addUniform( 'particles', '1f', PARTICLES ); material.addUniformTexture( 'samplerRandom', randomTexture.texture ); if ( process.env.DEV ) { @@ -63,10 +58,7 @@ export class FlickyParticles { return material; } - private __createGeometryRender( options: FlickyParticlesOptions ): Geometry { - const { particlesSqrt } = options; - const particles = particlesSqrt * particlesSqrt; - + private __createGeometryRender(): Geometry { const geometry = new InstancedGeometry(); const bufferP = glCat.createBuffer(); @@ -80,12 +72,12 @@ export class FlickyParticles { const bufferComputeUV = glCat.createBuffer(); bufferComputeUV.setVertexbuffer( ( () => { - const ret = new Float32Array( particles * 2 ); - for ( let iy = 0; iy < particlesSqrt; iy ++ ) { - for ( let ix = 0; ix < particlesSqrt; ix ++ ) { - const i = ix + iy * particlesSqrt; - const s = ( ix + 0.5 ) / particlesSqrt; - const t = ( iy + 0.5 ) / particlesSqrt; + const ret = new Float32Array( PARTICLES * 2 ); + for ( let iy = 0; iy < PARTICLES_SQRT; iy ++ ) { + for ( let ix = 0; ix < PARTICLES_SQRT; ix ++ ) { + const i = ix + iy * PARTICLES_SQRT; + const s = ( ix + 0.5 ) / PARTICLES_SQRT; + const t = ( iy + 0.5 ) / PARTICLES_SQRT; ret[ i * 2 + 0 ] = s; ret[ i * 2 + 1 ] = t; } @@ -102,12 +94,12 @@ export class FlickyParticles { geometry.count = 4; geometry.mode = gl.TRIANGLE_STRIP; - geometry.primcount = options.particlesSqrt * options.particlesSqrt; + geometry.primcount = PARTICLES; return geometry; } - private __createMaterialRender( options: FlickyParticlesOptions ): Material { + private __createMaterialRender(): Material { const material = new Material( flickyParticleRenderVert, flickyParticleRenderFrag, diff --git a/src/main.ts b/src/main.ts index 4b88517..c735366 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,29 +1,9 @@ import { canvas } from './globals/canvas'; -import { Dog } from './heck/Dog'; -import { CanvasRenderTarget } from './heck/CanvasRenderTarget'; -import { Lambda } from './heck/components/Lambda'; -import { randomTexture } from './globals/randomTexture'; -import { SphereParticles } from './entities/SphereParticles'; -import { Swap, Vector3 } from '@fms-cat/experimental'; import { BufferRenderTarget } from './heck/BufferRenderTarget'; -import { CameraEntity } from './entities/CameraEntity'; -import { LightEntity } from './entities/LightEntity'; -import { Bloom } from './entities/Bloom'; -import { Post } from './entities/Post'; -import { Raymarcher } from './entities/Raymarcher'; -import { Trails } from './entities/Trails'; -import { Glitch } from './entities/Glitch'; -import { Rings } from './entities/Rings'; -import { RTInspector } from './entities/RTInspector'; import { Component } from './heck/components/Component'; -import { FlickyParticles } from './entities/FlickyParticles'; -import { PixelSorter } from './entities/PixelSorter'; -import { IBLLUT } from './entities/IBLLUT'; -import { EnvironmentMap } from './entities/EnvironmentMap'; -import { Cube } from './entities/Cube'; import { music } from './globals/music'; -import { automaton } from './globals/automaton'; import { getCheckboxActive } from './globals/dom'; +import { dog } from './scene'; // == music ======================================================================================== if ( process.env.DEV ) { @@ -60,161 +40,6 @@ if ( process.env.DEV ) { }; } -// == scene ======================================================================================== -let totalFrame = 0; -let isInitialFrame = true; - -const dog = new Dog(); - -const canvasRenderTarget = new CanvasRenderTarget(); - -// Mr. Update Everything -dog.root.components.push( new Lambda( { - onUpdate: () => { - totalFrame ++; - isInitialFrame = false; - - randomTexture.update(); - automaton.update( music.time ); - }, - visible: false, - name: process.env.DEV && 'main/update', -} ) ); - -// -- bake ----------------------------------------------------------------------------------------- -const ibllut = new IBLLUT(); -dog.root.children.push( ibllut.entity ); - -const environmentMap = new EnvironmentMap(); -dog.root.children.push( environmentMap.entity ); - -// -- "objects" ------------------------------------------------------------------------------------ -const sphereParticles = new SphereParticles(); -dog.root.children.push( sphereParticles.entity ); - -const trails = new Trails(); -dog.root.children.push( trails.entity ); - -const rings = new Rings(); -dog.root.children.push( rings.entity ); - -const cube = new Cube(); -dog.root.children.push( cube.entity ); - -const flickyParticles = new FlickyParticles( { - particlesSqrt: 8, -} ); -dog.root.children.push( flickyParticles.entity ); - -const raymarcher = new Raymarcher(); -dog.root.children.push( raymarcher.entity ); - -// -- things that is not an "object" --------------------------------------------------------------- -const swapOptions = { - width: canvasRenderTarget.width, - height: canvasRenderTarget.height -}; - -const swap = new Swap( - new BufferRenderTarget( { - ...swapOptions, - name: process.env.DEV && 'main/postSwap0', - } ), - new BufferRenderTarget( { - ...swapOptions, - name: process.env.DEV && 'main/postSwap1', - } ), -); - -const light = new LightEntity( { - root: dog.root, - shadowMapFov: 90.0, - shadowMapNear: 1.0, - shadowMapFar: 20.0, - namePrefix: process.env.DEV && 'light1', -} ); -light.color = [ 40.0, 40.0, 40.0 ]; -light.entity.transform.lookAt( new Vector3( [ -1.0, 2.0, 8.0 ] ) ); -dog.root.children.push( light.entity ); - -// const light2 = new LightEntity( { -// root: dog.root, -// shadowMapFov: 90.0, -// shadowMapNear: 1.0, -// shadowMapFar: 20.0, -// namePrefix: process.env.DEV && 'light2', -// } ); -// light2.color = [ 50.0, 30.0, 40.0 ]; -// light2.entity.transform.lookAt( new Vector3( [ -4.0, -2.0, 6.0 ] ) ); -// dog.root.children.push( light2.entity ); - -const camera = new CameraEntity( { - root: dog.root, - target: swap.o, - lights: [ - light, - // light2 - ], - textureIBLLUT: ibllut.texture, - textureEnv: environmentMap.texture, -} ); -camera.camera.clear = [ 0.0, 0.0, 0.0, 0.0 ]; -camera.entity.components.unshift( new Lambda( { - onUpdate: ( event ) => { - const t1 = 0.02 * Math.sin( event.time ); - const s1 = Math.sin( t1 ); - const c1 = Math.cos( t1 ); - const t2 = 0.02 * Math.cos( event.time ); - const s2 = Math.sin( t2 ); - const c2 = Math.cos( t2 ); - const r = 5.0; - - camera.entity.transform.lookAt( new Vector3( [ - r * c1 * s2, - r * s1, - r * c1 * c2 - ] ) ); - }, - visible: false, - name: process.env.DEV && 'main/updateCamera', -} ) ); -dog.root.children.push( camera.entity ); - -swap.swap(); -const bloom = new Bloom( { - input: swap.i, - target: swap.o -} ); -dog.root.children.push( bloom.entity ); - -swap.swap(); -const glitch = new Glitch( { - input: swap.i, - target: swap.o, -} ); -dog.root.children.push( glitch.entity ); - -swap.swap(); -const pixelSorter = new PixelSorter( { - input: swap.i, - target: swap.o, -} ); -dog.root.children.push( pixelSorter.entity ); - -swap.swap(); -const post = new Post( { - input: swap.i, - target: canvasRenderTarget -} ); -dog.root.children.push( post.entity ); - -if ( process.env.DEV ) { - const rtInspector = new RTInspector( { - target: canvasRenderTarget - } ); - dog.root.children.push( rtInspector.entity ); -} - // -- keyboards ------------------------------------------------------------------------------------ if ( process.env.DEV ) { const checkboxActive = getCheckboxActive(); diff --git a/src/scene.ts b/src/scene.ts new file mode 100644 index 0000000..f86e7f8 --- /dev/null +++ b/src/scene.ts @@ -0,0 +1,222 @@ +import { Swap, Vector3 } from '@fms-cat/experimental'; +import { Bloom } from './entities/Bloom'; +import { CameraEntity } from './entities/CameraEntity'; +import { Cube } from './entities/Cube'; +import { EnvironmentMap } from './entities/EnvironmentMap'; +import { FlickyParticles } from './entities/FlickyParticles'; +import { Glitch } from './entities/Glitch'; +import { IBLLUT } from './entities/IBLLUT'; +import { LightEntity } from './entities/LightEntity'; +import { PixelSorter } from './entities/PixelSorter'; +import { Post } from './entities/Post'; +import { Raymarcher } from './entities/Raymarcher'; +import { Rings } from './entities/Rings'; +import { RTInspector } from './entities/RTInspector'; +import { SphereParticles } from './entities/SphereParticles'; +import { Trails } from './entities/Trails'; +import { automaton } from './globals/automaton'; +import { music } from './globals/music'; +import { randomTexture } from './globals/randomTexture'; +import { BufferRenderTarget } from './heck/BufferRenderTarget'; +import { CanvasRenderTarget } from './heck/CanvasRenderTarget'; +import { Lambda } from './heck/components/Lambda'; +import { Dog } from './heck/Dog'; +import { Entity } from './heck/Entity'; +import { arraySetDelete } from './utils/arraySetDelete'; + +let totalFrame = 0; +let isInitialFrame = true; + +// -- dog ------------------------------------------------------------------------------------------ +export const dog = new Dog(); + +const canvasRenderTarget = new CanvasRenderTarget(); + +// Mr. Update Everything +dog.root.components.push( new Lambda( { + onUpdate: () => { + totalFrame ++; + isInitialFrame = false; + + randomTexture.update(); + automaton.update( music.time ); + }, + visible: false, + name: process.env.DEV && 'main/update', +} ) ); + +// -- util ----------------------------------------------------------------------------------------- +class EntityReplacer { + public current?: T; + public creator: () => T; + + public constructor( creator: () => T ) { + this.creator = creator; + this.replace(); + } + + public replace(): void { + if ( this.current ) { + arraySetDelete( dog.root.children, this.current.entity ); + } + + this.current = this.creator(); + dog.root.children.push( this.current.entity ); + } +} + +// -- bake ----------------------------------------------------------------------------------------- +const ibllut = new IBLLUT(); +dog.root.children.push( ibllut.entity ); + +const environmentMap = new EnvironmentMap(); +dog.root.children.push( environmentMap.entity ); + +// -- "objects" ------------------------------------------------------------------------------------ +const replacerSphereParticles = new EntityReplacer( () => new SphereParticles() ); +if ( process.env.DEV && module.hot ) { + module.hot.accept( './entities/SphereParticles', () => { + replacerSphereParticles.replace(); + } ); +} + +const replacerTrails = new EntityReplacer( () => new Trails() ); +if ( process.env.DEV && module.hot ) { + module.hot.accept( './entities/Trails', () => { + replacerTrails.replace(); + } ); +} + +const replacerRings = new EntityReplacer( () => new Rings() ); +if ( process.env.DEV && module.hot ) { + module.hot.accept( './entities/Rings', () => { + replacerRings.replace(); + } ); +} + +const replacerCube = new EntityReplacer( () => new Cube() ); +if ( process.env.DEV && module.hot ) { + module.hot.accept( './entities/Cube', () => { + replacerCube.replace(); + } ); +} + +const replacerFlickyParticles = new EntityReplacer( () => new FlickyParticles() ); +if ( process.env.DEV && module.hot ) { + module.hot.accept( './entities/FlickyParticles', () => { + replacerFlickyParticles.replace(); + } ); +} + +const replacerRaymarcher = new EntityReplacer( () => new Raymarcher() ); +if ( process.env.DEV && module.hot ) { + module.hot.accept( './entities/Raymarcher', () => { + replacerRaymarcher.replace(); + } ); +} + +// -- things that is not an "object" --------------------------------------------------------------- +const swapOptions = { + width: canvasRenderTarget.width, + height: canvasRenderTarget.height +}; + +const swap = new Swap( + new BufferRenderTarget( { + ...swapOptions, + name: process.env.DEV && 'main/postSwap0', + } ), + new BufferRenderTarget( { + ...swapOptions, + name: process.env.DEV && 'main/postSwap1', + } ), +); + +const light = new LightEntity( { + root: dog.root, + shadowMapFov: 90.0, + shadowMapNear: 1.0, + shadowMapFar: 20.0, + namePrefix: process.env.DEV && 'light1', +} ); +light.color = [ 40.0, 40.0, 40.0 ]; +light.entity.transform.lookAt( new Vector3( [ -1.0, 2.0, 8.0 ] ) ); +dog.root.children.push( light.entity ); + +// const light2 = new LightEntity( { +// root: dog.root, +// shadowMapFov: 90.0, +// shadowMapNear: 1.0, +// shadowMapFar: 20.0, +// namePrefix: process.env.DEV && 'light2', +// } ); +// light2.color = [ 50.0, 30.0, 40.0 ]; +// light2.entity.transform.lookAt( new Vector3( [ -4.0, -2.0, 6.0 ] ) ); +// dog.root.children.push( light2.entity ); + +const camera = new CameraEntity( { + root: dog.root, + target: swap.o, + lights: [ + light, + // light2 + ], + textureIBLLUT: ibllut.texture, + textureEnv: environmentMap.texture, +} ); +camera.camera.clear = [ 0.0, 0.0, 0.0, 0.0 ]; +camera.entity.components.unshift( new Lambda( { + onUpdate: ( event ) => { + const t1 = 0.02 * Math.sin( event.time ); + const s1 = Math.sin( t1 ); + const c1 = Math.cos( t1 ); + const t2 = 0.02 * Math.cos( event.time ); + const s2 = Math.sin( t2 ); + const c2 = Math.cos( t2 ); + const r = 5.0; + + camera.entity.transform.lookAt( new Vector3( [ + r * c1 * s2, + r * s1, + r * c1 * c2 + ] ) ); + }, + visible: false, + name: process.env.DEV && 'main/updateCamera', +} ) ); +dog.root.children.push( camera.entity ); + +swap.swap(); +const bloom = new Bloom( { + input: swap.i, + target: swap.o +} ); +dog.root.children.push( bloom.entity ); + +swap.swap(); +const glitch = new Glitch( { + input: swap.i, + target: swap.o, +} ); +dog.root.children.push( glitch.entity ); + +swap.swap(); +const pixelSorter = new PixelSorter( { + input: swap.i, + target: swap.o, +} ); +dog.root.children.push( pixelSorter.entity ); + +swap.swap(); +const post = new Post( { + input: swap.i, + target: canvasRenderTarget +} ); +dog.root.children.push( post.entity ); + +if ( process.env.DEV ) { + const rtInspector = new RTInspector( { + target: canvasRenderTarget + } ); + dog.root.children.push( rtInspector.entity ); +} diff --git a/src/utils/arraySetDelete.ts b/src/utils/arraySetDelete.ts new file mode 100644 index 0000000..eabe999 --- /dev/null +++ b/src/utils/arraySetDelete.ts @@ -0,0 +1,8 @@ +export function arraySetDelete( array: Array, element: T ): boolean { + const index = array.indexOf( element ); + if ( index !== -1 ) { + array.splice( index, 1 ); + return true; + } + return false; +}