party version

This commit is contained in:
FMS-Cat
2021-04-03 09:38:52 +09:00
parent 1449c8fd00
commit c8f3abe286
39 changed files with 1832 additions and 581 deletions

File diff suppressed because one or more lines are too long

View File

@@ -2,13 +2,13 @@ export const
RTINSPECTOR_MULTIPLE = false, RTINSPECTOR_MULTIPLE = false,
// RTINSPECTOR_MULTIPLE = true, // RTINSPECTOR_MULTIPLE = true,
RTINSPECTOR_CAPTURE_NAME: string | null = null, RTINSPECTOR_CAPTURE_NAME: string | null = null,
// RTINSPECTOR_CAPTURE_NAME: string | null = 'PixelSorter/index', // RTINSPECTOR_CAPTURE_NAME: string | null = 'SSR/quad',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'Greetings/intermediate0', // RTINSPECTOR_CAPTURE_NAME: string | null = 'Greetings/intermediate0',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'main/postSwap0', // RTINSPECTOR_CAPTURE_NAME: string | null = 'main/postSwap0',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'EnvironmentMap/swap0', // RTINSPECTOR_CAPTURE_NAME: string | null = 'EnvironmentMap/swap0',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'DeferredCamera/cameraTarget', // RTINSPECTOR_CAPTURE_NAME: string | null = 'DeferredCamera/cameraTarget',
RTINSPECTOR_CAPTURE_INDEX = 0, RTINSPECTOR_CAPTURE_INDEX = 3,
COMPONENT_UPDATE_BREAKPOINT: string | null = null, COMPONENT_UPDATE_BREAKPOINT: string | null = null,
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'ForwardCamera/camera', // COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic2/shadowMapCamera',
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic1/shadowMapCamera', // COMPONENT_UPDATE_BREAKPOINT: string | null = 'lightDynamic1/shadowMapCamera',
COMPONENT_DRAW_BREAKPOINT: string | null = null; COMPONENT_DRAW_BREAKPOINT: string | null = null;

100
src/entities/BigBlur.ts Normal file
View 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;
} );
}
}

View File

