refactor: separate scene from main

This commit is contained in:
FMS-Cat
2021-03-15 14:25:33 +09:00
parent a6a6036495
commit 78bfd15d20
4 changed files with 251 additions and 204 deletions

View File

@@ -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,

View File

@@ -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();

222
src/scene.ts Normal file
View File

@@ -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<T extends { entity: Entity }> {
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 );
}

View File

@@ -0,0 +1,8 @@
export function arraySetDelete<T>( array: Array<T>, element: T ): boolean {
const index = array.indexOf( element );
if ( index !== -1 ) {
array.splice( index, 1 );
return true;
}
return false;
}