future: cubemap

This commit is contained in:
FMS-Cat
2021-03-19 00:12:51 +09:00
parent 562ec9ee4b
commit 1bb083f4cd
32 changed files with 626 additions and 379 deletions

View File

@@ -1,7 +1,8 @@
export const
RTINSPECTOR_MULTIPLE = false,
RTINSPECTOR_CAPTURE_NAME: string | null = null,
// RTINSPECTOR_CAPTURE_NAME: string | null = 'CameraEntity/cameraTarget',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'light1/shadowMap',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'EnvironmentMap/swap0',
RTINSPECTOR_CAPTURE_INDEX = 0,
COMPONENT_UPDATE_BREAKPOINT: string | null = null,
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'Bloom/quadDup3',

View File

@@ -1,6 +1,7 @@
export const
RANDOM_RESOLUTION = [ 64, 64 ],
STATIC_RANDOM_RESOLUTION = [ 2048, 2048 ],
CUBEMAP_RESOLUTION = [ 512, 512 ],
AO_RESOLUTION_RATIO = 1.0,
RESOLUTION = [ 1280, 720 ],
MUSIC_BPM = 180,

View File

@@ -58,6 +58,7 @@ export class CameraEntity {
near: 0.1,
far: 20.0,
name: 'CameraEntity/camera',
materialTag: 'deferred',
} );
this.__entity.components.push( this.__camera );

View File

