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 export const
RTINSPECTOR_MULTIPLE = false, RTINSPECTOR_MULTIPLE = false,
RTINSPECTOR_CAPTURE_NAME: string | null = null, 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, RTINSPECTOR_CAPTURE_INDEX = 0,
COMPONENT_UPDATE_BREAKPOINT: string | null = null, COMPONENT_UPDATE_BREAKPOINT: string | null = null,
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'Bloom/quadDup3', // COMPONENT_UPDATE_BREAKPOINT: string | null = 'Bloom/quadDup3',

View File

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

View File

@@ -58,6 +58,7 @@ export class CameraEntity {
near: 0.1, near: 0.1,
far: 20.0, far: 20.0,
name: 'CameraEntity/camera', name: 'CameraEntity/camera',
materialTag: 'deferred',
} ); } );
this.__entity.components.push( this.__camera ); 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 { Mesh } from '../heck/components/Mesh';
import { Entity } from '../heck/Entity'; import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry'; import { Geometry } from '../heck/Geometry';
import { Material } from '../heck/Material'; import { Material, MaterialMap } from '../heck/Material';
import cubeVert from '../shaders/cube.vert'; import cubeVert from '../shaders/cube.vert';
import cubeFrag from '../shaders/cube.frag'; import cubeFrag from '../shaders/cube.frag';
import depthFrag from '../shaders/depth.frag';
import { genCube } from '../geometries/genCube'; import { genCube } from '../geometries/genCube';
import { Lambda } from '../heck/components/Lambda'; import { Lambda } from '../heck/components/Lambda';
export class Cube { export class Cube {
public mesh: Mesh; public mesh: Mesh;
public geometry: Geometry; public geometry: Geometry;
public material: Material; public materials: MaterialMap<'deferred' | 'shadow'>;
public entity: Entity; public entity: Entity;
public constructor() { public constructor() {
@@ -29,11 +30,11 @@ export class Cube {
this.entity.transform.scale = this.entity.transform.scale.scale( 0.8 ); this.entity.transform.scale = this.entity.transform.scale.scale( 0.8 );
this.geometry = this.__createGeometry(); this.geometry = this.__createGeometry();
this.material = this.__createMaterial(); this.materials = this.__createMaterials();
this.mesh = new Mesh( { this.mesh = new Mesh( {
geometry: this.geometry, geometry: this.geometry,
material: this.material, materials: this.materials,
name: process.env.DEV && 'Cube/mesh', name: process.env.DEV && 'Cube/mesh',
} ); } );
this.entity.components.push( this.mesh ); this.entity.components.push( this.mesh );
@@ -42,6 +43,10 @@ export class Cube {
onUpdate: ( { time } ) => { onUpdate: ( { time } ) => {
this.entity.transform.rotation = rot0.multiply( this.entity.transform.rotation = rot0.multiply(
Quaternion.fromAxisAngle( new Vector3( [ 0.0, 1.0, 0.0 ] ), time ) 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, visible: false,
@@ -64,10 +69,14 @@ export class Cube {
return geometry; return geometry;
} }
private __createMaterial(): Material { private __createMaterials(): MaterialMap<'deferred' | 'shadow'> {
const material = new Material( cubeVert, cubeFrag ); 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 ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {
@@ -77,12 +86,13 @@ export class Cube {
'../shaders/cube.frag', '../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 { BufferRenderTarget } from '../heck/BufferRenderTarget';
import { Swap, Xorshift } from '@fms-cat/experimental'; import { Swap, Xorshift } from '@fms-cat/experimental';
import { Lambda } from '../heck/components/Lambda'; import { Lambda } from '../heck/components/Lambda';
import { CubemapRenderTarget } from '../heck/CubemapRenderTarget';
const WIDTH = 1024; const WIDTH = 1024;
const HEIGHT = 512; const HEIGHT = 512;
@@ -20,7 +21,9 @@ export class EnvironmentMap {
return this.swap.o.texture; return this.swap.o.texture;
} }
public constructor() { public constructor( { cubemap }: {
cubemap: CubemapRenderTarget;
} ) {
this.entity = new Entity(); this.entity = new Entity();
this.entity.visible = false; this.entity.visible = false;
@@ -47,6 +50,7 @@ export class EnvironmentMap {
); );
material.addUniform( 'uniformSeed', '4f', rng.gen(), rng.gen(), rng.gen(), rng.gen() ); material.addUniform( 'uniformSeed', '4f', rng.gen(), rng.gen(), rng.gen(), rng.gen() );
material.addUniformTexture( 'sampler0', this.swap.i.texture ); material.addUniformTexture( 'sampler0', this.swap.i.texture );
material.addUniformCubemap( 'samplerCubemap', cubemap.texture );
if ( process.env.DEV ) { if ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {

View File

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

View File

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

View File

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

View File

@@ -1,70 +1,63 @@
import { GLCatTexture } from '@fms-cat/glcat-ts';
import { Mesh, MeshCull } from '../heck/components/Mesh'; import { Mesh, MeshCull } from '../heck/components/Mesh';
import { TRIANGLE_STRIP_QUAD, Vector3 } from '@fms-cat/experimental'; import { TRIANGLE_STRIP_QUAD, Vector3 } from '@fms-cat/experimental';
import { gl, glCat } from '../globals/canvas'; import { gl, glCat } from '../globals/canvas';
import { Entity } from '../heck/Entity'; import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry'; import { Geometry } from '../heck/Geometry';
import { Material } from '../heck/Material'; import { Material, MaterialMap } from '../heck/Material';
import quadVert from '../shaders/quad.vert'; import quadVert from '../shaders/quad.vert';
import raymarcherFrag from '../shaders/raymarcher.frag'; import raymarcherFrag from '../shaders/raymarcher.frag';
import { Lambda } from '../heck/components/Lambda'; import { Lambda } from '../heck/components/Lambda';
import { randomTexture, randomTextureStatic } from '../globals/randomTexture'; import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
export class Raymarcher { export class Raymarcher {
private __mesh: Mesh; public materials: MaterialMap<'deferred' | 'shadow'>;
private __geometry: Geometry; public mesh: Mesh;
public geometry: Geometry;
private __material: Material; public readonly entity: Entity;
public get material(): Material {
return this.__material;
}
private __entity: Entity;
public get entity(): Entity {
return this.__entity;
}
public constructor() { public constructor() {
this.__entity = new Entity(); this.entity = new Entity();
this.__entity.transform.position = new Vector3( [ 0.0, 0.0, 0.3 ] ); 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.transform.scale = new Vector3( [ 16.0, 9.0, 1.0 ] ).scale( 0.15 );
this.__geometry = this.__createGeoemtry(); this.geometry = this.__createGeoemtry();
this.__material = this.__createMaterial(); 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 ); material.addUniformTexture( 'samplerRandom', randomTexture.texture );
this.__material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture ); material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
}
this.__entity.components.push( new Lambda( { this.entity.components.push( new Lambda( {
onDraw: ( event ) => { onDraw: ( event ) => {
this.__material.addUniform( for ( const material of Object.values( this.materials ) ) {
material.addUniform(
'cameraNearFar', 'cameraNearFar',
'2f', '2f',
event.camera.near, event.camera.near,
event.camera.far event.camera.far
); );
this.__material.addUniformVector( material.addUniformVector(
'inversePV', 'inversePV',
'Matrix4fv', 'Matrix4fv',
event.projectionMatrix.multiply( event.viewMatrix ).inverse!.elements event.projectionMatrix.multiply( event.viewMatrix ).inverse!.elements
); );
}
}, },
active: false, active: false,
name: process.env.DEV && 'Raymarcher/setCameraUniforms', name: process.env.DEV && 'Raymarcher/setCameraUniforms',
} ) ); } ) );
this.__mesh = new Mesh( { this.mesh = new Mesh( {
geometry: this.__geometry, geometry: this.geometry,
material: this.__material, materials: this.materials,
name: process.env.DEV && 'Raymarcher/mesh', name: process.env.DEV && 'Raymarcher/mesh',
} ); } );
this.__mesh.cull = MeshCull.None; this.mesh.cull = MeshCull.None;
this.__entity.components.push( this.__mesh ); this.entity.components.push( this.mesh );
} }
protected __createGeoemtry(): Geometry { protected __createGeoemtry(): Geometry {
@@ -84,17 +77,19 @@ export class Raymarcher {
return geometry; return geometry;
} }
protected __createMaterial(): Material { protected __createMaterials(): MaterialMap<'deferred' | 'shadow'> {
const material = new Material( quadVert, raymarcherFrag ); const deferred = new Material( quadVert, raymarcherFrag, { defines: { 'DEFERRED': 'true' } } );
const shadow = new Material( quadVert, raymarcherFrag, { defines: { 'SHADOW': 'true' } } );
if ( process.env.DEV ) { if ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {
module.hot.accept( '../shaders/raymarcher.frag', () => { 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 { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry'; import { Geometry } from '../heck/Geometry';
import { InstancedGeometry } from '../heck/InstancedGeometry'; 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 ringsVert from '../shaders/rings.vert';
import ringsFrag from '../shaders/rings.frag'; import ringsFrag from '../shaders/rings.frag';
import { gl, glCat } from '../globals/canvas'; import { gl, glCat } from '../globals/canvas';
import { Lambda } from '../heck/components/Lambda';
const PRIMCOUNT = 32; const PRIMCOUNT = 32;
export class Rings { export class Rings {
public mesh: Mesh; public mesh: Mesh;
public geometry: Geometry; public geometry: Geometry;
public material: Material; public materials: MaterialMap;
public entity: Entity; public entity: Entity;
public constructor() { public constructor() {
this.entity = new Entity(); this.entity = new Entity();
this.entity.transform.rotation = Quaternion.fromAxisAngle( const rot0 = Quaternion.fromAxisAngle(
new Vector3( [ 1.0, 0.0, 0.0 ] ), new Vector3( [ 1.0, 0.0, 0.0 ] ),
0.4, 0.4,
).multiply( Quaternion.fromAxisAngle( ).multiply( Quaternion.fromAxisAngle(
new Vector3( [ 0.0, 0.0, 1.0 ] ), new Vector3( [ 0.0, 0.0, 1.0 ] ),
0.4, 0.4,
) ); ) );
this.entity.transform.rotation = rot0;
this.geometry = this.__createGeometry(); this.geometry = this.__createGeometry();
this.material = this.__createMaterial(); this.materials = this.__createMaterials();
this.mesh = new Mesh( { this.mesh = new Mesh( {
geometry: this.geometry, geometry: this.geometry,
material: this.material, materials: this.materials,
name: process.env.DEV && 'Rings/mesh', name: process.env.DEV && 'Rings/mesh',
} ); } );
this.entity.components.push( this.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 { private __createGeometry(): Geometry {
@@ -66,10 +83,20 @@ export class Rings {
return geometry; return geometry;
} }
private __createMaterial(): Material { private __createMaterials(): MaterialMap {
const material = new Material( ringsVert, ringsFrag ); 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 ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {
@@ -79,12 +106,14 @@ export class Rings {
'../shaders/rings.frag', '../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 { GPUParticles } from './GPUParticles';
import { Geometry } from '../heck/Geometry'; import { Geometry } from '../heck/Geometry';
import { InstancedGeometry } from '../heck/InstancedGeometry'; import { InstancedGeometry } from '../heck/InstancedGeometry';
import { Material } from '../heck/Material'; import { Material, MaterialMap } from '../heck/Material';
import { genOctahedron } from '../geometries/genOctahedron'; import { genOctahedron } from '../geometries/genOctahedron';
import depthFrag from '../shaders/depth.frag';
import discardFrag from '../shaders/discard.frag';
import quadVert from '../shaders/quad.vert'; import quadVert from '../shaders/quad.vert';
import sphereParticleComputeFrag from '../shaders/sphere-particles-compute.frag'; import sphereParticleComputeFrag from '../shaders/sphere-particles-compute.frag';
import sphereParticleRenderFrag from '../shaders/sphere-particles-render.frag'; import sphereParticleRenderFrag from '../shaders/sphere-particles-render.frag';
@@ -16,24 +18,16 @@ const PARTICLES = PARTICLES_SQRT * PARTICLES_SQRT;
export class SphereParticles { export class SphereParticles {
public get entity(): Entity { public get entity(): Entity {
return this.__gpuParticles.entity; return this.gpuParticles.entity;
} }
private __gpuParticles: GPUParticles; public gpuParticles: GPUParticles;
public get materialCompute(): Material {
return this.__gpuParticles.materialCompute;
}
public get materialRender(): Material {
return this.__gpuParticles.materialRender;
}
public constructor() { public constructor() {
this.__gpuParticles = new GPUParticles( { this.gpuParticles = new GPUParticles( {
materialCompute: this.__createMaterialCompute(), materialCompute: this.__createMaterialCompute(),
geometryRender: this.__createGeometryRender(), geometryRender: this.__createGeometryRender(),
materialRender: this.__createMaterialRender(), materialsRender: this.__createMaterialsRender(),
computeWidth: PARTICLES_SQRT, computeWidth: PARTICLES_SQRT,
computeHeight: PARTICLES_SQRT, computeHeight: PARTICLES_SQRT,
computeNumBuffers: 2, computeNumBuffers: 2,
@@ -59,7 +53,7 @@ export class SphereParticles {
} }
private __createGeometryRender(): Geometry { private __createGeometryRender(): Geometry {
const octahedron = genOctahedron( { radius: 1.0, div: 1 } ); const octahedron = genOctahedron( { radius: 1.0, div: 3 } );
const geometry = new InstancedGeometry(); const geometry = new InstancedGeometry();
@@ -96,42 +90,32 @@ export class SphereParticles {
return geometry; return geometry;
} }
private __createMaterialRender(): Material { private __createMaterialsRender(): MaterialMap<'deferred' | 'shadow'> {
const material = new Material( const deferred = new Material(
sphereParticleRenderVert, sphereParticleRenderVert,
sphereParticleRenderFrag, sphereParticleRenderFrag,
{ { defines: { 'DEFERRED': 'true' } },
defines: {
'USE_CLIP': 'true',
'USE_VERTEX_COLOR': 'true'
},
},
); );
material.addUniform( 'colorVar', '1f', 0.1 ); deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
const shadow = new Material( sphereParticleRenderVert, depthFrag );
shadow.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
if ( process.env.DEV ) { if ( process.env.DEV ) {
if ( module.hot ) { if ( module.hot ) {
module.hot.accept( '../shaders/sphere-particles-render.vert', () => { module.hot.accept(
material.replaceShader( [
sphereParticleRenderVert, '../shaders/sphere-particles-render.vert',
sphereParticleRenderFrag, '../shaders/sphere-particles-render.frag',
],
() => {
deferred.replaceShader( sphereParticleRenderVert, sphereParticleRenderFrag );
shadow.replaceShader( sphereParticleRenderVert, depthFrag );
}
); );
} );
} }
} }
if ( process.env.DEV ) { return { deferred, shadow };
if ( module.hot ) {
module.hot.accept( '../shaders/sphere-particles-render.frag', () => {
material.replaceShader(
sphereParticleRenderVert,
sphereParticleRenderFrag,
);
} );
}
}
return material;
} }
} }

View File

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

View File

@@ -13,29 +13,10 @@ export interface BufferRenderTargetOptions {
export class BufferRenderTarget extends RenderTarget { export class BufferRenderTarget extends RenderTarget {
public static nameMap = new Map<string, BufferRenderTarget>(); public static nameMap = new Map<string, BufferRenderTarget>();
private readonly __framebuffer: GLCatFramebuffer; public readonly framebuffer: GLCatFramebuffer;
public readonly width: number;
public get framebuffer(): GLCatFramebuffer { public readonly height: number;
return this.__framebuffer; public readonly numBuffers: number;
}
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;
}
private __name?: string; private __name?: string;
public get name(): string | undefined { public get name(): string | undefined {
@@ -67,18 +48,18 @@ export class BufferRenderTarget extends RenderTarget {
public constructor( options: BufferRenderTargetOptions ) { public constructor( options: BufferRenderTargetOptions ) {
super(); super();
this.__framebuffer = glCat.lazyDrawbuffers( this.framebuffer = glCat.lazyDrawbuffers(
options.width, options.width,
options.height, options.height,
options.numBuffers || 1, options.numBuffers ?? 1,
{ {
isFloat: options.isFloat || true isFloat: options.isFloat ?? true
} }
); );
this.__width = options.width; this.width = options.width;
this.__height = options.height; this.height = options.height;
this.__numBuffers = options.numBuffers || 1; this.numBuffers = options.numBuffers ?? 1;
if ( process.env.DEV ) { if ( process.env.DEV ) {
this.name = options?.name; this.name = options?.name;
@@ -86,20 +67,20 @@ export class BufferRenderTarget extends RenderTarget {
} }
public get texture(): GLCatTexture { public get texture(): GLCatTexture {
return this.__framebuffer.texture!; return this.framebuffer.texture!;
} }
public getTexture( attachment: number ): GLCatTexture | null { public getTexture( attachment: number ): GLCatTexture | null {
return this.__framebuffer.getTexture( attachment ); return this.framebuffer.getTexture( attachment );
} }
public bind(): void { public bind(): void {
gl.bindFramebuffer( gl.FRAMEBUFFER, this.__framebuffer.raw ); gl.bindFramebuffer( gl.FRAMEBUFFER, this.framebuffer.raw );
glCat.drawBuffers( this.__numBuffers ); glCat.drawBuffers( this.numBuffers );
gl.viewport( 0, 0, this.width, this.height ); gl.viewport( 0, 0, this.width, this.height );
} }
public dispose(): void { 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 { Matrix4 } from '@fms-cat/experimental';
import { RenderTarget } from './RenderTarget'; import { RenderTarget } from './RenderTarget';
import { Transform } from './Transform'; import { Transform } from './Transform';
import { MaterialTag } from './Material';
export interface EntityUpdateEvent { export interface EntityUpdateEvent {
frameCount: number; frameCount: number;
@@ -20,6 +21,8 @@ export interface EntityDrawEvent {
viewMatrix: Matrix4; viewMatrix: Matrix4;
projectionMatrix: Matrix4; projectionMatrix: Matrix4;
camera: Camera; camera: Camera;
cameraTransform: Transform;
materialTag: MaterialTag;
} }
export class Entity { export class Entity {
@@ -69,9 +72,11 @@ export class Entity {
renderTarget: event.renderTarget, renderTarget: event.renderTarget,
globalTransform, globalTransform,
camera: event.camera, camera: event.camera,
cameraTransform: event.cameraTransform,
viewMatrix: event.viewMatrix, viewMatrix: event.viewMatrix,
projectionMatrix: event.projectionMatrix, projectionMatrix: event.projectionMatrix,
entity: this entity: this,
materialTag: event.materialTag,
} ); } );
} ); } );
@@ -83,7 +88,9 @@ export class Entity {
globalTransform, globalTransform,
viewMatrix: event.viewMatrix, viewMatrix: event.viewMatrix,
projectionMatrix: event.projectionMatrix, 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 { gl } from '../globals/canvas';
import { SHADERPOOL } from './ShaderPool'; import { SHADERPOOL } from './ShaderPool';
export type MaterialTag =
| 'deferred'
| 'forward'
| 'shadow';
export type MaterialMap<T extends MaterialTag = MaterialTag> = { [ tag in T ]: Material };
export class Material { export class Material {
protected __linkOptions: GLCatProgramLinkOptions; protected __linkOptions: GLCatProgramLinkOptions;
@@ -29,6 +36,12 @@ export class Material {
}; };
} = {}; } = {};
protected __uniformCubemaps: {
[ name: string ]: {
texture: GLCatTextureCubemap | null;
};
} = {};
private __vert: string; private __vert: string;
public get vert(): string { public get vert(): string {
@@ -89,6 +102,10 @@ export class Material {
this.__uniformTextures[ name ] = { texture }; this.__uniformTextures[ name ] = { texture };
} }
public addUniformCubemap( name: string, texture: GLCatTextureCubemap | null ): void {
this.__uniformCubemaps[ name ] = { texture };
}
public setUniforms(): void { public setUniforms(): void {
const program = this.program; const program = this.program;
@@ -103,6 +120,10 @@ export class Material {
Object.entries( this.__uniformTextures ).forEach( ( [ name, { texture } ] ) => { Object.entries( this.__uniformTextures ).forEach( ( [ name, { texture } ] ) => {
program.uniformTexture( name, texture ); program.uniformTexture( name, texture );
} ); } );
Object.entries( this.__uniformCubemaps ).forEach( ( [ name, { texture } ] ) => {
program.uniformCubemap( name, texture );
} );
} }
public setBlendMode(): void { public setBlendMode(): void {

View File

@@ -4,20 +4,18 @@ import { Matrix4 } from '@fms-cat/experimental';
import { RenderTarget } from '../RenderTarget'; import { RenderTarget } from '../RenderTarget';
import { Transform } from '../Transform'; import { Transform } from '../Transform';
import { glCat } from '../../globals/canvas'; import { glCat } from '../../globals/canvas';
import { MaterialTag } from '../Material';
export interface CameraOptions extends ComponentOptions { export interface CameraOptions extends ComponentOptions {
renderTarget?: RenderTarget; renderTarget?: RenderTarget;
projectionMatrix: Matrix4; projectionMatrix: Matrix4;
materialTag: MaterialTag;
scene?: Entity; scene?: Entity;
clear?: Array<number | undefined> | false; clear?: Array<number | undefined> | false;
} }
export abstract class Camera extends Component { export abstract class Camera extends Component {
protected __projectionMatrix: Matrix4; public projectionMatrix: Matrix4;
public get projectionMatrix(): Matrix4 {
return this.__projectionMatrix;
}
public renderTarget?: RenderTarget; public renderTarget?: RenderTarget;
@@ -25,6 +23,8 @@ export abstract class Camera extends Component {
public clear: Array<number | undefined> | false = []; public clear: Array<number | undefined> | false = [];
public materialTag: MaterialTag;
public abstract get near(): number; public abstract get near(): number;
public abstract get far(): number; public abstract get far(): number;
@@ -36,7 +36,8 @@ export abstract class Camera extends Component {
this.renderTarget = options.renderTarget; this.renderTarget = options.renderTarget;
this.scene = options.scene; this.scene = options.scene;
this.__projectionMatrix = options.projectionMatrix; this.projectionMatrix = options.projectionMatrix;
this.materialTag = options.materialTag;
if ( options.clear !== undefined ) { this.clear = options.clear; } if ( options.clear !== undefined ) { this.clear = options.clear; }
} }
@@ -63,10 +64,12 @@ export abstract class Camera extends Component {
frameCount: event.frameCount, frameCount: event.frameCount,
time: event.time, time: event.time,
renderTarget: renderTarget, renderTarget: renderTarget,
cameraTransform: event.globalTransform,
globalTransform: new Transform(), globalTransform: new Transform(),
viewMatrix, viewMatrix,
projectionMatrix: this.__projectionMatrix, projectionMatrix: this.projectionMatrix,
camera: this camera: this,
materialTag: this.materialTag,
} ); } );
if ( process.env.DEV ) { 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 { COMPONENT_DRAW_BREAKPOINT, COMPONENT_UPDATE_BREAKPOINT } from '../../config-hot';
import { GPUTimer } from '../GPUTimer'; import { GPUTimer } from '../GPUTimer';
import { getDivComponentsDraw, getDivComponentsUpdate } from '../../globals/dom'; import { getDivComponentsDraw, getDivComponentsUpdate } from '../../globals/dom';
import { MaterialTag } from '../Material';
export interface ComponentUpdateEvent { export interface ComponentUpdateEvent {
frameCount: number; frameCount: number;
@@ -19,6 +20,8 @@ export interface ComponentDrawEvent {
frameCount: number; frameCount: number;
time: number; time: number;
camera: Camera; camera: Camera;
cameraTransform: Transform;
materialTag: MaterialTag;
renderTarget: RenderTarget; renderTarget: RenderTarget;
globalTransform: Transform; globalTransform: Transform;
viewMatrix: Matrix4; 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 { Component, ComponentDrawEvent, ComponentOptions } from './Component';
import { Geometry } from '../Geometry'; import { Geometry } from '../Geometry';
import { Material } from '../Material'; import { MaterialMap, MaterialTag } from '../Material';
import { glCat } from '../../globals/canvas'; import { glCat } from '../../globals/canvas';
export enum MeshCull { export enum MeshCull {
@@ -18,12 +18,12 @@ const meshCullMap = {
export interface MeshOptions extends ComponentOptions { export interface MeshOptions extends ComponentOptions {
geometry: Geometry; geometry: Geometry;
material: Material; materials: Partial<MaterialMap<MaterialTag>>;
} }
export class Mesh extends Component { export class Mesh extends Component {
public geometry: Geometry; public geometry: Geometry;
public material: Material; public materials: Partial<MaterialMap<MaterialTag>>;
public cull: MeshCull = MeshCull.Back; public cull: MeshCull = MeshCull.Back;
@@ -33,16 +33,21 @@ export class Mesh extends Component {
this.active = false; this.active = false;
this.geometry = options.geometry; this.geometry = options.geometry;
this.material = options.material; this.materials = options.materials;
} }
protected __drawImpl( event: ComponentDrawEvent ): void { protected __drawImpl( event: ComponentDrawEvent ): void {
const gl = glCat.renderingContext; 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 ); glCat.useProgram( program );
this.material.setBlendMode(); material.setBlendMode();
if ( this.cull === MeshCull.None ) { if ( this.cull === MeshCull.None ) {
gl.disable( gl.CULL_FACE ); gl.disable( gl.CULL_FACE );
@@ -51,13 +56,15 @@ export class Mesh extends Component {
gl.cullFace( meshCullMap[ this.cull ] ); 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( 'time', event.time );
program.uniform1f( 'frameCount', event.frameCount ); program.uniform1f( 'frameCount', event.frameCount );
program.uniform2f( 'resolution', event.renderTarget.width, event.renderTarget.height ); 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( 'normalMatrix', event.globalTransform.matrix.inverse!.transpose.elements );
program.uniformMatrix4fv( 'modelMatrix', event.globalTransform.matrix.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 { Matrix4 } from '@fms-cat/experimental';
import { RenderTarget } from '../RenderTarget'; import { RenderTarget } from '../RenderTarget';
import { ComponentOptions } from './Component'; import { ComponentOptions } from './Component';
import { MaterialTag } from '../Material';
export interface PerspectiveCameraOptions extends ComponentOptions { export interface PerspectiveCameraOptions extends ComponentOptions {
materialTag: MaterialTag;
renderTarget?: RenderTarget; renderTarget?: RenderTarget;
near?: number; near?: number;
far?: number; far?: number;
@@ -14,17 +16,8 @@ export interface PerspectiveCameraOptions extends ComponentOptions {
} }
export class PerspectiveCamera extends Camera { export class PerspectiveCamera extends Camera {
private __near: number; public readonly near: number;
public readonly far: number;
public get near(): number {
return this.__near;
}
private __far: number;
public get far(): number {
return this.__far;
}
public constructor( options: PerspectiveCameraOptions ) { public constructor( options: PerspectiveCameraOptions ) {
const projectionMatrix = Matrix4.perspective( const projectionMatrix = Matrix4.perspective(
@@ -38,10 +31,10 @@ export class PerspectiveCamera extends Camera {
projectionMatrix, projectionMatrix,
renderTarget: options.renderTarget, renderTarget: options.renderTarget,
scene: options.scene, scene: options.scene,
clear: options.clear clear: options.clear,
} ); } );
this.__near = options.near || 0.01; this.near = options.near || 0.01;
this.__far = options.far || 100.0; 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 { Bloom } from './entities/Bloom';
import { CameraEntity } from './entities/CameraEntity'; import { CameraEntity } from './entities/CameraEntity';
import { Cube } from './entities/Cube'; import { Cube } from './entities/Cube';
import { CubemapCameraEntity } from './entities/CubemapCameraEntity';
import { EnvironmentMap } from './entities/EnvironmentMap'; import { EnvironmentMap } from './entities/EnvironmentMap';
import { FlickyParticles } from './entities/FlickyParticles'; import { FlickyParticles } from './entities/FlickyParticles';
import { Glitch } from './entities/Glitch'; import { Glitch } from './entities/Glitch';
@@ -69,23 +70,20 @@ class EntityReplacer<T extends { entity: Entity }> {
const ibllut = new IBLLUT(); const ibllut = new IBLLUT();
dog.root.children.push( ibllut.entity ); dog.root.children.push( ibllut.entity );
const environmentMap = new EnvironmentMap();
dog.root.children.push( environmentMap.entity );
// -- "objects" ------------------------------------------------------------------------------------ // -- "objects" ------------------------------------------------------------------------------------
const replacerSphereParticles = new EntityReplacer( () => new SphereParticles() ); // const replacerSphereParticles = new EntityReplacer( () => new SphereParticles() );
if ( process.env.DEV && module.hot ) { // if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/SphereParticles', () => { // module.hot.accept( './entities/SphereParticles', () => {
replacerSphereParticles.replace(); // replacerSphereParticles.replace();
} ); // } );
} // }
const replacerTrails = new EntityReplacer( () => new Trails() ); // const replacerTrails = new EntityReplacer( () => new Trails() );
if ( process.env.DEV && module.hot ) { // if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/Trails', () => { // module.hot.accept( './entities/Trails', () => {
replacerTrails.replace(); // replacerTrails.replace();
} ); // } );
} // }
const replacerRings = new EntityReplacer( () => new Rings() ); const replacerRings = new EntityReplacer( () => new Rings() );
if ( process.env.DEV && module.hot ) { if ( process.env.DEV && module.hot ) {
@@ -94,12 +92,12 @@ if ( process.env.DEV && module.hot ) {
} ); } );
} }
const replacerCube = new EntityReplacer( () => new Cube() ); // const replacerCube = new EntityReplacer( () => new Cube() );
if ( process.env.DEV && module.hot ) { // if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/Cube', () => { // module.hot.accept( './entities/Cube', () => {
replacerCube.replace(); // replacerCube.replace();
} ); // } );
} // }
const replacerFlickyParticles = new EntityReplacer( () => new FlickyParticles() ); const replacerFlickyParticles = new EntityReplacer( () => new FlickyParticles() );
if ( process.env.DEV && module.hot ) { if ( process.env.DEV && module.hot ) {
@@ -139,7 +137,7 @@ const light = new LightEntity( {
shadowMapFar: 20.0, shadowMapFar: 20.0,
namePrefix: process.env.DEV && 'light1', 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 ] ) ); light.entity.transform.lookAt( new Vector3( [ -1.0, 2.0, 8.0 ] ) );
dog.root.children.push( light.entity ); 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 ] ) ); // light2.entity.transform.lookAt( new Vector3( [ -4.0, -2.0, 6.0 ] ) );
// dog.root.children.push( light2.entity ); // 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( { const camera = new CameraEntity( {
root: dog.root, root: dog.root,
target: swap.o, target: swap.o,

View File

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

View File

@@ -22,6 +22,7 @@ uniform float head;
uniform vec2 resolution; uniform vec2 resolution;
uniform vec4 uniformSeed; uniform vec4 uniformSeed;
uniform sampler2D sampler0; uniform sampler2D sampler0;
uniform samplerCube samplerCubemap;
vec4 seed; vec4 seed;
@@ -66,14 +67,7 @@ vec3 ImportanceSampleGGX( vec2 Xi, float roughness, vec3 N ) {
} }
vec3 haha( vec3 L ) { vec3 haha( vec3 L ) {
bool circ = dot( L, normalize( vec3( 1.0, 3.0, 3.0 ) ) ) > 0.9; return texture( samplerCubemap, L ).xyz;
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;
} }
void main() { void main() {
@@ -92,11 +86,11 @@ void main() {
float a = TAU * uv.x; float a = TAU * uv.x;
float b = PI * ( uv.y - 0.5 ); 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 R = N;
vec3 V = R; vec3 V = R;
seed = uniformSeed + N.xyzx; seed = uniformSeed + 500.0 * N.xyzx;
vec4 col = vec4( 0.0 ); vec4 col = vec4( 0.0 );
for ( int i = 0; i < SAMPLES; i ++ ) { 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 ); 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 ); fragColor = vec4( tex, 1.0 );
} }

View File

@@ -29,14 +29,27 @@ in vec3 vNormal;
in vec4 vPosition; in vec4 vPosition;
in vec4 vDice; 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 float time;
uniform sampler2D samplerRandomStatic; 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 ======================================================================================== // == utils ========================================================================================
mat2 rotate2D( float t ) { mat2 rotate2D( float t ) {
return mat2( cos( t ), sin( t ), -sin( t ), cos( t ) ); return mat2( cos( t ), sin( t ), -sin( t ), cos( t ) );
@@ -163,8 +176,23 @@ void main() {
} }
#ifdef FORWARD
fragColor = vec4( 1.0 );
#endif
#ifdef DEFERRED
fragPosition = vPosition; fragPosition = vPosition;
fragNormal = vec4( vNormal, 1.0 ); fragNormal = vec4( vNormal, 1.0 );
fragColor = vec4( color, 1.0 ); fragColor = vec4( color, 1.0 );
fragWTF = vec4( vec3( 0.0 ), MTL_UNLIT ); 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 ) { float kick( float t ) {
if ( t < 0.0 ) { return 0.0; } 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 phase = 50.0 * t - 15.0 * exp( -200.0 * t ) - 9.4 * exp( -30.0 * t );
float fm = 0.7 * exp( -40.0 * t ) * sin( 2.0 * TAU * phase ); return exp( -4.0 * t ) * sin( TAU * phase );
return exp( -4.0 * t ) * sin( TAU * phase + fm );
} }
vec2 longsnare( float t ) { vec2 longsnare( float t ) {
@@ -145,7 +144,7 @@ vec2 crash( float t ) {
if ( t < 0.0 ) { return vec2( 0.0 ); } if ( t < 0.0 ) { return vec2( 0.0 ); }
t = t + 0.01 * sin( 0.5 * exp( -40.0 * t ) + 3.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 ); float fmamp = -3.4 * exp( -1.0 * t );
vec2 fm = fmamp * sin( vec2( 38855.0, 38865.0 ) * t ); vec2 fm = fmamp * sin( vec2( 38855.0, 38865.0 ) * t );
float amp = exp( -3.0 * t ); float amp = exp( -3.0 * t );
@@ -234,7 +233,7 @@ vec2 mainAudio( vec4 time ) {
: time.x; : time.x;
float sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick ); float sidechain = smoothstep( 0.0, 0.7 * BEAT, tKick );
{ {
dest += 0.2 * kick( tKick ); dest += 0.25 * kick( tKick );
} }
// -- snare -------------------------------------------------------------------------------------- // -- snare --------------------------------------------------------------------------------------
@@ -262,7 +261,7 @@ vec2 mainAudio( vec4 time ) {
} }
if ( 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 ); 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 );
@@ -299,7 +298,7 @@ vec2 mainAudio( vec4 time ) {
// -- 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 ) ||
inRange( time.w, SECTION_AAAA, SECTION_PSY ) inRange( time.w, SECTION_AAAA, SECTION_PSY )
) { ) {
float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) ); float chunk = floor( 6.0 * fs( lofi( time.z, 0.5 * BEAT ) ) );
@@ -336,6 +335,7 @@ vec2 mainAudio( vec4 time ) {
// -- 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 );
t += 1.0 * inRangeInteg( time.z, 28.0 * BEAT, 31.5 * BEAT, 50.0 );
float freq = n2f( float( chordsB[ progB ] ) ) * 0.125; float freq = n2f( float( chordsB[ progB ] ) ) * 0.125;
float fadetime = max( 0.0, time.w - SECTION_AAAA + 8.0 * BEAT ); 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 ) ); 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 ); 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 --------------------------------------------------------------------------------------- // -- harp ---------------------------------------------------------------------------------------
@@ -469,7 +469,7 @@ vec2 mainAudio( vec4 time ) {
dest += 0.2 * kick( t ) * exp( -decay * t ); 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 * 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 --------------------------------------------------------------------------- // -- fill, before psy ---------------------------------------------------------------------------

View File

@@ -13,14 +13,21 @@ const int MTL_IRIDESCENT = 4;
in vec2 vUv; in vec2 vUv;
layout (location = 0) out vec4 fragPosition; #ifdef DEFERRED
layout (location = 1) out vec4 fragNormal; layout (location = 0) out vec4 fragPosition;
layout (location = 2) out vec4 fragColor; layout (location = 1) out vec4 fragNormal;
layout (location = 3) out vec4 fragWTF; layout (location = 2) out vec4 fragColor;
layout (location = 3) out vec4 fragWTF;
#endif
#ifdef SHADOW
out vec4 fragColor;
#endif
uniform float time; uniform float time;
uniform vec2 resolution; uniform vec2 resolution;
uniform vec2 cameraNearFar; uniform vec2 cameraNearFar;
uniform vec3 cameraPos;
uniform mat4 viewMatrix; uniform mat4 viewMatrix;
uniform mat4 projectionMatrix; uniform mat4 projectionMatrix;
uniform mat4 inversePV; uniform mat4 inversePV;
@@ -76,8 +83,19 @@ void main() {
float depth = projPos.z / projPos.w; float depth = projPos.z / projPos.w;
gl_FragDepth = 0.5 + 0.5 * depth; gl_FragDepth = 0.5 + 0.5 * depth;
#ifdef DEFERRED
fragPosition = vec4( rayPos, depth ); fragPosition = vec4( rayPos, depth );
fragNormal = vec4( normal, 1.0 ); fragNormal = vec4( normal, 1.0 );
fragColor = color; fragColor = color;
fragWTF = vec4( vec3( 0.8, 0.8, 0.0 ), MTL_PBR ); 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 vec4 vPosition;
in vec3 vNormal; in vec3 vNormal;
layout (location = 0) out vec4 fragPosition; #ifdef FORWARD
layout (location = 1) out vec4 fragNormal; out vec4 fragColor;
layout (location = 2) out vec4 fragColor; #endif
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; uniform float time;
void main() { void main() {
#ifdef FORWARD
fragColor = vec4( 28.0 * vec3( 0.2, 0.9, 0.5 ), 1.0 );
#endif
#ifdef DEFERRED
fragPosition = vPosition; fragPosition = vPosition;
fragNormal = vec4( normalize( vNormal ), 1.0 ); fragNormal = vec4( normalize( vNormal ), 1.0 );
fragColor = vec4( 0.2, 0.9, 0.5, 1.0 ); fragColor = vec4( 0.2, 0.9, 0.5, 1.0 );
fragWTF = vec4( vec3( 0.2, 0.2, 4.0 ), MTL_PBR ); 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 vColor;
in vec4 vRandom; in vec4 vRandom;
layout (location = 0) out vec4 fragPosition; #ifdef DEFERRED
layout (location = 1) out vec4 fragNormal; layout (location = 0) out vec4 fragPosition;
layout (location = 2) out vec4 fragColor; layout (location = 1) out vec4 fragNormal;
layout (location = 3) out vec4 fragWTF; layout (location = 2) out vec4 fragColor;
layout (location = 3) out vec4 fragWTF;
#endif
uniform float time; uniform float time;
@@ -35,8 +37,10 @@ mat2 rotate2D( float _t ) {
void main() { void main() {
if ( vColor.a < 0.0 ) { discard; } if ( vColor.a < 0.0 ) { discard; }
#ifdef DEFERRED
fragPosition = vPosition; fragPosition = vPosition;
fragNormal = vec4( vNormal, 1.0 ); fragNormal = vec4( vNormal, 1.0 );
fragColor = vec4( vColor.xyz, 1.0 ); fragColor = vec4( vColor.xyz, 1.0 );
fragWTF = vec4( vec3( 0.4, 0.4, 0.0 ), MTL_PBR ); 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.__rng = new Xorshift();
this.__array = new Uint8Array( width * height * 4 ); this.__array = new Uint8Array( width * height * 4 );
this.__texture = glCat.createTexture()!; this.__texture = glCat.createTexture()!;
this.__texture.textureFilter( gl.LINEAR );
this.__texture.textureWrap( gl.REPEAT ); this.__texture.textureWrap( gl.REPEAT );
} }