end my suffer

This commit is contained in:
FMS-Cat
2021-03-29 04:22:58 +09:00
parent 7b4bf5029b
commit 15b7da52bc
26 changed files with 549 additions and 232 deletions

File diff suppressed because one or more lines are too long

View File

@@ -4,8 +4,8 @@ export const
RTINSPECTOR_CAPTURE_NAME: string | null = null,
// RTINSPECTOR_CAPTURE_NAME: string | null = 'Bloom/swap1',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'main/postSwap0',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'CameraEntity/cameraTarget',
// RTINSPECTOR_CAPTURE_NAME: string | null = 'DeferredCamera/cameraTarget',
RTINSPECTOR_CAPTURE_INDEX = 0,
COMPONENT_UPDATE_BREAKPOINT: string | null = null,
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'Bloom/quadUp1',
// COMPONENT_UPDATE_BREAKPOINT: string | null = 'ForwardCamera/camera',
COMPONENT_DRAW_BREAKPOINT: string | null = null;

View File

@@ -5,7 +5,7 @@ export const
AO_RESOLUTION_RATIO = 1.0,
RESOLUTION = [ 1280, 720 ],
MUSIC_BPM = 180,
START_POSITION = 36,
START_POSITION = 45,
MUSIC_LENGTH = 213,
MUSIC_AUTOMATON_TEXTURE_HEIGHT = 16,
IBLLUT_ITER = 400,

View File

