mirror of
https://github.com/FMS-Cat/condition.git
synced 2025-08-08 06:56:31 +02:00
size: mangler hell
This commit is contained in:
17
README.md
17
README.md
@@ -2,9 +2,24 @@
|
|||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
- You will need [`shader_minifier.exe`](https://github.com/laurentlb/Shader_Minifier) in your PATH
|
- You will need these stuff in your PATH:
|
||||||
|
- [`shader_minifier.exe`](https://github.com/laurentlb/Shader_Minifier)
|
||||||
|
- [`jsexe.exe`](https://www.pouet.net/)
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
yarn
|
yarn
|
||||||
yarn build
|
yarn build
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Minification
|
||||||
|
|
||||||
|
[terser's](https://terser.org/docs/api-reference.html) mangler is spicy
|
||||||
|
you'll die instantly if you access to object properties using a string identifier
|
||||||
|
see `webpack.config.js` and `src/automaton-fxs/fxDefinitions.ts` for the funny jokes
|
||||||
|
|
||||||
|
jsexe is good
|
||||||
|
note that it cannot parse nowadays ecmascript though
|
||||||
|
|
||||||
|
shader minifier is way too spicy so I made a [separate document](./shader-minifier-tips.md)
|
||||||
|
|
||||||
|
libopus is cheating
|
||||||
|
@@ -5,7 +5,10 @@
|
|||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "webpack-cli serve --mode development",
|
"dev": "webpack-cli serve --mode development",
|
||||||
"build": "webpack --mode production && ruby pnginator.rb ./dist/bundle.js ./dist/out.png.html"
|
"build": "yarn build-js && yarn build-png",
|
||||||
|
"build-js": "webpack --mode production",
|
||||||
|
"build-png": "jsexe -cn -po ./dist/bundle.js ./dist/out.png.html",
|
||||||
|
"h": "start http://localhost:8081/out.png.html && http-server ./dist"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@fms-cat/automaton": "^4.1.0",
|
"@fms-cat/automaton": "^4.1.0",
|
||||||
|
106
pnginator.rb
106
pnginator.rb
@@ -1,106 +0,0 @@
|
|||||||
#!/usr/bin/env ruby -w
|
|
||||||
|
|
||||||
# pnginator.rb: pack a .js file into a PNG image with an HTML payload;
|
|
||||||
# when saved with an .html extension and opened in a browser, the HTML extracts and executes
|
|
||||||
# the javascript.
|
|
||||||
|
|
||||||
# Usage: ruby pnginator.rb input.js output.png.html
|
|
||||||
|
|
||||||
# By Gasman <http://matt.west.co.tt/>
|
|
||||||
# from an original idea by Daeken: http://daeken.com/superpacking-js-demos
|
|
||||||
|
|
||||||
|
|
||||||
MAX_WIDTH = 4096
|
|
||||||
USE_PNGOUT = true
|
|
||||||
|
|
||||||
require 'zlib'
|
|
||||||
require 'tempfile'
|
|
||||||
|
|
||||||
input_filename, output_filename = ARGV
|
|
||||||
|
|
||||||
f = File.open(input_filename, 'rb')
|
|
||||||
js = f.read
|
|
||||||
f.close
|
|
||||||
|
|
||||||
if js.length < MAX_WIDTH
|
|
||||||
# js fits onto one pixel line
|
|
||||||
js += "\x00"
|
|
||||||
scanlines = [js]
|
|
||||||
width = js.length
|
|
||||||
height = 1
|
|
||||||
|
|
||||||
# Daeken's single-pixel-row bootstrap (requires js string to be reversed)
|
|
||||||
# (edit by Gasman: change eval to (1,eval) to force global evaluation and avoid massive slowdown)
|
|
||||||
# html = "<canvas id=q><img onload=for(p=q.width=#{width},(c=q.getContext('2d')).drawImage(this,0,e='');p;)e+=String.fromCharCode(c.getImageData(--p,0,1,1).data[0]);(1,eval)(e) src=#>"
|
|
||||||
|
|
||||||
# p01's single-pixel-row bootstrap (requires an 0x00 end marker on the js string)
|
|
||||||
# (edit by Gasman: move drawImage out of getImageData params (it returns undef, which is invalid) and change eval to (1,eval) to force global evaluation)
|
|
||||||
html = "<canvas id=c><img onload=with(c.getContext('2d'))for(p=e='';drawImage(this,p--,0),t=getImageData(0,0,1,1).data[0];)e+=String.fromCharCode(t);(1,eval)(e) src=#>"
|
|
||||||
else
|
|
||||||
js = "\x00" + js
|
|
||||||
width = MAX_WIDTH
|
|
||||||
# split js into scanlines of 'width' pixels; pad the last one with whitespace
|
|
||||||
scanlines = js.scan(/.{1,#{width}}/m).collect{|line| line.ljust(width, "\x00")}
|
|
||||||
height = scanlines.length
|
|
||||||
|
|
||||||
# p01's multiple-pixel-row bootstrap (requires a dummy first byte on the js string)
|
|
||||||
# (edit by Gasman: set explicit canvas width to support widths above 300; move drawImage out of getImageData params; change eval to (1,eval) to force global evaluation)
|
|
||||||
html = "<canvas id=c><img onload=for(w=c.width=#{width},a=c.getContext('2d'),a.drawImage(this,p=0,0),e='',d=a.getImageData(0,0,w,#{height}).data;t=d[p+=4];)e+=String.fromCharCode(t);(1,eval)(e) src=#>"
|
|
||||||
end
|
|
||||||
|
|
||||||
# prepend each scanline with 0x00 to indicate 'no filtering', then concat into one string
|
|
||||||
image_data = scanlines.collect{|line| "\x00" + line}.join
|
|
||||||
idat_chunk = Zlib::Deflate.deflate(image_data, 9) # 9 = maximum compression
|
|
||||||
|
|
||||||
def png_chunk(signature, data)
|
|
||||||
[data.length, signature, data, Zlib::crc32(signature + data)].pack("NA4A*N")
|
|
||||||
end
|
|
||||||
|
|
||||||
if USE_PNGOUT
|
|
||||||
# Create a valid (no format hacks) .png file to pass to pngout
|
|
||||||
f = Tempfile.open(['pnginator', '.png'])
|
|
||||||
|
|
||||||
begin
|
|
||||||
f.write("\x89PNG\x0d\x0a\x1a\x0a") # PNG file header
|
|
||||||
f.write(png_chunk("IHDR", [width, height, 8, 0, 0, 0, 0].pack("NNccccc")))
|
|
||||||
f.write(png_chunk("IDAT", idat_chunk))
|
|
||||||
f.write(png_chunk("IEND", ''))
|
|
||||||
f.close
|
|
||||||
|
|
||||||
system("pngout", f.path, "-c0", "-y")
|
|
||||||
|
|
||||||
# read file back and extract the IDAT chunk
|
|
||||||
f.open
|
|
||||||
f.read(8)
|
|
||||||
while !f.eof?
|
|
||||||
length, signature = f.read(8).unpack("NA4")
|
|
||||||
data = f.read(length)
|
|
||||||
crc = f.read(4)
|
|
||||||
|
|
||||||
if signature == "IDAT"
|
|
||||||
idat_chunk = data
|
|
||||||
break
|
|
||||||
end
|
|
||||||
end
|
|
||||||
ensure
|
|
||||||
f.close
|
|
||||||
f.unlink
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
File.open(output_filename, 'wb') do |f|
|
|
||||||
f.write("\x89PNG\x0d\x0a\x1a\x0a") # PNG file header
|
|
||||||
|
|
||||||
f.write(png_chunk("IHDR", [width, height, 8, 0, 0, 0, 0].pack("NNccccc")))
|
|
||||||
|
|
||||||
# a custom chunk containing the HTML payload; stated chunk length is 4 less than the actual length,
|
|
||||||
# leaving the final 4 bytes to take the place of the checksum
|
|
||||||
f.write([html.length - 4, "jawh", html].pack("NA4A*"))
|
|
||||||
|
|
||||||
# can safely omit the checksum of the IDAT chunk
|
|
||||||
# f.write([idat_chunk.length, "IDAT", idat_chunk, Zlib::crc32("IDAT" + idat_chunk)].pack("NA4A*N"))
|
|
||||||
f.write([idat_chunk.length, "IDAT", idat_chunk].pack("NA4A*"))
|
|
||||||
|
|
||||||
# can safely omit the IEND chunk
|
|
||||||
# f.write([0, "IEND", "", Zlib::crc32("IEND")].pack("NA4A*N"))
|
|
||||||
end
|
|
@@ -1,3 +0,0 @@
|
|||||||
export { sine, hermitePatch } from '@fms-cat/automaton-fxs';
|
|
||||||
export { repeat } from './repeat';
|
|
||||||
export { transpose } from './transpose';
|
|
14
src/automaton-fxs/fxDefinitions.ts
Normal file
14
src/automaton-fxs/fxDefinitions.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { sine } from './sine';
|
||||||
|
import { repeat } from './repeat';
|
||||||
|
import { hermitePatch } from './hermitePatch';
|
||||||
|
import { transpose } from './transpose';
|
||||||
|
|
||||||
|
// quotes! prevent fx names from being mangled
|
||||||
|
const fxDefinitions = {
|
||||||
|
'sine': sine,
|
||||||
|
'repeat': repeat,
|
||||||
|
'hermitePatch': hermitePatch,
|
||||||
|
'transpose': transpose,
|
||||||
|
};
|
||||||
|
|
||||||
|
export { fxDefinitions };
|
34
src/automaton-fxs/hermitePatch.ts
Normal file
34
src/automaton-fxs/hermitePatch.ts
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import type { FxDefinition } from '@fms-cat/automaton';
|
||||||
|
|
||||||
|
export const hermitePatch: FxDefinition = {
|
||||||
|
func( context ) {
|
||||||
|
if ( context.init ) {
|
||||||
|
const dt = context.deltaTime;
|
||||||
|
|
||||||
|
const v0 = context.getValue( context.t0 );
|
||||||
|
const dv0 = v0 - context.getValue( context.t0 - dt );
|
||||||
|
const v1 = context.getValue( context.t1 );
|
||||||
|
const dv1 = v1 - context.getValue( context.t1 - dt );
|
||||||
|
|
||||||
|
context.state.p0 = v0;
|
||||||
|
context.state.m0 = dv0 / dt * context.length;
|
||||||
|
context.state.p1 = v1;
|
||||||
|
context.state.m1 = dv1 / dt * context.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { p0, m0, p1, m1 } = context.state;
|
||||||
|
const t = context.progress;
|
||||||
|
|
||||||
|
return (
|
||||||
|
( ( 2.0 * t - 3.0 ) * t * t + 1.0 ) * p0 +
|
||||||
|
( ( ( t - 2.0 ) * t + 1.0 ) * t ) * m0 +
|
||||||
|
( ( -2.0 * t + 3.0 ) * t * t ) * p1 +
|
||||||
|
( ( t - 1.0 ) * t * t ) * m1
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
hermitePatch.name = 'Hermite Patch';
|
||||||
|
hermitePatch.description = 'Patch a curve using hermite spline.';
|
||||||
|
}
|
@@ -1,11 +1,6 @@
|
|||||||
import type { FxDefinition } from '@fms-cat/automaton';
|
import type { FxDefinition } from '@fms-cat/automaton';
|
||||||
|
|
||||||
export const repeat: FxDefinition = {
|
export const repeat: FxDefinition = {
|
||||||
name: 'Repeat',
|
|
||||||
description: 'Repeat a section of the curve.',
|
|
||||||
params: {
|
|
||||||
interval: { name: 'Interval', type: 'float', default: 1.0, min: 0.0 },
|
|
||||||
},
|
|
||||||
func( context ) {
|
func( context ) {
|
||||||
if ( context.index === context.i1 ) {
|
if ( context.index === context.i1 ) {
|
||||||
context.setShouldNotInterpolate( true );
|
context.setShouldNotInterpolate( true );
|
||||||
@@ -20,3 +15,11 @@ export const repeat: FxDefinition = {
|
|||||||
return context.getValue( context.t0 + context.elapsed % context.params.interval );
|
return context.getValue( context.t0 + context.elapsed % context.params.interval );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
repeat.name = 'Repeat';
|
||||||
|
repeat.description = 'Repeat a section of the curve.';
|
||||||
|
repeat.params = {
|
||||||
|
interval: { name: 'Interval', type: 'float', default: 1.0, min: 0.0 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
21
src/automaton-fxs/sine.ts
Normal file
21
src/automaton-fxs/sine.ts
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
import type { FxDefinition } from '@fms-cat/automaton';
|
||||||
|
|
||||||
|
const TAU = Math.PI * 2.0;
|
||||||
|
|
||||||
|
export const sine: FxDefinition = {
|
||||||
|
func( context ) {
|
||||||
|
const v = context.value;
|
||||||
|
const p = context.elapsed * context.params.freq + context.params.offset;
|
||||||
|
return v + context.params.amp * Math.sin( p * TAU );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
sine.name = 'Sinewave';
|
||||||
|
sine.description = 'Overlay a sinewave to the curve.';
|
||||||
|
sine.params = {
|
||||||
|
amp: { name: 'Amp', type: 'float', default: 0.1 },
|
||||||
|
freq: { name: 'Frequency', type: 'float', default: 5.0 },
|
||||||
|
offset: { name: 'Offset', type: 'float', default: 0.0, min: 0.0, max: 1.0 }
|
||||||
|
};
|
||||||
|
}
|
@@ -1,9 +1,6 @@
|
|||||||
import type { FxDefinition } from '@fms-cat/automaton';
|
import type { FxDefinition } from '@fms-cat/automaton';
|
||||||
|
|
||||||
export const transpose: FxDefinition = {
|
export const transpose: FxDefinition = {
|
||||||
params: {
|
|
||||||
note: { name: 'Note', type: 'float', default: 0.0 }
|
|
||||||
},
|
|
||||||
func( context ) {
|
func( context ) {
|
||||||
if ( context.init ) {
|
if ( context.init ) {
|
||||||
context.state.v0 = context.value;
|
context.state.v0 = context.value;
|
||||||
@@ -17,3 +14,11 @@ export const transpose: FxDefinition = {
|
|||||||
return v0 + ( context.value - v0 ) * Math.pow( 2.0, context.params.note / 12.0 );
|
return v0 + ( context.value - v0 ) * Math.pow( 2.0, context.params.note / 12.0 );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if ( process.env.DEV ) {
|
||||||
|
transpose.name = 'Transpose';
|
||||||
|
transpose.description = 'I probably don\'t need it...';
|
||||||
|
transpose.params = {
|
||||||
|
note: { name: 'Note', type: 'float', default: 0.0 },
|
||||||
|
};
|
||||||
|
}
|
||||||
|
File diff suppressed because one or more lines are too long
@@ -5,5 +5,6 @@ export const
|
|||||||
AO_RESOLUTION_RATIO = 1.0,
|
AO_RESOLUTION_RATIO = 1.0,
|
||||||
RESOLUTION = [ 1280, 720 ],
|
RESOLUTION = [ 1280, 720 ],
|
||||||
MUSIC_BPM = 180,
|
MUSIC_BPM = 180,
|
||||||
|
START_POSITION = 36,
|
||||||
MUSIC_BUFFER_LENGTH = 4096,
|
MUSIC_BUFFER_LENGTH = 4096,
|
||||||
MUSIC_AUTOMATON_TEXTURE_HEIGHT = 16;
|
MUSIC_AUTOMATON_TEXTURE_HEIGHT = 16;
|
||||||
|
@@ -97,9 +97,7 @@ export class CameraEntity extends Entity {
|
|||||||
quadVert,
|
quadVert,
|
||||||
shadingFrag,
|
shadingFrag,
|
||||||
{
|
{
|
||||||
defines: {
|
defines: iLight === 0 ? [ 'IS_FIRST_LIGHT' ] : [],
|
||||||
IS_FIRST_LIGHT: iLight === 0 ? 'true' : undefined
|
|
||||||
},
|
|
||||||
initOptions: { geometry: quadGeometry, target: dummyRenderTarget },
|
initOptions: { geometry: quadGeometry, target: dummyRenderTarget },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@@ -102,32 +102,34 @@ export class Condition extends Entity {
|
|||||||
geometry.primcount = 12 * 16;
|
geometry.primcount = 12 * 16;
|
||||||
|
|
||||||
// -- create materials -------------------------------------------------------------------------
|
// -- create materials -------------------------------------------------------------------------
|
||||||
const materials = {
|
const forward = new Material(
|
||||||
forward: new Material(
|
conditionVert,
|
||||||
conditionVert,
|
conditionFrag,
|
||||||
conditionFrag,
|
{
|
||||||
{
|
defines: [ 'FORWARD 1' ],
|
||||||
defines: { 'FORWARD': 'true' },
|
initOptions: { geometry, target: dummyRenderTarget },
|
||||||
initOptions: { geometry, target: dummyRenderTarget },
|
},
|
||||||
},
|
);
|
||||||
),
|
|
||||||
deferred: new Material(
|
const deferred = new Material(
|
||||||
conditionVert,
|
conditionVert,
|
||||||
conditionFrag,
|
conditionFrag,
|
||||||
{
|
{
|
||||||
defines: { 'DEFERRED': 'true' },
|
defines: [ 'DEFERRED 1' ],
|
||||||
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
shadow: new Material(
|
|
||||||
conditionVert,
|
const depth = new Material(
|
||||||
conditionFrag,
|
conditionVert,
|
||||||
{
|
conditionFrag,
|
||||||
defines: { 'SHADOW': 'true' },
|
{
|
||||||
initOptions: { geometry, target: dummyRenderTarget },
|
defines: [ 'SHADOW 1' ],
|
||||||
},
|
initOptions: { geometry, target: dummyRenderTarget },
|
||||||
),
|
},
|
||||||
};
|
);
|
||||||
|
|
||||||
|
const materials = { forward, deferred, depth };
|
||||||
|
|
||||||
objectValuesMap( materials, ( material ) => {
|
objectValuesMap( materials, ( material ) => {
|
||||||
material.addUniformTexture( 'samplerSvg', texture );
|
material.addUniformTexture( 'samplerSvg', texture );
|
||||||
@@ -149,9 +151,9 @@ export class Condition extends Entity {
|
|||||||
'../shaders/condition.frag',
|
'../shaders/condition.frag',
|
||||||
],
|
],
|
||||||
() => {
|
() => {
|
||||||
materials.forward.replaceShader( conditionVert, conditionFrag );
|
forward.replaceShader( conditionVert, conditionFrag );
|
||||||
materials.deferred.replaceShader( conditionVert, conditionFrag );
|
deferred.replaceShader( conditionVert, conditionFrag );
|
||||||
materials.shadow.replaceShader( conditionVert, conditionFrag );
|
depth.replaceShader( conditionVert, conditionFrag );
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,132 +0,0 @@
|
|||||||
import { Mesh } from '../heck/components/Mesh';
|
|
||||||
import { Entity } from '../heck/Entity';
|
|
||||||
import { Geometry } from '../heck/Geometry';
|
|
||||||
import { Material } from '../heck/Material';
|
|
||||||
import svgVert from '../shaders/svg.vert';
|
|
||||||
import conditionCharFrag from '../shaders/condition-char.frag';
|
|
||||||
import { gl, glCat } from '../globals/canvas';
|
|
||||||
import { Vector3 } from '@fms-cat/experimental';
|
|
||||||
import { GLCatTexture } from '@fms-cat/glcat-ts';
|
|
||||||
import { auto } from '../globals/automaton';
|
|
||||||
import { dummyRenderTargetFourDrawBuffers, dummyRenderTarget } from '../globals/dummyRenderTarget';
|
|
||||||
|
|
||||||
const POINTS_MAX = 256;
|
|
||||||
|
|
||||||
interface SVGTestOptions {
|
|
||||||
table: GLCatTexture;
|
|
||||||
pos: number;
|
|
||||||
i: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ConditionChar extends Entity {
|
|
||||||
public constructor( { table, pos, i }: SVGTestOptions ) {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.transform.position = this.transform.position.add( new Vector3( [ 2 * pos, 0, 0 ] ) );
|
|
||||||
|
|
||||||
// -- create buffers ---------------------------------------------------------------------------
|
|
||||||
const arrayPos = [];
|
|
||||||
const arrayInd = [];
|
|
||||||
|
|
||||||
for ( let i = 0; i < POINTS_MAX; i ++ ) {
|
|
||||||
const x = i / POINTS_MAX;
|
|
||||||
arrayPos.push( x, 0, x, 1, x, 2 );
|
|
||||||
|
|
||||||
for ( let j = 0; j < 3; j ++ ) {
|
|
||||||
const j1 = ( j + 1 ) % 3;
|
|
||||||
arrayInd.push(
|
|
||||||
i * 3 + j,
|
|
||||||
i * 3 + 3 + j,
|
|
||||||
i * 3 + 3 + j1,
|
|
||||||
i * 3 + j,
|
|
||||||
i * 3 + 3 + j1,
|
|
||||||
i * 3 + j1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
arrayPos.push( 1, 0, 1, 1, 1, 2 );
|
|
||||||
|
|
||||||
const bufferPos = glCat.createBuffer();
|
|
||||||
bufferPos.setVertexbuffer( new Float32Array( arrayPos ) );
|
|
||||||
|
|
||||||
const bufferInd = glCat.createBuffer();
|
|
||||||
bufferInd.setIndexbuffer( new Uint16Array( arrayInd ) );
|
|
||||||
|
|
||||||
// -- create geometry --------------------------------------------------------------------------
|
|
||||||
const geometry = new Geometry();
|
|
||||||
|
|
||||||
geometry.vao.bindVertexbuffer( bufferPos, 0, 2 );
|
|
||||||
geometry.vao.bindIndexbuffer( bufferInd );
|
|
||||||
|
|
||||||
geometry.count = 18 * POINTS_MAX;
|
|
||||||
geometry.mode = gl.TRIANGLES;
|
|
||||||
geometry.indexType = gl.UNSIGNED_SHORT;
|
|
||||||
|
|
||||||
// -- create materials -------------------------------------------------------------------------
|
|
||||||
const materials = {
|
|
||||||
forward: new Material(
|
|
||||||
svgVert,
|
|
||||||
conditionCharFrag,
|
|
||||||
{
|
|
||||||
defines: { 'FORWARD': 'true' },
|
|
||||||
initOptions: { geometry, target: dummyRenderTarget },
|
|
||||||
},
|
|
||||||
),
|
|
||||||
deferred: new Material(
|
|
||||||
svgVert,
|
|
||||||
conditionCharFrag,
|
|
||||||
{
|
|
||||||
defines: { 'DEFERRED': 'true' },
|
|
||||||
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
|
||||||
},
|
|
||||||
),
|
|
||||||
shadow: new Material(
|
|
||||||
svgVert,
|
|
||||||
conditionCharFrag,
|
|
||||||
{
|
|
||||||
defines: { 'SHADOW': 'true' },
|
|
||||||
initOptions: { geometry, target: dummyRenderTarget },
|
|
||||||
},
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
|
||||||
if ( module.hot ) {
|
|
||||||
module.hot.accept(
|
|
||||||
[
|
|
||||||
'../shaders/svg.vert',
|
|
||||||
'../shaders/condition-char.frag',
|
|
||||||
],
|
|
||||||
() => {
|
|
||||||
materials.forward.replaceShader( svgVert, conditionCharFrag );
|
|
||||||
materials.deferred.replaceShader( svgVert, conditionCharFrag );
|
|
||||||
materials.shadow.replaceShader( svgVert, conditionCharFrag );
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// -- create meshes ----------------------------------------------------------------------------
|
|
||||||
const mesh = new Mesh( {
|
|
||||||
geometry,
|
|
||||||
materials,
|
|
||||||
name: process.env.DEV && `ConditionChar/mesh${ i }`,
|
|
||||||
} );
|
|
||||||
this.components.push( mesh );
|
|
||||||
|
|
||||||
// -- material uniforms ------------------------------------------------------------------------
|
|
||||||
for ( const material of Object.values( materials ) ) {
|
|
||||||
material.addUniform( 'svgi', '1f', i );
|
|
||||||
material.addUniformTexture( 'samplerSvg', table );
|
|
||||||
|
|
||||||
auto( 'Condition/phaseOffset', ( { value } ) => {
|
|
||||||
material.addUniform( 'phaseOffset', '1f', value );
|
|
||||||
} );
|
|
||||||
|
|
||||||
auto( 'Condition/phaseWidth', ( { value } ) => {
|
|
||||||
material.addUniform( 'phaseWidth', '1f', value );
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -54,21 +54,22 @@ export class Cube extends Entity {
|
|||||||
geometry.primcount = PRIMCOUNT;
|
geometry.primcount = PRIMCOUNT;
|
||||||
|
|
||||||
// -- materials --------------------------------------------------------------------------------
|
// -- materials --------------------------------------------------------------------------------
|
||||||
const materials = {
|
const deferred = new Material(
|
||||||
deferred: new Material(
|
|
||||||
cubeVert,
|
cubeVert,
|
||||||
cubeFrag,
|
cubeFrag,
|
||||||
{
|
{
|
||||||
defines: { 'DEFERRED': 'true' },
|
defines: [ 'DEFERRED 1' ],
|
||||||
initOptions: { geometry: quadGeometry, target: dummyRenderTargetFourDrawBuffers },
|
initOptions: { geometry: quadGeometry, target: dummyRenderTargetFourDrawBuffers },
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
shadow: new Material(
|
|
||||||
|
const depth = new Material(
|
||||||
cubeVert,
|
cubeVert,
|
||||||
depthFrag,
|
depthFrag,
|
||||||
{ initOptions: { geometry: quadGeometry, target: dummyRenderTarget } },
|
{ initOptions: { geometry: quadGeometry, target: dummyRenderTarget } },
|
||||||
),
|
);
|
||||||
};
|
|
||||||
|
const materials = { deferred, depth };
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
if ( module.hot ) {
|
if ( module.hot ) {
|
||||||
@@ -78,8 +79,8 @@ export class Cube extends Entity {
|
|||||||
'../shaders/cube.frag',
|
'../shaders/cube.frag',
|
||||||
],
|
],
|
||||||
() => {
|
() => {
|
||||||
materials.deferred.replaceShader( cubeVert, cubeFrag );
|
deferred.replaceShader( cubeVert, cubeFrag );
|
||||||
materials.shadow.replaceShader( cubeVert, depthFrag );
|
depth.replaceShader( cubeVert, depthFrag );
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -11,6 +11,7 @@ import { gl, glCat } from '../globals/canvas';
|
|||||||
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
||||||
import { quadGeometry } from '../globals/quadGeometry';
|
import { quadGeometry } from '../globals/quadGeometry';
|
||||||
import { dummyRenderTargetFourDrawBuffers, dummyRenderTarget } from '../globals/dummyRenderTarget';
|
import { dummyRenderTargetFourDrawBuffers, dummyRenderTarget } from '../globals/dummyRenderTarget';
|
||||||
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
|
|
||||||
const PARTICLES_SQRT = 8;
|
const PARTICLES_SQRT = 8;
|
||||||
const PARTICLES = PARTICLES_SQRT * PARTICLES_SQRT;
|
const PARTICLES = PARTICLES_SQRT * PARTICLES_SQRT;
|
||||||
@@ -72,7 +73,7 @@ export class FlickyParticles extends Entity {
|
|||||||
flickyParticleRenderVert,
|
flickyParticleRenderVert,
|
||||||
flickyParticleRenderFrag,
|
flickyParticleRenderFrag,
|
||||||
{
|
{
|
||||||
defines: { 'FORWARD': 'true' },
|
defines: [ 'FORWARD 1' ],
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTarget },
|
initOptions: { geometry: geometryRender, target: dummyRenderTarget },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -81,7 +82,7 @@ export class FlickyParticles extends Entity {
|
|||||||
flickyParticleRenderVert,
|
flickyParticleRenderVert,
|
||||||
flickyParticleRenderFrag,
|
flickyParticleRenderFrag,
|
||||||
{
|
{
|
||||||
defines: { 'DEFERRED': 'true' },
|
defines: [ 'DEFERRED 1' ],
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -90,16 +91,16 @@ export class FlickyParticles extends Entity {
|
|||||||
flickyParticleRenderVert,
|
flickyParticleRenderVert,
|
||||||
flickyParticleRenderFrag,
|
flickyParticleRenderFrag,
|
||||||
{
|
{
|
||||||
defines: { 'SHADOW': 'true' },
|
defines: [ 'SHADOW 1' ],
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTarget },
|
initOptions: { geometry: geometryRender, target: dummyRenderTarget },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const materialsRender = { forward, deferred, shadow };
|
const materialsRender = { forward, deferred, shadow };
|
||||||
|
|
||||||
for ( const material of Object.values( materialsRender ) ) {
|
objectValuesMap( materialsRender, ( material ) => {
|
||||||
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
||||||
}
|
} );
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
if ( module.hot ) {
|
if ( module.hot ) {
|
||||||
|
@@ -7,6 +7,7 @@ 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';
|
||||||
import { gl } from '../globals/canvas';
|
import { gl } from '../globals/canvas';
|
||||||
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
|
|
||||||
export interface GPUParticlesOptions {
|
export interface GPUParticlesOptions {
|
||||||
materialCompute: Material;
|
materialCompute: Material;
|
||||||
@@ -62,14 +63,14 @@ export class GPUParticles extends Entity {
|
|||||||
name: process.env.DEV && `${ namePrefix }/meshRender`,
|
name: process.env.DEV && `${ namePrefix }/meshRender`,
|
||||||
} );
|
} );
|
||||||
|
|
||||||
for ( const material of Object.values( materialsRender ) ) {
|
objectValuesMap( materialsRender, ( material ) => {
|
||||||
material?.addUniform(
|
material?.addUniform(
|
||||||
'resolutionCompute',
|
'resolutionCompute',
|
||||||
'2f',
|
'2f',
|
||||||
computeWidth,
|
computeWidth,
|
||||||
computeHeight
|
computeHeight
|
||||||
);
|
);
|
||||||
}
|
} );
|
||||||
|
|
||||||
// -- swapper ----------------------------------------------------------------------------------
|
// -- swapper ----------------------------------------------------------------------------------
|
||||||
this.components.push( new Lambda( {
|
this.components.push( new Lambda( {
|
||||||
@@ -84,12 +85,12 @@ export class GPUParticles extends Entity {
|
|||||||
swapCompute.i.getTexture( attachment )
|
swapCompute.i.getTexture( attachment )
|
||||||
);
|
);
|
||||||
|
|
||||||
for ( const material of Object.values( materialsRender ) ) {
|
objectValuesMap( materialsRender, ( material ) => {
|
||||||
material?.addUniformTexture(
|
material?.addUniformTexture(
|
||||||
`samplerCompute${ i }`,
|
`samplerCompute${ i }`,
|
||||||
swapCompute.o.getTexture( attachment )
|
swapCompute.o.getTexture( attachment )
|
||||||
);
|
);
|
||||||
}
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
quadCompute.target = swapCompute.o;
|
quadCompute.target = swapCompute.o;
|
||||||
|
@@ -58,7 +58,7 @@ export class LightEntity extends Entity {
|
|||||||
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',
|
materialTag: 'depth',
|
||||||
} );
|
} );
|
||||||
this.camera.clear = [ 1.0, 1.0, 1.0, 1.0 ];
|
this.camera.clear = [ 1.0, 1.0, 1.0, 1.0 ];
|
||||||
this.components.push( this.camera );
|
this.components.push( this.camera );
|
||||||
|
@@ -10,6 +10,7 @@ import { randomTexture, randomTextureStatic } from '../globals/randomTexture';
|
|||||||
import { auto } from '../globals/automaton';
|
import { auto } from '../globals/automaton';
|
||||||
import { dummyRenderTargetFourDrawBuffers, dummyRenderTarget } from '../globals/dummyRenderTarget';
|
import { dummyRenderTargetFourDrawBuffers, dummyRenderTarget } from '../globals/dummyRenderTarget';
|
||||||
import { genOctahedron } from '../geometries/genOctahedron';
|
import { genOctahedron } from '../geometries/genOctahedron';
|
||||||
|
import { objectValuesMap } from '../utils/objectEntriesMap';
|
||||||
|
|
||||||
export class Raymarcher extends Entity {
|
export class Raymarcher extends Entity {
|
||||||
public constructor() {
|
public constructor() {
|
||||||
@@ -31,45 +32,46 @@ export class Raymarcher extends Entity {
|
|||||||
geometry.indexType = octahedron.indexType;
|
geometry.indexType = octahedron.indexType;
|
||||||
|
|
||||||
// -- materials --------------------------------------------------------------------------------
|
// -- materials --------------------------------------------------------------------------------
|
||||||
const materials = {
|
const deferred = new Material(
|
||||||
deferred: new Material(
|
raymarchObjectVert,
|
||||||
raymarchObjectVert,
|
raymarcherFrag,
|
||||||
raymarcherFrag,
|
{
|
||||||
{
|
defines: [ 'DEFERRED 1' ],
|
||||||
defines: { 'DEFERRED': 'true' },
|
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
||||||
initOptions: { geometry, target: dummyRenderTargetFourDrawBuffers },
|
},
|
||||||
},
|
);
|
||||||
),
|
|
||||||
shadow: new Material(
|
const depth = new Material(
|
||||||
raymarchObjectVert,
|
raymarchObjectVert,
|
||||||
raymarcherFrag,
|
raymarcherFrag,
|
||||||
{
|
{
|
||||||
defines: { 'SHADOW': 'true' },
|
defines: [ 'SHADOW 1' ],
|
||||||
initOptions: { geometry, target: dummyRenderTarget }
|
initOptions: { geometry, target: dummyRenderTarget }
|
||||||
},
|
},
|
||||||
),
|
);
|
||||||
};
|
|
||||||
|
const materials = { deferred, depth };
|
||||||
|
|
||||||
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', () => {
|
||||||
materials.deferred.replaceShader( raymarchObjectVert, raymarcherFrag );
|
deferred.replaceShader( raymarchObjectVert, raymarcherFrag );
|
||||||
materials.shadow.replaceShader( raymarchObjectVert, raymarcherFrag );
|
depth.replaceShader( raymarchObjectVert, raymarcherFrag );
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for ( const material of Object.values( materials ) ) {
|
objectValuesMap( materials, ( material ) => {
|
||||||
material.addUniform( 'range', '4f', -1.0, -1.0, 1.0, 1.0 );
|
material.addUniform( 'range', '4f', -1.0, -1.0, 1.0, 1.0 );
|
||||||
|
|
||||||
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
material.addUniformTexture( 'samplerRandom', randomTexture.texture );
|
||||||
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
material.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
||||||
}
|
} );
|
||||||
|
|
||||||
// -- updater ----------------------------------------------------------------------------------
|
// -- updater ----------------------------------------------------------------------------------
|
||||||
this.components.push( new Lambda( {
|
this.components.push( new Lambda( {
|
||||||
onDraw: ( event ) => {
|
onDraw: ( event ) => {
|
||||||
for ( const material of Object.values( materials ) ) {
|
objectValuesMap( materials, ( material ) => {
|
||||||
material.addUniform(
|
material.addUniform(
|
||||||
'cameraNearFar',
|
'cameraNearFar',
|
||||||
'2f',
|
'2f',
|
||||||
@@ -90,15 +92,15 @@ export class Raymarcher extends Entity {
|
|||||||
material.addUniform( 'deformAmp', '1f', auto( 'Music/NEURO_WUB_AMP' ) );
|
material.addUniform( 'deformAmp', '1f', auto( 'Music/NEURO_WUB_AMP' ) );
|
||||||
material.addUniform( 'deformFreq', '1f', auto( 'Music/NEURO_WUB_FREQ' ) + auto( 'Music/NEURO_DETUNE' ) );
|
material.addUniform( 'deformFreq', '1f', auto( 'Music/NEURO_WUB_FREQ' ) + auto( 'Music/NEURO_DETUNE' ) );
|
||||||
material.addUniform( 'deformTime', '1f', auto( 'Music/NEURO_TIME' ) );
|
material.addUniform( 'deformTime', '1f', auto( 'Music/NEURO_TIME' ) );
|
||||||
}
|
} );
|
||||||
},
|
},
|
||||||
name: process.env.DEV && 'Raymarcher/updater',
|
name: process.env.DEV && 'Raymarcher/updater',
|
||||||
} ) );
|
} ) );
|
||||||
|
|
||||||
// -- mesh -------------------------------------------------------------------------------------
|
// -- mesh -------------------------------------------------------------------------------------
|
||||||
const mesh = new Mesh( {
|
const mesh = new Mesh( {
|
||||||
geometry: geometry,
|
geometry,
|
||||||
materials: materials,
|
materials,
|
||||||
name: process.env.DEV && 'Raymarcher/mesh',
|
name: process.env.DEV && 'Raymarcher/mesh',
|
||||||
} );
|
} );
|
||||||
mesh.cull = MeshCull.None;
|
mesh.cull = MeshCull.None;
|
||||||
|
@@ -47,28 +47,34 @@ export class Rings extends Entity {
|
|||||||
geometry.primcount = PRIMCOUNT;
|
geometry.primcount = PRIMCOUNT;
|
||||||
|
|
||||||
// -- materials --------------------------------------------------------------------------------
|
// -- materials --------------------------------------------------------------------------------
|
||||||
|
const forward = new Material(
|
||||||
|
ringsVert,
|
||||||
|
ringsFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'FORWARD 1' ],
|
||||||
|
initOptions: { geometry, target: dummyRenderTarget },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const deferred = new Material(
|
||||||
|
ringsVert,
|
||||||
|
ringsFrag,
|
||||||
|
{
|
||||||
|
defines: [ 'DEFERRED 1' ],
|
||||||
|
initOptions: { geometry, target: dummyRenderTarget },
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const depth = new Material(
|
||||||
|
ringsVert,
|
||||||
|
depthFrag,
|
||||||
|
{ initOptions: { geometry, target: dummyRenderTarget } },
|
||||||
|
);
|
||||||
|
|
||||||
const materials = {
|
const materials = {
|
||||||
forward: new Material(
|
forward,
|
||||||
ringsVert,
|
deferred,
|
||||||
ringsFrag,
|
depth,
|
||||||
{
|
|
||||||
defines: { 'FORWARD': 'true' },
|
|
||||||
initOptions: { geometry, target: dummyRenderTarget },
|
|
||||||
},
|
|
||||||
),
|
|
||||||
deferred: new Material(
|
|
||||||
ringsVert,
|
|
||||||
ringsFrag,
|
|
||||||
{
|
|
||||||
defines: { 'DEFERRED': 'true' },
|
|
||||||
initOptions: { geometry, target: dummyRenderTarget },
|
|
||||||
},
|
|
||||||
),
|
|
||||||
shadow: new Material(
|
|
||||||
ringsVert,
|
|
||||||
depthFrag,
|
|
||||||
{ initOptions: { geometry, target: dummyRenderTarget } },
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
@@ -79,9 +85,9 @@ export class Rings extends Entity {
|
|||||||
'../shaders/rings.frag',
|
'../shaders/rings.frag',
|
||||||
],
|
],
|
||||||
() => {
|
() => {
|
||||||
materials.forward.replaceShader( ringsVert, ringsFrag );
|
forward.replaceShader( ringsVert, ringsFrag );
|
||||||
materials.deferred.replaceShader( ringsVert, ringsFrag );
|
deferred.replaceShader( ringsVert, ringsFrag );
|
||||||
materials.shadow.replaceShader( ringsVert, depthFrag );
|
depth.replaceShader( ringsVert, depthFrag );
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -89,8 +95,8 @@ export class Rings extends Entity {
|
|||||||
|
|
||||||
// -- mesh -------------------------------------------------------------------------------------
|
// -- mesh -------------------------------------------------------------------------------------
|
||||||
const mesh = new Mesh( {
|
const mesh = new Mesh( {
|
||||||
geometry: geometry,
|
geometry,
|
||||||
materials: materials,
|
materials,
|
||||||
name: process.env.DEV && 'Rings/mesh',
|
name: process.env.DEV && 'Rings/mesh',
|
||||||
} );
|
} );
|
||||||
this.components.push( mesh );
|
this.components.push( mesh );
|
||||||
|
@@ -75,21 +75,21 @@ export class SphereParticles extends Entity {
|
|||||||
sphereParticleRenderVert,
|
sphereParticleRenderVert,
|
||||||
sphereParticleRenderFrag,
|
sphereParticleRenderFrag,
|
||||||
{
|
{
|
||||||
defines: { 'DEFERRED': 'true' },
|
defines: [ 'DEFERRED 1' ],
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const shadow = new Material(
|
const depth = new Material(
|
||||||
sphereParticleRenderVert,
|
sphereParticleRenderVert,
|
||||||
depthFrag,
|
depthFrag,
|
||||||
{ initOptions: { geometry: geometryRender, target: dummyRenderTarget } },
|
{ initOptions: { geometry: geometryRender, target: dummyRenderTarget } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const materialsRender = { deferred, shadow };
|
const materialsRender = { deferred, depth };
|
||||||
|
|
||||||
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
||||||
shadow.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
depth.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
if ( module.hot ) {
|
if ( module.hot ) {
|
||||||
@@ -100,7 +100,7 @@ export class SphereParticles extends Entity {
|
|||||||
],
|
],
|
||||||
() => {
|
() => {
|
||||||
deferred.replaceShader( sphereParticleRenderVert, sphereParticleRenderFrag );
|
deferred.replaceShader( sphereParticleRenderVert, sphereParticleRenderFrag );
|
||||||
shadow.replaceShader( sphereParticleRenderVert, depthFrag );
|
depth.replaceShader( sphereParticleRenderVert, depthFrag );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -68,7 +68,7 @@ export class SufferTexts extends Entity {
|
|||||||
sufferTextsRenderVert,
|
sufferTextsRenderVert,
|
||||||
sufferTextsRenderFrag,
|
sufferTextsRenderFrag,
|
||||||
{
|
{
|
||||||
defines: { 'DEFERRED': 'true' },
|
defines: [ 'DEFERRED 1' ],
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@@ -108,20 +108,20 @@ export class Trails extends Entity {
|
|||||||
trailsRenderVert,
|
trailsRenderVert,
|
||||||
trailsRenderFrag,
|
trailsRenderFrag,
|
||||||
{
|
{
|
||||||
defines: { 'DEFERRED': 'true' },
|
defines: [ 'DEFERRED 1' ],
|
||||||
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
initOptions: { geometry: geometryRender, target: dummyRenderTargetFourDrawBuffers },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
const shadow = new Material(
|
const depth = new Material(
|
||||||
trailsRenderVert,
|
trailsRenderVert,
|
||||||
depthFrag,
|
depthFrag,
|
||||||
{ initOptions: { geometry: geometryRender, target: dummyRenderTarget } },
|
{ initOptions: { geometry: geometryRender, target: dummyRenderTarget } },
|
||||||
);
|
);
|
||||||
|
|
||||||
const materialsRender = { deferred, shadow };
|
const materialsRender = { deferred, depth };
|
||||||
|
|
||||||
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
deferred.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
||||||
shadow.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
depth.addUniformTexture( 'samplerRandomStatic', randomTextureStatic.texture );
|
||||||
|
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
if ( module.hot ) {
|
if ( module.hot ) {
|
||||||
@@ -132,7 +132,7 @@ export class Trails extends Entity {
|
|||||||
],
|
],
|
||||||
() => {
|
() => {
|
||||||
deferred.replaceShader( trailsRenderVert, trailsRenderFrag );
|
deferred.replaceShader( trailsRenderVert, trailsRenderFrag );
|
||||||
shadow.replaceShader( trailsRenderVert, depthFrag );
|
depth.replaceShader( trailsRenderVert, depthFrag );
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import { Automaton } from '@fms-cat/automaton';
|
import { Automaton } from '@fms-cat/automaton';
|
||||||
import { AutomatonWithGUI } from '@fms-cat/automaton-with-gui';
|
import { AutomatonWithGUI } from '@fms-cat/automaton-with-gui';
|
||||||
import automatonData from '../automaton.json';
|
import automatonData from '../automaton.json';
|
||||||
import * as automatonFxs from '../automaton-fxs/automatonFxs';
|
|
||||||
import { music } from './music';
|
import { music } from './music';
|
||||||
import { getDivAutomaton } from './dom';
|
import { getDivAutomaton } from './dom';
|
||||||
|
import { fxDefinitions } from '../automaton-fxs/fxDefinitions';
|
||||||
|
|
||||||
export const automaton = ( () => {
|
export const automaton = ( () => {
|
||||||
if ( process.env.DEV ) {
|
if ( process.env.DEV ) {
|
||||||
@@ -14,8 +14,8 @@ export const automaton = ( () => {
|
|||||||
{
|
{
|
||||||
gui: getDivAutomaton(),
|
gui: getDivAutomaton(),
|
||||||
isPlaying: true,
|
isPlaying: true,
|
||||||
fxDefinitions: automatonFxs,
|
fxDefinitions,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
automatonWithGUI.on( 'play', () => { music.isPlaying = true; } );
|
automatonWithGUI.on( 'play', () => { music.isPlaying = true; } );
|
||||||
@@ -38,8 +38,8 @@ export const automaton = ( () => {
|
|||||||
return new Automaton(
|
return new Automaton(
|
||||||
automatonData,
|
automatonData,
|
||||||
{
|
{
|
||||||
fxDefinitions: automatonFxs
|
fxDefinitions,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} )();
|
} )();
|
||||||
|
@@ -8,7 +8,7 @@ import { SHADERPOOL } from './ShaderPool';
|
|||||||
export type MaterialTag =
|
export type MaterialTag =
|
||||||
| 'deferred'
|
| 'deferred'
|
||||||
| 'forward'
|
| 'forward'
|
||||||
| 'shadow';
|
| 'depth';
|
||||||
|
|
||||||
export type MaterialMap<T extends MaterialTag = MaterialTag> = { [ tag in T ]: Material };
|
export type MaterialMap<T extends MaterialTag = MaterialTag> = { [ tag in T ]: Material };
|
||||||
|
|
||||||
@@ -20,9 +20,7 @@ export interface MaterialInitOptions {
|
|||||||
export class Material {
|
export class Material {
|
||||||
protected __linkOptions: GLCatProgramLinkOptions;
|
protected __linkOptions: GLCatProgramLinkOptions;
|
||||||
|
|
||||||
protected __defines: {
|
protected __defines: string[];
|
||||||
[ name: string ]: ( string | undefined );
|
|
||||||
};
|
|
||||||
|
|
||||||
protected __uniforms: {
|
protected __uniforms: {
|
||||||
[ name: string ]: {
|
[ name: string ]: {
|
||||||
@@ -84,7 +82,7 @@ export class Material {
|
|||||||
vert: string,
|
vert: string,
|
||||||
frag: string,
|
frag: string,
|
||||||
{ defines, blend, linkOptions, initOptions }: {
|
{ defines, blend, linkOptions, initOptions }: {
|
||||||
defines?: { [ key: string ]: ( string | undefined ) },
|
defines?: string[],
|
||||||
blend?: [ GLenum, GLenum ],
|
blend?: [ GLenum, GLenum ],
|
||||||
linkOptions?: GLCatProgramLinkOptions,
|
linkOptions?: GLCatProgramLinkOptions,
|
||||||
initOptions?: MaterialInitOptions,
|
initOptions?: MaterialInitOptions,
|
||||||
@@ -93,7 +91,7 @@ export class Material {
|
|||||||
this.__vert = vert;
|
this.__vert = vert;
|
||||||
this.__frag = frag;
|
this.__frag = frag;
|
||||||
this.__linkOptions = linkOptions ?? {};
|
this.__linkOptions = linkOptions ?? {};
|
||||||
this.__defines = defines ?? {};
|
this.__defines = defines ?? [];
|
||||||
this.blend = blend ?? [ gl.ONE, gl.ZERO ];
|
this.blend = blend ?? [ gl.ONE, gl.ZERO ];
|
||||||
|
|
||||||
if ( initOptions ) {
|
if ( initOptions ) {
|
||||||
@@ -153,12 +151,12 @@ export class Material {
|
|||||||
vert: string,
|
vert: string,
|
||||||
frag: string,
|
frag: string,
|
||||||
options?: {
|
options?: {
|
||||||
defines?: { [ key: string ]: ( string | undefined ) },
|
defines?: string[],
|
||||||
linkOptions?: GLCatProgramLinkOptions,
|
linkOptions?: GLCatProgramLinkOptions,
|
||||||
},
|
},
|
||||||
): Promise<void> {
|
): Promise<void> {
|
||||||
if ( options?.defines ) {
|
if ( options?.defines ) {
|
||||||
this.__defines = { ...options.defines };
|
this.__defines = [ ...options.defines ];
|
||||||
}
|
}
|
||||||
|
|
||||||
const program = await SHADERPOOL.getProgramAsync(
|
const program = await SHADERPOOL.getProgramAsync(
|
||||||
@@ -194,9 +192,9 @@ export class Material {
|
|||||||
protected __withDefines( code: string ): string {
|
protected __withDefines( code: string ): string {
|
||||||
let inject = '';
|
let inject = '';
|
||||||
|
|
||||||
Object.entries( this.__defines ).map( ( [ key, value ] ) => {
|
this.__defines.map( ( value ) => {
|
||||||
if ( value != null ) {
|
if ( value != null ) {
|
||||||
inject += `#define ${key} ${value}\n`;
|
inject += `#define ${value}\n`;
|
||||||
}
|
}
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
10
src/main.ts
10
src/main.ts
@@ -4,6 +4,7 @@ import { Component } from './heck/components/Component';
|
|||||||
import { music } from './globals/music';
|
import { music } from './globals/music';
|
||||||
import { getCheckboxActive, getDivCanvasContainer } from './globals/dom';
|
import { getCheckboxActive, getDivCanvasContainer } from './globals/dom';
|
||||||
import { dog } from './scene';
|
import { dog } from './scene';
|
||||||
|
import { START_POSITION } from './config';
|
||||||
|
|
||||||
// == dom ==========================================================================================
|
// == dom ==========================================================================================
|
||||||
document.body.style.margin = '0';
|
document.body.style.margin = '0';
|
||||||
@@ -20,6 +21,9 @@ if ( process.env.DEV ) {
|
|||||||
canvas.style.margin = 'auto';
|
canvas.style.margin = 'auto';
|
||||||
canvas.style.maxWidth = '100%';
|
canvas.style.maxWidth = '100%';
|
||||||
canvas.style.maxHeight = '100%';
|
canvas.style.maxHeight = '100%';
|
||||||
|
|
||||||
|
music.isPlaying = true;
|
||||||
|
music.time = START_POSITION;
|
||||||
} else {
|
} else {
|
||||||
canvas.style.position = 'fixed';
|
canvas.style.position = 'fixed';
|
||||||
canvas.style.left = '0';
|
canvas.style.left = '0';
|
||||||
@@ -34,6 +38,7 @@ if ( process.env.DEV ) {
|
|||||||
button.onclick = () => {
|
button.onclick = () => {
|
||||||
document.body.appendChild( canvas );
|
document.body.appendChild( canvas );
|
||||||
music.isPlaying = true;
|
music.isPlaying = true;
|
||||||
|
music.time = START_POSITION;
|
||||||
document.body.requestFullscreen();
|
document.body.requestFullscreen();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -70,8 +75,3 @@ if ( process.env.DEV ) {
|
|||||||
console.info( Component.nameMap );
|
console.info( Component.nameMap );
|
||||||
console.info( BufferRenderTarget.nameMap );
|
console.info( BufferRenderTarget.nameMap );
|
||||||
}
|
}
|
||||||
|
|
||||||
// == music ========================================================================================
|
|
||||||
if ( process.env.DEV ) {
|
|
||||||
music.isPlaying = true;
|
|
||||||
}
|
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
export const sufferList = [
|
export const sufferList = [
|
||||||
'#DEFINE DISGRACE 1',
|
'#DEFINE DISGRACE 1',
|
||||||
|
'WELCOME TO THE MANGLER HELL',
|
||||||
'CTRL + ALT + DESPAIR',
|
'CTRL + ALT + DESPAIR',
|
||||||
'PUBIC CONSTRUCTOR()',
|
|
||||||
'LIBOPUS IS CHEATING',
|
'LIBOPUS IS CHEATING',
|
||||||
'PUBLIC GET FUCKED()',
|
'PUBLIC GET FUCKED()',
|
||||||
'\'RETRUN\': UNDECLARED IDENTIFIER',
|
'\'RETRUN\': UNDECLARED IDENTIFIER',
|
||||||
'NOTICE ME, GARBAGE COLLECTOR',
|
'NOTICE ME, GARBAGE COLLECTOR',
|
||||||
'WEBGL HATES YOU',
|
'WEBGL HATES YOU',
|
||||||
'#DEFINE COMPROMISE 1',
|
'#DEFINE COMPROMISE 1',
|
||||||
'GL.DISABLE(GL.TIMEZONE)',
|
|
||||||
'WHERE IS MY SLEEPING SCHEDULE?',
|
'WHERE IS MY SLEEPING SCHEDULE?',
|
||||||
|
'GL.DISABLE(GL.TIMEZONE)',
|
||||||
'SVG.GETPOINTATLENGTH IS CHEATING',
|
'SVG.GETPOINTATLENGTH IS CHEATING',
|
||||||
'COPY\'N\'PASTE ENGINEER',
|
'COPY\'N\'PASTE ENGINEER',
|
||||||
'ENGLISH SUCKS',
|
|
||||||
'60FPS OR DIE',
|
'60FPS OR DIE',
|
||||||
|
'<PLACEHOLDER>',
|
||||||
'END MY SUFFER',
|
'END MY SUFFER',
|
||||||
];
|
];
|
||||||
|
6
src/utils/iterateOverMap.ts
Normal file
6
src/utils/iterateOverMap.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
export function iterateOverMap<TKey, TValue, TReturn>(
|
||||||
|
map: Map<TKey, TValue>,
|
||||||
|
func: ( value: TValue, key: TKey ) => TReturn,
|
||||||
|
): TReturn[] {
|
||||||
|
return Array.from( map.entries() ).map( ( [ key, value ] ) => func( value, key ) );
|
||||||
|
}
|
@@ -1,11 +1,40 @@
|
|||||||
/* eslint-env node */
|
/* eslint-env node */
|
||||||
/* eslint-disable @typescript-eslint/no-var-requires */
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
||||||
|
|
||||||
|
const TerserPlugin = require( 'terser-webpack-plugin' );
|
||||||
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
|
const HtmlWebpackPlugin = require( 'html-webpack-plugin' );
|
||||||
const packageJson = require( './package.json' );
|
const packageJson = require( './package.json' );
|
||||||
const path = require( 'path' );
|
const path = require( 'path' );
|
||||||
const webpack = require( 'webpack' );
|
const webpack = require( 'webpack' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type TerserPlugin.TerserPluginOptions[ 'terserOptions' ]
|
||||||
|
*/
|
||||||
|
const terserOptions = {
|
||||||
|
compress: {
|
||||||
|
arguments: true,
|
||||||
|
booleans_as_integers: true,
|
||||||
|
drop_console: true,
|
||||||
|
keep_fargs: false,
|
||||||
|
passes: 1,
|
||||||
|
unsafe_arrows: true,
|
||||||
|
unsafe_math: true,
|
||||||
|
},
|
||||||
|
mangle: {
|
||||||
|
properties: {
|
||||||
|
regex: /.+/,
|
||||||
|
reserved: [
|
||||||
|
// material tags
|
||||||
|
'forward',
|
||||||
|
'deferred',
|
||||||
|
'depth',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
},
|
||||||
|
module: true,
|
||||||
|
toplevel: true,
|
||||||
|
};
|
||||||
|
|
||||||
module.exports = ( env, argv ) => {
|
module.exports = ( env, argv ) => {
|
||||||
const VERSION = packageJson.version;
|
const VERSION = packageJson.version;
|
||||||
const DEV = argv.mode === 'development';
|
const DEV = argv.mode === 'development';
|
||||||
@@ -67,6 +96,7 @@ module.exports = ( env, argv ) => {
|
|||||||
},
|
},
|
||||||
optimization: {
|
optimization: {
|
||||||
minimize: !DEV,
|
minimize: !DEV,
|
||||||
|
minimizer: [ new TerserPlugin( { terserOptions } ) ],
|
||||||
moduleIds: DEV ? 'named' : undefined,
|
moduleIds: DEV ? 'named' : undefined,
|
||||||
usedExports: !DEV,
|
usedExports: !DEV,
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user