@@ -4,11 +4,11 @@ import { BeamShot } from './BeamShot';
import { Entity } from '../heck/Entity'; import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry'; import { Geometry } from '../heck/Geometry';
import { Lambda } from '../heck/components/Lambda'; import { Lambda } from '../heck/components/Lambda';
import { Material } from '../heck/Material'; import { Material, MaterialMap } from '../heck/Material';
import { Mesh, MeshCull } from '../heck/components/Mesh'; import { Mesh, MeshCull } from '../heck/components/Mesh';
import { Vector3 } from '@fms-cat/experimental'; import { Vector3 } from '@fms-cat/experimental';
import { auto } from '../globals/automaton'; import { auto } from '../globals/automaton';
import { dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget'; import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
import { genCube } from '../geometries/genCube'; import { genCube } from '../geometries/genCube';
import { objectValuesMap } from '../utils/objectEntriesMap'; import { objectValuesMap } from '../utils/objectEntriesMap';
import crystalFrag from '../shaders/crystal.frag'; import crystalFrag from '../shaders/crystal.frag';
@@ -49,44 +49,52 @@ export class Crystal extends Entity {
}, },
); );
// I don't think we need this const depth = new Material(
// const depth = new Material( raymarchObjectVert,
// raymarchObjectVert, crystalFrag,
// crystalFrag, {
// { defines: [ 'DEPTH 1' ],
// defines: [ 'DEPTH 1' ], initOptions: { geometry, target: dummyRenderTarget }
// initOptions: { geometry, target: dummyRenderTarget } },
// }, );
// );
const materials = { deferred }; const materials: MaterialMap = { deferred };
if ( process.env.DEV ) { if ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {
module.hot.accept( '../shaders/crystal.frag', () => { module.hot.accept( '../shaders/crystal.frag', () => {
deferred.replaceShader( raymarchObjectVert, crystalFrag ); deferred.replaceShader( raymarchObjectVert, crystalFrag );
// depth.replaceShader( raymarchObjectVert, crystalFrag ); depth.replaceShader( raymarchObjectVert, crystalFrag );
} ); } );
} }
} }
objectValuesMap( materials, ( material ) => { objectValuesMap( materials, ( material ) => {
material.addUniform( 'size', '2f', width, height ); material?.addUniform( 'size', '2f', width, height );
material.addUniform( 'noiseOffset', '1f', noiseOffset ); material?.addUniform( 'noiseOffset', '1f', noiseOffset );
} );
// haha
auto( 'Crystal/enableDepth', ( { uninit } ) => {
if ( uninit ) {
delete materials.depth;
} else {
materials.depth = depth;
}
} ); } );
// -- updater ---------------------------------------------------------------------------------- // -- updater ----------------------------------------------------------------------------------
this.components.push( new Lambda( { this.components.push( new Lambda( {
onDraw: ( event ) => { onDraw: ( event ) => {
objectValuesMap( materials, ( material ) => { objectValuesMap( materials, ( material ) => {
material.addUniform( material?.addUniform(
'cameraNearFar', 'cameraNearFar',
'2f', '2f',
event.camera.near, event.camera.near,
event.camera.far event.camera.far
); );
material.addUniformMatrixVector( material?.addUniformMatrixVector(
'inversePVM', 'inversePVM',
'Matrix4fv', 'Matrix4fv',
event.projectionMatrix event.projectionMatrix

View File

@@ -49,7 +49,6 @@ export class DeferredCamera extends Entity {
name: 'DeferredCamera/camera', name: 'DeferredCamera/camera',
materialTag: 'deferred', materialTag: 'deferred',
} ); } );
this.camera.clear = [];
// -- ao --------------------------------------------------------------------------------------- // -- ao ---------------------------------------------------------------------------------------
const aoTarget = new BufferRenderTarget( { const aoTarget = new BufferRenderTarget( {

View File

@@ -20,7 +20,7 @@ import greetingsPreLainFrag from '../shaders/greetings-pre-lain.frag';
import greetingsVert from '../shaders/greetings.vert'; import greetingsVert from '../shaders/greetings.vert';
import quadVert from '../shaders/quad.vert'; import quadVert from '../shaders/quad.vert';
const INSTANCES = 256; const INSTANCES = 64;
// -- preprocessor --------------------------------------------------------------------------------- // -- preprocessor ---------------------------------------------------------------------------------
const materialBlurH = new Material( const materialBlurH = new Material(
@@ -171,6 +171,8 @@ const charPosList = [
'holon', 'holon',
'gam0022', 'gam0022',
'gaz', 'gaz',
'gyabo',
'iYOYi',
'jetlag', 'jetlag',
'Jugem-T', 'Jugem-T',
'kaneta', 'kaneta',

View 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 );
}
}

View File

@@ -8,7 +8,6 @@ import { auto } from '../globals/automaton';
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget'; import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
import { genCube } from '../geometries/genCube'; import { genCube } from '../geometries/genCube';
import { objectValuesMap } from '../utils/objectEntriesMap'; import { objectValuesMap } from '../utils/objectEntriesMap';
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
import ifsAsUsualFrag from '../shaders/ifs-as-usual.frag'; import ifsAsUsualFrag from '../shaders/ifs-as-usual.frag';
import raymarchObjectVert from '../shaders/raymarch-object.vert'; import raymarchObjectVert from '../shaders/raymarch-object.vert';
@@ -47,7 +46,7 @@ export class IFSAsUsual extends Entity {
}, },
); );
const materials = { deferred, depth }; const materials = { deferred };
if ( process.env.DEV ) { if ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {
@@ -58,11 +57,6 @@ export class IFSAsUsual extends Entity {
} }
} }
objectValuesMap( materials, ( material ) => {
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
} );
// -- updater ---------------------------------------------------------------------------------- // -- updater ----------------------------------------------------------------------------------
this.components.push( new Lambda( { this.components.push( new Lambda( {
onDraw: ( event ) => { onDraw: ( event ) => {
@@ -88,6 +82,22 @@ export class IFSAsUsual extends Entity {
name: process.env.DEV && 'IFSAsUsual/updater', name: process.env.DEV && 'IFSAsUsual/updater',
} ) ); } ) );
// -- speen ------------------------------------------------------------------------------------
const axis = new Vector3( [ 1.0, -1.0, 1.0 ] ).normalized;
this.components.push( new Lambda( {
onUpdate: ( { time } ) => {
this.transform.rotation = Quaternion.fromAxisAngle( axis, time );
},
name: process.env.DEV && 'IFSAsUsual/updater2',
} ) );
// -- auto -------------------------------------------------------------------------------------
auto( 'IFSAsUsual/ifsSeed', ( { value } ) => {
objectValuesMap( materials, ( material ) => {
material.addUniform( 'ifsSeed', '1f', value );
} );
} );
// -- mesh ------------------------------------------------------------------------------------- // -- mesh -------------------------------------------------------------------------------------
const mesh = new Mesh( { const mesh = new Mesh( {
geometry, geometry,
@@ -96,17 +106,5 @@ export class IFSAsUsual extends Entity {
} ); } );
mesh.cull = MeshCull.None; mesh.cull = MeshCull.None;
this.components.push( mesh ); this.components.push( mesh );
// -- speen ------------------------------------------------------------------------------------
const axis = new Vector3( [ 1.0, -1.0, 1.0 ] ).normalized;
this.components.push( new Lambda( {
onUpdate: ( { time } ) => {
this.transform.rotation = Quaternion.fromAxisAngle( axis, time );
objectValuesMap( materials, ( material ) => {
material.addUniform( 'ifsSeed', '1f', auto( 'IFSAsUsual/ifsSeed' ) );
} );
},
name: process.env.DEV && 'IFSAsUsual/update',
} ) );
} }
} }

117
src/entities/PsyField.ts Normal file
View 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
View 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
View 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;
} );
}
}

View File

@@ -89,11 +89,11 @@ export class SceneCrystals extends Entity {
shadowMapFar: 20.0, shadowMapFar: 20.0,
namePrefix: process.env.DEV && 'lightCrystals1', namePrefix: process.env.DEV && 'lightCrystals1',
} ); } );
light1.color = [ 400.0, 400.0, 400.0 ]; light1.color = [ 100.0, 100.0, 100.0 ];
light1.transform.lookAt( new Vector3( [ 0.0, 4.0, 1.0 ] ) ); light1.transform.lookAt( new Vector3( [ 0.0, 4.0, 1.0 ] ) );
auto( 'SceneCrystals/light/amp', ( { value } ) => { auto( 'SceneCrystals/light/amp', ( { value } ) => {
light1.color = [ 400.0 * value, 400.0 * value, 400.0 * value ]; light1.color = [ 100.0 * value, 100.0 * value, 100.0 * value ];
} ); } );
this.lights = [ light1 ]; this.lights = [ light1 ];

View File

@@ -5,7 +5,6 @@ import { IFSPistons } from './IFSPistons';
import { LightEntity } from './LightEntity'; import { LightEntity } from './LightEntity';
import { LightShaft } from './LightShaft'; import { LightShaft } from './LightShaft';
import { Quaternion, Vector3 } from '@fms-cat/experimental'; import { Quaternion, Vector3 } from '@fms-cat/experimental';
import { SufferTexts } from './SufferTexts';
import { Wobbleball } from './Wobbleball'; import { Wobbleball } from './Wobbleball';
interface SceneNeuroOptions { interface SceneNeuroOptions {
@@ -69,7 +68,6 @@ export class SceneNeuro extends Entity {
new Wobbleball(), new Wobbleball(),
new IFSPistons(), new IFSPistons(),
boundingBox, boundingBox,
new SufferTexts(),
...this.lights, ...this.lights,
); );
} }

43
src/entities/ScenePsy.ts Normal file
View 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,
);
}
}

View File

@@ -21,7 +21,7 @@ const PARTICLES = 256;
const sufferList = [ const sufferList = [
'#DEFINE DISGRACE 1', '#DEFINE DISGRACE 1',
'WELCOME TO THE MANGLER HELL', 'WELCOME TO THE MANGLER HELL',
'CTRL + ALT + DESPAIR', 'DEADLINE HARMS YOUR HEALTH',
'LIBOPUS IS CHEATING', 'LIBOPUS IS CHEATING',
'PUBLIC GET FUCKED()', 'PUBLIC GET FUCKED()',
'\'RETRUN\': UNDECLARED IDENTIFIER', '\'RETRUN\': UNDECLARED IDENTIFIER',
@@ -33,7 +33,7 @@ const sufferList = [
'SVG.GETPOINTATLENGTH IS CHEATING', 'SVG.GETPOINTATLENGTH IS CHEATING',
'COPY\'N\'PASTE ENGINEER', 'COPY\'N\'PASTE ENGINEER',
'60FPS OR DIE', '60FPS OR DIE',
'<PLACEHOLDER>', 'EXPECT A TERRIBLE STYLE INCONSISTENCY',
'END MY SUFFER', 'END MY SUFFER',
]; ];

View 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
View 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 );
} );
}
}

View File

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

View File