@@ -102,7 +102,7 @@ export class Condition extends Entity {
geometry.primcount = 12 * 16;
// -- create materials -------------------------------------------------------------------------
const forward = new Material(
const cubemap = new Material(
conditionVert,
conditionFrag,
{
@@ -129,7 +129,7 @@ export class Condition extends Entity {
},
);
const materials = { forward, deferred, depth };
const materials = { cubemap, deferred, depth };
objectValuesMap( materials, ( material ) => {
material.addUniformTexture( 'samplerSvg', texture );
@@ -155,7 +155,7 @@ export class Condition extends Entity {
'../shaders/condition.frag',
],
() => {
forward.replaceShader( conditionVert, conditionFrag );
cubemap.replaceShader( conditionVert, conditionFrag );
deferred.replaceShader( conditionVert, conditionFrag );
depth.replaceShader( conditionVert, conditionFrag );
},

View File

@@ -3,7 +3,6 @@ import { CubemapCamera } from '../heck/components/CubemapCamera';
import { CubemapRenderTarget } from '../heck/CubemapRenderTarget';
import { Entity } from '../heck/Entity';
import { LightEntity } from './LightEntity';
import { PerspectiveCamera } from '../heck/components/PerspectiveCamera';
export interface CubemapCameraEntityOptions {
scenes: Entity[];
@@ -12,7 +11,7 @@ export interface CubemapCameraEntityOptions {
export class CubemapCameraEntity extends Entity {
public scenes: Entity[];
public camera: PerspectiveCamera;
public camera: CubemapCamera;
public readonly target: CubemapRenderTarget;
public constructor( options: CubemapCameraEntityOptions ) {
@@ -31,7 +30,7 @@ export class CubemapCameraEntity extends Entity {
near: 1.0,
far: 20.0,
name: 'CubemapCameraEntity/camera',
materialTag: 'forward',
materialTag: 'cubemap',
} );
this.components.push( this.camera );
}

View File

@@ -25,10 +25,12 @@ export interface DeferredCameraOptions {
}
export class DeferredCamera extends Entity {
public cameraTarget: BufferRenderTarget;
public constructor( options: DeferredCameraOptions ) {
super();
const cameraTarget = new BufferRenderTarget( {
this.cameraTarget = new BufferRenderTarget( {
width: options.target.width,
height: options.target.height,
numBuffers: 4,
@@ -37,7 +39,7 @@ export class DeferredCamera extends Entity {
const camera = new PerspectiveCamera( {
scenes: options.scenes,
renderTarget: cameraTarget,
renderTarget: this.cameraTarget,
near: 0.1,
far: 20.0,
name: 'DeferredCamera/camera',
@@ -75,7 +77,7 @@ export class DeferredCamera extends Entity {
for ( let i = 0; i < 2; i ++ ) { // it doesn't need 2 and 3
aoMaterial.addUniformTexture(
'sampler' + i,
cameraTarget.getTexture( gl.COLOR_ATTACHMENT0 + i )
this.cameraTarget.getTexture( gl.COLOR_ATTACHMENT0 + i )
);
}
@@ -161,6 +163,12 @@ export class DeferredCamera extends Entity {
lights.map( ( light ) => light.color ).flat(),
);
shadingMaterial.addUniformVector(
'lightParams',
'4fv',
lights.map( ( light ) => [ light.spotness, 0.0, 0.0, 0.0 ] ).flat(),
);
shadingMaterial.addUniformMatrixVector(
'lightPV',
'Matrix4fv',
@@ -182,7 +190,7 @@ export class DeferredCamera extends Entity {
for ( let i = 0; i < 4; i ++ ) {
shadingMaterial.addUniformTexture(
'sampler' + i,
cameraTarget.getTexture( gl.COLOR_ATTACHMENT0 + i )
this.cameraTarget.getTexture( gl.COLOR_ATTACHMENT0 + i )
);
}

View File

@@ -3,7 +3,7 @@ import { GPUParticles } from './GPUParticles';
import { InstancedGeometry } from '../heck/InstancedGeometry';
import { Material } from '../heck/Material';
import { TRIANGLE_STRIP_QUAD } from '@fms-cat/experimental';
import { dummyRenderTarget, dummyRenderTargetFourDrawBuffers } from '../globals/dummyRenderTarget';
import { dummyRenderTarget } from '../globals/dummyRenderTarget';
import { gl, glCat } from '../globals/canvas';
import { objectValuesMap } from '../utils/objectEntriesMap';
import { quadGeometry } from '../globals/quadGeometry';
@@ -78,25 +78,16 @@ export class FlickyParticles extends Entity {
},
);
const deferred = new Material(
const depth = new Material(
flickyParticleRenderVert,
flickyParticleRenderFrag,
{
defines: [ 'DEFERRED 1' ],
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
},
);
const shadow = new Material(
flickyParticleRenderVert,
flickyParticleRenderFrag,
{
defines: [ 'SHADOW 1' ],
defines: [ 'DEPTH 1' ],
initOptions: { geometry: geometryRender, target: dummyRenderTarget },
},
);
const materialsRender = { forward, deferred, shadow };
const materialsRender = { forward, cubemap: forward, depth };
objectValuesMap( materialsRender, ( material ) => {
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
@@ -111,8 +102,7 @@ export class FlickyParticles extends Entity {
],
() => {
forward.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
deferred.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
shadow.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
depth.replaceShader( flickyParticleRenderVert, flickyParticleRenderFrag );
}
);
}

View File

@@ -18,7 +18,7 @@ export class ForwardCamera extends Entity {
renderTarget: options.target,
near: 0.1,
far: 20.0,
name: 'CameraEntity/camera',
name: 'ForwardCamera/camera',
materialTag: 'forward',
} );
camera.clear = false;

View File

@@ -14,22 +14,34 @@ export interface LightEntityOptions {
shadowMapFov?: number;
shadowMapNear?: number;
shadowMapFar?: number;
shadowMapWidth?: number;
shadowMapHeight?: number;
shadowMapSize?: number;
namePrefix?: string;
}
export class LightEntity extends Entity {
public spotness: number = 0.0;
public color: [ number, number, number ] = [ 1.0, 1.0, 1.0 ];
public camera: PerspectiveCamera;
public shadowMap: BufferRenderTarget;
public get shadowMapFov(): number {
return this.camera.fov;
}
public get shadowMapNear(): number {
return this.camera.near;
}
public get shadowMapFar(): number {
return this.camera.far;
}
public constructor( options: LightEntityOptions ) {
super();
const swapOptions = {
width: options.shadowMapWidth ?? 1024,
height: options.shadowMapHeight ?? 1024
width: options.shadowMapSize ?? 1024,
height: options.shadowMapSize ?? 1024,
};
const swap = new Swap(

106
src/entities/LightShaft.ts Normal file
View File

@@ -0,0 +1,106 @@
import { BufferRenderTarget } from '../heck/BufferRenderTarget';
import { Entity } from '../heck/Entity';
import { Geometry } from '../heck/Geometry';
import { Lambda } from '../heck/components/Lambda';
import { LightEntity } from './LightEntity';
import { Material } from '../heck/Material';
import { Mesh } from '../heck/components/Mesh';
import { dummyRenderTarget } from '../globals/dummyRenderTarget';
import { genCube } from '../geometries/genCube';
import { gl } from '../globals/canvas';
import { randomTexture } from '../globals/randomTexture';
import lightShaftFrag from '../shaders/light-shaft.frag';
import lightShaftVert from '../shaders/light-shaft.vert';
interface LightShaftOptions {
light: LightEntity;
namePrefix?: string;
}
export class LightShaft extends Entity {
private __forward: Material;
public constructor( { light, namePrefix }: LightShaftOptions ) {
super();
// -- geometry ---------------------------------------------------------------------------------
const cube = genCube();
const geometry = new Geometry();
geometry.vao.bindVertexbuffer( cube.position, 0, 3 );
geometry.vao.bindIndexbuffer( cube.index );
geometry.count = cube.count;
geometry.mode = cube.mode;
geometry.indexType = cube.indexType;
// -- materials --------------------------------------------------------------------------------
const forward = this.__forward = new Material(
lightShaftVert,
lightShaftFrag,
{
initOptions: { geometry: geometry, target: dummyRenderTarget },
blend: [ gl.ONE, gl.ONE ],
},
);
forward.addUniformTexture( 'samplerRandom', randomTexture.texture );
forward.addUniformTexture( 'samplerShadow', light.shadowMap.texture );
const materials = { forward };
// -- updater ----------------------------------------------------------------------------------
this.components.push( new Lambda( {
onDraw: ( event ) => {
forward.addUniform( 'lightFov', '1f', light.shadowMapFov );
forward.addUniform( 'lightNearFar', '2f', light.shadowMapNear, light.shadowMapFar );
forward.addUniform( 'lightPos', '3f', ...light.globalTransformCache.position.elements );
forward.addUniform( 'lightColor', '3f', ...light.color );
forward.addUniformMatrixVector(
'lightPV',
'Matrix4fv',
light.camera.projectionMatrix.multiply(
light.globalTransformCache.matrix.inverse!
).elements,
);
forward.addUniform(
'cameraNearFar',
'2f',
event.camera.near,
event.camera.far
);
forward.addUniformMatrixVector(
'inversePVM',
'Matrix4fv',
event.projectionMatrix
.multiply( event.viewMatrix )
.multiply( event.globalTransform.matrix )
.inverse!
.elements
);
},
name: process.env.DEV && `${ namePrefix }/updater`,
} ) );
// -- mesh -------------------------------------------------------------------------------------
const mesh = new Mesh( {
geometry,
materials,
name: process.env.DEV && `${ namePrefix }/mesh`,
} );
mesh.depthTest = false;
mesh.depthWrite = false;
this.components.push( mesh );
}
/**
* どうやってフレームバッファのデプスを取るかわかりませんでした 許してほしい
*/
public setDefferedCameraTarget( deferredCameraTarget: BufferRenderTarget ): void {
this.__forward.addUniformTexture( 'samplerDeferred0', deferredCameraTarget.texture );
}
}

View File

@@ -0,0 +1,30 @@
import { Entity } from '../heck/Entity';
import { LightEntity } from './LightEntity';
import { Vector3 } from '@fms-cat/experimental';
interface LightsFirstOptions {
scenes: Entity[];
}
export class LightsFirst extends Entity {
public readonly lights: LightEntity[];
public constructor( { scenes }: LightsFirstOptions ) {
super();
const light = new LightEntity( {
scenes,
shadowMapFov: 30.0,
shadowMapNear: 1.0,
shadowMapFar: 20.0,
namePrefix: process.env.DEV && 'lightFirst',
} );
light.color = [ 100.0, 100.0, 100.0 ];
light.transform.lookAt( new Vector3( [ 4.0, 4.0, 4.0 ] ) );
this.children.push( light );
this.lights = [ light ];
}
}

View File

@@ -0,0 +1,61 @@
import { BufferRenderTarget } from '../heck/BufferRenderTarget';
import { Entity } from '../heck/Entity';
import { LightEntity } from './LightEntity';
import { LightShaft } from './LightShaft';
import { Vector3 } from '@fms-cat/experimental';
interface LightsPinkOptions {
scenes: Entity[];
}
export class LightsPink extends Entity {
public readonly lights: LightEntity[];
private readonly __shafts: LightShaft[];
public constructor( { scenes }: LightsPinkOptions ) {
super();
type TypeScriptSucks = [ [ number, number, number ], [ number, number, number ], boolean ][];
this.__shafts = [];
this.lights = ( [
[ [ 6000.0, 10.0, 200.0 ], [ 8.0, 4.0, -8.0 ], true ],
[ [ 6000.0, 10.0, 200.0 ], [ -8.0, 4.0, -8.0 ], true ],
[ [ 30.0, 30.0, 30.0 ], [ 0.0, 4.0, 4.0 ], false ],
] as TypeScriptSucks ).map( ( [ color, pos, isSpot ], i ) => {
const light = new LightEntity( {
scenes,
shadowMapFov: isSpot ? 10.0 : 50.0,
shadowMapNear: 0.5,
shadowMapFar: 20.0,
shadowMapSize: isSpot ? 64 : 256,
namePrefix: process.env.DEV && `lightPink${ i }/light`,
} );
light.color = color;
light.spotness = isSpot ? 0.9 : 0.0;
light.transform.lookAt( new Vector3( pos ) );
this.children.push( light );
if ( isSpot ) {
const shaft = new LightShaft( {
light,
namePrefix: process.env.DEV && `lightPink${ i }/Shaft`,
} );
this.__shafts.push( shaft );
light.children.push( shaft );
}
return light;
} );
}
public setDefferedCameraTarget( deferredCameraTarget: BufferRenderTarget ): void {
this.__shafts.map( ( shaft ) => {
shaft.setDefferedCameraTarget( deferredCameraTarget );
} );
}
}

View File

@@ -84,7 +84,7 @@ export class Wobbleball extends Entity {
'Matrix4fv',
event.projectionMatrix
.multiply( event.viewMatrix )
.multiply( this.transform.matrix )
.multiply( event.globalTransform.matrix )
.inverse!
.elements
);

View File

@@ -8,6 +8,7 @@ import { injectCodeToShader } from '../utils/injectCodeToShader';
export type MaterialTag =
| 'deferred'
| 'forward'
| 'cubemap'
| 'depth';
export type MaterialMap = { [ tag in MaterialTag ]?: Material };

View File

@@ -26,6 +26,8 @@ export class Mesh extends Component {
public materials: MaterialMap;
public cull: MeshCull = MeshCull.Back;
public depthWrite = true;
public depthTest = true;
public constructor( options: MeshOptions ) {
super( options );
@@ -56,6 +58,14 @@ export class Mesh extends Component {
gl.cullFace( meshCullMap[ this.cull ] );
}
if ( this.depthTest ) {
gl.enable( gl.DEPTH_TEST );
} else {
gl.disable( gl.DEPTH_TEST );
}
gl.depthMask( this.depthWrite );
material.setUniforms();
program.uniform( 'time', '1f', event.time );

View File

@@ -16,15 +16,16 @@ export interface PerspectiveCameraOptions extends ComponentOptions {
}
export class PerspectiveCamera extends Camera {
public readonly fov: number;
public readonly near: number;
public readonly far: number;
public constructor( options: PerspectiveCameraOptions ) {
const projectionMatrix = Matrix4.perspective(
options.fov || 45.0,
options.near || 0.01,
options.far || 100.0,
);
const fov = options.fov ?? 45.0;
const near = options.near ?? 0.01;
const far = options.far ?? 100.0;
const projectionMatrix = Matrix4.perspective( fov, near, far );
super( {
...options,
@@ -34,7 +35,8 @@ export class PerspectiveCamera extends Camera {
clear: options.clear,
} );
this.near = options.near || 0.01;
this.far = options.far || 100.0;
this.fov = fov;
this.near = near;
this.far = far;
}
}

View File

@@ -1,7 +1,7 @@
import { Component, ComponentOptions, ComponentUpdateEvent } from './Component';
import { Material } from '../Material';
import { RenderTarget } from '../RenderTarget';
import { glCat } from '../../globals/canvas';
import { gl, glCat } from '../../globals/canvas';
import { quadGeometry } from '../../globals/quadGeometry';
export interface QuadOptions extends ComponentOptions {
@@ -37,6 +37,9 @@ export class Quad extends Component {
this.target.bind();
this.material.setBlendMode();
gl.enable( gl.DEPTH_TEST );
gl.depthMask( true );
if ( this.clear ) {
glCat.clear( ...this.clear );
}

View File

@@ -110,6 +110,8 @@ export abstract class Music {
if ( this.isPlaying ) {
this.deltaTime = now - this.__prevAudioTime;
this.time += this.deltaTime;
} else {
this.deltaTime = 0.0;
}
this.__updateImpl();

View File

@@ -2,7 +2,7 @@ import { Antialias } from './entities/Antialias';
import { Bloom } from './entities/Bloom';
import { BufferRenderTarget } from './heck/BufferRenderTarget';
import { CanvasRenderTarget } from './heck/CanvasRenderTarget';
import { Component, ComponentUpdateEvent } from './heck/components/Component';
import { Component } from './heck/components/Component';
import { Condition } from './entities/Condition';
import { Cube } from './entities/Cube';
import { CubemapCameraEntity } from './entities/CubemapCameraEntity';
@@ -17,7 +17,8 @@ import { Glitch } from './entities/Glitch';
import { IBLLUT } from './entities/IBLLUT';
import { IFSPistons } from './entities/IFSPistons';
import { Lambda } from './heck/components/Lambda';
import { LightEntity } from './entities/LightEntity';
import { LightsFirst } from './entities/LightsFirst';
import { LightsPink } from './entities/LightsPink';
import { PixelSorter } from './entities/PixelSorter';
import { Post } from './entities/Post';
import { RTInspector } from './entities/RTInspector';
@@ -147,17 +148,6 @@ if ( process.env.DEV && module.hot ) {
} );
}
const replacerFlickyParticles = new EntityReplacer(
deferredRoot,
() => new FlickyParticles(),
'FlickyParticles',
);
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/FlickyParticles', () => {
replacerFlickyParticles.replace();
} );
}
const replacerWobbleball = new EntityReplacer( deferredRoot, () => new Wobbleball(), 'Wobbleball' );
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/Wobbleball', () => {
@@ -187,6 +177,17 @@ if ( process.env.DEV && module.hot ) {
} );
}
const replacerFlickyParticles = new EntityReplacer(
forwardRoot,
() => new FlickyParticles(),
'FlickyParticles',
);
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/FlickyParticles', () => {
replacerFlickyParticles.replace();
} );
}
// -- things that is not an "object" ---------------------------------------------------------------
const swapOptions = {
width: canvasRenderTarget.width,
@@ -204,40 +205,24 @@ const swap = new Swap(
} ),
);
const replacerLightFirst = new EntityReplacer( dog.root, () => {
const light = new LightEntity( {
scenes: [ dog.root ],
shadowMapFov: 90.0,
shadowMapNear: 1.0,
shadowMapFar: 20.0,
namePrefix: process.env.DEV && 'lightFirst',
} );
light.color = [ 100.0, 100.0, 100.0 ];
light.transform.lookAt( new Vector3( [ 4.0, 4.0, 4.0 ] ) );
return light;
}, 'LightFirst' );
const lightFirst = replacerLightFirst.current;
const replacerLightsFirst = new EntityReplacer(
dog.root,
() => new LightsFirst( { scenes: [ dog.root ] } ),
'LightsFirst',
);
const replacerLightPink = new EntityReplacer( dog.root, () => {
const light = new LightEntity( {
const replacerLightsPink = new EntityReplacer(
dog.root,
() => new LightsPink( {
scenes: [ dog.root ],
shadowMapFov: 90.0,
shadowMapNear: 1.0,
shadowMapFar: 20.0,
namePrefix: process.env.DEV && 'lightPink',
} );
light.color = [ 120.0, 2.0, 10.0 ];
light.transform.lookAt( new Vector3( [ -1.0, 2.0, 2.0 ] ) );
return light;
}, 'LightPink' );
const lightPink = replacerLightPink.current;
} ),
'LightsPink',
);
if ( process.env.DEV && module.hot ) {
module.hot.accept( './entities/LightEntity', () => {
replacerLightFirst.replace();
replacerLightPink.replace();
} );
}
const lights = [
...replacerLightsFirst.current.lights,
...replacerLightsPink.current.lights,
];
// const light2 = new LightEntity( {
// root: dog.root,
@@ -252,11 +237,7 @@ if ( process.env.DEV && module.hot ) {
const cubemapCamera = new CubemapCameraEntity( {
scenes: [ dog.root ],
lights: [
lightFirst,
lightPink,
// light2
],
lights,
} );
dog.root.children.push( cubemapCamera );
@@ -266,90 +247,78 @@ const environmentMap = new EnvironmentMap( {
dog.root.children.push( environmentMap );
// -- camera ---------------------------------------------------------------------------------------
const cameraOnUpdate = ( { time }: ComponentUpdateEvent ): void => {
const r = auto( 'Camera/rot/r' );
const t = auto( 'Camera/rot/t' );
const p = auto( 'Camera/rot/p' );
const x = auto( 'Camera/pos/x' );
const y = auto( 'Camera/pos/y' );
const z = auto( 'Camera/pos/z' );
const roll = auto( 'Camera/roll' );
const shake = auto( 'Camera/shake' );
const st = Math.sin( t );
const ct = Math.cos( t );
const sp = Math.sin( p );
const cp = Math.cos( p );
const wubPosAmp = 0.01;
const wubPosTheta = 3.0 * time;
const wubTarAmp = 0.02;
const wubTarTheta = 4.21 * time;
deferredCamera.transform.lookAt(
new Vector3( [
r * ct * sp + wubPosAmp * Math.sin( wubPosTheta ),
r * st + wubPosAmp * Math.sin( 2.0 + wubPosTheta ),
r * ct * cp + wubPosAmp * Math.sin( 4.0 + wubPosTheta ),
] ),
new Vector3( [
wubTarAmp * Math.sin( wubTarTheta ),
wubTarAmp * Math.sin( 2.0 + wubTarTheta ),
wubTarAmp * Math.sin( 4.0 + wubTarTheta ),
] ),
undefined,
0.02 * Math.sin( 2.74 * time ) + roll,
);
deferredCamera.transform.position = deferredCamera.transform.position.add(
new Vector3( [ x, y, z ] )
);
if ( shake > 0.0 ) {
deferredCamera.transform.position = deferredCamera.transform.position.add(
new Vector3( [
Math.sin( 145.0 * time ),
Math.sin( 2.0 + 148.0 * time ),
Math.sin( 4.0 + 151.0 * time )
] ).scale( shake )
);
}
};
const deferredCamera = new DeferredCamera( {
scenes: [ deferredRoot ],
scenes: [ dog.root ],
target: swap.o,
lights: [
lightFirst,
lightPink,
// light2
],
lights,
textureIBLLUT: ibllut.texture,
textureEnv: environmentMap.texture,
} );
deferredCamera.components.unshift( new Lambda( {
onUpdate: cameraOnUpdate,
name: process.env.DEV && 'main/updateDeferredCamera',
} ) );
dog.root.children.push( deferredCamera );
replacerLightsPink.current.setDefferedCameraTarget( deferredCamera.cameraTarget );
const forwardCamera = new ForwardCamera( {
scenes: [ forwardRoot ],
scenes: [ dog.root ],
target: swap.o,
lights: [
lightFirst,
lightPink,
// light2
],
lights,
} );
forwardCamera.components.unshift( new Lambda( {
onUpdate: cameraOnUpdate,
name: process.env.DEV && 'main/updateForwardCamera',
} ) );
dog.root.children.push( forwardCamera );
dog.root.components.push( new Lambda( {
onUpdate: ( { time } ) => {
const r = auto( 'Camera/rot/r' );
const t = auto( 'Camera/rot/t' );
const p = auto( 'Camera/rot/p' );
const x = auto( 'Camera/pos/x' );
const y = auto( 'Camera/pos/y' );
const z = auto( 'Camera/pos/z' );
const roll = auto( 'Camera/roll' );
const shake = auto( 'Camera/shake' );
const st = Math.sin( t );
const ct = Math.cos( t );
const sp = Math.sin( p );
const cp = Math.cos( p );
const wubPosAmp = 0.01;
const wubPosTheta = 3.0 * time;
const wubTarAmp = 0.02;
const wubTarTheta = 4.21 * time;
[ deferredCamera, forwardCamera ].map( ( camera ) => {
camera.transform.lookAt(
new Vector3( [
r * ct * sp + wubPosAmp * Math.sin( wubPosTheta ),
r * st + wubPosAmp * Math.sin( 2.0 + wubPosTheta ),
r * ct * cp + wubPosAmp * Math.sin( 4.0 + wubPosTheta ),
] ),
new Vector3( [
wubTarAmp * Math.sin( wubTarTheta ),
wubTarAmp * Math.sin( 2.0 + wubTarTheta ),
wubTarAmp * Math.sin( 4.0 + wubTarTheta ),
] ),
undefined,
0.02 * Math.sin( 2.74 * time ) + roll,
);
camera.transform.position = camera.transform.position.add(
new Vector3( [ x, y, z ] )
);
if ( shake > 0.0 ) {
camera.transform.position = camera.transform.position.add(
new Vector3( [
Math.sin( 145.0 * time ),
Math.sin( 2.0 + 148.0 * time ),
Math.sin( 4.0 + 151.0 * time )
] ).scale( shake )
);
}
} );
},
name: process.env.DEV && 'main/updateCamera',
} ) );
// -- post -----------------------------------------------------------------------------------------
swap.swap();
const antialias = new Antialias( {

View File

@@ -43,7 +43,7 @@ uniform sampler2D samplerRandomStatic;
layout (location = 3) out vec4 fragWTF;
#endif
#ifdef SHADOW
#ifdef DEPTH
out vec4 fragColor;
uniform vec2 cameraNearFar;
@@ -187,7 +187,7 @@ void main() {
fragWTF = vec4( vec3( 0.0 ), MTL_UNLIT );
#endif
#ifdef SHADOW
#ifdef DEPTH
float depth = linearstep(
cameraNearFar.x,
cameraNearFar.y,

View File

@@ -7,10 +7,6 @@ precision highp float;
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
const int MARCH_ITER = 90;
const int MTL_UNLIT = 1;
const int MTL_PBR = 2;
const int MTL_GRADIENT = 3;
const int MTL_IRIDESCENT = 4;
const float PI = 3.14159265;
const float TAU = PI * 2.0;
@@ -21,15 +17,12 @@ const float TAU = PI * 2.0;
layout (location = 3) out vec4 fragWTF;
#endif
in vec4 vPosition;
in vec4 vPositionWithoutModel;
#ifdef SHADOW
out vec4 fragColor;
#endif
uniform float deformAmp;
uniform float deformFreq;
uniform float deformTime;
uniform float time;
uniform float ifsSeed;
uniform vec2 resolution;
@@ -48,12 +41,6 @@ vec3 divideByW( vec4 v ) {
return v.xyz / v.w;
}
// https://www.iquilezles.org/www/articles/smin/smin.htm
float smin( float a, float b, float k ) {
float h = max( k - abs( a - b ), 0.0 ) / k;
return min( a, b ) - h * h * h * k * ( 1.0 / 6.0 );
}
mat2 rot2d( float t ) {
float c = cos( t );
float s = sin( t );
@@ -90,7 +77,9 @@ vec4 map( vec3 p ) {
float d1, d2;
{
float clampbox = box( p - vec3( 0.0, 10.0, 0.0 ), vec3( 1.0, 10.0, 1.0 ) - 0.1 );
vec3 pt = p;
float clampbox = box( pt - vec3( 0.0, 10.0, 0.0 ), vec3( 1.0, 10.0, 1.0 ) - 0.1 );
vec3 r = mix(
fs( vec3( 4.7, 2.2, 8.3 ) + floor( ifsSeed ) ),
@@ -98,7 +87,7 @@ vec4 map( vec3 p ) {
fract( ifsSeed )
);
vec3 t = 0.1 * vec3( 3.0, 2.3, 3.5 );
vec3 pt = ifs( p, r, t );
pt = ifs( pt, r, t );
pt = mod( pt - 0.1, 0.2 ) - 0.1;
@@ -106,7 +95,9 @@ vec4 map( vec3 p ) {
}
{
float clampbox = box( p - vec3( 0.0, 10.0, 0.0 ), vec3( 1.0, 10.0, 1.0 ) );
vec3 pt = p;
float clampbox = box( pt - vec3( 0.0, 10.0, 0.0 ), vec3( 1.0, 10.0, 1.0 ) );
vec3 r = mix(
fs( vec3( 5.3, 1.1, 2.9 ) + floor( ifsSeed ) ),
@@ -114,7 +105,7 @@ vec4 map( vec3 p ) {
fract( ifsSeed )
);
vec3 t = 0.2 * vec3( 3.0, 2.3, 3.5 );
vec3 pt = ifs( p, r, t );
pt = ifs( pt, r, t );
pt = mod( pt - 0.1, 0.2 ) - 0.1;
@@ -139,7 +130,7 @@ void main() {
vec3 rayOri = divideByW( inversePVM * vec4( p, 0.0, 1.0 ) );
vec3 farPos = divideByW( inversePVM * vec4( p, 1.0, 1.0 ) );
vec3 rayDir = normalize( farPos - rayOri );
float rayLen = length( vPosition.xyz - cameraPos );
float rayLen = length( vPositionWithoutModel.xyz - rayOri );
vec3 rayPos = rayOri + rayDir * rayLen;
vec4 isect;
@@ -176,11 +167,11 @@ void main() {
0.2 * smoothstep( -0.2, 0.4, noise.y ) * ( 0.8 + 0.2 * sin( 17.0 * noiseDetail.x ) )
);
fragColor = vec4( vec3( 0.4 ), 1.0 );
fragWTF = vec4( vec3( roughness, 0.9, 0.0 ), MTL_PBR );
fragColor = vec4( vec3( 0.04 ), 1.0 );
fragWTF = vec4( vec3( roughness, 0.9, 0.0 ), 2 );
} else if ( isect.y == 1.0 ) {
fragColor = vec4( vec3( 1.0 ), 1.0 );
fragWTF = vec4( vec3( 0.3, 0.1, 0.0 ), MTL_PBR );
fragWTF = vec4( vec3( 0.3, 0.1, 0.0 ), 2 );
}
#endif

View File

@@ -0,0 +1,111 @@
#version 300 es
precision highp float;
#define saturate(x) clamp(x,0.,1.)
#define linearstep(a,b,x) saturate(((x)-(a))/((b)-(a)))
const int MARCH_ITER = 20;
const float INV_MARCH_ITER = 1.0 / float( MARCH_ITER );
const float PI = 3.14159265;
const float TAU = PI * 2.0;
in float vFrustumZ;
in vec4 vPosition;
out vec4 fragColor;
uniform float time;
uniform vec2 lightNearFar;
uniform vec2 resolution;
uniform vec2 cameraNearFar;
uniform vec3 cameraPos;
uniform vec3 lightColor;
uniform vec3 lightPos;
uniform mat4 lightPV;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 inversePVM;
uniform sampler2D samplerDeferred0;
uniform sampler2D samplerRandom;
uniform sampler2D samplerShadow;
float cameraDepth;
#pragma glslify: prng = require( ./-prng );
vec3 divideByW( vec4 v ) {
return v.xyz / v.w;
}
float map( vec3 p ) {
vec4 pt = projectionMatrix * viewMatrix * vec4( p, 1.0 );
float depth = pt.z / pt.w;
if ( depth > cameraDepth ) {
return 0.0;
}
float l = length( p - lightPos );
float tooNear = smoothstep( 0.0, 0.1, l );
vec4 lightProj = lightPV * vec4( p, 1.0 );
vec3 lightP = lightProj.xyz / lightProj.w;
if ( lightP.z < 0.0 || 1.0 < lightP.z ) {
return 0.0;
}
float depth = linearstep(
lightNearFar.x,
lightNearFar.y,
l
);
vec4 tex = texture( samplerShadow, 0.5 + 0.5 * lightP.xy );
float variance = saturate( tex.y - tex.x * tex.x );
float md = depth - tex.x;
float softShadow = md < 0.0 ? 1.0 : linearstep( 0.2, 1.0, variance / ( variance + md * md ) );
// spot
float spot = smoothstep( 1.0, 0.5, length( lightP.xy ) );
return tooNear * softShadow * spot * 1.0 / l / l;
}
void main() {
vec2 p = ( gl_FragCoord.xy * 2.0 - resolution ) / resolution.y;
vec4 seed = texture( samplerRandom, p );
prng( seed );
vec4 texDeferred0 = texture( samplerDeferred0, gl_FragCoord.xy / resolution.xy );
cameraDepth = 2.0 * texDeferred0.w - 1.0;
vec3 rayOri = cameraPos;
vec3 rayDir = normalize( vPosition.xyz - rayOri );
float rayLen = gl_FrontFacing
? 1E-2
: length( vPosition.xyz - rayOri );
vec3 rayPos = rayOri + rayDir * rayLen;
// this is terrible
// There definitely are better ways to do this
float stepLen = gl_FrontFacing
? 1.0
: 0.1;
float accum = 0.0;
float isect;
for ( int i = 0; i < MARCH_ITER; i ++ ) {
isect = map( rayPos );
accum += isect * INV_MARCH_ITER;
rayLen += stepLen * 0.8 + 0.2 * prng( seed );
rayPos = rayOri + rayDir * rayLen;
if ( rayLen > cameraNearFar.y ) { break; }
}
fragColor = vec4( 0.01 * lightColor * accum, 1.0 );
}

View File

@@ -0,0 +1,33 @@
#version 300 es
const float PI = 3.14159265;
layout (location = 0) in vec3 position;
out float vFrustumZ;
out vec4 vPosition;
uniform float lightFov;
uniform vec2 lightNearFar;
uniform vec2 resolution;
uniform mat4 projectionMatrix;
uniform mat4 viewMatrix;
uniform mat4 modelMatrix;
// ------
void main() {
float vFrustumZ = 0.5 + 0.5 * position.z;
vec3 pos = mix(
vec3( position.xy * lightNearFar.x * tan( lightFov / 360.0 * PI ), -lightNearFar.x ),
vec3( position.xy * lightNearFar.y * tan( lightFov / 360.0 * PI ), -lightNearFar.y ),
vFrustumZ
);
vPosition = modelMatrix * vec4( pos, 1.0 );
vec4 outPos = projectionMatrix * viewMatrix * vPosition;
outPos.x *= resolution.y / resolution.x;
gl_Position = outPos;
}

View File

@@ -2,6 +2,7 @@
layout (location = 0) in vec3 position;
out vec4 vPositionWithoutModel;
out vec4 vPosition;
uniform vec2 resolution;
@@ -12,7 +13,8 @@ uniform mat4 modelMatrix;
// ------
void main() {
vPosition = modelMatrix * vec4( position, 1.0 );
vPositionWithoutModel = vec4( position, 1.0 );
vPosition = modelMatrix * vPositionWithoutModel;
vec4 outPos = projectionMatrix * viewMatrix * vPosition;
outPos.x *= resolution.y / resolution.x;

View File

@@ -5,8 +5,6 @@ precision highp float;
const int MTL_NONE = 0;
const int MTL_UNLIT = 1;
const int MTL_PBR = 2;
const int MTL_GRADIENT = 3;
const int AO_ITER = 8;
const float ENV_UV_MARGIN = 0.9375;
const float AO_BIAS = 0.0;
const float AO_RADIUS = 0.5;
@@ -27,11 +25,13 @@ in vec2 vUv;
out vec4 fragColor;
uniform int lightCount;
uniform vec2 resolution;
uniform vec2 lightNearFar[8];
uniform vec2 cameraNearFar;
uniform vec3 cameraPos;
uniform vec3 lightPos[8];
uniform vec3 lightColor[8];
uniform vec4 lightParams[8];
uniform mat4 lightPV[8];
uniform mat4 cameraView;
uniform mat4 cameraPV;
@@ -59,27 +59,6 @@ vec3 catColor( float _p ) {
);
}
vec3 blurpleGradient( float t ) {
vec3 colorA = vec3( 0.01, 0.04, 0.2 );
vec3 colorB = vec3( 0.02, 0.3, 0.9 );
vec3 colorC = vec3( 0.9, 0.01, 0.6 );
vec3 colorD = vec3( 0.5, 0.02, 0.02 );
return mix(
colorA,
mix(
colorB,
mix(
colorC,
colorD,
linearstep( 0.67, 1.0, t )
),
linearstep( 0.33, 0.67, t )
),
linearstep( 0.0, 0.33, t )
);
}
vec4 sampleEnvNearest( vec2 uv, float lv ) {
float p = pow( 0.5, float( lv ) );
vec2 uvt = ENV_UV_MARGIN * ( uv - 0.5 ) + 0.5;
@@ -128,7 +107,7 @@ vec4 fetchShadowMap( int iLight, vec2 uv ) {
}
// == features =====================================================================================
float castShadow( int iLight, Isect isect, float NdotL ) {
float castShadow( int iLight, vec2 lightUv, Isect isect, float NdotL ) {
float depth = linearstep(
lightNearFar[ iLight ].x,
lightNearFar[ iLight ].y,
@@ -138,12 +117,9 @@ float castShadow( int iLight, Isect isect, float NdotL ) {
float bias = 0.0001 + 0.0001 * ( 1.0 - NdotL );
depth -= bias;
vec4 proj = lightPV[ iLight ] * vec4( isect.position, 1.0 );
vec2 uv = proj.xy / proj.w * 0.5 + 0.5;
vec4 tex = fetchShadowMap( iLight, lightUv );
vec4 tex = fetchShadowMap( iLight, uv );
float edgeClip = smoothstep( 0.4, 0.5, max( abs( uv.x - 0.5 ), abs( uv.y - 0.5 ) ) );
float edgeClip = smoothstep( 0.4, 0.5, max( abs( lightUv.x - 0.5 ), abs( lightUv.y - 0.5 ) ) );
float variance = saturate( tex.y - tex.x * tex.x );
float md = depth - tex.x;
@@ -205,9 +181,18 @@ vec3 shadePBR( Isect isect ) {
float decayL = 1.0 / ( lenL * lenL );
// fetch shadowmap
float shadow = castShadow( iLight, isect, NdotL );
shadow = mix( 0.5, 1.0, shadow );
// fetch shadowmap + spot lighting
vec4 lightProj = lightPV[ iLight ] * vec4( isect.position, 1.0 );
vec2 lightP = lightProj.xy / lightProj.w;
float shadow = mix(
1.0,
smoothstep( 1.0, 0.5, length( lightP ) ),
lightParams[ iLight ].x
);
shadow *= castShadow( iLight, lightP * 0.5 + 0.5, isect, NdotL );
shadow = mix( 0.0, 1.0, shadow );
// do shading
vec3 diffuse = brdfLambert( f0, albedo, VdotH );
@@ -246,11 +231,6 @@ vec3 shadePBR( Isect isect ) {
}
vec3 shadeGradient( Isect isect ) {
float shade = isect.normal.y;
return blurpleGradient( 0.5 + 0.5 * shade );
}
// == main procedure ===============================================================================
void main() {
vec4 tex0 = texture( sampler0, vUv );
@@ -270,6 +250,13 @@ void main() {
isect.materialId = int( tex3.w + 0.5 );
isect.materialParams = tex3.xyz;
// from isect
vec3 V = cameraPos - isect.position;
float lenV = length( V );
V = normalize( V );
float NdotV = clamp( dot( isect.normal, V ), EPSILON, 1.0 );
vec3 color = vec3( 0.0 );
if ( isect.materialId == MTL_NONE ) {
@@ -281,8 +268,6 @@ void main() {
} else if ( isect.materialId == MTL_PBR ) {
color = shadePBR( isect );
} else if ( isect.materialId == MTL_GRADIENT ) {
color = shadeGradient( isect );
}
@@ -297,4 +282,6 @@ void main() {
fragColor = vec4( color, 1.0 );
// fragColor.xyz *= smoothstep( 1.0, 0.7, calcDepth( tex0.xyz ) );
gl_FragDepth = 0.5 + 0.5 * isect.depth;
}

View File

@@ -21,7 +21,7 @@ const float TAU = PI * 2.0;
layout (location = 3) out vec4 fragWTF;
#endif
in vec4 vPosition;
in vec4 vPositionWithoutModel;
#ifdef SHADOW
out vec4 fragColor;
@@ -115,7 +115,7 @@ void main() {
vec3 rayOri = divideByW( inversePVM * vec4( p, 0.0, 1.0 ) );
vec3 farPos = divideByW( inversePVM * vec4( p, 1.0, 1.0 ) );
vec3 rayDir = normalize( farPos - rayOri );
float rayLen = length( vPosition.xyz - cameraPos );
float rayLen = length( vPositionWithoutModel.xyz - rayOri );
vec3 rayPos = rayOri + rayDir * rayLen;
float dist;
@@ -132,7 +132,7 @@ void main() {
discard;
}
vec3 modelNormal = ( normalMatrix * vec4( normalFunc( rayPos, 1E-2 ), 1.0 ) ).xyz;
vec3 modelNormal = ( normalMatrix * vec4( normalFunc( rayPos, 1E-3 ), 1.0 ) ).xyz;
vec4 modelPos = modelMatrix * vec4( rayPos, 1.0 );
vec4 projPos = projectionMatrix * viewMatrix * modelPos; // terrible
@@ -143,7 +143,7 @@ void main() {
fragPosition = vec4( modelPos.xyz, depth );
fragNormal = vec4( modelNormal, 1.0 );
fragColor = vec4( 0.4, 0.7, 0.9, 1.0 );
fragWTF = vec4( vec3( 0.9, 0.2, 0.0 ), MTL_PBR );
fragWTF = vec4( vec3( 0.9, 0.7, 0.0 ), MTL_PBR );
#endif
#ifdef SHADOW