mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-08-08 23:16:35 +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 = true,
|
||||
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 = 'main/postSwap0',
|
||||
// RTINSPECTOR_CAPTURE_NAME: string | null = 'EnvironmentMap/swap0',
|
||||
// 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 = 'ForwardCamera/camera',
|
||||
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic2/shadowMapCamera',
|
||||
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic1/shadowMapCamera',
|
||||
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 { Geometry } from '../heck/Geometry';
|
||||
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 { Vector3 } from '@fms-cat/experimental';
|
||||
import { auto } from '../globals/automaton';
|
||||
import { dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
|
||||
import { genCube } from '../geometries/genCube';
|
||||
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||
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(
|
||||
// raymarchObjectVert,
|
||||
// crystalFrag,
|
||||
// {
|
||||
// defines: [ 'DEPTH 1' ],
|
||||
// initOptions: { geometry, target: dummyRenderTarget }
|
||||
// },
|
||||
// );
|
||||
const depth = new Material(
|
||||
raymarchObjectVert,
|
||||
crystalFrag,
|
||||
{
|
||||
defines: [ 'DEPTH 1' ],
|
||||
initOptions: { geometry, target: dummyRenderTarget }
|
||||
},
|
||||
);
|
||||
|
||||
const materials = { deferred };
|
||||
const materials: MaterialMap = { deferred };
|
||||
|
||||
if ( process.env.DEV ) {
|
||||
if ( module.hot ) {
|
||||
module.hot.accept( '../shaders/crystal.frag', () => {
|
||||
deferred.replaceShader( raymarchObjectVert, crystalFrag );
|
||||
// depth.replaceShader( raymarchObjectVert, crystalFrag );
|
||||
depth.replaceShader( raymarchObjectVert, crystalFrag );
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
objectValuesMap( materials, ( material ) => {
|
||||
material.addUniform( 'size', '2f', width, height );
|
||||
material.addUniform( 'noiseOffset', '1f', noiseOffset );
|
||||
material?.addUniform( 'size', '2f', width, height );
|
||||
material?.addUniform( 'noiseOffset', '1f', noiseOffset );
|
||||
} );
|
||||
|
||||
// haha
|
||||
auto( 'Crystal/enableDepth', ( { uninit } ) => {
|
||||
if ( uninit ) {
|
||||
delete materials.depth;
|
||||
} else {
|
||||
materials.depth = depth;
|
||||
}
|
||||
} );
|
||||
|
||||
// -- updater ----------------------------------------------------------------------------------
|
||||
this.components.push( new Lambda( {
|
||||
onDraw: ( event ) => {
|
||||
objectValuesMap( materials, ( material ) => {
|
||||
material.addUniform(
|
||||
material?.addUniform(
|
||||
'cameraNearFar',
|
||||
'2f',
|
||||
event.camera.near,
|
||||
event.camera.far
|
||||
);
|
||||
|
||||
material.addUniformMatrixVector(
|
||||
material?.addUniformMatrixVector(
|
||||
'inversePVM',
|
||||
'Matrix4fv',
|
||||
event.projectionMatrix
|
||||
|
@@ -49,7 +49,6 @@ export class DeferredCamera extends Entity {
|
||||
name: 'DeferredCamera/camera',
|
||||
materialTag: 'deferred',
|
||||
} );
|
||||
this.camera.clear = [];
|
||||
|
||||
// -- ao ---------------------------------------------------------------------------------------
|
||||
const aoTarget = new BufferRenderTarget( {
|
||||
|
@@ -20,7 +20,7 @@ import greetingsPreLainFrag from '../shaders/greetings-pre-lain.frag';
|
||||
import greetingsVert from '../shaders/greetings.vert';
|
||||
import quadVert from '../shaders/quad.vert';
|
||||
|
||||
const INSTANCES = 256;
|
||||
const INSTANCES = 64;
|
||||
|
||||
// -- preprocessor ---------------------------------------------------------------------------------
|
||||
const materialBlurH = new Material(
|
||||
@@ -171,6 +171,8 @@ const charPosList = [
|
||||
'holon',
|
||||
'gam0022',
|
||||
'gaz',
|
||||
'gyabo',
|
||||
'iYOYi',
|
||||
'jetlag',
|
||||
'Jugem-T',
|
||||
'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 { genCube } from '../geometries/genCube';
|
||||
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
||||
import ifsAsUsualFrag from '../shaders/ifs-as-usual.frag';
|
||||
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 ( 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 ----------------------------------------------------------------------------------
|
||||
this.components.push( new Lambda( {
|
||||
onDraw: ( event ) => {
|
||||
@@ -88,6 +82,22 @@ export class IFSAsUsual extends Entity {
|
||||
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 -------------------------------------------------------------------------------------
|
||||
const mesh = new Mesh( {
|
||||
geometry,
|
||||
@@ -96,17 +106,5 @@ export class IFSAsUsual extends Entity {
|
||||
} );
|
||||
mesh.cull = MeshCull.None;
|
||||
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,
|
||||
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 ] ) );
|
||||
|
||||
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 ];
|
||||
|
@@ -5,7 +5,6 @@ import { IFSPistons } from './IFSPistons';
|
||||
import { LightEntity } from './LightEntity';
|
||||
import { LightShaft } from './LightShaft';
|
||||
import { Quaternion, Vector3 } from '@fms-cat/experimental';
|
||||
import { SufferTexts } from './SufferTexts';
|
||||
import { Wobbleball } from './Wobbleball';
|
||||
|
||||
interface SceneNeuroOptions {
|
||||
@@ -69,7 +68,6 @@ export class SceneNeuro extends Entity {
|
||||
new Wobbleball(),
|
||||
new IFSPistons(),
|
||||
boundingBox,
|
||||
new SufferTexts(),
|
||||
...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 = [
|
||||
'#DEFINE DISGRACE 1',
|
||||
'WELCOME TO THE MANGLER HELL',
|
||||
'CTRL + ALT + DESPAIR',
|
||||
'DEADLINE HARMS YOUR HEALTH',
|
||||
'LIBOPUS IS CHEATING',
|
||||
'PUBLIC GET FUCKED()',
|
||||
'\'RETRUN\': UNDECLARED IDENTIFIER',
|
||||
@@ -33,7 +33,7 @@ const sufferList = [
|
||||
'SVG.GETPOINTATLENGTH IS CHEATING',
|
||||
'COPY\'N\'PASTE ENGINEER',
|
||||
'60FPS OR DIE',
|
||||
'<PLACEHOLDER>',
|
||||
'EXPECT A TERRIBLE STYLE INCONSISTENCY',
|
||||
'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 ----------------------------------------------------------------------------------------
|
||||
if ( process.env.DEV ) {
|
||||
console.info( Component.nameMap );
|
||||
@@ -80,21 +71,31 @@ async function load(): Promise<void> {
|
||||
}
|
||||
|
||||
if ( !process.env.DEV ) {
|
||||
document.write( 'Wait a moment... ' );
|
||||
document.body.innerHTML = '';
|
||||
document.write( 'Wait a moment...' );
|
||||
}
|
||||
|
||||
await music.prepare();
|
||||
|
||||
if ( !process.env.DEV ) {
|
||||
document.body.innerHTML = '';
|
||||
|
||||
const button = document.createElement( 'a' );
|
||||
document.body.appendChild( button );
|
||||
document.body.prepend( button );
|
||||
button.innerHTML = 'click me!';
|
||||
|
||||
button.onclick = () => {
|
||||
document.body.appendChild( canvas );
|
||||
document.body.prepend( canvas );
|
||||
music.isPlaying = true;
|
||||
document.body.requestFullscreen();
|
||||
};
|
||||
|
||||
window.addEventListener( 'keydown', ( event ) => {
|
||||
if ( event.key === 'Escape' ) { // panic button
|
||||
dog.root.active = false;
|
||||
music.isPlaying = false;
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
load();
|
||||
|
@@ -21,6 +21,8 @@ const sectionResets = [
|
||||
336.0,
|
||||
400.0,
|
||||
464.0,
|
||||
528.0,
|
||||
560.0,
|
||||
1E9,
|
||||
].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_AAAA = 400.0 * BEAT;
|
||||
const float SECTION_PSY = 464.0 * BEAT;
|
||||
const float SECTION_END = 528.0 * BEAT;
|
||||
|
||||
#define saturate(i) clamp(i, 0.,1.)
|
||||
#define aSaturate(i) clamp((i),-1.,1.)
|
||||
@@ -42,6 +43,13 @@ in float off;
|
||||
out float outL;
|
||||
out float outR;
|
||||
|
||||
float seed;
|
||||
|
||||
float random() {
|
||||
seed = fs( seed );
|
||||
return 2.0 * seed - 1.0;
|
||||
}
|
||||
|
||||
float auto( float y ) {
|
||||
return texture( samplerAutomaton, vec2( off / bufferLength, y ) ).x;
|
||||
}
|
||||
@@ -256,14 +264,23 @@ vec2 mainAudio( vec4 time ) {
|
||||
-3, 3, 7, 12, 17, 22
|
||||
);
|
||||
|
||||
int progB = ( time.w < SECTION_AAAA - 8.0 * BEAT )
|
||||
? 6 * ( int( time.z / ( 8.0 * BEAT ) ) % 8 )
|
||||
int progB = ( time.w < SECTION_PORTER_FUCKING_ROBINSON ) ? 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;
|
||||
|
||||
float bassfreq = n2f( 0.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 ---------------------------------------------------------------------------------------
|
||||
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 );
|
||||
@@ -329,29 +346,6 @@ vec2 mainAudio( vec4 time ) {
|
||||
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 ---------------------------------------------------------------------------------------
|
||||
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 );
|
||||
@@ -500,7 +494,8 @@ vec2 mainAudio( vec4 time ) {
|
||||
: 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_PSY ? 1E9
|
||||
: time.x;
|
||||
: time.w < SECTION_END ? time.x
|
||||
: time.z;
|
||||
{
|
||||
sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick );
|
||||
dest += 0.25 * kick( tKick, 1.0 );
|
||||
@@ -523,7 +518,7 @@ vec2 mainAudio( vec4 time ) {
|
||||
|
||||
if (
|
||||
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 decay = mix( 40.0, 100.0, fs( floor( time.z / ( 0.25 * BEAT ) ) ) );
|
||||
@@ -531,42 +526,20 @@ vec2 mainAudio( vec4 time ) {
|
||||
}
|
||||
|
||||
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 );
|
||||
dest += 0.1 * mix( 0.3, 1.0, sidechain ) * hihat( t, 20.0 );
|
||||
}
|
||||
|
||||
// -- clap ---------------------------------------------------------------------------------------
|
||||
// -- crash --------------------------------------------------------------------------------------
|
||||
if (
|
||||
inRange( time.w, SECTION_PSY + 64.0 * BEAT, 1E9 )
|
||||
) {
|
||||
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 )
|
||||
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY )
|
||||
) {
|
||||
float t = time.z;
|
||||
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 ---------------------------------------------------------------------------------------
|
||||
if (
|
||||
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 = 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;
|
||||
|
||||
float roll = fs( 2.4 + lofi( time.z, 0.5 * BEAT ) );
|
||||
@@ -591,7 +564,7 @@ vec2 mainAudio( vec4 time ) {
|
||||
}
|
||||
|
||||
// -- 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( time.x, 0.25 * BEAT );
|
||||
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 );
|
||||
}
|
||||
|
||||
// -- 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 ----------------------------------------------------------------------------------
|
||||
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA ) ) {
|
||||
float t = mod( time.z, 8.0 * BEAT );
|
||||
@@ -658,10 +655,10 @@ vec2 mainAudio( vec4 time ) {
|
||||
// -- lead ---------------------------------------------------------------------------------------
|
||||
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY ) ) {
|
||||
const int notes[16] = int[](
|
||||
0, 10, 12, 19,
|
||||
0, 14, 15, 22,
|
||||
-4, 10, 12, 19,
|
||||
-5, 14, 15, 22,
|
||||
0, 17, 19, 26,
|
||||
0, 14, 15, 22
|
||||
-3, 14, 15, 22
|
||||
);
|
||||
|
||||
vec2 sum = vec2( 0.0 );
|
||||
@@ -700,6 +697,10 @@ vec2 mainAudio( vec4 time ) {
|
||||
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 ------------------------------------------------------------------------------------
|
||||
if ( inRange( time.w, SECTION_AAAA + 32.0 * BEAT, SECTION_PSY ) ) {
|
||||
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 );
|
||||
}
|
||||
|
||||
// -- fill, psy crashes --------------------------------------------------------------------------
|
||||
if ( inRange( time.w, SECTION_PSY + 61.0 * BEAT, SECTION_PSY + 64.0 * BEAT ) ) {
|
||||
dest *= 0.0;
|
||||
// -- fadeout ------------------------------------------------------------------------------------
|
||||
dest *= fadeout;
|
||||
|
||||
float stretch = time.x - lofi( time.x, 0.02 ) * 0.9;
|
||||
float range = inRangeFloat( time.y, 0.0 * BEAT, 1.75 * BEAT );
|
||||
dest += 0.2 * kick( stretch, 1.0 ) * range;
|
||||
dest += 0.1 * crash( stretch ) * range;
|
||||
// -- oidos!! ------------------------------------------------------------------------------------
|
||||
// https://www.shadertoy.com/view/NdlGDl
|
||||
if ( inRange( time.w, SECTION_END, 1E9 ) ) {
|
||||
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 );
|
||||
dest += vec2( 0.1, 0.07 ) * crash( time.y - 2.5 * BEAT ) * inRangeSmooth( time.y, 0.0, 2.75 * BEAT, 400.0 );
|
||||
dest += vec2( 0.07, 0.1 ) * crash( time.y - 3.0 * BEAT ) * inRangeSmooth( time.y, 0.0, 3.25 * BEAT, 400.0 );
|
||||
dest += vec2( 0.1, 0.07 ) * crash( time.y - 3.5 * BEAT ) * inRangeSmooth( time.y, 0.0, 3.75 * BEAT, 400.0 );
|
||||
float relfreq = pow( 2.0, reltone / 12.0 );
|
||||
float relfreqOt = floor( relfreq + 0.5 );
|
||||
float relfreqH = mix( relfreq, relfreqOt, 0.2 );
|
||||
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 );
|
||||
}
|
||||
|
78
src/scene.ts
78
src/scene.ts
@@ -1,4 +1,5 @@
|
||||
import { Antialias } from './entities/Antialias';
|
||||
import { BigBlur } from './entities/BigBlur';
|
||||
import { Bloom } from './entities/Bloom';
|
||||
import { BufferRenderTarget } from './heck/BufferRenderTarget';
|
||||
import { CanvasRenderTarget } from './heck/CanvasRenderTarget';
|
||||
@@ -20,15 +21,19 @@ import { NoiseVoxels } from './entities/NoiseVoxels';
|
||||
import { PixelSorter } from './entities/PixelSorter';
|
||||
import { Post } from './entities/Post';
|
||||
import { RTInspector } from './entities/RTInspector';
|
||||
import { SSR } from './entities/SSR';
|
||||
import { SceneBegin } from './entities/SceneBegin';
|
||||
import { SceneCrystals } from './entities/SceneCrystals';
|
||||
import { SceneDynamic } from './entities/SceneDynamic';
|
||||
import { SceneNeuro } from './entities/SceneNeuro';
|
||||
import { ScenePsy } from './entities/ScenePsy';
|
||||
import { Serial } from './entities/Serial';
|
||||
import { SphereParticles } from './entities/SphereParticles';
|
||||
import { SufferTexts } from './entities/SufferTexts';
|
||||
import { Swap, Vector3 } from '@fms-cat/experimental';
|
||||
import { TestScreen } from './entities/TestScreen';
|
||||
import { Tetrahedron } from './entities/Tetrahedron';
|
||||
import { Trails } from './entities/Trails';
|
||||
import { TextOverlay } from './entities/TextOverlay';
|
||||
import { arraySetDelete } from './utils/arraySetDelete';
|
||||
import { auto, automaton } from './globals/automaton';
|
||||
import { music } from './globals/music';
|
||||
@@ -92,9 +97,25 @@ class EntityReplacer<T extends Entity> {
|
||||
const ibllut = new IBLLUT();
|
||||
dog.root.children.push( ibllut.entity );
|
||||
|
||||
// -- deferred stuff -------------------------------------------------------------------------------
|
||||
const deferredRoot = new Entity();
|
||||
dog.root.children.push( deferredRoot );
|
||||
const replacerFlickyParticles = new EntityReplacer(
|
||||
() => new FlickyParticles(),
|
||||
'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(
|
||||
() => 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(
|
||||
() => new SceneBegin( { scenes: [ dog.root ] } ),
|
||||
'SceneBegin'
|
||||
@@ -206,17 +220,15 @@ if ( process.env.DEV && module.hot ) {
|
||||
} );
|
||||
}
|
||||
|
||||
// -- forward stuff --------------------------------------------------------------------------------
|
||||
const forwardRoot = new Entity();
|
||||
dog.root.children.push( forwardRoot );
|
||||
|
||||
const replacerFlickyParticles = new EntityReplacer(
|
||||
() => new FlickyParticles(),
|
||||
'FlickyParticles',
|
||||
const replacerScenePsy = new EntityReplacer(
|
||||
() => new ScenePsy( { scenes: [ dog.root ] } ),
|
||||
'ScenePsy'
|
||||
);
|
||||
if ( process.env.DEV && module.hot ) {
|
||||
module.hot.accept( './entities/FlickyParticles', () => {
|
||||
replacerFlickyParticles.replace();
|
||||
module.hot.accept( './entities/ScenePsy', () => {
|
||||
replacerScenePsy.current.lights.map( ( light ) => arraySetDelete( lights, light ) );
|
||||
replacerScenePsy.replace();
|
||||
lights.push( ...replacerScenePsy.current.lights );
|
||||
} );
|
||||
}
|
||||
|
||||
@@ -242,6 +254,7 @@ const lights = [
|
||||
...replacerSceneNeuro.current.lights,
|
||||
...replacerSceneDynamic.current.lights,
|
||||
...replacerSceneCrystals.current.lights,
|
||||
...replacerScenePsy.current.lights,
|
||||
];
|
||||
|
||||
// const light2 = new LightEntity( {
|
||||
@@ -345,6 +358,14 @@ dog.root.components.push( new Lambda( {
|
||||
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 -----------------------------------------------------------------------------------------
|
||||
swap.swap();
|
||||
const antialias = new Antialias( {
|
||||
@@ -353,6 +374,18 @@ const antialias = new 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();
|
||||
const bloom = new Bloom( {
|
||||
input: swap.i,
|
||||
@@ -395,6 +428,11 @@ const post = new Post( {
|
||||
} );
|
||||
dog.root.children.push( post );
|
||||
|
||||
const testScreen = new TestScreen( {
|
||||
target: canvasRenderTarget
|
||||
} );
|
||||
dog.root.children.push( testScreen );
|
||||
|
||||
if ( process.env.DEV ) {
|
||||
const rtInspector = new RTInspector( {
|
||||
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
|
||||
|
||||
#ifdef DEPTH
|
||||
MARCH_ITER = 10;
|
||||
MARCH_ITER = 30;
|
||||
#endif
|
||||
|
||||
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||
@@ -128,7 +128,7 @@ void main() {
|
||||
fragPosition = vec4( modelPos.xyz, depth );
|
||||
fragNormal = vec4( modelNormal, 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
|
||||
|
||||
#ifdef DEPTH
|
||||
|
@@ -181,7 +181,7 @@ void main() {
|
||||
fragPosition = vec4( modelPos.xyz, depth );
|
||||
fragNormal = vec4( modelNormal, 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
|
||||
|
||||
#ifdef DEPTH
|
||||
|
@@ -42,10 +42,6 @@ void main() {
|
||||
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 += 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 ===================================================================
|
||||
vPosition = 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;
|
||||
|
||||
#define lofi(i,j) (floor((i)/(j))*(j))
|
||||
#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)))
|
||||
@@ -23,7 +24,6 @@ in vec4 vPositionWithoutModel;
|
||||
out vec4 fragColor;
|
||||
#endif
|
||||
|
||||
uniform float time;
|
||||
uniform float ifsSeed;
|
||||
uniform vec2 resolution;
|
||||
uniform vec2 cameraNearFar;
|
||||
@@ -33,9 +33,6 @@ uniform mat4 modelMatrix;
|
||||
uniform mat4 viewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
uniform mat4 inversePVM;
|
||||
uniform sampler2D samplerRandom;
|
||||
uniform sampler2D samplerRandomStatic;
|
||||
uniform sampler2D samplerCapture;
|
||||
|
||||
vec3 divideByW( vec4 v ) {
|
||||
return v.xyz / v.w;
|
||||
@@ -82,7 +79,7 @@ float map( vec3 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(
|
||||
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.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;
|
||||
}
|
||||
@@ -119,7 +116,7 @@ void main() {
|
||||
|
||||
for ( int i = 0; i < MARCH_ITER; i ++ ) {
|
||||
isect = map( rayPos );
|
||||
rayLen += 0.5 * isect;
|
||||
rayLen += 0.8 * isect;
|
||||
rayPos = rayOri + rayDir * rayLen;
|
||||
|
||||
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 HUGE = 9E16;
|
||||
const float INTERVAL = 0.03125;
|
||||
const float PI = 3.14159265;
|
||||
const float TAU = 6.283185307;
|
||||
|
||||
#define fs(i) (fract(sin((i)*114.514)*1919.810))
|
||||
#define saturate(i) clamp(i,0.,1.)
|
||||
#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 = 1) out vec4 fragCompute1;
|
||||
@@ -17,40 +18,18 @@ layout (location = 1) out vec4 fragCompute1;
|
||||
uniform bool init;
|
||||
uniform bool shouldUpdate;
|
||||
uniform float time;
|
||||
uniform float beat;
|
||||
uniform float trails;
|
||||
uniform float trailLength;
|
||||
uniform float totalFrame;
|
||||
uniform float deltaTime;
|
||||
uniform vec2 resolution;
|
||||
uniform sampler2D samplerCompute0;
|
||||
uniform sampler2D samplerCompute1;
|
||||
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 ) {
|
||||
return fract( sin( i ) * 1846.42 );
|
||||
}
|
||||
|
||||
vec4 sampleRandom( vec2 _uv ) {
|
||||
return texture( samplerRandom, _uv );
|
||||
}
|
||||
|
||||
#pragma glslify: prng = require( ./-prng );
|
||||
#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise );
|
||||
|
||||
@@ -67,40 +46,6 @@ vec3 randomSphere( inout vec4 seed ) {
|
||||
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() {
|
||||
vec2 uv = gl_FragCoord.xy / resolution;
|
||||
|
||||
@@ -115,8 +60,14 @@ void main() {
|
||||
vec4 tex0 = texture( samplerCompute0, uv );
|
||||
vec4 tex1 = texture( samplerCompute1, uv );
|
||||
|
||||
tex0.z += 4.0 * deltaTime; // camera
|
||||
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;
|
||||
@@ -140,46 +91,55 @@ void main() {
|
||||
float timing = mix( 0.0, PARTICLE_LIFE_LENGTH, floor( uv.y * trails ) / trails );
|
||||
timing += lofi( time, PARTICLE_LIFE_LENGTH );
|
||||
|
||||
if ( time - deltaTime + PARTICLE_LIFE_LENGTH < timing ) {
|
||||
if ( time - dt + PARTICLE_LIFE_LENGTH < timing ) {
|
||||
timing -= PARTICLE_LIFE_LENGTH;
|
||||
}
|
||||
|
||||
// == initialize particles =======================================================================
|
||||
if ( shouldUpdate ) {
|
||||
// == initialize particles =====================================================================
|
||||
if (
|
||||
time - deltaTime < timing && timing <= time
|
||||
time - dt < timing && timing <= time
|
||||
) {
|
||||
dt = time - timing;
|
||||
|
||||
pos = 1.0 * randomSphere( seed );
|
||||
pos = lofi( 5.0 * randomSphere( seed ), INTERVAL );
|
||||
pos.z -= 4.0;
|
||||
|
||||
vel = 1.0 * randomSphere( seed );
|
||||
|
||||
life = 1.0;
|
||||
life = 0.0;
|
||||
|
||||
jumpFlag = 1.0;
|
||||
} else {
|
||||
jumpFlag = 0.0; // remove jumping flag
|
||||
}
|
||||
|
||||
// == update particles ===========================================================================
|
||||
// == update particles =========================================================================
|
||||
// noise field
|
||||
vel += 40.0 * cyclicNoise( pos ) * dt;
|
||||
vel += 4.0 * cyclicNoise( pos ) * dt;
|
||||
|
||||
// resistance
|
||||
vel *= exp( -10.0 * dt );
|
||||
// vel *= exp( -10.0 * dt );
|
||||
// vel.z += 10.0 * dt;
|
||||
|
||||
vec3 v = vel;
|
||||
// float vmax = max( abs( v.x ), max( abs( v.y ), abs( v.z ) ) );
|
||||
// v *= (
|
||||
// abs( v.x ) == vmax ? vec3( 1.0, 0.0, 0.0 ) :
|
||||
// abs( v.y ) == vmax ? vec3( 0.0, 1.0, 0.0 ) :
|
||||
// vec3( 0.0, 0.0, 1.0 )
|
||||
// );
|
||||
float vmax = max( abs( v.x ), max( abs( v.y ), abs( v.z ) ) );
|
||||
v = INTERVAL * sign( v ) * (
|
||||
abs( v.x ) == vmax ? vec3( 1.0, 0.0, 0.0 ) :
|
||||
abs( v.y ) == vmax ? vec3( 0.0, 1.0, 0.0 ) :
|
||||
vec3( 0.0, 0.0, 1.0 )
|
||||
) / dt;
|
||||
|
||||
// pos.xyz += velScale * 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 );
|
||||
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_PBR = 2;
|
||||
const int MTL_REFRACT = 3;
|
||||
const int MTL_PSY = 4;
|
||||
const float ENV_UV_MARGIN = 0.9375;
|
||||
const float AO_BIAS = 0.0;
|
||||
const float AO_RADIUS = 0.5;
|
||||
@@ -276,6 +277,27 @@ void main() {
|
||||
|
||||
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 ) );
|
||||
|
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,
|
||||
drop_console: true,
|
||||
keep_fargs: false,
|
||||
passes: 1,
|
||||
passes: 2,
|
||||
unsafe_arrows: true,
|
||||
unsafe_math: true,
|
||||
},
|
||||
|
Reference in New Issue
Block a user