@@ -57,15 +57,6 @@ if ( process.env.DEV ) {
} ); } );
} }
if ( !process.env.DEV ) {
window.addEventListener( 'keydown', ( event ) => {
if ( event.key === 'Escape' ) { // panic button
dog.root.active = false;
music.isPlaying = false;
}
} );
}
// -- wenis ---------------------------------------------------------------------------------------- // -- wenis ----------------------------------------------------------------------------------------
if ( process.env.DEV ) { if ( process.env.DEV ) {
console.info( Component.nameMap ); console.info( Component.nameMap );
@@ -80,21 +71,31 @@ async function load(): Promise<void> {
} }
if ( !process.env.DEV ) { if ( !process.env.DEV ) {
document.write( 'Wait a moment... ' ); document.body.innerHTML = '';
document.write( 'Wait a moment...' );
} }
await music.prepare(); await music.prepare();
if ( !process.env.DEV ) { if ( !process.env.DEV ) {
document.body.innerHTML = '';
const button = document.createElement( 'a' ); const button = document.createElement( 'a' );
document.body.appendChild( button ); document.body.prepend( button );
button.innerHTML = 'click me!'; button.innerHTML = 'click me!';
button.onclick = () => { button.onclick = () => {
document.body.appendChild( canvas ); document.body.prepend( canvas );
music.isPlaying = true; music.isPlaying = true;
document.body.requestFullscreen(); document.body.requestFullscreen();
}; };
window.addEventListener( 'keydown', ( event ) => {
if ( event.key === 'Escape' ) { // panic button
dog.root.active = false;
music.isPlaying = false;
}
} );
} }
} }
load(); load();

View File

@@ -21,6 +21,8 @@ const sectionResets = [
336.0, 336.0,
400.0, 400.0,
464.0, 464.0,
528.0,
560.0,
1E9, 1E9,
].map( ( v ) => v * 60.0 / MUSIC_BPM ); ].map( ( v ) => v * 60.0 / MUSIC_BPM );

View File

