mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-10-03 00:11:53 +02:00
refactor: separate scene from main
This commit is contained in:
@@ -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,
|
||||
|
177
src/main.ts
177
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();
|
||||
|
222
src/scene.ts
Normal file
222
src/scene.ts
Normal 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 );
|
||||
}
|
8
src/utils/arraySetDelete.ts
Normal file
8
src/utils/arraySetDelete.ts
Normal 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;
|
||||
}
|
Reference in New Issue
Block a user