├── .babelrc
├── .gitignore
├── README.md
├── src
├── fragapp
│ ├── vert.glsl
│ ├── frag.glsl
│ └── index.js
├── 003
│ ├── vert.glsl
│ ├── frag.glsl
│ └── index.js
├── 001
│ ├── vert.glsl
│ ├── compute-position.glsl
│ ├── frag.glsl
│ ├── compute-velocity.glsl
│ └── index.js
├── templates
│ └── index.hbs
├── ThreeApp.js
├── 002
│ └── index.js
└── lib
│ └── GPUComputationRenderer.js
├── public
├── 001
│ ├── particle.png
│ └── index.html
├── now.json
├── index.html
├── scripts
│ ├── ga.js
│ ├── tween.min.js
│ └── dat.gui.min.js
├── 002
│ ├── index.html
│ └── bundle.js
├── 003
│ ├── index.html
│ └── bundle.js
└── styles
│ └── experiments.css
├── experiments.json
├── LICENSE
├── package.json
└── webpack.config.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["latest"]
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | **/*.sw*
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # experiments
2 |
3 | audio/VR/AR/GL experiments for the web.
4 |
--------------------------------------------------------------------------------
/src/fragapp/vert.glsl:
--------------------------------------------------------------------------------
1 | void main() {
2 | gl_Position = vec4(position, 1.0);
3 | }
4 |
--------------------------------------------------------------------------------
/public/001/particle.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jsantell/experiments/HEAD/public/001/particle.png
--------------------------------------------------------------------------------
/public/now.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "experiments-jsantell",
3 | "alias": "experiments.jsantell.com",
4 | "type": "static"
5 | }
6 |
--------------------------------------------------------------------------------
/src/003/vert.glsl:
--------------------------------------------------------------------------------
1 | varying vec2 vUv;
2 |
3 | void main() {
4 | vUv = uv;
5 | gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
6 | }
7 |
--------------------------------------------------------------------------------
/src/001/vert.glsl:
--------------------------------------------------------------------------------
1 | uniform float size;
2 | uniform sampler2D tPosition;
3 | uniform sampler2D tVelocity;
4 | varying vec3 vPosition;
5 |
6 | void main() {
7 | vec3 pos = texture2D(tPosition, uv).xyz;
8 | vPosition = pos;
9 | gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
10 | gl_PointSize = size;
11 | }
12 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Experiments
6 |
7 |
8 |
9 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/src/001/compute-position.glsl:
--------------------------------------------------------------------------------
1 | uniform float delta;
2 |
3 | #pragma glslify: when_lt = require(glsl-conditionals/when_lt)
4 |
5 | void main() {
6 | vec2 uv = gl_FragCoord.xy / resolution.xy;
7 | vec3 pos = texture2D(tPosition, uv).xyz;
8 | vec4 tmpVel = texture2D(tVelocity, uv);
9 | vec3 vel = tmpVel.xyz;
10 | float mass = tmpVel.w;
11 |
12 | pos += vel * delta * mass;
13 |
14 | pos *= when_lt(length(pos), 2.5);
15 |
16 | gl_FragColor = vec4(pos, 1.0);
17 | }
18 |
--------------------------------------------------------------------------------
/src/001/frag.glsl:
--------------------------------------------------------------------------------
1 | uniform float time;
2 | uniform sampler2D sprite;
3 |
4 | varying vec3 vPosition;
5 |
6 | #pragma glslify: map = require(glsl-map)
7 | #pragma glslify: hsl2rgb = require(glsl-hsl2rgb)
8 |
9 | void main() {
10 | vec4 tex = texture2D(sprite, gl_PointCoord);
11 | float l = length(vPosition);
12 | float t = clamp(-1.0, 1.0, sin(time * 0.0005));
13 | vec3 hsl = hsl2rgb(map(t+l, -1.0, 3.0, 0.3, 0.7), 0.8, 0.5);
14 | gl_FragColor = vec4(hsl, tex.a*0.1);
15 | }
16 |
--------------------------------------------------------------------------------
/src/fragapp/frag.glsl:
--------------------------------------------------------------------------------
1 | uniform float uTime;
2 | uniform float uDelta;
3 | uniform vec2 uResolution;
4 |
5 | #pragma glslify: hsl2rgb = require(glsl-hsl2rgb)
6 |
7 | void main() {
8 | vec2 st = gl_FragCoord.xy / uResolution.xy;
9 | float hue = cos(st.y) + sin(uTime * 0.0001);
10 | vec3 rgb = vec3(
11 | (sin((uTime * 0.001) + 0.1) + 1.0) / 2.0,
12 | (sin((uTime * 0.001) + 0.2) + 1.0) / 2.0,
13 | (sin((uTime * 0.001) + 0.8) + 1.0) / 2.0
14 | );
15 | gl_FragColor = vec4(rgb, 1.0);
16 | }
17 |
--------------------------------------------------------------------------------
/public/scripts/ga.js:
--------------------------------------------------------------------------------
1 | (function() {
2 | if (!/jsantell.com/.test(window.location.host)) {
3 | return;
4 | }
5 | (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
6 | (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
7 | m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
8 | })(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
9 |
10 | ga('create', 'UA-23782413-1', 'auto');
11 | ga('send', 'pageview');
12 | })();
13 |
--------------------------------------------------------------------------------
/src/003/frag.glsl:
--------------------------------------------------------------------------------
1 | uniform vec3 fgColor;
2 | uniform vec3 bgColor;
3 |
4 | varying vec2 vUv;
5 |
6 | #pragma glslify: when_gt = require(glsl-conditionals/when_gt)
7 |
8 | void main() {
9 | float limit = 0.1;
10 | vec3 color = fgColor;
11 |
12 | float isTiled = 0.0;
13 | isTiled += when_gt(limit, vUv.x);
14 | isTiled += when_gt(limit, vUv.y);
15 | isTiled += when_gt(vUv.x, 1.0 - limit);
16 | isTiled += when_gt(vUv.y, 1.0 - limit);
17 |
18 | color = (step(1.0, isTiled) * bgColor) + ((1.0 - step(1.0, isTiled)) * fgColor);
19 | gl_FragColor = vec4(color, 1.0);
20 | }
21 |
--------------------------------------------------------------------------------
/experiments.json:
--------------------------------------------------------------------------------
1 | {
2 | "experiments": {
3 | "001": {
4 | "title": "Energy",
5 | "subtitle": "1 Million Particles",
6 | "dependencies": [
7 | { "name": "three" }
8 | ]
9 | },
10 | "002": {
11 | "title": "Slinky",
12 | "subtitle": "Exploration of splines",
13 | "dependencies": [
14 | { "name": "three" }
15 | ]
16 | },
17 | "003": {
18 | "title": "rubix",
19 | "subtitle": "three degrees of freedom",
20 | "dependencies": [
21 | { "name": "three" },
22 | { "name": "tween" }
23 | ]
24 | }
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/public/001/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Experiment 001: Energy
6 |
7 |
8 |
9 |
10 |
11 |
12 | Experiment 001
13 | Energy
14 | 1 Million Particles
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/public/002/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Experiment 002: Slinky
6 |
7 |
8 |
9 |
10 |
11 |
12 | Experiment 002
13 | Slinky
14 | Exploration of splines
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/src/001/compute-velocity.glsl:
--------------------------------------------------------------------------------
1 | uniform float time;
2 |
3 | #pragma glslify: snoise3 = require(glsl-noise/simplex/3d)
4 | #pragma glslify: when_gt = require(glsl-conditionals/when_gt)
5 |
6 | const float max = 1.5;
7 |
8 | void main() {
9 | vec2 uv = gl_FragCoord.xy / resolution.xy;
10 | vec3 pos = texture2D(tPosition, uv).xyz;
11 | vec4 tmpVel = texture2D(tVelocity, uv);
12 | vec3 vel = tmpVel.xyz;
13 | float mass = tmpVel.w;
14 |
15 | // decay
16 | vel *= 0.9;
17 |
18 | float mod = sin(time * 0.0001);
19 | vel += -pos * 15.0 * snoise3(pos*mod+5.0);
20 |
21 | float outOfBounds = when_gt(length(pos), max);
22 | vel = (outOfBounds * -pos * 0.15) + ((1.0 - outOfBounds) * vel);
23 |
24 | gl_FragColor = vec4(vel, mass);
25 | }
26 |
--------------------------------------------------------------------------------
/public/003/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Experiment 003: rubix
6 |
7 |
8 |
9 |
10 |
11 |
12 | Experiment 003
13 | rubix
14 | three degrees of freedom
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/public/styles/experiments.css:
--------------------------------------------------------------------------------
1 | body {
2 | margin: 0;
3 | padding: 0;
4 | font-family: 'Roboto', sans-serif;
5 | color: white;
6 | padding: fixed;
7 | }
8 |
9 | #info {
10 | padding: 10px;
11 | background-color: rgba(0, 0, 0, 0.4);
12 | position: fixed;
13 | left: 0;
14 | bottom: 0;
15 | font-size: 120%;
16 | }
17 |
18 | .experiment-number {
19 | font-weight: 800;
20 | text-transform: uppercase;
21 | }
22 |
23 | .experiment-number:after {
24 | content: ':';
25 | }
26 |
27 | .experiment-title {
28 | font-weight: 300;
29 | text-transform: uppercase;
30 | }
31 |
32 | .experiment-subtitle {
33 | margin-top: 3px;
34 | text-transform: lowercase;
35 | font-weight: 300;
36 | font-size: 70%;
37 | color: #ccc;
38 | display: block;
39 | }
40 |
41 | .experiment-subtitle:before {
42 | content: '>';
43 | }
44 |
--------------------------------------------------------------------------------
/src/templates/index.hbs:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Experiment {{htmlWebpackPlugin.options.id}}: {{htmlWebpackPlugin.options.title}}
6 |
7 |
8 |
9 |
10 |
11 |
12 | Experiment {{htmlWebpackPlugin.options.id}}
13 | {{htmlWebpackPlugin.options.title}}
14 | {{htmlWebpackPlugin.options.subtitle}}
15 |
16 | {{#each htmlWebpackPlugin.options.dependencies}}
17 |
18 | {{/each}}
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2017 Jordan Santell
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy
4 | of this software and associated documentation files (the "Software"), to deal
5 | in the Software without restriction, including without limitation the rights
6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 | copies of the Software, and to permit persons to whom the Software is
8 | furnished to do so, subject to the following conditions:
9 |
10 | The above copyright notice and this permission notice shall be included in
11 | all copies or substantial portions of the Software.
12 |
13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 | THE SOFTWARE.
20 |
--------------------------------------------------------------------------------
/src/fragapp/index.js:
--------------------------------------------------------------------------------
1 | import { PlaneGeometry, Mesh, ShaderMaterial } from 'three';
2 | import ThreeApp from '../ThreeApp';
3 | import vertexShader from './vert.glsl';
4 | import fragmentShader from './frag.glsl';
5 |
6 | class Experiment002 extends ThreeApp {
7 | init() {
8 | this.material = new ShaderMaterial({
9 | uniforms: {
10 | uTime: { value: performance.now() },
11 | uResolution: { value: [window.innerWidth, window.innerHeight] },
12 | uDelta: { value: 0 },
13 | },
14 | fragmentShader,
15 | vertexShader,
16 | });
17 | this.geometry = new PlaneGeometry(2, 2);
18 | this.mesh = new Mesh(this.geometry, this.material);
19 | this.scene.add(this.mesh);
20 |
21 | this.camera.position.set(0, 0, 1);
22 | }
23 |
24 | update(t, delta) {
25 | this.material.uniforms.uTime.value = t;
26 | this.material.uniforms.uDelta.value = delta;
27 | }
28 |
29 | render() {
30 | this.renderer.render(this.scene, this.camera);
31 | }
32 |
33 | onResize() {
34 | super.onResize();
35 | this.material.uniforms.uResolution.value = [window.innerWidth, window.innerHeight];
36 | }
37 | }
38 |
39 | export default new Experiment002();
40 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@jsantell/experiments",
3 | "version": "1.0.0",
4 | "private": true,
5 | "description": "audio/VR/AR/GL experiments for the web.",
6 | "main": "index.js",
7 | "scripts": {
8 | "build": "webpack",
9 | "watch": "webpack-dev-server"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/jsantell/experiments.git"
14 | },
15 | "author": "Jordan Santell",
16 | "license": "MIT",
17 | "bugs": {
18 | "url": "https://github.com/jsantell/experiments/issues"
19 | },
20 | "homepage": "https://github.com/jsantell/experiments#readme",
21 | "devDependencies": {
22 | "babel-core": "^6.26.0",
23 | "babel-loader": "^7.1.2",
24 | "babel-preset-latest": "^6.24.1",
25 | "glsl-conditionals": "^1.0.0",
26 | "glsl-hsl2rgb": "^1.1.0",
27 | "glsl-hsv2rgb": "^1.0.0",
28 | "glsl-map": "^1.0.1",
29 | "glsl-noise": "0.0.0",
30 | "glsl-raytrace": "^1.0.0",
31 | "glsl-sdf-box": "^1.0.0",
32 | "glsl-sdf-normal": "^1.0.0",
33 | "glsl-turntable-camera": "^1.0.0",
34 | "glslify-loader": "^1.0.2",
35 | "handlebars": "^4.0.11",
36 | "handlebars-loader": "^1.6.0",
37 | "html-webpack-plugin": "^2.30.1",
38 | "raw-loader": "^0.5.1",
39 | "webpack": "^3.7.1",
40 | "webpack-dev-server": "^2.9.1"
41 | },
42 | "dependencies": {
43 | "@alex_toudic/wagner": "^0.1.20",
44 | "stats.js": "^0.17.0"
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const fs = require('fs');
2 | const path = require('path');
3 | const webpack = require('webpack');
4 | const html = require('html-webpack-plugin');
5 | const experiments = require('./experiments.json').experiments;
6 |
7 | const data = {
8 | entries: {},
9 | html: [],
10 | };
11 | Object.keys(experiments).map(id => {
12 | data.entries[id] = `./src/${id}/index.js`;
13 |
14 | const meta = experiments[id];
15 | const config = Object.assign({
16 | title: 'untitled',
17 | subtitle: '',
18 | template: './src/templates/index.hbs',
19 | id: id,
20 | filename: `${id}/index.html`,
21 | inject: false,
22 | }, meta);
23 |
24 | data.html.push(new html(config));
25 | });
26 |
27 | module.exports = {
28 | entry: data.entries,
29 | output: {
30 | path: path.join(__dirname, 'public'),
31 | publicPath: '',
32 | libraryTarget: 'umd',
33 | library: 'app',
34 | filename: '[name]/bundle.js'
35 | },
36 | module: {
37 | rules: [
38 | { test: /\.js/, exclude: /node_modules/, use: ['babel-loader'] },
39 | { test: /\.hbs/, exclude: /node_modules/, use: ['handlebars-loader'] },
40 | {
41 | test: /\.(glsl|frag|vert)$/,
42 | // exclude: /node_modules/,
43 | use: ['raw-loader', 'glslify-loader']
44 | },
45 | ]
46 | },
47 | externals: {
48 | three: {
49 | commonjs: 'three',
50 | commonjs2: 'three',
51 | amd: 'three',
52 | root: 'THREE',
53 | },
54 | tween: {
55 | commonjs: 'tween',
56 | commonjs2: 'tween',
57 | amd: 'tween',
58 | root: 'TWEEN',
59 | },
60 | 'dat.gui': 'dat',
61 | },
62 | resolve: {
63 | extensions: ['.js']
64 | },
65 | devServer: {
66 | contentBase: [path.resolve(path.join(__dirname, 'public'))],
67 | host: '0.0.0.0',
68 | disableHostCheck: true
69 | },
70 | plugins: [
71 | ...data.html
72 | ]
73 | };
74 |
--------------------------------------------------------------------------------
/src/ThreeApp.js:
--------------------------------------------------------------------------------
1 | import { WebGLRenderer, PerspectiveCamera, Scene } from 'three';
2 | import Stats from 'stats.js';
3 |
4 | export default class App {
5 | constructor() {
6 |
7 | if (window.location.search) {
8 | const params = window.location.search.substr(1).split('&');
9 | for (let param of params) {
10 | let [prop, value] = param.split('=');
11 | if (prop === 'debug') {
12 | this.stats = new Stats();
13 | this.stats.showPanel(0);
14 | document.body.appendChild(this.stats.dom);
15 | }
16 | }
17 | }
18 | this.renderer = new WebGLRenderer();
19 | this.renderer.setPixelRatio(window.devicePixelRatio);
20 | this.renderer.setSize(window.innerWidth, window.innerHeight);
21 | this.renderer.autoClear = false;
22 | document.body.appendChild(this.renderer.domElement);
23 |
24 | this.scene = new Scene();
25 |
26 | this.camera = new PerspectiveCamera(60, this.getAspect(), 0.1, 100);
27 |
28 | this.onResize = this.onResize.bind(this);
29 | window.addEventListener('resize', this.onResize);
30 |
31 | this.init();
32 |
33 | this.lastTick = 0;
34 | this.onTick = this.onTick.bind(this);
35 | requestAnimationFrame(this.onTick);
36 | }
37 |
38 | onTick() {
39 | const t = performance.now();
40 | const delta = performance.now() - this.lastTick;
41 | if (this.stats) {
42 | this.stats.begin();
43 | }
44 | this.update(t, delta);
45 | this.render(t, delta);
46 | if (this.stats) {
47 | this.stats.end();
48 | }
49 | this.lastTick = t;
50 | requestAnimationFrame(this.onTick);
51 | }
52 |
53 | getAspect() {
54 | return window.innerWidth / window.innerHeight;
55 | }
56 |
57 | onResize() {
58 | this.camera.aspect = this.getAspect();
59 | this.camera.updateProjectionMatrix();
60 | this.renderer.setSize(window.innerWidth, window.innerHeight);
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/002/index.js:
--------------------------------------------------------------------------------
1 | import { EllipseCurve, SplineCurve, Color, LineBasicMaterial, Line, Path, AdditiveBlending, Object3D } from 'three';
2 | import ThreeApp from '../ThreeApp';
3 | import WAGNER from '@alex_toudic/wagner';
4 | import BloomPass from '@alex_toudic/wagner/src/passes/bloom/MultiPassBloomPass';
5 |
6 | const count = 400;
7 | const points = 100;
8 | class Experiment extends ThreeApp {
9 | init() {
10 | this.renderer.setClearColor(0x111111);
11 | this.curves = [];
12 |
13 | for (let i = 0; i < count; i++) {
14 | const curve = new EllipseCurve(0, 0, 2, 2, 0, 2 * Math.PI, false, 0);
15 | const path = new Path(curve.getPoints(points));
16 | const geo = path.createPointsGeometry(points);
17 | const c = (i / count) * 360 / 1.9;
18 | const mat = new LineBasicMaterial({
19 | color: new Color(`hsl(${c}, 100%, 50%)`),
20 | transparent: true,
21 | depthWrite: false,
22 | blending: AdditiveBlending,
23 | opacity: 0.4,
24 | });
25 | const line = new Line(geo, mat);
26 | this.curves.push(line);
27 | this.scene.add(line);
28 | }
29 |
30 | this.camera.position.set(0, 0, 5);
31 |
32 | this.pivot = new Object3D();
33 | this.pivot.add(this.camera);
34 | this.scene.add(this.pivot);
35 |
36 | this.composer = new WAGNER.Composer(this.renderer);
37 | this.pass = new BloomPass({
38 | zoomBlurStrength: 0.05,
39 | applyZoomBlur: true,
40 | blurAmount: 0.2,
41 | });
42 | }
43 |
44 | update(t, delta) {
45 | for (let i = 0; i < count; i++) {
46 | const curve = this.curves[i];
47 | const pct = i / count;
48 | const scale = ((Math.sin(t * 0.0001 + (pct*Math.PI*2)) + 1) / 2);
49 | curve.scale.set(scale, scale, scale);
50 | curve.rotation.z = t * 0.00001 + (pct*2);
51 | curve.rotation.y = t * 0.001 + (pct*Math.PI*2);
52 | curve.rotation.x = (t * 0.001 + (pct*Math.PI*2)) + Math.PI/2;
53 | }
54 | this.pivot.rotation.y = -t * 0.001;
55 | }
56 |
57 | render() {
58 | this.renderer.clearColor();
59 | this.composer.reset();
60 | this.composer.render(this.scene, this.camera);
61 | this.composer.pass(this.pass);
62 | this.composer.toScreen();
63 | }
64 | }
65 |
66 | export default new Experiment();
67 |
--------------------------------------------------------------------------------
/public/scripts/tween.min.js:
--------------------------------------------------------------------------------
1 | var TWEEN=TWEEN||function(){var n=[];return{getAll:function(){return n},removeAll:function(){n=[]},add:function(t){n.push(t)},remove:function(t){var r=n.indexOf(t);-1!==r&&n.splice(r,1)},update:function(t,r){if(0===n.length)return!1;var i=0;for(t=void 0!==t?t:TWEEN.now();in;n++)p[n].stop()},this.delay=function(n){return s=n,this},this.repeat=function(n){return e=n,this},this.yoyo=function(n){return a=n,this},this.easing=function(n){return l=n,this},this.interpolation=function(n){return E=n,this},this.chain=function(){return p=arguments,this},this.onStart=function(n){return d=n,this},this.onUpdate=function(n){return w=n,this},this.onComplete=function(n){return I=n,this},this.onStop=function(n){return M=n,this},this.update=function(n){var f,M,T;if(h>n)return!0;v===!1&&(null!==d&&d.call(t),v=!0),M=(n-h)/u,M=M>1?1:M,T=l(M);for(f in i)if(void 0!==r[f]){var N=r[f]||0,W=i[f];W instanceof Array?t[f]=E(W,T):("string"==typeof W&&(W="+"===W.charAt(0)||"-"===W.charAt(0)?N+parseFloat(W,10):parseFloat(W,10)),"number"==typeof W&&(t[f]=N+(W-N)*T))}if(null!==w&&w.call(t,T),1===M){if(e>0){isFinite(e)&&e--;for(f in o){if("string"==typeof i[f]&&(o[f]=o[f]+parseFloat(i[f],10)),a){var O=o[f];o[f]=i[f],i[f]=O}r[f]=o[f]}return a&&(c=!c),h=n+s,!0}null!==I&&I.call(t);for(var m=0,g=p.length;g>m;m++)p[m].start(h+u);return!1}return!0}},TWEEN.Easing={Linear:{None:function(n){return n}},Quadratic:{In:function(n){return n*n},Out:function(n){return n*(2-n)},InOut:function(n){return(n*=2)<1?.5*n*n:-.5*(--n*(n-2)-1)}},Cubic:{In:function(n){return n*n*n},Out:function(n){return--n*n*n+1},InOut:function(n){return(n*=2)<1?.5*n*n*n:.5*((n-=2)*n*n+2)}},Quartic:{In:function(n){return n*n*n*n},Out:function(n){return 1- --n*n*n*n},InOut:function(n){return(n*=2)<1?.5*n*n*n*n:-.5*((n-=2)*n*n*n-2)}},Quintic:{In:function(n){return n*n*n*n*n},Out:function(n){return--n*n*n*n*n+1},InOut:function(n){return(n*=2)<1?.5*n*n*n*n*n:.5*((n-=2)*n*n*n*n+2)}},Sinusoidal:{In:function(n){return 1-Math.cos(n*Math.PI/2)},Out:function(n){return Math.sin(n*Math.PI/2)},InOut:function(n){return.5*(1-Math.cos(Math.PI*n))}},Exponential:{In:function(n){return 0===n?0:Math.pow(1024,n-1)},Out:function(n){return 1===n?1:1-Math.pow(2,-10*n)},InOut:function(n){return 0===n?0:1===n?1:(n*=2)<1?.5*Math.pow(1024,n-1):.5*(-Math.pow(2,-10*(n-1))+2)}},Circular:{In:function(n){return 1-Math.sqrt(1-n*n)},Out:function(n){return Math.sqrt(1- --n*n)},InOut:function(n){return(n*=2)<1?-.5*(Math.sqrt(1-n*n)-1):.5*(Math.sqrt(1-(n-=2)*n)+1)}},Elastic:{In:function(n){return 0===n?0:1===n?1:-Math.pow(2,10*(n-1))*Math.sin(5*(n-1.1)*Math.PI)},Out:function(n){return 0===n?0:1===n?1:Math.pow(2,-10*n)*Math.sin(5*(n-.1)*Math.PI)+1},InOut:function(n){return 0===n?0:1===n?1:(n*=2,1>n?-.5*Math.pow(2,10*(n-1))*Math.sin(5*(n-1.1)*Math.PI):.5*Math.pow(2,-10*(n-1))*Math.sin(5*(n-1.1)*Math.PI)+1)}},Back:{In:function(n){var t=1.70158;return n*n*((t+1)*n-t)},Out:function(n){var t=1.70158;return--n*n*((t+1)*n+t)+1},InOut:function(n){var t=2.5949095;return(n*=2)<1?.5*(n*n*((t+1)*n-t)):.5*((n-=2)*n*((t+1)*n+t)+2)}},Bounce:{In:function(n){return 1-TWEEN.Easing.Bounce.Out(1-n)},Out:function(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375},InOut:function(n){return.5>n?.5*TWEEN.Easing.Bounce.In(2*n):.5*TWEEN.Easing.Bounce.Out(2*n-1)+.5}}},TWEEN.Interpolation={Linear:function(n,t){var r=n.length-1,i=r*t,o=Math.floor(i),u=TWEEN.Interpolation.Utils.Linear;return 0>t?u(n[0],n[1],i):t>1?u(n[r],n[r-1],r-i):u(n[o],n[o+1>r?r:o+1],i-o)},Bezier:function(n,t){for(var r=0,i=n.length-1,o=Math.pow,u=TWEEN.Interpolation.Utils.Bernstein,e=0;i>=e;e++)r+=o(1-t,i-e)*o(t,e)*n[e]*u(i,e);return r},CatmullRom:function(n,t){var r=n.length-1,i=r*t,o=Math.floor(i),u=TWEEN.Interpolation.Utils.CatmullRom;return n[0]===n[r]?(0>t&&(o=Math.floor(i=r*(1+t))),u(n[(o-1+r)%r],n[o],n[(o+1)%r],n[(o+2)%r],i-o)):0>t?n[0]-(u(n[0],n[0],n[1],n[1],-i)-n[0]):t>1?n[r]-(u(n[r],n[r],n[r-1],n[r-1],i-r)-n[r]):u(n[o?o-1:0],n[o],n[o+1>r?r:o+1],n[o+2>r?r:o+2],i-o)},Utils:{Linear:function(n,t,r){return(t-n)*r+n},Bernstein:function(n,t){var r=TWEEN.Interpolation.Utils.Factorial;return r(n)/r(t)/r(n-t)},Factorial:function(){var n=[1];return function(t){var r=1;if(n[t])return n[t];for(var i=t;i>1;i--)r*=i;return n[t]=r,r}}(),CatmullRom:function(n,t,r,i,o){var u=.5*(r-n),e=.5*(i-t),a=o*o,f=o*a;return(2*t-2*r+u+e)*f+(-3*t+3*r-2*u-e)*a+u*o+t}}},function(n){"function"==typeof define&&define.amd?define([],function(){return TWEEN}):"undefined"!=typeof module&&"object"==typeof exports?module.exports=TWEEN:void 0!==n&&(n.TWEEN=TWEEN)}(this);
2 | //# sourceMappingURL=Tween.min.js.map
--------------------------------------------------------------------------------
/src/003/index.js:
--------------------------------------------------------------------------------
1 | import { Vector3, Color, Mesh, ShaderMaterial, MeshBasicMaterial, BoxGeometry, AdditiveBlending, Object3D } from 'three';
2 | import { Tween, Easing, update as tweenUpdate } from 'tween';
3 | import ThreeApp from '../ThreeApp';
4 | import fragmentShader from './frag.glsl';
5 | import vertexShader from './vert.glsl';
6 | import WAGNER from '@alex_toudic/wagner';
7 | import VignettePass from '@alex_toudic/wagner/src/passes/vignette/VignettePass';
8 |
9 | const ROTATION_DELAY = 100;
10 | const ROTATION_SPEED = 800;
11 | const DIMENSIONS = 3;
12 | const CUBE_SCALE = 1.0;
13 | const CUBE_DISTANCE_SCALE = 1.0;
14 | const EASING = Easing.Back.Out;
15 | const BG_COLOR = 0x333333;
16 |
17 | // Randomly return val1 or val2
18 | const or = (val1, val2) => Math.random() > 0.5 ? val1 : val2;
19 | // Pass in an axis ('x', 'y', 'z') and return a different axis
20 | const getDifferentAxis = axis => axis === 'x' ? or('y', 'z') :
21 | axis === 'y' ? or('x', 'z') : or('y', 'x');
22 | const getRandomAxis = () => ['x', 'y', 'z'][Math.floor(Math.random() * 3)];
23 |
24 | class Experiment extends ThreeApp {
25 | init() {
26 | this.renderer.setClearColor(BG_COLOR);
27 | this.curves = [];
28 |
29 | this.cubeGroup = new Object3D();
30 | this.rotationHelper = new Object3D();
31 | this.cubeGroup.add(this.rotationHelper);
32 | this.scene.add(this.cubeGroup);
33 | this.material = new ShaderMaterial({
34 | vertexShader,
35 | fragmentShader,
36 | uniforms: {
37 | fgColor: { value: new Color(0xffffff) },
38 | bgColor: { value: new Color(BG_COLOR) },
39 | },
40 | });
41 |
42 | this.createCubes();
43 |
44 | this.pivot = new Object3D();
45 | this.scene.add(this.pivot);
46 | this.camera.lookAt(new Vector3());
47 | this.pivot.add(this.camera);
48 | this.camera.position.set(4, 4, 4);
49 |
50 | this.lastRotation = 0;
51 | this.composer = new WAGNER.Composer(this.renderer);
52 | this.pass = new VignettePass(0.9, 1.0);
53 | }
54 |
55 | createCubes() {
56 | this.cubes = [];
57 |
58 | /**
59 | * Store cubes in plane, row, columns, below
60 | * is a face
61 | *
62 | * z,y,x
63 | *
64 | * 0,0,0 0,0,1 0,0,2
65 | * 0,1,0 0,1,1 0,1,2
66 | * 0,2,0 0,2,1 0,2,2
67 | *
68 | */
69 | const solid = this.material;
70 | const transparent = new MeshBasicMaterial({ opacity: 0, transparent: true });
71 | const last = DIMENSIONS - 1;
72 | for (let z = 0; z < DIMENSIONS; z++) {
73 | const plane = this.cubes[z] = [];
74 | for (let y = 0; y < DIMENSIONS; y++) {
75 | const row = plane[y] = [];
76 | for (let x = 0; x < DIMENSIONS; x++) {
77 | let cube = new Mesh(new BoxGeometry(CUBE_SCALE, CUBE_SCALE, CUBE_SCALE), [
78 | x === last ? solid : transparent, // bot right
79 | x === 0 ? solid : transparent, // back left
80 | y === last ? solid : transparent, // top
81 | y === 0 ? solid : transparent, // bottom
82 | z === last ? solid : transparent, // bot left
83 | z === 0 ? solid : transparent, // back right
84 | ]);
85 | row[x] = cube;
86 | this.cubeGroup.add(cube);
87 |
88 | const half = DIMENSIONS % 2 === 0 ? (DIMENSIONS / 2) -0.5 : Math.floor(DIMENSIONS / 2);
89 | cube.position.set(
90 | ((x ) - half) * CUBE_DISTANCE_SCALE,
91 | ((y ) - half) * CUBE_DISTANCE_SCALE,
92 | ((z ) - half) * CUBE_DISTANCE_SCALE
93 | );
94 | }
95 | }
96 | }
97 | }
98 |
99 | getCubesBySlice(axis, index) {
100 | // I'm sure there's a better way for this
101 | const cubes = [];
102 | for (let z = 0; z < DIMENSIONS; z++) {
103 | for (let y = 0; y < DIMENSIONS; y++) {
104 | for (let x = 0; x < DIMENSIONS; x++) {
105 | const r = axis === 'z' ? z :
106 | axis === 'y' ? y : x;
107 | if (r === index) {
108 | const cube = this.cubes[z][y][x];
109 | cubes.push(cube);
110 | }
111 | }
112 | }
113 | }
114 | return cubes;
115 | }
116 |
117 | rotateCubes(axis, index, dir) {
118 | const cubes = this.getCubesBySlice(axis, index);
119 | for (let cube of cubes) {
120 | this.cubeGroup.remove(cube);
121 | this.rotationHelper.add(cube);
122 | }
123 |
124 | this.cubeTween = this.rotate(this.rotationHelper, axis, dir);
125 | this.cubeTween.onComplete(() => {
126 | cubes.forEach(c => {
127 | this.cubeGroup.add(c);
128 | this.rotationHelper.remove(c);
129 | });
130 | this.rotationHelper.rotation.set(0, 0, 0);
131 | this.cubeTween = null;
132 | });
133 | }
134 |
135 | rotate(object, axis, dir, easing) {
136 | const startRotation = object.rotation[axis];
137 |
138 | return new Tween({ x: 0 })
139 | .to({ x: 1 }, ROTATION_SPEED)
140 | .onUpdate(value => {
141 | object.rotation[axis] = startRotation + (value * Math.PI / 2 * dir);
142 | })
143 | .easing(easing || EASING)
144 | .start();
145 | }
146 |
147 | update(t, delta) {
148 | if (this.lastRotation + ROTATION_SPEED + ROTATION_DELAY < t &&
149 | !this.camTween && !this.cubeTween) {
150 | const index = Math.floor(Math.random() * 3);
151 | const axis = getRandomAxis();
152 | const dir = or(-1, 1);
153 | // Rotate a slice of cubes on `axis` at `index`
154 | this.rotateCubes(axis, index, dir);
155 | // Also rotate the camera randomly on a different access
156 | this.camTween = this.rotate(this.pivot, getRandomAxis(), dir * -1, Easing.Cubic.Out);
157 | this.camTween.onComplete(() => this.camTween = null);
158 |
159 | this.lastRotation = t;
160 | }
161 | this.camera.lookAt(new Vector3());
162 | this.camera.updateMatrixWorld();
163 |
164 | tweenUpdate();
165 | }
166 |
167 | render() {
168 | this.renderer.clearColor();
169 | this.composer.reset();
170 | this.composer.render(this.scene, this.camera);
171 | this.composer.pass(this.pass);
172 | this.composer.toScreen();
173 | }
174 | }
175 |
176 | export default new Experiment();
177 |
--------------------------------------------------------------------------------
/src/001/index.js:
--------------------------------------------------------------------------------
1 | import { SphereBufferGeometry, TextureLoader, AdditiveBlending, BufferAttribute, Points, Mesh, Object3D, ShaderMaterial, BoxBufferGeometry } from 'three';
2 | import ThreeApp from '../ThreeApp';
3 | import GPUComputationRenderer from '../lib/GPUComputationRenderer';
4 | import vertexShader from './vert.glsl';
5 | import fragmentShader from './frag.glsl';
6 | import computePositionShader from './compute-position.glsl';
7 | import computeVelocityShader from './compute-velocity.glsl';
8 | import WAGNER from '@alex_toudic/wagner';
9 | import BloomPass from '@alex_toudic/wagner/src/passes/bloom/MultiPassBloomPass';
10 |
11 | const scale = 1000;
12 | const size = 1;
13 | class Experiment extends ThreeApp {
14 | init() {
15 | this.renderer.setClearColor(0x111111);
16 | this.material = new ShaderMaterial({
17 | uniforms: {
18 | size: { value: size },
19 | time: { value: 0.0 },
20 | tPosition: { value: null },
21 | tVelocity: { value: null },
22 | sprite: { value: null },
23 | },
24 | fragmentShader,
25 | vertexShader,
26 | transparent: true,
27 | depthWrite: false,
28 | });
29 | this.material.blending = AdditiveBlending;
30 | this.textureLoader = new TextureLoader();
31 | this.textureLoader.load('particle.png', texture => {
32 | this.material.uniforms.sprite.value = texture;
33 | });
34 |
35 | this.setupGeometry();
36 |
37 | this.mesh = new Points(this.geometry, this.material);
38 | this.mesh.position.set(0, 0, 0);
39 |
40 | this.setupGPURenderer();
41 |
42 | this.pivot = new Object3D();
43 | this.pivot.add(this.camera);
44 | this.scene.add(this.mesh);
45 | this.scene.add(this.pivot);
46 | this.camera.position.set(0, 0, 4);
47 |
48 | this.composer = new WAGNER.Composer(this.renderer);
49 | this.pass = new BloomPass({
50 | zoomBlurStrength: 0.5,
51 | applyZoomBlur: true,
52 | blurAmount: 5,
53 | });
54 | }
55 |
56 | getTextureSize() {
57 | const count = this.geometry.getAttribute('position').count;
58 |
59 | let size = 2;
60 | while (size < Math.sqrt(count)) {
61 | size *= 2;
62 | }
63 |
64 | return size;
65 | }
66 |
67 | setupGeometry() {
68 | this.geometry = new SphereBufferGeometry(3,scale, scale);
69 |
70 | const verticesCount = this.geometry.getAttribute('position').count;
71 | console.log('Particle count: ', verticesCount);
72 | const width = this.getTextureSize();
73 | const uvs = new Float32Array(verticesCount * 2);
74 | let count = 0;
75 |
76 | for (let i = 0; i < width; i++) {
77 | for (let j = 0; j < width; j++) {
78 | uvs[count++] = i / (width - 1);
79 | uvs[count++] = j / (width - 1);
80 |
81 | if (count === verticesCount * 2) {
82 | break;
83 | }
84 | }
85 | if (count === verticesCount * 2) {
86 | break;
87 | }
88 | }
89 | this.geometry.addAttribute('uv', new BufferAttribute(uvs, 2));
90 | }
91 |
92 | setupGPURenderer() {
93 | const textureSize = this.getTextureSize();
94 | this.gpu = new GPUComputationRenderer(textureSize, textureSize, this.renderer);
95 |
96 | this.velTexture = this.gpu.createTexture();
97 | this.posTexture = this.gpu.createTexture();
98 |
99 | this.seedTextures();
100 |
101 | this.velVar = this.gpu.addVariable('tVelocity', computeVelocityShader, this.velTexture);
102 | this.posVar = this.gpu.addVariable('tPosition', computePositionShader, this.posTexture);
103 | this.gpu.setVariableDependencies(this.velVar, [this.velVar, this.posVar]);
104 | this.gpu.setVariableDependencies(this.posVar, [this.velVar, this.posVar]);
105 | this.velVar.material.uniforms.time = { value: 0.0 };
106 | this.posVar.material.uniforms.delta = { value: 0.0 };
107 |
108 | const error = this.gpu.init();
109 | if (error) {
110 | throw new Error(error);
111 | }
112 | }
113 |
114 | seedTextures() {
115 | const positionData = this.posTexture.image.data;
116 | const velocityData = this.velTexture.image.data;
117 |
118 | // Use BoxBufferGeometry's position to start in
119 | // the texture
120 | let posCount = 0;
121 | let geoPos = this.geometry.getAttribute('position');
122 |
123 | for (let i = 0; i < positionData.length; i += 4) {
124 | if (i / 4 >= geoPos.count) {
125 | positionData[i] = positionData[i + 1] = positionData[i + 2] = positionData[i + 3] = 0;
126 | velocityData[i] = velocityData[i + 1] = velocityData[i + 2] = velocityData[i + 3] = 0;
127 | } else {
128 | /*
129 | // Initial position from buffer geometry
130 | positionData[i] = geoPos.array[posCount++];
131 | positionData[i + 1] = geoPos.array[posCount++];
132 | positionData[i + 2] = geoPos.array[posCount++];
133 | positionData[i + 3] = 1;
134 | */
135 |
136 | let theta = Math.random() * Math.PI * 2;
137 | let phi = (Math.random() * Math.PI) - (Math.PI/2);
138 | let r = Math.random() * 1.5;
139 | positionData[i] = r * Math.cos(theta) * Math.cos(phi);
140 | positionData[i + 1] = r * Math.sin(phi);
141 | positionData[i + 2] = r * Math.sin(theta) * Math.cos(phi);
142 | positionData[i + 3] = 1;
143 |
144 | velocityData[i] = Math.random()*2 - 1;
145 | velocityData[i + 1] = Math.random()*2 - 1;
146 | velocityData[i + 2] = Math.random()*2-1;
147 | velocityData[i + 3] = 1;
148 | }
149 | }
150 | }
151 |
152 | update(t, delta) {
153 | this.pivot.rotation.y = t * 0.0001;
154 | this.material.uniforms.time.value = t;
155 | this.velVar.material.uniforms.time.value = t;
156 | this.posVar.material.uniforms.delta.value = delta / 1000;
157 | }
158 |
159 | render() {
160 | this.renderer.clearColor();
161 | this.gpu.compute();
162 | this.material.uniforms.tPosition.value = this.gpu.getCurrentRenderTarget(this.posVar).texture;
163 | this.material.uniforms.tVelocity.value = this.gpu.getCurrentRenderTarget(this.velVar).texture;
164 | this.composer.reset();
165 | this.composer.render(this.scene, this.camera);
166 | this.composer.pass(this.pass);
167 | this.composer.toScreen();
168 | // this.renderer.render(this.scene, this.camera);
169 | }
170 | }
171 |
172 | export default new Experiment();
173 |
--------------------------------------------------------------------------------
/src/lib/GPUComputationRenderer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @author yomboprime https://github.com/yomboprime
3 | *
4 | * GPUComputationRenderer, based on SimulationRenderer by zz85
5 | *
6 | * The GPUComputationRenderer uses the concept of variables. These variables are RGBA float textures that hold 4 floats
7 | * for each compute element (texel)
8 | *
9 | * Each variable has a fragment shader that defines the computation made to obtain the variable in question.
10 | * You can use as many variables you need, and make dependencies so you can use textures of other variables in the shader
11 | * (the sampler uniforms are added automatically) Most of the variables will need themselves as dependency.
12 | *
13 | * The renderer has actually two render targets per variable, to make ping-pong. Textures from the current frame are used
14 | * as inputs to render the textures of the next frame.
15 | *
16 | * The render targets of the variables can be used as input textures for your visualization shaders.
17 | *
18 | * Variable names should be valid identifiers and should not collide with THREE GLSL used identifiers.
19 | * a common approach could be to use 'texture' prefixing the variable name; i.e texturePosition, textureVelocity...
20 | *
21 | * The size of the computation (sizeX * sizeY) is defined as 'resolution' automatically in the shader. For example:
22 | * #DEFINE resolution vec2( 1024.0, 1024.0 )
23 | *
24 | * -------------
25 | *
26 | * Basic use:
27 | *
28 | * // Initialization...
29 | *
30 | * // Create computation renderer
31 | * var gpuCompute = new GPUComputationRenderer( 1024, 1024, renderer );
32 | *
33 | * // Create initial state float textures
34 | * var pos0 = gpuCompute.createTexture();
35 | * var vel0 = gpuCompute.createTexture();
36 | * // and fill in here the texture data...
37 | *
38 | * // Add texture variables
39 | * var velVar = gpuCompute.addVariable( "textureVelocity", fragmentShaderVel, pos0 );
40 | * var posVar = gpuCompute.addVariable( "texturePosition", fragmentShaderPos, vel0 );
41 | *
42 | * // Add variable dependencies
43 | * gpuCompute.setVariableDependencies( velVar, [ velVar, posVar ] );
44 | * gpuCompute.setVariableDependencies( posVar, [ velVar, posVar ] );
45 | *
46 | * // Add custom uniforms
47 | * velVar.material.uniforms.time = { value: 0.0 };
48 | *
49 | * // Check for completeness
50 | * var error = gpuCompute.init();
51 | * if ( error !== null ) {
52 | * console.error( error );
53 | * }
54 | *
55 | *
56 | * // In each frame...
57 | *
58 | * // Compute!
59 | * gpuCompute.compute();
60 | *
61 | * // Update texture uniforms in your visualization materials with the gpu renderer output
62 | * myMaterial.uniforms.myTexture.value = gpuCompute.getCurrentRenderTarget( posVar ).texture;
63 | *
64 | * // Do your rendering
65 | * renderer.render( myScene, myCamera );
66 | *
67 | * -------------
68 | *
69 | * Also, you can use utility functions to create ShaderMaterial and perform computations (rendering between textures)
70 | * Note that the shaders can have multiple input textures.
71 | *
72 | * var myFilter1 = gpuCompute.createShaderMaterial( myFilterFragmentShader1, { theTexture: { value: null } } );
73 | * var myFilter2 = gpuCompute.createShaderMaterial( myFilterFragmentShader2, { theTexture: { value: null } } );
74 | *
75 | * var inputTexture = gpuCompute.createTexture();
76 | *
77 | * // Fill in here inputTexture...
78 | *
79 | * myFilter1.uniforms.theTexture.value = inputTexture;
80 | *
81 | * var myRenderTarget = gpuCompute.createRenderTarget();
82 | * myFilter2.uniforms.theTexture.value = myRenderTarget.texture;
83 | *
84 | * var outputRenderTarget = gpuCompute.createRenderTarget();
85 | *
86 | * // Now use the output texture where you want:
87 | * myMaterial.uniforms.map.value = outputRenderTarget.texture;
88 | *
89 | * // And compute each frame, before rendering to screen:
90 | * gpuCompute.doRenderTarget( myFilter1, myRenderTarget );
91 | * gpuCompute.doRenderTarget( myFilter2, outputRenderTarget );
92 | *
93 | *
94 | *
95 | * @param {int} sizeX Computation problem size is always 2d: sizeX * sizeY elements.
96 | * @param {int} sizeY Computation problem size is always 2d: sizeX * sizeY elements.
97 | * @param {WebGLRenderer} renderer The renderer
98 | */
99 |
100 | export default function GPUComputationRenderer( sizeX, sizeY, renderer ) {
101 |
102 | this.variables = [];
103 |
104 | this.currentTextureIndex = 0;
105 |
106 | var scene = new THREE.Scene();
107 |
108 | var camera = new THREE.Camera();
109 | camera.position.z = 1;
110 |
111 | var passThruUniforms = {
112 | texture: { value: null }
113 | };
114 |
115 | var passThruShader = createShaderMaterial( getPassThroughFragmentShader(), passThruUniforms );
116 |
117 | var mesh = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), passThruShader );
118 | scene.add( mesh );
119 |
120 |
121 | this.addVariable = function( variableName, computeFragmentShader, initialValueTexture ) {
122 |
123 | var material = this.createShaderMaterial( computeFragmentShader );
124 |
125 | var variable = {
126 | name: variableName,
127 | initialValueTexture: initialValueTexture,
128 | material: material,
129 | dependencies: null,
130 | renderTargets: [],
131 | wrapS: null,
132 | wrapT: null,
133 | minFilter: THREE.NearestFilter,
134 | magFilter: THREE.NearestFilter
135 | };
136 |
137 | this.variables.push( variable );
138 |
139 | return variable;
140 |
141 | };
142 |
143 | this.setVariableDependencies = function( variable, dependencies ) {
144 |
145 | variable.dependencies = dependencies;
146 |
147 | };
148 |
149 | this.init = function() {
150 |
151 | if ( ! renderer.extensions.get( "OES_texture_float" ) ) {
152 |
153 | return "No OES_texture_float support for float textures.";
154 |
155 | }
156 |
157 | if ( renderer.capabilities.maxVertexTextures === 0 ) {
158 |
159 | return "No support for vertex shader textures.";
160 |
161 | }
162 |
163 | for ( var i = 0; i < this.variables.length; i++ ) {
164 |
165 | var variable = this.variables[ i ];
166 |
167 | // Creates rendertargets and initialize them with input texture
168 | variable.renderTargets[ 0 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
169 | variable.renderTargets[ 1 ] = this.createRenderTarget( sizeX, sizeY, variable.wrapS, variable.wrapT, variable.minFilter, variable.magFilter );
170 | this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 0 ] );
171 | this.renderTexture( variable.initialValueTexture, variable.renderTargets[ 1 ] );
172 |
173 | // Adds dependencies uniforms to the ShaderMaterial
174 | var material = variable.material;
175 | var uniforms = material.uniforms;
176 | if ( variable.dependencies !== null ) {
177 |
178 | for ( var d = 0; d < variable.dependencies.length; d++ ) {
179 |
180 | var depVar = variable.dependencies[ d ];
181 |
182 | if ( depVar.name !== variable.name ) {
183 |
184 | // Checks if variable exists
185 | var found = false;
186 | for ( var j = 0; j < this.variables.length; j++ ) {
187 |
188 | if ( depVar.name === this.variables[ j ].name ) {
189 | found = true;
190 | break;
191 | }
192 |
193 | }
194 | if ( ! found ) {
195 | return "Variable dependency not found. Variable=" + variable.name + ", dependency=" + depVar.name;
196 | }
197 |
198 | }
199 |
200 | uniforms[ depVar.name ] = { value: null };
201 |
202 | material.fragmentShader = "\nuniform sampler2D " + depVar.name + ";\n" + material.fragmentShader;
203 |
204 | }
205 | }
206 | }
207 |
208 | this.currentTextureIndex = 0;
209 |
210 | return null;
211 |
212 | };
213 |
214 | this.compute = function() {
215 |
216 | var currentTextureIndex = this.currentTextureIndex;
217 | var nextTextureIndex = this.currentTextureIndex === 0 ? 1 : 0;
218 |
219 | for ( var i = 0, il = this.variables.length; i < il; i++ ) {
220 |
221 | var variable = this.variables[ i ];
222 |
223 | // Sets texture dependencies uniforms
224 | if ( variable.dependencies !== null ) {
225 |
226 | var uniforms = variable.material.uniforms;
227 | for ( var d = 0, dl = variable.dependencies.length; d < dl; d++ ) {
228 |
229 | var depVar = variable.dependencies[ d ];
230 |
231 | uniforms[ depVar.name ].value = depVar.renderTargets[ currentTextureIndex ].texture;
232 |
233 | }
234 |
235 | }
236 |
237 | // Performs the computation for this variable
238 | this.doRenderTarget( variable.material, variable.renderTargets[ nextTextureIndex ] );
239 |
240 | }
241 |
242 | this.currentTextureIndex = nextTextureIndex;
243 | };
244 |
245 | this.getCurrentRenderTarget = function( variable ) {
246 |
247 | return variable.renderTargets[ this.currentTextureIndex ];
248 |
249 | };
250 |
251 | this.getAlternateRenderTarget = function( variable ) {
252 |
253 | return variable.renderTargets[ this.currentTextureIndex === 0 ? 1 : 0 ];
254 |
255 | };
256 |
257 | function addResolutionDefine( materialShader ) {
258 |
259 | materialShader.defines.resolution = 'vec2( ' + sizeX.toFixed( 1 ) + ', ' + sizeY.toFixed( 1 ) + " )";
260 |
261 | }
262 | this.addResolutionDefine = addResolutionDefine;
263 |
264 |
265 | // The following functions can be used to compute things manually
266 |
267 | function createShaderMaterial( computeFragmentShader, uniforms ) {
268 |
269 | uniforms = uniforms || {};
270 |
271 | var material = new THREE.ShaderMaterial( {
272 | uniforms: uniforms,
273 | vertexShader: getPassThroughVertexShader(),
274 | fragmentShader: computeFragmentShader
275 | } );
276 |
277 | addResolutionDefine( material );
278 |
279 | return material;
280 | }
281 | this.createShaderMaterial = createShaderMaterial;
282 |
283 | this.createRenderTarget = function( sizeXTexture, sizeYTexture, wrapS, wrapT, minFilter, magFilter ) {
284 |
285 | sizeXTexture = sizeXTexture || sizeX;
286 | sizeYTexture = sizeYTexture || sizeY;
287 |
288 | wrapS = wrapS || THREE.ClampToEdgeWrapping;
289 | wrapT = wrapT || THREE.ClampToEdgeWrapping;
290 |
291 | minFilter = minFilter || THREE.NearestFilter;
292 | magFilter = magFilter || THREE.NearestFilter;
293 |
294 | var renderTarget = new THREE.WebGLRenderTarget( sizeXTexture, sizeYTexture, {
295 | wrapS: wrapS,
296 | wrapT: wrapT,
297 | minFilter: minFilter,
298 | magFilter: magFilter,
299 | format: THREE.RGBAFormat,
300 | type: ( /(iPad|iPhone|iPod)/g.test( navigator.userAgent ) ) ? THREE.HalfFloatType : THREE.FloatType,
301 | stencilBuffer: false
302 | } );
303 |
304 | return renderTarget;
305 |
306 | };
307 |
308 | this.createTexture = function( sizeXTexture, sizeYTexture ) {
309 |
310 | sizeXTexture = sizeXTexture || sizeX;
311 | sizeYTexture = sizeYTexture || sizeY;
312 |
313 | var a = new Float32Array( sizeXTexture * sizeYTexture * 4 );
314 | var texture = new THREE.DataTexture( a, sizeX, sizeY, THREE.RGBAFormat, THREE.FloatType );
315 | texture.needsUpdate = true;
316 |
317 | return texture;
318 |
319 | };
320 |
321 |
322 | this.renderTexture = function( input, output ) {
323 |
324 | // Takes a texture, and render out in rendertarget
325 | // input = Texture
326 | // output = RenderTarget
327 |
328 | passThruUniforms.texture.value = input;
329 |
330 | this.doRenderTarget( passThruShader, output);
331 |
332 | passThruUniforms.texture.value = null;
333 |
334 | };
335 |
336 | this.doRenderTarget = function( material, output ) {
337 |
338 | mesh.material = material;
339 | renderer.render( scene, camera, output );
340 | mesh.material = passThruShader;
341 |
342 | };
343 |
344 | // Shaders
345 |
346 | function getPassThroughVertexShader() {
347 |
348 | return "void main() {\n" +
349 | "\n" +
350 | " gl_Position = vec4( position, 1.0 );\n" +
351 | "\n" +
352 | "}\n";
353 |
354 | }
355 |
356 | function getPassThroughFragmentShader() {
357 |
358 | return "uniform sampler2D texture;\n" +
359 | "\n" +
360 | "void main() {\n" +
361 | "\n" +
362 | " vec2 uv = gl_FragCoord.xy / resolution.xy;\n" +
363 | "\n" +
364 | " gl_FragColor = texture2D( texture, uv );\n" +
365 | "\n" +
366 | "}\n";
367 |
368 | }
369 |
370 | }
371 |
--------------------------------------------------------------------------------
/public/003/bundle.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory(require("three"), require("tween"));
4 | else if(typeof define === 'function' && define.amd)
5 | define(["three", "tween"], factory);
6 | else if(typeof exports === 'object')
7 | exports["app"] = factory(require("three"), require("tween"));
8 | else
9 | root["app"] = factory(root["THREE"], root["TWEEN"]);
10 | })(this, function(__WEBPACK_EXTERNAL_MODULE_0__, __WEBPACK_EXTERNAL_MODULE_29__) {
11 | return /******/ (function(modules) { // webpackBootstrap
12 | /******/ // The module cache
13 | /******/ var installedModules = {};
14 | /******/
15 | /******/ // The require function
16 | /******/ function __webpack_require__(moduleId) {
17 | /******/
18 | /******/ // Check if module is in cache
19 | /******/ if(installedModules[moduleId]) {
20 | /******/ return installedModules[moduleId].exports;
21 | /******/ }
22 | /******/ // Create a new module (and put it into the cache)
23 | /******/ var module = installedModules[moduleId] = {
24 | /******/ i: moduleId,
25 | /******/ l: false,
26 | /******/ exports: {}
27 | /******/ };
28 | /******/
29 | /******/ // Execute the module function
30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 | /******/
32 | /******/ // Flag the module as loaded
33 | /******/ module.l = true;
34 | /******/
35 | /******/ // Return the exports of the module
36 | /******/ return module.exports;
37 | /******/ }
38 | /******/
39 | /******/
40 | /******/ // expose the modules object (__webpack_modules__)
41 | /******/ __webpack_require__.m = modules;
42 | /******/
43 | /******/ // expose the module cache
44 | /******/ __webpack_require__.c = installedModules;
45 | /******/
46 | /******/ // define getter function for harmony exports
47 | /******/ __webpack_require__.d = function(exports, name, getter) {
48 | /******/ if(!__webpack_require__.o(exports, name)) {
49 | /******/ Object.defineProperty(exports, name, {
50 | /******/ configurable: false,
51 | /******/ enumerable: true,
52 | /******/ get: getter
53 | /******/ });
54 | /******/ }
55 | /******/ };
56 | /******/
57 | /******/ // getDefaultExport function for compatibility with non-harmony modules
58 | /******/ __webpack_require__.n = function(module) {
59 | /******/ var getter = module && module.__esModule ?
60 | /******/ function getDefault() { return module['default']; } :
61 | /******/ function getModuleExports() { return module; };
62 | /******/ __webpack_require__.d(getter, 'a', getter);
63 | /******/ return getter;
64 | /******/ };
65 | /******/
66 | /******/ // Object.prototype.hasOwnProperty.call
67 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
68 | /******/
69 | /******/ // __webpack_public_path__
70 | /******/ __webpack_require__.p = "";
71 | /******/
72 | /******/ // Load entry module and return exports
73 | /******/ return __webpack_require__(__webpack_require__.s = 28);
74 | /******/ })
75 | /************************************************************************/
76 | /******/ ([
77 | /* 0 */
78 | /***/ (function(module, exports) {
79 |
80 | module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
81 |
82 | /***/ }),
83 | /* 1 */
84 | /***/ (function(module, exports, __webpack_require__) {
85 |
86 | "use strict";
87 |
88 |
89 | var THREE = __webpack_require__(0);
90 | var processShader = __webpack_require__(8);
91 |
92 | function Pass() {
93 | this.shader = null;
94 | this.loaded = null;
95 | this.params = {};
96 | this.isSim = false;
97 | }
98 |
99 | module.exports = Pass;
100 |
101 | Pass.prototype.setShader = function(vs, fs) {
102 | this.shader = processShader(vs, fs);
103 | };
104 |
105 | Pass.prototype.run = function(composer) {
106 | composer.pass(this.shader);
107 | };
108 |
109 | Pass.prototype.getOfflineTexture = function(w, h, useRGBA) {
110 | return new THREE.WebGLRenderTarget(w, h, {
111 | minFilter: THREE.LinearFilter,
112 | magFilter: THREE.LinearFilter,
113 | format: useRGBA ? THREE.RGBAFormat : THREE.RGBFormat
114 | });
115 | };
116 |
117 |
118 | /***/ }),
119 | /* 2 */
120 | /***/ (function(module, exports) {
121 |
122 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\n\nvoid main() {\n\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}"
123 |
124 | /***/ }),
125 | /* 3 */
126 | /***/ (function(module, exports, __webpack_require__) {
127 |
128 | "use strict";
129 |
130 |
131 | var Pass = __webpack_require__(1);
132 | var vertex = __webpack_require__(2);
133 | var fragment = __webpack_require__(9);
134 |
135 | function CopyPass() {
136 | Pass.call(this);
137 | this.setShader(vertex, fragment);
138 | }
139 |
140 | module.exports = CopyPass;
141 |
142 | CopyPass.prototype = Object.create(Pass.prototype);
143 | CopyPass.prototype.constructor = CopyPass;
144 |
145 |
146 | /***/ }),
147 | /* 4 */
148 | /***/ (function(module, exports, __webpack_require__) {
149 |
150 | "use strict";
151 |
152 |
153 | module.exports.Composer = __webpack_require__(5);
154 | module.exports.CopyPass = __webpack_require__(3);
155 | module.exports.BlendMode = {
156 | Normal: 1,
157 | Dissolve: 2, // UNAVAILABLE
158 | Darken: 3,
159 | Multiply: 4,
160 | ColorBurn: 5,
161 | LinearBurn: 6,
162 | DarkerColor: 7, // UNAVAILABLE
163 | Lighten: 8,
164 | Screen: 9,
165 | ColorDodge: 10,
166 | LinearDodge: 11,
167 | LighterColor: 12, // UNAVAILABLE
168 | Overlay: 13,
169 | SoftLight: 14,
170 | HardLight: 15,
171 | VividLight: 16, // UNAVAILABLE
172 | LinearLight: 17,
173 | PinLight: 18, // UNAVAILABLE
174 | HardMix: 19, // UNAVAILABLE
175 | Difference: 20,
176 | Exclusion: 21,
177 | Substract: 22, // UNAVAILABLE
178 | Divide: 23 // UNAVAILABLE
179 | };
180 |
181 |
182 | /***/ }),
183 | /* 5 */
184 | /***/ (function(module, exports, __webpack_require__) {
185 |
186 | "use strict";
187 |
188 |
189 | var THREE = __webpack_require__(0);
190 | var CopyPass = __webpack_require__(3);
191 | var Stack = __webpack_require__(10);
192 | var Pass = __webpack_require__(1);
193 |
194 | function Composer(renderer, settings) {
195 | var pixelRatio = renderer.getPixelRatio();
196 |
197 | this.width = Math.floor(renderer.context.canvas.width / pixelRatio) || 1;
198 | this.height = Math.floor(renderer.context.canvas.height / pixelRatio) || 1;
199 |
200 | this.output = null;
201 | this.input = null;
202 | this.read = null;
203 | this.write = null;
204 |
205 | this.settings = settings || {};
206 | this.useRGBA = this.settings.useRGBA || false;
207 |
208 | this.renderer = renderer;
209 | this.copyPass = new CopyPass(this.settings);
210 |
211 | this.defaultMaterial = new THREE.MeshBasicMaterial({color: 0x00FF00, wireframe: false});
212 | this.scene = new THREE.Scene();
213 | this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(1, 1), this.defaultMaterial);
214 | this.scene.add(this.quad);
215 | this.camera = new THREE.OrthographicCamera(1, 1, 1, 1, -10000, 10000);
216 |
217 | this.front = new THREE.WebGLRenderTarget(1, 1, {
218 | minFilter: this.settings.minFilter !== undefined ? this.settings.minFilter : THREE.LinearFilter,
219 | magFilter: this.settings.magFilter !== undefined ? this.settings.magFilter : THREE.LinearFilter,
220 | wrapS: this.settings.wrapS !== undefined ? this.settings.wrapS : THREE.ClampToEdgeWrapping,
221 | wrapT: this.settings.wrapT !== undefined ? this.settings.wrapT : THREE.ClampToEdgeWrapping,
222 | format: this.useRGBA ? THREE.RGBAFormat : THREE.RGBFormat,
223 | type: this.settings.type !== undefined ? this.settings.type : THREE.UnsignedByteType,
224 | stencilBuffer: this.settings.stencilBuffer !== undefined ? this.settings.stencilBuffer : true
225 | });
226 |
227 | this.back = this.front.clone();
228 | this.startTime = Date.now();
229 | this.passes = {};
230 |
231 | this.setSize(this.width, this.height);
232 | }
233 |
234 | module.exports = Composer;
235 |
236 | Composer.prototype.swapBuffers = function() {
237 | this.output = this.write;
238 | this.input = this.read;
239 |
240 | var t = this.write;
241 | this.write = this.read;
242 | this.read = t;
243 | };
244 |
245 | Composer.prototype.render = function(scene, camera, keep, output) {
246 | if (keep) this.swapBuffers();
247 | this.renderer.render(scene, camera, output ? output : this.write, true);
248 | if (!output) this.swapBuffers();
249 | };
250 |
251 | Composer.prototype.toScreen = function() {
252 | this.quad.material = this.copyPass.shader;
253 | this.quad.material.uniforms.tInput.value = this.read;
254 | this.quad.material.uniforms.resolution.value.set(this.width, this.height);
255 | this.renderer.render(this.scene, this.camera);
256 | };
257 |
258 | Composer.prototype.toTexture = function(t) {
259 | this.quad.material = this.copyPass.shader;
260 | this.quad.material.uniforms.tInput.value = this.read;
261 | this.renderer.render(this.scene, this.camera, t, false);
262 | };
263 |
264 | Composer.prototype.pass = function(pass) {
265 | if (pass instanceof Stack) {
266 | this.passStack(pass);
267 | }
268 | else {
269 | if (pass instanceof THREE.ShaderMaterial) {
270 | this.quad.material = pass;
271 | }
272 | if (pass instanceof Pass) {
273 | pass.run(this);
274 | return;
275 | }
276 |
277 | if (!pass.isSim) {
278 | this.quad.material.uniforms.tInput.value = this.read;
279 | }
280 |
281 | this.quad.material.uniforms.resolution.value.set(this.width, this.height);
282 | this.quad.material.uniforms.time.value = 0.001 * (Date.now() - this.startTime);
283 | this.renderer.render(this.scene, this.camera, this.write, false);
284 | this.swapBuffers();
285 | }
286 | };
287 |
288 | Composer.prototype.passStack = function(stack) {
289 | stack.getPasses().forEach(function(pass) {
290 | this.pass(pass);
291 | }.bind(this));
292 | };
293 |
294 | Composer.prototype.reset = function() {
295 | this.read = this.front;
296 | this.write = this.back;
297 | this.output = this.write;
298 | this.input = this.read;
299 | };
300 |
301 | Composer.prototype.setSource = function(src) {
302 | this.quad.material = this.copyPass.shader;
303 | this.quad.material.uniforms.tInput.value = src;
304 | this.renderer.render(this.scene, this.camera, this.write, true);
305 | this.swapBuffers();
306 | };
307 |
308 | Composer.prototype.setSize = function(w, h) {
309 | this.width = w;
310 | this.height = h;
311 |
312 | this.camera.projectionMatrix.makeOrthographic( w / - 2, w / 2, h / 2, h / - 2, this.camera.near, this.camera.far );
313 | this.quad.scale.set( w, h, 1 );
314 |
315 | this.front.setSize( w, h );
316 | this.back.setSize( w, h );
317 | };
318 |
319 |
320 |
321 | /***/ }),
322 | /* 6 */
323 | /***/ (function(module, exports, __webpack_require__) {
324 |
325 | "use strict";
326 |
327 |
328 | Object.defineProperty(exports, "__esModule", {
329 | value: true
330 | });
331 |
332 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
333 |
334 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
335 |
336 | var _three = __webpack_require__(0);
337 |
338 | var _stats = __webpack_require__(7);
339 |
340 | var _stats2 = _interopRequireDefault(_stats);
341 |
342 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
343 |
344 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
345 |
346 | var App = function () {
347 | function App() {
348 | _classCallCheck(this, App);
349 |
350 | if (window.location.search) {
351 | var params = window.location.search.substr(1).split('&');
352 | var _iteratorNormalCompletion = true;
353 | var _didIteratorError = false;
354 | var _iteratorError = undefined;
355 |
356 | try {
357 | for (var _iterator = params[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
358 | var param = _step.value;
359 |
360 | var _param$split = param.split('='),
361 | _param$split2 = _slicedToArray(_param$split, 2),
362 | prop = _param$split2[0],
363 | value = _param$split2[1];
364 |
365 | if (prop === 'debug') {
366 | this.stats = new _stats2.default();
367 | this.stats.showPanel(0);
368 | document.body.appendChild(this.stats.dom);
369 | }
370 | }
371 | } catch (err) {
372 | _didIteratorError = true;
373 | _iteratorError = err;
374 | } finally {
375 | try {
376 | if (!_iteratorNormalCompletion && _iterator.return) {
377 | _iterator.return();
378 | }
379 | } finally {
380 | if (_didIteratorError) {
381 | throw _iteratorError;
382 | }
383 | }
384 | }
385 | }
386 | this.renderer = new _three.WebGLRenderer();
387 | this.renderer.setPixelRatio(window.devicePixelRatio);
388 | this.renderer.setSize(window.innerWidth, window.innerHeight);
389 | this.renderer.autoClear = false;
390 | document.body.appendChild(this.renderer.domElement);
391 |
392 | this.scene = new _three.Scene();
393 |
394 | this.camera = new _three.PerspectiveCamera(60, this.getAspect(), 0.1, 100);
395 |
396 | this.onResize = this.onResize.bind(this);
397 | window.addEventListener('resize', this.onResize);
398 |
399 | this.init();
400 |
401 | this.lastTick = 0;
402 | this.onTick = this.onTick.bind(this);
403 | requestAnimationFrame(this.onTick);
404 | }
405 |
406 | _createClass(App, [{
407 | key: 'onTick',
408 | value: function onTick() {
409 | var t = performance.now();
410 | var delta = performance.now() - this.lastTick;
411 | if (this.stats) {
412 | this.stats.begin();
413 | }
414 | this.update(t, delta);
415 | this.render(t, delta);
416 | if (this.stats) {
417 | this.stats.end();
418 | }
419 | this.lastTick = t;
420 | requestAnimationFrame(this.onTick);
421 | }
422 | }, {
423 | key: 'getAspect',
424 | value: function getAspect() {
425 | return window.innerWidth / window.innerHeight;
426 | }
427 | }, {
428 | key: 'onResize',
429 | value: function onResize() {
430 | this.camera.aspect = this.getAspect();
431 | this.camera.updateProjectionMatrix();
432 | this.renderer.setSize(window.innerWidth, window.innerHeight);
433 | }
434 | }]);
435 |
436 | return App;
437 | }();
438 |
439 | exports.default = App;
440 |
441 | /***/ }),
442 | /* 7 */
443 | /***/ (function(module, exports, __webpack_require__) {
444 |
445 | // stats.js - http://github.com/mrdoob/stats.js
446 | (function(f,e){ true?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;dg+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/
448 | 1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=h;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);
449 | b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+" "+e+" ("+g(c)+"-"+g(k)+")",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});
450 |
451 |
452 | /***/ }),
453 | /* 8 */
454 | /***/ (function(module, exports, __webpack_require__) {
455 |
456 | "use strict";
457 |
458 |
459 | var THREE = __webpack_require__(0);
460 |
461 | module.exports = function processShader(vertexShaderCode, fragmentShaderCode) {
462 |
463 | var regExp = /uniform\s+([^\s]+)\s+([^\s]+)\s*;/gi;
464 | var regExp2 = /uniform\s+([^\s]+)\s+([^\s]+)\s*\[\s*(\w+)\s*\]*\s*;/gi;
465 |
466 | var typesMap = {
467 | sampler2D: { type: 't', value: function() { return new THREE.Texture(); } },
468 | samplerCube: { type: 't', value: function() {} },
469 |
470 | bool: { type: 'b', value: function() { return 0; } },
471 | int: { type: 'i', value: function() { return 0; } },
472 | float: { type: 'f', value: function() { return 0; } },
473 |
474 | vec2: { type: 'v2', value: function() { return new THREE.Vector2(); } },
475 | vec3: { type: 'v3', value: function() { return new THREE.Vector3(); } },
476 | vec4: { type: 'v4', value: function() { return new THREE.Vector4(); } },
477 |
478 | bvec2: { type: 'v2', value: function() { return new THREE.Vector2(); } },
479 | bvec3: { type: 'v3', value: function() { return new THREE.Vector3(); } },
480 | bvec4: { type: 'v4', value: function() { return new THREE.Vector4(); } },
481 |
482 | ivec2: { type: 'v2', value: function() { return new THREE.Vector2(); } },
483 | ivec3: { type: 'v3', value: function() { return new THREE.Vector3(); } },
484 | ivec4: { type: 'v4', value: function() { return new THREE.Vector4(); } },
485 |
486 | mat2: { type: 'v2', value: function() { return new THREE.Matrix2(); } },
487 | mat3: { type: 'v3', value: function() { return new THREE.Matrix3(); } },
488 | mat4: { type: 'v4', value: function() { return new THREE.Matrix4(); } }
489 | };
490 |
491 | var arrayTypesMap = {
492 | float: { type: 'fv', value: function() { return []; } },
493 | vec3: { type: 'v3v', value: function() { return []; } }
494 | };
495 |
496 | var matches;
497 | var uniforms = {
498 | resolution: { type: 'v2', value: new THREE.Vector2( 1, 1 ), default: true },
499 | time: { type: 'f', value: Date.now(), default: true },
500 | tInput: { type: 't', value: new THREE.Texture(), default: true }
501 | };
502 |
503 | var uniformType, uniformName, arraySize;
504 |
505 | while ((matches = regExp.exec(fragmentShaderCode)) !== null) {
506 | if (matches.index === regExp.lastIndex) {
507 | regExp.lastIndex++;
508 | }
509 | uniformType = matches[1];
510 | uniformName = matches[2];
511 |
512 | uniforms[uniformName] = {
513 | type: typesMap[uniformType].type,
514 | value: typesMap[uniformType].value()
515 | };
516 | }
517 |
518 | while ((matches = regExp2.exec(fragmentShaderCode)) !== null) {
519 | if (matches.index === regExp.lastIndex) {
520 | regExp.lastIndex++;
521 | }
522 | uniformType = matches[1];
523 | uniformName = matches[2];
524 | arraySize = matches[3];
525 |
526 | uniforms[uniformName] = {
527 | type: arrayTypesMap[uniformType].type,
528 | value: arrayTypesMap[uniformType].value()
529 | };
530 | }
531 |
532 | var shader = new THREE.ShaderMaterial({
533 | uniforms: uniforms,
534 | vertexShader: vertexShaderCode,
535 | fragmentShader: fragmentShaderCode,
536 | shading: THREE.FlatShading,
537 | depthWrite: false,
538 | depthTest: false,
539 | transparent: true
540 | });
541 |
542 | return shader;
543 | };
544 |
545 | /***/ }),
546 | /* 9 */
547 | /***/ (function(module, exports) {
548 |
549 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\nuniform sampler2D tInput;\n\nvoid main() {\n gl_FragColor = texture2D( tInput, vUv );\n\n}"
550 |
551 | /***/ }),
552 | /* 10 */
553 | /***/ (function(module, exports, __webpack_require__) {
554 |
555 | "use strict";
556 |
557 |
558 | function Stack(shadersPool) {
559 | this.passItems = [];
560 | this.shadersPool = shadersPool;
561 | this.passes = [];
562 | }
563 |
564 | module.exports = Stack;
565 |
566 | Stack.prototype.addPass = function(shaderName, enabled, params, index) {
567 | var length = 0;
568 | var passItem = {
569 | shaderName: shaderName,
570 | enabled: enabled || false
571 | };
572 |
573 | // TODO use and store params values
574 |
575 | this.passItems.push(passItem);
576 | length = this.passItems.length;
577 |
578 | this.updatePasses();
579 |
580 | if (index) {
581 | return this.movePassToIndex(this.passItems[length], index);
582 | }
583 | else {
584 | return length - 1;
585 | }
586 | };
587 |
588 | Stack.prototype.removePass = function(index) {
589 | this.passItems.splice(index, 1);
590 | this.updatePasses();
591 | };
592 |
593 | Stack.prototype.enablePass = function(index) {
594 | this.passItems[index].enabled = true;
595 | this.updatePasses();
596 | };
597 |
598 | Stack.prototype.disablePass = function(index) {
599 | this.passItems[index].enabled = false;
600 | this.updatePasses();
601 | };
602 |
603 | Stack.prototype.isPassEnabled = function(index) {
604 | return this.passItems[index].enabled;
605 | };
606 |
607 | Stack.prototype.movePassToIndex = function(index, destIndex) {
608 | this.passItems.splice(destIndex, 0, this.passItems.splice(index, 1)[0]);
609 | this.updatePasses();
610 |
611 | // TODO check if destIndex is final index
612 | return destIndex;
613 | };
614 |
615 | Stack.prototype.reverse = function() {
616 | this.passItems.reverse();
617 | this.updatePasses();
618 | };
619 |
620 | Stack.prototype.updatePasses = function() {
621 | this.passes = this.shadersPool.getPasses(this.passItems);
622 |
623 | // init default params for new passItems
624 | this.passItems.forEach(function(passItem, index) {
625 | if (passItem.params === undefined) {
626 | passItem.params = JSON.parse(JSON.stringify(this.passes[index].params)); // clone params without reference to the real shader instance params
627 | }
628 | }.bind(this));
629 | };
630 |
631 | Stack.prototype.getPasses = function() {
632 | return this.passes;
633 | };
634 |
635 |
636 | /***/ }),
637 | /* 11 */,
638 | /* 12 */,
639 | /* 13 */,
640 | /* 14 */,
641 | /* 15 */,
642 | /* 16 */,
643 | /* 17 */,
644 | /* 18 */,
645 | /* 19 */,
646 | /* 20 */,
647 | /* 21 */,
648 | /* 22 */,
649 | /* 23 */,
650 | /* 24 */,
651 | /* 25 */,
652 | /* 26 */,
653 | /* 27 */,
654 | /* 28 */
655 | /***/ (function(module, exports, __webpack_require__) {
656 |
657 | "use strict";
658 |
659 |
660 | Object.defineProperty(exports, "__esModule", {
661 | value: true
662 | });
663 |
664 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
665 |
666 | var _three = __webpack_require__(0);
667 |
668 | var _tween = __webpack_require__(29);
669 |
670 | var _ThreeApp2 = __webpack_require__(6);
671 |
672 | var _ThreeApp3 = _interopRequireDefault(_ThreeApp2);
673 |
674 | var _frag = __webpack_require__(30);
675 |
676 | var _frag2 = _interopRequireDefault(_frag);
677 |
678 | var _vert = __webpack_require__(31);
679 |
680 | var _vert2 = _interopRequireDefault(_vert);
681 |
682 | var _wagner = __webpack_require__(4);
683 |
684 | var _wagner2 = _interopRequireDefault(_wagner);
685 |
686 | var _VignettePass = __webpack_require__(32);
687 |
688 | var _VignettePass2 = _interopRequireDefault(_VignettePass);
689 |
690 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
691 |
692 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
693 |
694 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
695 |
696 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
697 |
698 | var ROTATION_DELAY = 100;
699 | var ROTATION_SPEED = 800;
700 | var DIMENSIONS = 3;
701 | var CUBE_SCALE = 1.0;
702 | var CUBE_DISTANCE_SCALE = 1.0;
703 | var EASING = _tween.Easing.Back.Out;
704 | var BG_COLOR = 0x333333;
705 |
706 | // Randomly return val1 or val2
707 | var or = function or(val1, val2) {
708 | return Math.random() > 0.5 ? val1 : val2;
709 | };
710 | // Pass in an axis ('x', 'y', 'z') and return a different axis
711 | var getDifferentAxis = function getDifferentAxis(axis) {
712 | return axis === 'x' ? or('y', 'z') : axis === 'y' ? or('x', 'z') : or('y', 'x');
713 | };
714 | var getRandomAxis = function getRandomAxis() {
715 | return ['x', 'y', 'z'][Math.floor(Math.random() * 3)];
716 | };
717 |
718 | var Experiment = function (_ThreeApp) {
719 | _inherits(Experiment, _ThreeApp);
720 |
721 | function Experiment() {
722 | _classCallCheck(this, Experiment);
723 |
724 | return _possibleConstructorReturn(this, (Experiment.__proto__ || Object.getPrototypeOf(Experiment)).apply(this, arguments));
725 | }
726 |
727 | _createClass(Experiment, [{
728 | key: 'init',
729 | value: function init() {
730 | this.renderer.setClearColor(BG_COLOR);
731 | this.curves = [];
732 |
733 | this.cubeGroup = new _three.Object3D();
734 | this.rotationHelper = new _three.Object3D();
735 | this.cubeGroup.add(this.rotationHelper);
736 | this.scene.add(this.cubeGroup);
737 | this.material = new _three.ShaderMaterial({
738 | vertexShader: _vert2.default,
739 | fragmentShader: _frag2.default,
740 | uniforms: {
741 | fgColor: { value: new _three.Color(0xffffff) },
742 | bgColor: { value: new _three.Color(BG_COLOR) }
743 | }
744 | });
745 |
746 | this.createCubes();
747 |
748 | this.pivot = new _three.Object3D();
749 | this.scene.add(this.pivot);
750 | this.camera.lookAt(new _three.Vector3());
751 | this.pivot.add(this.camera);
752 | this.camera.position.set(4, 4, 4);
753 |
754 | this.lastRotation = 0;
755 | this.composer = new _wagner2.default.Composer(this.renderer);
756 | this.pass = new _VignettePass2.default(0.9, 1.0);
757 | }
758 | }, {
759 | key: 'createCubes',
760 | value: function createCubes() {
761 | this.cubes = [];
762 |
763 | /**
764 | * Store cubes in plane, row, columns, below
765 | * is a face
766 | *
767 | * z,y,x
768 | *
769 | * 0,0,0 0,0,1 0,0,2
770 | * 0,1,0 0,1,1 0,1,2
771 | * 0,2,0 0,2,1 0,2,2
772 | *
773 | */
774 | var solid = this.material;
775 | var transparent = new _three.MeshBasicMaterial({ opacity: 0, transparent: true });
776 | var last = DIMENSIONS - 1;
777 | for (var z = 0; z < DIMENSIONS; z++) {
778 | var plane = this.cubes[z] = [];
779 | for (var y = 0; y < DIMENSIONS; y++) {
780 | var row = plane[y] = [];
781 | for (var x = 0; x < DIMENSIONS; x++) {
782 | var cube = new _three.Mesh(new _three.BoxGeometry(CUBE_SCALE, CUBE_SCALE, CUBE_SCALE), [x === last ? solid : transparent, // bot right
783 | x === 0 ? solid : transparent, // back left
784 | y === last ? solid : transparent, // top
785 | y === 0 ? solid : transparent, // bottom
786 | z === last ? solid : transparent, // bot left
787 | z === 0 ? solid : transparent]);
788 | row[x] = cube;
789 | this.cubeGroup.add(cube);
790 |
791 | var half = DIMENSIONS % 2 === 0 ? DIMENSIONS / 2 - 0.5 : Math.floor(DIMENSIONS / 2);
792 | cube.position.set((x - half) * CUBE_DISTANCE_SCALE, (y - half) * CUBE_DISTANCE_SCALE, (z - half) * CUBE_DISTANCE_SCALE);
793 | }
794 | }
795 | }
796 | }
797 | }, {
798 | key: 'getCubesBySlice',
799 | value: function getCubesBySlice(axis, index) {
800 | // I'm sure there's a better way for this
801 | var cubes = [];
802 | for (var z = 0; z < DIMENSIONS; z++) {
803 | for (var y = 0; y < DIMENSIONS; y++) {
804 | for (var x = 0; x < DIMENSIONS; x++) {
805 | var r = axis === 'z' ? z : axis === 'y' ? y : x;
806 | if (r === index) {
807 | var cube = this.cubes[z][y][x];
808 | cubes.push(cube);
809 | }
810 | }
811 | }
812 | }
813 | return cubes;
814 | }
815 | }, {
816 | key: 'rotateCubes',
817 | value: function rotateCubes(axis, index, dir) {
818 | var _this2 = this;
819 |
820 | var cubes = this.getCubesBySlice(axis, index);
821 | var _iteratorNormalCompletion = true;
822 | var _didIteratorError = false;
823 | var _iteratorError = undefined;
824 |
825 | try {
826 | for (var _iterator = cubes[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
827 | var cube = _step.value;
828 |
829 | this.cubeGroup.remove(cube);
830 | this.rotationHelper.add(cube);
831 | }
832 | } catch (err) {
833 | _didIteratorError = true;
834 | _iteratorError = err;
835 | } finally {
836 | try {
837 | if (!_iteratorNormalCompletion && _iterator.return) {
838 | _iterator.return();
839 | }
840 | } finally {
841 | if (_didIteratorError) {
842 | throw _iteratorError;
843 | }
844 | }
845 | }
846 |
847 | this.cubeTween = this.rotate(this.rotationHelper, axis, dir);
848 | this.cubeTween.onComplete(function () {
849 | cubes.forEach(function (c) {
850 | _this2.cubeGroup.add(c);
851 | _this2.rotationHelper.remove(c);
852 | });
853 | _this2.rotationHelper.rotation.set(0, 0, 0);
854 | _this2.cubeTween = null;
855 | });
856 | }
857 | }, {
858 | key: 'rotate',
859 | value: function rotate(object, axis, dir, easing) {
860 | var startRotation = object.rotation[axis];
861 |
862 | return new _tween.Tween({ x: 0 }).to({ x: 1 }, ROTATION_SPEED).onUpdate(function (value) {
863 | object.rotation[axis] = startRotation + value * Math.PI / 2 * dir;
864 | }).easing(easing || EASING).start();
865 | }
866 | }, {
867 | key: 'update',
868 | value: function update(t, delta) {
869 | var _this3 = this;
870 |
871 | if (this.lastRotation + ROTATION_SPEED + ROTATION_DELAY < t && !this.camTween && !this.cubeTween) {
872 | var index = Math.floor(Math.random() * 3);
873 | var axis = getRandomAxis();
874 | var dir = or(-1, 1);
875 | // Rotate a slice of cubes on `axis` at `index`
876 | this.rotateCubes(axis, index, dir);
877 | // Also rotate the camera randomly on a different access
878 | this.camTween = this.rotate(this.pivot, getRandomAxis(), dir * -1, _tween.Easing.Cubic.Out);
879 | this.camTween.onComplete(function () {
880 | return _this3.camTween = null;
881 | });
882 |
883 | this.lastRotation = t;
884 | }
885 | this.camera.lookAt(new _three.Vector3());
886 | this.camera.updateMatrixWorld();
887 |
888 | (0, _tween.update)();
889 | }
890 | }, {
891 | key: 'render',
892 | value: function render() {
893 | this.renderer.clearColor();
894 | this.composer.reset();
895 | this.composer.render(this.scene, this.camera);
896 | this.composer.pass(this.pass);
897 | this.composer.toScreen();
898 | }
899 | }]);
900 |
901 | return Experiment;
902 | }(_ThreeApp3.default);
903 |
904 | exports.default = new Experiment();
905 |
906 | /***/ }),
907 | /* 29 */
908 | /***/ (function(module, exports) {
909 |
910 | module.exports = __WEBPACK_EXTERNAL_MODULE_29__;
911 |
912 | /***/ }),
913 | /* 30 */
914 | /***/ (function(module, exports) {
915 |
916 | module.exports = "#define GLSLIFY 1\nuniform vec3 fgColor;\nuniform vec3 bgColor;\n\nvarying vec2 vUv;\n\nfloat when_gt_1_0(float x, float y) {\n return max(sign(x - y), 0.0);\n}\n\nvec2 when_gt_1_0(vec2 x, vec2 y) {\n return max(sign(x - y), 0.0);\n}\n\nvec3 when_gt_1_0(vec3 x, vec3 y) {\n return max(sign(x - y), 0.0);\n}\n\nvec4 when_gt_1_0(vec4 x, vec4 y) {\n return max(sign(x - y), 0.0);\n}\n\n\n\n\nvoid main() {\n float limit = 0.1;\n vec3 color = fgColor;\n\n float isTiled = 0.0;\n isTiled += when_gt_1_0(limit, vUv.x);\n isTiled += when_gt_1_0(limit, vUv.y);\n isTiled += when_gt_1_0(vUv.x, 1.0 - limit);\n isTiled += when_gt_1_0(vUv.y, 1.0 - limit);\n\n color = (step(1.0, isTiled) * bgColor) + ((1.0 - step(1.0, isTiled)) * fgColor);\n gl_FragColor = vec4(color, 1.0);\n}\n"
917 |
918 | /***/ }),
919 | /* 31 */
920 | /***/ (function(module, exports) {
921 |
922 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\n\nvoid main() {\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}\n"
923 |
924 | /***/ }),
925 | /* 32 */
926 | /***/ (function(module, exports, __webpack_require__) {
927 |
928 | "use strict";
929 |
930 |
931 | var Pass = __webpack_require__(1);
932 | var vertex = __webpack_require__(2);
933 | var fragment = __webpack_require__(33);
934 |
935 | function VignettePass(boost, reduction) {
936 | Pass.call(this);
937 |
938 | this.setShader(vertex, fragment);
939 |
940 | this.params.boost = boost || 2;
941 | this.params.reduction = reduction || 2;
942 | }
943 |
944 | module.exports = VignettePass;
945 |
946 | VignettePass.prototype = Object.create(Pass.prototype);
947 | VignettePass.prototype.constructor = VignettePass;
948 |
949 | VignettePass.prototype.run = function(composer) {
950 | this.shader.uniforms.boost.value = this.params.boost;
951 | this.shader.uniforms.reduction.value = this.params.reduction;
952 | composer.pass(this.shader);
953 | };
954 |
955 |
956 | /***/ }),
957 | /* 33 */
958 | /***/ (function(module, exports) {
959 |
960 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\nuniform sampler2D tInput;\nuniform vec2 resolution;\n\nuniform float reduction;\nuniform float boost;\n\nvoid main() {\n\n vec4 color = texture2D( tInput, vUv );\n\n vec2 center = resolution * 0.5;\n float vignette = distance( center, gl_FragCoord.xy ) / resolution.x;\n vignette = boost - vignette * reduction;\n\n color.rgb *= vignette;\n gl_FragColor = color;\n\n}"
961 |
962 | /***/ })
963 | /******/ ]);
964 | });
--------------------------------------------------------------------------------
/public/002/bundle.js:
--------------------------------------------------------------------------------
1 | (function webpackUniversalModuleDefinition(root, factory) {
2 | if(typeof exports === 'object' && typeof module === 'object')
3 | module.exports = factory(require("three"));
4 | else if(typeof define === 'function' && define.amd)
5 | define(["three"], factory);
6 | else if(typeof exports === 'object')
7 | exports["app"] = factory(require("three"));
8 | else
9 | root["app"] = factory(root["THREE"]);
10 | })(this, function(__WEBPACK_EXTERNAL_MODULE_0__) {
11 | return /******/ (function(modules) { // webpackBootstrap
12 | /******/ // The module cache
13 | /******/ var installedModules = {};
14 | /******/
15 | /******/ // The require function
16 | /******/ function __webpack_require__(moduleId) {
17 | /******/
18 | /******/ // Check if module is in cache
19 | /******/ if(installedModules[moduleId]) {
20 | /******/ return installedModules[moduleId].exports;
21 | /******/ }
22 | /******/ // Create a new module (and put it into the cache)
23 | /******/ var module = installedModules[moduleId] = {
24 | /******/ i: moduleId,
25 | /******/ l: false,
26 | /******/ exports: {}
27 | /******/ };
28 | /******/
29 | /******/ // Execute the module function
30 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
31 | /******/
32 | /******/ // Flag the module as loaded
33 | /******/ module.l = true;
34 | /******/
35 | /******/ // Return the exports of the module
36 | /******/ return module.exports;
37 | /******/ }
38 | /******/
39 | /******/
40 | /******/ // expose the modules object (__webpack_modules__)
41 | /******/ __webpack_require__.m = modules;
42 | /******/
43 | /******/ // expose the module cache
44 | /******/ __webpack_require__.c = installedModules;
45 | /******/
46 | /******/ // define getter function for harmony exports
47 | /******/ __webpack_require__.d = function(exports, name, getter) {
48 | /******/ if(!__webpack_require__.o(exports, name)) {
49 | /******/ Object.defineProperty(exports, name, {
50 | /******/ configurable: false,
51 | /******/ enumerable: true,
52 | /******/ get: getter
53 | /******/ });
54 | /******/ }
55 | /******/ };
56 | /******/
57 | /******/ // getDefaultExport function for compatibility with non-harmony modules
58 | /******/ __webpack_require__.n = function(module) {
59 | /******/ var getter = module && module.__esModule ?
60 | /******/ function getDefault() { return module['default']; } :
61 | /******/ function getModuleExports() { return module; };
62 | /******/ __webpack_require__.d(getter, 'a', getter);
63 | /******/ return getter;
64 | /******/ };
65 | /******/
66 | /******/ // Object.prototype.hasOwnProperty.call
67 | /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
68 | /******/
69 | /******/ // __webpack_public_path__
70 | /******/ __webpack_require__.p = "";
71 | /******/
72 | /******/ // Load entry module and return exports
73 | /******/ return __webpack_require__(__webpack_require__.s = 27);
74 | /******/ })
75 | /************************************************************************/
76 | /******/ ([
77 | /* 0 */
78 | /***/ (function(module, exports) {
79 |
80 | module.exports = __WEBPACK_EXTERNAL_MODULE_0__;
81 |
82 | /***/ }),
83 | /* 1 */
84 | /***/ (function(module, exports, __webpack_require__) {
85 |
86 | "use strict";
87 |
88 |
89 | var THREE = __webpack_require__(0);
90 | var processShader = __webpack_require__(8);
91 |
92 | function Pass() {
93 | this.shader = null;
94 | this.loaded = null;
95 | this.params = {};
96 | this.isSim = false;
97 | }
98 |
99 | module.exports = Pass;
100 |
101 | Pass.prototype.setShader = function(vs, fs) {
102 | this.shader = processShader(vs, fs);
103 | };
104 |
105 | Pass.prototype.run = function(composer) {
106 | composer.pass(this.shader);
107 | };
108 |
109 | Pass.prototype.getOfflineTexture = function(w, h, useRGBA) {
110 | return new THREE.WebGLRenderTarget(w, h, {
111 | minFilter: THREE.LinearFilter,
112 | magFilter: THREE.LinearFilter,
113 | format: useRGBA ? THREE.RGBAFormat : THREE.RGBFormat
114 | });
115 | };
116 |
117 |
118 | /***/ }),
119 | /* 2 */
120 | /***/ (function(module, exports) {
121 |
122 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\n\nvoid main() {\n\n vUv = uv;\n gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\n}"
123 |
124 | /***/ }),
125 | /* 3 */
126 | /***/ (function(module, exports, __webpack_require__) {
127 |
128 | "use strict";
129 |
130 |
131 | var Pass = __webpack_require__(1);
132 | var vertex = __webpack_require__(2);
133 | var fragment = __webpack_require__(9);
134 |
135 | function CopyPass() {
136 | Pass.call(this);
137 | this.setShader(vertex, fragment);
138 | }
139 |
140 | module.exports = CopyPass;
141 |
142 | CopyPass.prototype = Object.create(Pass.prototype);
143 | CopyPass.prototype.constructor = CopyPass;
144 |
145 |
146 | /***/ }),
147 | /* 4 */
148 | /***/ (function(module, exports, __webpack_require__) {
149 |
150 | "use strict";
151 |
152 |
153 | module.exports.Composer = __webpack_require__(5);
154 | module.exports.CopyPass = __webpack_require__(3);
155 | module.exports.BlendMode = {
156 | Normal: 1,
157 | Dissolve: 2, // UNAVAILABLE
158 | Darken: 3,
159 | Multiply: 4,
160 | ColorBurn: 5,
161 | LinearBurn: 6,
162 | DarkerColor: 7, // UNAVAILABLE
163 | Lighten: 8,
164 | Screen: 9,
165 | ColorDodge: 10,
166 | LinearDodge: 11,
167 | LighterColor: 12, // UNAVAILABLE
168 | Overlay: 13,
169 | SoftLight: 14,
170 | HardLight: 15,
171 | VividLight: 16, // UNAVAILABLE
172 | LinearLight: 17,
173 | PinLight: 18, // UNAVAILABLE
174 | HardMix: 19, // UNAVAILABLE
175 | Difference: 20,
176 | Exclusion: 21,
177 | Substract: 22, // UNAVAILABLE
178 | Divide: 23 // UNAVAILABLE
179 | };
180 |
181 |
182 | /***/ }),
183 | /* 5 */
184 | /***/ (function(module, exports, __webpack_require__) {
185 |
186 | "use strict";
187 |
188 |
189 | var THREE = __webpack_require__(0);
190 | var CopyPass = __webpack_require__(3);
191 | var Stack = __webpack_require__(10);
192 | var Pass = __webpack_require__(1);
193 |
194 | function Composer(renderer, settings) {
195 | var pixelRatio = renderer.getPixelRatio();
196 |
197 | this.width = Math.floor(renderer.context.canvas.width / pixelRatio) || 1;
198 | this.height = Math.floor(renderer.context.canvas.height / pixelRatio) || 1;
199 |
200 | this.output = null;
201 | this.input = null;
202 | this.read = null;
203 | this.write = null;
204 |
205 | this.settings = settings || {};
206 | this.useRGBA = this.settings.useRGBA || false;
207 |
208 | this.renderer = renderer;
209 | this.copyPass = new CopyPass(this.settings);
210 |
211 | this.defaultMaterial = new THREE.MeshBasicMaterial({color: 0x00FF00, wireframe: false});
212 | this.scene = new THREE.Scene();
213 | this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(1, 1), this.defaultMaterial);
214 | this.scene.add(this.quad);
215 | this.camera = new THREE.OrthographicCamera(1, 1, 1, 1, -10000, 10000);
216 |
217 | this.front = new THREE.WebGLRenderTarget(1, 1, {
218 | minFilter: this.settings.minFilter !== undefined ? this.settings.minFilter : THREE.LinearFilter,
219 | magFilter: this.settings.magFilter !== undefined ? this.settings.magFilter : THREE.LinearFilter,
220 | wrapS: this.settings.wrapS !== undefined ? this.settings.wrapS : THREE.ClampToEdgeWrapping,
221 | wrapT: this.settings.wrapT !== undefined ? this.settings.wrapT : THREE.ClampToEdgeWrapping,
222 | format: this.useRGBA ? THREE.RGBAFormat : THREE.RGBFormat,
223 | type: this.settings.type !== undefined ? this.settings.type : THREE.UnsignedByteType,
224 | stencilBuffer: this.settings.stencilBuffer !== undefined ? this.settings.stencilBuffer : true
225 | });
226 |
227 | this.back = this.front.clone();
228 | this.startTime = Date.now();
229 | this.passes = {};
230 |
231 | this.setSize(this.width, this.height);
232 | }
233 |
234 | module.exports = Composer;
235 |
236 | Composer.prototype.swapBuffers = function() {
237 | this.output = this.write;
238 | this.input = this.read;
239 |
240 | var t = this.write;
241 | this.write = this.read;
242 | this.read = t;
243 | };
244 |
245 | Composer.prototype.render = function(scene, camera, keep, output) {
246 | if (keep) this.swapBuffers();
247 | this.renderer.render(scene, camera, output ? output : this.write, true);
248 | if (!output) this.swapBuffers();
249 | };
250 |
251 | Composer.prototype.toScreen = function() {
252 | this.quad.material = this.copyPass.shader;
253 | this.quad.material.uniforms.tInput.value = this.read;
254 | this.quad.material.uniforms.resolution.value.set(this.width, this.height);
255 | this.renderer.render(this.scene, this.camera);
256 | };
257 |
258 | Composer.prototype.toTexture = function(t) {
259 | this.quad.material = this.copyPass.shader;
260 | this.quad.material.uniforms.tInput.value = this.read;
261 | this.renderer.render(this.scene, this.camera, t, false);
262 | };
263 |
264 | Composer.prototype.pass = function(pass) {
265 | if (pass instanceof Stack) {
266 | this.passStack(pass);
267 | }
268 | else {
269 | if (pass instanceof THREE.ShaderMaterial) {
270 | this.quad.material = pass;
271 | }
272 | if (pass instanceof Pass) {
273 | pass.run(this);
274 | return;
275 | }
276 |
277 | if (!pass.isSim) {
278 | this.quad.material.uniforms.tInput.value = this.read;
279 | }
280 |
281 | this.quad.material.uniforms.resolution.value.set(this.width, this.height);
282 | this.quad.material.uniforms.time.value = 0.001 * (Date.now() - this.startTime);
283 | this.renderer.render(this.scene, this.camera, this.write, false);
284 | this.swapBuffers();
285 | }
286 | };
287 |
288 | Composer.prototype.passStack = function(stack) {
289 | stack.getPasses().forEach(function(pass) {
290 | this.pass(pass);
291 | }.bind(this));
292 | };
293 |
294 | Composer.prototype.reset = function() {
295 | this.read = this.front;
296 | this.write = this.back;
297 | this.output = this.write;
298 | this.input = this.read;
299 | };
300 |
301 | Composer.prototype.setSource = function(src) {
302 | this.quad.material = this.copyPass.shader;
303 | this.quad.material.uniforms.tInput.value = src;
304 | this.renderer.render(this.scene, this.camera, this.write, true);
305 | this.swapBuffers();
306 | };
307 |
308 | Composer.prototype.setSize = function(w, h) {
309 | this.width = w;
310 | this.height = h;
311 |
312 | this.camera.projectionMatrix.makeOrthographic( w / - 2, w / 2, h / 2, h / - 2, this.camera.near, this.camera.far );
313 | this.quad.scale.set( w, h, 1 );
314 |
315 | this.front.setSize( w, h );
316 | this.back.setSize( w, h );
317 | };
318 |
319 |
320 |
321 | /***/ }),
322 | /* 6 */
323 | /***/ (function(module, exports, __webpack_require__) {
324 |
325 | "use strict";
326 |
327 |
328 | Object.defineProperty(exports, "__esModule", {
329 | value: true
330 | });
331 |
332 | var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
333 |
334 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
335 |
336 | var _three = __webpack_require__(0);
337 |
338 | var _stats = __webpack_require__(7);
339 |
340 | var _stats2 = _interopRequireDefault(_stats);
341 |
342 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
343 |
344 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
345 |
346 | var App = function () {
347 | function App() {
348 | _classCallCheck(this, App);
349 |
350 | if (window.location.search) {
351 | var params = window.location.search.substr(1).split('&');
352 | var _iteratorNormalCompletion = true;
353 | var _didIteratorError = false;
354 | var _iteratorError = undefined;
355 |
356 | try {
357 | for (var _iterator = params[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
358 | var param = _step.value;
359 |
360 | var _param$split = param.split('='),
361 | _param$split2 = _slicedToArray(_param$split, 2),
362 | prop = _param$split2[0],
363 | value = _param$split2[1];
364 |
365 | if (prop === 'debug') {
366 | this.stats = new _stats2.default();
367 | this.stats.showPanel(0);
368 | document.body.appendChild(this.stats.dom);
369 | }
370 | }
371 | } catch (err) {
372 | _didIteratorError = true;
373 | _iteratorError = err;
374 | } finally {
375 | try {
376 | if (!_iteratorNormalCompletion && _iterator.return) {
377 | _iterator.return();
378 | }
379 | } finally {
380 | if (_didIteratorError) {
381 | throw _iteratorError;
382 | }
383 | }
384 | }
385 | }
386 | this.renderer = new _three.WebGLRenderer();
387 | this.renderer.setPixelRatio(window.devicePixelRatio);
388 | this.renderer.setSize(window.innerWidth, window.innerHeight);
389 | this.renderer.autoClear = false;
390 | document.body.appendChild(this.renderer.domElement);
391 |
392 | this.scene = new _three.Scene();
393 |
394 | this.camera = new _three.PerspectiveCamera(60, this.getAspect(), 0.1, 100);
395 |
396 | this.onResize = this.onResize.bind(this);
397 | window.addEventListener('resize', this.onResize);
398 |
399 | this.init();
400 |
401 | this.lastTick = 0;
402 | this.onTick = this.onTick.bind(this);
403 | requestAnimationFrame(this.onTick);
404 | }
405 |
406 | _createClass(App, [{
407 | key: 'onTick',
408 | value: function onTick() {
409 | var t = performance.now();
410 | var delta = performance.now() - this.lastTick;
411 | if (this.stats) {
412 | this.stats.begin();
413 | }
414 | this.update(t, delta);
415 | this.render(t, delta);
416 | if (this.stats) {
417 | this.stats.end();
418 | }
419 | this.lastTick = t;
420 | requestAnimationFrame(this.onTick);
421 | }
422 | }, {
423 | key: 'getAspect',
424 | value: function getAspect() {
425 | return window.innerWidth / window.innerHeight;
426 | }
427 | }, {
428 | key: 'onResize',
429 | value: function onResize() {
430 | this.camera.aspect = this.getAspect();
431 | this.camera.updateProjectionMatrix();
432 | this.renderer.setSize(window.innerWidth, window.innerHeight);
433 | }
434 | }]);
435 |
436 | return App;
437 | }();
438 |
439 | exports.default = App;
440 |
441 | /***/ }),
442 | /* 7 */
443 | /***/ (function(module, exports, __webpack_require__) {
444 |
445 | // stats.js - http://github.com/mrdoob/stats.js
446 | (function(f,e){ true?module.exports=e():"function"===typeof define&&define.amd?define(e):f.Stats=e()})(this,function(){var f=function(){function e(a){c.appendChild(a.dom);return a}function u(a){for(var d=0;dg+1E3&&(r.update(1E3*a/(c-g),100),g=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/
448 | 1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){k=this.end()},domElement:c,setMode:u}};f.Panel=function(e,f,l){var c=Infinity,k=0,g=Math.round,a=g(window.devicePixelRatio||1),r=80*a,h=48*a,t=3*a,v=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=h;q.style.cssText="width:80px;height:48px";var b=q.getContext("2d");b.font="bold "+9*a+"px Helvetica,Arial,sans-serif";b.textBaseline="top";b.fillStyle=l;b.fillRect(0,0,r,h);b.fillStyle=f;b.fillText(e,t,v);
449 | b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(h,w){c=Math.min(c,h);k=Math.max(k,h);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=f;b.fillText(g(h)+" "+e+" ("+g(c)+"-"+g(k)+")",t,v);b.drawImage(q,d+a,m,n-a,p,d,m,n-a,p);b.fillRect(d+n-a,m,a,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d+n-a,m,a,g((1-h/w)*p))}}};return f});
450 |
451 |
452 | /***/ }),
453 | /* 8 */
454 | /***/ (function(module, exports, __webpack_require__) {
455 |
456 | "use strict";
457 |
458 |
459 | var THREE = __webpack_require__(0);
460 |
461 | module.exports = function processShader(vertexShaderCode, fragmentShaderCode) {
462 |
463 | var regExp = /uniform\s+([^\s]+)\s+([^\s]+)\s*;/gi;
464 | var regExp2 = /uniform\s+([^\s]+)\s+([^\s]+)\s*\[\s*(\w+)\s*\]*\s*;/gi;
465 |
466 | var typesMap = {
467 | sampler2D: { type: 't', value: function() { return new THREE.Texture(); } },
468 | samplerCube: { type: 't', value: function() {} },
469 |
470 | bool: { type: 'b', value: function() { return 0; } },
471 | int: { type: 'i', value: function() { return 0; } },
472 | float: { type: 'f', value: function() { return 0; } },
473 |
474 | vec2: { type: 'v2', value: function() { return new THREE.Vector2(); } },
475 | vec3: { type: 'v3', value: function() { return new THREE.Vector3(); } },
476 | vec4: { type: 'v4', value: function() { return new THREE.Vector4(); } },
477 |
478 | bvec2: { type: 'v2', value: function() { return new THREE.Vector2(); } },
479 | bvec3: { type: 'v3', value: function() { return new THREE.Vector3(); } },
480 | bvec4: { type: 'v4', value: function() { return new THREE.Vector4(); } },
481 |
482 | ivec2: { type: 'v2', value: function() { return new THREE.Vector2(); } },
483 | ivec3: { type: 'v3', value: function() { return new THREE.Vector3(); } },
484 | ivec4: { type: 'v4', value: function() { return new THREE.Vector4(); } },
485 |
486 | mat2: { type: 'v2', value: function() { return new THREE.Matrix2(); } },
487 | mat3: { type: 'v3', value: function() { return new THREE.Matrix3(); } },
488 | mat4: { type: 'v4', value: function() { return new THREE.Matrix4(); } }
489 | };
490 |
491 | var arrayTypesMap = {
492 | float: { type: 'fv', value: function() { return []; } },
493 | vec3: { type: 'v3v', value: function() { return []; } }
494 | };
495 |
496 | var matches;
497 | var uniforms = {
498 | resolution: { type: 'v2', value: new THREE.Vector2( 1, 1 ), default: true },
499 | time: { type: 'f', value: Date.now(), default: true },
500 | tInput: { type: 't', value: new THREE.Texture(), default: true }
501 | };
502 |
503 | var uniformType, uniformName, arraySize;
504 |
505 | while ((matches = regExp.exec(fragmentShaderCode)) !== null) {
506 | if (matches.index === regExp.lastIndex) {
507 | regExp.lastIndex++;
508 | }
509 | uniformType = matches[1];
510 | uniformName = matches[2];
511 |
512 | uniforms[uniformName] = {
513 | type: typesMap[uniformType].type,
514 | value: typesMap[uniformType].value()
515 | };
516 | }
517 |
518 | while ((matches = regExp2.exec(fragmentShaderCode)) !== null) {
519 | if (matches.index === regExp.lastIndex) {
520 | regExp.lastIndex++;
521 | }
522 | uniformType = matches[1];
523 | uniformName = matches[2];
524 | arraySize = matches[3];
525 |
526 | uniforms[uniformName] = {
527 | type: arrayTypesMap[uniformType].type,
528 | value: arrayTypesMap[uniformType].value()
529 | };
530 | }
531 |
532 | var shader = new THREE.ShaderMaterial({
533 | uniforms: uniforms,
534 | vertexShader: vertexShaderCode,
535 | fragmentShader: fragmentShaderCode,
536 | shading: THREE.FlatShading,
537 | depthWrite: false,
538 | depthTest: false,
539 | transparent: true
540 | });
541 |
542 | return shader;
543 | };
544 |
545 | /***/ }),
546 | /* 9 */
547 | /***/ (function(module, exports) {
548 |
549 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\nuniform sampler2D tInput;\n\nvoid main() {\n gl_FragColor = texture2D( tInput, vUv );\n\n}"
550 |
551 | /***/ }),
552 | /* 10 */
553 | /***/ (function(module, exports, __webpack_require__) {
554 |
555 | "use strict";
556 |
557 |
558 | function Stack(shadersPool) {
559 | this.passItems = [];
560 | this.shadersPool = shadersPool;
561 | this.passes = [];
562 | }
563 |
564 | module.exports = Stack;
565 |
566 | Stack.prototype.addPass = function(shaderName, enabled, params, index) {
567 | var length = 0;
568 | var passItem = {
569 | shaderName: shaderName,
570 | enabled: enabled || false
571 | };
572 |
573 | // TODO use and store params values
574 |
575 | this.passItems.push(passItem);
576 | length = this.passItems.length;
577 |
578 | this.updatePasses();
579 |
580 | if (index) {
581 | return this.movePassToIndex(this.passItems[length], index);
582 | }
583 | else {
584 | return length - 1;
585 | }
586 | };
587 |
588 | Stack.prototype.removePass = function(index) {
589 | this.passItems.splice(index, 1);
590 | this.updatePasses();
591 | };
592 |
593 | Stack.prototype.enablePass = function(index) {
594 | this.passItems[index].enabled = true;
595 | this.updatePasses();
596 | };
597 |
598 | Stack.prototype.disablePass = function(index) {
599 | this.passItems[index].enabled = false;
600 | this.updatePasses();
601 | };
602 |
603 | Stack.prototype.isPassEnabled = function(index) {
604 | return this.passItems[index].enabled;
605 | };
606 |
607 | Stack.prototype.movePassToIndex = function(index, destIndex) {
608 | this.passItems.splice(destIndex, 0, this.passItems.splice(index, 1)[0]);
609 | this.updatePasses();
610 |
611 | // TODO check if destIndex is final index
612 | return destIndex;
613 | };
614 |
615 | Stack.prototype.reverse = function() {
616 | this.passItems.reverse();
617 | this.updatePasses();
618 | };
619 |
620 | Stack.prototype.updatePasses = function() {
621 | this.passes = this.shadersPool.getPasses(this.passItems);
622 |
623 | // init default params for new passItems
624 | this.passItems.forEach(function(passItem, index) {
625 | if (passItem.params === undefined) {
626 | passItem.params = JSON.parse(JSON.stringify(this.passes[index].params)); // clone params without reference to the real shader instance params
627 | }
628 | }.bind(this));
629 | };
630 |
631 | Stack.prototype.getPasses = function() {
632 | return this.passes;
633 | };
634 |
635 |
636 | /***/ }),
637 | /* 11 */
638 | /***/ (function(module, exports, __webpack_require__) {
639 |
640 | "use strict";
641 |
642 |
643 | var THREE = __webpack_require__(0);
644 | var Pass = __webpack_require__(1);
645 | var Composer = __webpack_require__(5);
646 | var BlendMode = __webpack_require__(4).BlendMode;
647 | var FullBoxBlurPass = __webpack_require__(12);
648 | var BlendPass = __webpack_require__(15);
649 | var ZoomBlurPass = __webpack_require__(17);
650 | var BrightnessContrastPass = __webpack_require__(19);
651 |
652 | function MultiPassBloomPass(options) {
653 | Pass.call(this);
654 |
655 | options = options || {};
656 |
657 | this.composer = null;
658 |
659 | this.tmpTexture = this.getOfflineTexture( options.width, options.height, true );
660 | this.blurPass = new FullBoxBlurPass(2);
661 | this.blendPass = new BlendPass();
662 | this.zoomBlur = new ZoomBlurPass();
663 | this.brightnessContrastPass = new BrightnessContrastPass();
664 |
665 | this.width = options.width || 512;
666 | this.height = options.height || 512;
667 |
668 | this.params.blurAmount = options.blurAmount || 2;
669 | this.params.applyZoomBlur = options.applyZoomBlur || false;
670 | this.params.zoomBlurStrength = options.zoomBlurStrength || 0.2;
671 | this.params.useTexture = options.useTexture || false;
672 | this.params.zoomBlurCenter = options.zoomBlurCenter || new THREE.Vector2(0.5, 0.5);
673 | this.params.blendMode = options.blendMode || BlendMode.Screen;
674 | this.params.glowTexture = null;
675 | }
676 |
677 | module.exports = MultiPassBloomPass;
678 |
679 | MultiPassBloomPass.prototype = Object.create(Pass.prototype);
680 | MultiPassBloomPass.prototype.constructor = MultiPassBloomPass;
681 |
682 | MultiPassBloomPass.prototype.run = function(composer) {
683 | if (!this.composer) {
684 | this.composer = new Composer(composer.renderer, {useRGBA: true});
685 | this.composer.setSize(this.width, this.height);
686 | }
687 |
688 | this.composer.reset();
689 |
690 | if (this.params.useTexture === true) {
691 | this.composer.setSource(this.params.glowTexture);
692 | } else {
693 | this.composer.setSource(composer.output);
694 | }
695 |
696 | this.blurPass.params.amount = this.params.blurAmount;
697 | this.composer.pass(this.blurPass);
698 |
699 | if (this.params.applyZoomBlur) {
700 | this.zoomBlur.params.center.set(0.5, 0.5);
701 | this.zoomBlur.params.strength = this.params.zoomBlurStrength;
702 | this.composer.pass(this.zoomBlur);
703 | }
704 |
705 | if (this.params.useTexture === true) {
706 | this.blendPass.params.mode = BlendMode.Screen;
707 | this.blendPass.params.tInput = this.params.glowTexture;
708 | composer.pass(this.blendPass);
709 | }
710 |
711 | this.blendPass.params.mode = this.params.blendMode;
712 | this.blendPass.params.tInput2 = this.composer.output;
713 | composer.pass(this.blendPass);
714 | };
715 |
716 |
717 | /***/ }),
718 | /* 12 */
719 | /***/ (function(module, exports, __webpack_require__) {
720 |
721 | "use strict";
722 |
723 |
724 | var Pass = __webpack_require__(1);
725 | var BoxBlurPass = __webpack_require__(13);
726 |
727 | function FullBoxBlurPass(amount) {
728 | Pass.call(this);
729 |
730 | amount = amount || 2;
731 |
732 | this.boxPass = new BoxBlurPass(amount, amount);
733 | this.params.amount = amount;
734 | }
735 |
736 | module.exports = FullBoxBlurPass;
737 |
738 | FullBoxBlurPass.prototype = Object.create(Pass.prototype);
739 | FullBoxBlurPass.prototype.constructor = FullBoxBlurPass;
740 |
741 | FullBoxBlurPass.prototype.run = function(composer) {
742 | var s = this.params.amount;
743 | this.boxPass.params.delta.set( s, 0 );
744 | composer.pass( this.boxPass );
745 | this.boxPass.params.delta.set( 0, s );
746 | composer.pass( this.boxPass );
747 | };
748 |
749 |
750 | /***/ }),
751 | /* 13 */
752 | /***/ (function(module, exports, __webpack_require__) {
753 |
754 | "use strict";
755 |
756 |
757 | var THREE = __webpack_require__(0);
758 | var Pass = __webpack_require__(1);
759 | var vertex = __webpack_require__(2);
760 | var fragment = __webpack_require__(14);
761 |
762 | function BoxBlurPass(deltaX, deltaY) {
763 | Pass.call(this);
764 |
765 | this.setShader(vertex, fragment);
766 | this.params.delta = new THREE.Vector2(deltaX || 0, deltaY || 0);
767 | }
768 |
769 | module.exports = BoxBlurPass;
770 |
771 | BoxBlurPass.prototype = Object.create(Pass.prototype);
772 | BoxBlurPass.prototype.constructor = BoxBlurPass;
773 |
774 | BoxBlurPass.prototype.run = function(composer) {
775 | this.shader.uniforms.delta.value.copy(this.params.delta);
776 | composer.pass(this.shader);
777 |
778 | };
779 |
780 |
781 | /***/ }),
782 | /* 14 */
783 | /***/ (function(module, exports) {
784 |
785 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\nuniform sampler2D tInput;\nuniform vec2 delta;\nuniform vec2 resolution;\n\nvoid main() {\n\n vec4 sum = vec4( 0. );\n vec2 inc = delta / resolution;\n\n sum += texture2D( tInput, ( vUv - inc * 4. ) ) * 0.051;\n sum += texture2D( tInput, ( vUv - inc * 3. ) ) * 0.0918;\n sum += texture2D( tInput, ( vUv - inc * 2. ) ) * 0.12245;\n sum += texture2D( tInput, ( vUv - inc * 1. ) ) * 0.1531;\n sum += texture2D( tInput, ( vUv + inc * 0. ) ) * 0.1633;\n sum += texture2D( tInput, ( vUv + inc * 1. ) ) * 0.1531;\n sum += texture2D( tInput, ( vUv + inc * 2. ) ) * 0.12245;\n sum += texture2D( tInput, ( vUv + inc * 3. ) ) * 0.0918;\n sum += texture2D( tInput, ( vUv + inc * 4. ) ) * 0.051;\n\n gl_FragColor = sum;\n\n}"
786 |
787 | /***/ }),
788 | /* 15 */
789 | /***/ (function(module, exports, __webpack_require__) {
790 |
791 | "use strict";
792 |
793 |
794 | var THREE = __webpack_require__(0);
795 | var Pass = __webpack_require__(1);
796 | var vertex = __webpack_require__(2);
797 | var fragment = __webpack_require__(16);
798 |
799 | function BlendPass(options) {
800 | Pass.call(this);
801 |
802 | options = options || {};
803 |
804 | this.setShader(vertex, fragment);
805 |
806 | this.params.mode = options.mode || 1;
807 | this.params.opacity = options.opacity || 1;
808 | this.params.tInput2 = options.tInput2 || null;
809 | this.params.resolution2 = options.resolution2 || new THREE.Vector2();
810 | this.params.sizeMode = options.sizeMode || 1;
811 | this.params.aspectRatio = options.aspectRatio || 1;
812 | this.params.aspectRatio2 = options.aspectRatio2 || 1;
813 | }
814 |
815 | module.exports = BlendPass;
816 |
817 | BlendPass.prototype = Object.create(Pass.prototype);
818 | BlendPass.prototype.constructor = BlendPass;
819 |
820 | BlendPass.prototype.run = function(composer) {
821 | this.shader.uniforms.mode.value = this.params.mode;
822 | this.shader.uniforms.opacity.value = this.params.opacity;
823 | this.shader.uniforms.tInput2.value = this.params.tInput2;
824 | this.shader.uniforms.sizeMode.value = this.params.sizeMode;
825 | this.shader.uniforms.aspectRatio.value = this.params.aspectRatio;
826 | this.shader.uniforms.aspectRatio2.value = this.params.aspectRatio2;
827 | composer.pass(this.shader);
828 | };
829 |
830 |
831 | /***/ }),
832 | /* 16 */
833 | /***/ (function(module, exports) {
834 |
835 | module.exports = "#define GLSLIFY 1\nvarying vec2 vUv;\nuniform sampler2D tInput;\nuniform sampler2D tInput2;\nuniform vec2 resolution;\nuniform vec2 resolution2;\nuniform float aspectRatio;\nuniform float aspectRatio2;\nuniform int mode;\nuniform int sizeMode;\nuniform float opacity;\n\nvec2 vUv2;\n\nfloat applyOverlayToChannel( float base, float blend ) {\n\n return (base < 0.5 ? (2.0 * base * blend) : (1.0 - 2.0 * (1.0 - base) * (1.0 - blend)));\n\n}\n\nfloat applySoftLightToChannel( float base, float blend ) {\n\n return ((blend < 0.5) ? (2.0 * base * blend + base * base * (1.0 - 2.0 * blend)) : (sqrt(base) * (2.0 * blend - 1.0) + 2.0 * base * (1.0 - blend)));\n\n}\n\nfloat applyColorBurnToChannel( float base, float blend ) {\n\n return ((blend == 0.0) ? blend : max((1.0 - ((1.0 - base) / blend)), 0.0));\n\n}\n\nfloat applyColorDodgeToChannel( float base, float blend ) {\n\n return ((blend == 1.0) ? blend : min(base / (1.0 - blend), 1.0));\n\n}\n\nfloat applyLinearBurnToChannel( float base, float blend ) {\n\n return max(base + blend - 1., 0.0 );\n\n}\n\nfloat applyLinearDodgeToChannel( float base, float blend ) {\n\n return min( base + blend, 1. );\n\n}\n\nfloat applyLinearLightToChannel( float base, float blend ) {\n\n return ( blend < .5 ) ? applyLinearBurnToChannel( base, 2. * blend ) : applyLinearDodgeToChannel( base, 2. * ( blend - .5 ) );\n\n}\n\nvoid main() {\n\n vUv2 = vUv;\n \n if( sizeMode == 1 ) {\n \n if( aspectRatio2 > aspectRatio ) {\n vUv2.x = vUv.x * aspectRatio / aspectRatio2;\n vUv2.x += .5 * ( 1. - aspectRatio / aspectRatio2 ); \n vUv2.y = vUv.y;\n }\n\n if( aspectRatio2 < aspectRatio ) {\n vUv2.x = vUv.x;\n vUv2.y = vUv.y * aspectRatio2 / aspectRatio;\n vUv2.y += .5 * ( 1. - aspectRatio2 / aspectRatio );\n }\n\n }\n\n vec4 base = texture2D( tInput, vUv );\n vec4 blend = texture2D( tInput2, vUv2 );\n\n if( mode == 1 ) { // normal\n\n gl_FragColor = base;\n gl_FragColor.a *= opacity;\n return;\n\n }\n\n if( mode == 2 ) { // dissolve\n\n }\n\n if( mode == 3 ) { // darken\n\n gl_FragColor = min( base, blend );\n return;\n\n }\n\n if( mode == 4 ) { // multiply\n\n gl_FragColor = base * blend;\n return;\n\n }\n\n if( mode == 5 ) { // color burn\n\n gl_FragColor = vec4(\n applyColorBurnToChannel( base.r, blend.r ),\n applyColorBurnToChannel( base.g, blend.g ),\n applyColorBurnToChannel( base.b, blend.b ),\n applyColorBurnToChannel( base.a, blend.a )\n );\n return;\n\n }\n\n if( mode == 6 ) { // linear burn\n\n gl_FragColor = max(base + blend - 1.0, 0.0);\n return;\n\n }\n\n if( mode == 7 ) { // darker color\n\n }\n\n if( mode == 8 ) { // lighten\n\n gl_FragColor = max( base, blend );\n return;\n\n }\n\n if( mode == 9 ) { // screen\n\n gl_FragColor = (1.0 - ((1.0 - base) * (1.0 - blend)));\n gl_FragColor = gl_FragColor * opacity + base * ( 1. - opacity );\n return;\n\n }\n\n if( mode == 10 ) { // color dodge\n\n gl_FragColor = vec4(\n applyColorDodgeToChannel( base.r, blend.r ),\n applyColorDodgeToChannel( base.g, blend.g ),\n applyColorDodgeToChannel( base.b, blend.b ),\n applyColorDodgeToChannel( base.a, blend.a )\n );\n return;\n\n }\n\n if( mode == 11 ) { // linear dodge\n\n gl_FragColor = min(base + blend, 1.0);\n return;\n\n }\n\n if( mode == 12 ) { // lighter color\n\n }\n\n if( mode == 13 ) { // overlay\n\n gl_FragColor = gl_FragColor = vec4( \n applyOverlayToChannel( base.r, blend.r ),\n applyOverlayToChannel( base.g, blend.g ),\n applyOverlayToChannel( base.b, blend.b ),\n applyOverlayToChannel( base.a, blend.a )\n );\n gl_FragColor = gl_FragColor * opacity + base * ( 1. - opacity );\n \n return;\n\n }\n\n if( mode == 14 ) { // soft light\n\n gl_FragColor = vec4( \n applySoftLightToChannel( base.r, blend.r ),\n applySoftLightToChannel( base.g, blend.g ),\n applySoftLightToChannel( base.b, blend.b ),\n applySoftLightToChannel( base.a, blend.a )\n );\n return;\n\n }\n\n if( mode == 15 ) { // hard light\n\n gl_FragColor = vec4( \n applyOverlayToChannel( base.r, blend.r ),\n applyOverlayToChannel( base.g, blend.g ),\n applyOverlayToChannel( base.b, blend.b ),\n applyOverlayToChannel( base.a, blend.a )\n );\n gl_FragColor = gl_FragColor * opacity + base * ( 1. - opacity );\n return;\n\n }\n\n if( mode == 16 ) { // vivid light\n\n }\n\n if( mode == 17 ) { // linear light\n\n gl_FragColor = vec4( \n applyLinearLightToChannel( base.r, blend.r ),\n applyLinearLightToChannel( base.g, blend.g ),\n applyLinearLightToChannel( base.b, blend.b ),\n applyLinearLightToChannel( base.a, blend.a )\n );\n return;\n\n }\n\n if( mode == 18 ) { // pin light\n\n }\n\n if( mode == 19 ) { // hard mix\n\n }\n\n if( mode == 20 ) { // difference\n\n gl_FragColor = abs( base - blend );\n gl_FragColor.a = base.a + blend.b;\n return;\n\n }\n\n if( mode == 21 ) { // exclusion\n\n gl_FragColor = base + blend - 2. * base * blend;\n \n }\n\n if( mode == 22 ) { // substract\n\n }\n\n if( mode == 23 ) { // divide\n\n }\n\n gl_FragColor = vec4( 1., 0., 1., 1. );\n\n}"
836 |
837 | /***/ }),
838 | /* 17 */
839 | /***/ (function(module, exports, __webpack_require__) {
840 |
841 | "use strict";
842 |
843 |
844 | var THREE = __webpack_require__(0);
845 | var Pass = __webpack_require__(1);
846 | var vertex = __webpack_require__(2);
847 | var fragment = __webpack_require__(18);
848 |
849 | function ZoomBlurPass(options) {
850 | Pass.call(this);
851 |
852 | options = options || {};
853 |
854 | this.setShader(vertex, fragment);
855 |
856 | this.params.center = new THREE.Vector2(options.centerX || 0.5, options.centerY || 0.5);
857 | this.params.strength = options.strength || 0.1;
858 | }
859 |
860 | module.exports = ZoomBlurPass;
861 |
862 | ZoomBlurPass.prototype = Object.create(Pass.prototype);
863 | ZoomBlurPass.prototype.constructor = ZoomBlurPass;
864 |
865 | ZoomBlurPass.prototype.run = function(composer) {
866 | this.shader.uniforms.center.value.set(composer.width * this.params.center.x, composer.height * this.params.center.y);
867 | this.shader.uniforms.strength.value = this.params.strength;
868 | composer.pass(this.shader);
869 | };
870 |
871 |
872 | /***/ }),
873 | /* 18 */
874 | /***/ (function(module, exports) {
875 |
876 | module.exports = "#define GLSLIFY 1\nuniform sampler2D tInput;\nuniform vec2 center;\nuniform float strength;\nuniform vec2 resolution;\nvarying vec2 vUv;\n\nfloat random(vec3 scale,float seed){return fract(sin(dot(gl_FragCoord.xyz+seed,scale))*43758.5453+seed);}\n\nvoid main(){\n vec4 color=vec4(0.0);\n float total=0.0;\n vec2 toCenter=center-vUv*resolution;\n float offset=random(vec3(12.9898,78.233,151.7182),0.0);\n for(float t=0.0;t<=40.0;t++){\n float percent=(t+offset)/40.0;\n float weight=4.0*(percent-percent*percent);\n vec4 sample=texture2D(tInput,vUv+toCenter*percent*strength/resolution);\n sample.rgb*=sample.a;\n color+=sample*weight;\n total+=weight;\n }\n gl_FragColor=color/total;\n gl_FragColor.rgb/=gl_FragColor.a+0.00001;\n}"
877 |
878 | /***/ }),
879 | /* 19 */
880 | /***/ (function(module, exports, __webpack_require__) {
881 |
882 | "use strict";
883 |
884 |
885 | var Pass = __webpack_require__(1);
886 | var vertex = __webpack_require__(2);
887 | var fragment = __webpack_require__(20);
888 |
889 | function BrightnessContrastPass(brightness, contrast) {
890 | Pass.call(this);
891 |
892 | this.setShader(vertex, fragment);
893 |
894 | this.params.brightness = brightness || 1;
895 | this.params.contrast = contrast || 1;
896 | }
897 |
898 | module.exports = BrightnessContrastPass;
899 |
900 | BrightnessContrastPass.prototype = Object.create(Pass.prototype);
901 | BrightnessContrastPass.prototype.constructor = BrightnessContrastPass;
902 |
903 | BrightnessContrastPass.prototype.run = function(composer) {
904 | this.shader.uniforms.brightness.value = this.params.brightness;
905 | this.shader.uniforms.contrast.value = this.params.contrast;
906 | composer.pass(this.shader);
907 | };
908 |
909 |
910 | /***/ }),
911 | /* 20 */
912 | /***/ (function(module, exports) {
913 |
914 | module.exports = "#define GLSLIFY 1\nuniform float brightness;\nuniform float contrast;\nuniform sampler2D tInput;\n\nvarying vec2 vUv;\n\nvoid main() {\n\n vec3 color = texture2D(tInput, vUv).rgb;\n vec3 colorContrasted = (color) * contrast;\n vec3 bright = colorContrasted + vec3(brightness,brightness,brightness);\n gl_FragColor.rgb = bright;\n gl_FragColor.a = 1.;\n\n}"
915 |
916 | /***/ }),
917 | /* 21 */,
918 | /* 22 */,
919 | /* 23 */,
920 | /* 24 */,
921 | /* 25 */,
922 | /* 26 */,
923 | /* 27 */
924 | /***/ (function(module, exports, __webpack_require__) {
925 |
926 | "use strict";
927 |
928 |
929 | Object.defineProperty(exports, "__esModule", {
930 | value: true
931 | });
932 |
933 | var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
934 |
935 | var _three = __webpack_require__(0);
936 |
937 | var _ThreeApp2 = __webpack_require__(6);
938 |
939 | var _ThreeApp3 = _interopRequireDefault(_ThreeApp2);
940 |
941 | var _wagner = __webpack_require__(4);
942 |
943 | var _wagner2 = _interopRequireDefault(_wagner);
944 |
945 | var _MultiPassBloomPass = __webpack_require__(11);
946 |
947 | var _MultiPassBloomPass2 = _interopRequireDefault(_MultiPassBloomPass);
948 |
949 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
950 |
951 | function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
952 |
953 | function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
954 |
955 | function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
956 |
957 | var count = 400;
958 | var points = 100;
959 |
960 | var Experiment = function (_ThreeApp) {
961 | _inherits(Experiment, _ThreeApp);
962 |
963 | function Experiment() {
964 | _classCallCheck(this, Experiment);
965 |
966 | return _possibleConstructorReturn(this, (Experiment.__proto__ || Object.getPrototypeOf(Experiment)).apply(this, arguments));
967 | }
968 |
969 | _createClass(Experiment, [{
970 | key: 'init',
971 | value: function init() {
972 | this.renderer.setClearColor(0x111111);
973 | this.curves = [];
974 |
975 | for (var i = 0; i < count; i++) {
976 | var curve = new _three.EllipseCurve(0, 0, 2, 2, 0, 2 * Math.PI, false, 0);
977 | var path = new _three.Path(curve.getPoints(points));
978 | var geo = path.createPointsGeometry(points);
979 | var c = i / count * 360 / 1.9;
980 | var mat = new _three.LineBasicMaterial({
981 | color: new _three.Color('hsl(' + c + ', 100%, 50%)'),
982 | transparent: true,
983 | depthWrite: false,
984 | blending: _three.AdditiveBlending,
985 | opacity: 0.4
986 | });
987 | var line = new _three.Line(geo, mat);
988 | this.curves.push(line);
989 | this.scene.add(line);
990 | }
991 |
992 | this.camera.position.set(0, 0, 5);
993 |
994 | this.pivot = new _three.Object3D();
995 | this.pivot.add(this.camera);
996 | this.scene.add(this.pivot);
997 |
998 | this.composer = new _wagner2.default.Composer(this.renderer);
999 | this.pass = new _MultiPassBloomPass2.default({
1000 | zoomBlurStrength: 0.05,
1001 | applyZoomBlur: true,
1002 | blurAmount: 0.2
1003 | });
1004 | }
1005 | }, {
1006 | key: 'update',
1007 | value: function update(t, delta) {
1008 | for (var i = 0; i < count; i++) {
1009 | var curve = this.curves[i];
1010 | var pct = i / count;
1011 | var scale = (Math.sin(t * 0.0001 + pct * Math.PI * 2) + 1) / 2;
1012 | curve.scale.set(scale, scale, scale);
1013 | curve.rotation.z = t * 0.00001 + pct * 2;
1014 | curve.rotation.y = t * 0.001 + pct * Math.PI * 2;
1015 | curve.rotation.x = t * 0.001 + pct * Math.PI * 2 + Math.PI / 2;
1016 | }
1017 | this.pivot.rotation.y = -t * 0.001;
1018 | }
1019 | }, {
1020 | key: 'render',
1021 | value: function render() {
1022 | this.renderer.clearColor();
1023 | this.composer.reset();
1024 | this.composer.render(this.scene, this.camera);
1025 | this.composer.pass(this.pass);
1026 | this.composer.toScreen();
1027 | }
1028 | }]);
1029 |
1030 | return Experiment;
1031 | }(_ThreeApp3.default);
1032 |
1033 | exports.default = new Experiment();
1034 |
1035 | /***/ })
1036 | /******/ ]);
1037 | });
--------------------------------------------------------------------------------
/public/scripts/dat.gui.min.js:
--------------------------------------------------------------------------------
1 | !function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.dat=t():e.dat=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(1),r=o(i);t.default=r.default,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(2),r=o(i),a=n(6),l=o(a),s=n(3),u=o(s),d=n(7),c=o(d),f=n(8),_=o(f),p=n(10),h=o(p),m=n(11),b=o(m),g=n(12),v=o(g),y=n(13),w=o(y),x=n(14),E=o(x),C=n(15),A=o(C),S=n(16),k=o(S),O=n(9),T=o(O),R=n(17),L=o(R);t.default={color:{Color:r.default,math:l.default,interpret:u.default},controllers:{Controller:c.default,BooleanController:_.default,OptionController:h.default,StringController:b.default,NumberController:v.default,NumberControllerBox:w.default,NumberControllerSlider:E.default,FunctionController:A.default,ColorController:k.default},dom:{dom:T.default},gui:{GUI:L.default},GUI:L.default},e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t,n){Object.defineProperty(e,t,{get:function(){return"RGB"===this.__state.space?this.__state[t]:(h.recalculateRGB(this,t,n),this.__state[t])},set:function(e){"RGB"!==this.__state.space&&(h.recalculateRGB(this,t,n),this.__state.space="RGB"),this.__state[t]=e}})}function a(e,t){Object.defineProperty(e,t,{get:function(){return"HSV"===this.__state.space?this.__state[t]:(h.recalculateHSV(this),this.__state[t])},set:function(e){"HSV"!==this.__state.space&&(h.recalculateHSV(this),this.__state.space="HSV"),this.__state[t]=e}})}t.__esModule=!0;var l=n(3),s=o(l),u=n(6),d=o(u),c=n(4),f=o(c),_=n(5),p=o(_),h=function(){function e(){if(i(this,e),this.__state=s.default.apply(this,arguments),this.__state===!1)throw new Error("Failed to interpret color arguments");this.__state.a=this.__state.a||1}return e.prototype.toString=function(){return(0,f.default)(this)},e.prototype.toHexString=function(){return(0,f.default)(this,!0)},e.prototype.toOriginal=function(){return this.__state.conversion.write(this)},e}();h.recalculateRGB=function(e,t,n){if("HEX"===e.__state.space)e.__state[t]=d.default.component_from_hex(e.__state.hex,n);else{if("HSV"!==e.__state.space)throw new Error("Corrupted color state");p.default.extend(e.__state,d.default.hsv_to_rgb(e.__state.h,e.__state.s,e.__state.v))}},h.recalculateHSV=function(e){var t=d.default.rgb_to_hsv(e.r,e.g,e.b);p.default.extend(e.__state,{s:t.s,v:t.v}),p.default.isNaN(t.h)?p.default.isUndefined(e.__state.h)&&(e.__state.h=0):e.__state.h=t.h},h.COMPONENTS=["r","g","b","h","s","v","hex","a"],r(h.prototype,"r",2),r(h.prototype,"g",1),r(h.prototype,"b",0),a(h.prototype,"h"),a(h.prototype,"s"),a(h.prototype,"v"),Object.defineProperty(h.prototype,"a",{get:function(){return this.__state.a},set:function(e){this.__state.a=e}}),Object.defineProperty(h.prototype,"hex",{get:function(){return"HEX"!==!this.__state.space&&(this.__state.hex=d.default.rgb_to_hex(this.r,this.g,this.b)),this.__state.hex},set:function(e){this.__state.space="HEX",this.__state.hex=e}}),t.default=h,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(4),r=o(i),a=n(5),l=o(a),s=[{litmus:l.default.isString,conversions:{THREE_CHAR_HEX:{read:function(e){var t=e.match(/^#([A-F0-9])([A-F0-9])([A-F0-9])$/i);return null!==t&&{space:"HEX",hex:parseInt("0x"+t[1].toString()+t[1].toString()+t[2].toString()+t[2].toString()+t[3].toString()+t[3].toString(),0)}},write:r.default},SIX_CHAR_HEX:{read:function(e){var t=e.match(/^#([A-F0-9]{6})$/i);return null!==t&&{space:"HEX",hex:parseInt("0x"+t[1].toString(),0)}},write:r.default},CSS_RGB:{read:function(e){var t=e.match(/^rgb\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);return null!==t&&{space:"RGB",r:parseFloat(t[1]),g:parseFloat(t[2]),b:parseFloat(t[3])}},write:r.default},CSS_RGBA:{read:function(e){var t=e.match(/^rgba\(\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*,\s*(.+)\s*\)/);return null!==t&&{space:"RGB",r:parseFloat(t[1]),g:parseFloat(t[2]),b:parseFloat(t[3]),a:parseFloat(t[4])}},write:r.default}}},{litmus:l.default.isNumber,conversions:{HEX:{read:function(e){return{space:"HEX",hex:e,conversionName:"HEX"}},write:function(e){return e.hex}}}},{litmus:l.default.isArray,conversions:{RGB_ARRAY:{read:function(e){return 3===e.length&&{space:"RGB",r:e[0],g:e[1],b:e[2]}},write:function(e){return[e.r,e.g,e.b]}},RGBA_ARRAY:{read:function(e){return 4===e.length&&{space:"RGB",r:e[0],g:e[1],b:e[2],a:e[3]}},write:function(e){return[e.r,e.g,e.b,e.a]}}}},{litmus:l.default.isObject,conversions:{RGBA_OBJ:{read:function(e){return!!(l.default.isNumber(e.r)&&l.default.isNumber(e.g)&&l.default.isNumber(e.b)&&l.default.isNumber(e.a))&&{space:"RGB",r:e.r,g:e.g,b:e.b,a:e.a}},write:function(e){return{r:e.r,g:e.g,b:e.b,a:e.a}}},RGB_OBJ:{read:function(e){return!!(l.default.isNumber(e.r)&&l.default.isNumber(e.g)&&l.default.isNumber(e.b))&&{space:"RGB",r:e.r,g:e.g,b:e.b}},write:function(e){return{r:e.r,g:e.g,b:e.b}}},HSVA_OBJ:{read:function(e){return!!(l.default.isNumber(e.h)&&l.default.isNumber(e.s)&&l.default.isNumber(e.v)&&l.default.isNumber(e.a))&&{space:"HSV",h:e.h,s:e.s,v:e.v,a:e.a}},write:function(e){return{h:e.h,s:e.s,v:e.v,a:e.a}}},HSV_OBJ:{read:function(e){return!!(l.default.isNumber(e.h)&&l.default.isNumber(e.s)&&l.default.isNumber(e.v))&&{space:"HSV",h:e.h,s:e.s,v:e.v}},write:function(e){return{h:e.h,s:e.s,v:e.v}}}}}],u=void 0,d=void 0,c=function(){d=!1;var e=arguments.length>1?l.default.toArray(arguments):arguments[0];return l.default.each(s,function(t){if(t.litmus(e))return l.default.each(t.conversions,function(t,n){if(u=t.read(e),d===!1&&u!==!1)return d=u,u.conversionName=n,u.conversion=t,l.default.BREAK}),l.default.BREAK}),d};t.default=c,e.exports=t.default},function(e,t){"use strict";t.__esModule=!0,t.default=function(e,t){var n=e.__state.conversionName.toString(),o=Math.round(e.r),i=Math.round(e.g),r=Math.round(e.b),a=e.a,l=Math.round(e.h),s=e.s.toFixed(1),u=e.v.toFixed(1);if(t||"THREE_CHAR_HEX"===n||"SIX_CHAR_HEX"===n){for(var d=e.hex.toString(16);d.length<6;)d="0"+d;return"#"+d}return"CSS_RGB"===n?"rgb("+o+","+i+","+r+")":"CSS_RGBA"===n?"rgba("+o+","+i+","+r+","+a+")":"HEX"===n?"0x"+e.hex.toString(16):"RGB_ARRAY"===n?"["+o+","+i+","+r+"]":"RGBA_ARRAY"===n?"["+o+","+i+","+r+","+a+"]":"RGB_OBJ"===n?"{r:"+o+",g:"+i+",b:"+r+"}":"RGBA_OBJ"===n?"{r:"+o+",g:"+i+",b:"+r+",a:"+a+"}":"HSV_OBJ"===n?"{h:"+l+",s:"+s+",v:"+u+"}":"HSVA_OBJ"===n?"{h:"+l+",s:"+s+",v:"+u+",a:"+a+"}":"unknown format"},e.exports=t.default},function(e,t){"use strict";t.__esModule=!0;var n=Array.prototype.forEach,o=Array.prototype.slice,i={BREAK:{},extend:function(e){return this.each(o.call(arguments,1),function(t){var n=this.isObject(t)?Object.keys(t):[];n.forEach(function(n){this.isUndefined(t[n])||(e[n]=t[n])}.bind(this))},this),e},defaults:function(e){return this.each(o.call(arguments,1),function(t){var n=this.isObject(t)?Object.keys(t):[];n.forEach(function(n){this.isUndefined(e[n])&&(e[n]=t[n])}.bind(this))},this),e},compose:function(){var e=o.call(arguments);return function(){for(var t=o.call(arguments),n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},each:function(e,t,o){if(e)if(n&&e.forEach&&e.forEach===n)e.forEach(t,o);else if(e.length===e.length+0){var i=void 0,r=void 0;for(i=0,r=e.length;i>8*t&255},hex_with_component:function(e,t,o){return o<<(n=8*t)|e&~(255<-1?t.length-t.indexOf(".")-1:0}t.__esModule=!0;var s=n(7),u=o(s),d=n(5),c=o(d),f=function(e){function t(n,o,a){i(this,t);var s=r(this,e.call(this,n,o)),u=a||{};return s.__min=u.min,s.__max=u.max,s.__step=u.step,c.default.isUndefined(s.__step)?0===s.initialValue?s.__impliedStep=1:s.__impliedStep=Math.pow(10,Math.floor(Math.log(Math.abs(s.initialValue))/Math.LN10))/10:s.__impliedStep=s.__step,s.__precision=l(s.__impliedStep),s}return a(t,e),t.prototype.setValue=function(t){var n=t;return void 0!==this.__min&&nthis.__max&&(n=this.__max),void 0!==this.__step&&n%this.__step!==0&&(n=Math.round(n/this.__step)*this.__step),e.prototype.setValue.call(this,n)},t.prototype.min=function(e){return this.__min=e,this},t.prototype.max=function(e){return this.__max=e,this},t.prototype.step=function(e){return this.__step=e,this.__impliedStep=e,this.__precision=l(e),this},t}(u.default);t.default=f,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t){var n=Math.pow(10,t);return Math.round(e*n)/n}t.__esModule=!0;var s=n(12),u=o(s),d=n(9),c=o(d),f=n(5),_=o(f),p=function(e){function t(n,o,a){function l(){var e=parseFloat(m.__input.value);_.default.isNaN(e)||m.setValue(e)}function s(){m.__onFinishChange&&m.__onFinishChange.call(m,m.getValue())}function u(){s()}function d(e){var t=b-e.clientY;m.setValue(m.getValue()+t*m.__impliedStep),b=e.clientY}function f(){c.default.unbind(window,"mousemove",d),c.default.unbind(window,"mouseup",f),s()}function p(e){c.default.bind(window,"mousemove",d),c.default.bind(window,"mouseup",f),b=e.clientY}i(this,t);var h=r(this,e.call(this,n,o,a));h.__truncationSuspended=!1;var m=h,b=void 0;return h.__input=document.createElement("input"),h.__input.setAttribute("type","text"),c.default.bind(h.__input,"change",l),c.default.bind(h.__input,"blur",u),c.default.bind(h.__input,"mousedown",p),c.default.bind(h.__input,"keydown",function(e){13===e.keyCode&&(m.__truncationSuspended=!0,this.blur(),m.__truncationSuspended=!1,s())}),h.updateDisplay(),h.domElement.appendChild(h.__input),h}return a(t,e),t.prototype.updateDisplay=function(){return this.__input.value=this.__truncationSuspended?this.getValue():l(this.getValue(),this.__precision),e.prototype.updateDisplay.call(this)},t}(u.default);t.default=p,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t,n,o,i){return o+(i-o)*((e-t)/(n-t))}t.__esModule=!0;var s=n(12),u=o(s),d=n(9),c=o(d),f=function(e){function t(n,o,a,s,u){function d(e){document.activeElement.blur(),c.default.bind(window,"mousemove",f),c.default.bind(window,"mouseup",_),f(e)}function f(e){e.preventDefault();var t=h.__background.getBoundingClientRect();return h.setValue(l(e.clientX,t.left,t.right,h.__min,h.__max)),!1}function _(){c.default.unbind(window,"mousemove",f),c.default.unbind(window,"mouseup",_),h.__onFinishChange&&h.__onFinishChange.call(h,h.getValue())}i(this,t);var p=r(this,e.call(this,n,o,{min:a,max:s,step:u})),h=p;return p.__background=document.createElement("div"),p.__foreground=document.createElement("div"),c.default.bind(p.__background,"mousedown",d),c.default.addClass(p.__background,"slider"),c.default.addClass(p.__foreground,"slider-fg"),p.updateDisplay(),p.__background.appendChild(p.__foreground),p.domElement.appendChild(p.__background),p}return a(t,e),t.prototype.updateDisplay=function(){var t=(this.getValue()-this.__min)/(this.__max-this.__min);return this.__foreground.style.width=100*t+"%",e.prototype.updateDisplay.call(this)},t}(u.default);t.default=f,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}t.__esModule=!0;var l=n(7),s=o(l),u=n(9),d=o(u),c=function(e){function t(n,o,a){i(this,t);var l=r(this,e.call(this,n,o)),s=l;return l.__button=document.createElement("div"),l.__button.innerHTML=void 0===a?"Fire":a,d.default.bind(l.__button,"click",function(e){return e.preventDefault(),s.fire(),!1}),d.default.addClass(l.__button,"button"),l.domElement.appendChild(l.__button),l}return a(t,e),t.prototype.fire=function(){this.__onChange&&this.__onChange.call(this),this.getValue().call(this.object),this.__onFinishChange&&this.__onFinishChange.call(this,this.getValue())},t}(s.default);t.default=c,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function r(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function a(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function l(e,t,n,o){e.style.background="",g.default.each(y,function(i){e.style.cssText+="background: "+i+"linear-gradient("+t+", "+n+" 0%, "+o+" 100%); "})}function s(e){e.style.background="",e.style.cssText+="background: -moz-linear-gradient(top, #ff0000 0%, #ff00ff 17%, #0000ff 34%, #00ffff 50%, #00ff00 67%, #ffff00 84%, #ff0000 100%);",e.style.cssText+="background: -webkit-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);",e.style.cssText+="background: -o-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);",e.style.cssText+="background: -ms-linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);",e.style.cssText+="background: linear-gradient(top, #ff0000 0%,#ff00ff 17%,#0000ff 34%,#00ffff 50%,#00ff00 67%,#ffff00 84%,#ff0000 100%);"}t.__esModule=!0;var u=n(7),d=o(u),c=n(9),f=o(c),_=n(2),p=o(_),h=n(3),m=o(h),b=n(5),g=o(b),v=function(e){function t(n,o){function a(e){h(e),f.default.bind(window,"mousemove",h),f.default.bind(window,"mouseup",u)}function u(){f.default.unbind(window,"mousemove",h),f.default.unbind(window,"mouseup",u),_()}function d(){var e=(0,m.default)(this.value);e!==!1?(y.__color.__state=e,y.setValue(y.__color.toOriginal())):this.value=y.__color.toString()}function c(){f.default.unbind(window,"mousemove",b),f.default.unbind(window,"mouseup",c),_()}function _(){y.__onFinishChange&&y.__onFinishChange.call(y,y.__color.toOriginal())}function h(e){e.preventDefault();var t=y.__saturation_field.getBoundingClientRect(),n=(e.clientX-t.left)/(t.right-t.left),o=1-(e.clientY-t.top)/(t.bottom-t.top);return o>1?o=1:o<0&&(o=0),n>1?n=1:n<0&&(n=0),y.__color.v=o,y.__color.s=n,y.setValue(y.__color.toOriginal()),!1}function b(e){e.preventDefault();var t=y.__hue_field.getBoundingClientRect(),n=1-(e.clientY-t.top)/(t.bottom-t.top);return n>1?n=1:n<0&&(n=0),y.__color.h=360*n,y.setValue(y.__color.toOriginal()),!1}i(this,t);var v=r(this,e.call(this,n,o));v.__color=new p.default(v.getValue()),v.__temp=new p.default(0);var y=v;v.domElement=document.createElement("div"),f.default.makeSelectable(v.domElement,!1),v.__selector=document.createElement("div"),v.__selector.className="selector",v.__saturation_field=document.createElement("div"),v.__saturation_field.className="saturation-field",v.__field_knob=document.createElement("div"),v.__field_knob.className="field-knob",v.__field_knob_border="2px solid ",v.__hue_knob=document.createElement("div"),v.__hue_knob.className="hue-knob",v.__hue_field=document.createElement("div"),v.__hue_field.className="hue-field",v.__input=document.createElement("input"),v.__input.type="text",v.__input_textShadow="0 1px 1px ",f.default.bind(v.__input,"keydown",function(e){13===e.keyCode&&d.call(this)}),f.default.bind(v.__input,"blur",d),f.default.bind(v.__selector,"mousedown",function(){f.default.addClass(this,"drag").bind(window,"mouseup",function(){f.default.removeClass(y.__selector,"drag")})});var w=document.createElement("div");return g.default.extend(v.__selector.style,{width:"122px",height:"102px",padding:"3px",backgroundColor:"#222",boxShadow:"0px 1px 3px rgba(0,0,0,0.3)"}),g.default.extend(v.__field_knob.style,{position:"absolute",width:"12px",height:"12px",border:v.__field_knob_border+(v.__color.v<.5?"#fff":"#000"),boxShadow:"0px 1px 3px rgba(0,0,0,0.5)",borderRadius:"12px",zIndex:1}),g.default.extend(v.__hue_knob.style,{position:"absolute",width:"15px",height:"2px",borderRight:"4px solid #fff",zIndex:1}),g.default.extend(v.__saturation_field.style,{width:"100px",height:"100px",border:"1px solid #555",marginRight:"3px",display:"inline-block",cursor:"pointer"}),g.default.extend(w.style,{width:"100%",height:"100%",background:"none"}),l(w,"top","rgba(0,0,0,0)","#000"),g.default.extend(v.__hue_field.style,{width:"15px",height:"100px",border:"1px solid #555",cursor:"ns-resize",position:"absolute",top:"3px",right:"3px"}),s(v.__hue_field),g.default.extend(v.__input.style,{outline:"none",textAlign:"center",color:"#fff",border:0,fontWeight:"bold",textShadow:v.__input_textShadow+"rgba(0,0,0,0.7)"}),f.default.bind(v.__saturation_field,"mousedown",a),f.default.bind(v.__field_knob,"mousedown",a),f.default.bind(v.__hue_field,"mousedown",function(e){b(e),f.default.bind(window,"mousemove",b),f.default.bind(window,"mouseup",c)}),v.__saturation_field.appendChild(w),v.__selector.appendChild(v.__field_knob),v.__selector.appendChild(v.__saturation_field),v.__selector.appendChild(v.__hue_field),v.__hue_field.appendChild(v.__hue_knob),v.domElement.appendChild(v.__input),v.domElement.appendChild(v.__selector),v.updateDisplay(),v}return a(t,e),t.prototype.updateDisplay=function(){var e=(0,m.default)(this.getValue());if(e!==!1){var t=!1;g.default.each(p.default.COMPONENTS,function(n){if(!g.default.isUndefined(e[n])&&!g.default.isUndefined(this.__color.__state[n])&&e[n]!==this.__color.__state[n])return t=!0,{}},this),t&&g.default.extend(this.__color.__state,e)}g.default.extend(this.__temp.__state,this.__color.__state),this.__temp.a=1;var n=this.__color.v<.5||this.__color.s>.5?255:0,o=255-n;g.default.extend(this.__field_knob.style,{marginLeft:100*this.__color.s-7+"px",marginTop:100*(1-this.__color.v)-7+"px",backgroundColor:this.__temp.toHexString(),border:this.__field_knob_border+"rgb("+n+","+n+","+n+")"}),this.__hue_knob.style.marginTop=100*(1-this.__color.h/360)+"px",this.__temp.s=1,this.__temp.v=1,l(this.__saturation_field,"left","#fff",this.__temp.toHexString()),this.__input.value=this.__color.toString(),g.default.extend(this.__input.style,{backgroundColor:this.__color.toHexString(),color:"rgb("+n+","+n+","+n+")",textShadow:this.__input_textShadow+"rgba("+o+","+o+","+o+",.7)"})},t}(d.default),y=["-moz-","-o-","-webkit-","-ms-",""];t.default=v,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t,n){var o=document.createElement("li");return t&&o.appendChild(t),n?e.__ul.insertBefore(o,n):e.__ul.appendChild(o),e.onResize(),o}function r(e,t){var n=e.__preset_select[e.__preset_select.selectedIndex];t?n.innerHTML=n.value+"*":n.innerHTML=n.value}function a(e,t,n){if(n.__li=t,n.__gui=e,U.default.extend(n,{options:function(t){if(arguments.length>1){var o=n.__li.nextElementSibling;return n.remove(),s(e,n.object,n.property,{before:o,factoryArgs:[U.default.toArray(arguments)]})}if(U.default.isArray(t)||U.default.isObject(t)){var i=n.__li.nextElementSibling;return n.remove(),s(e,n.object,n.property,{before:i,factoryArgs:[t]})}},name:function(e){return n.__li.firstElementChild.firstElementChild.innerHTML=e,n},listen:function(){return n.__gui.listen(n),n},remove:function(){return n.__gui.remove(n),n}}),n instanceof N.default){var o=new B.default(n.object,n.property,{
2 | min:n.__min,max:n.__max,step:n.__step});U.default.each(["updateDisplay","onChange","onFinishChange","step"],function(e){var t=n[e],i=o[e];n[e]=o[e]=function(){var e=Array.prototype.slice.call(arguments);return i.apply(o,e),t.apply(n,e)}}),z.default.addClass(t,"has-slider"),n.domElement.insertBefore(o.domElement,n.domElement.firstElementChild)}else if(n instanceof B.default){var i=function(t){if(U.default.isNumber(n.__min)&&U.default.isNumber(n.__max)){var o=n.__li.firstElementChild.firstElementChild.innerHTML,i=n.__gui.__listening.indexOf(n)>-1;n.remove();var r=s(e,n.object,n.property,{before:n.__li.nextElementSibling,factoryArgs:[n.__min,n.__max,n.__step]});return r.name(o),i&&r.listen(),r}return t};n.min=U.default.compose(i,n.min),n.max=U.default.compose(i,n.max)}else n instanceof O.default?(z.default.bind(t,"click",function(){z.default.fakeEvent(n.__checkbox,"click")}),z.default.bind(n.__checkbox,"click",function(e){e.stopPropagation()})):n instanceof R.default?(z.default.bind(t,"click",function(){z.default.fakeEvent(n.__button,"click")}),z.default.bind(t,"mouseover",function(){z.default.addClass(n.__button,"hover")}),z.default.bind(t,"mouseout",function(){z.default.removeClass(n.__button,"hover")})):n instanceof j.default&&(z.default.addClass(t,"color"),n.updateDisplay=U.default.compose(function(e){return t.style.borderLeftColor=n.__color.toString(),e},n.updateDisplay),n.updateDisplay());n.setValue=U.default.compose(function(t){return e.getRoot().__preset_select&&n.isModified()&&r(e.getRoot(),!0),t},n.setValue)}function l(e,t){var n=e.getRoot(),o=n.__rememberedObjects.indexOf(t.object);if(o!==-1){var i=n.__rememberedObjectIndecesToControllers[o];if(void 0===i&&(i={},n.__rememberedObjectIndecesToControllers[o]=i),i[t.property]=t,n.load&&n.load.remembered){var r=n.load.remembered,a=void 0;if(r[e.preset])a=r[e.preset];else{if(!r[Q])return;a=r[Q]}if(a[o]&&void 0!==a[o][t.property]){var l=a[o][t.property];t.initialValue=l,t.setValue(l)}}}}function s(e,t,n,o){if(void 0===t[n])throw new Error('Object "'+t+'" has no property "'+n+'"');var r=void 0;if(o.color)r=new j.default(t,n);else{var s=[t,n].concat(o.factoryArgs);r=C.default.apply(e,s)}o.before instanceof S.default&&(o.before=o.before.__li),l(e,r),z.default.addClass(r.domElement,"c");var u=document.createElement("span");z.default.addClass(u,"property-name"),u.innerHTML=r.property;var d=document.createElement("div");d.appendChild(u),d.appendChild(r.domElement);var c=i(e,d,o.before);return z.default.addClass(c,oe.CLASS_CONTROLLER_ROW),r instanceof j.default?z.default.addClass(c,"color"):z.default.addClass(c,g(r.getValue())),a(e,c,r),e.__controllers.push(r),r}function u(e,t){return document.location.href+"."+t}function d(e,t,n){var o=document.createElement("option");o.innerHTML=t,o.value=t,e.__preset_select.appendChild(o),n&&(e.__preset_select.selectedIndex=e.__preset_select.length-1)}function c(e,t){t.style.display=e.useLocalStorage?"block":"none"}function f(e){var t=e.__save_row=document.createElement("li");z.default.addClass(e.domElement,"has-save"),e.__ul.insertBefore(t,e.__ul.firstChild),z.default.addClass(t,"save-row");var n=document.createElement("span");n.innerHTML=" ",z.default.addClass(n,"button gears");var o=document.createElement("span");o.innerHTML="Save",z.default.addClass(o,"button"),z.default.addClass(o,"save");var i=document.createElement("span");i.innerHTML="New",z.default.addClass(i,"button"),z.default.addClass(i,"save-as");var r=document.createElement("span");r.innerHTML="Revert",z.default.addClass(r,"button"),z.default.addClass(r,"revert");var a=e.__preset_select=document.createElement("select");if(e.load&&e.load.remembered?U.default.each(e.load.remembered,function(t,n){d(e,n,n===e.preset)}):d(e,Q,!1),z.default.bind(a,"change",function(){for(var t=0;t0&&(e.preset=this.preset,e.remembered||(e.remembered={}),e.remembered[this.preset]=h(this)),e.folders={},U.default.each(this.__folders,function(t,n){e.folders[n]=t.getSaveObject()}),e},save:function(){this.load.remembered||(this.load.remembered={}),this.load.remembered[this.preset]=h(this),r(this,!1),this.saveToLocalStorageIfPossible()},saveAs:function(e){this.load.remembered||(this.load.remembered={},this.load.remembered[Q]=h(this,!0)),this.load.remembered[e]=h(this),this.preset=e,d(this,e,!0),this.saveToLocalStorageIfPossible()},revert:function(e){U.default.each(this.__controllers,function(t){this.getRoot().load.remembered?l(e||this.getRoot(),t):t.setValue(t.initialValue),t.__onFinishChange&&t.__onFinishChange.call(t,t.getValue())},this),U.default.each(this.__folders,function(e){e.revert(e)}),e||r(this.getRoot(),!1)},listen:function(e){var t=0===this.__listening.length;this.__listening.push(e),t&&b(this.__listening)},updateDisplay:function(){U.default.each(this.__controllers,function(e){e.updateDisplay()}),U.default.each(this.__folders,function(e){e.updateDisplay()})}}),t.default=oe,e.exports=t.default},function(e,t){"use strict";e.exports={load:function(e,t){var n=t||document,o=n.createElement("link");o.type="text/css",o.rel="stylesheet",o.href=e,n.getElementsByTagName("head")[0].appendChild(o)},inject:function(e,t){var n=t||document,o=document.createElement("style");o.type="text/css",o.innerHTML=e;var i=n.getElementsByTagName("head")[0];try{i.appendChild(o)}catch(e){}}}},function(e,t){e.exports=" Here's the new load parameter for your
GUI's constructor:
Automatically save values to
localStorage on exit.
The values saved to localStorage will override those passed to dat.GUI's constructor. This makes it easier to work incrementally, but localStorage is fragile, and your friends may not see the same values you do.
"},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}t.__esModule=!0;var i=n(10),r=o(i),a=n(13),l=o(a),s=n(14),u=o(s),d=n(11),c=o(d),f=n(15),_=o(f),p=n(8),h=o(p),m=n(5),b=o(m),g=function(e,t){var n=e[t];return b.default.isArray(arguments[2])||b.default.isObject(arguments[2])?new r.default(e,t,arguments[2]):b.default.isNumber(n)?b.default.isNumber(arguments[2])&&b.default.isNumber(arguments[3])?b.default.isNumber(arguments[4])?new u.default(e,t,arguments[2],arguments[3],arguments[4]):new u.default(e,t,arguments[2],arguments[3]):b.default.isNumber(arguments[4])?new l.default(e,t,{min:arguments[2],max:arguments[3],step:arguments[4]}):new l.default(e,t,{min:arguments[2],max:arguments[3]}):b.default.isString(n)?new c.default(e,t):b.default.isFunction(n)?new _.default(e,t,""):b.default.isBoolean(n)?new h.default(e,t):null};t.default=g,e.exports=t.default},function(e,t){"use strict";function n(e){setTimeout(e,1e3/60)}t.__esModule=!0,t.default=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||n,e.exports=t.default},function(e,t,n){"use strict";function o(e){return e&&e.__esModule?e:{default:e}}function i(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}t.__esModule=!0;var r=n(9),a=o(r),l=n(5),s=o(l),u=function(){function e(){i(this,e),this.backgroundElement=document.createElement("div"),s.default.extend(this.backgroundElement.style,{backgroundColor:"rgba(0,0,0,0.8)",top:0,left:0,display:"none",zIndex:"1000",opacity:0,WebkitTransition:"opacity 0.2s linear",transition:"opacity 0.2s linear"}),a.default.makeFullscreen(this.backgroundElement),this.backgroundElement.style.position="fixed",this.domElement=document.createElement("div"),s.default.extend(this.domElement.style,{position:"fixed",display:"none",zIndex:"1001",opacity:0,WebkitTransition:"-webkit-transform 0.2s ease-out, opacity 0.2s linear",transition:"transform 0.2s ease-out, opacity 0.2s linear"}),document.body.appendChild(this.backgroundElement),document.body.appendChild(this.domElement);var t=this;a.default.bind(this.backgroundElement,"click",function(){t.hide()})}return e.prototype.show=function(){var e=this;this.backgroundElement.style.display="block",this.domElement.style.display="block",this.domElement.style.opacity=0,this.domElement.style.webkitTransform="scale(1.1)",this.layout(),s.default.defer(function(){e.backgroundElement.style.opacity=1,e.domElement.style.opacity=1,e.domElement.style.webkitTransform="scale(1)"})},e.prototype.hide=function e(){var t=this,e=function e(){t.domElement.style.display="none",t.backgroundElement.style.display="none",a.default.unbind(t.domElement,"webkitTransitionEnd",e),a.default.unbind(t.domElement,"transitionend",e),a.default.unbind(t.domElement,"oTransitionEnd",e)};a.default.bind(this.domElement,"webkitTransitionEnd",e),a.default.bind(this.domElement,"transitionend",e),a.default.bind(this.domElement,"oTransitionEnd",e),this.backgroundElement.style.opacity=0,this.domElement.style.opacity=0,this.domElement.style.webkitTransform="scale(1.1)"},e.prototype.layout=function(){this.domElement.style.left=window.innerWidth/2-a.default.getWidth(this.domElement)/2+"px",this.domElement.style.top=window.innerHeight/2-a.default.getHeight(this.domElement)/2+"px"},e}();t.default=u,e.exports=t.default},function(e,t,n){t=e.exports=n(24)(),t.push([e.id,".dg ul{list-style:none;margin:0;padding:0;width:100%;clear:both}.dg.ac{position:fixed;top:0;left:0;right:0;height:0;z-index:0}.dg:not(.ac) .main{overflow:hidden}.dg.main{transition:opacity .1s linear}.dg.main.taller-than-window{overflow-y:auto}.dg.main.taller-than-window .close-button{opacity:1;margin-top:-1px;border-top:1px solid #2c2c2c}.dg.main ul.closed .close-button{opacity:1!important}.dg.main .close-button.drag,.dg.main:hover .close-button{opacity:1}.dg.main .close-button{transition:opacity .1s linear;border:0;line-height:19px;height:20px;cursor:pointer;text-align:center;background-color:#000}.dg.main .close-button.close-top{position:relative}.dg.main .close-button.close-bottom{position:absolute}.dg.main .close-button:hover{background-color:#111}.dg.a{float:right;margin-right:15px;overflow-y:visible}.dg.a.has-save>ul.close-top{margin-top:0}.dg.a.has-save>ul.close-bottom{margin-top:27px}.dg.a.has-save>ul.closed{margin-top:0}.dg.a .save-row{top:0;z-index:1002}.dg.a .save-row.close-top{position:relative}.dg.a .save-row.close-bottom{position:fixed}.dg li{transition:height .1s ease-out;transition:overflow .1s linear}.dg li:not(.folder){cursor:auto;height:27px;line-height:27px;padding:0 4px 0 5px}.dg li.folder{padding:0;border-left:4px solid transparent}.dg li.title{margin-left:-4px}.dg .closed li:not(.title),.dg .closed ul li,.dg .closed ul li>*{height:0;overflow:hidden;border:0}.dg .cr{clear:both;padding-left:3px;height:27px;overflow:hidden}.dg .property-name{cursor:default;float:left;clear:left;width:40%;overflow:hidden;text-overflow:ellipsis}.dg .c{float:left;width:60%;position:relative}.dg .c input[type=text]{border:0;margin-top:4px;padding:3px;width:100%;float:right}.dg .has-slider input[type=text]{width:30%;margin-left:0}.dg .slider{float:left;width:66%;margin-left:-5px;margin-right:0;height:19px;margin-top:4px}.dg .slider-fg{height:100%}.dg .c input[type=checkbox]{margin-top:7px}.dg .c select{margin-top:5px}.dg .cr.boolean,.dg .cr.boolean *,.dg .cr.function,.dg .cr.function *,.dg .cr.function .property-name{cursor:pointer}.dg .cr.color{overflow:visible}.dg .selector{display:none;position:absolute;margin-left:-9px;margin-top:23px;z-index:10}.dg .c:hover .selector,.dg .selector.drag{display:block}.dg li.save-row{padding:0}.dg li.save-row .button{display:inline-block;padding:0 6px}.dg.dialogue{background-color:#222;width:460px;padding:15px;font-size:13px;line-height:15px}#dg-new-constructor{padding:10px;color:#222;font-family:Monaco,monospace;font-size:10px;border:0;resize:none;box-shadow:inset 1px 1px 1px #888;word-wrap:break-word;margin:12px 0;display:block;width:440px;overflow-y:scroll;height:100px;position:relative}#dg-local-explain{display:none;font-size:11px;line-height:17px;border-radius:3px;background-color:#333;padding:8px;margin-top:10px}#dg-local-explain code{font-size:10px}#dat-gui-save-locally{display:none}.dg{color:#eee;font:11px Lucida Grande,sans-serif;text-shadow:0 -1px 0 #111}.dg.main::-webkit-scrollbar{width:5px;background:#1a1a1a}.dg.main::-webkit-scrollbar-corner{height:0;display:none}.dg.main::-webkit-scrollbar-thumb{border-radius:5px;background:#676767}.dg li:not(.folder){background:#1a1a1a;border-bottom:1px solid #2c2c2c}.dg li.save-row{line-height:25px;background:#dad5cb;border:0}.dg li.save-row select{margin-left:5px;width:108px}.dg li.save-row .button{margin-left:5px;margin-top:1px;border-radius:2px;font-size:9px;line-height:7px;padding:4px 4px 5px;background:#c5bdad;color:#fff;text-shadow:0 1px 0 #b0a58f;box-shadow:0 -1px 0 #b0a58f;cursor:pointer}.dg li.save-row .button.gears{background:#c5bdad url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAANCAYAAAB/9ZQ7AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAQJJREFUeNpiYKAU/P//PwGIC/ApCABiBSAW+I8AClAcgKxQ4T9hoMAEUrxx2QSGN6+egDX+/vWT4e7N82AMYoPAx/evwWoYoSYbACX2s7KxCxzcsezDh3evFoDEBYTEEqycggWAzA9AuUSQQgeYPa9fPv6/YWm/Acx5IPb7ty/fw+QZblw67vDs8R0YHyQhgObx+yAJkBqmG5dPPDh1aPOGR/eugW0G4vlIoTIfyFcA+QekhhHJhPdQxbiAIguMBTQZrPD7108M6roWYDFQiIAAv6Aow/1bFwXgis+f2LUAynwoIaNcz8XNx3Dl7MEJUDGQpx9gtQ8YCueB+D26OECAAQDadt7e46D42QAAAABJRU5ErkJggg==) 2px 1px no-repeat;height:7px;width:8px}.dg li.save-row .button:hover{background-color:#bab19e;box-shadow:0 -1px 0 #b0a58f}.dg li.folder{border-bottom:0}.dg li.title{padding-left:16px;background:#000 url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlI+hKgFxoCgAOw==) 6px 10px no-repeat;cursor:pointer;border-bottom:1px solid hsla(0,0%,100%,.2)}.dg .closed li.title{background-image:url(data:image/gif;base64,R0lGODlhBQAFAJEAAP////Pz8////////yH5BAEAAAIALAAAAAAFAAUAAAIIlGIWqMCbWAEAOw==)}.dg .cr.boolean{border-left:3px solid #806787}.dg .cr.color{border-left:3px solid}.dg .cr.function{border-left:3px solid #e61d5f}.dg .cr.number{border-left:3px solid #2fa1d6}.dg .cr.number input[type=text]{color:#2fa1d6}.dg .cr.string{border-left:3px solid #1ed36f}.dg .cr.string input[type=text]{color:#1ed36f}.dg .cr.boolean:hover,.dg .cr.function:hover{background:#111}.dg .c input[type=text]{background:#303030;outline:none}.dg .c input[type=text]:hover{background:#3c3c3c}.dg .c input[type=text]:focus{background:#494949;color:#fff}.dg .c .slider{background:#303030;cursor:ew-resize}.dg .c .slider-fg{background:#2fa1d6;max-width:100%}.dg .c .slider:hover{background:#3c3c3c}.dg .c .slider:hover .slider-fg{background:#44abda}",""])},function(e,t){e.exports=function(){var e=[];return e.toString=function(){for(var e=[],t=0;t