@@ -14,6 +14,7 @@ const float SECTION_WHOA = 272.0 * BEAT;
const float SECTION_PORTER_FUCKING_ROBINSON = 336.0 * BEAT; const float SECTION_PORTER_FUCKING_ROBINSON = 336.0 * BEAT;
const float SECTION_AAAA = 400.0 * BEAT; const float SECTION_AAAA = 400.0 * BEAT;
const float SECTION_PSY = 464.0 * BEAT; const float SECTION_PSY = 464.0 * BEAT;
const float SECTION_END = 528.0 * BEAT;
#define saturate(i) clamp(i, 0.,1.) #define saturate(i) clamp(i, 0.,1.)
#define aSaturate(i) clamp((i),-1.,1.) #define aSaturate(i) clamp((i),-1.,1.)
@@ -42,6 +43,13 @@ in float off;
out float outL; out float outL;
out float outR; out float outR;
float seed;
float random() {
seed = fs( seed );
return 2.0 * seed - 1.0;
}
float auto( float y ) { float auto( float y ) {
return texture( samplerAutomaton, vec2( off / bufferLength, y ) ).x; return texture( samplerAutomaton, vec2( off / bufferLength, y ) ).x;
} }
@@ -256,14 +264,23 @@ vec2 mainAudio( vec4 time ) {
-3, 3, 7, 12, 17, 22 -3, 3, 7, 12, 17, 22
); );
int progB = ( time.w < SECTION_AAAA - 8.0 * BEAT ) int progB = ( time.w < SECTION_PORTER_FUCKING_ROBINSON ) ? 6 * ( int( time.z / ( 8.0 * BEAT ) ) % 8 )
? 6 * ( int( time.z / ( 8.0 * BEAT ) ) % 8 ) : ( time.w < SECTION_AAAA - 8.0 * BEAT ) ? 6 * ( 4 + ( int( time.z / ( 8.0 * BEAT ) ) % 4 ) )
: 36; : 36;
float bassfreq = n2f( 0.0 ); float bassfreq = n2f( 0.0 );
float sidechain = 1.0; float sidechain = 1.0;
float fadeout = smoothstep( SECTION_END + 32.0 * BEAT, SECTION_END, time.w );
// -- test ---------------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_BEGIN - 8.0 * BEAT, SECTION_BEGIN ) ) {
float freq = 1000.0 * ( 1.0 + step( time.y, BEAT ) );
float amp = inRangeSmooth( time.x, 0.0, 0.04, 1E3 );
dest += 0.3 * amp * sin( TAU * freq * time.x );
}
// -- kick --------------------------------------------------------------------------------------- // -- kick ---------------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_BEGIN + 64.0 * BEAT, SECTION_NEURO - 14.5 * BEAT ) ) { if ( inRange( time.w, SECTION_BEGIN + 64.0 * BEAT, SECTION_NEURO - 14.5 * BEAT ) ) {
float t = mod( mod( time.z - 1.5 * BEAT, 4.0 * BEAT ), 2.5 * BEAT ); float t = mod( mod( time.z - 1.5 * BEAT, 4.0 * BEAT ), 2.5 * BEAT );
@@ -329,29 +346,6 @@ vec2 mainAudio( vec4 time ) {
dest += 0.14 * mix( 0.3, 1.0, sidechain ) * aSaturate( sum ); dest += 0.14 * mix( 0.3, 1.0, sidechain ) * aSaturate( sum );
} }
// -- choir --------------------------------------------------------------------------------------
if ( inRange( time.w, 0.0, SECTION_PORTER_FUCKING_ROBINSON ) ) {
const int notes[7] = int[](
10, 0, 10, 7, -5, 0, -5
);
vec2 sum = vec2( 0.0 );
vec2 radius = vec2( 0.00002 );
float tb = lofi( time.z, 0.5 * BEAT );
float t = time.z - tb;
for ( int i = 0; i < 21; i ++ ) {
int note = notes[ int( time.z / ( 0.5 * BEAT ) ) % 7 ];
float freq = n2f( note ) * 0.25;
freq *= 1.0 + 0.01 * ( 0.5 - fs( float( i ) ) );
float phase = 2.0 * tri( time.w * freq );
sum += 0.1 * inRangeSmooth( t, 0.0, 0.5 * BEAT, 1E3 ) * wavetable( phase, radius, vec2( 0.3 * float( i ) ) );
}
//dest += 0.14 * aSaturate( sum );
}
// -- kick --------------------------------------------------------------------------------------- // -- kick ---------------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_NEURO, SECTION_WHOA - 2.5 * BEAT ) ) { if ( inRange( time.w, SECTION_NEURO, SECTION_WHOA - 2.5 * BEAT ) ) {
float t = mod( mod( mod( time.y, 4.0 * BEAT ), 3.25 * BEAT ), 1.75 * BEAT ); float t = mod( mod( mod( time.y, 4.0 * BEAT ), 3.25 * BEAT ), 1.75 * BEAT );
@@ -500,7 +494,8 @@ vec2 mainAudio( vec4 time ) {
: time.w < SECTION_AAAA ? 1E9 : time.w < SECTION_AAAA ? 1E9
: time.w < SECTION_AAAA + 1.0 * BEAT ? time.x + mod( lofi( time.z, BEAT ), 8.0 * BEAT ) : time.w < SECTION_AAAA + 1.0 * BEAT ? time.x + mod( lofi( time.z, BEAT ), 8.0 * BEAT )
: time.w < SECTION_PSY ? 1E9 : time.w < SECTION_PSY ? 1E9
: time.x; : time.w < SECTION_END ? time.x
: time.z;
{ {
sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick ); sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick );
dest += 0.25 * kick( tKick, 1.0 ); dest += 0.25 * kick( tKick, 1.0 );
@@ -523,7 +518,7 @@ vec2 mainAudio( vec4 time ) {
if ( if (
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) || inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) ||
inRange( time.w, SECTION_PSY + 16.0 * BEAT, 1E9 ) inRange( time.w, SECTION_PSY + 16.0 * BEAT, SECTION_END )
) { ) {
float t = mod( time.x, 0.25 * BEAT ); float t = mod( time.x, 0.25 * BEAT );
float decay = mix( 40.0, 100.0, fs( floor( time.z / ( 0.25 * BEAT ) ) ) ); float decay = mix( 40.0, 100.0, fs( floor( time.z / ( 0.25 * BEAT ) ) ) );
@@ -531,42 +526,20 @@ vec2 mainAudio( vec4 time ) {
} }
if ( if (
inRange( time.w, SECTION_PSY + 31.5 * BEAT, 1E9 ) inRange( time.w, SECTION_PSY + 31.5 * BEAT, SECTION_END )
) { ) {
float t = mod( time.x - 0.5 * BEAT, BEAT ); float t = mod( time.x - 0.5 * BEAT, BEAT );
dest += 0.1 * mix( 0.3, 1.0, sidechain ) * hihat( t, 20.0 ); dest += 0.1 * mix( 0.3, 1.0, sidechain ) * hihat( t, 20.0 );
} }
// -- clap --------------------------------------------------------------------------------------- // -- crash --------------------------------------------------------------------------------------
if ( if (
inRange( time.w, SECTION_PSY + 64.0 * BEAT, 1E9 ) inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY )
) {
float t = mod( time.y - 1.0 * BEAT, 2.0 * BEAT );
dest += 0.1 * clap( t );
}
// -- crash ---------------------------------------------------------------------------------------
if (
!inRange( time.w, 0.0, SECTION_PORTER_FUCKING_ROBINSON ) &&
!inRange( time.w, SECTION_PSY, SECTION_PSY + 16.0 * BEAT )
) { ) {
float t = time.z; float t = time.z;
dest += 0.14 * crash( t ); dest += 0.14 * crash( t );
} }
// -- psysaw -------------------------------------------------------------------------------------
if (
inRange( time.w, SECTION_PSY + 64.0 * BEAT, 1E9 )
) {
float t = mod( time.z, 0.25 * BEAT );
float begin = time.z - t;
float dice = fs( begin );
if ( t < ( 0.25 - dice * 0.2 ) * BEAT ) {
float freq = 20.0 * sin( TAU * begin * 1.8 );
dest += 0.07 * saw( 20.0 * exp( -2.0 * fract( 10.0 * exp( -freq * t ) ) ) );
}
}
// -- amen --------------------------------------------------------------------------------------- // -- amen ---------------------------------------------------------------------------------------
if ( if (
inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) || inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA - 8.0 * BEAT ) ||
@@ -574,7 +547,7 @@ vec2 mainAudio( vec4 time ) {
) { ) {
float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) ); float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) );
// float chunk = time.y / ( 1.0 * BEAT ); // float chunk = time.y / ( 1.0 * BEAT );
vec2 vib = 0.003 * sin( 3.0 * time.z + vec2( 0.0, 0.2 ) ); vec2 vib = 0.003 * sin( 3.0 * time.z + vec2( 0.0, 1.4 ) );
vec2 tread = 2.0 * time.x + vib; vec2 tread = 2.0 * time.x + vib;
float roll = fs( 2.4 + lofi( time.z, 0.5 * BEAT ) ); float roll = fs( 2.4 + lofi( time.z, 0.5 * BEAT ) );
@@ -591,7 +564,7 @@ vec2 mainAudio( vec4 time ) {
} }
// -- psy bass ----------------------------------------------------------------------------------- // -- psy bass -----------------------------------------------------------------------------------
if ( SECTION_PSY < time.w ) { if ( inRange( time.w, SECTION_PSY, SECTION_END ) ) {
// float t = mod( aTime - 0.5 beat, 1.0 beat ); // float t = mod( aTime - 0.5 beat, 1.0 beat );
float t = mod( time.x, 0.25 * BEAT ); float t = mod( time.x, 0.25 * BEAT );
float decay = exp( -50.0 * t ); float decay = exp( -50.0 * t );
@@ -603,6 +576,30 @@ vec2 mainAudio( vec4 time ) {
dest += 0.12 * sidechain * wave * exp( -max( 0.0, t - 0.22 * BEAT ) * 400.0 ); dest += 0.12 * sidechain * wave * exp( -max( 0.0, t - 0.22 * BEAT ) * 400.0 );
} }
// -- pad ----------------------------------------------------------------------------------------
if ( SECTION_PSY < time.w ) {
vec2 sum = vec2( 0.0 );
float tb = lofi( time.z, 0.25 * BEAT );
float t = time.z - tb;
float rev = exp( 3.0 * fs( tb ) - 3.0 ) * exp( -20.0 * t );
vec2 radius = vec2( 0.02 ) * fadeout;
for ( int i = 0; i < 21; i ++ ) {
float freq = n2f( chordsA[ ( i % 8 ) ] ) * 0.25;
freq *= 1.0 + 0.001 * ( 0.5 - fs( float( i ) ) );
float phase = tri( time.w * freq ) * rev;
sum += 0.14 * wavetable( phase, radius, vec2( 0.3 * float( i ) ) );
}
for ( int i = 0; i < 7; i ++ ) {
float rate = n2r( float( chordsA[ i ] ) ) * 0.5;
sum += 0.1 * choir( time.z * rate * 0.5 ) * exp( -30.0 * t );
}
dest += 0.14 * mix( 0.3, 1.0, sidechain ) * aSaturate( sum );
}
// -- superbass ---------------------------------------------------------------------------------- // -- superbass ----------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA ) ) { if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA ) ) {
float t = mod( time.z, 8.0 * BEAT ); float t = mod( time.z, 8.0 * BEAT );
@@ -658,10 +655,10 @@ vec2 mainAudio( vec4 time ) {
// -- lead --------------------------------------------------------------------------------------- // -- lead ---------------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY ) ) { if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_PSY ) ) {
const int notes[16] = int[]( const int notes[16] = int[](
0, 10, 12, 19, -4, 10, 12, 19,
0, 14, 15, 22, -5, 14, 15, 22,
0, 17, 19, 26, 0, 17, 19, 26,
0, 14, 15, 22 -3, 14, 15, 22
); );
vec2 sum = vec2( 0.0 ); vec2 sum = vec2( 0.0 );
@@ -700,6 +697,10 @@ vec2 mainAudio( vec4 time ) {
dest += 0.3 * deepkick( mod( time.z, 8.0 * BEAT ) ); dest += 0.3 * deepkick( mod( time.z, 8.0 * BEAT ) );
} }
if ( inRange( time.w, SECTION_END, SECTION_END + 64.0 * BEAT ) ) {
dest += 0.3 * deepkick( time.z );
}
// -- buildup ------------------------------------------------------------------------------------ // -- buildup ------------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_AAAA + 32.0 * BEAT, SECTION_PSY ) ) { if ( inRange( time.w, SECTION_AAAA + 32.0 * BEAT, SECTION_PSY ) ) {
float ph = linearstep( SECTION_AAAA + 32.0 * BEAT, SECTION_PSY, time.w ); float ph = linearstep( SECTION_AAAA + 32.0 * BEAT, SECTION_PSY, time.w );
@@ -733,22 +734,41 @@ vec2 mainAudio( vec4 time ) {
dest += 0.2 * kick( time.y - 3.5 * BEAT, 1.0 ) * inRangeSmooth( time.y, 3.0 * BEAT, 3.75 * BEAT, 100.0 ); dest += 0.2 * kick( time.y - 3.5 * BEAT, 1.0 ) * inRangeSmooth( time.y, 3.0 * BEAT, 3.75 * BEAT, 100.0 );
} }
// -- fill, psy crashes -------------------------------------------------------------------------- // -- fadeout ------------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_PSY + 61.0 * BEAT, SECTION_PSY + 64.0 * BEAT ) ) { dest *= fadeout;
dest *= 0.0;
float stretch = time.x - lofi( time.x, 0.02 ) * 0.9; // -- oidos!! ------------------------------------------------------------------------------------
float range = inRangeFloat( time.y, 0.0 * BEAT, 1.75 * BEAT ); // https://www.shadertoy.com/view/NdlGDl
dest += 0.2 * kick( stretch, 1.0 ) * range; if ( inRange( time.w, SECTION_END, 1E9 ) ) {
dest += 0.1 * crash( stretch ) * range; seed = 0.261;
dest += 0.2 * kick( mod( time.x - 0.25 * BEAT, 0.5 * BEAT ), 1.0 ) * inRangeFloat( time.y, 1.75 * BEAT, 2.5 * BEAT ); for ( int i = 0; i < 50; i ++ ) {
float reltone = 4.0 + random() * 45.0;
dest += 0.2 * kick( mod( time.x, 0.5 * BEAT ), 1.0 ) * inRangeFloat( time.y, 2.5 * BEAT, 1E9 ); float relfreq = pow( 2.0, reltone / 12.0 );
dest += vec2( 0.1, 0.07 ) * crash( time.y - 2.5 * BEAT ) * inRangeSmooth( time.y, 0.0, 2.75 * BEAT, 400.0 ); float relfreqOt = floor( relfreq + 0.5 );
dest += vec2( 0.07, 0.1 ) * crash( time.y - 3.0 * BEAT ) * inRangeSmooth( time.y, 0.0, 3.25 * BEAT, 400.0 ); float relfreqH = mix( relfreq, relfreqOt, 0.2 );
dest += vec2( 0.1, 0.07 ) * crash( time.y - 3.5 * BEAT ) * inRangeSmooth( time.y, 0.0, 3.75 * BEAT, 400.0 ); reltone = log2( relfreqH ) * 12.0;
float mtone = reltone;
float mfreq = 220.0 * pow( 2.0, mtone / 12.0 );
for ( int j = 0; j < 50; j ++ ) {
float ptone = mtone + random() * 0.5;
float freq = 220.0 * pow( 2.0, ptone / 12.0 );
float noisePhase = TAU * fract( freq * time.z * 5.0 );
vec2 tt = time.z + 0.002 * wavetable( noisePhase, vec2( 0.0001 ), vec2( 0.03 * float( j ) ) );
vec2 phase = TAU * fract( freq * tt ) + TAU * vec2( random(), random() );
dest += ( 1.0 - fadeout ) * 0.0002 * sin( phase );
} }
}
}
float realfadeout = smoothstep( SECTION_END + 48.0 * BEAT, SECTION_END + 16.0 * BEAT, time.w );
dest *= realfadeout;
return aSaturate( dest ); return aSaturate( dest );
} }

