mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-08-09 07:26:28 +02:00
party version
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -2,13 +2,13 @@ export const
|
|||||||
RTINSPECTOR_MULTIPLE = false,
|
RTINSPECTOR_MULTIPLE = false,
|
||||||
// RTINSPECTOR_MULTIPLE = true,
|
// RTINSPECTOR_MULTIPLE = true,
|
||||||
RTINSPECTOR_CAPTURE_NAME: string | null = null,
|
RTINSPECTOR_CAPTURE_NAME: string | null = null,
|
||||||
// RTINSPECTOR_CAPTURE_NAME: string | null = 'PixelSorter/index',
|
// RTINSPECTOR_CAPTURE_NAME: string | null = 'SSR/quad',
|
||||||
// RTINSPECTOR_CAPTURE_NAME: string | null = 'Greetings/intermediate0',
|
// RTINSPECTOR_CAPTURE_NAME: string | null = 'Greetings/intermediate0',
|
||||||
// RTINSPECTOR_CAPTURE_NAME: string | null = 'main/postSwap0',
|
// RTINSPECTOR_CAPTURE_NAME: string | null = 'main/postSwap0',
|
||||||
// RTINSPECTOR_CAPTURE_NAME: string | null = 'EnvironmentMap/swap0',
|
// RTINSPECTOR_CAPTURE_NAME: string | null = 'EnvironmentMap/swap0',
|
||||||
// RTINSPECTOR_CAPTURE_NAME: string | null = 'DeferredCamera/cameraTarget',
|
// RTINSPECTOR_CAPTURE_NAME: string | null = 'DeferredCamera/cameraTarget',
|
||||||
RTINSPECTOR_CAPTURE_INDEX = 0,
|
RTINSPECTOR_CAPTURE_INDEX = 3,
|
||||||
COMPONENT_UPDATE_BREAKPOINT: string | null = null,
|
COMPONENT_UPDATE_BREAKPOINT: string | null = null,
|
||||||
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'ForwardCamera/camera',
|
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic2/shadowMapCamera',
|
||||||
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic1/shadowMapCamera',
|
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic1/shadowMapCamera',
|
||||||
COMPONENT_DRAW_BREAKPOINT: string | null = null;
|
COMPONENT_DRAW_BREAKPOINT: string | null = null;
|
||||||
|
100
src/entities/BigBlur.ts
Normal file
100
src/entities/BigBlur.ts
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
import { Blit } from '../heck/components/Blit';
|
||||||
|
import { BufferRenderTarget } from '../heck/BufferRenderTarget';
|
||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { Quad } from '../heck/components/Quad';
|
||||||
|
import { RenderTarget } from '../heck/RenderTarget';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
import { dummyRenderTarget } from '../globals/dummyRenderTarget';
|
||||||
|
import { quadGeometry } from '../globals/quadGeometry';
|
||||||
|
import bigBlurFrag from '../shaders/big-blur.frag';
|
||||||
|
import quadVert from '../shaders/quad.vert';
|
||||||
|
|
||||||
|
export interface BigBlurOptions {
|
||||||
|
input: BufferRenderTarget;
|
||||||
|
target: RenderTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class BigBlur extends Entity {
|
||||||
|
public constructor( options: BigBlurOptions ) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const entityBypass = new Entity();
|
||||||
|
entityBypass.visible = false;
|
||||||
|
this.children.push( entityBypass );
|
||||||
|
|
||||||
|
const entityMain = new Entity();
|
||||||
|
entityMain.active = false;
|
||||||
|
entityMain.visible = false;
|
||||||
|
this.children.push( entityMain );
|
||||||
|
|
||||||
|
// -- bypass -----------------------------------------------------------------------------------
|
||||||
|
entityBypass.components.push( new Blit( {
|
||||||
|
src: options.input,
|
||||||
|
dst: options.target,
|
||||||
|
name: 'BigBlur/blitBypass',
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
// -- h ----------------------------------------------------------------------------------------
|
||||||
|
const targetH = new BufferRenderTarget( {
|
||||||
|
width: options.target.width,
|
||||||
|
height: options.target.height,
|
||||||
|
name: process.env.DEV && 'BigBlur/targetH',
|
||||||
|
} );
|
||||||
|
|
||||||
|
const materialH = new Material(
|
||||||
|
quadVert,
|
||||||
|
bigBlurFrag,
|
||||||
|
{ initOptions: { geometry: quadGeometry, target: dummyRenderTarget } },
|
||||||
|
);
|
||||||
|
materialH.addUniformTexture( 'sampler0', options.input.texture );
|
||||||
|
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/big-blur.frag', () => {
|
||||||
|
materialH.replaceShader( quadVert, bigBlurFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
const quadH = new Quad( {
|
||||||
|
target: targetH,
|
||||||
|
material: materialH,
|
||||||
|
name: process.env.DEV && 'BigBlur/quadH',
|
||||||
|
} );
|
||||||
|
entityMain.components.push( quadH );
|
||||||
|
|
||||||
|
// -- h ----------------------------------------------------------------------------------------
|
||||||
|
const materialV = new Material(
|
||||||
|
quadVert,
|
||||||
|
bigBlurFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'IS_VERTICAL 1' ],
|
||||||
|
initOptions: { geometry: quadGeometry, target: dummyRenderTarget }
|
||||||
|
},
|
||||||
|
);
|
||||||
|
materialV.addUniformTexture( 'sampler0', targetH.texture );
|
||||||
|
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/big-blur.frag', () => {
|
||||||
|
materialV.replaceShader( quadVert, bigBlurFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
const quadV = new Quad( {
|
||||||
|
target: options.target,
|
||||||
|
material: materialV,
|
||||||
|
name: process.env.DEV && 'BigBlur/quad',
|
||||||
|
} );
|
||||||
|
entityMain.components.push( quadV );
|
||||||
|
|
||||||
|
// -- update uniform ---------------------------------------------------------------------------
|
||||||
|
auto( 'BigBlur/amp', ( { value } ) => {
|
||||||
|
materialH.addUniform( 'ratio', '1f', Math.min( 1.0, 100.0 * value ) );
|
||||||
|
materialH.addUniform( 'sigma', '1f', 100.0 * value );
|
||||||
|
materialV.addUniform( 'ratio', '1f', Math.min( 1.0, 100.0 * value ) );
|
||||||
|
materialV.addUniform( 'sigma', '1f', 100.0 * value );
|
||||||
|
|
||||||
|
entityMain.active = 0.0 < value;
|
||||||
|
entityBypass.active = !entityMain.active;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
@@ -4,11 +4,11 @@ import { BeamShot } from './BeamShot';
|
|||||||
import { Entity } from '../heck/Entity';
|
import { Entity } from '../heck/Entity';
|
||||||
import { Geometry } from '../heck/Geometry';
|
import { Geometry } from '../heck/Geometry';
|
||||||
import { Lambda } from '../heck/components/Lambda';
|
import { Lambda } from '../heck/components/Lambda';
|
||||||
import { Material } from '../heck/Material';
|
import { Material, MaterialMap } from '../heck/Material';
|
||||||
import { Mesh, MeshCull } from '../heck/components/Mesh';
|
import { Mesh, MeshCull } from '../heck/components/Mesh';
|
||||||
import { Vector3 } from '@fms-cat/experimental';
|
import { Vector3 } from '@fms-cat/experimental';
|
||||||
import { auto } from '../globals/automaton';
|
import { auto } from '../globals/automaton';
|
||||||
import { dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||||
import { genCube } from '../geometries/genCube';
|
import { genCube } from '../geometries/genCube';
|
||||||
import { objectValuesMap } from '../utils/objectEntriesMap';
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
import crystalFrag from '../shaders/crystal.frag';
|
import crystalFrag from '../shaders/crystal.frag';
|
||||||
@@ -49,44 +49,52 @@ export class Crystal extends Entity {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// I don't think we need this
|
const depth = new Material(
|
||||||
// const depth = new Material(
|
raymarchObjectVert,
|
||||||
// raymarchObjectVert,
|
crystalFrag,
|
||||||
// crystalFrag,
|
{
|
||||||
// {
|
defines: [ 'DEPTH 1' ],
|
||||||
// defines: [ 'DEPTH 1' ],
|
initOptions: { geometry, target: dummyRenderTarget }
|
||||||
// initOptions: { geometry, target: dummyRenderTarget }
|
},
|
||||||
// },
|
);
|
||||||
// );
|
|
||||||
|
|
||||||
const materials = { deferred };
|
const materials: MaterialMap = { deferred };
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
if ( module.hot ) {
|
if ( module.hot ) {
|
||||||
module.hot.accept( '../shaders/crystal.frag', () => {
|
module.hot.accept( '../shaders/crystal.frag', () => {
|
||||||
deferred.replaceShader( raymarchObjectVert, crystalFrag );
|
deferred.replaceShader( raymarchObjectVert, crystalFrag );
|
||||||
// depth.replaceShader( raymarchObjectVert, crystalFrag );
|
depth.replaceShader( raymarchObjectVert, crystalFrag );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objectValuesMap( materials, ( material ) => {
|
objectValuesMap( materials, ( material ) => {
|
||||||
material.addUniform( 'size', '2f', width, height );
|
material?.addUniform( 'size', '2f', width, height );
|
||||||
material.addUniform( 'noiseOffset', '1f', noiseOffset );
|
material?.addUniform( 'noiseOffset', '1f', noiseOffset );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// haha
|
||||||
|
auto( 'Crystal/enableDepth', ( { uninit } ) => {
|
||||||
|
if ( uninit ) {
|
||||||
|
delete materials.depth;
|
||||||
|
} else {
|
||||||
|
materials.depth = depth;
|
||||||
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
// -- updater ----------------------------------------------------------------------------------
|
// -- updater ----------------------------------------------------------------------------------
|
||||||
this.components.push( new Lambda( {
|
this.components.push( new Lambda( {
|
||||||
onDraw: ( event ) => {
|
onDraw: ( event ) => {
|
||||||
objectValuesMap( materials, ( material ) => {
|
objectValuesMap( materials, ( material ) => {
|
||||||
material.addUniform(
|
material?.addUniform(
|
||||||
'cameraNearFar',
|
'cameraNearFar',
|
||||||
'2f',
|
'2f',
|
||||||
event.camera.near,
|
event.camera.near,
|
||||||
event.camera.far
|
event.camera.far
|
||||||
);
|
);
|
||||||
|
|
||||||
material.addUniformMatrixVector(
|
material?.addUniformMatrixVector(
|
||||||
'inversePVM',
|
'inversePVM',
|
||||||
'Matrix4fv',
|
'Matrix4fv',
|
||||||
event.projectionMatrix
|
event.projectionMatrix
|
||||||
|
@@ -49,7 +49,6 @@ export class DeferredCamera extends Entity {
|
|||||||
name: 'DeferredCamera/camera',
|
name: 'DeferredCamera/camera',
|
||||||
materialTag: 'deferred',
|
materialTag: 'deferred',
|
||||||
} );
|
} );
|
||||||
this.camera.clear = [];
|
|
||||||
|
|
||||||
// -- ao ---------------------------------------------------------------------------------------
|
// -- ao ---------------------------------------------------------------------------------------
|
||||||
const aoTarget = new BufferRenderTarget( {
|
const aoTarget = new BufferRenderTarget( {
|
||||||
|
@@ -20,7 +20,7 @@ import greetingsPreLainFrag from '../shaders/greetings-pre-lain.frag';
|
|||||||
import greetingsVert from '../shaders/greetings.vert';
|
import greetingsVert from '../shaders/greetings.vert';
|
||||||
import quadVert from '../shaders/quad.vert';
|
import quadVert from '../shaders/quad.vert';
|
||||||
|
|
||||||
const INSTANCES = 256;
|
const INSTANCES = 64;
|
||||||
|
|
||||||
// -- preprocessor ---------------------------------------------------------------------------------
|
// -- preprocessor ---------------------------------------------------------------------------------
|
||||||
const materialBlurH = new Material(
|
const materialBlurH = new Material(
|
||||||
@@ -171,6 +171,8 @@ const charPosList = [
|
|||||||
'holon',
|
'holon',
|
||||||
'gam0022',
|
'gam0022',
|
||||||
'gaz',
|
'gaz',
|
||||||
|
'gyabo',
|
||||||
|
'iYOYi',
|
||||||
'jetlag',
|
'jetlag',
|
||||||
'Jugem-T',
|
'Jugem-T',
|
||||||
'kaneta',
|
'kaneta',
|
||||||
|
96
src/entities/HooperBall.ts
Normal file
96
src/entities/HooperBall.ts
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { Geometry } from '../heck/Geometry';
|
||||||
|
import { Lambda } from '../heck/components/Lambda';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { Mesh, MeshCull } from '../heck/components/Mesh';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||||
|
import { genOctahedron } from '../geometries/genOctahedron';
|
||||||
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
|
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
||||||
|
import hooperballFrag from '../shaders/hooperball.frag';
|
||||||
|
import raymarchObjectVert from '../shaders/raymarch-object.vert';
|
||||||
|
|
||||||
|
export class Hooperball extends Entity {
|
||||||
|
public constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// -- geometry ---------------------------------------------------------------------------------
|
||||||
|
const octahedron = genOctahedron( { radius: 2.0, div: 1 } );
|
||||||
|
|
||||||
|
const geometry = new Geometry();
|
||||||
|
|
||||||
|
geometry.vao.bindVertexbuffer( octahedron.position, 0, 3 );
|
||||||
|
geometry.vao.bindIndexbuffer( octahedron.index );
|
||||||
|
|
||||||
|
geometry.count = octahedron.count;
|
||||||
|
geometry.mode = octahedron.mode;
|
||||||
|
geometry.indexType = octahedron.indexType;
|
||||||
|
|
||||||
|
// -- materials --------------------------------------------------------------------------------
|
||||||
|
const deferred = new Material(
|
||||||
|
raymarchObjectVert,
|
||||||
|
hooperballFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'DEFERRED 1' ],
|
||||||
|
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const depth = new Material(
|
||||||
|
raymarchObjectVert,
|
||||||
|
hooperballFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'DEPTH 1' ],
|
||||||
|
initOptions: { geometry, target: dummyRenderTarget }
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const materials = { deferred, depth };
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/hooperball.frag', () => {
|
||||||
|
deferred.replaceShader( raymarchObjectVert, hooperballFrag );
|
||||||
|
depth.replaceShader( raymarchObjectVert, hooperballFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- updater ----------------------------------------------------------------------------------
|
||||||
|
this.components.push( new Lambda( {
|
||||||
|
onDraw: ( event ) => {
|
||||||
|
objectValuesMap( materials, ( material ) => {
|
||||||
|
material.addUniform(
|
||||||
|
'cameraNearFar',
|
||||||
|
'2f',
|
||||||
|
event.camera.near,
|
||||||
|
event.camera.far
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniformMatrixVector(
|
||||||
|
'inversePVM',
|
||||||
|
'Matrix4fv',
|
||||||
|
event.projectionMatrix
|
||||||
|
.multiply( event.viewMatrix )
|
||||||
|
.multiply( event.globalTransform.matrix )
|
||||||
|
.inverse!
|
||||||
|
.elements
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniform( 'deformSeed', '1f', auto( 'Hooperball/deformSeed' ) );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
name: process.env.DEV && 'Hooperball/updater',
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
// -- mesh -------------------------------------------------------------------------------------
|
||||||
|
const mesh = new Mesh( {
|
||||||
|
geometry,
|
||||||
|
materials,
|
||||||
|
name: process.env.DEV && 'Hooperball/mesh',
|
||||||
|
} );
|
||||||
|
mesh.cull = MeshCull.None;
|
||||||
|
this.components.push( mesh );
|
||||||
|
}
|
||||||
|
}
|
@@ -8,7 +8,6 @@ import { auto } from '../globals/automaton';
|
|||||||
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||||
import { genCube } from '../geometries/genCube';
|
import { genCube } from '../geometries/genCube';
|
||||||
import { objectValuesMap } from '../utils/objectEntriesMap';
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
|
||||||
import ifsAsUsualFrag from '../shaders/ifs-as-usual.frag';
|
import ifsAsUsualFrag from '../shaders/ifs-as-usual.frag';
|
||||||
import raymarchObjectVert from '../shaders/raymarch-object.vert';
|
import raymarchObjectVert from '../shaders/raymarch-object.vert';
|
||||||
|
|
||||||
@@ -47,7 +46,7 @@ export class IFSAsUsual extends Entity {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const materials = { deferred, depth };
|
const materials = { deferred };
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
if ( module.hot ) {
|
if ( module.hot ) {
|
||||||
@@ -58,11 +57,6 @@ export class IFSAsUsual extends Entity {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
objectValuesMap( materials, ( material ) => {
|
|
||||||
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
|
||||||
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// -- updater ----------------------------------------------------------------------------------
|
// -- updater ----------------------------------------------------------------------------------
|
||||||
this.components.push( new Lambda( {
|
this.components.push( new Lambda( {
|
||||||
onDraw: ( event ) => {
|
onDraw: ( event ) => {
|
||||||
@@ -88,6 +82,22 @@ export class IFSAsUsual extends Entity {
|
|||||||
name: process.env.DEV && 'IFSAsUsual/updater',
|
name: process.env.DEV && 'IFSAsUsual/updater',
|
||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
|
// -- speen ------------------------------------------------------------------------------------
|
||||||
|
const axis = new Vector3( [ 1.0, -1.0, 1.0 ] ).normalized;
|
||||||
|
this.components.push( new Lambda( {
|
||||||
|
onUpdate: ( { time } ) => {
|
||||||
|
this.transform.rotation = Quaternion.fromAxisAngle( axis, time );
|
||||||
|
},
|
||||||
|
name: process.env.DEV && 'IFSAsUsual/updater2',
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
// -- auto -------------------------------------------------------------------------------------
|
||||||
|
auto( 'IFSAsUsual/ifsSeed', ( { value } ) => {
|
||||||
|
objectValuesMap( materials, ( material ) => {
|
||||||
|
material.addUniform( 'ifsSeed', '1f', value );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
||||||
// -- mesh -------------------------------------------------------------------------------------
|
// -- mesh -------------------------------------------------------------------------------------
|
||||||
const mesh = new Mesh( {
|
const mesh = new Mesh( {
|
||||||
geometry,
|
geometry,
|
||||||
@@ -96,17 +106,5 @@ export class IFSAsUsual extends Entity {
|
|||||||
} );
|
} );
|
||||||
mesh.cull = MeshCull.None;
|
mesh.cull = MeshCull.None;
|
||||||
this.components.push( mesh );
|
this.components.push( mesh );
|
||||||
|
|
||||||
// -- speen ------------------------------------------------------------------------------------
|
|
||||||
const axis = new Vector3( [ 1.0, -1.0, 1.0 ] ).normalized;
|
|
||||||
this.components.push( new Lambda( {
|
|
||||||
onUpdate: ( { time } ) => {
|
|
||||||
this.transform.rotation = Quaternion.fromAxisAngle( axis, time );
|
|
||||||
objectValuesMap( materials, ( material ) => {
|
|
||||||
material.addUniform( 'ifsSeed', '1f', auto( 'IFSAsUsual/ifsSeed' ) );
|
|
||||||
} );
|
|
||||||
},
|
|
||||||
name: process.env.DEV && 'IFSAsUsual/update',
|
|
||||||
} ) );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
117
src/entities/PsyField.ts
Normal file
117
src/entities/PsyField.ts
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { Geometry } from '../heck/Geometry';
|
||||||
|
import { Lambda } from '../heck/components/Lambda';
|
||||||
|
import { LightEntity } from './LightEntity';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { Mesh, MeshCull } from '../heck/components/Mesh';
|
||||||
|
import { Vector3 } from '@fms-cat/experimental';
|
||||||
|
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||||
|
import { genCube } from '../geometries/genCube';
|
||||||
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
|
import psyFieldFrag from '../shaders/psy-field.frag';
|
||||||
|
import raymarchObjectVert from '../shaders/raymarch-object.vert';
|
||||||
|
|
||||||
|
export class PsyField extends Entity {
|
||||||
|
public lights: LightEntity[] = [];
|
||||||
|
|
||||||
|
public constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.transform.position = new Vector3( [ 0.0, 0.0, 0.0 ] );
|
||||||
|
this.transform.scale = new Vector3( [ 1.0, 1.0, 1.0 ] );
|
||||||
|
|
||||||
|
// -- geometry ---------------------------------------------------------------------------------
|
||||||
|
const cube = genCube( { dimension: [ 100.0, 1.0, 100.0 ] } );
|
||||||
|
|
||||||
|
const geometry = new Geometry();
|
||||||
|
|
||||||
|
geometry.vao.bindVertexbuffer( cube.position, 0, 3 );
|
||||||
|
geometry.vao.bindIndexbuffer( cube.index );
|
||||||
|
|
||||||
|
geometry.count = cube.count;
|
||||||
|
geometry.mode = cube.mode;
|
||||||
|
geometry.indexType = cube.indexType;
|
||||||
|
|
||||||
|
// -- materials --------------------------------------------------------------------------------
|
||||||
|
// const forward = new Material(
|
||||||
|
// raymarchObjectVert,
|
||||||
|
// psyFieldFrag,
|
||||||
|
// {
|
||||||
|
// defines: [ 'FORWARD 1' ],
|
||||||
|
// initOptions: { geometry, target: dummyRenderTarget },
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
|
||||||
|
const deferred = new Material(
|
||||||
|
raymarchObjectVert,
|
||||||
|
psyFieldFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'DEFERRED 1' ],
|
||||||
|
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const depth = new Material(
|
||||||
|
raymarchObjectVert,
|
||||||
|
psyFieldFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'DEPTH 1' ],
|
||||||
|
initOptions: { geometry, target: dummyRenderTarget }
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const materials = { deferred, depth };
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/psy-field.frag', () => {
|
||||||
|
// forward.replaceShader( raymarchObjectVert, psyFieldFrag );
|
||||||
|
deferred.replaceShader( raymarchObjectVert, psyFieldFrag );
|
||||||
|
depth.replaceShader( raymarchObjectVert, psyFieldFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- forward lights ---------------------------------------------------------------------------
|
||||||
|
// this.components.push( new Lambda( {
|
||||||
|
// onDraw: ( { frameCount } ) => {
|
||||||
|
// setLightUniforms( forward, this.lights, frameCount );
|
||||||
|
// },
|
||||||
|
// name: process.env.DEV && 'PsyField/setLightUniforms',
|
||||||
|
// } ) );
|
||||||
|
|
||||||
|
// -- updater ----------------------------------------------------------------------------------
|
||||||
|
this.components.push( new Lambda( {
|
||||||
|
onDraw: ( event ) => {
|
||||||
|
objectValuesMap( materials, ( material ) => {
|
||||||
|
material.addUniform(
|
||||||
|
'cameraNearFar',
|
||||||
|
'2f',
|
||||||
|
event.camera.near,
|
||||||
|
event.camera.far
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniformMatrixVector(
|
||||||
|
'inversePVM',
|
||||||
|
'Matrix4fv',
|
||||||
|
event.projectionMatrix
|
||||||
|
.multiply( event.viewMatrix )
|
||||||
|
.multiply( event.globalTransform.matrix )
|
||||||
|
.inverse!
|
||||||
|
.elements
|
||||||
|
);
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
name: process.env.DEV && 'PsyField/updater',
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
// -- mesh -------------------------------------------------------------------------------------
|
||||||
|
const mesh = new Mesh( {
|
||||||
|
geometry,
|
||||||
|
materials,
|
||||||
|
name: process.env.DEV && 'PsyField/mesh',
|
||||||
|
} );
|
||||||
|
mesh.cull = MeshCull.None;
|
||||||
|
this.components.push( mesh );
|
||||||
|
}
|
||||||
|
}
|
146
src/entities/Racer.ts
Normal file
146
src/entities/Racer.ts
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { GPUParticles } from './GPUParticles';
|
||||||
|
import { Geometry } from '../heck/Geometry';
|
||||||
|
import { Lambda } from '../heck/components/Lambda';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
import { dummyRenderTargetFourDrawBuffers, dummyRenderTargetTwoDrawBuffers } from '../globals/dummyRenderTarget';
|
||||||
|
import { gl, glCat } from '../globals/canvas';
|
||||||
|
import { matrix2d } from '@fms-cat/experimental';
|
||||||
|
import { quadGeometry } from '../globals/quadGeometry';
|
||||||
|
import { randomTexture } from '../globals/randomTexture';
|
||||||
|
import quadVert from '../shaders/quad.vert';
|
||||||
|
import racerComputeFrag from '../shaders/racer-compute.frag';
|
||||||
|
import racerRenderFrag from '../shaders/racer-render.frag';
|
||||||
|
import racerRenderVert from '../shaders/racer-render.vert';
|
||||||
|
|
||||||
|
const TRAILS = 4096;
|
||||||
|
const TRAIL_LENGTH = 64;
|
||||||
|
|
||||||
|
export class Racer extends Entity {
|
||||||
|
public constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// -- material compute -------------------------------------------------------------------------
|
||||||
|
const materialCompute = new Material(
|
||||||
|
quadVert,
|
||||||
|
racerComputeFrag,
|
||||||
|
{ initOptions: { geometry: quadGeometry, target: dummyRenderTargetTwoDrawBuffers } },
|
||||||
|
);
|
||||||
|
|
||||||
|
materialCompute.addUniform( 'trails', '1f', TRAILS );
|
||||||
|
materialCompute.addUniform( 'trailLength', '1f', TRAIL_LENGTH );
|
||||||
|
materialCompute.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/racer-compute.frag', () => {
|
||||||
|
materialCompute.replaceShader( quadVert, racerComputeFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- lambda to say update ---------------------------------------------------------------------
|
||||||
|
this.components.push( new Lambda( {
|
||||||
|
onUpdate: ( { time, deltaTime } ) => {
|
||||||
|
const shouldUpdate
|
||||||
|
= Math.floor( 60.0 * time ) !== Math.floor( 60.0 * ( time - deltaTime ) );
|
||||||
|
materialCompute.addUniform( 'shouldUpdate', '1i', shouldUpdate ? 1 : 0 );
|
||||||
|
},
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
// -- geometry render --------------------------------------------------------------------------
|
||||||
|
const geometryRender = new Geometry();
|
||||||
|
|
||||||
|
const bufferComputeUV = glCat.createBuffer();
|
||||||
|
bufferComputeUV.setVertexbuffer(
|
||||||
|
new Float32Array( matrix2d( TRAIL_LENGTH, TRAILS ) ).map( ( v, i ) => {
|
||||||
|
if ( i % 2 === 0 ) { return ( v + 0.5 ) / TRAIL_LENGTH; }
|
||||||
|
else { return ( v + 0.5 ) / TRAILS; }
|
||||||
|
} )
|
||||||
|
);
|
||||||
|
|
||||||
|
geometryRender.vao.bindVertexbuffer( bufferComputeUV, 0, 2 );
|
||||||
|
|
||||||
|
geometryRender.count = TRAILS * TRAIL_LENGTH;
|
||||||
|
geometryRender.mode = gl.POINTS;
|
||||||
|
|
||||||
|
// -- materials render -------------------------------------------------------------------------
|
||||||
|
const forward = new Material(
|
||||||
|
racerRenderVert,
|
||||||
|
racerRenderFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'FORWARD 1' ],
|
||||||
|
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
|
blend: [ gl.ONE, gl.ONE ],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
// const cubemap = new Material(
|
||||||
|
// racerRenderVert,
|
||||||
|
// racerRenderFrag,
|
||||||
|
// {
|
||||||
|
// defines: [ 'FORWARD 1', 'CUBEMAP 1' ],
|
||||||
|
// initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
|
// blend: [ gl.ONE, gl.ONE ],
|
||||||
|
// },
|
||||||
|
// );
|
||||||
|
|
||||||
|
const deferred = new Material(
|
||||||
|
racerRenderVert,
|
||||||
|
racerRenderFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'DEFERRED 1' ],
|
||||||
|
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
forward.addUniform( 'trails', '1f', TRAILS );
|
||||||
|
forward.addUniform( 'trailLength', '1f', TRAIL_LENGTH );
|
||||||
|
|
||||||
|
// cubemap.addUniform( 'trails', '1f', TRAILS );
|
||||||
|
// cubemap.addUniform( 'trailLength', '1f', TRAIL_LENGTH );
|
||||||
|
|
||||||
|
deferred.addUniform( 'trails', '1f', TRAILS );
|
||||||
|
deferred.addUniform( 'trailLength', '1f', TRAIL_LENGTH );
|
||||||
|
|
||||||
|
const materialsRender = { forward, deferred };
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept(
|
||||||
|
[
|
||||||
|
'../shaders/racer-render.vert',
|
||||||
|
'../shaders/racer-render.frag',
|
||||||
|
],
|
||||||
|
() => {
|
||||||
|
forward.replaceShader( racerRenderVert, racerRenderFrag );
|
||||||
|
// cubemap.replaceShader( racerRenderVert, racerRenderFrag );
|
||||||
|
deferred.replaceShader( racerRenderVert, racerRenderFrag );
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- auto -------------------------------------------------------------------------------------
|
||||||
|
auto( 'Racer/active', ( { init, uninit } ) => {
|
||||||
|
this.active = !uninit;
|
||||||
|
this.visible = !uninit;
|
||||||
|
|
||||||
|
materialCompute.addUniform( 'init', '1i', init ? 1 : 0 );
|
||||||
|
} );
|
||||||
|
|
||||||
|
// -- gpu particles ----------------------------------------------------------------------------
|
||||||
|
const gpuParticles = new GPUParticles( {
|
||||||
|
materialCompute,
|
||||||
|
geometryRender,
|
||||||
|
materialsRender,
|
||||||
|
computeWidth: TRAIL_LENGTH,
|
||||||
|
computeHeight: TRAILS,
|
||||||
|
computeNumBuffers: 2,
|
||||||
|
namePrefix: process.env.DEV && 'Racer',
|
||||||
|
} );
|
||||||
|
gpuParticles.meshRender.depthWrite = false;
|
||||||
|
this.children.push( gpuParticles );
|
||||||
|
}
|
||||||
|
}
|
123
src/entities/SSR.ts
Normal file
123
src/entities/SSR.ts
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
import { Blit } from '../heck/components/Blit';
|
||||||
|
import { BufferRenderTarget } from '../heck/BufferRenderTarget';
|
||||||
|
import { DeferredCamera } from './DeferredCamera';
|
||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { Lambda } from '../heck/components/Lambda';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { Quad } from '../heck/components/Quad';
|
||||||
|
import { RenderTarget } from '../heck/RenderTarget';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
import { dummyRenderTarget } from '../globals/dummyRenderTarget';
|
||||||
|
import { gl } from '../globals/canvas';
|
||||||
|
import { quadGeometry } from '../globals/quadGeometry';
|
||||||
|
import { randomTexture } from '../globals/randomTexture';
|
||||||
|
import quadVert from '../shaders/quad.vert';
|
||||||
|
import ssrFrag from '../shaders/ssr.frag';
|
||||||
|
|
||||||
|
export interface SSROptions {
|
||||||
|
camera: DeferredCamera;
|
||||||
|
shaded: BufferRenderTarget;
|
||||||
|
target: RenderTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SSR extends Entity {
|
||||||
|
public constructor( options: SSROptions ) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
const entityBypass = new Entity();
|
||||||
|
entityBypass.visible = false;
|
||||||
|
this.children.push( entityBypass );
|
||||||
|
|
||||||
|
const entityMain = new Entity();
|
||||||
|
entityMain.active = false;
|
||||||
|
entityMain.visible = false;
|
||||||
|
this.children.push( entityMain );
|
||||||
|
|
||||||
|
// -- bypass -----------------------------------------------------------------------------------
|
||||||
|
entityBypass.components.push( new Blit( {
|
||||||
|
src: options.shaded,
|
||||||
|
dst: options.target,
|
||||||
|
name: 'SSR/blitBypass',
|
||||||
|
} ) );
|
||||||
|
|
||||||
|
// -- ha ---------------------------------------------------------------------------------------
|
||||||
|
const { camera } = options;
|
||||||
|
|
||||||
|
const material = new Material(
|
||||||
|
quadVert,
|
||||||
|
ssrFrag,
|
||||||
|
{
|
||||||
|
initOptions: { geometry: quadGeometry, target: dummyRenderTarget },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
||||||
|
|
||||||
|
for ( let i = 0; i < 4; i ++ ) {
|
||||||
|
material.addUniformTexture(
|
||||||
|
'sampler' + i,
|
||||||
|
options.camera.cameraTarget.getTexture( gl.COLOR_ATTACHMENT0 + i )
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
material.addUniformTexture( 'samplerShaded', options.shaded.texture );
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/ssr.frag', () => {
|
||||||
|
material.replaceShader( quadVert, ssrFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- camera uniforms --------------------------------------------------------------------------
|
||||||
|
const lambda = new Lambda( {
|
||||||
|
onUpdate: () => {
|
||||||
|
const cameraView = camera.transform.matrix.inverse!;
|
||||||
|
|
||||||
|
material.addUniformMatrixVector(
|
||||||
|
'cameraView',
|
||||||
|
'Matrix4fv',
|
||||||
|
cameraView.elements
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniformMatrixVector(
|
||||||
|
'cameraPV',
|
||||||
|
'Matrix4fv',
|
||||||
|
camera.camera.projectionMatrix.multiply(
|
||||||
|
cameraView
|
||||||
|
).elements
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniform(
|
||||||
|
'cameraNearFar',
|
||||||
|
'2f',
|
||||||
|
camera.camera.near,
|
||||||
|
camera.camera.far
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniform(
|
||||||
|
'cameraPos',
|
||||||
|
'3f',
|
||||||
|
...camera.transform.position.elements
|
||||||
|
);
|
||||||
|
},
|
||||||
|
name: process.env.DEV && 'SSR/shading/setCameraUniforms',
|
||||||
|
} );
|
||||||
|
entityMain.components.push( lambda );
|
||||||
|
|
||||||
|
// -- quad -------------------------------------------------------------------------------------
|
||||||
|
const quad = new Quad( {
|
||||||
|
target: options.target,
|
||||||
|
material,
|
||||||
|
name: process.env.DEV && 'SSR/quad',
|
||||||
|
} );
|
||||||
|
entityMain.components.push( quad );
|
||||||
|
|
||||||
|
// -- auto -------------------------------------------------------------------------------------
|
||||||
|
auto( 'SSR/active', ( { uninit } ) => {
|
||||||
|
entityMain.active = !uninit;
|
||||||
|
entityBypass.active = !entityMain.active;
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
@@ -89,11 +89,11 @@ export class SceneCrystals extends Entity {
|
|||||||
shadowMapFar: 20.0,
|
shadowMapFar: 20.0,
|
||||||
namePrefix: process.env.DEV && 'lightCrystals1',
|
namePrefix: process.env.DEV && 'lightCrystals1',
|
||||||
} );
|
} );
|
||||||
light1.color = [ 400.0, 400.0, 400.0 ];
|
light1.color = [ 100.0, 100.0, 100.0 ];
|
||||||
light1.transform.lookAt( new Vector3( [ 0.0, 4.0, 1.0 ] ) );
|
light1.transform.lookAt( new Vector3( [ 0.0, 4.0, 1.0 ] ) );
|
||||||
|
|
||||||
auto( 'SceneCrystals/light/amp', ( { value } ) => {
|
auto( 'SceneCrystals/light/amp', ( { value } ) => {
|
||||||
light1.color = [ 400.0 * value, 400.0 * value, 400.0 * value ];
|
light1.color = [ 100.0 * value, 100.0 * value, 100.0 * value ];
|
||||||
} );
|
} );
|
||||||
|
|
||||||
this.lights = [ light1 ];
|
this.lights = [ light1 ];
|
||||||
|
@@ -5,7 +5,6 @@ import { IFSPistons } from './IFSPistons';
|
|||||||
import { LightEntity } from './LightEntity';
|
import { LightEntity } from './LightEntity';
|
||||||
import { LightShaft } from './LightShaft';
|
import { LightShaft } from './LightShaft';
|
||||||
import { Quaternion, Vector3 } from '@fms-cat/experimental';
|
import { Quaternion, Vector3 } from '@fms-cat/experimental';
|
||||||
import { SufferTexts } from './SufferTexts';
|
|
||||||
import { Wobbleball } from './Wobbleball';
|
import { Wobbleball } from './Wobbleball';
|
||||||
|
|
||||||
interface SceneNeuroOptions {
|
interface SceneNeuroOptions {
|
||||||
@@ -69,7 +68,6 @@ export class SceneNeuro extends Entity {
|
|||||||
new Wobbleball(),
|
new Wobbleball(),
|
||||||
new IFSPistons(),
|
new IFSPistons(),
|
||||||
boundingBox,
|
boundingBox,
|
||||||
new SufferTexts(),
|
|
||||||
...this.lights,
|
...this.lights,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
43
src/entities/ScenePsy.ts
Normal file
43
src/entities/ScenePsy.ts
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { Hooperball } from './HooperBall';
|
||||||
|
import { LightEntity } from './LightEntity';
|
||||||
|
import { PsyField } from './PsyField';
|
||||||
|
import { Racer } from './Racer';
|
||||||
|
import { Vector3 } from '@fms-cat/experimental';
|
||||||
|
|
||||||
|
interface ScenePsyOptions {
|
||||||
|
scenes: Entity[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ScenePsy extends Entity {
|
||||||
|
public readonly lights: LightEntity[];
|
||||||
|
|
||||||
|
public constructor( { scenes }: ScenePsyOptions ) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// -- hooperball -------------------------------------------------------------------------------
|
||||||
|
const hooperball = new Hooperball();
|
||||||
|
|
||||||
|
// -- field ------------------------------------------------------------------------------------
|
||||||
|
const psyField = new PsyField();
|
||||||
|
psyField.transform.position = new Vector3( [ 0.0, -2.0, 0.0 ] );
|
||||||
|
|
||||||
|
const psyField2 = new PsyField();
|
||||||
|
psyField2.transform.position = new Vector3( [ 0.0, 2.0, 0.0 ] );
|
||||||
|
|
||||||
|
// -- racer ------------------------------------------------------------------------------------
|
||||||
|
const racer = new Racer();
|
||||||
|
|
||||||
|
// -- no lights --------------------------------------------------------------------------------
|
||||||
|
this.lights = [];
|
||||||
|
|
||||||
|
// -- scene ------------------------------------------------------------------------------------
|
||||||
|
this.children.push(
|
||||||
|
hooperball,
|
||||||
|
psyField,
|
||||||
|
psyField2,
|
||||||
|
racer,
|
||||||
|
...this.lights,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -21,7 +21,7 @@ const PARTICLES = 256;
|
|||||||
const sufferList = [
|
const sufferList = [
|
||||||
'#DEFINE DISGRACE 1',
|
'#DEFINE DISGRACE 1',
|
||||||
'WELCOME TO THE MANGLER HELL',
|
'WELCOME TO THE MANGLER HELL',
|
||||||
'CTRL + ALT + DESPAIR',
|
'DEADLINE HARMS YOUR HEALTH',
|
||||||
'LIBOPUS IS CHEATING',
|
'LIBOPUS IS CHEATING',
|
||||||
'PUBLIC GET FUCKED()',
|
'PUBLIC GET FUCKED()',
|
||||||
'\'RETRUN\': UNDECLARED IDENTIFIER',
|
'\'RETRUN\': UNDECLARED IDENTIFIER',
|
||||||
@@ -33,7 +33,7 @@ const sufferList = [
|
|||||||
'SVG.GETPOINTATLENGTH IS CHEATING',
|
'SVG.GETPOINTATLENGTH IS CHEATING',
|
||||||
'COPY\'N\'PASTE ENGINEER',
|
'COPY\'N\'PASTE ENGINEER',
|
||||||
'60FPS OR DIE',
|
'60FPS OR DIE',
|
||||||
'<PLACEHOLDER>',
|
'EXPECT A TERRIBLE STYLE INCONSISTENCY',
|
||||||
'END MY SUFFER',
|
'END MY SUFFER',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
60
src/entities/TestScreen.ts
Normal file
60
src/entities/TestScreen.ts
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { Quad } from '../heck/components/Quad';
|
||||||
|
import { RenderTarget } from '../heck/RenderTarget';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
import { dummyRenderTarget } from '../globals/dummyRenderTarget';
|
||||||
|
import { quadGeometry } from '../globals/quadGeometry';
|
||||||
|
import { randomTexture } from '../globals/randomTexture';
|
||||||
|
import quadVert from '../shaders/quad.vert';
|
||||||
|
import testScreenFrag from '../shaders/test-screen.frag';
|
||||||
|
|
||||||
|
export interface TestScreenOptions {
|
||||||
|
target: RenderTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TestScreen extends Entity {
|
||||||
|
public constructor( options: TestScreenOptions ) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// -- post -------------------------------------------------------------------------------------
|
||||||
|
const material = new Material(
|
||||||
|
quadVert,
|
||||||
|
testScreenFrag,
|
||||||
|
{
|
||||||
|
initOptions: { geometry: quadGeometry, target: dummyRenderTarget },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/test-screen.frag', () => {
|
||||||
|
material.replaceShader( quadVert, testScreenFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const quad = new Quad( {
|
||||||
|
target: options.target,
|
||||||
|
material,
|
||||||
|
name: process.env.DEV && 'TestScreen/quad',
|
||||||
|
} );
|
||||||
|
this.components.push( quad );
|
||||||
|
|
||||||
|
// -- auto -------------------------------------------------------------------------------------
|
||||||
|
auto( 'TestScreen/circle', ( { value } ) => {
|
||||||
|
material.addUniform( 'circle', '1f', value );
|
||||||
|
} );
|
||||||
|
|
||||||
|
auto( 'TestScreen/fade', ( { value } ) => {
|
||||||
|
material.addUniform( 'fade', '1f', value );
|
||||||
|
} );
|
||||||
|
|
||||||
|
auto( 'TestScreen/mode', ( { value } ) => {
|
||||||
|
this.active = value > 0.0;
|
||||||
|
material.addUniform( 'mode', '1f', value );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
108
src/entities/TextOverlay.ts
Normal file
108
src/entities/TextOverlay.ts
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
import { Entity } from '../heck/Entity';
|
||||||
|
import { GLCatTexture } from '@fms-cat/glcat-ts';
|
||||||
|
import { Material } from '../heck/Material';
|
||||||
|
import { Quad } from '../heck/components/Quad';
|
||||||
|
import { RenderTarget } from '../heck/RenderTarget';
|
||||||
|
import { auto } from '../globals/automaton';
|
||||||
|
import { dummyRenderTarget } from '../globals/dummyRenderTarget';
|
||||||
|
import { gl, glCat } from '../globals/canvas';
|
||||||
|
import { quadGeometry } from '../globals/quadGeometry';
|
||||||
|
import quadVert from '../shaders/quad.vert';
|
||||||
|
import textOverlayFrag from '../shaders/text-overlay.frag';
|
||||||
|
|
||||||
|
export interface TextOverlayOptions {
|
||||||
|
target: RenderTarget;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class TextOverlay extends Entity {
|
||||||
|
public constructor( options: TextOverlayOptions ) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
// -- create cards -----------------------------------------------------------------------------
|
||||||
|
const canvasText = document.createElement( 'canvas' );
|
||||||
|
const width = canvasText.width = options.target.width;
|
||||||
|
const height = canvasText.height = options.target.height;
|
||||||
|
|
||||||
|
const context = canvasText.getContext( '2d' )!;
|
||||||
|
context.fillStyle = '#fff';
|
||||||
|
context.textAlign = 'center';
|
||||||
|
context.textBaseline = 'middle';
|
||||||
|
context.font = `100 ${ 0.02 * width }px Bahnschrift, sans-serif`;
|
||||||
|
|
||||||
|
const heck = ( texture: GLCatTexture, text: string ): GLCatTexture => {
|
||||||
|
context.clearRect( 0, 0, width, height );
|
||||||
|
context.fillText( text, width / 2.0, height / 2.0 );
|
||||||
|
texture.setTexture( canvasText );
|
||||||
|
return texture;
|
||||||
|
};
|
||||||
|
|
||||||
|
const textures = [
|
||||||
|
heck( glCat.createTexture(), 'Revision 2021' ),
|
||||||
|
heck( glCat.createTexture(), 'A 64k WebGL intro' ),
|
||||||
|
glCat.createTexture(),
|
||||||
|
glCat.createTexture(),
|
||||||
|
];
|
||||||
|
|
||||||
|
{
|
||||||
|
context.clearRect( 0, 0, width, height );
|
||||||
|
context.fillText( 'Code, Graphics, Music', 0.5 * width, 0.47 * height );
|
||||||
|
context.font = `100 ${ 0.03 * width }px Bahnschrift, sans-serif`;
|
||||||
|
context.fillText( 'FMS_Cat', 0.5 * width, 0.52 * height );
|
||||||
|
context.font = `100 ${ 0.02 * width }px Bahnschrift, sans-serif`;
|
||||||
|
|
||||||
|
textures[ 2 ].setTexture( canvasText );
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
context.clearRect( 0, 0, width, height );
|
||||||
|
context.fillText( 'I promise I will hire a', 0.5 * width, 0.48 * height );
|
||||||
|
context.fillText( 'graphic direction guy next time', 0.5 * width, 0.52 * height );
|
||||||
|
|
||||||
|
context.textAlign = 'right';
|
||||||
|
context.fillText( 'Press Esc to exit the experience', 0.9 * width, 0.91 * height );
|
||||||
|
|
||||||
|
context.textAlign = 'left';
|
||||||
|
context.fillText( 'by FMS_Cat', 0.28 * width, 0.85 * height );
|
||||||
|
context.fillText( 'A 64K WebGL Intro @ Revision 2021', 0.1 * width, 0.91 * height );
|
||||||
|
context.font = `100 ${ 0.04 * width }px Bahnschrift, sans-serif`;
|
||||||
|
context.fillText( 'Condition', 0.1 * width, 0.84 * height );
|
||||||
|
|
||||||
|
textures[ 3 ].setTexture( canvasText );
|
||||||
|
}
|
||||||
|
|
||||||
|
// -- post -------------------------------------------------------------------------------------
|
||||||
|
const material = new Material(
|
||||||
|
quadVert,
|
||||||
|
textOverlayFrag,
|
||||||
|
{
|
||||||
|
initOptions: { geometry: quadGeometry, target: dummyRenderTarget },
|
||||||
|
blend: [ gl.ONE, gl.ONE ],
|
||||||
|
},
|
||||||
|
);
|
||||||
|
material.addUniformTexture( 'sampler0', textures[ 0 ] );
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
if ( module.hot ) {
|
||||||
|
module.hot.accept( '../shaders/text-overlay.frag', () => {
|
||||||
|
material.replaceShader( quadVert, textOverlayFrag );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const quad = new Quad( {
|
||||||
|
target: options.target,
|
||||||
|
material,
|
||||||
|
name: process.env.DEV && 'TextOverlay/quad',
|
||||||
|
} );
|
||||||
|
this.components.push( quad );
|
||||||
|
|
||||||
|
// -- auto -------------------------------------------------------------------------------------
|
||||||
|
auto( 'TextOverlay/texture', ( { value } ) => {
|
||||||
|
material.addUniformTexture( 'sampler0', textures[ value ] );
|
||||||
|
} );
|
||||||
|
|
||||||
|
auto( 'TextOverlay/amp', ( { value } ) => {
|
||||||
|
material.addUniform( 'amp', '1f', value );
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
@@ -1,163 +0,0 @@
|
|||||||
import { Entity } from '../heck/Entity';
|
|
||||||
import { GPUParticles } from './GPUParticles';
|
|
||||||
import { InstancedGeometry } from '../heck/InstancedGeometry';
|
|
||||||
import { Lambda } from '../heck/components/Lambda';
|
|
||||||
import { Material } from '../heck/Material';
|
|
||||||
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers, dummyRenderTargetTwoDrawBuffers } from '../globals/dummyRenderTarget';
|
|
||||||
import { gl, glCat } from '../globals/canvas';
|
|
||||||
import { quadGeometry } from '../globals/quadGeometry';
|
|
||||||
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
|
||||||
import depthFrag from '../shaders/depth.frag';
|
|
||||||
import quadVert from '../shaders/quad.vert';
|
|
||||||
import trailsComputeFrag from '../shaders/trails-compute.frag';
|
|
||||||
import trailsRenderFrag from '../shaders/trails-render.frag';
|
|
||||||
import trailsRenderVert from '../shaders/trails-render.vert';
|
|
||||||
|
|
||||||
const TRAILS = 4096;
|
|
||||||
const TRAIL_LENGTH = 64;
|
|
||||||
|
|
||||||
export class Trails extends Entity {
|
|
||||||
public constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
// -- material compute -------------------------------------------------------------------------
|
|
||||||
const materialCompute = new Material(
|
|
||||||
quadVert,
|
|
||||||
trailsComputeFrag,
|
|
||||||
{ initOptions: { geometry: quadGeometry, target: dummyRenderTargetTwoDrawBuffers } },
|
|
||||||
);
|
|
||||||
|
|
||||||
materialCompute.addUniform( 'trails', '1f', TRAILS );
|
|
||||||
materialCompute.addUniform( 'trailLength', '1f', TRAIL_LENGTH );
|
|
||||||
materialCompute.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
|
||||||
if ( module.hot ) {
|
|
||||||
module.hot.accept( '../shaders/trails-compute.frag', () => {
|
|
||||||
materialCompute.replaceShader( quadVert, trailsComputeFrag );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- lambda to say update ---------------------------------------------------------------------
|
|
||||||
this.components.push( new Lambda( {
|
|
||||||
onUpdate: ( { time, deltaTime } ) => {
|
|
||||||
const shouldUpdate
|
|
||||||
= Math.floor( 60.0 * time ) !== Math.floor( 60.0 * ( time - deltaTime ) );
|
|
||||||
materialCompute.addUniform( 'shouldUpdate', '1i', shouldUpdate ? 1 : 0 );
|
|
||||||
},
|
|
||||||
} ) );
|
|
||||||
|
|
||||||
// -- geometry render --------------------------------------------------------------------------
|
|
||||||
const geometryRender = new InstancedGeometry();
|
|
||||||
|
|
||||||
const bufferComputeU = glCat.createBuffer();
|
|
||||||
bufferComputeU.setVertexbuffer( ( () => {
|
|
||||||
const ret = new Float32Array( TRAIL_LENGTH * 3 );
|
|
||||||
for ( let i = 0; i < TRAIL_LENGTH; i ++ ) {
|
|
||||||
const u = ( 0.5 + i ) / TRAIL_LENGTH;
|
|
||||||
ret[ i * 3 + 0 ] = u;
|
|
||||||
ret[ i * 3 + 1 ] = u;
|
|
||||||
ret[ i * 3 + 2 ] = u;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
} )() );
|
|
||||||
|
|
||||||
geometryRender.vao.bindVertexbuffer( bufferComputeU, 0, 1 );
|
|
||||||
|
|
||||||
const bufferComputeV = glCat.createBuffer();
|
|
||||||
bufferComputeV.setVertexbuffer( ( () => {
|
|
||||||
const ret = new Float32Array( TRAILS );
|
|
||||||
for ( let i = 0; i < TRAILS; i ++ ) {
|
|
||||||
ret[ i ] = ( i + 0.5 ) / TRAILS;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
} )() );
|
|
||||||
|
|
||||||
geometryRender.vao.bindVertexbuffer( bufferComputeV, 1, 1, 1 );
|
|
||||||
|
|
||||||
const bufferTriIndex = glCat.createBuffer();
|
|
||||||
bufferTriIndex.setVertexbuffer( ( () => {
|
|
||||||
const ret = new Float32Array( 3 * TRAIL_LENGTH );
|
|
||||||
for ( let i = 0; i < TRAIL_LENGTH; i ++ ) {
|
|
||||||
ret[ i * 3 + 0 ] = 0;
|
|
||||||
ret[ i * 3 + 1 ] = 1;
|
|
||||||
ret[ i * 3 + 2 ] = 2;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
} )() );
|
|
||||||
|
|
||||||
geometryRender.vao.bindVertexbuffer( bufferTriIndex, 2, 1 );
|
|
||||||
|
|
||||||
const indexBuffer = glCat.createBuffer();
|
|
||||||
indexBuffer.setIndexbuffer( ( () => {
|
|
||||||
const ret = new Uint16Array( ( TRAIL_LENGTH - 1 ) * 18 );
|
|
||||||
for ( let i = 0; i < TRAIL_LENGTH - 1; i ++ ) {
|
|
||||||
for ( let j = 0; j < 3; j ++ ) {
|
|
||||||
const jn = ( j + 1 ) % 3;
|
|
||||||
ret[ i * 18 + j * 6 + 0 ] = i * 3 + j;
|
|
||||||
ret[ i * 18 + j * 6 + 1 ] = i * 3 + 3 + j;
|
|
||||||
ret[ i * 18 + j * 6 + 2 ] = i * 3 + 3 + jn;
|
|
||||||
ret[ i * 18 + j * 6 + 3 ] = i * 3 + j;
|
|
||||||
ret[ i * 18 + j * 6 + 4 ] = i * 3 + 3 + jn;
|
|
||||||
ret[ i * 18 + j * 6 + 5 ] = i * 3 + jn;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
} )() );
|
|
||||||
|
|
||||||
geometryRender.vao.bindIndexbuffer( indexBuffer );
|
|
||||||
|
|
||||||
geometryRender.count = ( TRAIL_LENGTH - 1 ) * 18;
|
|
||||||
geometryRender.primcount = TRAILS;
|
|
||||||
geometryRender.mode = gl.TRIANGLES;
|
|
||||||
geometryRender.indexType = gl.UNSIGNED_SHORT;
|
|
||||||
|
|
||||||
// -- materials render -------------------------------------------------------------------------
|
|
||||||
const deferred = new Material(
|
|
||||||
trailsRenderVert,
|
|
||||||
trailsRenderFrag,
|
|
||||||
{
|
|
||||||
defines: [ 'DEFERRED 1' ],
|
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
|
||||||
},
|
|
||||||
);
|
|
||||||
const depth = new Material(
|
|
||||||
trailsRenderVert,
|
|
||||||
depthFrag,
|
|
||||||
{ initOptions: { geometry: geometryRender, target: dummyRenderTarget } },
|
|
||||||
);
|
|
||||||
|
|
||||||
const materialsRender = { deferred, depth };
|
|
||||||
|
|
||||||
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
|
||||||
depth.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
|
||||||
if ( module.hot ) {
|
|
||||||
module.hot.accept(
|
|
||||||
[
|
|
||||||
'../shaders/trails-render.vert',
|
|
||||||
'../shaders/trails-render.frag',
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
deferred.replaceShader( trailsRenderVert, trailsRenderFrag );
|
|
||||||
depth.replaceShader( trailsRenderVert, depthFrag );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- gpu particles ----------------------------------------------------------------------------
|
|
||||||
const gpuParticles = new GPUParticles( {
|
|
||||||
materialCompute,
|
|
||||||
geometryRender,
|
|
||||||
materialsRender,
|
|
||||||
computeWidth: TRAIL_LENGTH,
|
|
||||||
computeHeight: TRAILS,
|
|
||||||
computeNumBuffers: 2,
|
|
||||||
namePrefix: process.env.DEV && 'Trails',
|
|
||||||
} );
|
|
||||||
this.children.push( gpuParticles );
|
|
||||||
}
|
|
||||||
}
|
|
25
src/main.ts
25
src/main.ts
@@ -57,15 +57,6 @@ if ( process.env.DEV ) {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !process.env.DEV ) {
|
|
||||||
window.addEventListener( 'keydown', ( event ) => {
|
|
||||||
if ( event.key === 'Escape' ) { // panic button
|
|
||||||
dog.root.active = false;
|
|
||||||
music.isPlaying = false;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- wenis ----------------------------------------------------------------------------------------
|
// -- wenis ----------------------------------------------------------------------------------------
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
console.info( Component.nameMap );
|
console.info( Component.nameMap );
|
||||||
@@ -80,21 +71,31 @@ async function load(): Promise<void> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ( !process.env.DEV ) {
|
if ( !process.env.DEV ) {
|
||||||
document.write( 'Wait a moment... ' );
|
document.body.innerHTML = '';
|
||||||
|
document.write( 'Wait a moment...' );
|
||||||
}
|
}
|
||||||
|
|
||||||
await music.prepare();
|
await music.prepare();
|
||||||
|
|
||||||
if ( !process.env.DEV ) {
|
if ( !process.env.DEV ) {
|
||||||
|
document.body.innerHTML = '';
|
||||||
|
|
||||||
const button = document.createElement( 'a' );
|
const button = document.createElement( 'a' );
|
||||||
document.body.appendChild( button );
|
document.body.prepend( button );
|
||||||
button.innerHTML = 'click me!';
|
button.innerHTML = 'click me!';
|
||||||
|
|
||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
document.body.appendChild( canvas );
|
document.body.prepend( canvas );
|
||||||
music.isPlaying = true;
|
music.isPlaying = true;
|
||||||
document.body.requestFullscreen();
|
document.body.requestFullscreen();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.addEventListener( 'keydown', ( event ) => {
|
||||||
|
if ( event.key === 'Escape' ) { // panic button
|
||||||
|
dog.root.active = false;
|
||||||
|
music.isPlaying = false;
|
||||||
|
}
|
||||||
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
load();
|
load();
|
||||||
|
@@ -21,6 +21,8 @@ const sectionResets = [
|
|||||||
336.0,
|
336.0,
|
||||||
400.0,
|
400.0,
|
||||||
464.0,
|
464.0,
|
||||||
|
528.0,
|
||||||
|
560.0,
|
||||||
1E9,
|
1E9,
|
||||||
].map( ( v ) => v * 60.0 / MUSIC_BPM );
|
].map( ( v ) => v * 60.0 / MUSIC_BPM );
|
||||||
|
|
||||||
|
@@ -14,6 +14,7 @@ const float SECTION_WHOA = 272.0 * BEAT;
|
|||||||
const float SECTION_PORTER_FUCKING_ROBINSON = 336.0 * BEAT;
|
const float SECTION_PORTER_FUCKING_ROBINSON = 336.0 * BEAT;
|
||||||
const float SECTION_AAAA = 400.0 * BEAT;
|
const float SECTION_AAAA = 400.0 * BEAT;
|
||||||
const float SECTION_PSY = 464.0 * BEAT;
|
const float SECTION_PSY = 464.0 * BEAT;
|
||||||
|
const float SECTION_END = 528.0 * BEAT;
|
||||||
|
|
||||||
#define saturate(i) clamp(i, 0.,1.)
|
#define saturate(i) clamp(i, 0.,1.)
|
||||||
#define aSaturate(i) clamp((i),-1.,1.)
|
#define aSaturate(i) clamp((i),-1.,1.)
|
||||||
@@ -42,6 +43,13 @@ in float off;
|
|||||||
out float outL;
|
out float outL;
|
||||||
out float outR;
|
out float outR;
|
||||||
|
|
||||||
|
float seed;
|
||||||
|
|
||||||
|
float random() {
|
||||||
|
seed = fs( seed );
|
||||||
|
return 2.0 * seed - 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
float auto( float y ) {
|
float auto( float y ) {
|
||||||
return texture( samplerAutomaton, vec2( off / bufferLength, y ) ).x;
|
return texture( samplerAutomaton, vec2( off / bufferLength, y ) ).x;
|
||||||
}
|
}
|
||||||
@@ -256,14 +264,23 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
-3, 3, 7, 12, 17, 22
|
-3, 3, 7, 12, 17, 22
|
||||||
);
|
);
|
||||||
|
|
||||||
int progB = ( time.w < SECTION_AAAA - 8.0 * BEAT )
|
int progB = ( time.w < SECTION_PORTER_FUCKING_ROBINSON ) ? 6 * ( int( time.z / ( 8.0 * BEAT ) ) % 8 )
|
||||||
? 6 * ( int( time.z / ( 8.0 * BEAT ) ) % 8 )
|
: ( time.w < SECTION_AAAA - 8.0 * BEAT ) ? 6 * ( 4 + ( int( time.z / ( 8.0 * BEAT ) ) % 4 ) )
|
||||||
: 36;
|
: 36;
|
||||||
|
|
||||||
float bassfreq = n2f( 0.0 );
|
float bassfreq = n2f( 0.0 );
|
||||||
|
|
||||||
float sidechain = 1.0;
|
float sidechain = 1.0;
|
||||||
|
|
||||||
|
float fadeout = smoothstep( SECTION_END + 32.0 * BEAT, SECTION_END, time.w );
|
||||||
|
|
||||||
|
// -- test ---------------------------------------------------------------------------------------
|
||||||
|
if ( inRange( time.w, SECTION_BEGIN - 8.0 * BEAT, SECTION_BEGIN ) ) {
|
||||||
|
float freq = 1000.0 * ( 1.0 + step( time.y, BEAT ) );
|
||||||
|
float amp = inRangeSmooth( time.x, 0.0, 0.04, 1E3 );
|
||||||
|
dest += 0.3 * amp * sin( TAU * freq * time.x );
|
||||||
|
}
|
||||||
|
|
||||||
// -- kick ---------------------------------------------------------------------------------------
|
// -- kick ---------------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_BEGIN + 64.0 * BEAT, SECTION_NEURO - 14.5 * BEAT ) ) {
|
if ( inRange( time.w, SECTION_BEGIN + 64.0 * BEAT, SECTION_NEURO - 14.5 * BEAT ) ) {
|
||||||
float t = mod( mod( time.z - 1.5 * BEAT, 4.0 * BEAT ), 2.5 * BEAT );
|
float t = mod( mod( time.z - 1.5 * BEAT, 4.0 * BEAT ), 2.5 * BEAT );
|
||||||
@@ -329,29 +346,6 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
dest += 0.14 * mix( 0.3, 1.0, sidechain ) * aSaturate( sum );
|
dest += 0.14 * mix( 0.3, 1.0, sidechain ) * aSaturate( sum );
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- choir --------------------------------------------------------------------------------------
|
|
||||||
if ( inRange( time.w, 0.0, SECTION_PORTER_FUCKING_ROBINSON ) ) {
|
|
||||||
const int notes[7] = int[](
|
|
||||||
10, 0, 10, 7, -5, 0, -5
|
|
||||||
);
|
|
||||||
|
|
||||||
vec2 sum = vec2( 0.0 );
|
|
||||||
|
|
||||||
vec2 radius = vec2( 0.00002 );
|
|
||||||
float tb = lofi( time.z, 0.5 * BEAT );
|
|
||||||
float t = time.z - tb;
|
|
||||||
|
|
||||||
for ( int i = 0; i < 21; i ++ ) {
|
|
||||||
int note = notes[ int( time.z / ( 0.5 * BEAT ) ) % 7 ];
|
|
||||||
float freq = n2f( note ) * 0.25;
|
|
||||||
freq *= 1.0 + 0.01 * ( 0.5 - fs( float( i ) ) );
|
|
||||||
float phase = 2.0 * tri( time.w * freq );
|
|
||||||
sum += 0.1 * inRangeSmooth( t, 0.0, 0.5 * BEAT, 1E3 ) * wavetable( phase, radius, vec2( 0.3 * float( i ) ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
//dest += 0.14 * aSaturate( sum );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- kick ---------------------------------------------------------------------------------------
|
// -- kick ---------------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_NEURO, SECTION_WHOA - 2.5 * BEAT ) ) {
|
if ( inRange( time.w, SECTION_NEURO, SECTION_WHOA - 2.5 * BEAT ) ) {
|
||||||
float t = mod( mod( mod( time.y, 4.0 * BEAT ), 3.25 * BEAT ), 1.75 * BEAT );
|
float t = mod( mod( mod( time.y, 4.0 * BEAT ), 3.25 * BEAT ), 1.75 * BEAT );
|
||||||
@@ -500,7 +494,8 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
: time.w < SECTION_AAAA ? 1E9
|
: time.w < SECTION_AAAA ? 1E9
|
||||||
: time.w < SECTION_AAAA + 1.0 * BEAT ? time.x + mod( lofi( time.z, BEAT ), 8.0 * BEAT )
|
: time.w < SECTION_AAAA + 1.0 * BEAT ? time.x + mod( lofi( time.z, BEAT ), 8.0 * BEAT )
|
||||||
: time.w < SECTION_PSY ? 1E9
|
: time.w < SECTION_PSY ? 1E9
|
||||||
: time.x;
|
: time.w < SECTION_END ? time.x
|
||||||
|
: time.z;
|
||||||
{
|
{
|
||||||
sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick );
|
sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick );
|
||||||
dest += 0.25 * kick( tKick, 1.0 );
|
dest += 0.25 * kick( tKick, 1.0 );
|
||||||
@@ -523,7 +518,7 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
|
|
||||||
if (
|
if (
|
||||||
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) ||
|
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) ||
|
||||||
inRange( time.w, SECTION_PSY + 16.0 * BEAT, 1E9 )
|
inRange( time.w, SECTION_PSY + 16.0 * BEAT, SECTION_END )
|
||||||
) {
|
) {
|
||||||
float t = mod( time.x, 0.25 * BEAT );
|
float t = mod( time.x, 0.25 * BEAT );
|
||||||
float decay = mix( 40.0, 100.0, fs( floor( time.z / ( 0.25 * BEAT ) ) ) );
|
float decay = mix( 40.0, 100.0, fs( floor( time.z / ( 0.25 * BEAT ) ) ) );
|
||||||
@@ -531,42 +526,20 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
inRange( time.w, SECTION_PSY + 31.5 * BEAT, 1E9 )
|
inRange( time.w, SECTION_PSY + 31.5 * BEAT, SECTION_END )
|
||||||
) {
|
) {
|
||||||
float t = mod( time.x - 0.5 * BEAT, BEAT );
|
float t = mod( time.x - 0.5 * BEAT, BEAT );
|
||||||
dest += 0.1 * mix( 0.3, 1.0, sidechain ) * hihat( t, 20.0 );
|
dest += 0.1 * mix( 0.3, 1.0, sidechain ) * hihat( t, 20.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- clap ---------------------------------------------------------------------------------------
|
// -- crash --------------------------------------------------------------------------------------
|
||||||
if (
|
if (
|
||||||
inRange( time.w, SECTION_PSY + 64.0 * BEAT, 1E9 )
|
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY )
|
||||||
) {
|
|
||||||
float t = mod( time.y - 1.0 * BEAT, 2.0 * BEAT );
|
|
||||||
dest += 0.1 * clap( t );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- crash ---------------------------------------------------------------------------------------
|
|
||||||
if (
|
|
||||||
!inRange( time.w, 0.0, SECTION_PORTER_FUCKING_ROBINSON ) &&
|
|
||||||
!inRange( time.w, SECTION_PSY, SECTION_PSY + 16.0 * BEAT )
|
|
||||||
) {
|
) {
|
||||||
float t = time.z;
|
float t = time.z;
|
||||||
dest += 0.14 * crash( t );
|
dest += 0.14 * crash( t );
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- psysaw -------------------------------------------------------------------------------------
|
|
||||||
if (
|
|
||||||
inRange( time.w, SECTION_PSY + 64.0 * BEAT, 1E9 )
|
|
||||||
) {
|
|
||||||
float t = mod( time.z, 0.25 * BEAT );
|
|
||||||
float begin = time.z - t;
|
|
||||||
float dice = fs( begin );
|
|
||||||
if ( t < ( 0.25 - dice * 0.2 ) * BEAT ) {
|
|
||||||
float freq = 20.0 * sin( TAU * begin * 1.8 );
|
|
||||||
dest += 0.07 * saw( 20.0 * exp( -2.0 * fract( 10.0 * exp( -freq * t ) ) ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- amen ---------------------------------------------------------------------------------------
|
// -- amen ---------------------------------------------------------------------------------------
|
||||||
if (
|
if (
|
||||||
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) ||
|
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) ||
|
||||||
@@ -574,7 +547,7 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
) {
|
) {
|
||||||
float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) );
|
float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) );
|
||||||
// float chunk = time.y / ( 1.0 * BEAT );
|
// float chunk = time.y / ( 1.0 * BEAT );
|
||||||
vec2 vib = 0.003 * sin( 3.0 * time.z + vec2( 0.0, 0.2 ) );
|
vec2 vib = 0.003 * sin( 3.0 * time.z + vec2( 0.0, 1.4 ) );
|
||||||
vec2 tread = 2.0 * time.x + vib;
|
vec2 tread = 2.0 * time.x + vib;
|
||||||
|
|
||||||
float roll = fs( 2.4 + lofi( time.z, 0.5 * BEAT ) );
|
float roll = fs( 2.4 + lofi( time.z, 0.5 * BEAT ) );
|
||||||
@@ -591,7 +564,7 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// -- psy bass -----------------------------------------------------------------------------------
|
// -- psy bass -----------------------------------------------------------------------------------
|
||||||
if ( SECTION_PSY < time.w ) {
|
if ( inRange( time.w, SECTION_PSY, SECTION_END ) ) {
|
||||||
// float t = mod( aTime - 0.5 beat, 1.0 beat );
|
// float t = mod( aTime - 0.5 beat, 1.0 beat );
|
||||||
float t = mod( time.x, 0.25 * BEAT );
|
float t = mod( time.x, 0.25 * BEAT );
|
||||||
float decay = exp( -50.0 * t );
|
float decay = exp( -50.0 * t );
|
||||||
@@ -603,6 +576,30 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
dest += 0.12 * sidechain * wave * exp( -max( 0.0, t - 0.22 * BEAT ) * 400.0 );
|
dest += 0.12 * sidechain * wave * exp( -max( 0.0, t - 0.22 * BEAT ) * 400.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -- pad ----------------------------------------------------------------------------------------
|
||||||
|
if ( SECTION_PSY < time.w ) {
|
||||||
|
vec2 sum = vec2( 0.0 );
|
||||||
|
|
||||||
|
float tb = lofi( time.z, 0.25 * BEAT );
|
||||||
|
float t = time.z - tb;
|
||||||
|
float rev = exp( 3.0 * fs( tb ) - 3.0 ) * exp( -20.0 * t );
|
||||||
|
vec2 radius = vec2( 0.02 ) * fadeout;
|
||||||
|
|
||||||
|
for ( int i = 0; i < 21; i ++ ) {
|
||||||
|
float freq = n2f( chordsA[ ( i % 8 ) ] ) * 0.25;
|
||||||
|
freq *= 1.0 + 0.001 * ( 0.5 - fs( float( i ) ) );
|
||||||
|
float phase = tri( time.w * freq ) * rev;
|
||||||
|
sum += 0.14 * wavetable( phase, radius, vec2( 0.3 * float( i ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( int i = 0; i < 7; i ++ ) {
|
||||||
|
float rate = n2r( float( chordsA[ i ] ) ) * 0.5;
|
||||||
|
sum += 0.1 * choir( time.z * rate * 0.5 ) * exp( -30.0 * t );
|
||||||
|
}
|
||||||
|
|
||||||
|
dest += 0.14 * mix( 0.3, 1.0, sidechain ) * aSaturate( sum );
|
||||||
|
}
|
||||||
|
|
||||||
// -- superbass ----------------------------------------------------------------------------------
|
// -- superbass ----------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA ) ) {
|
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA ) ) {
|
||||||
float t = mod( time.z, 8.0 * BEAT );
|
float t = mod( time.z, 8.0 * BEAT );
|
||||||
@@ -658,10 +655,10 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
// -- lead ---------------------------------------------------------------------------------------
|
// -- lead ---------------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY ) ) {
|
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY ) ) {
|
||||||
const int notes[16] = int[](
|
const int notes[16] = int[](
|
||||||
0, 10, 12, 19,
|
-4, 10, 12, 19,
|
||||||
0, 14, 15, 22,
|
-5, 14, 15, 22,
|
||||||
0, 17, 19, 26,
|
0, 17, 19, 26,
|
||||||
0, 14, 15, 22
|
-3, 14, 15, 22
|
||||||
);
|
);
|
||||||
|
|
||||||
vec2 sum = vec2( 0.0 );
|
vec2 sum = vec2( 0.0 );
|
||||||
@@ -700,6 +697,10 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
dest += 0.3 * deepkick( mod( time.z, 8.0 * BEAT ) );
|
dest += 0.3 * deepkick( mod( time.z, 8.0 * BEAT ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( inRange( time.w, SECTION_END, SECTION_END + 64.0 * BEAT ) ) {
|
||||||
|
dest += 0.3 * deepkick( time.z );
|
||||||
|
}
|
||||||
|
|
||||||
// -- buildup ------------------------------------------------------------------------------------
|
// -- buildup ------------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_AAAA + 32.0 * BEAT, SECTION_PSY ) ) {
|
if ( inRange( time.w, SECTION_AAAA + 32.0 * BEAT, SECTION_PSY ) ) {
|
||||||
float ph = linearstep( SECTION_AAAA + 32.0 * BEAT, SECTION_PSY, time.w );
|
float ph = linearstep( SECTION_AAAA + 32.0 * BEAT, SECTION_PSY, time.w );
|
||||||
@@ -733,22 +734,41 @@ vec2 mainAudio( vec4 time ) {
|
|||||||
dest += 0.2 * kick( time.y - 3.5 * BEAT, 1.0 ) * inRangeSmooth( time.y, 3.0 * BEAT, 3.75 * BEAT, 100.0 );
|
dest += 0.2 * kick( time.y - 3.5 * BEAT, 1.0 ) * inRangeSmooth( time.y, 3.0 * BEAT, 3.75 * BEAT, 100.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- fill, psy crashes --------------------------------------------------------------------------
|
// -- fadeout ------------------------------------------------------------------------------------
|
||||||
if ( inRange( time.w, SECTION_PSY + 61.0 * BEAT, SECTION_PSY + 64.0 * BEAT ) ) {
|
dest *= fadeout;
|
||||||
dest *= 0.0;
|
|
||||||
|
|
||||||
float stretch = time.x - lofi( time.x, 0.02 ) * 0.9;
|
// -- oidos!! ------------------------------------------------------------------------------------
|
||||||
float range = inRangeFloat( time.y, 0.0 * BEAT, 1.75 * BEAT );
|
// https://www.shadertoy.com/view/NdlGDl
|
||||||
dest += 0.2 * kick( stretch, 1.0 ) * range;
|
if ( inRange( time.w, SECTION_END, 1E9 ) ) {
|
||||||
dest += 0.1 * crash( stretch ) * range;
|
seed = 0.261;
|
||||||
|
|
||||||
dest += 0.2 * kick( mod( time.x - 0.25 * BEAT, 0.5 * BEAT ), 1.0 ) * inRangeFloat( time.y, 1.75 * BEAT, 2.5 * BEAT );
|
for ( int i = 0; i < 50; i ++ ) {
|
||||||
|
float reltone = 4.0 + random() * 45.0;
|
||||||
|
|
||||||
dest += 0.2 * kick( mod( time.x, 0.5 * BEAT ), 1.0 ) * inRangeFloat( time.y, 2.5 * BEAT, 1E9 );
|
float relfreq = pow( 2.0, reltone / 12.0 );
|
||||||
dest += vec2( 0.1, 0.07 ) * crash( time.y - 2.5 * BEAT ) * inRangeSmooth( time.y, 0.0, 2.75 * BEAT, 400.0 );
|
float relfreqOt = floor( relfreq + 0.5 );
|
||||||
dest += vec2( 0.07, 0.1 ) * crash( time.y - 3.0 * BEAT ) * inRangeSmooth( time.y, 0.0, 3.25 * BEAT, 400.0 );
|
float relfreqH = mix( relfreq, relfreqOt, 0.2 );
|
||||||
dest += vec2( 0.1, 0.07 ) * crash( time.y - 3.5 * BEAT ) * inRangeSmooth( time.y, 0.0, 3.75 * BEAT, 400.0 );
|
reltone = log2( relfreqH ) * 12.0;
|
||||||
|
|
||||||
|
float mtone = reltone;
|
||||||
|
float mfreq = 220.0 * pow( 2.0, mtone / 12.0 );
|
||||||
|
|
||||||
|
for ( int j = 0; j < 50; j ++ ) {
|
||||||
|
float ptone = mtone + random() * 0.5;
|
||||||
|
|
||||||
|
float freq = 220.0 * pow( 2.0, ptone / 12.0 );
|
||||||
|
|
||||||
|
float noisePhase = TAU * fract( freq * time.z * 5.0 );
|
||||||
|
vec2 tt = time.z + 0.002 * wavetable( noisePhase, vec2( 0.0001 ), vec2( 0.03 * float( j ) ) );
|
||||||
|
|
||||||
|
vec2 phase = TAU * fract( freq * tt ) + TAU * vec2( random(), random() );
|
||||||
|
dest += ( 1.0 - fadeout ) * 0.0002 * sin( phase );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float realfadeout = smoothstep( SECTION_END + 48.0 * BEAT, SECTION_END + 16.0 * BEAT, time.w );
|
||||||
|
dest *= realfadeout;
|
||||||
|
|
||||||
return aSaturate( dest );
|
return aSaturate( dest );
|
||||||
}
|
}
|
||||||
|
78
src/scene.ts
78
src/scene.ts
@@ -1,4 +1,5 @@
|
|||||||
import { Antialias } from './entities/Antialias';
|
import { Antialias } from './entities/Antialias';
|
||||||
|
import { BigBlur } from './entities/BigBlur';
|
||||||
import { Bloom } from './entities/Bloom';
|
import { Bloom } from './entities/Bloom';
|
||||||
import { BufferRenderTarget } from './heck/BufferRenderTarget';
|
import { BufferRenderTarget } from './heck/BufferRenderTarget';
|
||||||
import { CanvasRenderTarget } from './heck/CanvasRenderTarget';
|
import { CanvasRenderTarget } from './heck/CanvasRenderTarget';
|
||||||
@@ -20,15 +21,19 @@ import { NoiseVoxels } from './entities/NoiseVoxels';
|
|||||||
import { PixelSorter } from './entities/PixelSorter';
|
import { PixelSorter } from './entities/PixelSorter';
|
||||||
import { Post } from './entities/Post';
|
import { Post } from './entities/Post';
|
||||||
import { RTInspector } from './entities/RTInspector';
|
import { RTInspector } from './entities/RTInspector';
|
||||||
|
import { SSR } from './entities/SSR';
|
||||||
import { SceneBegin } from './entities/SceneBegin';
|
import { SceneBegin } from './entities/SceneBegin';
|
||||||
import { SceneCrystals } from './entities/SceneCrystals';
|
import { SceneCrystals } from './entities/SceneCrystals';
|
||||||
import { SceneDynamic } from './entities/SceneDynamic';
|
import { SceneDynamic } from './entities/SceneDynamic';
|
||||||
import { SceneNeuro } from './entities/SceneNeuro';
|
import { SceneNeuro } from './entities/SceneNeuro';
|
||||||
|
import { ScenePsy } from './entities/ScenePsy';
|
||||||
import { Serial } from './entities/Serial';
|
import { Serial } from './entities/Serial';
|
||||||
import { SphereParticles } from './entities/SphereParticles';
|
import { SphereParticles } from './entities/SphereParticles';
|
||||||
|
import { SufferTexts } from './entities/SufferTexts';
|
||||||
import { Swap, Vector3 } from '@fms-cat/experimental';
|
import { Swap, Vector3 } from '@fms-cat/experimental';
|
||||||
|
import { TestScreen } from './entities/TestScreen';
|
||||||
import { Tetrahedron } from './entities/Tetrahedron';
|
import { Tetrahedron } from './entities/Tetrahedron';
|
||||||
import { Trails } from './entities/Trails';
|
import { TextOverlay } from './entities/TextOverlay';
|
||||||
import { arraySetDelete } from './utils/arraySetDelete';
|
import { arraySetDelete } from './utils/arraySetDelete';
|
||||||
import { auto, automaton } from './globals/automaton';
|
import { auto, automaton } from './globals/automaton';
|
||||||
import { music } from './globals/music';
|
import { music } from './globals/music';
|
||||||
@@ -92,9 +97,25 @@ class EntityReplacer<T extends Entity> {
|
|||||||
const ibllut = new IBLLUT();
|
const ibllut = new IBLLUT();
|
||||||
dog.root.children.push( ibllut.entity );
|
dog.root.children.push( ibllut.entity );
|
||||||
|
|
||||||
// -- deferred stuff -------------------------------------------------------------------------------
|
const replacerFlickyParticles = new EntityReplacer(
|
||||||
const deferredRoot = new Entity();
|
() => new FlickyParticles(),
|
||||||
dog.root.children.push( deferredRoot );
|
'FlickyParticles',
|
||||||
|
);
|
||||||
|
if ( process.env.DEV && module.hot ) {
|
||||||
|
module.hot.accept( './entities/FlickyParticles', () => {
|
||||||
|
replacerFlickyParticles.replace();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
|
const replacerSufferTexts = new EntityReplacer(
|
||||||
|
() => new SufferTexts(),
|
||||||
|
'SufferTexts',
|
||||||
|
);
|
||||||
|
if ( process.env.DEV && module.hot ) {
|
||||||
|
module.hot.accept( './entities/SufferTexts', () => {
|
||||||
|
replacerSufferTexts.replace();
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
|
||||||
const replacerSphereParticles = new EntityReplacer(
|
const replacerSphereParticles = new EntityReplacer(
|
||||||
() => new SphereParticles(),
|
() => new SphereParticles(),
|
||||||
@@ -146,13 +167,6 @@ if ( process.env.DEV && module.hot ) {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
const replacerTrails = new EntityReplacer( () => new Trails(), 'Trails' );
|
|
||||||
if ( process.env.DEV && module.hot ) {
|
|
||||||
module.hot.accept( './entities/Trails', () => {
|
|
||||||
replacerTrails.replace();
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
|
|
||||||
const replacerSceneBegin = new EntityReplacer(
|
const replacerSceneBegin = new EntityReplacer(
|
||||||
() => new SceneBegin( { scenes: [ dog.root ] } ),
|
() => new SceneBegin( { scenes: [ dog.root ] } ),
|
||||||
'SceneBegin'
|
'SceneBegin'
|
||||||
@@ -206,17 +220,15 @@ if ( process.env.DEV && module.hot ) {
|
|||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
// -- forward stuff --------------------------------------------------------------------------------
|
const replacerScenePsy = new EntityReplacer(
|
||||||
const forwardRoot = new Entity();
|
() => new ScenePsy( { scenes: [ dog.root ] } ),
|
||||||
dog.root.children.push( forwardRoot );
|
'ScenePsy'
|
||||||
|
|
||||||
const replacerFlickyParticles = new EntityReplacer(
|
|
||||||
() => new FlickyParticles(),
|
|
||||||
'FlickyParticles',
|
|
||||||
);
|
);
|
||||||
if ( process.env.DEV && module.hot ) {
|
if ( process.env.DEV && module.hot ) {
|
||||||
module.hot.accept( './entities/FlickyParticles', () => {
|
module.hot.accept( './entities/ScenePsy', () => {
|
||||||
replacerFlickyParticles.replace();
|
replacerScenePsy.current.lights.map( ( light ) => arraySetDelete( lights, light ) );
|
||||||
|
replacerScenePsy.replace();
|
||||||
|
lights.push( ...replacerScenePsy.current.lights );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -242,6 +254,7 @@ const lights = [
|
|||||||
...replacerSceneNeuro.current.lights,
|
...replacerSceneNeuro.current.lights,
|
||||||
...replacerSceneDynamic.current.lights,
|
...replacerSceneDynamic.current.lights,
|
||||||
...replacerSceneCrystals.current.lights,
|
...replacerSceneCrystals.current.lights,
|
||||||
|
...replacerScenePsy.current.lights,
|
||||||
];
|
];
|
||||||
|
|
||||||
// const light2 = new LightEntity( {
|
// const light2 = new LightEntity( {
|
||||||
@@ -345,6 +358,14 @@ dog.root.components.push( new Lambda( {
|
|||||||
name: process.env.DEV && 'main/updateCamera',
|
name: process.env.DEV && 'main/updateCamera',
|
||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
|
swap.swap();
|
||||||
|
const ssr = new SSR( {
|
||||||
|
camera: deferredCamera,
|
||||||
|
shaded: swap.i,
|
||||||
|
target: swap.o,
|
||||||
|
} );
|
||||||
|
dog.root.children.push( ssr );
|
||||||
|
|
||||||
// -- post -----------------------------------------------------------------------------------------
|
// -- post -----------------------------------------------------------------------------------------
|
||||||
swap.swap();
|
swap.swap();
|
||||||
const antialias = new Antialias( {
|
const antialias = new Antialias( {
|
||||||
@@ -353,6 +374,18 @@ const antialias = new Antialias( {
|
|||||||
} );
|
} );
|
||||||
dog.root.children.push( antialias );
|
dog.root.children.push( antialias );
|
||||||
|
|
||||||
|
swap.swap();
|
||||||
|
const bigBlur = new BigBlur( {
|
||||||
|
input: swap.i,
|
||||||
|
target: swap.o,
|
||||||
|
} );
|
||||||
|
dog.root.children.push( bigBlur );
|
||||||
|
|
||||||
|
const textOverlay = new TextOverlay( {
|
||||||
|
target: swap.o,
|
||||||
|
} );
|
||||||
|
dog.root.children.push( textOverlay );
|
||||||
|
|
||||||
swap.swap();
|
swap.swap();
|
||||||
const bloom = new Bloom( {
|
const bloom = new Bloom( {
|
||||||
input: swap.i,
|
input: swap.i,
|
||||||
@@ -395,6 +428,11 @@ const post = new Post( {
|
|||||||
} );
|
} );
|
||||||
dog.root.children.push( post );
|
dog.root.children.push( post );
|
||||||
|
|
||||||
|
const testScreen = new TestScreen( {
|
||||||
|
target: canvasRenderTarget
|
||||||
|
} );
|
||||||
|
dog.root.children.push( testScreen );
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
const rtInspector = new RTInspector( {
|
const rtInspector = new RTInspector( {
|
||||||
target: canvasRenderTarget
|
target: canvasRenderTarget
|
||||||
|
40
src/shaders/big-blur.frag
Normal file
40
src/shaders/big-blur.frag
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
const float PI = 3.14159265;
|
||||||
|
|
||||||
|
in vec2 vUv;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform float ratio;
|
||||||
|
uniform float sigma;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform sampler2D sampler0;
|
||||||
|
|
||||||
|
float gaussian( float x ) {
|
||||||
|
return 1.0 / sqrt( 2.0 * PI * sigma ) * exp( - x * x / 2.0 / sigma );
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 bv;
|
||||||
|
|
||||||
|
#ifdef IS_VERTICAL
|
||||||
|
bv = vec2( 0.0, 4.0 ) / resolution;
|
||||||
|
#else
|
||||||
|
bv = vec2( 4.0, 0.0 ) / resolution;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
vec4 sum = vec4( 0.0 );
|
||||||
|
|
||||||
|
for ( int i = -100; i < 100; i ++ ) {
|
||||||
|
float fi = float( i );
|
||||||
|
vec2 uvt = vUv + fi * bv;
|
||||||
|
if ( abs( uvt.x - 0.5 ) < 0.5 && abs( uvt.y - 0.5 ) < 0.5 ) {
|
||||||
|
sum += gaussian( fi ) * texture( sampler0, uvt );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = mix( texture( sampler0, vUv ), sum / sum.w, ratio );
|
||||||
|
}
|
@@ -101,7 +101,7 @@ void main() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEPTH
|
#ifdef DEPTH
|
||||||
MARCH_ITER = 10;
|
MARCH_ITER = 30;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||||
@@ -128,7 +128,7 @@ void main() {
|
|||||||
fragPosition = vec4( modelPos.xyz, depth );
|
fragPosition = vec4( modelPos.xyz, depth );
|
||||||
fragNormal = vec4( modelNormal, 1.0 );
|
fragNormal = vec4( modelNormal, 1.0 );
|
||||||
fragColor = vec4( vec3( 0.5 ), 1.0 );
|
fragColor = vec4( vec3( 0.5 ), 1.0 );
|
||||||
fragWTF = vec4( vec3( 0.04, 1.0, 0.0 ), 3 );
|
fragWTF = vec4( vec3( 0.08, 0.9, 0.0 ), 3 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEPTH
|
#ifdef DEPTH
|
||||||
|
@@ -181,7 +181,7 @@ void main() {
|
|||||||
fragPosition = vec4( modelPos.xyz, depth );
|
fragPosition = vec4( modelPos.xyz, depth );
|
||||||
fragNormal = vec4( modelNormal, 1.0 );
|
fragNormal = vec4( modelNormal, 1.0 );
|
||||||
fragColor = vec4( vec3( 0.6, 0.5, 0.4 ), 1.0 );
|
fragColor = vec4( vec3( 0.6, 0.5, 0.4 ), 1.0 );
|
||||||
fragWTF = vec4( vec3( 0.5, 0.2, 0.0 ), 3 );
|
fragWTF = vec4( vec3( 0.5, 0.2, 0.0 ), 2 );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef DEPTH
|
#ifdef DEPTH
|
||||||
|
@@ -42,10 +42,6 @@ void main() {
|
|||||||
vec2 offset = ( 0.6 - 0.2 * exp( -5.0 * vTime ) ) * vec2( vCharParams.y, 0.0 );
|
vec2 offset = ( 0.6 - 0.2 * exp( -5.0 * vTime ) ) * vec2( vCharParams.y, 0.0 );
|
||||||
vPosition.xy += ( offset + shape ) * min( 500.0 / charParams2.x, 1.0 );
|
vPosition.xy += ( offset + shape ) * min( 500.0 / charParams2.x, 1.0 );
|
||||||
|
|
||||||
vPosition.xy += 1.0
|
|
||||||
* ( fs( vCharParams.z + vec2( 2.66, 1.79 ) ) * 2.0 - 1.0 )
|
|
||||||
* pow( fs( vCharParams.z + 7.8 ), 2.0 );
|
|
||||||
|
|
||||||
// == send the vertex position ===================================================================
|
// == send the vertex position ===================================================================
|
||||||
vPosition = vPosition;
|
vPosition = vPosition;
|
||||||
vec4 outPos = vPosition;
|
vec4 outPos = vPosition;
|
||||||
|
214
src/shaders/hooperball.frag
Normal file
214
src/shaders/hooperball.frag
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
// rip of https://www.shadertoy.com/view/tsyBWD
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||||
|
#define lofi(i,j) (floor((i)/(j))*(j))
|
||||||
|
#define saturate(x) clamp(x,0.,1.)
|
||||||
|
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||||
|
|
||||||
|
const int MARCH_ITER = 90;
|
||||||
|
const float PI = 3.14159265;
|
||||||
|
const float TAU = PI * 2.0;
|
||||||
|
const float foldcos = cos( PI / 5.0 );
|
||||||
|
const float foldrem = sqrt( 0.75 - foldcos * foldcos );
|
||||||
|
const vec3 foldvec = vec3( -0.5, -foldcos, foldrem );
|
||||||
|
const vec3 foldface = vec3( 0.0, foldrem, foldcos );
|
||||||
|
const vec3 foldu = vec3( 1.0, 0.0, 0.0 );
|
||||||
|
const vec3 foldv = normalize( cross( foldu, foldface ) );
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
layout (location = 0) out vec4 fragPosition;
|
||||||
|
layout (location = 1) out vec4 fragNormal;
|
||||||
|
layout (location = 2) out vec4 fragColor;
|
||||||
|
layout (location = 3) out vec4 fragWTF;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in vec4 vPositionWithoutModel;
|
||||||
|
|
||||||
|
#ifdef DEPTH
|
||||||
|
out vec4 fragColor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform float deformSeed;
|
||||||
|
uniform float time;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform vec2 cameraNearFar;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform mat4 normalMatrix;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
uniform mat4 viewMatrix;
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
uniform mat4 inversePVM;
|
||||||
|
|
||||||
|
vec3 divideByW( vec4 v ) {
|
||||||
|
return v.xyz / v.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Heck{
|
||||||
|
vec2 coord;
|
||||||
|
vec2 cell;
|
||||||
|
float len;
|
||||||
|
};
|
||||||
|
|
||||||
|
vec2 uv2heck( vec2 v ) {
|
||||||
|
v.y *= 2.0 / sqrt( 3.0 );
|
||||||
|
v.x += v.y * 0.5;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 heck2uv( vec2 v ) {
|
||||||
|
v.y /= 2.0 / sqrt( 3.0 );
|
||||||
|
v.x -= v.y * 0.5;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
Heck doHeck( vec2 v, float scale ) {
|
||||||
|
Heck heck;
|
||||||
|
|
||||||
|
v = uv2heck( v ) * scale;
|
||||||
|
|
||||||
|
heck.cell.x = floor( v.x );
|
||||||
|
heck.cell.y = lofi( v.y + heck.cell.x + 2.0, 3.0 ) - heck.cell.x - 2.0;
|
||||||
|
heck.coord = v - heck.cell - vec2( 0.0, 1.0 );
|
||||||
|
|
||||||
|
bool a = heck.coord.x < heck.coord.y;
|
||||||
|
heck.cell += a ? vec2( 0.0, 2.0 ) : vec2( 1.0, 1.0 );
|
||||||
|
heck.coord += a ? vec2( 0.0, -1.0 ) : vec2( -1.0, 0.0 );
|
||||||
|
|
||||||
|
heck.cell = heck2uv( heck.cell / scale );
|
||||||
|
|
||||||
|
heck.len = max( abs( heck.coord.x ), abs( heck.coord.y ) );
|
||||||
|
heck.len = max( heck.len, abs( heck.coord.y - heck.coord.x ) );
|
||||||
|
|
||||||
|
return heck;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// https://www.iquilezles.org/www/articles/smin/smin.htm
|
||||||
|
float smin( float a, float b, float k ) {
|
||||||
|
float h = max( k - abs( a - b ), 0.0 ) / k;
|
||||||
|
return min( a, b ) - h * h * h * k * ( 1.0 / 6.0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
mat2 rot2d( float t ) {
|
||||||
|
float c = cos( t );
|
||||||
|
float s = sin( t );
|
||||||
|
return mat2( c, -s, s, c );
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma glslify: noise = require( ./-simplex4d );
|
||||||
|
|
||||||
|
vec3 fold( vec3 p ) {
|
||||||
|
for ( int i = 0; i < 5; i ++ ) {
|
||||||
|
p.xy = abs( p.xy );
|
||||||
|
p -= 2.0 * min( dot( foldvec, p ), 0.0 ) * foldvec;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 mapIcosa(vec3 p){
|
||||||
|
p.zx = rot2d( 0.8 * time ) * p.zx;
|
||||||
|
p.xy = rot2d( 1.8 * time ) * p.xy;
|
||||||
|
p = fold( p );
|
||||||
|
|
||||||
|
vec3 isect = p / dot( foldface, p );
|
||||||
|
vec2 uv = vec2( dot( isect, foldu ), dot( isect, foldv ) );
|
||||||
|
|
||||||
|
float phase = deformSeed;
|
||||||
|
float scale = 5.0 + 4.0 * sin( 1.8 * phase );
|
||||||
|
Heck heck = doHeck( uv, scale );
|
||||||
|
vec3 point = normalize( foldface + heck.cell.x * foldu + heck.cell.y * foldv );
|
||||||
|
|
||||||
|
phase += 4.7 * length( heck.cell );
|
||||||
|
float height = 1.0 + 0.1 * sin( 4.9 * phase );
|
||||||
|
|
||||||
|
float dotPointP = dot( point, p );
|
||||||
|
float d = max( dotPointP - height, ( heck.len - 0.4 / dotPointP ) / scale * dotPointP * dotPointP );
|
||||||
|
vec4 ia = vec4( d, 1, 0, 0 );
|
||||||
|
|
||||||
|
float width = 0.8 + 0.2 * sin( 7.6 * phase );
|
||||||
|
float haha = abs( dotPointP - height ) - 0.02;
|
||||||
|
float haha2 = ( heck.len - width ) / scale * dotPointP;
|
||||||
|
d = max( haha, haha2 );
|
||||||
|
vec4 ib = vec4( d, 2, step( -0.03, heck.len - width ) * step( -haha, 0.03 ), 0 );
|
||||||
|
|
||||||
|
ia = ib.x < ia.x ? ib : ia;
|
||||||
|
|
||||||
|
return ia;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec4 map( vec3 p ) {
|
||||||
|
vec3 pt = p;
|
||||||
|
return mapIcosa( pt );
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normalFunc( vec3 p, float dd ) {
|
||||||
|
vec2 d = vec2( 0.0, dd );
|
||||||
|
return normalize( vec3(
|
||||||
|
map( p + d.yxx ).x - map( p - d.yxx ).x,
|
||||||
|
map( p + d.xyx ).x - map( p - d.xyx ).x,
|
||||||
|
map( p + d.xxy ).x - map( p - d.xxy ).x
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 p = ( gl_FragCoord.xy * 2.0 - resolution ) / resolution.y;
|
||||||
|
|
||||||
|
vec3 rayOri = divideByW( inversePVM * vec4( p, 0.0, 1.0 ) );
|
||||||
|
vec3 farPos = divideByW( inversePVM * vec4( p, 1.0, 1.0 ) );
|
||||||
|
vec3 rayDir = normalize( farPos - rayOri );
|
||||||
|
float rayLen = length( vPositionWithoutModel.xyz - rayOri );
|
||||||
|
vec3 rayPos = rayOri + rayDir * rayLen;
|
||||||
|
vec4 isect;
|
||||||
|
|
||||||
|
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||||
|
isect = map( rayPos );
|
||||||
|
rayLen += 0.5 * isect.x;
|
||||||
|
rayPos = rayOri + rayDir * rayLen;
|
||||||
|
|
||||||
|
if ( abs( isect.x ) < 1E-3 ) { break; }
|
||||||
|
if ( rayLen > cameraNearFar.y ) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0.01 < isect.x ) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 modelNormal = normalize( normalMatrix * vec4( normalFunc( rayPos, 1E-3 ), 1.0 ) ).xyz;
|
||||||
|
|
||||||
|
vec4 modelPos = modelMatrix * vec4( rayPos, 1.0 );
|
||||||
|
vec4 projPos = projectionMatrix * viewMatrix * modelPos; // terrible
|
||||||
|
float depth = projPos.z / projPos.w;
|
||||||
|
gl_FragDepth = 0.5 + 0.5 * depth;
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
fragPosition = vec4( modelPos.xyz, depth );
|
||||||
|
fragNormal = vec4( modelNormal, 1.0 );
|
||||||
|
|
||||||
|
if ( isect.y == 1.0 ) {
|
||||||
|
fragColor = vec4( vec3( 0.1 ), 1.0 );
|
||||||
|
fragWTF = vec4( vec3( 0.8, 0.7, 0.0 ), 2 );
|
||||||
|
} else if ( isect.y == 2.0 ) {
|
||||||
|
if ( isect.z > 0.99 ) {
|
||||||
|
fragColor = vec4( 0.1, 0.5, 0.4, 1.0 );
|
||||||
|
fragWTF = vec4( vec3( 0.8, 0.1, 1.0 ), 2 );
|
||||||
|
} else {
|
||||||
|
fragColor = vec4( vec3( 0.1 ), 1.0 );
|
||||||
|
fragWTF = vec4( vec3( 0.7, 0.8, 0.0 ), 2 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEPTH
|
||||||
|
float shadowDepth = linearstep(
|
||||||
|
cameraNearFar.x,
|
||||||
|
cameraNearFar.y,
|
||||||
|
length( cameraPos - modelPos.xyz )
|
||||||
|
);
|
||||||
|
fragColor = vec4( shadowDepth, shadowDepth * shadowDepth, shadowDepth, 1.0 );
|
||||||
|
#endif
|
||||||
|
}
|
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
precision highp float;
|
precision highp float;
|
||||||
|
|
||||||
|
#define lofi(i,j) (floor((i)/(j))*(j))
|
||||||
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||||
#define saturate(x) clamp(x,0.,1.)
|
#define saturate(x) clamp(x,0.,1.)
|
||||||
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||||
@@ -23,7 +24,6 @@ in vec4 vPositionWithoutModel;
|
|||||||
out vec4 fragColor;
|
out vec4 fragColor;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uniform float time;
|
|
||||||
uniform float ifsSeed;
|
uniform float ifsSeed;
|
||||||
uniform vec2 resolution;
|
uniform vec2 resolution;
|
||||||
uniform vec2 cameraNearFar;
|
uniform vec2 cameraNearFar;
|
||||||
@@ -33,9 +33,6 @@ uniform mat4 modelMatrix;
|
|||||||
uniform mat4 viewMatrix;
|
uniform mat4 viewMatrix;
|
||||||
uniform mat4 projectionMatrix;
|
uniform mat4 projectionMatrix;
|
||||||
uniform mat4 inversePVM;
|
uniform mat4 inversePVM;
|
||||||
uniform sampler2D samplerRandom;
|
|
||||||
uniform sampler2D samplerRandomStatic;
|
|
||||||
uniform sampler2D samplerCapture;
|
|
||||||
|
|
||||||
vec3 divideByW( vec4 v ) {
|
vec3 divideByW( vec4 v ) {
|
||||||
return v.xyz / v.w;
|
return v.xyz / v.w;
|
||||||
@@ -82,7 +79,7 @@ float map( vec3 p ) {
|
|||||||
|
|
||||||
vec3 pt = p;
|
vec3 pt = p;
|
||||||
|
|
||||||
float clampbox = box( pt, vec3( 1.0, 1.0, 1.0 ) );
|
float clampbox = box( pt, vec3( 1.0 ) );
|
||||||
|
|
||||||
vec3 r = mix(
|
vec3 r = mix(
|
||||||
fs( vec3( 4.7, 3.2, 4.3 ) + floor( ifsSeed ) ),
|
fs( vec3( 4.7, 3.2, 4.3 ) + floor( ifsSeed ) ),
|
||||||
@@ -93,7 +90,7 @@ float map( vec3 p ) {
|
|||||||
pt = ifs( pt, r, 0.2 * t );
|
pt = ifs( pt, r, 0.2 * t );
|
||||||
pt = ifs( pt, r.yzx, 0.1 * t.yzx );
|
pt = ifs( pt, r.yzx, 0.1 * t.yzx );
|
||||||
|
|
||||||
float d = max( box( pt, vec3( 0.08 ) ), clampbox );
|
float d = max( box( pt, vec3( 0.09 ) ), clampbox );
|
||||||
|
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
@@ -119,7 +116,7 @@ void main() {
|
|||||||
|
|
||||||
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||||
isect = map( rayPos );
|
isect = map( rayPos );
|
||||||
rayLen += 0.5 * isect;
|
rayLen += 0.8 * isect;
|
||||||
rayPos = rayOri + rayDir * rayLen;
|
rayPos = rayOri + rayDir * rayLen;
|
||||||
|
|
||||||
if ( abs( isect ) < 1E-3 ) { break; }
|
if ( abs( isect ) < 1E-3 ) { break; }
|
||||||
|
237
src/shaders/psy-field.frag
Normal file
237
src/shaders/psy-field.frag
Normal file
@@ -0,0 +1,237 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||||
|
#define saturate(x) clamp(x,0.,1.)
|
||||||
|
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||||
|
|
||||||
|
const float PI = 3.14159265;
|
||||||
|
const float TAU = PI * 2.0;
|
||||||
|
|
||||||
|
#ifdef FORWARD
|
||||||
|
out vec4 fragColor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
layout (location = 0) out vec4 fragPosition;
|
||||||
|
layout (location = 1) out vec4 fragNormal;
|
||||||
|
layout (location = 2) out vec4 fragColor;
|
||||||
|
layout (location = 3) out vec4 fragWTF;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
in vec4 vPositionWithoutModel;
|
||||||
|
|
||||||
|
#ifdef DEPTH
|
||||||
|
out vec4 fragColor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform int lightCount;
|
||||||
|
uniform float deformAmp;
|
||||||
|
uniform float deformFreq;
|
||||||
|
uniform float deformTime;
|
||||||
|
uniform float time;
|
||||||
|
uniform float noiseOffset;
|
||||||
|
uniform vec2 lightNearFar[ 8 ];
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform vec2 size;
|
||||||
|
uniform vec2 cameraNearFar;
|
||||||
|
uniform vec3 lightPos[ 8 ];
|
||||||
|
uniform vec3 lightColor[ 8 ];
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform vec4 lightParams[ 8 ];
|
||||||
|
uniform mat4 lightPV[ 8 ];
|
||||||
|
uniform mat4 normalMatrix;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
uniform mat4 viewMatrix;
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
uniform mat4 inversePVM;
|
||||||
|
uniform sampler2D samplerRandom;
|
||||||
|
uniform sampler2D samplerRandomStatic;
|
||||||
|
uniform sampler2D samplerCapture;
|
||||||
|
uniform sampler2D samplerShadow[ 8 ];
|
||||||
|
|
||||||
|
vec3 divideByW( vec4 v ) {
|
||||||
|
return v.xyz / v.w;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma glslify: doAnalyticLighting = require( ./modules/doAnalyticLighting.glsl );
|
||||||
|
#pragma glslify: doShadowMapping = require( ./modules/doShadowMapping.glsl );
|
||||||
|
|
||||||
|
vec4 fetchShadowMap( int iLight, vec2 uv ) {
|
||||||
|
if ( iLight == 0 ) {
|
||||||
|
return texture( samplerShadow[ 0 ], uv );
|
||||||
|
} else if ( iLight == 1 ) {
|
||||||
|
return texture( samplerShadow[ 1 ], uv );
|
||||||
|
} else if ( iLight == 2 ) {
|
||||||
|
return texture( samplerShadow[ 2 ], uv );
|
||||||
|
} else if ( iLight == 3 ) {
|
||||||
|
return texture( samplerShadow[ 3 ], uv );
|
||||||
|
} else if ( iLight == 4 ) {
|
||||||
|
return texture( samplerShadow[ 4 ], uv );
|
||||||
|
} else if ( iLight == 5 ) {
|
||||||
|
return texture( samplerShadow[ 5 ], uv );
|
||||||
|
} else if ( iLight == 6 ) {
|
||||||
|
return texture( samplerShadow[ 6 ], uv );
|
||||||
|
} else if ( iLight == 7 ) {
|
||||||
|
return texture( samplerShadow[ 7 ], uv );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma glslify: orthBasis = require( ./modules/orthBasis );
|
||||||
|
|
||||||
|
vec3 ifs( vec3 p, vec3 r, vec3 t ) {
|
||||||
|
vec3 s = t;
|
||||||
|
mat3 bas = orthBasis( r );
|
||||||
|
|
||||||
|
for ( int i = 0; i < 5; i ++ ) {
|
||||||
|
p = abs( p ) - abs( s ) * pow( 1.8, -float( i ) );
|
||||||
|
|
||||||
|
s = bas * s;
|
||||||
|
|
||||||
|
p.xy = p.x < p.y ? p.yx : p.xy;
|
||||||
|
p.yz = p.y < p.z ? p.zy : p.yz;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
float box( vec3 p, vec3 s ) {
|
||||||
|
vec3 d = abs( p ) - s;
|
||||||
|
return min( 0.0, max( d.x, max( d.y, d.z ) ) ) + length( max( vec3( 0.0 ), d ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
float map( vec3 p ) {
|
||||||
|
vec4 isect;
|
||||||
|
|
||||||
|
vec3 pt = p;
|
||||||
|
pt.z -= 4.0 * time;
|
||||||
|
pt.zx = mod( pt.zx - 5.0, 10.0 ) - 5.0;
|
||||||
|
|
||||||
|
vec3 r = vec3( 1.6, 0.5, -0.8 );
|
||||||
|
vec3 t = vec3( 4.8, 3.7, 2.1 );
|
||||||
|
pt = ifs( pt, r, t );
|
||||||
|
pt = ifs( pt, r.yzx, 0.4 * t.yzx );
|
||||||
|
|
||||||
|
float d = box( pt, vec3( 0.14 ) );
|
||||||
|
d = max( d, abs( p.y ) - 1.0 );
|
||||||
|
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 nMap( vec3 p, float dd ) {
|
||||||
|
vec2 d = vec2( 0.0, dd );
|
||||||
|
return normalize( vec3(
|
||||||
|
map( p + d.yxx ) - map( p - d.yxx ),
|
||||||
|
map( p + d.xyx ) - map( p - d.xyx ),
|
||||||
|
map( p + d.xxy ) - map( p - d.xxy )
|
||||||
|
) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 p = ( gl_FragCoord.xy * 2.0 - resolution ) / resolution.y;
|
||||||
|
|
||||||
|
vec3 rayOri = divideByW( inversePVM * vec4( p, 0.0, 1.0 ) );
|
||||||
|
vec3 farPos = divideByW( inversePVM * vec4( p, 1.0, 1.0 ) );
|
||||||
|
vec3 rayDir = normalize( farPos - rayOri );
|
||||||
|
float rayLen = length( vPositionWithoutModel.xyz - rayOri );
|
||||||
|
vec3 rayPos = rayOri + rayDir * rayLen;
|
||||||
|
float dist;
|
||||||
|
|
||||||
|
int MARCH_ITER;
|
||||||
|
|
||||||
|
#ifdef FORWARD
|
||||||
|
MARCH_ITER = 10;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
MARCH_ITER = 40;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEPTH
|
||||||
|
MARCH_ITER = 10;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||||
|
dist = map( rayPos );
|
||||||
|
rayLen += 0.5 * dist;
|
||||||
|
rayPos = rayOri + rayDir * rayLen;
|
||||||
|
|
||||||
|
if ( abs( dist ) < 1E-3 ) { break; }
|
||||||
|
if ( rayLen > cameraNearFar.y ) { break; }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( 0.01 < dist ) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 normal = nMap( rayPos, 1E-3 );
|
||||||
|
vec3 modelNormal = normalize( normalMatrix * vec4( normal, 1.0 ) ).xyz;
|
||||||
|
|
||||||
|
vec4 modelPos = modelMatrix * vec4( rayPos, 1.0 );
|
||||||
|
vec4 projPos = projectionMatrix * viewMatrix * modelPos; // terrible
|
||||||
|
float depth = projPos.z / projPos.w;
|
||||||
|
gl_FragDepth = 0.5 + 0.5 * depth;
|
||||||
|
|
||||||
|
#ifdef FORWARD
|
||||||
|
vec3 color = vec3( 0.0 );
|
||||||
|
|
||||||
|
// for each lights
|
||||||
|
for ( int iLight = 0; iLight < 8; iLight ++ ) {
|
||||||
|
if ( iLight >= lightCount ) { break; }
|
||||||
|
|
||||||
|
vec3 V = cameraPos - modelPos.xyz;
|
||||||
|
vec3 L = lightPos[ iLight ] - modelPos.xyz;
|
||||||
|
|
||||||
|
// shading
|
||||||
|
vec3 shade = doAnalyticLighting(
|
||||||
|
V,
|
||||||
|
L,
|
||||||
|
modelNormal,
|
||||||
|
vec3( 0.6, 0.5, 0.4 ),
|
||||||
|
0.5,
|
||||||
|
0.2
|
||||||
|
) * lightColor[ iLight ];
|
||||||
|
|
||||||
|
// fetch shadowmap + spot lighting
|
||||||
|
vec4 lightProj = lightPV[ iLight ] * modelPos;
|
||||||
|
vec2 lightP = lightProj.xy / lightProj.w;
|
||||||
|
|
||||||
|
shade *= doShadowMapping(
|
||||||
|
L,
|
||||||
|
modelNormal,
|
||||||
|
fetchShadowMap( iLight, 0.5 + 0.5 * lightP ),
|
||||||
|
lightP,
|
||||||
|
lightNearFar[ iLight ],
|
||||||
|
lightParams[ iLight ].x
|
||||||
|
);
|
||||||
|
|
||||||
|
color += shade;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 gradient = 0.5 + 0.5 * cos(
|
||||||
|
3.0 + 1.5 * exp( -0.4 * max( rayLen - 3.0, 0.0 ) ) + vec3( 0.0, 2.0, 4.0 )
|
||||||
|
);
|
||||||
|
float edge = step( 0.1, length( normal - nMap( rayPos, 1E-2 ) ) );
|
||||||
|
|
||||||
|
color += gradient * edge;
|
||||||
|
|
||||||
|
fragColor = vec4( color, 1.0 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
fragPosition = vec4( modelPos.xyz, depth );
|
||||||
|
fragNormal = vec4( modelNormal, 1.0 );
|
||||||
|
fragColor = vec4( vec3( 0.0 ), 1.0 );
|
||||||
|
fragWTF = vec4( vec3( 1.0, 0.0, 0.0 ), 4 );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEPTH
|
||||||
|
float shadowDepth = linearstep(
|
||||||
|
cameraNearFar.x,
|
||||||
|
cameraNearFar.y,
|
||||||
|
length( cameraPos - modelPos.xyz )
|
||||||
|
);
|
||||||
|
fragColor = vec4( shadowDepth, shadowDepth * shadowDepth, shadowDepth, 1.0 );
|
||||||
|
#endif
|
||||||
|
}
|
@@ -4,12 +4,13 @@ precision highp float;
|
|||||||
|
|
||||||
const float PARTICLE_LIFE_LENGTH = 5.0;
|
const float PARTICLE_LIFE_LENGTH = 5.0;
|
||||||
const float HUGE = 9E16;
|
const float HUGE = 9E16;
|
||||||
|
const float INTERVAL = 0.03125;
|
||||||
const float PI = 3.14159265;
|
const float PI = 3.14159265;
|
||||||
const float TAU = 6.283185307;
|
const float TAU = 6.283185307;
|
||||||
|
|
||||||
|
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||||
#define saturate(i) clamp(i,0.,1.)
|
#define saturate(i) clamp(i,0.,1.)
|
||||||
#define lofi(i,m) (floor((i)/(m))*(m))
|
#define lofi(i,m) (floor((i)/(m))*(m))
|
||||||
#define lofir(i,m) (floor((i)/(m)+.5)*(m))
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 fragCompute0;
|
layout (location = 0) out vec4 fragCompute0;
|
||||||
layout (location = 1) out vec4 fragCompute1;
|
layout (location = 1) out vec4 fragCompute1;
|
||||||
@@ -17,40 +18,18 @@ layout (location = 1) out vec4 fragCompute1;
|
|||||||
uniform bool init;
|
uniform bool init;
|
||||||
uniform bool shouldUpdate;
|
uniform bool shouldUpdate;
|
||||||
uniform float time;
|
uniform float time;
|
||||||
uniform float beat;
|
|
||||||
uniform float trails;
|
uniform float trails;
|
||||||
uniform float trailLength;
|
uniform float trailLength;
|
||||||
uniform float totalFrame;
|
|
||||||
uniform float deltaTime;
|
uniform float deltaTime;
|
||||||
uniform vec2 resolution;
|
uniform vec2 resolution;
|
||||||
uniform sampler2D samplerCompute0;
|
uniform sampler2D samplerCompute0;
|
||||||
uniform sampler2D samplerCompute1;
|
uniform sampler2D samplerCompute1;
|
||||||
uniform sampler2D samplerRandom;
|
uniform sampler2D samplerRandom;
|
||||||
uniform float noiseScale;
|
|
||||||
uniform float noisePhase;
|
|
||||||
// uniform float velScale;
|
|
||||||
// uniform float genRate;
|
|
||||||
|
|
||||||
// ------
|
|
||||||
|
|
||||||
vec2 uvInvT( vec2 _uv ) {
|
|
||||||
return vec2( 0.0, 1.0 ) + vec2( 1.0, -1.0 ) * _uv;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------
|
|
||||||
|
|
||||||
mat2 rotate2D( float _t ) {
|
|
||||||
return mat2( cos( _t ), sin( _t ), -sin( _t ), cos( _t ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
float fractSin( float i ) {
|
float fractSin( float i ) {
|
||||||
return fract( sin( i ) * 1846.42 );
|
return fract( sin( i ) * 1846.42 );
|
||||||
}
|
}
|
||||||
|
|
||||||
vec4 sampleRandom( vec2 _uv ) {
|
|
||||||
return texture( samplerRandom, _uv );
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma glslify: prng = require( ./-prng );
|
#pragma glslify: prng = require( ./-prng );
|
||||||
#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise );
|
#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise );
|
||||||
|
|
||||||
@@ -67,40 +46,6 @@ vec3 randomSphere( inout vec4 seed ) {
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 randomCircle( inout vec4 seed ) {
|
|
||||||
vec2 v;
|
|
||||||
for ( int i = 0; i < 10; i ++ ) {
|
|
||||||
v = vec2(
|
|
||||||
prng( seed ),
|
|
||||||
prng( seed )
|
|
||||||
) * 2.0 - 1.0;
|
|
||||||
if ( length( v ) < 1.0 ) { break; }
|
|
||||||
}
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 randomBox( inout vec4 seed ) {
|
|
||||||
vec3 v;
|
|
||||||
v = vec3(
|
|
||||||
prng( seed ),
|
|
||||||
prng( seed ),
|
|
||||||
prng( seed )
|
|
||||||
) * 2.0 - 1.0;
|
|
||||||
return v;
|
|
||||||
}
|
|
||||||
|
|
||||||
float uneune( float i, float p ) {
|
|
||||||
return sin( TAU * (
|
|
||||||
fractSin( i ) + floor( 1.0 + 4.0 * fractSin( i + 54.12 ) ) * p
|
|
||||||
) );
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 uneune3( float i, float p ) {
|
|
||||||
return vec3( uneune( i, p ), uneune( i + 11.87, p ), uneune( i + 21.92, p ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ------
|
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec2 uv = gl_FragCoord.xy / resolution;
|
vec2 uv = gl_FragCoord.xy / resolution;
|
||||||
|
|
||||||
@@ -115,8 +60,14 @@ void main() {
|
|||||||
vec4 tex0 = texture( samplerCompute0, uv );
|
vec4 tex0 = texture( samplerCompute0, uv );
|
||||||
vec4 tex1 = texture( samplerCompute1, uv );
|
vec4 tex1 = texture( samplerCompute1, uv );
|
||||||
|
|
||||||
|
tex0.z += 4.0 * deltaTime; // camera
|
||||||
if ( shouldUpdate ) {
|
if ( shouldUpdate ) {
|
||||||
tex0.w = saturate( tex0.w - 1.0 / trailLength ); // decrease the life
|
tex0.w = tex0.w + 1.0 / trailLength; // update the life
|
||||||
|
}
|
||||||
|
|
||||||
|
// quick patch!
|
||||||
|
if ( init ) {
|
||||||
|
tex0.w = 1E9;
|
||||||
}
|
}
|
||||||
|
|
||||||
fragCompute0 = tex0;
|
fragCompute0 = tex0;
|
||||||
@@ -140,46 +91,55 @@ void main() {
|
|||||||
float timing = mix( 0.0, PARTICLE_LIFE_LENGTH, floor( uv.y * trails ) / trails );
|
float timing = mix( 0.0, PARTICLE_LIFE_LENGTH, floor( uv.y * trails ) / trails );
|
||||||
timing += lofi( time, PARTICLE_LIFE_LENGTH );
|
timing += lofi( time, PARTICLE_LIFE_LENGTH );
|
||||||
|
|
||||||
if ( time - deltaTime + PARTICLE_LIFE_LENGTH < timing ) {
|
if ( time - dt + PARTICLE_LIFE_LENGTH < timing ) {
|
||||||
timing -= PARTICLE_LIFE_LENGTH;
|
timing -= PARTICLE_LIFE_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
// == initialize particles =======================================================================
|
if ( shouldUpdate ) {
|
||||||
|
// == initialize particles =====================================================================
|
||||||
if (
|
if (
|
||||||
time - deltaTime < timing && timing <= time
|
time - dt < timing && timing <= time
|
||||||
) {
|
) {
|
||||||
dt = time - timing;
|
dt = time - timing;
|
||||||
|
|
||||||
pos = 1.0 * randomSphere( seed );
|
pos = lofi( 5.0 * randomSphere( seed ), INTERVAL );
|
||||||
|
pos.z -= 4.0;
|
||||||
|
|
||||||
vel = 1.0 * randomSphere( seed );
|
vel = 1.0 * randomSphere( seed );
|
||||||
|
|
||||||
life = 1.0;
|
life = 0.0;
|
||||||
|
|
||||||
jumpFlag = 1.0;
|
jumpFlag = 1.0;
|
||||||
} else {
|
} else {
|
||||||
jumpFlag = 0.0; // remove jumping flag
|
jumpFlag = 0.0; // remove jumping flag
|
||||||
}
|
}
|
||||||
|
|
||||||
// == update particles ===========================================================================
|
// == update particles =========================================================================
|
||||||
// noise field
|
// noise field
|
||||||
vel += 40.0 * cyclicNoise( pos ) * dt;
|
vel += 4.0 * cyclicNoise( pos ) * dt;
|
||||||
|
|
||||||
// resistance
|
// resistance
|
||||||
vel *= exp( -10.0 * dt );
|
// vel *= exp( -10.0 * dt );
|
||||||
// vel.z += 10.0 * dt;
|
// vel.z += 10.0 * dt;
|
||||||
|
|
||||||
vec3 v = vel;
|
vec3 v = vel;
|
||||||
// float vmax = max( abs( v.x ), max( abs( v.y ), abs( v.z ) ) );
|
float vmax = max( abs( v.x ), max( abs( v.y ), abs( v.z ) ) );
|
||||||
// v *= (
|
v = INTERVAL * sign( v ) * (
|
||||||
// abs( v.x ) == vmax ? vec3( 1.0, 0.0, 0.0 ) :
|
abs( v.x ) == vmax ? vec3( 1.0, 0.0, 0.0 ) :
|
||||||
// abs( v.y ) == vmax ? vec3( 0.0, 1.0, 0.0 ) :
|
abs( v.y ) == vmax ? vec3( 0.0, 1.0, 0.0 ) :
|
||||||
// vec3( 0.0, 0.0, 1.0 )
|
vec3( 0.0, 0.0, 1.0 )
|
||||||
// );
|
) / dt;
|
||||||
|
|
||||||
// pos.xyz += velScale * v * dt;
|
|
||||||
pos += v * dt;
|
pos += v * dt;
|
||||||
life -= dt / PARTICLE_LIFE_LENGTH;
|
life += dt / PARTICLE_LIFE_LENGTH;
|
||||||
|
}
|
||||||
|
|
||||||
|
pos.z += 4.0 * deltaTime; // camera
|
||||||
|
|
||||||
|
// quick patch!
|
||||||
|
if ( init ) {
|
||||||
|
life = 1E9;
|
||||||
|
}
|
||||||
|
|
||||||
fragCompute0 = vec4( pos, life );
|
fragCompute0 = vec4( pos, life );
|
||||||
fragCompute1 = vec4( vel, jumpFlag );
|
fragCompute1 = vec4( vel, jumpFlag );
|
55
src/shaders/racer-render.frag
Normal file
55
src/shaders/racer-render.frag
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
in float vLife;
|
||||||
|
in vec4 vPosition;
|
||||||
|
|
||||||
|
#ifdef FORWARD
|
||||||
|
out vec4 fragColor;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
layout (location = 0) out vec4 fragPosition;
|
||||||
|
layout (location = 1) out vec4 fragNormal;
|
||||||
|
layout (location = 2) out vec4 fragColor;
|
||||||
|
layout (location = 3) out vec4 fragWTF;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform vec4 color;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if ( length( gl_PointCoord - 0.5 ) > 0.5 ) { discard; }
|
||||||
|
|
||||||
|
float lenV = length( vPosition.xyz - cameraPos );
|
||||||
|
|
||||||
|
vec3 gradient = 0.5 + 0.5 * cos(
|
||||||
|
3.0 + 1.5 * exp( -0.4 * max( lenV - 3.0, 0.0 ) ) + vec3( 0.0, 2.0, 4.0 )
|
||||||
|
);
|
||||||
|
|
||||||
|
vec3 color = 10.0 * gradient * exp( -5.0 * vLife );
|
||||||
|
|
||||||
|
// too near!
|
||||||
|
color *= smoothstep( 0.5, 1.0, lenV );
|
||||||
|
|
||||||
|
#ifdef FORWARD
|
||||||
|
#ifndef CUBEMAP
|
||||||
|
if ( length( color.xyz ) >= 1.0 ) { discard; }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// decay
|
||||||
|
color *= exp( -0.4 * max( lenV - 3.0, 0.0 ) );
|
||||||
|
|
||||||
|
fragColor.xyz = vec3( color );
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DEFERRED
|
||||||
|
if ( length( color.xyz ) < 1.0 ) { discard; }
|
||||||
|
|
||||||
|
fragPosition = vPosition;
|
||||||
|
fragNormal = vec4( 0.0, 0.0, 1.0, 1.0 );
|
||||||
|
fragColor = vec4( color.xyz, 1.0 );
|
||||||
|
fragWTF = vec4( vec3( 0.0 ), 1 );
|
||||||
|
#endif
|
||||||
|
}
|
46
src/shaders/racer-render.vert
Normal file
46
src/shaders/racer-render.vert
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
const float PI = 3.14159265;
|
||||||
|
const float TAU = 6.283185307;
|
||||||
|
const float COLOR_VAR = 0.1;
|
||||||
|
|
||||||
|
#define saturate(x) clamp(x,0.,1.)
|
||||||
|
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||||
|
|
||||||
|
layout (location = 0) in vec2 computeUV;
|
||||||
|
|
||||||
|
out float vLife;
|
||||||
|
out vec4 vPosition;
|
||||||
|
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform mat4 projectionMatrix;
|
||||||
|
uniform mat4 viewMatrix;
|
||||||
|
uniform mat4 modelMatrix;
|
||||||
|
uniform sampler2D samplerCompute0;
|
||||||
|
uniform sampler2D samplerCompute1;
|
||||||
|
|
||||||
|
mat2 rotate2D( float _t ) {
|
||||||
|
return mat2( cos( _t ), sin( _t ), -sin( _t ), cos( _t ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = computeUV;
|
||||||
|
|
||||||
|
vec4 pos = texture( samplerCompute0, uv );
|
||||||
|
|
||||||
|
vLife = pos.w;
|
||||||
|
|
||||||
|
vPosition = modelMatrix * vec4( pos.xyz, 1.0 );
|
||||||
|
vec4 outPos = projectionMatrix * viewMatrix * vPosition;
|
||||||
|
outPos.x *= resolution.y / resolution.x;
|
||||||
|
gl_Position = outPos;
|
||||||
|
|
||||||
|
vPosition.w = outPos.z / outPos.w;
|
||||||
|
|
||||||
|
#ifdef CUBEMAP
|
||||||
|
// ????
|
||||||
|
gl_PointSize = 2.0;
|
||||||
|
#else
|
||||||
|
gl_PointSize = resolution.y * 0.01 / outPos.z;
|
||||||
|
#endif
|
||||||
|
}
|
@@ -6,6 +6,7 @@ const int MTL_NONE = 0;
|
|||||||
const int MTL_UNLIT = 1;
|
const int MTL_UNLIT = 1;
|
||||||
const int MTL_PBR = 2;
|
const int MTL_PBR = 2;
|
||||||
const int MTL_REFRACT = 3;
|
const int MTL_REFRACT = 3;
|
||||||
|
const int MTL_PSY = 4;
|
||||||
const float ENV_UV_MARGIN = 0.9375;
|
const float ENV_UV_MARGIN = 0.9375;
|
||||||
const float AO_BIAS = 0.0;
|
const float AO_BIAS = 0.0;
|
||||||
const float AO_RADIUS = 0.5;
|
const float AO_RADIUS = 0.5;
|
||||||
@@ -276,6 +277,27 @@ void main() {
|
|||||||
|
|
||||||
color += isect.color * texEnvRefractive;
|
color += isect.color * texEnvRefractive;
|
||||||
|
|
||||||
|
} else if ( isect.materialId == MTL_PSY ) {
|
||||||
|
color = 0.02 * smoothstep( 0.9, 1.0, texture( samplerAo, isect.screenUv ).xyz );
|
||||||
|
|
||||||
|
// vec2 f = ( 1.0 - 2.0 * prng( seed ) ) / resolution;
|
||||||
|
vec2 f = 1.0 / resolution;
|
||||||
|
vec4 tex0x = texture( sampler0, vUv + f );
|
||||||
|
vec4 tex1x = texture( sampler1, vUv + f );
|
||||||
|
vec4 tex3x = texture( sampler3, vUv + f );
|
||||||
|
|
||||||
|
float valid = MTL_PSY == int( tex3x.w ) ? 1.0 : 0.0;
|
||||||
|
|
||||||
|
float edge = saturate(
|
||||||
|
step( 0.1, abs( length( cameraPos - tex0x.xyz ) - lenV ) ) +
|
||||||
|
step( 0.1, length( tex1x.xyz - tex1.xyz ) )
|
||||||
|
) * valid;
|
||||||
|
|
||||||
|
vec3 gradient = 0.5 + 0.5 * cos(
|
||||||
|
3.0 + 1.5 * exp( -0.4 * max( lenV - 3.0, 0.0 ) ) + vec3( 0.0, 2.0, 4.0 )
|
||||||
|
);
|
||||||
|
color += 0.4 * gradient * edge;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
color *= exp( -0.4 * max( lenV - 3.0, 0.0 ) );
|
color *= exp( -0.4 * max( lenV - 3.0, 0.0 ) );
|
||||||
|
96
src/shaders/ssr.frag
Normal file
96
src/shaders/ssr.frag
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
const float PI = 3.14159265359;
|
||||||
|
const float TAU = 6.28318530718;
|
||||||
|
|
||||||
|
#define saturate(x) clamp(x,0.,1.)
|
||||||
|
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||||
|
|
||||||
|
vec4 seed;
|
||||||
|
|
||||||
|
in vec2 vUv;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform vec2 cameraNearFar;
|
||||||
|
uniform vec3 cameraPos;
|
||||||
|
uniform mat4 cameraView;
|
||||||
|
uniform mat4 cameraPV;
|
||||||
|
uniform sampler2D sampler0; // position.xyz, depth
|
||||||
|
uniform sampler2D sampler1; // normal.xyz
|
||||||
|
uniform sampler2D sampler2; // color.rgba
|
||||||
|
uniform sampler2D sampler3; // materialParams.xyz, materialId
|
||||||
|
uniform sampler2D samplerShaded;
|
||||||
|
uniform sampler2D samplerRandom;
|
||||||
|
|
||||||
|
#pragma glslify: prng = require( ./-prng );
|
||||||
|
|
||||||
|
// == structs ======================================================================================
|
||||||
|
struct Isect {
|
||||||
|
vec2 screenUv;
|
||||||
|
vec3 color;
|
||||||
|
vec3 position;
|
||||||
|
float depth;
|
||||||
|
vec3 normal;
|
||||||
|
int materialId;
|
||||||
|
vec3 materialParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
// == main procedure ===============================================================================
|
||||||
|
void main() {
|
||||||
|
vec4 tex0 = texture( sampler0, vUv );
|
||||||
|
vec4 tex1 = texture( sampler1, vUv );
|
||||||
|
vec4 tex2 = texture( sampler2, vUv );
|
||||||
|
vec4 tex3 = texture( sampler3, vUv );
|
||||||
|
vec4 shaded = texture( samplerShaded, vUv );
|
||||||
|
|
||||||
|
Isect isect;
|
||||||
|
isect.screenUv = vUv;
|
||||||
|
isect.position = tex0.xyz;
|
||||||
|
isect.depth = tex0.w;
|
||||||
|
isect.normal = normalize( tex1.xyz );
|
||||||
|
isect.color = tex2.rgb;
|
||||||
|
isect.materialId = int( tex3.w + 0.5 );
|
||||||
|
isect.materialParams = tex3.xyz;
|
||||||
|
|
||||||
|
vec3 ssr = vec3( 0.0 );
|
||||||
|
|
||||||
|
if ( isect.materialId != 1 ) {
|
||||||
|
seed = texture( samplerRandom, vUv ) * 1919.810;
|
||||||
|
prng( seed );
|
||||||
|
|
||||||
|
// from isect
|
||||||
|
vec3 V = cameraPos - isect.position;
|
||||||
|
float lenV = length( V );
|
||||||
|
V = normalize( V );
|
||||||
|
|
||||||
|
// ssr
|
||||||
|
vec3 refl = reflect( -V, clamp( isect.normal, -1.0, 1.0 ) );
|
||||||
|
float reflLen = 0.0;
|
||||||
|
|
||||||
|
for ( int i = 0; i < 9; i ++ ) {
|
||||||
|
reflLen += 0.1 + 0.01 * prng( seed );
|
||||||
|
|
||||||
|
vec3 reflP = isect.position + reflLen * refl;
|
||||||
|
vec4 reflSP = cameraPV * vec4( reflP, 1.0 );
|
||||||
|
reflSP.x *= resolution.y / resolution.x;
|
||||||
|
reflSP /= reflSP.w;
|
||||||
|
|
||||||
|
vec2 reflUv = 0.5 + 0.5 * reflSP.xy;
|
||||||
|
float outOfScreenMul = smoothstep( 0.5, 0.4, abs( reflUv.x - 0.5 ) );
|
||||||
|
outOfScreenMul *= smoothstep( 0.5, 0.4, abs( reflUv.y - 0.5 ) );
|
||||||
|
|
||||||
|
vec4 reflTexPos = texture( sampler0, reflUv );
|
||||||
|
if ( reflSP.z > reflTexPos.w ) {
|
||||||
|
float diff = length( reflP.xyz - reflTexPos.xyz );
|
||||||
|
ssr += texture( samplerShaded, reflUv ).xyz * outOfScreenMul * exp( -3.0 * reflLen ) * exp( -10.0 * diff );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = vec4( shaded.xyz + ssr, 1.0 );
|
||||||
|
}
|
30
src/shaders/test-screen.frag
Normal file
30
src/shaders/test-screen.frag
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
#define saturate(i) clamp(i, 0.,1.)
|
||||||
|
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
||||||
|
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
in vec2 vUv;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform float time;
|
||||||
|
uniform float fade;
|
||||||
|
uniform float circle;
|
||||||
|
uniform float mode;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform sampler2D samplerRandom;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
if ( mode == 1.0 ) {
|
||||||
|
fragColor = vec4( vUv, fade, 1.0 );
|
||||||
|
} else if ( mode == 2.0 ) {
|
||||||
|
vec2 p = vUv * 2.0 - 1.0;
|
||||||
|
p.x *= resolution.x / resolution.y;
|
||||||
|
|
||||||
|
float shape = linearstep( 2.0 / resolution.y, 0.0, length( p ) - 0.3 * circle );
|
||||||
|
fragColor = vec4( vec3( shape ), 1.0 );
|
||||||
|
}
|
||||||
|
}
|
28
src/shaders/text-overlay.frag
Normal file
28
src/shaders/text-overlay.frag
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#version 300 es
|
||||||
|
|
||||||
|
precision highp float;
|
||||||
|
|
||||||
|
in vec2 vUv;
|
||||||
|
|
||||||
|
out vec4 fragColor;
|
||||||
|
|
||||||
|
uniform float amp;
|
||||||
|
uniform vec2 resolution;
|
||||||
|
uniform sampler2D sampler0;
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
vec2 uv = vUv;
|
||||||
|
uv.y = 1.0 - uv.y;
|
||||||
|
|
||||||
|
float shape = texture( sampler0, uv ).w;
|
||||||
|
shape = pow( shape, 2.2 );
|
||||||
|
|
||||||
|
float blur = 0.0;
|
||||||
|
|
||||||
|
for ( int i = -10; i < 10; i ++ ) {
|
||||||
|
float t = texture( sampler0, uv + vec2( 4 * i, 0.0 ) / resolution ).w;
|
||||||
|
blur += exp( -0.2 * abs( float( i ) ) ) * pow( t, 2.2 );
|
||||||
|
}
|
||||||
|
|
||||||
|
fragColor = amp * vec4( shape + 0.03 * blur );
|
||||||
|
}
|
@@ -1,44 +0,0 @@
|
|||||||
#version 300 es
|
|
||||||
|
|
||||||
precision highp float;
|
|
||||||
|
|
||||||
const int MTL_UNLIT = 1;
|
|
||||||
const int MTL_PBR = 2;
|
|
||||||
|
|
||||||
const float PI = 3.14159265;
|
|
||||||
const float TAU = 6.28318531;
|
|
||||||
|
|
||||||
#define saturate(i) clamp(i,0.,1.)
|
|
||||||
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
|
||||||
|
|
||||||
// == varings / uniforms ===========================================================================
|
|
||||||
in vec4 vPosition;
|
|
||||||
in vec3 vNormal;
|
|
||||||
in vec4 vColor;
|
|
||||||
in float vLife;
|
|
||||||
in vec4 vRandom;
|
|
||||||
|
|
||||||
layout (location = 0) out vec4 fragPosition;
|
|
||||||
layout (location = 1) out vec4 fragNormal;
|
|
||||||
layout (location = 2) out vec4 fragColor;
|
|
||||||
layout (location = 3) out vec4 fragWTF;
|
|
||||||
|
|
||||||
uniform float time;
|
|
||||||
|
|
||||||
// == common =======================================================================================
|
|
||||||
mat2 rotate2D( float _t ) {
|
|
||||||
return mat2( cos( _t ), sin( _t ), -sin( _t ), cos( _t ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// == main procedure ===============================================================================
|
|
||||||
void main() {
|
|
||||||
if ( vColor.a < 0.0 ) { discard; }
|
|
||||||
|
|
||||||
float emissive = 0.0;
|
|
||||||
// emissive *= 0.5 + 0.5 * sin( TAU * vRandom.z + 20.0 * time );
|
|
||||||
|
|
||||||
fragPosition = vPosition;
|
|
||||||
fragNormal = vec4( vNormal, 1.0 );
|
|
||||||
fragColor = vColor;
|
|
||||||
fragWTF = vec4( vec3( 0.4, 0.1, emissive ), MTL_PBR );
|
|
||||||
}
|
|
@@ -1,122 +0,0 @@
|
|||||||
#version 300 es
|
|
||||||
|
|
||||||
const float HUGE = 9E16;
|
|
||||||
const float PI = 3.14159265;
|
|
||||||
const float TAU = 6.283185307;
|
|
||||||
const float COLOR_VAR = 0.1;
|
|
||||||
|
|
||||||
#define saturate(x) clamp(x,0.,1.)
|
|
||||||
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
|
|
||||||
#define lofi(i,m) (floor((i)/(m))*(m))
|
|
||||||
#define lofir(i,m) (floor((i+0.5)/(m))*(m))
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
|
||||||
layout (location = 0) in float computeU;
|
|
||||||
layout (location = 1) in float computeV;
|
|
||||||
layout (location = 2) in float triIndex;
|
|
||||||
|
|
||||||
out float vLife;
|
|
||||||
out vec3 vNormal;
|
|
||||||
out vec4 vPosition;
|
|
||||||
out vec4 vColor;
|
|
||||||
out vec4 vRandom;
|
|
||||||
|
|
||||||
uniform bool isShadow;
|
|
||||||
uniform float ppp;
|
|
||||||
uniform float trailShaker;
|
|
||||||
uniform float colorVar;
|
|
||||||
uniform float colorOffset;
|
|
||||||
uniform vec2 resolution;
|
|
||||||
uniform vec2 resolutionCompute;
|
|
||||||
uniform mat4 projectionMatrix;
|
|
||||||
uniform mat4 viewMatrix;
|
|
||||||
uniform mat4 modelMatrix;
|
|
||||||
uniform mat4 normalMatrix;
|
|
||||||
uniform sampler2D samplerCompute0;
|
|
||||||
uniform sampler2D samplerCompute1;
|
|
||||||
uniform sampler2D samplerRandomStatic;
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
|
||||||
vec3 blurpleGradient( float t ) {
|
|
||||||
vec3 colorA = vec3( 0.01, 0.04, 0.2 );
|
|
||||||
vec3 colorB = vec3( 0.02, 0.3, 0.9 );
|
|
||||||
vec3 colorC = vec3( 0.9, 0.01, 0.6 );
|
|
||||||
vec3 colorD = vec3( 0.5, 0.02, 0.02 );
|
|
||||||
|
|
||||||
return mix(
|
|
||||||
colorA,
|
|
||||||
mix(
|
|
||||||
colorB,
|
|
||||||
mix(
|
|
||||||
colorC,
|
|
||||||
colorD,
|
|
||||||
linearstep( 0.67, 1.0, t )
|
|
||||||
),
|
|
||||||
linearstep( 0.33, 0.67, t )
|
|
||||||
),
|
|
||||||
linearstep( 0.0, 0.33, t )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec3 catColor( float _p ) {
|
|
||||||
return 0.5 + 0.5 * vec3(
|
|
||||||
cos( _p ),
|
|
||||||
cos( _p + PI / 3.0 * 4.0 ),
|
|
||||||
cos( _p + PI / 3.0 * 2.0 )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
vec4 random( vec2 _uv ) {
|
|
||||||
return texture( samplerRandomStatic, _uv );
|
|
||||||
}
|
|
||||||
|
|
||||||
mat2 rotate2D( float _t ) {
|
|
||||||
return mat2( cos( _t ), sin( _t ), -sin( _t ), cos( _t ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
vec2 uv = vec2( computeU, computeV );
|
|
||||||
|
|
||||||
// == fetch texture ==============================================================================
|
|
||||||
vec4 pos = texture( samplerCompute0, uv );
|
|
||||||
vec4 vel = texture( samplerCompute1, uv );
|
|
||||||
vec4 velp = texture( samplerCompute1, uv - vec2( 1.0, 0.0 ) / resolutionCompute );
|
|
||||||
|
|
||||||
// == assign varying variables ===================================================================
|
|
||||||
vLife = pos.w;
|
|
||||||
|
|
||||||
vRandom = random( uv.yy * 182.92 );
|
|
||||||
|
|
||||||
vColor.xyz = (
|
|
||||||
vRandom.y < 0.8
|
|
||||||
? pow( catColor( TAU * ( ( vRandom.x * 2.0 - 1.0 ) * COLOR_VAR + 0.0 ) ), vec3( 2.0 ) )
|
|
||||||
: vec3( 0.4 )
|
|
||||||
);
|
|
||||||
// vColor.xyz = blurpleGradient( vLife );
|
|
||||||
// vColor.xyz = catColor( 3.0 + 4.0 * vLife );
|
|
||||||
|
|
||||||
vColor.w = ( velp.w < 0.5 && vel.w < 0.5 && 0.0 < vLife ) ? 1.0 : -1.0;
|
|
||||||
|
|
||||||
// == compute size and direction =================================================================
|
|
||||||
float size = 0.005;
|
|
||||||
size *= 1.0 + pow( vRandom.w, 2.0 );
|
|
||||||
// size *= max( 0.0, sin( PI * vLife ) );
|
|
||||||
|
|
||||||
vec3 dir = normalize( vel.xyz );
|
|
||||||
vec3 sid = normalize( cross( dir, vec3( 0.0, 1.0, 0.0 ) ) );
|
|
||||||
vec3 top = normalize( cross( sid, dir ) );
|
|
||||||
|
|
||||||
float theta = triIndex / 3.0 * TAU + vLife * 1.0;
|
|
||||||
vec2 tri = vec2( sin( theta ), cos( theta ) );
|
|
||||||
vNormal = ( normalMatrix * vec4( tri.x * sid + tri.y * top, 1.0 ) ).xyz;
|
|
||||||
pos.xyz += size * vNormal;
|
|
||||||
|
|
||||||
vPosition = modelMatrix * vec4( pos.xyz, 1.0 );
|
|
||||||
vec4 outPos = projectionMatrix * viewMatrix * vPosition;
|
|
||||||
outPos.x *= resolution.y / resolution.x;
|
|
||||||
gl_Position = outPos;
|
|
||||||
|
|
||||||
vPosition.w = outPos.z / outPos.w;
|
|
||||||
}
|
|
@@ -16,7 +16,7 @@ const terserOptions = {
|
|||||||
booleans_as_integers: true,
|
booleans_as_integers: true,
|
||||||
drop_console: true,
|
drop_console: true,
|
||||||
keep_fargs: false,
|
keep_fargs: false,
|
||||||
passes: 1,
|
passes: 2,
|
||||||
unsafe_arrows: true,
|
unsafe_arrows: true,
|
||||||
unsafe_math: true,
|
unsafe_math: true,
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user