@@ -2,16 +2,17 @@ import { Quaternion, Vector3 } from '@fms-cat/experimental';
import { Mesh } from '../heck/components/Mesh';
import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry';
import { Material } from '../heck/Material';
import { Material, MaterialMap } from '../heck/Material';
import cubeVert from '../shaders/cube.vert';
import cubeFrag from '../shaders/cube.frag';
import depthFrag from '../shaders/depth.frag';
import { genCube } from '../geometries/genCube';
import { Lambda } from '../heck/components/Lambda';
export class Cube {
public mesh: Mesh;
public geometry: Geometry;
public material: Material;
public materials: MaterialMap<'deferred' | 'shadow'>;
public entity: Entity;
public constructor() {
@@ -29,11 +30,11 @@ export class Cube {
this.entity.transform.scale = this.entity.transform.scale.scale( 0.8 );
this.geometry = this.__createGeometry();
this.material = this.__createMaterial();
this.materials = this.__createMaterials();
this.mesh = new Mesh( {
geometry: this.geometry,
material: this.material,
materials: this.materials,
name: process.env.DEV && 'Cube/mesh',
} );
this.entity.components.push( this.mesh );
@@ -42,6 +43,10 @@ export class Cube {
onUpdate: ( { time } ) => {
this.entity.transform.rotation = rot0.multiply(
Quaternion.fromAxisAngle( new Vector3( [ 0.0, 1.0, 0.0 ] ), time )
).multiply(
Quaternion.fromAxisAngle( new Vector3( [ 1.0, 0.0, 0.0 ] ), 1.0 )
).multiply(
Quaternion.fromAxisAngle( new Vector3( [ 0.0, 0.0, 1.0 ] ), 1.0 )
);
},
visible: false,
@@ -64,10 +69,14 @@ export class Cube {
return geometry;
}
private __createMaterial(): Material {
const material = new Material( cubeVert, cubeFrag );
private __createMaterials(): MaterialMap<'deferred' | 'shadow'> {
const deferred = new Material(
cubeVert,
cubeFrag,
{ defines: { 'DEFERRED': 'true' } },
);
material.addUniform( 'inflate', '1f', 0.01 );
const shadow = new Material( cubeVert, depthFrag );
if ( process.env.DEV ) {
if ( module.hot ) {
@@ -77,12 +86,13 @@ export class Cube {
'../shaders/cube.frag',
],
() => {
material.replaceShader( cubeVert, cubeFrag );
deferred.replaceShader( cubeVert, cubeFrag );
shadow.replaceShader( cubeVert, depthFrag );
},
);
}
}
return material;
return { deferred, shadow };
}
}

View File

@@ -0,0 +1,39 @@
import { Entity } from '../heck/Entity';
import { LightEntity } from './LightEntity';
import { PerspectiveCamera } from '../heck/components/PerspectiveCamera';
import { CubemapRenderTarget } from '../heck/CubemapRenderTarget';
import { CubemapCamera } from '../heck/components/CubemapCamera';
import { CUBEMAP_RESOLUTION } from '../config';
export interface CubemapCameraEntityOptions {
root: Entity;
lights: LightEntity[];
}
export class CubemapCameraEntity {
public root: Entity;
public camera: PerspectiveCamera;
public readonly target: CubemapRenderTarget;
public entity: Entity;
public constructor( options: CubemapCameraEntityOptions ) {
this.root = options.root;
this.entity = new Entity();
this.target = new CubemapRenderTarget( {
width: CUBEMAP_RESOLUTION[ 0 ],
height: CUBEMAP_RESOLUTION[ 1 ],
} );
this.camera = new CubemapCamera( {
scene: this.root,
renderTarget: this.target,
near: 0.1,
far: 20.0,
name: 'CubemapCameraEntity/camera',
materialTag: 'forward',
} );
this.entity.components.push( this.camera );
}
}

View File

@@ -7,6 +7,7 @@ import quadVert from '../shaders/quad.vert';
import { BufferRenderTarget } from '../heck/BufferRenderTarget';
import { Swap, Xorshift } from '@fms-cat/experimental';
import { Lambda } from '../heck/components/Lambda';
import { CubemapRenderTarget } from '../heck/CubemapRenderTarget';
const WIDTH = 1024;
const HEIGHT = 512;
@@ -20,7 +21,9 @@ export class EnvironmentMap {
return this.swap.o.texture;
}
public constructor() {
public constructor( { cubemap }: {
cubemap: CubemapRenderTarget;
} ) {
this.entity = new Entity();
this.entity.visible = false;
@@ -47,6 +50,7 @@ export class EnvironmentMap {
);
material.addUniform( 'uniformSeed', '4f', rng.gen(), rng.gen(), rng.gen(), rng.gen() );
material.addUniformTexture( 'sampler0', this.swap.i.texture );
material.addUniformCubemap( 'samplerCubemap', cubemap.texture );
if ( process.env.DEV ) {
if ( module.hot ) {

View File

@@ -2,7 +2,7 @@ import { Entity } from '../heck/Entity';
import { GPUParticles } from './GPUParticles';
import { Geometry } from '../heck/Geometry';
import { InstancedGeometry } from '../heck/InstancedGeometry';
import { Material } from '../heck/Material';
import { Material, MaterialMap } from '../heck/Material';
import quadVert from '../shaders/quad.vert';
import flickyParticleComputeFrag from '../shaders/flicky-particles-compute.frag';
import flickyParticleRenderFrag from '../shaders/flicky-particles-render.frag';
@@ -16,24 +16,16 @@ const PARTICLES = PARTICLES_SQRT * PARTICLES_SQRT;
export class FlickyParticles {
public get entity(): Entity {
return this.__gpuParticles.entity;
return this.gpuParticles.entity;
}
private __gpuParticles: GPUParticles;
public get materialCompute(): Material {
return this.__gpuParticles.materialCompute;
}
public get materialRender(): Material {
return this.__gpuParticles.materialRender;
}
public gpuParticles: GPUParticles;
public constructor() {
this.__gpuParticles = new GPUParticles( {
this.gpuParticles = new GPUParticles( {
materialCompute: this.__createMaterialCompute(),
geometryRender: this.__createGeometryRender(),
materialRender: this.__createMaterialRender(),
materialsRender: this.__createMaterialsRender(),
computeWidth: PARTICLES_SQRT,
computeHeight: PARTICLES_SQRT,
computeNumBuffers: 1,
@@ -99,36 +91,44 @@ export class FlickyParticles {
return geometry;
}
private __createMaterialRender(): Material {
const material = new Material(
private __createMaterialsRender(): MaterialMap {
const forward = new Material(
flickyParticleRenderVert,
flickyParticleRenderFrag,
{ defines: { 'FORWARD': 'true' } },
);
material.addUniform( 'colorVar', '1f', 0.1 );
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
forward.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
const deferred = new Material(
flickyParticleRenderVert,
flickyParticleRenderFrag,
{ defines: { 'DEFERRED': 'true' } },
);
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
const shadow = new Material(
flickyParticleRenderVert,
flickyParticleRenderFrag,
{ defines: { 'SHADOW': 'true' } },
);
shadow.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
if ( process.env.DEV ) {
if ( module.hot ) {
module.hot.accept( '../shaders/flicky-particles-render.vert', () => {
material.replaceShader(
flickyParticleRenderVert,
flickyParticleRenderFrag,
);
} );
module.hot.accept(
[
'../shaders/flicky-particles-render.vert',
'../shaders/flicky-particles-render.frag',
],
() => {
forward.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
deferred.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
shadow.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
}
);
}
}
if ( process.env.DEV ) {
if ( module.hot ) {
module.hot.accept( '../shaders/flicky-particles-render.frag', () => {
material.replaceShader(
flickyParticleRenderVert,
flickyParticleRenderFrag,
);
} );
}
}
return material;
return { forward, deferred, shadow };
}
}

View File

@@ -2,7 +2,7 @@ import { BufferRenderTarget, BufferRenderTargetOptions } from '../heck/BufferRen
import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry';
import { Lambda } from '../heck/components/Lambda';
import { Material } from '../heck/Material';
import { Material, MaterialMap, MaterialTag } from '../heck/Material';
import { Mesh } from '../heck/components/Mesh';
import { Quad } from '../heck/components/Quad';
import { Swap } from '@fms-cat/experimental';
@@ -11,7 +11,7 @@ import { gl } from '../globals/canvas';
export interface GPUParticlesOptions {
materialCompute: Material;
geometryRender: Geometry;
materialRender: Material;
materialsRender: Partial<MaterialMap<MaterialTag>>;
computeWidth: number;
computeHeight: number;
computeNumBuffers: number;
@@ -39,8 +39,8 @@ export class GPUParticles {
return this.__quadCompute.material;
}
public get materialRender(): Material {
return this.__meshRender.material;
public get materialsRender(): Partial<MaterialMap<MaterialTag>> {
return this.__meshRender.materials;
}
public constructor( options: GPUParticlesOptions ) {
@@ -75,10 +75,13 @@ export class GPUParticles {
`samplerCompute${ i }`,
this.__swapCompute.i.getTexture( attachment )
);
this.materialRender.addUniformTexture(
`samplerCompute${ i }`,
this.__swapCompute.o.getTexture( attachment )
);
for ( const material of Object.values( this.materialsRender ) ) {
material?.addUniformTexture(
`samplerCompute${ i }`,
this.__swapCompute.o.getTexture( attachment )
);
}
}
this.__quadCompute.target = this.__swapCompute.o;
@@ -98,15 +101,19 @@ export class GPUParticles {
// -- render -----------------------------------------------------------------------------------
this.__meshRender = new Mesh( {
geometry: options.geometryRender,
material: options.materialRender,
materials: options.materialsRender,
name: process.env.DEV && `${ options.namePrefix }/meshRender`,
} );
options.materialRender.addUniform(
'resolutionCompute',
'2f',
options.computeWidth,
options.computeHeight
);
for ( const material of Object.values( options.materialsRender ) ) {
material?.addUniform(
'resolutionCompute',
'2f',
options.computeWidth,
options.computeHeight
);
}
this.__entity.components.push( this.__meshRender );
}
}

View File

@@ -1,11 +1,9 @@
import { BufferRenderTarget } from '../heck/BufferRenderTarget';
import { Entity } from '../heck/Entity';
import { Lambda } from '../heck/components/Lambda';
import { Material } from '../heck/Material';
import { PerspectiveCamera } from '../heck/components/PerspectiveCamera';
import { Quad } from '../heck/components/Quad';
import { Swap } from '@fms-cat/experimental';
import posToDepthFrag from '../shaders/pos-to-depth.frag';
import quadVert from '../shaders/quad.vert';
import shadowBlurFrag from '../shaders/shadow-blur.frag';
@@ -52,8 +50,8 @@ export class LightEntity {
this.__entity = new Entity();
const swapOptions = {
width: options.shadowMapWidth || 1024,
height: options.shadowMapHeight || 1024
width: options.shadowMapWidth ?? 1024,
height: options.shadowMapHeight ?? 1024
};
const swap = new Swap(
@@ -68,9 +66,9 @@ export class LightEntity {
);
// -- camera -----------------------------------------------------------------------------------
const fov = options.shadowMapFov || 45.0;
const near = options.shadowMapNear || 0.1;
const far = options.shadowMapFar || 100.0;
const fov = options.shadowMapFov ?? 45.0;
const near = options.shadowMapNear ?? 0.1;
const far = options.shadowMapFar ?? 100.0;
this.__shadowMapCamera = new PerspectiveCamera( {
fov,
@@ -79,44 +77,20 @@ export class LightEntity {
renderTarget: swap.o,
scene: this.__root,
name: process.env.DEV && `${ options.namePrefix }/shadowMapCamera`,
materialTag: 'shadow',
} );
this.__shadowMapCamera.clear = [ 1.0, 1.0, 1.0, 1.0 ];
this.__entity.components.push( this.__shadowMapCamera );
this.__shadowMap = new BufferRenderTarget( {
width: options.shadowMapWidth || 2048,
height: options.shadowMapHeight || 2048,
width: options.shadowMapWidth ?? 1024,
height: options.shadowMapHeight ?? 1024,
name: process.env.DEV && `${ options.namePrefix }/shadowMap`,
} );
swap.swap();
// -- convert ----------------------------------------------------------------------------------
const materialConvert = new Material(
quadVert,
posToDepthFrag
);
materialConvert.addUniformTexture( 'sampler0', swap.i.texture );
this.__entity.components.push( new Lambda( {
onUpdate: () => {
materialConvert.addUniform( 'cameraPos', '3f', ...this.entity.transform.position.elements );
materialConvert.addUniform( 'cameraNearFar', '2f', this.camera.near, this.camera.far );
},
visible: false,
name: process.env.DEV && `${ options.namePrefix }/setCameraUniforms`,
} ) );
this.__entity.components.push( new Quad( {
target: swap.o,
material: materialConvert,
name: process.env.DEV && `${ options.namePrefix }/quadConvertPosToDepth`,
} ) );
swap.swap();
// -- blur ---------------------------------------------------------------------------------------
// -- blur -------------------------------------------------------------------------------------
for ( let i = 0; i < 2; i ++ ) {
const material = new Material(
quadVert,

View File

@@ -1,70 +1,63 @@
import { GLCatTexture } from '@fms-cat/glcat-ts';
import { Mesh, MeshCull } from '../heck/components/Mesh';
import { TRIANGLE_STRIP_QUAD, Vector3 } from '@fms-cat/experimental';
import { gl, glCat } from '../globals/canvas';
import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry';
import { Material } from '../heck/Material';
import { Material, MaterialMap } from '../heck/Material';
import quadVert from '../shaders/quad.vert';
import raymarcherFrag from '../shaders/raymarcher.frag';
import { Lambda } from '../heck/components/Lambda';
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
export class Raymarcher {
private __mesh: Mesh;
private __geometry: Geometry;
private __material: Material;
public get material(): Material {
return this.__material;
}
private __entity: Entity;
public get entity(): Entity {
return this.__entity;
}
public materials: MaterialMap<'deferred' | 'shadow'>;
public mesh: Mesh;
public geometry: Geometry;
public readonly entity: Entity;
public constructor() {
this.__entity = new Entity();
this.__entity.transform.position = new Vector3( [ 0.0, 0.0, 0.3 ] );
this.__entity.transform.scale = new Vector3( [ 16.0, 9.0, 1.0 ] ).scale( 0.15 );
this.entity = new Entity();
this.entity.transform.position = new Vector3( [ 0.0, 0.0, 0.3 ] );
this.entity.transform.scale = new Vector3( [ 16.0, 9.0, 1.0 ] ).scale( 0.15 );
this.__geometry = this.__createGeoemtry();
this.__material = this.__createMaterial();
this.geometry = this.__createGeoemtry();
this.materials = this.__createMaterials();
this.__material.addUniform( 'range', '4f', -1.0, -1.0, 1.0, 1.0 );
for ( const material of Object.values( this.materials ) ) {
material.addUniform( 'range', '4f', -1.0, -1.0, 1.0, 1.0 );
this.__material.addUniformTexture( 'samplerRandom', randomTexture.texture );
this.__material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
}
this.__entity.components.push( new Lambda( {
this.entity.components.push( new Lambda( {
onDraw: ( event ) => {
this.__material.addUniform(
'cameraNearFar',
'2f',
event.camera.near,
event.camera.far
);
for ( const material of Object.values( this.materials ) ) {
material.addUniform(
'cameraNearFar',
'2f',
event.camera.near,
event.camera.far
);
this.__material.addUniformVector(
'inversePV',
'Matrix4fv',
event.projectionMatrix.multiply( event.viewMatrix ).inverse!.elements
);
material.addUniformVector(
'inversePV',
'Matrix4fv',
event.projectionMatrix.multiply( event.viewMatrix ).inverse!.elements
);
}
},
active: false,
name: process.env.DEV && 'Raymarcher/setCameraUniforms',
} ) );
this.__mesh = new Mesh( {
geometry: this.__geometry,
material: this.__material,
this.mesh = new Mesh( {
geometry: this.geometry,
materials: this.materials,
name: process.env.DEV && 'Raymarcher/mesh',
} );
this.__mesh.cull = MeshCull.None;
this.__entity.components.push( this.__mesh );
this.mesh.cull = MeshCull.None;
this.entity.components.push( this.mesh );
}
protected __createGeoemtry(): Geometry {
@@ -84,17 +77,19 @@ export class Raymarcher {
return geometry;
}
protected __createMaterial(): Material {
const material = new Material( quadVert, raymarcherFrag );
protected __createMaterials(): MaterialMap<'deferred' | 'shadow'> {
const deferred = new Material( quadVert, raymarcherFrag, { defines: { 'DEFERRED': 'true' } } );
const shadow = new Material( quadVert, raymarcherFrag, { defines: { 'SHADOW': 'true' } } );
if ( process.env.DEV ) {
if ( module.hot ) {
module.hot.accept( '../shaders/raymarcher.frag', () => {
material.replaceShader( quadVert, raymarcherFrag );
deferred.replaceShader( quadVert, raymarcherFrag );
shadow.replaceShader( quadVert, raymarcherFrag );
} );
}
}
return material;
return { deferred, shadow };
}
}

View File

@@ -4,39 +4,56 @@ import { Mesh } from '../heck/components/Mesh';
import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry';
import { InstancedGeometry } from '../heck/InstancedGeometry';
import { Material } from '../heck/Material';
import { Material, MaterialMap } from '../heck/Material';
import depthFrag from '../shaders/depth.frag';
import ringsVert from '../shaders/rings.vert';
import ringsFrag from '../shaders/rings.frag';
import { gl, glCat } from '../globals/canvas';
import { Lambda } from '../heck/components/Lambda';
const PRIMCOUNT = 32;
export class Rings {
public mesh: Mesh;
public geometry: Geometry;
public material: Material;
public materials: MaterialMap;
public entity: Entity;
public constructor() {
this.entity = new Entity();
this.entity.transform.rotation = Quaternion.fromAxisAngle(
const rot0 = Quaternion.fromAxisAngle(
new Vector3( [ 1.0, 0.0, 0.0 ] ),
0.4,
).multiply( Quaternion.fromAxisAngle(
new Vector3( [ 0.0, 0.0, 1.0 ] ),
0.4,
) );
this.entity.transform.rotation = rot0;
this.geometry = this.__createGeometry();
this.material = this.__createMaterial();
this.materials = this.__createMaterials();
this.mesh = new Mesh( {
geometry: this.geometry,
material: this.material,
materials: this.materials,
name: process.env.DEV && 'Rings/mesh',
} );
this.entity.components.push( this.mesh );
this.entity.components.push( new Lambda( {
onUpdate: ( { time } ) => {
this.entity.transform.rotation = rot0.multiply(
Quaternion.fromAxisAngle( new Vector3( [ 0.0, 1.0, 0.0 ] ), time )
).multiply(
Quaternion.fromAxisAngle( new Vector3( [ 1.0, 0.0, 0.0 ] ), 1.0 )
).multiply(
Quaternion.fromAxisAngle( new Vector3( [ 0.0, 0.0, 1.0 ] ), 1.0 )
);
},
visible: false,
name: process.env.DEV && 'Cube/speen',
} ) );
}
private __createGeometry(): Geometry {
@@ -66,10 +83,20 @@ export class Rings {
return geometry;
}
private __createMaterial(): Material {
const material = new Material( ringsVert, ringsFrag );
private __createMaterials(): MaterialMap {
const forward = new Material(
ringsVert,
ringsFrag,
{ defines: { 'FORWARD': 'true' } },
);
material.addUniform( 'inflate', '1f', 0.01 );
const deferred = new Material(
ringsVert,
ringsFrag,
{ defines: { 'DEFERRED': 'true' } },
);
const shadow = new Material( ringsVert, depthFrag );
if ( process.env.DEV ) {
if ( module.hot ) {
@@ -79,12 +106,14 @@ export class Rings {
'../shaders/rings.frag',
],
() => {
material.replaceShader( ringsVert, ringsFrag );
forward.replaceShader( ringsVert, ringsFrag );
deferred.replaceShader( ringsVert, ringsFrag );
shadow.replaceShader( ringsVert, depthFrag );
},
);
}
}
return material;
return { forward, deferred, shadow };
}
}

View File

@@ -2,8 +2,10 @@ import { Entity } from '../heck/Entity';
import { GPUParticles } from './GPUParticles';
import { Geometry } from '../heck/Geometry';
import { InstancedGeometry } from '../heck/InstancedGeometry';
import { Material } from '../heck/Material';
import { Material, MaterialMap } from '../heck/Material';
import { genOctahedron } from '../geometries/genOctahedron';
import depthFrag from '../shaders/depth.frag';
import discardFrag from '../shaders/discard.frag';
import quadVert from '../shaders/quad.vert';
import sphereParticleComputeFrag from '../shaders/sphere-particles-compute.frag';
import sphereParticleRenderFrag from '../shaders/sphere-particles-render.frag';
@@ -16,24 +18,16 @@ const PARTICLES = PARTICLES_SQRT * PARTICLES_SQRT;
export class SphereParticles {
public get entity(): Entity {
return this.__gpuParticles.entity;
return this.gpuParticles.entity;
}
private __gpuParticles: GPUParticles;
public get materialCompute(): Material {
return this.__gpuParticles.materialCompute;
}
public get materialRender(): Material {
return this.__gpuParticles.materialRender;
}
public gpuParticles: GPUParticles;
public constructor() {
this.__gpuParticles = new GPUParticles( {
this.gpuParticles = new GPUParticles( {
materialCompute: this.__createMaterialCompute(),
geometryRender: this.__createGeometryRender(),
materialRender: this.__createMaterialRender(),
materialsRender: this.__createMaterialsRender(),
computeWidth: PARTICLES_SQRT,
computeHeight: PARTICLES_SQRT,
computeNumBuffers: 2,
@@ -59,7 +53,7 @@ export class SphereParticles {
}
private __createGeometryRender(): Geometry {
const octahedron = genOctahedron( { radius: 1.0, div: 1 } );
const octahedron = genOctahedron( { radius: 1.0, div: 3 } );
const geometry = new InstancedGeometry();
@@ -96,42 +90,32 @@ export class SphereParticles {
return geometry;
}
private __createMaterialRender(): Material {
const material = new Material(
private __createMaterialsRender(): MaterialMap<'deferred' | 'shadow'> {
const deferred = new Material(
sphereParticleRenderVert,
sphereParticleRenderFrag,
{
defines: {
'USE_CLIP': 'true',
'USE_VERTEX_COLOR': 'true'
},
},
{ defines: { 'DEFERRED': 'true' } },
);
material.addUniform( 'colorVar', '1f', 0.1 );
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
const shadow = new Material( sphereParticleRenderVert, depthFrag );
shadow.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
if ( process.env.DEV ) {
if ( module.hot ) {
module.hot.accept( '../shaders/sphere-particles-render.vert', () => {
material.replaceShader(
sphereParticleRenderVert,
sphereParticleRenderFrag,
);
} );
module.hot.accept(
[
'../shaders/sphere-particles-render.vert',
'../shaders/sphere-particles-render.frag',
],
() => {
deferred.replaceShader( sphereParticleRenderVert, sphereParticleRenderFrag );
shadow.replaceShader( sphereParticleRenderVert, depthFrag );
}
);
}
}
if ( process.env.DEV ) {
if ( module.hot ) {
module.hot.accept( '../shaders/sphere-particles-render.frag', () => {
material.replaceShader(
sphereParticleRenderVert,
sphereParticleRenderFrag,
);
} );
}
}
return material;
return { deferred, shadow };
}
}

View File

@@ -2,8 +2,9 @@ import { Entity } from '../heck/Entity';
import { GPUParticles } from './GPUParticles';
import { Geometry } from '../heck/Geometry';
import { InstancedGeometry } from '../heck/InstancedGeometry';
import { Material } from '../heck/Material';
import { Material, MaterialMap } from '../heck/Material';
import quadVert from '../shaders/quad.vert';
import depthFrag from '../shaders/depth.frag';
import trailsComputeFrag from '../shaders/trails-compute.frag';
import trailsRenderFrag from '../shaders/trails-render.frag';
import trailsRenderVert from '../shaders/trails-render.vert';
@@ -15,24 +16,16 @@ const TRAIL_LENGTH = 64;
export class Trails {
public get entity(): Entity {
return this.__gpuParticles.entity;
return this.gpuParticles.entity;
}
private __gpuParticles: GPUParticles;
public get materialCompute(): Material {
return this.__gpuParticles.materialCompute;
}
public get materialRender(): Material {
return this.__gpuParticles.materialRender;
}
public gpuParticles: GPUParticles;
public constructor() {
this.__gpuParticles = new GPUParticles( {
this.gpuParticles = new GPUParticles( {
materialCompute: this.__createMaterialCompute(),
geometryRender: this.__createGeometryRender(),
materialRender: this.__createMaterialRender(),
materialsRender: this.__createMaterialsRender(),
computeWidth: TRAIL_LENGTH,
computeHeight: TRAILS,
computeNumBuffers: 2,
@@ -140,33 +133,32 @@ export class Trails {
return geometry;
}
private __createMaterialRender(): Material {
const material = new Material(
private __createMaterialsRender(): MaterialMap<'deferred' | 'shadow'> {
const deferred = new Material(
trailsRenderVert,
trailsRenderFrag,
{ defines: { 'DEFERRED': 'true' } },
);
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
const shadow = new Material( trailsRenderVert, depthFrag );
shadow.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
if ( process.env.DEV ) {
if ( module.hot ) {
module.hot.accept( '../shaders/trails-render.vert', () => {
material.replaceShader(
trailsRenderVert,
trailsRenderFrag,
);
} );
}
if ( module.hot ) {
module.hot.accept( '../shaders/trails-render.frag', () => {
material.replaceShader(
trailsRenderVert,
trailsRenderFrag,
);
} );
module.hot.accept(
[
'../shaders/trails-render.vert',
'../shaders/trails-render.frag',
],
() => {
deferred.replaceShader( trailsRenderVert, trailsRenderFrag );
shadow.replaceShader( trailsRenderVert, depthFrag );
}
);
}
}
return material;
return { deferred, shadow };
}
}

View File

@@ -13,29 +13,10 @@ export interface BufferRenderTargetOptions {
export class BufferRenderTarget extends RenderTarget {
public static nameMap = new Map<string, BufferRenderTarget>();
private readonly __framebuffer: GLCatFramebuffer;
public get framebuffer(): GLCatFramebuffer {
return this.__framebuffer;
}
private __width: number;
public get width(): number {
return this.__width;
}
private __height: number;
public get height(): number {
return this.__height;
}
private __numBuffers: number;
public get numBuffers(): number {
return this.__numBuffers;
}
public readonly framebuffer: GLCatFramebuffer;
public readonly width: number;
public readonly height: number;
public readonly numBuffers: number;
private __name?: string;
public get name(): string | undefined {
@@ -67,18 +48,18 @@ export class BufferRenderTarget extends RenderTarget {
public constructor( options: BufferRenderTargetOptions ) {
super();
this.__framebuffer = glCat.lazyDrawbuffers(
this.framebuffer = glCat.lazyDrawbuffers(
options.width,
options.height,
options.numBuffers || 1,
options.numBuffers ?? 1,
{
isFloat: options.isFloat || true
isFloat: options.isFloat ?? true
}
);
this.__width = options.width;
this.__height = options.height;
this.__numBuffers = options.numBuffers || 1;
this.width = options.width;
this.height = options.height;
this.numBuffers = options.numBuffers ?? 1;
if ( process.env.DEV ) {
this.name = options?.name;
@@ -86,20 +67,20 @@ export class BufferRenderTarget extends RenderTarget {
}
public get texture(): GLCatTexture {
return this.__framebuffer.texture!;
return this.framebuffer.texture!;
}
public getTexture( attachment: number ): GLCatTexture | null {
return this.__framebuffer.getTexture( attachment );
return this.framebuffer.getTexture( attachment );
}
public bind(): void {
gl.bindFramebuffer( gl.FRAMEBUFFER, this.__framebuffer.raw );
glCat.drawBuffers( this.__numBuffers );
gl.bindFramebuffer( gl.FRAMEBUFFER, this.framebuffer.raw );
glCat.drawBuffers( this.numBuffers );
gl.viewport( 0, 0, this.width, this.height );
}
public dispose(): void {
this.__framebuffer.dispose();
this.framebuffer.dispose();
}
}

View File

@@ -0,0 +1,43 @@
import { GLCatFramebuffer, GLCatTextureCubemap } from '@fms-cat/glcat-ts';
import { gl, glCat } from '../globals/canvas';
import { RenderTarget } from './RenderTarget';
export interface CubemapRenderTargetOptions {
width: number;
height: number;
isFloat?: boolean;
}
export class CubemapRenderTarget extends RenderTarget {
public readonly framebuffer: GLCatFramebuffer;
public readonly texture: GLCatTextureCubemap;
public readonly width: number;
public readonly height: number;
public constructor( options: CubemapRenderTargetOptions ) {
super();
const { framebuffer, texture } = glCat.lazyCubemapFramebuffer(
options.width,
options.height,
{
isFloat: options.isFloat ?? true
},
);
this.framebuffer = framebuffer;
this.texture = texture;
this.width = options.width;
this.height = options.height;
}
public bind(): void {
gl.bindFramebuffer( gl.FRAMEBUFFER, this.framebuffer.raw );
glCat.drawBuffers( 1 );
gl.viewport( 0, 0, this.width, this.height );
}
public dispose(): void {
this.framebuffer.dispose();
}
}

View File

@@ -3,6 +3,7 @@ import { Component } from './components/Component';
import { Matrix4 } from '@fms-cat/experimental';
import { RenderTarget } from './RenderTarget';
import { Transform } from './Transform';
import { MaterialTag } from './Material';
export interface EntityUpdateEvent {
frameCount: number;
@@ -20,6 +21,8 @@ export interface EntityDrawEvent {
viewMatrix: Matrix4;
projectionMatrix: Matrix4;
camera: Camera;
cameraTransform: Transform;
materialTag: MaterialTag;
}
export class Entity {
@@ -69,9 +72,11 @@ export class Entity {
renderTarget: event.renderTarget,
globalTransform,
camera: event.camera,
cameraTransform: event.cameraTransform,
viewMatrix: event.viewMatrix,
projectionMatrix: event.projectionMatrix,
entity: this
entity: this,
materialTag: event.materialTag,
} );
} );
@@ -83,7 +88,9 @@ export class Entity {
globalTransform,
viewMatrix: event.viewMatrix,
projectionMatrix: event.projectionMatrix,
camera: event.camera
camera: event.camera,
cameraTransform: event.cameraTransform,
materialTag: event.materialTag,
} );
} );
}

View File

@@ -1,7 +1,14 @@
import { GLCatProgram, GLCatProgramLinkOptions, GLCatProgramUniformType, GLCatTexture } from '@fms-cat/glcat-ts';
import { GLCatProgram, GLCatProgramLinkOptions, GLCatProgramUniformType, GLCatTexture, GLCatTextureCubemap } from '@fms-cat/glcat-ts';
import { gl } from '../globals/canvas';
import { SHADERPOOL } from './ShaderPool';
export type MaterialTag =
| 'deferred'
| 'forward'
| 'shadow';
export type MaterialMap<T extends MaterialTag = MaterialTag> = { [ tag in T ]: Material };
export class Material {
protected __linkOptions: GLCatProgramLinkOptions;
@@ -29,6 +36,12 @@ export class Material {
};
} = {};
protected __uniformCubemaps: {
[ name: string ]: {
texture: GLCatTextureCubemap | null;
};
} = {};
private __vert: string;
public get vert(): string {
@@ -89,6 +102,10 @@ export class Material {
this.__uniformTextures[ name ] = { texture };
}
public addUniformCubemap( name: string, texture: GLCatTextureCubemap | null ): void {
this.__uniformCubemaps[ name ] = { texture };
}
public setUniforms(): void {
const program = this.program;
@@ -103,6 +120,10 @@ export class Material {
Object.entries( this.__uniformTextures ).forEach( ( [ name, { texture } ] ) => {
program.uniformTexture( name, texture );
} );
Object.entries( this.__uniformCubemaps ).forEach( ( [ name, { texture } ] ) => {
program.uniformCubemap( name, texture );
} );
}
public setBlendMode(): void {

View File

@@ -4,20 +4,18 @@ import { Matrix4 } from '@fms-cat/experimental';
import { RenderTarget } from '../RenderTarget';
import { Transform } from '../Transform';
import { glCat } from '../../globals/canvas';
import { MaterialTag } from '../Material';
export interface CameraOptions extends ComponentOptions {
renderTarget?: RenderTarget;
projectionMatrix: Matrix4;
materialTag: MaterialTag;
scene?: Entity;
clear?: Array<number | undefined> | false;
}
export abstract class Camera extends Component {
protected __projectionMatrix: Matrix4;
public get projectionMatrix(): Matrix4 {
return this.__projectionMatrix;
}
public projectionMatrix: Matrix4;
public renderTarget?: RenderTarget;
@@ -25,6 +23,8 @@ export abstract class Camera extends Component {
public clear: Array<number | undefined> | false = [];
public materialTag: MaterialTag;
public abstract get near(): number;
public abstract get far(): number;
@@ -36,7 +36,8 @@ export abstract class Camera extends Component {
this.renderTarget = options.renderTarget;
this.scene = options.scene;
this.__projectionMatrix = options.projectionMatrix;
this.projectionMatrix = options.projectionMatrix;
this.materialTag = options.materialTag;
if ( options.clear !== undefined ) { this.clear = options.clear; }
}
@@ -63,10 +64,12 @@ export abstract class Camera extends Component {
frameCount: event.frameCount,
time: event.time,
renderTarget: renderTarget,
cameraTransform: event.globalTransform,
globalTransform: new Transform(),
viewMatrix,
projectionMatrix: this.__projectionMatrix,
camera: this
projectionMatrix: this.projectionMatrix,
camera: this,
materialTag: this.materialTag,
} );
if ( process.env.DEV ) {

View File

@@ -6,6 +6,7 @@ import { Transform } from '../Transform';
import { COMPONENT_DRAW_BREAKPOINT, COMPONENT_UPDATE_BREAKPOINT } from '../../config-hot';
import { GPUTimer } from '../GPUTimer';
import { getDivComponentsDraw, getDivComponentsUpdate } from '../../globals/dom';
import { MaterialTag } from '../Material';
export interface ComponentUpdateEvent {
frameCount: number;
@@ -19,6 +20,8 @@ export interface ComponentDrawEvent {
frameCount: number;
time: number;
camera: Camera;
cameraTransform: Transform;
materialTag: MaterialTag;
renderTarget: RenderTarget;
globalTransform: Transform;
viewMatrix: Matrix4;

View File

@@ -0,0 +1,81 @@
import { Camera } from './Camera';
import { Entity } from '../Entity';
import { Matrix4, Quaternion, Vector3 } from '@fms-cat/experimental';
import { ComponentOptions, ComponentUpdateEvent } from './Component';
import { CubemapRenderTarget } from '../CubemapRenderTarget';
import { gl } from '../../globals/canvas';
import { Transform } from '../Transform';
import { MaterialTag } from '../Material';
const INV_SQRT2 = 1.0 / Math.sqrt( 2.0 );
const CUBEMAP_ROTATIONS = [ // 🔥
new Quaternion( [ 0.0, INV_SQRT2, 0.0, INV_SQRT2 ] ), // PX
new Quaternion( [ 0.0, -INV_SQRT2, 0.0, INV_SQRT2 ] ), // NX
new Quaternion( [ 0.0, INV_SQRT2, INV_SQRT2, 0.0 ] ), // PY
new Quaternion( [ 0.0, INV_SQRT2, -INV_SQRT2, 0.0 ] ), // NY
new Quaternion( [ 0.0, 1.0, 0.0, 0.0 ] ), // PZ
new Quaternion( [ 0.0, 0.0, 0.0, 1.0 ] ), // NZ
];
export interface CubemapCameraOptions extends ComponentOptions {
materialTag: MaterialTag;
renderTarget?: CubemapRenderTarget;
near?: number;
far?: number;
scene?: Entity;
clear?: Array<number | undefined> | false;
}
export class CubemapCamera extends Camera {
public renderTarget?: CubemapRenderTarget;
public readonly near: number;
public readonly far: number;
public constructor( options: CubemapCameraOptions ) {
const projectionMatrix = Matrix4.perspective(
90.0,
options.near ?? 0.1,
options.far ?? 20.0,
);
super( {
...options,
projectionMatrix,
renderTarget: options.renderTarget,
scene: options.scene,
clear: options.clear,
materialTag: options.materialTag,
} );
this.near = options.near ?? 0.1;
this.far = options.far ?? 20.0;
}
protected __updateImpl( event: ComponentUpdateEvent ): void {
const { renderTarget } = this;
if ( !renderTarget ) {
throw new Error( process.env.DEV && 'You must assign a renderTarget to the Camera' );
}
for ( let i = 0; i < 6; i ++ ) {
renderTarget.framebuffer.attachTexture(
renderTarget.texture,
{ textarget: gl.TEXTURE_CUBE_MAP_POSITIVE_X + i },
);
const globalTransform = new Transform();
globalTransform.matrix = Matrix4.compose(
event.globalTransform.position,
CUBEMAP_ROTATIONS[ i ],
new Vector3( [ 1.0, 1.0, 1.0 ] ),
);
super.__updateImpl( {
...event,
globalTransform,
} );
}
}
}

View File

@@ -1,6 +1,6 @@
import { Component, ComponentDrawEvent, ComponentOptions } from './Component';
import { Geometry } from '../Geometry';
import { Material } from '../Material';
import { MaterialMap, MaterialTag } from '../Material';
import { glCat } from '../../globals/canvas';
export enum MeshCull {
@@ -18,12 +18,12 @@ const meshCullMap = {
export interface MeshOptions extends ComponentOptions {
geometry: Geometry;
material: Material;
materials: Partial<MaterialMap<MaterialTag>>;
}
export class Mesh extends Component {
public geometry: Geometry;
public material: Material;
public materials: Partial<MaterialMap<MaterialTag>>;
public cull: MeshCull = MeshCull.Back;
@@ -33,16 +33,21 @@ export class Mesh extends Component {
this.active = false;
this.geometry = options.geometry;
this.material = options.material;
this.materials = options.materials;
}
protected __drawImpl( event: ComponentDrawEvent ): void {
const gl = glCat.renderingContext;
const program = this.material.program;
const material = this.materials[ event.materialTag ];
if ( material == null ) {
return;
}
const program = material.program;
glCat.useProgram( program );
this.material.setBlendMode();
material.setBlendMode();
if ( this.cull === MeshCull.None ) {
gl.disable( gl.CULL_FACE );
@@ -51,13 +56,15 @@ export class Mesh extends Component {
gl.cullFace( meshCullMap[ this.cull ] );
}
this.geometry.assignBuffers( this.material );
this.geometry.assignBuffers( material );
this.material.setUniforms();
material.setUniforms();
program.uniform1f( 'time', event.time );
program.uniform1f( 'frameCount', event.frameCount );
program.uniform2f( 'resolution', event.renderTarget.width, event.renderTarget.height );
program.uniform3f( 'cameraPos', ...event.cameraTransform.position.elements );
program.uniform2f( 'cameraNearFar', event.camera.near, event.camera.far );
program.uniformMatrix4fv( 'normalMatrix', event.globalTransform.matrix.inverse!.transpose.elements );
program.uniformMatrix4fv( 'modelMatrix', event.globalTransform.matrix.elements );

View File

@@ -3,8 +3,10 @@ import { Entity } from '../Entity';
import { Matrix4 } from '@fms-cat/experimental';
import { RenderTarget } from '../RenderTarget';
import { ComponentOptions } from './Component';
import { MaterialTag } from '../Material';
export interface PerspectiveCameraOptions extends ComponentOptions {
materialTag: MaterialTag;
renderTarget?: RenderTarget;
near?: number;
far?: number;
@@ -14,17 +16,8 @@ export interface PerspectiveCameraOptions extends ComponentOptions {
}
export class PerspectiveCamera extends Camera {
private __near: number;
public get near(): number {
return this.__near;
}
private __far: number;
public get far(): number {
return this.__far;
}
public readonly near: number;
public readonly far: number;
public constructor( options: PerspectiveCameraOptions ) {
const projectionMatrix = Matrix4.perspective(
@@ -38,10 +31,10 @@ export class PerspectiveCamera extends Camera {
projectionMatrix,
renderTarget: options.renderTarget,
scene: options.scene,
clear: options.clear
clear: options.clear,
} );
this.__near = options.near || 0.01;
this.__far = options.far || 100.0;
this.near = options.near || 0.01;
this.far = options.far || 100.0;
}
}

View File

@@ -2,6 +2,7 @@ import { Swap, Vector3 } from '@fms-cat/experimental';
import { Bloom } from './entities/Bloom';
import { CameraEntity } from './entities/CameraEntity';
import { Cube } from './entities/Cube';
import { CubemapCameraEntity } from './entities/CubemapCameraEntity';
import { EnvironmentMap } from './entities/EnvironmentMap';
import { FlickyParticles } from './entities/FlickyParticles';
import { Glitch } from './entities/Glitch';
@@ -69,23 +70,20 @@ class EntityReplacer<T extends { entity: Entity }> {
const ibllut = new IBLLUT();
dog.root.children.push( ibllut.entity );
const environmentMap = new EnvironmentMap();
dog.root.children.push( environmentMap.entity );
// -- "objects" ------------------------------------------------------------------------------------
const replacerSphereParticles = new EntityReplacer( () => new SphereParticles() );
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/SphereParticles', () => {
replacerSphereParticles.replace();
} );
}
// const replacerSphereParticles = new EntityReplacer( () => new SphereParticles() );
// if ( process.env.DEV && module.hot ) {
// module.hot.accept( './entities/SphereParticles', () => {
// replacerSphereParticles.replace();
// } );
// }
const replacerTrails = new EntityReplacer( () => new Trails() );
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/Trails', () => {
replacerTrails.replace();
} );
}
// const replacerTrails = new EntityReplacer( () => new Trails() );
// if ( process.env.DEV && module.hot ) {
// module.hot.accept( './entities/Trails', () => {
// replacerTrails.replace();
// } );
// }
const replacerRings = new EntityReplacer( () => new Rings() );
if ( process.env.DEV && module.hot ) {
@@ -94,12 +92,12 @@ if ( process.env.DEV && module.hot ) {
} );
}
const replacerCube = new EntityReplacer( () => new Cube() );
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/Cube', () => {
replacerCube.replace();
} );
}
// const replacerCube = new EntityReplacer( () => new Cube() );
// if ( process.env.DEV && module.hot ) {
// module.hot.accept( './entities/Cube', () => {
// replacerCube.replace();
// } );
// }
const replacerFlickyParticles = new EntityReplacer( () => new FlickyParticles() );
if ( process.env.DEV && module.hot ) {
@@ -139,7 +137,7 @@ const light = new LightEntity( {
shadowMapFar: 20.0,
namePrefix: process.env.DEV && 'light1',
} );
light.color = [ 40.0, 40.0, 40.0 ];
light.color = [ 0.1, 0.1, 0.1 ];
light.entity.transform.lookAt( new Vector3( [ -1.0, 2.0, 8.0 ] ) );
dog.root.children.push( light.entity );
@@ -154,6 +152,20 @@ dog.root.children.push( light.entity );
// light2.entity.transform.lookAt( new Vector3( [ -4.0, -2.0, 6.0 ] ) );
// dog.root.children.push( light2.entity );
const cubemapCamera = new CubemapCameraEntity( {
root: dog.root,
lights: [
light,
// light2
],
} );
dog.root.children.push( cubemapCamera.entity );
const environmentMap = new EnvironmentMap( {
cubemap: cubemapCamera.target,
} );
dog.root.children.push( environmentMap.entity );
const camera = new CameraEntity( {
root: dog.root,
target: swap.o,

View File

@@ -9,10 +9,12 @@ in vec3 vNormal;
in vec4 vPosition;
in vec4 vPositionWithoutModel;
layout (location = 0) out vec4 fragPosition;
layout (location = 1) out vec4 fragNormal;
layout (location = 2) out vec4 fragColor;
layout (location = 3) out vec4 fragWTF;
#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
#pragma glslify: noise = require( ./-simplex4d );
@@ -29,8 +31,10 @@ float fbm( vec4 p ) {
void main() {
float rough = sin( 14.0 * fbm( vPositionWithoutModel ) );
fragPosition = vPosition;
fragNormal = vec4( normalize( vNormal ), 1.0 );
fragColor = vec4( vec3( 0.5 ), 1.0 );
fragWTF = vec4( vec3( 0.2 + 0.03 * rough, 0.17, 0.0 ), MTL_PBR );
#ifdef DEFERRED
fragPosition = vPosition;
fragNormal = vec4( normalize( vNormal ), 1.0 );
fragColor = vec4( vec3( 0.02, 0.04, 0.9 ), 1.0 );
fragWTF = vec4( vec3( 0.02 + 0.03 * rough, 0.87, 0.0 ), MTL_PBR );
#endif
}

View File

@@ -5,20 +5,18 @@ precision highp float;
#define saturate(x) clamp(x,0.,1.)
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
in vec2 vUv;
in vec4 vPosition;
out vec4 fragColor;
uniform vec2 cameraNearFar;
uniform vec3 cameraPos;
uniform sampler2D sampler0;
void main() {
vec4 tex = texture( sampler0, vUv );
float depth = linearstep(
cameraNearFar.x,
cameraNearFar.y,
length( cameraPos - tex.xyz )
length( cameraPos - vPosition.xyz )
);
fragColor = vec4( depth, depth * depth, depth, 1.0 );
}

View File

@@ -22,6 +22,7 @@ uniform float head;
uniform vec2 resolution;
uniform vec4 uniformSeed;
uniform sampler2D sampler0;
uniform samplerCube samplerCubemap;
vec4 seed;
@@ -66,14 +67,7 @@ vec3 ImportanceSampleGGX( vec2 Xi, float roughness, vec3 N ) {
}
vec3 haha( vec3 L ) {
bool circ = dot( L, normalize( vec3( 1.0, 3.0, 3.0 ) ) ) > 0.9;
vec3 c = circ ? 0.01 * vec3( 0.1, 0.1, 1.0 ) : vec3( 0.0 );
bool ring = abs( dot( L, vec3( -0.3, 1.0, 0.3 ) ) ) < 0.1;
c += ring ? 10.0 * vec3( 0.1, 1.0, 0.3 ) : vec3( 0.0 );
return c;
// return 0.5 + 0.5 * L;
return texture( samplerCubemap, L ).xyz;
}
void main() {
@@ -92,11 +86,11 @@ void main() {
float a = TAU * uv.x;
float b = PI * ( uv.y - 0.5 );
vec3 N = vec3( sin( a ) * cos( b ), -sin( b ), -cos( a ) * cos( b ) );
vec3 N = vec3( -sin( a ) * cos( b ), sin( b ), -cos( a ) * cos( b ) );
vec3 R = N;
vec3 V = R;
seed = uniformSeed + N.xyzx;
seed = uniformSeed + 500.0 * N.xyzx;
vec4 col = vec4( 0.0 );
for ( int i = 0; i < SAMPLES; i ++ ) {
@@ -113,7 +107,7 @@ void main() {
col.xyz = col.w <= 0.001 ? vec3( 0.0 ) : ( col.xyz / col.w );
tex.xyz = mix( tex.xyz, col.xyz, 1.0 / 16.0 );
tex.xyz = mix( tex.xyz, col.xyz, 1.0 / 4.0 );
fragColor = vec4( tex, 1.0 );
}

View File

@@ -29,14 +29,27 @@ in vec3 vNormal;
in vec4 vPosition;
in vec4 vDice;
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;
uniform sampler2D samplerRandomStatic;
#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
#ifdef SHADOW
out vec4 fragColor;
uniform vec2 cameraNearFar;
uniform vec3 cameraPos;
#endif
// == utils ========================================================================================
mat2 rotate2D( float t ) {
return mat2( cos( t ), sin( t ), -sin( t ), cos( t ) );
@@ -163,8 +176,23 @@ void main() {
}
fragPosition = vPosition;
fragNormal = vec4( vNormal, 1.0 );
fragColor = vec4( color, 1.0 );
fragWTF = vec4( vec3( 0.0 ), MTL_UNLIT );
#ifdef FORWARD
fragColor = vec4( 1.0 );
#endif
#ifdef DEFERRED
fragPosition = vPosition;
fragNormal = vec4( vNormal, 1.0 );
fragColor = vec4( color, 1.0 );
fragWTF = vec4( vec3( 0.0 ), MTL_UNLIT );
#endif
#ifdef SHADOW
float depth = linearstep(
cameraNearFar.x,
cameraNearFar.y,
length( cameraPos - vPosition.xyz )
);
fragColor = vec4( depth, depth * depth, depth, 1.0 );
#endif
}

View File

@@ -82,9 +82,8 @@ vec2 filterSaw( vec2 time, float freq, float cutoff, float resonance ) {
float kick( float t ) {
if ( t < 0.0 ) { return 0.0; }
float phase = 50.0 * t - 12.0 * exp( -200.0 * t ) - 7.4 * exp( -40.0 * t );
float fm = 0.7 * exp( -40.0 * t ) * sin( 2.0 * TAU * phase );
return exp( -4.0 * t ) * sin( TAU * phase + fm );
float phase = 50.0 * t - 15.0 * exp( -200.0 * t ) - 9.4 * exp( -30.0 * t );
return exp( -4.0 * t ) * sin( TAU * phase );
}
vec2 longsnare( float t ) {
@@ -145,7 +144,7 @@ vec2 crash( float t ) {
if ( t < 0.0 ) { return vec2( 0.0 ); }
t = t + 0.01 * sin( 0.5 * exp( -40.0 * t ) + 3.0 );
t = lofi( t, 0.00004 );
t = lofi( 0.8 * t, 0.00004 );
float fmamp = -3.4 * exp( -1.0 * t );
vec2 fm = fmamp * sin( vec2( 38855.0, 38865.0 ) * t );
float amp = exp( -3.0 * t );
@@ -234,7 +233,7 @@ vec2 mainAudio( vec4 time ) {
: time.x;
float sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick );
{
dest += 0.2 * kick( tKick );
dest += 0.25 * kick( tKick );
}
// -- snare --------------------------------------------------------------------------------------
@@ -262,7 +261,7 @@ vec2 mainAudio( vec4 time ) {
}
if (
inRange( time.w, SECTION_PSY + 32.0 * BEAT, 1E9 )
inRange( time.w, SECTION_PSY + 31.5 * BEAT, 1E9 )
) {
float t = mod( time.x - 0.5 * BEAT, BEAT );
dest += 0.1 * mix( 0.3, 1.0, sidechain ) * hihat( t, 20.0 );
@@ -299,7 +298,7 @@ vec2 mainAudio( vec4 time ) {
// -- amen ---------------------------------------------------------------------------------------
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_AAAA, SECTION_PSY )
) {
float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) );
@@ -336,6 +335,7 @@ vec2 mainAudio( vec4 time ) {
// -- superbass ----------------------------------------------------------------------------------
if ( inRange( time.w, SECTION_PORTER_FUCKING_ROBINSON, SECTION_AAAA ) ) {
float t = mod( time.z, 8.0 * BEAT );
t += 1.0 * inRangeInteg( time.z, 28.0 * BEAT, 31.5 * BEAT, 50.0 );
float freq = n2f( float( chordsB[ progB ] ) ) * 0.125;
float fadetime = max( 0.0, time.w - SECTION_AAAA + 8.0 * BEAT );
dest += 0.1 * exp( -1.0 * fadetime ) * mix( 0.1, 1.0, sidechain ) * superbass( t, freq, exp( -2.0 * fadetime ) );
@@ -401,7 +401,7 @@ vec2 mainAudio( vec4 time ) {
sum += 0.3 * mix( 0.2, 1.0, sidechain ) * choir( t * rate * 0.5 );
}
dest += 0.1 * aSaturate( sum );
dest += 0.12 * aSaturate( sum );
}
// -- harp ---------------------------------------------------------------------------------------
@@ -469,7 +469,7 @@ vec2 mainAudio( vec4 time ) {
dest += 0.2 * kick( t ) * exp( -decay * t );
dest += 0.1 * inRangeFloat( time.w, SECTION_PSY - 32.0 * BEAT, 1E9 ) * clap( t );
dest += 0.1 * ph * inRangeFloat( time.w, SECTION_PSY - 16.0 * BEAT, 1E9 ) * snare909( t );
dest += 0.05 * ph * inRangeFloat( time.w, SECTION_PSY - 16.0 * BEAT, 1E9 ) * snare909( t );
}
// -- fill, before psy ---------------------------------------------------------------------------

View File

@@ -13,14 +13,21 @@ const int MTL_IRIDESCENT = 4;
in vec2 vUv;
layout (location = 0) out vec4 fragPosition;
layout (location = 1) out vec4 fragNormal;
layout (location = 2) out vec4 fragColor;
layout (location = 3) out vec4 fragWTF;
#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
#ifdef SHADOW
out vec4 fragColor;
#endif
uniform float time;
uniform vec2 resolution;
uniform vec2 cameraNearFar;
uniform vec3 cameraPos;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 inversePV;
@@ -76,8 +83,19 @@ void main() {
float depth = projPos.z / projPos.w;
gl_FragDepth = 0.5 + 0.5 * depth;
fragPosition = vec4( rayPos, depth );
fragNormal = vec4( normal, 1.0 );
fragColor = color;
fragWTF = vec4( vec3( 0.8, 0.8, 0.0 ), MTL_PBR );
#ifdef DEFERRED
fragPosition = vec4( rayPos, depth );
fragNormal = vec4( normal, 1.0 );
fragColor = color;
fragWTF = vec4( vec3( 0.2, 0.2, 0.0 ), MTL_PBR );
#endif
#ifdef SHADOW
float shadowDepth = linearstep(
cameraNearFar.x,
cameraNearFar.y,
length( cameraPos - rayPos )
);
fragColor = vec4( shadowDepth, shadowDepth * shadowDepth, shadowDepth, 1.0 );
#endif
}

View File

@@ -8,16 +8,28 @@ in float vLife;
in vec4 vPosition;
in vec3 vNormal;
layout (location = 0) out vec4 fragPosition;
layout (location = 1) out vec4 fragNormal;
layout (location = 2) out vec4 fragColor;
layout (location = 3) out vec4 fragWTF;
#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 float time;
void main() {
fragPosition = vPosition;
fragNormal = vec4( normalize( vNormal ), 1.0 );
fragColor = vec4( 0.2, 0.9, 0.5, 1.0 );
fragWTF = vec4( vec3( 0.2, 0.2, 4.0 ), MTL_PBR );
#ifdef FORWARD
fragColor = vec4( 28.0 * vec3( 0.2, 0.9, 0.5 ), 1.0 );
#endif
#ifdef DEFERRED
fragPosition = vPosition;
fragNormal = vec4( normalize( vNormal ), 1.0 );
fragColor = vec4( 0.2, 0.9, 0.5, 1.0 );
fragWTF = vec4( vec3( 0.2, 0.2, 4.0 ), MTL_PBR );
#endif
}

View File

@@ -19,10 +19,12 @@ in vec3 vNormal;
in vec4 vColor;
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;
#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 float time;
@@ -35,8 +37,10 @@ mat2 rotate2D( float _t ) {
void main() {
if ( vColor.a < 0.0 ) { discard; }
fragPosition = vPosition;
fragNormal = vec4( vNormal, 1.0 );
fragColor = vec4( vColor.xyz, 1.0 );
fragWTF = vec4( vec3( 0.4, 0.4, 0.0 ), MTL_PBR );
#ifdef DEFERRED
fragPosition = vPosition;
fragNormal = vec4( vNormal, 1.0 );
fragColor = vec4( vColor.xyz, 1.0 );
fragWTF = vec4( vec3( 0.1, 0.2, 0.0 ), MTL_PBR );
#endif
}

View File

@@ -19,6 +19,7 @@ export class RandomTexture {
this.__rng = new Xorshift();
this.__array = new Uint8Array( width * height * 4 );
this.__texture = glCat.createTexture()!;
this.__texture.textureFilter( gl.LINEAR );
this.__texture.textureWrap( gl.REPEAT );
}