View File

@@ -1,4 +1,5 @@
import { Antialias } from './entities/Antialias'; import { Antialias } from './entities/Antialias';
import { BigBlur } from './entities/BigBlur';
import { Bloom } from './entities/Bloom'; import { Bloom } from './entities/Bloom';
import { BufferRenderTarget } from './heck/BufferRenderTarget'; import { BufferRenderTarget } from './heck/BufferRenderTarget';
import { CanvasRenderTarget } from './heck/CanvasRenderTarget'; import { CanvasRenderTarget } from './heck/CanvasRenderTarget';
@@ -20,15 +21,19 @@ import { NoiseVoxels } from './entities/NoiseVoxels';
import { PixelSorter } from './entities/PixelSorter'; import { PixelSorter } from './entities/PixelSorter';
import { Post } from './entities/Post'; import { Post } from './entities/Post';
import { RTInspector } from './entities/RTInspector'; import { RTInspector } from './entities/RTInspector';
import { SSR } from './entities/SSR';
import { SceneBegin } from './entities/SceneBegin'; import { SceneBegin } from './entities/SceneBegin';
import { SceneCrystals } from './entities/SceneCrystals'; import { SceneCrystals } from './entities/SceneCrystals';
import { SceneDynamic } from './entities/SceneDynamic'; import { SceneDynamic } from './entities/SceneDynamic';
import { SceneNeuro } from './entities/SceneNeuro'; import { SceneNeuro } from './entities/SceneNeuro';
import { ScenePsy } from './entities/ScenePsy';
import { Serial } from './entities/Serial'; import { Serial } from './entities/Serial';
import { SphereParticles } from './entities/SphereParticles'; import { SphereParticles } from './entities/SphereParticles';
import { SufferTexts } from './entities/SufferTexts';
import { Swap, Vector3 } from '@fms-cat/experimental'; import { Swap, Vector3 } from '@fms-cat/experimental';
import { TestScreen } from './entities/TestScreen';
import { Tetrahedron } from './entities/Tetrahedron'; import { Tetrahedron } from './entities/Tetrahedron';
import { Trails } from './entities/Trails'; import { TextOverlay } from './entities/TextOverlay';
import { arraySetDelete } from './utils/arraySetDelete'; import { arraySetDelete } from './utils/arraySetDelete';
import { auto, automaton } from './globals/automaton'; import { auto, automaton } from './globals/automaton';
import { music } from './globals/music'; import { music } from './globals/music';
@@ -92,9 +97,25 @@ class EntityReplacer<T extends Entity> {
const ibllut = new IBLLUT(); const ibllut = new IBLLUT();
dog.root.children.push( ibllut.entity ); dog.root.children.push( ibllut.entity );
// -- deferred stuff ------------------------------------------------------------------------------- const replacerFlickyParticles = new EntityReplacer(
const deferredRoot = new Entity(); () => new FlickyParticles(),
dog.root.children.push( deferredRoot ); 'FlickyParticles',
);
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/FlickyParticles', () => {
replacerFlickyParticles.replace();
} );
}
const replacerSufferTexts = new EntityReplacer(
() => new SufferTexts(),
'SufferTexts',
);
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/SufferTexts', () => {
replacerSufferTexts.replace();
} );
}
const replacerSphereParticles = new EntityReplacer( const replacerSphereParticles = new EntityReplacer(
() => new SphereParticles(), () => new SphereParticles(),
@@ -146,13 +167,6 @@ if ( process.env.DEV && module.hot ) {
} ); } );
} }
const replacerTrails = new EntityReplacer( () => new Trails(), 'Trails' );
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/Trails', () => {
replacerTrails.replace();
} );
}
const replacerSceneBegin = new EntityReplacer( const replacerSceneBegin = new EntityReplacer(
() => new SceneBegin( { scenes: [ dog.root ] } ), () => new SceneBegin( { scenes: [ dog.root ] } ),
'SceneBegin' 'SceneBegin'
@@ -206,17 +220,15 @@ if ( process.env.DEV && module.hot ) {
} ); } );
} }
// -- forward stuff -------------------------------------------------------------------------------- const replacerScenePsy = new EntityReplacer(
const forwardRoot = new Entity(); () => new ScenePsy( { scenes: [ dog.root ] } ),
dog.root.children.push( forwardRoot ); 'ScenePsy'
const replacerFlickyParticles = new EntityReplacer(
() => new FlickyParticles(),
'FlickyParticles',
); );
if ( process.env.DEV && module.hot ) { if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/FlickyParticles', () => { module.hot.accept( './entities/ScenePsy', () => {
replacerFlickyParticles.replace(); replacerScenePsy.current.lights.map( ( light ) => arraySetDelete( lights, light ) );
replacerScenePsy.replace();
lights.push( ...replacerScenePsy.current.lights );
} ); } );
} }
@@ -242,6 +254,7 @@ const lights = [
...replacerSceneNeuro.current.lights, ...replacerSceneNeuro.current.lights,
...replacerSceneDynamic.current.lights, ...replacerSceneDynamic.current.lights,
...replacerSceneCrystals.current.lights, ...replacerSceneCrystals.current.lights,
...replacerScenePsy.current.lights,
]; ];
// const light2 = new LightEntity( { // const light2 = new LightEntity( {
@@ -345,6 +358,14 @@ dog.root.components.push( new Lambda( {
name: process.env.DEV && 'main/updateCamera', name: process.env.DEV && 'main/updateCamera',
} ) ); } ) );
swap.swap();
const ssr = new SSR( {
camera: deferredCamera,
shaded: swap.i,
target: swap.o,
} );
dog.root.children.push( ssr );
// -- post ----------------------------------------------------------------------------------------- // -- post -----------------------------------------------------------------------------------------
swap.swap(); swap.swap();
const antialias = new Antialias( { const antialias = new Antialias( {
@@ -353,6 +374,18 @@ const antialias = new Antialias( {
} ); } );
dog.root.children.push( antialias ); dog.root.children.push( antialias );
swap.swap();
const bigBlur = new BigBlur( {
input: swap.i,
target: swap.o,
} );
dog.root.children.push( bigBlur );
const textOverlay = new TextOverlay( {
target: swap.o,
} );
dog.root.children.push( textOverlay );
swap.swap(); swap.swap();
const bloom = new Bloom( { const bloom = new Bloom( {
input: swap.i, input: swap.i,
@@ -395,6 +428,11 @@ const post = new Post( {
} ); } );
dog.root.children.push( post ); dog.root.children.push( post );
const testScreen = new TestScreen( {
target: canvasRenderTarget
} );
dog.root.children.push( testScreen );
if ( process.env.DEV ) { if ( process.env.DEV ) {
const rtInspector = new RTInspector( { const rtInspector = new RTInspector( {
target: canvasRenderTarget target: canvasRenderTarget

40
src/shaders/big-blur.frag Normal file
View 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 );
}

View File

@@ -101,7 +101,7 @@ void main() {
#endif #endif
#ifdef DEPTH #ifdef DEPTH
MARCH_ITER = 10; MARCH_ITER = 30;
#endif #endif
for ( int i = 0; i < MARCH_ITER; i ++ ) { for ( int i = 0; i < MARCH_ITER; i ++ ) {
@@ -128,7 +128,7 @@ void main() {
fragPosition = vec4( modelPos.xyz, depth ); fragPosition = vec4( modelPos.xyz, depth );
fragNormal = vec4( modelNormal, 1.0 ); fragNormal = vec4( modelNormal, 1.0 );
fragColor = vec4( vec3( 0.5 ), 1.0 ); fragColor = vec4( vec3( 0.5 ), 1.0 );
fragWTF = vec4( vec3( 0.04, 1.0, 0.0 ), 3 ); fragWTF = vec4( vec3( 0.08, 0.9, 0.0 ), 3 );
#endif #endif
#ifdef DEPTH #ifdef DEPTH

View File

@@ -181,7 +181,7 @@ void main() {
fragPosition = vec4( modelPos.xyz, depth ); fragPosition = vec4( modelPos.xyz, depth );
fragNormal = vec4( modelNormal, 1.0 ); fragNormal = vec4( modelNormal, 1.0 );
fragColor = vec4( vec3( 0.6, 0.5, 0.4 ), 1.0 ); fragColor = vec4( vec3( 0.6, 0.5, 0.4 ), 1.0 );
fragWTF = vec4( vec3( 0.5, 0.2, 0.0 ), 3 ); fragWTF = vec4( vec3( 0.5, 0.2, 0.0 ), 2 );
#endif #endif
#ifdef DEPTH #ifdef DEPTH

View File

@@ -42,10 +42,6 @@ void main() {
vec2 offset = ( 0.6 - 0.2 * exp( -5.0 * vTime ) ) * vec2( vCharParams.y, 0.0 ); vec2 offset = ( 0.6 - 0.2 * exp( -5.0 * vTime ) ) * vec2( vCharParams.y, 0.0 );
vPosition.xy += ( offset + shape ) * min( 500.0 / charParams2.x, 1.0 ); vPosition.xy += ( offset + shape ) * min( 500.0 / charParams2.x, 1.0 );
vPosition.xy += 1.0
* ( fs( vCharParams.z + vec2( 2.66, 1.79 ) ) * 2.0 - 1.0 )
* pow( fs( vCharParams.z + 7.8 ), 2.0 );
// == send the vertex position =================================================================== // == send the vertex position ===================================================================
vPosition = vPosition; vPosition = vPosition;
vec4 outPos = vPosition; vec4 outPos = vPosition;

214
src/shaders/hooperball.frag Normal file
View 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
}

View File

@@ -2,6 +2,7 @@
precision highp float; precision highp float;
#define lofi(i,j) (floor((i)/(j))*(j))
#define fs(i) (fract(sin((i)*114.514)*1919.810)) #define fs(i) (fract(sin((i)*114.514)*1919.810))
#define saturate(x) clamp(x,0.,1.) #define saturate(x) clamp(x,0.,1.)
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a))) #define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
@@ -23,7 +24,6 @@ in vec4 vPositionWithoutModel;
out vec4 fragColor; out vec4 fragColor;
#endif #endif
uniform float time;
uniform float ifsSeed; uniform float ifsSeed;
uniform vec2 resolution; uniform vec2 resolution;
uniform vec2 cameraNearFar; uniform vec2 cameraNearFar;
@@ -33,9 +33,6 @@ uniform mat4 modelMatrix;
uniform mat4 viewMatrix; uniform mat4 viewMatrix;
uniform mat4 projectionMatrix; uniform mat4 projectionMatrix;
uniform mat4 inversePVM; uniform mat4 inversePVM;
uniform sampler2D samplerRandom;
uniform sampler2D samplerRandomStatic;
uniform sampler2D samplerCapture;
vec3 divideByW( vec4 v ) { vec3 divideByW( vec4 v ) {
return v.xyz / v.w; return v.xyz / v.w;
@@ -82,7 +79,7 @@ float map( vec3 p ) {
vec3 pt = p; vec3 pt = p;
float clampbox = box( pt, vec3( 1.0, 1.0, 1.0 ) ); float clampbox = box( pt, vec3( 1.0 ) );
vec3 r = mix( vec3 r = mix(
fs( vec3( 4.7, 3.2, 4.3 ) + floor( ifsSeed ) ), fs( vec3( 4.7, 3.2, 4.3 ) + floor( ifsSeed ) ),
@@ -93,7 +90,7 @@ float map( vec3 p ) {
pt = ifs( pt, r, 0.2 * t ); pt = ifs( pt, r, 0.2 * t );
pt = ifs( pt, r.yzx, 0.1 * t.yzx ); pt = ifs( pt, r.yzx, 0.1 * t.yzx );
float d = max( box( pt, vec3( 0.08 ) ), clampbox ); float d = max( box( pt, vec3( 0.09 ) ), clampbox );
return d; return d;
} }
@@ -119,7 +116,7 @@ void main() {
for ( int i = 0; i < MARCH_ITER; i ++ ) { for ( int i = 0; i < MARCH_ITER; i ++ ) {
isect = map( rayPos ); isect = map( rayPos );
rayLen += 0.5 * isect; rayLen += 0.8 * isect;
rayPos = rayOri + rayDir * rayLen; rayPos = rayOri + rayDir * rayLen;
if ( abs( isect ) < 1E-3 ) { break; } if ( abs( isect ) < 1E-3 ) { break; }

237
src/shaders/psy-field.frag Normal file
View 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
}

View File

@@ -4,12 +4,13 @@ precision highp float;
const float PARTICLE_LIFE_LENGTH = 5.0; const float PARTICLE_LIFE_LENGTH = 5.0;
const float HUGE = 9E16; const float HUGE = 9E16;
const float INTERVAL = 0.03125;
const float PI = 3.14159265; const float PI = 3.14159265;
const float TAU = 6.283185307; const float TAU = 6.283185307;
#define fs(i) (fract(sin((i)*114.514)*1919.810))
#define saturate(i) clamp(i,0.,1.) #define saturate(i) clamp(i,0.,1.)
#define lofi(i,m) (floor((i)/(m))*(m)) #define lofi(i,m) (floor((i)/(m))*(m))
#define lofir(i,m) (floor((i)/(m)+.5)*(m))
layout (location = 0) out vec4 fragCompute0; layout (location = 0) out vec4 fragCompute0;
layout (location = 1) out vec4 fragCompute1; layout (location = 1) out vec4 fragCompute1;
@@ -17,40 +18,18 @@ layout (location = 1) out vec4 fragCompute1;
uniform bool init; uniform bool init;
uniform bool shouldUpdate; uniform bool shouldUpdate;
uniform float time; uniform float time;
uniform float beat;
uniform float trails; uniform float trails;
uniform float trailLength; uniform float trailLength;
uniform float totalFrame;
uniform float deltaTime; uniform float deltaTime;
uniform vec2 resolution; uniform vec2 resolution;
uniform sampler2D samplerCompute0; uniform sampler2D samplerCompute0;
uniform sampler2D samplerCompute1; uniform sampler2D samplerCompute1;
uniform sampler2D samplerRandom; uniform sampler2D samplerRandom;
uniform float noiseScale;
uniform float noisePhase;
// uniform float velScale;
// uniform float genRate;
// ------
vec2 uvInvT( vec2 _uv ) {
return vec2( 0.0, 1.0 ) + vec2( 1.0, -1.0 ) * _uv;
}
// ------
mat2 rotate2D( float _t ) {
return mat2( cos( _t ), sin( _t ), -sin( _t ), cos( _t ) );
}
float fractSin( float i ) { float fractSin( float i ) {
return fract( sin( i ) * 1846.42 ); return fract( sin( i ) * 1846.42 );
} }
vec4 sampleRandom( vec2 _uv ) {
return texture( samplerRandom, _uv );
}
#pragma glslify: prng = require( ./-prng ); #pragma glslify: prng = require( ./-prng );
#pragma glslify: cyclicNoise = require( ./modules/cyclicNoise ); #pragma glslify: cyclicNoise = require( ./modules/cyclicNoise );
@@ -67,40 +46,6 @@ vec3 randomSphere( inout vec4 seed ) {
return v; return v;
} }
vec2 randomCircle( inout vec4 seed ) {
vec2 v;
for ( int i = 0; i < 10; i ++ ) {
v = vec2(
prng( seed ),
prng( seed )
) * 2.0 - 1.0;
if ( length( v ) < 1.0 ) { break; }
}
return v;
}
vec3 randomBox( inout vec4 seed ) {
vec3 v;
v = vec3(
prng( seed ),
prng( seed ),
prng( seed )
) * 2.0 - 1.0;
return v;
}
float uneune( float i, float p ) {
return sin( TAU * (
fractSin( i ) + floor( 1.0 + 4.0 * fractSin( i + 54.12 ) ) * p
) );
}
vec3 uneune3( float i, float p ) {
return vec3( uneune( i, p ), uneune( i + 11.87, p ), uneune( i + 21.92, p ) );
}
// ------
void main() { void main() {
vec2 uv = gl_FragCoord.xy / resolution; vec2 uv = gl_FragCoord.xy / resolution;
@@ -115,8 +60,14 @@ void main() {
vec4 tex0 = texture( samplerCompute0, uv ); vec4 tex0 = texture( samplerCompute0, uv );
vec4 tex1 = texture( samplerCompute1, uv ); vec4 tex1 = texture( samplerCompute1, uv );
tex0.z += 4.0 * deltaTime; // camera
if ( shouldUpdate ) { if ( shouldUpdate ) {
tex0.w = saturate( tex0.w - 1.0 / trailLength ); // decrease the life tex0.w = tex0.w + 1.0 / trailLength; // update the life
}
// quick patch!
if ( init ) {
tex0.w = 1E9;
} }
fragCompute0 = tex0; fragCompute0 = tex0;
@@ -140,46 +91,55 @@ void main() {
float timing = mix( 0.0, PARTICLE_LIFE_LENGTH, floor( uv.y * trails ) / trails ); float timing = mix( 0.0, PARTICLE_LIFE_LENGTH, floor( uv.y * trails ) / trails );
timing += lofi( time, PARTICLE_LIFE_LENGTH ); timing += lofi( time, PARTICLE_LIFE_LENGTH );
if ( time - deltaTime + PARTICLE_LIFE_LENGTH < timing ) { if ( time - dt + PARTICLE_LIFE_LENGTH < timing ) {
timing -= PARTICLE_LIFE_LENGTH; timing -= PARTICLE_LIFE_LENGTH;
} }
// == initialize particles ======================================================================= if ( shouldUpdate ) {
// == initialize particles =====================================================================
if ( if (
time - deltaTime < timing && timing <= time time - dt < timing && timing <= time
) { ) {
dt = time - timing; dt = time - timing;
pos = 1.0 * randomSphere( seed ); pos = lofi( 5.0 * randomSphere( seed ), INTERVAL );
pos.z -= 4.0;
vel = 1.0 * randomSphere( seed ); vel = 1.0 * randomSphere( seed );
life = 1.0; life = 0.0;
jumpFlag = 1.0; jumpFlag = 1.0;
} else { } else {
jumpFlag = 0.0; // remove jumping flag jumpFlag = 0.0; // remove jumping flag
} }
// == update particles =========================================================================== // == update particles =========================================================================
// noise field // noise field
vel += 40.0 * cyclicNoise( pos ) * dt; vel += 4.0 * cyclicNoise( pos ) * dt;
// resistance // resistance
vel *= exp( -10.0 * dt ); // vel *= exp( -10.0 * dt );
// vel.z += 10.0 * dt; // vel.z += 10.0 * dt;
vec3 v = vel; vec3 v = vel;
// float vmax = max( abs( v.x ), max( abs( v.y ), abs( v.z ) ) ); float vmax = max( abs( v.x ), max( abs( v.y ), abs( v.z ) ) );
// v *= ( v = INTERVAL * sign( v ) * (
// abs( v.x ) == vmax ? vec3( 1.0, 0.0, 0.0 ) : abs( v.x ) == vmax ? vec3( 1.0, 0.0, 0.0 ) :
// abs( v.y ) == vmax ? vec3( 0.0, 1.0, 0.0 ) : abs( v.y ) == vmax ? vec3( 0.0, 1.0, 0.0 ) :
// vec3( 0.0, 0.0, 1.0 ) vec3( 0.0, 0.0, 1.0 )
// ); ) / dt;
// pos.xyz += velScale * v * dt;
pos += v * dt; pos += v * dt;
life -= dt / PARTICLE_LIFE_LENGTH; life += dt / PARTICLE_LIFE_LENGTH;
}
pos.z += 4.0 * deltaTime; // camera
// quick patch!
if ( init ) {
life = 1E9;
}
fragCompute0 = vec4( pos, life ); fragCompute0 = vec4( pos, life );
fragCompute1 = vec4( vel, jumpFlag ); fragCompute1 = vec4( vel, jumpFlag );

View 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
}

View 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
}

View File

@@ -6,6 +6,7 @@ const int MTL_NONE = 0;
const int MTL_UNLIT = 1; const int MTL_UNLIT = 1;
const int MTL_PBR = 2; const int MTL_PBR = 2;
const int MTL_REFRACT = 3; const int MTL_REFRACT = 3;
const int MTL_PSY = 4;
const float ENV_UV_MARGIN = 0.9375; const float ENV_UV_MARGIN = 0.9375;
const float AO_BIAS = 0.0; const float AO_BIAS = 0.0;
const float AO_RADIUS = 0.5; const float AO_RADIUS = 0.5;
@@ -276,6 +277,27 @@ void main() {
color += isect.color * texEnvRefractive; color += isect.color * texEnvRefractive;
} else if ( isect.materialId == MTL_PSY ) {
color = 0.02 * smoothstep( 0.9, 1.0, texture( samplerAo, isect.screenUv ).xyz );
// vec2 f = ( 1.0 - 2.0 * prng( seed ) ) / resolution;
vec2 f = 1.0 / resolution;
vec4 tex0x = texture( sampler0, vUv + f );
vec4 tex1x = texture( sampler1, vUv + f );
vec4 tex3x = texture( sampler3, vUv + f );
float valid = MTL_PSY == int( tex3x.w ) ? 1.0 : 0.0;
float edge = saturate(
step( 0.1, abs( length( cameraPos - tex0x.xyz ) - lenV ) ) +
step( 0.1, length( tex1x.xyz - tex1.xyz ) )
) * valid;
vec3 gradient = 0.5 + 0.5 * cos(
3.0 + 1.5 * exp( -0.4 * max( lenV - 3.0, 0.0 ) ) + vec3( 0.0, 2.0, 4.0 )
);
color += 0.4 * gradient * edge;
} }
color *= exp( -0.4 * max( lenV - 3.0, 0.0 ) ); color *= exp( -0.4 * max( lenV - 3.0, 0.0 ) );

96
src/shaders/ssr.frag Normal file
View 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 );
}

View 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 );
}
}

View 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 );
}

View File

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

View File

@@ -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;
}

View File

@@ -16,7 +16,7 @@ const terserOptions = {
booleans_as_integers: true, booleans_as_integers: true,
drop_console: true, drop_console: true,
keep_fargs: false, keep_fargs: false,
passes: 1, passes: 2,
unsafe_arrows: true, unsafe_arrows: true,
unsafe_math: true, unsafe_math: true,
}, },