├── .gitignore ├── LICENSE ├── README.md ├── UV_Grid_Sm.jpg ├── components ├── README.md ├── bloom │ ├── README.md │ └── index.js ├── colors │ ├── README.md │ └── index.js ├── film │ ├── README.md │ └── index.js ├── fxaa │ ├── README.md │ └── index.js ├── glitch │ ├── README.md │ └── index.js ├── godrays │ ├── README.md │ └── index.js ├── index.js ├── lighty │ └── index.js ├── outline │ ├── README.md │ └── index.js └── ssao │ ├── README.md │ └── index.js ├── dist ├── aframe-effects.js ├── aframe-effects.min.js └── afrane-effects.min.js.map ├── index.html ├── index.js ├── lib ├── AdaptiveToneMappingPass.js ├── Detector.js ├── aframe.js ├── shaders │ ├── BlurShader.js │ ├── CopyShader.js │ ├── DepthLimitedBlurShader.js │ ├── FXAAShader.js │ ├── LuminosityHighPassShader.js │ ├── LuminosityShader.js │ ├── SAOShader.js │ └── ShaderGodRays.js ├── stats.min.js └── three.js ├── lut.png ├── package-lock.json ├── package.json ├── screen.png ├── shaders └── index.js ├── sponza ├── copyright.txt ├── index.html └── sponza.obj ├── systems ├── README.md ├── effects.js └── index.js └── three.html /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .cache 3 | .vscode 4 | *.swp 5 | build 6 | gh-pages/ 7 | node_modules 8 | npm-debug.log* 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Yannis Gravezas 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | AFRAME.Effects 2 | ======== 3 | 4 | If anyone actually wants to take ownership of the project, it's yours 5 | -------------------------------------------------------------------------------- /UV_Grid_Sm.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizgrav/aframe-effects/634940eb38588f20ae1be5cc572a2747723d7ad5/UV_Grid_Sm.jpg -------------------------------------------------------------------------------- /components/README.md: -------------------------------------------------------------------------------- 1 | Effect Components 2 | ===================== 3 | 4 | Effect components must register and unregister to make the effects system aware of them. 5 | 6 | ``` 7 | init: function() { 8 | this.el.sceneEl.systems.effects.register(this); 9 | }, 10 | 11 | remove: function () { 12 | this.el.sceneEl.systems.effects.unregister(this); 13 | } 14 | ``` 15 | 16 | The effects system also provides utilities to assist in writing post processing components, check [it's readme](../systems/README.md). 17 | 18 | There are three general types of effect components: 19 | 20 | #### 1) Material/Pass components. 21 | 22 | These are treated as a separate pass in the chain that will get executed autonomously, just like three's effect composer does. By toggling a **.bypass** boolean property on components of this type, they can be skipped in the effect chain execution without having to actually reset the chain, which can be costly. 23 | 24 | To create this type of components the developer needs to set a .pass or .material property with the appropriate three object. Materials will internally be wrapped in passes and need to have tDiffuse and/or tDepth uniforms defined for the texture passing between passes to work. Passes should loosely follow the three effect composers structure, in particular they must have a **render(renderer, writeBuffer, readBuffer )** method. 25 | 26 | #### 2) Fusable components. 27 | 28 | Continuous chains of these components will be fused together in a single material pass for efficiency. Material/Pass components will split the chains and create more passes. To enable them the component needs to have a **.fragment** property defined with the glsl text to be fused. 29 | 30 | To avoid name clash tokens specific to each component must be prefixed with **"$"** which will be expanded with each components attrName + "_" at fuse time(check the console for the generated source). 31 | 32 | The texts of all components in the chain will be concatenated into a single shader source. Every fusable fragment must contain a function with the signature **"void $main(inout vec color, vec4 origColor, vec2 uv float depth)"**. This function will be called in the order of the chain by default, but this can be overriden by appending an **'!'** to component names when specifying the effects system chain. 33 | 34 | Processing should modify the **color** argument which is the current color as processed so far in the chain. **origColor** is the original color the chain started with, **uv** is the uv of the full screen quad and **depth** is the value from the depth texture, in perspective depth. 35 | 36 | If the color or depth texel from the previous pass(which initially will be the scene's renderTarget) is desired, the developer must also declare a boolean property **.diffuse = true** on the component. Same for the depth texture texel with **.depth = true**. If not declared the values will default to vec4(0.) for the color and 0 for the depth. If one or more fused effects define these properties they will activate for the whole chain. 37 | 38 | If a **.uniforms** object is also declared, it's members will be included in the final shader, again with the appropriate prefix. You can then change the values in the components uniforms and these will be reflected in the fused shader. 39 | 40 | An **.includes** array can be provided to specify which threejs includes are needed so they can be added only once for the whole chain. 41 | 42 | Components that need to do preprocessing and generate intermediate textures should perform that processing in their **tock()** methods and expose the textures via their **.uniforms** property to feed the blending operation specified in the **.fragment** property. Fusing all final blends and operations that don't need to access adjacent pixels saves alot of bandwidth allowing more effects to be applied in the same budget. 43 | 44 | #### 3) Script effects. 45 | 46 | These behave like limited fused components but without the need to actually write a component. The effects system accepts ** 71 | 72 | 73 | ``` -------------------------------------------------------------------------------- /components/bloom/README.md: -------------------------------------------------------------------------------- 1 | Bloom 2 | ======== 3 | 4 | Makes bright things glow. Adapted from threejs UnrealBloomPass. 5 | 6 | | Schema | Type | Default | Description | 7 | | ------------- |:-------------:| -----:| :---: | 8 | | strength | number | 1.0 | Intensity of the effect | 9 | | radius | number | 0.4 | How far will the glow reach | 10 | | threshold | are neat | 0.8 | default filters luminance threshold | 11 | | filter| array | "" | if set, it will use the specified array and fuse it into the material used to generate the input for the blur. An empty string will instead make use of the, luminance based, default| -------------------------------------------------------------------------------- /components/bloom/index.js: -------------------------------------------------------------------------------- 1 | // Adapted from spidersharma UnrealBloomPass 2 | var LuminosityHighPassShader = require('../../lib/shaders/LuminosityHighPassShader'); 3 | 4 | var BlurDirectionX = new THREE.Vector2( 1.0, 0.0 ); 5 | var BlurDirectionY = new THREE.Vector2( 0.0, 1.0 ); 6 | 7 | AFRAME.registerComponent("bloom", { 8 | multiple: true, 9 | 10 | schema: { 11 | enable: { default: true}, 12 | strength: { default: 1 }, 13 | radius: { default: 0.4 }, 14 | threshold: { default: 0.8 }, 15 | filter: { type: "array", default: [] } 16 | }, 17 | 18 | init: function () { 19 | this.system = this.el.sceneEl.systems.effects; 20 | var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }; 21 | this.renderTargetsHorizontal = []; 22 | this.renderTargetsVertical = []; 23 | this.nMips = 5; 24 | 25 | this.renderTargetBright = new THREE.WebGLRenderTarget( 1, 1, pars ); 26 | this.renderTargetBright.texture.name = "UnrealBloomPass.bright"; 27 | this.renderTargetBright.texture.generateMipmaps = false; 28 | 29 | for( var i=0; i\ 214 | varying vec2 vUv;\n\ 215 | uniform sampler2D colorTexture;\n\ 216 | uniform vec2 texSize;\ 217 | uniform vec2 direction;\ 218 | float gaussianPdf(in float x, in float sigma) {\ 219 | return 0.39894 * exp( -0.5 * x * x/( sigma * sigma))/sigma;\ 220 | }\ 221 | void main() {\n\ 222 | vec2 invSize = 1.0 / texSize;\ 223 | float fSigma = float(SIGMA);\ 224 | float weightSum = gaussianPdf(0.0, fSigma);\ 225 | vec3 diffuseSum = texture2D( colorTexture, vUv).rgb * weightSum;\ 226 | for( int i = 1; i < KERNEL_RADIUS; i ++ ) {\ 227 | float x = float(i);\ 228 | float w = gaussianPdf(x, fSigma);\ 229 | vec2 uvOffset = direction * invSize * x;\ 230 | vec3 sample1 = textureVR( colorTexture, vUv + uvOffset).rgb;\ 231 | vec3 sample2 = textureVR( colorTexture, vUv - uvOffset).rgb;\ 232 | diffuseSum += (sample1 + sample2) * w;\ 233 | weightSum += 2.0 * w;\ 234 | }\ 235 | gl_FragColor = vec4(diffuseSum/weightSum, 1.0);\n\ 236 | }" 237 | } ); 238 | }, 239 | 240 | getCompositeMaterial: function(nMips) { 241 | 242 | return new THREE.ShaderMaterial( { 243 | 244 | defines:{ 245 | "NUM_MIPS" : nMips 246 | }, 247 | 248 | uniforms: { 249 | "blurTexture1": { value: null }, 250 | "blurTexture2": { value: null }, 251 | "blurTexture3": { value: null }, 252 | "blurTexture4": { value: null }, 253 | "blurTexture5": { value: null }, 254 | "bloomStrength" : { value: 1.0 }, 255 | "bloomFactors" : { value: null }, 256 | "bloomTintColors" : { value: null }, 257 | "bloomRadius" : { value: 0.0 } 258 | }, 259 | 260 | vertexShader: 261 | "varying vec2 vUv;\n\ 262 | void main() {\n\ 263 | vUv = uv;\n\ 264 | gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n\ 265 | }", 266 | 267 | fragmentShader: 268 | "varying vec2 vUv;\ 269 | uniform sampler2D blurTexture1;\ 270 | uniform sampler2D blurTexture2;\ 271 | uniform sampler2D blurTexture3;\ 272 | uniform sampler2D blurTexture4;\ 273 | uniform sampler2D blurTexture5;\ 274 | uniform float bloomStrength;\ 275 | uniform float bloomRadius;\ 276 | uniform float bloomFactors[NUM_MIPS];\ 277 | uniform vec3 bloomTintColors[NUM_MIPS];\ 278 | \ 279 | float lerpBloomFactor(const in float factor) { \ 280 | float mirrorFactor = 1.2 - factor;\ 281 | return mix(factor, mirrorFactor, bloomRadius);\ 282 | }\ 283 | \ 284 | void main() {\ 285 | gl_FragColor = bloomStrength * ( lerpBloomFactor(bloomFactors[0]) * vec4(bloomTintColors[0], 1.0) * texture2D(blurTexture1, vUv) + \ 286 | lerpBloomFactor(bloomFactors[1]) * vec4(bloomTintColors[1], 1.0) * texture2D(blurTexture2, vUv) + \ 287 | lerpBloomFactor(bloomFactors[2]) * vec4(bloomTintColors[2], 1.0) * texture2D(blurTexture3, vUv) + \ 288 | lerpBloomFactor(bloomFactors[3]) * vec4(bloomTintColors[3], 1.0) * texture2D(blurTexture4, vUv) + \ 289 | lerpBloomFactor(bloomFactors[4]) * vec4(bloomTintColors[4], 1.0) * texture2D(blurTexture5, vUv) );\ 290 | }" 291 | } ); 292 | }, 293 | 294 | diffuse: true, 295 | defaults: ["1.0"], 296 | fragment: [ 297 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth){", 298 | " color.rgb += texture2D($texture, uv).rgb;", 299 | "}" 300 | ].join("\n") 301 | }); -------------------------------------------------------------------------------- /components/colors/README.md: -------------------------------------------------------------------------------- 1 | Colors 2 | ======== 3 | 4 | Generic chainable operations on color. Check the mode property for customization. Lut parts are taken from [@mattdesl glsl-lut](https://github.com/mattdesl/glsl-lut). Check that for details on use. The default lut png is included in this repos base. 5 | 6 | 7 | | Schema | Type | Default | Description | 8 | | ------------- |:-------------:| -----:| :---: | 9 | | mode | string | "map" | a series of characters that define the chain of color operations for this component instance. Check the next table for details. "map" sets up multiply, then add, then raise to power. Resets the effects chain. | 10 | | lut | selector | null | an image element to use as a lut. | 11 | | lutClamp | boolean | false | Check mattdesl's repo. Resets the effects chain. | 12 | | lutFlip | boolean | false | Check mattdesl's repo. Resets the effects chain.| 13 | | add | vec3 | Vector3(0,0,0)| The vec3 to use for the addition operation | 14 | | mul | vec3 | Vector3(1,1,1) | The vec3 to use for the multiply operation | 15 | | pow | vec3 | Vector3(1,1,1) | The vec3 to use for the power operation | 16 | | left | vec3 | Vector3(0,0,0) | The vec3 to use for the smoothstep operation | 17 | | right | vec3 | Vector3(1,1,1) | The vec3 to use for the smoothstep operation | 18 | | min | vec3 | Vector3(0,0,0) | The vec3 to use for the clamp operation | 19 | | max | vec3 | Vector3(1,1,1) | The vec3 to use for the clamp operation | 20 | | quant | vec3 | Vector3(0.2,0.2,0.2) | The vec3 to use for the quantize operation | 21 | | orig | vec3 | Vector3(1,1,1) | The vec3 to use for the mix-original operation | 22 | 23 | 24 | available mode operations 25 | 26 | | Key | Operation | Description | 27 | | ------------- |:-------------:| -----:| 28 | | m | multiply| multiply color with the 'mul' schema property | 29 | | a | addition| adds the 'add' schema property to color | 30 | | p | power | raise color to the 'pow' schema property | 31 | | h | rgb to hsv | convert color from rgb to hsv | 32 | | r | hsv to rgb | convert color from hsv to rgb | 33 | | s | smoothstep | perform a smoothstep on color using the 'left' and 'right' schema properties for the bounds| 34 | | l | lut | perform a lookup in the image provided with the 'lut' option | 35 | | q | quantize | Quantize color values. Number of bands is inverse of the 'quant' schema property. Useful for achieving a toon look | 36 | | c | clamp | clamp color using the 'min' and 'max' schema properties as bounds | 37 | | g | grayscale | converts color to grayscale | 38 | | o | mix-original | mix the current color in the chain with the original color, controlled with the 'orig' schema property | 39 | | t | technicolor | Converts color to technicolor | -------------------------------------------------------------------------------- /components/colors/index.js: -------------------------------------------------------------------------------- 1 | AFRAME.registerComponent("colors", { 2 | multiple: true, 3 | 4 | schema: { 5 | "mode": { default: "map" }, 6 | "lut": { type: "selector"}, 7 | "lutClamp": { default: false }, 8 | "lutFlip": { default: false }, 9 | "add": { type: "vec3", default: new THREE.Vector3(0,0,0) }, 10 | "mul": { type: "vec3", default: new THREE.Vector3(1,1,1) }, 11 | "pow": { type: "vec3", default: new THREE.Vector3(1,1,1) }, 12 | "left": { type: "vec3", default: new THREE.Vector3(0,0,0) }, 13 | "right": { type: "vec3", default: new THREE.Vector3(1,1,1) }, 14 | "min": { type: "vec3", default: new THREE.Vector3(0,0,0) }, 15 | "max": { type: "vec3", default: new THREE.Vector3(1,1,1) }, 16 | "quant": { type: "vec3", default: new THREE.Vector3(0.2,0.2,0.2) }, 17 | "orig": { type: "vec3", default: new THREE.Vector3(1,1,1) }, 18 | "red": { type: "vec3", default: new THREE.Vector3(1,0,0) }, 19 | "green": { type: "vec3", default: new THREE.Vector3(0,0.5,0.5) }, 20 | "blue": { type: "vec3", default: new THREE.Vector3(0,0.5,0.5) }, 21 | }, 22 | 23 | init: function () { 24 | this.system = this.el.sceneEl.systems.effects; 25 | this.uniforms = { 26 | "add": { type: "v3", value: null }, 27 | "mul": { type: "v3", value: null }, 28 | "pow": { type: "v3", value: null }, 29 | "left": { type: "v3", value: null }, 30 | "right": { type: "v3", value: null }, 31 | "min": { type: "v3", value: null }, 32 | "max": { type: "v3", value: null }, 33 | "quant": { type: "v3", value: null }, 34 | "orig": { type: "v3", value: null }, 35 | "red": { type: "v3", value: null }, 36 | "green": { type: "v3", value: null }, 37 | "blue": { type: "v3", value: null }, 38 | "texture": { 39 | type: "t", 40 | value: new THREE.Texture( 41 | undefined, // Default Image 42 | undefined, // Default Mapping 43 | undefined, // Default wrapS 44 | undefined, // Default wrapT 45 | THREE.NearestFilter, // magFilter 46 | THREE.NearestFilter // minFilter 47 | )} 48 | } 49 | 50 | this.rebuild(); 51 | 52 | this.system.register(this); 53 | }, 54 | 55 | update: function (oldData) { 56 | var d = this.data, us = this.uniforms, needsRebuild = false; 57 | 58 | for(var u in us) { 59 | if(d[u] !== undefined) us[u].value = d[u]; 60 | } 61 | [] 62 | if(this.data.lutFlip !== oldData.lutFlip || this.data.lutClamp !== oldData.lutClamp || this.data.mode != oldData.mode) { 63 | this.rebuild(); 64 | } 65 | 66 | if(this.data.lut !== oldData.lut) { 67 | const texture = this.uniforms.texture.value; 68 | texture.image = this.data.lut; 69 | texture.needsUpdate = true; 70 | } 71 | }, 72 | 73 | remove: function () { 74 | this.system.unregister(this); 75 | }, 76 | 77 | rebuild: function () { 78 | var arr = [], m = this.data.mode; 79 | for(var i=0; i < m.length; i++){ 80 | var op = this.ops[m[i]]; 81 | if(op) arr.push(op); 82 | } 83 | 84 | this.fragment = [ 85 | this.data.lutClamp ? "" : "#define $LUT_NO_CLAMP 1", 86 | this.data.lutFlip ? "#define $LUT_FLIP_Y 1" : "", 87 | this.preFragment, 88 | arr.join("\n"), 89 | "}" 90 | ].join("\n"); 91 | 92 | this.system.needsUpdate = true; 93 | }, 94 | 95 | ops: { 96 | "m": "color.rgb *= $mul;", 97 | "a": "color.rgb += $add;", 98 | "p": "color.rgb = pow(color.rgb, $pow);", 99 | "h": "color.rgb = $rgb2hsv(color.rgb);", 100 | "r": "color.rgb = $hsv2rgb(color.rgb);", 101 | "s": "color.rgb = smoothstep($left, $right, color.rgb);", 102 | "l": "color.rgb = $lut(color).rgb;", 103 | "q": "color.rgb = floor(color.rgb / $quant) * $quant;", 104 | "c": "color.rgb = clamp(color.rgb, $min, $max);", 105 | "g": "color.rgb = vec3(dot(color.rgb, vec3(0.299, 0.587, 0.114)));", 106 | "o": "color.rgb = mix(color.rgb, orig.rgb, $orig);", 107 | "t": "color.rgb = vec3(dot(color.rgb, $red), dot(color.rgb, $green), dot(color.rgb, $blue));", 108 | "b": "color.rgb = color.rgb;" 109 | }, 110 | 111 | diffuse: true, 112 | 113 | preFragment: [ 114 | // Lut from https://github.com/mattdesl/glsl-lut 115 | "vec4 $lut(vec4 textureColor) {", 116 | " #ifndef $LUT_NO_CLAMP", 117 | " textureColor = clamp(textureColor, 0.0, 1.0);", 118 | " #endif", 119 | 120 | " mediump float blueColor = textureColor.b * 63.0;", 121 | 122 | " mediump vec2 quad1;", 123 | " quad1.y = floor(floor(blueColor) / 8.0);", 124 | " quad1.x = floor(blueColor) - (quad1.y * 8.0);", 125 | 126 | " mediump vec2 quad2;", 127 | " quad2.y = floor(ceil(blueColor) / 8.0);", 128 | " quad2.x = ceil(blueColor) - (quad2.y * 8.0);", 129 | 130 | " highp vec2 texPos1;", 131 | " texPos1.x = (quad1.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);", 132 | " texPos1.y = (quad1.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);", 133 | 134 | " #ifdef $LUT_FLIP_Y", 135 | " texPos1.y = 1.0-texPos1.y;", 136 | " #endif", 137 | 138 | " highp vec2 texPos2;", 139 | " texPos2.x = (quad2.x * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.r);", 140 | " texPos2.y = (quad2.y * 0.125) + 0.5/512.0 + ((0.125 - 1.0/512.0) * textureColor.g);", 141 | 142 | " #ifdef $LUT_FLIP_Y", 143 | " texPos2.y = 1.0-texPos2.y;", 144 | " #endif", 145 | 146 | " lowp vec4 newColor1 = texture2D($texture, texPos1);", 147 | " lowp vec4 newColor2 = texture2D($texture, texPos2);", 148 | 149 | " lowp vec4 newColor = mix(newColor1, newColor2, fract(blueColor));", 150 | " return newColor;", 151 | "}", 152 | 153 | "vec3 $rgb2hsv(vec3 c){", 154 | 155 | " vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);", 156 | " vec4 p = mix(vec4(c.bg, K.wz), vec4(c.gb, K.xy), step(c.b, c.g));", 157 | " vec4 q = mix(vec4(p.xyw, c.r), vec4(c.r, p.yzx), step(p.x, c.r));", 158 | 159 | " float d = q.x - min(q.w, q.y);", 160 | " float e = 1.0e-10;", 161 | " return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);", 162 | "}", 163 | 164 | "vec3 $hsv2rgb(vec3 c)", 165 | "{", 166 | " vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);", 167 | " vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);", 168 | " return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);", 169 | "}", 170 | 171 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth){", 172 | "vec3 orig = color.rgb;", 173 | ].join("\n") 174 | }); -------------------------------------------------------------------------------- /components/film/README.md: -------------------------------------------------------------------------------- 1 | Film Grain 2 | ======== 3 | 4 | Noise grain. 5 | 6 | 7 | | Schema | Type | Default | Description | 8 | | ------------- |:-------------:| -----:| :---: | 9 | | speed | number | 1.0 | Speed of noise movement | 10 | | nIntensity | number | 0.5 | Noise intensity | 11 | | sIntensity | number | 0.05 | Scanline intensity | 12 | | sCount | number | 4096 | Scanline count | 13 | -------------------------------------------------------------------------------- /components/film/index.js: -------------------------------------------------------------------------------- 1 | // Ported from the standard shader in Three.js examples 2 | 3 | AFRAME.registerComponent("film", { 4 | multiple: true, 5 | 6 | schema: { 7 | "speed": { default: 1.0 }, 8 | "nIntensity": { default: 0.5 }, 9 | "sIntensity": { default: 0.05 }, 10 | "sCount": { default: 4096 } 11 | }, 12 | 13 | init: function () { 14 | this.uniforms = { 15 | "speed": { type: "f", value: 0.0 }, 16 | "nIntensity": { type: "f", value: 0.5 }, 17 | "sIntensity": { type: "f", value: 0.05 }, 18 | "sCount": { type: "f", value: 4096 } 19 | }; 20 | this.system = this.el.sceneEl.systems.effects; 21 | this.system.register(this); 22 | }, 23 | 24 | update: function () { 25 | var d = this.data, us = this.uniforms; 26 | for(var u in us) { 27 | if(d[u]) us[u].value = d[u]; 28 | } 29 | }, 30 | 31 | remove: function () { 32 | this.system.unregister(this); 33 | }, 34 | 35 | includes: ["common"], 36 | 37 | diffuse: true, 38 | 39 | fragment: [ 40 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth) {", 41 | " vec4 cTextureScreen = color;", 42 | " float dx = rand( uv + mod(time, 3.14) * $speed );", 43 | " vec3 cResult = cTextureScreen.rgb + cTextureScreen.rgb * clamp( 0.1 + dx, 0.0, 1.0 );", 44 | " vec2 sc = vec2( sin( uv.y * $sCount ), cos( uv.y * $sCount ) );", 45 | " cResult += cTextureScreen.rgb * vec3( sc.x, sc.y, sc.x ) * $sIntensity;", 46 | " cResult = cTextureScreen.rgb + clamp( $nIntensity, 0.0,1.0 ) * ( cResult - cTextureScreen.rgb );", 47 | " color.rgb = cResult; //cResult;", 48 | "}" 49 | ].join( "\n" ) 50 | }); -------------------------------------------------------------------------------- /components/fxaa/README.md: -------------------------------------------------------------------------------- 1 | Fast Approximate Anti Aliasing 2 | ======== 3 | 4 | Performs screen space anti aliasing baseed on luminance. It normally would be the last effect in the chain. The schema is a single property and accepts a boolean true/false to toggle the effect without having to reset the effects chain. Taken from [mattdesl three-shader-fxaa](https://github.com/mattdesl/three-shader-fxaa) -------------------------------------------------------------------------------- /components/fxaa/index.js: -------------------------------------------------------------------------------- 1 | // Uses matdesl's three-fxaa-shader 2 | 3 | var FXAAShader = require('../../lib/shaders/FXAAShader'); 4 | 5 | AFRAME.registerComponent("fxaa", { 6 | schema: { default: true }, 7 | 8 | init: function () { 9 | this.system = this.el.sceneEl.systems.effects; 10 | this.material = new THREE.ShaderMaterial({ 11 | fragmentShader: FXAAShader.fragmentShader, 12 | vertexShader: FXAAShader.vertexShader, 13 | uniforms: { 14 | tDiffuse: this.system.tDiffuse, 15 | resolution: { type: 'v2', value: new THREE.Vector2() } 16 | } 17 | }); 18 | this.system.register(this); 19 | this.needsResize = true; 20 | }, 21 | 22 | update: function () { 23 | this.bypass = !this.data; 24 | }, 25 | 26 | setSize: function (w, h) { 27 | this.material.uniforms.resolution.value.set(w, h); 28 | }, 29 | 30 | resize: true, 31 | 32 | remove: function () { 33 | this.material.dispose(); 34 | this.system.unregister(this); 35 | } 36 | }); -------------------------------------------------------------------------------- /components/glitch/README.md: -------------------------------------------------------------------------------- 1 | Glitch 2 | ======== 3 | 4 | Damaged cyborg effect. It has a single boolean property schema to toggle the effect on/off 5 | -------------------------------------------------------------------------------- /components/glitch/index.js: -------------------------------------------------------------------------------- 1 | // Ported from three's glitch pass/shader and added VR support 2 | 3 | AFRAME.registerComponent("glitch", { 4 | schema: { default: true }, 5 | 6 | init: function () { 7 | this.system = this.el.sceneEl.systems.effects; 8 | 9 | this.uniforms = { 10 | "tDisp": { type: "t", value: this.generateHeightmap( 64 ) }, 11 | "amount": { type: "f", value: 0.08 }, 12 | "angle": { type: "f", value: 0.02 }, 13 | "seed": { type: "f", value: 0.02 }, 14 | "seed_x": { type: "f", value: 0.02 },//-1,1 15 | "seed_y": { type: "f", value: 0.02 },//-1,1 16 | "distortion_x": { type: "f", value: 0.5 }, 17 | "distortion_y": { type: "f", value: 0.6 }, 18 | "col_s": { type: "f", value: 0.05 } 19 | }; 20 | 21 | this.exports = { 22 | glitch: { 23 | fragment: this.fragment, 24 | uniforms: this.uniforms 25 | } 26 | } 27 | // by declaring a .material property we set this component to take a whole pass of it's own 28 | this.material = this.system.fuse([this.exports.glitch]); 29 | 30 | this.system.register(this); 31 | }, 32 | 33 | vr: true, 34 | 35 | update: function () { 36 | this.bypass = !this.data; 37 | this.curF = 0; 38 | this.generateTrigger(); 39 | }, 40 | 41 | remove: function () { 42 | this.system.unregister(this); 43 | }, 44 | 45 | tock: function () { 46 | this.uniforms[ 'seed' ].value = Math.random();//default seeding 47 | 48 | if ( this.curF % this.randX == 0) { 49 | 50 | this.uniforms[ 'amount' ].value = Math.random() / 30; 51 | this.uniforms[ 'angle' ].value = THREE.Math.randFloat( - Math.PI, Math.PI ); 52 | this.uniforms[ 'seed_x' ].value = THREE.Math.randFloat( - 1, 1 ); 53 | this.uniforms[ 'seed_y' ].value = THREE.Math.randFloat( - 1, 1 ); 54 | this.uniforms[ 'distortion_x' ].value = THREE.Math.randFloat( 0, 1 ); 55 | this.uniforms[ 'distortion_y' ].value = THREE.Math.randFloat( 0, 1 ); 56 | this.curF = 0; 57 | this.generateTrigger(); 58 | 59 | } else if ( this.curF % this.randX < this.randX / 5 ) { 60 | 61 | this.uniforms[ 'amount' ].value = Math.random() / 90; 62 | this.uniforms[ 'angle' ].value = THREE.Math.randFloat( - Math.PI, Math.PI ); 63 | this.uniforms[ 'distortion_x' ].value = THREE.Math.randFloat( 0, 1 ); 64 | this.uniforms[ 'distortion_y' ].value = THREE.Math.randFloat( 0, 1 ); 65 | this.uniforms[ 'seed_x' ].value = THREE.Math.randFloat( - 0.3, 0.3 ); 66 | this.uniforms[ 'seed_y' ].value = THREE.Math.randFloat( - 0.3, 0.3 ); 67 | 68 | } 69 | 70 | this.curF ++; 71 | }, 72 | 73 | generateTrigger: function() { 74 | 75 | this.randX = THREE.Math.randInt( 120, 240 ); 76 | 77 | }, 78 | 79 | generateHeightmap: function( dt_size ) { 80 | 81 | var data_arr = new Float32Array( dt_size * dt_size * 3 ); 82 | var length = dt_size * dt_size; 83 | 84 | for ( var i = 0; i < length; i ++ ) { 85 | 86 | var val = THREE.Math.randFloat( 0, 1 ); 87 | data_arr[ i * 3 + 0 ] = val; 88 | data_arr[ i * 3 + 1 ] = val; 89 | data_arr[ i * 3 + 2 ] = val; 90 | 91 | } 92 | 93 | var texture = new THREE.DataTexture( data_arr, dt_size, dt_size, THREE.RGBFormat, THREE.FloatType ); 94 | texture.needsUpdate = true; 95 | return texture; 96 | 97 | }, 98 | 99 | fragment: [ 100 | "float $rand(vec2 co){", 101 | "return fract(sin(dot(co.xy ,vec2(12.9898,78.233))) * 43758.5453);", 102 | "}", 103 | 104 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth) {", 105 | "vec2 p = uv;", 106 | "vec2 p2 = vec2( smoothstep(uvClamp.x, uvClamp.y, p.x),p.y);", 107 | "float xs = floor(gl_FragCoord.x / 0.5);", 108 | "float ys = floor(gl_FragCoord.y / 0.5);", 109 | //based on staffantans glitch shader for unity https://github.com/staffantan/unityglitch 110 | "vec4 normal = texture2D ($tDisp, p2 * $seed * $seed);", 111 | "if(p2.y < $distortion_x + $col_s && p2.y > $distortion_x - $col_s * $seed) {", 112 | "if($seed_x>0.){", 113 | "p.y = 1. - (p.y + $distortion_y);", 114 | "}", 115 | "else {", 116 | "p.y = $distortion_y;", 117 | "}", 118 | "}", 119 | "if(p2.x < $distortion_y + $col_s && p2.x > $distortion_y - $col_s * $seed) {", 120 | "if( $seed_y > 0.){", 121 | "p.x = $distortion_x;", 122 | "}", 123 | "else {", 124 | "p.x = 1. - (p.x + $distortion_x);", 125 | "}", 126 | "}", 127 | "p.x+=normal.x* $seed_x * ($seed/5.);", 128 | "p.y+=normal.y* $seed_y * ($seed/5.);", 129 | //base from RGB shift shader 130 | "vec2 offset = $amount * vec2( cos($angle), sin($angle));", 131 | "vec4 cr = textureVR(tDiffuse, p + offset);", 132 | "vec4 cga = textureVR(tDiffuse, p);", 133 | "vec4 cb = textureVR(tDiffuse, p - offset);", 134 | "color = vec4(cr.r, cga.g, cb.b, cga.a);", 135 | //add noise 136 | "vec4 snow = 200.*$amount*vec4($rand(vec2(xs * $seed,ys * $seed*50.))*0.2);", 137 | "color = color+ snow;", 138 | "}" 139 | ].join( "\n" ) 140 | }); -------------------------------------------------------------------------------- /components/godrays/README.md: -------------------------------------------------------------------------------- 1 | God Rays 2 | ======== 3 | 4 | Imitates crepuscular rays by performing a radial blur on the depth buffer. -------------------------------------------------------------------------------- /components/godrays/index.js: -------------------------------------------------------------------------------- 1 | // Ported from the shader in Three.js examples 2 | // with the addition of a separate input pass 3 | 4 | AFRAME.registerComponent("godrays", { 5 | schema: { 6 | "tint": { type: "color", default: "#FFFFFF" }, 7 | "threshold": { type: "vec4", default: new THREE.Vector4(0,1,1) }, 8 | "src": { type: "selector", default: null }, 9 | "intensity": { default: 1 }, 10 | "filter": { type: "array", default: [] }, 11 | "ratio": { default: 0.25 } 12 | }, 13 | 14 | init: function () { 15 | this.system = this.el.sceneEl.systems.effects; 16 | var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }; 17 | this.rtFilter = new THREE.WebGLRenderTarget( 1, 1, pars ); 18 | this.rtTextureGodRays1 = new THREE.WebGLRenderTarget( 1, 1, pars ); 19 | this.rtTextureGodRays2 = new THREE.WebGLRenderTarget( 1, 1, pars ); 20 | 21 | this.exports = { 22 | filter: { 23 | includes: ["packing"], 24 | uniforms: { 25 | "tint": { type: "c", value: new THREE.Color() }, 26 | "threshold": { type: "v2", value: new THREE.Vector2(0,1) }, 27 | }, 28 | depth: true, 29 | fragment: [ 30 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth) {", 31 | " float v = viewZToOrthographicDepth(perspectiveDepthToViewZ(depth, cameraNear, cameraFar), cameraNear, cameraFar);", 32 | " color.rgb = vec3(smoothstep($threshold.x, $threshold.y, v)) * $tint;", 33 | "}" 34 | ].join( "\n" ), 35 | }, 36 | blur: { 37 | uniforms: { 38 | step: { type:"f", value: 1.0 }, 39 | src: { type: "v3", value: new THREE.Vector3( 0.5, 0.5, 0. ) } 40 | }, 41 | fragment: [ 42 | "void $main(inout vec4 color, vec4 orig, vec2 uv, float depth) {", 43 | "vec2 center = vec2(mix(uvClamp.x, uvClamp.y, $src.x), $src.y);", 44 | "vec2 delta = center - uv;", 45 | "float dist = length( delta );", 46 | "vec2 stepv = $step * delta / dist;", 47 | "float iters = dist/$step;", 48 | "vec4 col = vec4(0.0);", 49 | "if ( 0.0 <= iters && uv.y < 1.0 ) col += textureVR( tDiffuse, uv );", 50 | "uv += stepv;", 51 | "if ( 1.0 <= iters && uv.y < 1.0 ) col += textureVR( tDiffuse, uv );", 52 | "uv += stepv;", 53 | "if ( 2.0 <= iters && uv.y < 1.0 ) col += textureVR( tDiffuse, uv );", 54 | "uv += stepv;", 55 | "if ( 3.0 <= iters && uv.y < 1.0 ) col += textureVR( tDiffuse, uv );", 56 | "uv += stepv;", 57 | "if ( 4.0 <= iters && uv.y < 1.0 ) col += textureVR( tDiffuse, uv );", 58 | "uv += stepv;", 59 | "if ( 5.0 <= iters && uv.y < 1.0 ) col += textureVR( tDiffuse, uv );", 60 | "color = col/6.0;", 61 | "}" 62 | 63 | ].join( "\n" ) 64 | } 65 | } 66 | 67 | this.materialGodraysGenerate = this.system.fuse([this.exports.blur]); 68 | this.uniforms = { 69 | "intensity": { type: "f", value: 1 }, 70 | "attenuation": {type: "f", value: 1 }, 71 | "texture": { type: "t", value: this.rtTextureGodRays2 } 72 | }; 73 | 74 | this.materialFilter = null; 75 | 76 | this.needsResize = true; 77 | this.system.register(this); 78 | }, 79 | 80 | setSize: function (w,h) { 81 | w = Math.round(w * this.data.ratio); 82 | h = Math.round(h * this.data.ratio); 83 | this.rtTextureGodRays1.setSize(w,h); 84 | this.rtTextureGodRays2.setSize(w,h); 85 | this.rtFilter.setSize(w,h); 86 | }, 87 | 88 | update: function (oldData) { 89 | this.exports.filter.uniforms.tint.value.set(this.data.tint); 90 | this.uniforms.intensity.value = this.data.intensity; 91 | if(this.data.filter !== oldData.filter) { 92 | if(this.materialFilter) this.materialFilter.dispose(); 93 | this.materialFilter = this.system.fuse(this.data.filter.length ? this.data.filter : [this.exports.filter]); 94 | } 95 | this.bypass = this.data.src === null; 96 | }, 97 | 98 | tock: function () { 99 | if (!this.system.isActive(this, true)) return; 100 | var self = this; 101 | 102 | this.system.tDiffuse.value = this.system.renderTarget.texture; 103 | this.system.renderPass(this.materialFilter, this.rtFilter, fn ) 104 | 105 | var fn = function (material, camera, eye) { 106 | var cp3 = new THREE.Vector3(), cd3 = new THREE.Vector3(); 107 | var v3 = self.exports.blur.uniforms[ "src" ].value; 108 | self.data.src.object3D.getWorldPosition(v3); 109 | camera.getWorldPosition(cp3); 110 | camera.getWorldDirection(cd3); 111 | cp3.sub(v3); 112 | cp3.normalize(); 113 | cd3.normalize(); 114 | self.uniforms.attenuation.value = Math.pow(Math.max(0, -cd3.dot(cp3)), 1.33); 115 | 116 | v3.project( camera ); 117 | v3.set((v3.x + 1 ) / 2, (v3.y + 1 ) / 2, 0); 118 | 119 | }; 120 | 121 | var filterLen = 1.0; 122 | var TAPS_PER_PASS = 6.0; 123 | 124 | var pass = 1.0; 125 | var stepLen = filterLen * Math.pow( TAPS_PER_PASS, -pass ); 126 | this.exports.blur.uniforms[ "step" ].value = stepLen; 127 | this.system[ "tDiffuse" ].value = this.rtFilter.texture; 128 | this.system.renderPass(this.materialGodraysGenerate, this.rtTextureGodRays2, fn ) 129 | 130 | pass = 2.0; 131 | stepLen = filterLen * Math.pow( TAPS_PER_PASS, -pass ); 132 | this.exports.blur.uniforms[ "step" ].value = stepLen; 133 | this.system[ "tDiffuse" ].value = this.rtTextureGodRays2.texture; 134 | this.system.renderPass(this.materialGodraysGenerate, this.rtTextureGodRays1, fn ); 135 | 136 | pass = 3.0; 137 | stepLen = filterLen * Math.pow( TAPS_PER_PASS, -pass ); 138 | this.exports.blur.uniforms[ "step" ].value = stepLen; 139 | this.system[ "tDiffuse" ].value = this.rtTextureGodRays1.texture; 140 | this.system.renderPass(this.materialGodraysGenerate, this.rtTextureGodRays2, fn ) 141 | }, 142 | 143 | remove: function () { 144 | this.rtTextureGodRays1.dispose(); 145 | this.rtTextureGodRays2.dispose(); 146 | this.rtFilter.dispose(); 147 | 148 | this.materialGodraysGenerate.dispose(); 149 | this.materialFilter.dispose(); 150 | this.system.unregister(this); 151 | }, 152 | 153 | diffuse: true, 154 | 155 | fragment: [ 156 | "float $blendScreen(float base, float blend) {", 157 | " return 1.0-((1.0-base)*(1.0-blend));", 158 | "}", 159 | 160 | "vec3 $blendScreen(vec3 base, vec3 blend) {", 161 | " return vec3($blendScreen(base.r,blend.r),$blendScreen(base.g,blend.g),$blendScreen(base.b,blend.b));", 162 | "}", 163 | 164 | "vec3 $blendScreen(vec3 base, vec3 blend, float opacity) {", 165 | " return ($blendScreen(base, blend) * opacity + base * (1.0 - opacity));", 166 | "}", 167 | 168 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth) {", 169 | " vec4 texel = texture2D($texture, uv);", 170 | " color.rgb = $blendScreen( color.rgb, texel.rgb, $intensity * $attenuation);", 171 | "}" 172 | ].join( "\n" ) 173 | }); -------------------------------------------------------------------------------- /components/index.js: -------------------------------------------------------------------------------- 1 | require("./outline"); 2 | require("./film"); 3 | require("./fxaa"); 4 | require("./bloom"); 5 | require("./colors"); 6 | require("./glitch"); 7 | require("./godrays"); 8 | require("./ssao"); 9 | require("./lighty"); 10 | -------------------------------------------------------------------------------- /components/lighty/index.js: -------------------------------------------------------------------------------- 1 | AFRAME.registerComponent("lighty", { 2 | schema: { 3 | color: { type: "color", default: "#000000" }, 4 | radius: { type: "number", default: 0 }, 5 | decay: { type: "number", default: 1 } 6 | }, 7 | 8 | init: function () { 9 | this.el.sceneEl.systems.effects.addLight(this); 10 | }, 11 | 12 | remove: function () { 13 | this.el.sceneEl.systems.effects.removeLight(this); 14 | } 15 | }); -------------------------------------------------------------------------------- /components/outline/README.md: -------------------------------------------------------------------------------- 1 | Outline 2 | ======== 3 | 4 | Outlines edges based on depth -------------------------------------------------------------------------------- /components/outline/index.js: -------------------------------------------------------------------------------- 1 | // Sobel and freichen shaders from three.js examples 2 | 3 | AFRAME.registerComponent("outline", { 4 | multiple: true, 5 | 6 | schema: { 7 | enabled: { default: true }, 8 | color: { type: "color", default: "#000000" }, 9 | width: { type: "vec2", default: new THREE.Vector2(1,1) }, 10 | range: { type: "vec2", default: new THREE.Vector2(0,1500) }, 11 | strength: {type: "number", default: 1}, 12 | ratio: { type: "number", default: 0.5 }, 13 | smooth: { default: false } 14 | }, 15 | 16 | init: function () { 17 | this.system = this.el.sceneEl.systems.effects; 18 | var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }; 19 | this.renderTarget = new THREE.WebGLRenderTarget( 1, 1, pars ); 20 | this.blurTarget = new THREE.WebGLRenderTarget( 1, 1, pars ); 21 | this.needsResize = true; 22 | this.resolution = { type: "v4", value: new THREE.Vector4()}; 23 | this.tockUniforms = { 24 | resolution: this.resolution, 25 | color: { type: "c", value: new THREE.Color() }, 26 | width: { type: "v2", value: null }, 27 | range: { type: "v2", value: null }, 28 | strength: { type: "f", value: 1 } 29 | }; 30 | 31 | this.blurDirection = { type: "v2", value: new THREE.Vector2()}; 32 | 33 | this.exports = { 34 | sobel: { 35 | fragment: this.sobel, 36 | uniforms: this.tockUniforms, 37 | includes: ["packing"], 38 | depth: true 39 | }, 40 | 41 | blur: { 42 | fragment: this.blur, 43 | uniforms: { resolution: this.tockUniforms.resolution, direction: this.blurDirection }, 44 | diffuse: true 45 | } 46 | } 47 | this.currentMaterial = this.system.fuse([this.exports.sobel], true); 48 | 49 | 50 | this.blurMaterial = this.system.fuse([this.exports.blur], true); 51 | 52 | this.uniforms = { 53 | texture: { type: "t", value: this.renderTarget.texture } 54 | } 55 | 56 | this.system.register(this); 57 | }, 58 | 59 | update: function (oldData) { 60 | this.bypass = !this.data.enabled; 61 | this.tockUniforms.color.value.set(this.data.color); 62 | this.tockUniforms.width.value = this.data.width; 63 | this.tockUniforms.range.value = this.data.range; 64 | this.tockUniforms.strength.value = 1 / this.data.strength; 65 | }, 66 | 67 | setSize: function(w, h) { 68 | w = Math.round(w * this.data.ratio); 69 | h = Math.round(h * this.data.ratio); 70 | this.renderTarget.setSize(w,h); 71 | this.blurTarget.setSize(w,h); 72 | this.resolution.value.set(w, h, 1/w, 1/h); 73 | }, 74 | 75 | tock: function () { 76 | if (!this.system.isActive(this, true)) return; 77 | this.system.renderPass(this.currentMaterial, this.renderTarget); 78 | this.system.tDiffuse.value = this.renderTarget; 79 | if (!this.data.smooth) return; 80 | this.blurDirection.value.set(1,0); 81 | this.system.renderPass(this.blurMaterial, this.blurTarget); 82 | this.system.tDiffuse.value = this.blurTarget; 83 | this.blurDirection.value.set(0,1); 84 | this.system.renderPass(this.blurMaterial, this.renderTarget); 85 | }, 86 | 87 | remove: function () { 88 | this.system.unregister(this); 89 | }, 90 | 91 | diffuse: true, 92 | 93 | sobel: [ 94 | "mat3 $G[2];", 95 | 96 | "const mat3 $g0 = mat3( 1.0, 2.0, 1.0, 0.0, 0.0, 0.0, -1.0, -2.0, -1.0 );", 97 | "const mat3 $g1 = mat3( 1.0, 0.0, -1.0, 2.0, 0.0, -2.0, 1.0, 0.0, -1.0 );", 98 | 99 | 100 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth) {", 101 | 102 | "vec3 I[3];", 103 | "float cnv[2];", 104 | "float d;", 105 | 106 | "$G[0] = $g0;", 107 | "$G[1] = $g1;", 108 | 109 | "for (float i=0.0; i<3.0; i++)", 110 | "for (float j=0.0; j<3.0; j++) {", 111 | " d = texture2D(tDepth, uv + resolution.zw * vec2(i-1.0,j-1.0) ).x;", 112 | " d = perspectiveDepthToViewZ(d, cameraNear, cameraFar); ", 113 | " I[int(i)][int(j)] = viewZToOrthographicDepth(d, cameraNear, cameraFar);", 114 | "}", 115 | 116 | "for (int i=0; i<2; i++) {", 117 | "float dp3 = dot($G[i][0], I[0]) + dot($G[i][1], I[1]) + dot($G[i][2], I[2]);", 118 | "cnv[i] = dp3 * dp3; ", 119 | "}", 120 | "color = vec4($color, sqrt(cnv[0]*cnv[0]+cnv[1]*cnv[1]));", 121 | "} " 122 | ].join("\n"), 123 | 124 | blur: [ 125 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth){", 126 | "color.a *= 0.44198;", 127 | "color.a += texture2D(tDiffuse, uv + ($direction * $resolution.zw )).a * 0.27901;", 128 | "color.a += texture2D(tDiffuse, uv - ($direction * $resolution.zw )).a * 0.27901;", 129 | "}" 130 | ].join("\n"), 131 | 132 | fragment: [ 133 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth){", 134 | " vec4 texel = texture2D($texture, uv);", 135 | " color.rgb = mix(color.rgb, texel.rgb, smoothstep(0.1,0.3,texel.a));", 136 | "}" 137 | ].join("\n") 138 | }); -------------------------------------------------------------------------------- /components/ssao/README.md: -------------------------------------------------------------------------------- 1 | SSAO 2 | ======== 3 | 4 | Alchemy Screen Space Ambient Obscurance 5 | 6 | | Schema | Type | Default | Description | 7 | | ------------- |:-------------:| -----:| :---: | 8 | | samples | integer | 16 | The number of depth samples to get for every pixel. | 9 | | rings | integer | 5 | The number of rings to distribute the samples. Should be odd. | 10 | | radius | float | 0.5 | Radius of sampling in normalized screen coordinates(0-1).| 11 | | ratio | float | 0.5 | The ratio of the ssao render target. Affects performance | 12 | | intensity | float | 1.0 | Intensity of the final ssao composition | 13 | | scale | float | 0.15 | Relative to the camera far range. 0-1 | 14 | | blurRadius | integer | 7 | Radius for the blur. 0 disables | 15 | | depthCutoff | float | 10 | In camera units, controls spillage of ssao on edges | -------------------------------------------------------------------------------- /components/ssao/index.js: -------------------------------------------------------------------------------- 1 | var SAOShader = require("../../lib/shaders/SAOShader"); 2 | var DepthLimitedBlurShader = require("../../lib/shaders/DepthLimitedBlurShader"); 3 | 4 | AFRAME.registerComponent("ssao", { 5 | schema: { 6 | "samples": { type: "number", default: 16}, 7 | "rings": { type: "number", default: 7 }, 8 | "radius": { type: "number", default: 0.5 }, 9 | "ratio": { default: 0.5 }, 10 | "intensity": { default: 1.0 }, 11 | "maxDepth": { default: 0.99 }, 12 | "bias": { default: 0.05 }, 13 | "scale": { default: 0.15 }, 14 | "blurRadius": { default: 7 }, 15 | "depthCutoff": { default: 10 } 16 | }, 17 | 18 | init: function () { 19 | this.system = this.el.sceneEl.systems.effects; 20 | var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }; 21 | this.renderTargets = []; 22 | this.renderTargets.push(new THREE.WebGLRenderTarget( 1, 1, pars)); 23 | this.renderTargets.push(new THREE.WebGLRenderTarget( 1, 1, pars)); 24 | this.uniforms = { 25 | "texture": { type: "t", value: this.renderTargets[0].texture }, 26 | "intensity": { type: "f", value: 1.0 }, 27 | "maxDepth": { type: "f", value: 0.99 }, 28 | "depthCutoff": { type: "f", default: 1} 29 | }; 30 | this.SAOMaterial = null; 31 | this.hBlurMaterial = null; 32 | this.vBlurMaterial = null; 33 | this.sizeUniform = { type: "v2", value: new THREE.Vector2()}; 34 | this.system.register(this); 35 | }, 36 | 37 | update: function (od) { 38 | var d = this.data, self=this; 39 | 40 | this.rebuild(d.rings !== od.rings || d.samples !== od.samples, d.blurRadius !== od.blurRadius); 41 | this.uniforms.depthCutoff.value = d.depthCutoff; 42 | this.uniforms.intensity.value = d.intensity; 43 | this.uniforms.maxDepth.value = d.maxDepth; 44 | this.SAOMaterial.uniforms.bias.value = d.bias; 45 | this.SAOMaterial.uniforms.scale.value = d.scale; 46 | this.SAOMaterial.uniforms.kernelRadius.value = d.radius; 47 | this.hBlurMaterial.uniforms.depthCutoff.value = d.depthCutoff; 48 | this.vBlurMaterial.uniforms.depthCutoff.value = d.depthCutoff; 49 | }, 50 | 51 | rebuild: function (sao, blur) { 52 | var d = this.data; 53 | if(sao) { 54 | if (this.SAOMaterial) { 55 | this.SAOMaterial.dispose(); 56 | } 57 | this.SAOMaterial = this.system.materialize(SAOShader(true)); 58 | this.SAOMaterial.defines["RINGS"] = parseInt(d.rings) + "."; 59 | this.SAOMaterial.defines["SAMPLES"] = parseInt(d.samples) + "."; 60 | this.SAOMaterial.uniforms.cameraFar = this.system.cameraFar; 61 | this.SAOMaterial.uniforms.cameraNear = this.system.cameraNear; 62 | } 63 | if(blur) { 64 | if (this.hBlurMaterial) { 65 | this.hBlurMaterial.dispose(); 66 | this.vBlurMaterial.dispose(); 67 | } 68 | this.hBlurMaterial = this.system.materialize(DepthLimitedBlurShader(d.blurRadius, d.blurRadius/2, new THREE.Vector2(1,0))); 69 | this.vBlurMaterial = this.system.materialize(DepthLimitedBlurShader(d.blurRadius, d.blurRadius/2, new THREE.Vector2(0,1))); 70 | this.hBlurMaterial.uniforms.size = this.sizeUniform; 71 | this.vBlurMaterial.uniforms.size = this.sizeUniform; 72 | this.hBlurMaterial.uniforms.cameraFar = this.system.cameraFar; 73 | this.hBlurMaterial.uniforms.cameraNear = this.system.cameraNear; 74 | this.vBlurMaterial.uniforms.cameraFar = this.system.cameraFar; 75 | this.vBlurMaterial.uniforms.cameraNear = this.system.cameraNear; 76 | } 77 | }, 78 | 79 | setSize: function(w, h) { 80 | w = Math.ceil(w * this.data.ratio); 81 | h = Math.ceil(h * this.data.ratio); 82 | 83 | this.sizeUniform.value.set(w,h); 84 | 85 | this.renderTargets.forEach(function (rt) { 86 | rt.setSize(w,h); 87 | }); 88 | }, 89 | 90 | tock: function (time) { 91 | if (!this.system.isActive(this, true)) return; 92 | //this.SAOMaterial.uniforms.randomSeed.value = Math.random(); 93 | this.SAOMaterial.uniforms[ 'cameraInverseProjectionMatrix' ].value.getInverse( this.el.sceneEl.camera.projectionMatrix ); 94 | this.SAOMaterial.uniforms[ 'cameraProjectionMatrix' ].value = this.el.sceneEl.camera.projectionMatrix; 95 | 96 | this.SAOMaterial.uniforms.tDepth.value = this.el.sceneEl.renderTarget.depthTexture; 97 | this.system.renderPass(this.SAOMaterial, this.renderTargets[0], true); 98 | 99 | if(this.data.blurRadius) { 100 | this.hBlurMaterial.uniforms.tDiffuse.value = this.renderTargets[0].texture; 101 | this.system.renderPass(this.hBlurMaterial, this.renderTargets[1], true); 102 | 103 | this.vBlurMaterial.uniforms.tDiffuse.value = this.renderTargets[1].texture; 104 | this.system.renderPass(this.vBlurMaterial, this.renderTargets[0], true); 105 | } 106 | }, 107 | 108 | remove: function () { 109 | this.SAOMaterial.dispose(); 110 | this.hBlurMaterial.dispose(); 111 | this.vBlurMaterial.dispose(); 112 | this.renderTargets[0].dispose(); 113 | this.renderTargets[1].dispose(); 114 | this.system.unregister(this); 115 | }, 116 | 117 | includes: ["packing"], 118 | 119 | depth: true, 120 | 121 | diffuse: true, 122 | 123 | fragment: [ 124 | "float $unpackDepth(vec3 pack) {", 125 | " float depth = dot( pack, 1.0 / vec3(1.0, 256.0, 256.0*256.0) );", 126 | " return depth * (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0);", 127 | "}", 128 | "void $main(inout vec4 color, vec4 origColor, vec2 uv, float depth) {", 129 | " vec4 texel = texture2D($texture, uv);", 130 | " float z = perspectiveDepthToViewZ( $unpackDepth(texel.xyz), cameraNear, cameraFar );", 131 | " float Z = perspectiveDepthToViewZ( depth, cameraNear, cameraFar );", 132 | " color.rgb *= abs(z-Z) > $depthCutoff || Z >= $maxDepth * cameraFar ? 1.0 : 1.0 - texel.a * $intensity;", 133 | "}" 134 | ].join( "\n" ) 135 | }); -------------------------------------------------------------------------------- /dist/afrane-effects.min.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["dist/aframe-effects.js"],"names":["modules","installedModules","__webpack_require__","moduleId","exports","module","id","loaded","call","m","c","p","window","AFRAME","Component","el","self","this","attrName","name","components","data","System","sceneEl","systems","registerShader","registerComponent","definition","NewComponent","proto","Object","keys","forEach","key","value","writable","attr","prototype","create","constructor","registerSystem","NewSystem","fx","renderer","scene","cameras","renderTarget","object3D","Array","isArray","isPlaying","effects","init","chain","sys","oldData","update","tick","camera","set","get","v","remove","arr","split","pro","obj","schema","type","default","i","undefined","nd","o","render","time","behaviors","timeDelta","b","behavior","tock","Effects","passes","_passes","setupPostState","needsOverride","lightComponents","LightState","rows","cols","width","height","tileData","tileTexture","lightTexture","THREE","DataTexture","Float32Array","RGBAFormat","FloatType","needsUpdate","addLight","push","removeLight","index","indexOf","splice","WebGLRenderTarget","minFilter","LinearFilter","magFilter","format","texture","generateMipmaps","depthBuffer","depthTexture","DepthTexture","UnsignedShortType","stencilBuffer","Scene","OrthographicCamera","quad","Mesh","PlaneBufferGeometry","frustumCulled","add","sceneLeft","quadLeft","geometry","attributes","uv","array","sceneRight","quadRight","targets","tDiffuse","tDepth","cameraFar","cameraNear","uvClamp","uvBoth","resolution","Vector4","vertexShader","join","uvLeft","Vector2","uvRight","parseToken","renderPass","material","viewCb","forceClear","isFn","s","getSize","oldClear","autoClear","length","setView","Math","round","x","y","w","h","viewport","scissor","setViewport","setScissor","materialize","fs","fragmentShader","uniforms","ShaderMaterial","depthWrite","depthTest","blending","NoBlending","fog","extensions","derivatives","defines","fuse","temp","alpha","count","chunks","head","main","includes","needsDepth","needsDiffuse","k","callMain","swapMain","args","tok","exec","prop","document","querySelector","replace","fragment","Document","body","textContent","depth","dataset","diffuse","trim","defaults","prefix","d","u","inc","t2u","f","t","v2","v3","v4","m2","m3","m4","premain","source","debug","console","log","rebuild","pass","dispose","pickup","makepass","vr","writeBuffer","readBuffer","isActive","resize","bypass","isEnabled","needsResize","setSize","size","register","unregister","effect","rt","rts","onBeforeRender","resizeTiles","ArrayCamera","tileLights","rendererRender","setupPasses","far","near","r","ceil","Uint8Array","projectionMatrix","lights","image","ld","viewMatrix","matrixWorldInverse","fill","vector","Vector3","light","setFromMatrixPosition","matrixWorld","pw","pm","bs","lightBounds","radius","applyMatrix4","toArray","color","decay","i4","floor","i8","j","pos","minX","maxX","minY","maxY","hw","hh","copy","z","project","min","max","multiple","enabled","range","strength","ratio","smooth","system","pars","blurTarget","tockUniforms","Color","blurDirection","sobel","blur","direction","currentMaterial","blurMaterial","speed","nIntensity","sIntensity","sCount","us","FXAAShader","LuminosityHighPassShader","BlurDirectionX","BlurDirectionY","enable","threshold","filter","renderTargetsHorizontal","renderTargetsVertical","nMips","renderTargetBright","luminosityThreshold","smoothWidth","defaultColor","defaultOpacity","materialHighPassFilter","separableBlurMaterials","kernelSizeArray","getSeperableBlurMaterial","compositeMaterial","getCompositeMaterial","bloomFactors","bloomTintColors","oldClearColor","getClearColor","oldClearAlpha","getClearAlpha","oldAutoClear","setClearColor","inputRenderTarget","resx","resy","kernelRadius","KERNEL_RADIUS","SIGMA","colorTexture","texSize","NUM_MIPS","blurTexture1","blurTexture2","blurTexture3","blurTexture4","blurTexture5","bloomStrength","bloomRadius","shaderID","mode","lut","lutClamp","lutFlip","mul","pow","left","right","quant","orig","red","green","blue","Texture","NearestFilter","needsRebuild","op","ops","preFragment","a","l","q","g","tDisp","generateHeightmap","amount","angle","seed","seed_x","seed_y","distortion_x","distortion_y","col_s","glitch","curF","generateTrigger","random","randX","randFloat","PI","randInt","dt_size","data_arr","val","RGBFormat","tint","src","intensity","rtFilter","rtTextureGodRays1","rtTextureGodRays2","step","materialGodraysGenerate","attenuation","materialFilter","fn","eye","cp3","cd3","getWorldPosition","getWorldDirection","sub","normalize","dot","filterLen","TAPS_PER_PASS","stepLen","SAOShader","DepthLimitedBlurShader","samples","rings","maxDepth","bias","scale","blurRadius","depthCutoff","renderTargets","SAOMaterial","hBlurMaterial","vBlurMaterial","sizeUniform","od","sao","parseInt","getInverse","isFirst","cameraProjectionMatrix","Matrix4","cameraInverseProjectionMatrix","minResolution","randomSeed","BlurShaderUtils","createSampleWeights","stdDev","gaussian","exp","sqrt","weights","createSampleOffsets","uvIncrement","offsets","clone","multiplyScalar","configure","sampleUvOffsets","sampleWeights","config","ShaderChunk","utils","CubeLoader","CubeTextureLoader","texturePromises","ambientOcclusionMap","ambientOcclusionMapIntensity","ambientOcclusionTextureOffset","ambientOcclusionTextureRepeat","displacementMap","displacementScale","displacementBias","displacementTextureOffset","displacementTextureRepeat","emissive","emissiveIntensity","envMap","metalness","metalnessMap","metalnessTextureOffset","metalnessTextureRepeat","normalMap","normalScale","normalTextureOffset","normalTextureRepeat","offset","repeat","roughness","roughnessMap","roughnessTextureOffset","roughnessTextureRepeat","sphericalEnvMap","wireframe","wireframeLinewidth","MeshStandardMaterial","getMaterialData","updateMap","updateDistortionMap","updateEnvMap","onBeforeCompile","shader","State","updateMaterial","isLoadingEnvMap","loadTexture","textureLoaded","mapping","SphericalReflectionMapping","handleTextureEvents","then","cube","Promise","resolve","srcLoader","validateCubemapSrc","loadEnvMap","urls","load","newData","aoMapIntensity"],"mappings":"CAAS,SAAUA,SAET,GAAIC,oBAGJ,SAASC,qBAAoBC,UAG5B,GAAGF,iBAAiBE,UACnB,MAAOF,kBAAiBE,UAAUC,OAGnC,IAAIC,QAASJ,iBAAiBE,WAC7BC,WACAE,GAAIH,SACJI,OAAQ,MAITP,SAAQG,UAAUK,KAAKH,OAAOD,QAASC,OAAQA,OAAOD,QAASF,oBAG/DG,QAAOE,OAAS,IAGhB,OAAOF,QAAOD,QAKfF,oBAAoBO,EAAIT,OAGxBE,qBAAoBQ,EAAIT,gBAGxBC,qBAAoBS,EAAI,EAGxB,OAAOT,qBAAoB,MAK/B,SAAUG,OAAQD,QAASF,qBAEhC,IAAKU,OAAOC,OAAQ,CAChB,GAAIC,WAAY,SAAUC,GAAIT,IAC1B,GAAIU,MAAOC,IACXA,MAAKF,GAAKA,EACVE,MAAKF,EACLE,MAAKX,GAAKA,EACVW,MAAKC,SAAWD,KAAKE,MAAQb,GAAK,KAAOA,GAAK,GAC9CW,MAAKF,GAAGK,WAAWH,KAAKC,UAAYD,IACpCA,MAAKI,QAGT,IAAIC,QAAS,SAAUP,IACnB,GAAIC,MAAOC,IACXA,MAAKF,GAAKE,KAAKM,QAAUR,EACzBE,MAAKF,GAAGS,QAAQP,KAAKE,MAAQF,KAGjCJ,SACIO,cACAI,WACAC,eAAgB,aAGpBZ,QAAOa,kBAAoB,SAAUP,KAAMQ,YACvC,GAAIC,aACJ,IAAIC,SAEJC,QAAOC,KAAKJ,YAAYK,QAAQ,SAAUC,KACtCJ,MAAMI,MACFC,MAAOP,WAAWM,KAClBE,SAAU,OAIlBP,cAAe,SAAUb,GAAIqB,KAAM9B,IAC/BQ,UAAUN,KAAKS,KAAMF,GAAIqB,KAAM9B,IAGnCsB,cAAaS,UAAYP,OAAOQ,OAAOxB,UAAUuB,UAAWR,MAC5DD,cAAaS,UAAUlB,KAAOA,IAC9BS,cAAaS,UAAUE,YAAcX,YAErCf,QAAOO,WAAWD,MAAQS,YAC1B,OAAOA,cAGXf,QAAO2B,eAAiB,SAAUrB,KAAMQ,YACpC,GAAIc,UACJ,IAAIZ,SAEJC,QAAOC,KAAKJ,YAAYK,QAAQ,SAAUC,KACtCJ,MAAMI,MACFC,MAAOP,WAAWM,KAClBE,SAAU,OAIlBM,WAAY,SAAU1B,GAAIqB,KAAM9B,IAC5BgB,OAAOd,KAAKS,KAAMF,GAAIqB,KAAM9B,IAGhCmC,WAAUJ,UAAYP,OAAOQ,OAAOhB,OAAOe,UAAWR,MACtDY,WAAUJ,UAAUlB,KAAOA,IAC3BsB,WAAUJ,UAAUE,YAAcE,SAElC5B,QAAOW,QAAQL,MAAQsB,SACvB,OAAOA,WAGX,IAAIC,IAAK,SAASC,SAAUC,MAAOC,SAC/B5B,KAAKM,QAAUN,IACfA,MAAK6B,aAAe,IACpB7B,MAAK0B,SAAWA,QAChB1B,MAAK8B,SAAWH,KAChB3B,MAAK4B,QAAUG,MAAMC,QAAQJ,SAAWA,SAAWA,QACnD5B,MAAKG,aACLH,MAAKO,UACLP,MAAKiC,UAAY,IACjBjC,MAAKO,QAAQ2B,QAAU,GAAItC,QAAOW,QAAQ2B,QAAQlC,KAClDA,MAAKO,QAAQ2B,QAAQC,OAGzBV,IAAGL,UAAYP,OAAOQ,WAClBe,OACInB,MAAO,SAASmB,OACZ,GAAIC,KAAMrC,KAAKO,QAAQ2B,QAASnC,KAAOC,IACvC,IAAIsC,SAAUD,IAAIjC,IAClBiC,KAAIjC,KAAOgC,KACXC,KAAIE,OAAOD,QACXD,KAAIG,KAAK,EAAE,KAInBC,QACIC,IAAK,SAASd,SACV5B,KAAK4B,QAAUG,MAAMC,QAAQJ,SAAWA,SAAWA,UAGvDe,IAAK,WACD,MAAO3C,MAAK4B,QAAQ,KAI5BD,OACIe,IAAK,SAASE,GACV5C,KAAK8B,SAAWc,GAGpBD,IAAK,WACD,MAAO3C,MAAK8B,WAIpBK,MACIlB,MAAO,SAASf,MACZF,KAAK6C,OAAO3C,KACZ,IAAI4C,KAAM5C,KAAK6C,MAAM,KACrB,IAAIC,KAAMpD,OAAOO,WAAW2C,IAAI,GAChC,KAAIE,IAAK,MAAO,KAChB,IAAIC,KAAM,GAAID,KAAIhD,KAAM8C,IAAI,GAC5B,IAAGG,IAAIC,OAAOC,MAAQF,IAAIC,OAAOE,QAAS,CACtCH,IAAI7C,KAAO6C,IAAIC,OAAOE,YACnB,CACH,IAAI,GAAIC,KAAKJ,KAAIC,OAAQ,CACrBD,IAAI7C,KAAKiD,GAAKJ,IAAIC,OAAOG,GAAGD,SAGpC,GAAGH,IAAId,KAAMc,IAAId,MACjB,IAAGc,IAAIV,OAAQU,IAAIV,UACnB,OAAOU,OAIfV,QACItB,MAAO,SAASf,KAAME,MAClB,GAAI6C,KAAMjD,KAAKG,WAAWD,KAC1B,KAAI+C,IAAK,CAAEA,IAAMjD,KAAKmC,KAAKjC,MAC3B,IAAI+C,KAAO7C,OAASkD,UAAW,MAE/B,IAAIhB,SAAUW,IAAI7C,KAAMmD,GAAKN,IAAI7C,KAAM8C,OAASD,IAAIC,MACpD,IAAID,IAAIC,OAAOC,MAAQF,IAAIC,OAAOE,QAAS,CACvCH,IAAI7C,KAAOA,SACR,CACHkC,UACA,KAAI,GAAIkB,KAAKD,IAAI,CACbjB,QAAQkB,GAAKD,GAAGC,EAChB,IAAIpD,KAAKoD,GAAID,GAAGC,GAAKpD,KAAKoD,IAGlC,GAAGP,IAAIV,OAAQU,IAAIV,OAAOD,WAIlCO,QACI5B,MAAO,SAASf,MACZ,GAAI+C,KAAMjD,KAAKG,WAAWD,KAC1B,IAAG+C,KAAOA,IAAIJ,OAAQ,CAAEI,IAAIJ,eACrB7C,MAAKG,WAAWD,QAI/BuD,QACIxC,MAAO,SAASyC,MACZ,GAAIC,WAAY3D,KAAKG,UACrB,IAAIkC,KAAMrC,KAAKO,QAAQ2B,OAEvB,IAAI0B,WAAY5D,KAAK0D,KAAOA,KAAO1D,KAAK0D,KAAO,CAC/C1D,MAAK0D,KAAOA,IAEZ,KAAI,GAAIG,KAAKF,WAAW,CACpB,GAAIG,UAAWH,UAAUE,EACzB,IAAIC,SAAStB,KAAMsB,SAAStB,KAAKkB,KAAME,WAG3CvB,IAAIG,KAAKkB,KAAME,UACfvB,KAAIT,QAAU5B,KAAK4B,OAEnB,KAAI,GAAIiC,KAAKF,WAAW,CACpB,GAAIG,UAAWH,UAAUE,EACzB,IAAIC,SAASC,KAAMD,SAASC,KAAKL,KAAME,WAG3CvB,IAAI0B,KAAKL,KAAME,cAK3BjE,QAAOC,OAAOoE,QAAUvC,GAG5BxC,oBAAoB,EACpBA,qBAAoB,EACpBA,qBAAoB,KAKf,SAAUG,OAAQD,QAASF,qBAEhCA,oBAAoB,IAKf,SAAUG,OAAQD,SAIvBS,OAAO2B,eAAe,WAClB2B,QAAUC,KAAM,QAASC,YAEzBjB,KAAM,WACFnC,KAAKkC,UACLlC,MAAKiE,SACLjE,MAAKkE,UACLlE,MAAK4B,UACL5B,MAAKmE,gBACLnE,MAAKoE,cAAgB,IACrBpE,MAAKqE,kBACXrE,MAAKsE,YACJC,KAAM,EACNC,KAAM,EACNC,MAAO,EACPC,OAAQ,EACRC,UAAY1D,MAAO,MACnB2D,aAAe3D,MAAO,MACtB4D,cACC5D,MAAO,GAAI6D,OAAMC,YAAa,GAAIC,cAAc,GAAK,EAAI,GAAK,GAAI,EAAGF,MAAMG,WAAYH,MAAMI,cAK7F3C,OAAQ,WACJvC,KAAKmF,YAAc,MAGvBC,SAAU,SAAUtB,UACtB9D,KAAKqE,gBAAgBgB,KAAKvB,WAG3BwB,YAAa,SAAUxB,UACtB,GAAIyB,OAAQvF,KAAKqE,gBAAgBmB,QAAQ1B,SACzC9D,MAAKqE,gBAAgBoB,OAAOF,QAG1BpB,eAAgB,WACZnE,KAAK6B,aAAe,GAAIiD,OAAMY,kBAAkB,EAAG,GAAKC,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,YACpIjF,MAAK6B,aAAakE,QAAQC,gBAAkB,KAC5ChG,MAAK6B,aAAaoE,YAAc,IAChCjG,MAAK6B,aAAaqE,aAAe,GAAIpB,OAAMqB,YAC3CnG,MAAK6B,aAAaqE,aAAa/C,KAAO2B,MAAMsB,iBAC5CpG,MAAK6B,aAAaqE,aAAaP,UAAYb,MAAMc,YACjD5F,MAAK6B,aAAawE,cAAgB,KAClCrG,MAAK2B,MAAQ,GAAImD,OAAMwB,KACvBtG,MAAKyC,OAAS,GAAIqC,OAAMyB,oBAAoB,EAAG,EAAG,GAAI,EAAG,EAAG,EAC5DvG,MAAKwG,KAAO,GAAI1B,OAAM2B,KAAK,GAAI3B,OAAM4B,oBAAoB,EAAG,GAAI,KAChE1G,MAAKwG,KAAKG,cAAgB,KAC1B3G,MAAK2B,MAAMiF,IAAI5G,KAAKwG,KACpBxG,MAAK6G,UAAY,GAAI/B,OAAMwB,KAC3BtG,MAAK8G,SAAW,GAAIhC,OAAM2B,KAAK,GAAI3B,OAAM4B,oBAAoB,EAAG,GAAI,KACpE1G,MAAK8G,SAASC,SAASC,WAAWC,GAAGC,MAAMxE,KAAK,EAAG,EAAG,GAAK,EAAG,EAAG,EAAG,GAAK,GACzE1C,MAAK8G,SAASH,cAAgB,KAC9B3G,MAAK6G,UAAUD,IAAI5G,KAAK8G,SACxB9G,MAAKmH,WAAa,GAAIrC,OAAMwB,KAC5BtG,MAAKoH,UAAY,GAAItC,OAAM2B,KAAK,GAAI3B,OAAM4B,oBAAoB,EAAG,GAAI,KACrE1G,MAAKoH,UAAUL,SAASC,WAAWC,GAAGC,MAAMxE,KAAK,GAAK,EAAG,EAAG,EAAG,GAAK,EAAG,EAAG,GAC1E1C,MAAKoH,UAAUT,cAAgB,KAC/B3G,MAAKmH,WAAWP,IAAI5G,KAAKoH,UACzBpH,MAAKqH,SACD,GAAIvC,OAAMY,kBAAkB,EAAG,GAAKC,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,aAChH,GAAIH,OAAMY,kBAAkB,EAAG,GAAKC,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,aAGpHjF,MAAKsH,UAAYnE,KAAM,IAAKlC,MAAO,KACnCjB,MAAKuH,QAAUpE,KAAM,IAAKlC,MAAOjB,KAAK6B,aAAaqE,aACnDlG,MAAKwH,WAAarE,KAAM,IAAKlC,MAAO,EACpCjB,MAAKyH,YAActE,KAAM,IAAKlC,MAAO,EACrCjB,MAAK0D,MAASP,KAAM,IAAKlC,MAAO,EAChCjB,MAAK4D,WAAcT,KAAM,IAAKlC,MAAO,EACrCjB,MAAK0H,SAAYvE,KAAM,KAAMlC,MAAOjB,KAAK2H,OACzC3H,MAAK4H,YAAezE,KAAM,KAAMlC,MAAO,GAAI6D,OAAM+C,UAIrDC,cACI,oBACA,oBACA,gBACA,eACA,+EACA,KACFC,KAAK,MAEPC,OAAQ,GAAIlD,OAAMmD,QAAQ,EAAG,IAC7BC,QAAS,GAAIpD,OAAMmD,QAAQ,GAAK,GAChCN,OAAQ,GAAI7C,OAAMmD,QAAQ,EAAG,GAE7BE,WAAY,iGAEZC,WAAY,SAAUC,SAAUxG,aAAcyG,OAAQC,YAClD,GAAI7G,UAAW1B,KAAKM,QAAQoB,QAC5B1B,MAAKwG,KAAK6B,SAAWA,QACrB,IAAIG,YAAcF,UAAW,UAC7B,IAAIG,GAAI5G,cAAgBH,SAASgH,SACjC1I,MAAK4H,WAAW3G,MAAMyB,IAAI+F,EAAEhE,MAAOgE,EAAE/D,OAAQ,EAAE+D,EAAEhE,MAAO,EAAEgE,EAAE/D,OAC5D,IAAIiE,UAAWjH,SAASkH,SACxBlH,UAASkH,UAAY,KACrB,IAAIN,OAAQ,CACR,GAAItI,KAAK4B,QAAQiH,OAAS,EAAE,CACxB7I,KAAK8G,SAASuB,SAAWA,QACzBrI,MAAK0H,QAAQzG,MAAQjB,KAAKgI,MAC1Bc,SAAQ,EAAG,EAAGC,KAAKC,MAAMP,EAAEhE,MAAQ,IAAMgE,EAAE/D,OAC3C,IAAI8D,KAAMF,OAAOD,SAAUrI,KAAK4B,QAAQ,IAAK,EACtDF,UAAS+B,OAAOzD,KAAK6G,UAAW7G,KAAKyC,OAAQZ,aAAc8G,UAAYJ,WAE9DvI,MAAKoH,UAAUiB,SAAWA,QAC1BrI,MAAK0H,QAAQzG,MAAQjB,KAAKkI,OAC1BY,SAAQC,KAAKC,MAAMP,EAAEhE,MAAQ,IAAM,EAAGsE,KAAKC,MAAMP,EAAEhE,MAAQ,IAAMgE,EAAE/D,OACnE,IAAI8D,KAAMF,OAAOD,SAAUrI,KAAK4B,QAAQ,GAAI,EAC5CF,UAAS+B,OAAQzD,KAAKmH,WAAYnH,KAAKyC,OAAQZ,aAE/C7B,MAAK0H,QAAQzG,MAAQjB,KAAK2H,MAC1BmB,SAAQ,EAAG,EAAGL,EAAEhE,MAAOgE,EAAE/D,YACtB,CACHoE,QAAQ,EAAG,EAAGL,EAAEhE,MAAOgE,EAAE/D,OACzB,IAAI8D,KAAMF,OAAOD,SAAUrI,KAAKM,QAAQmC,OAAQ,EAChDf,UAAS+B,OAAQzD,KAAK2B,MAAO3B,KAAKyC,OAAQZ,aAAc8G,UAAYJ,iBAErE,CACHO,QAAQ,EAAG,EAAGL,EAAEhE,MAAOgE,EAAE/D,OACzBhD,UAAS+B,OAAOzD,KAAK2B,MAAO3B,KAAKyC,OAAQZ,aAAc8G,UAAYJ,YAEvE7G,SAASkH,UAAYD,QACrB,SAASG,SAAQG,EAAEC,EAAEC,EAAEC,GACnB,GAAIvH,aAAc,CACdA,aAAawH,SAAS3G,IAAKuG,EAAGC,EAAGC,EAAGC,EAChDvH,cAAayH,QAAQ5G,IAAKuG,EAAGC,EAAGC,EAAGC,OACpB,CACH1H,SAAS6H,YAAaN,EAAGC,EAAGC,EAAGC,EAC3C1H,UAAS8H,WAAYP,EAAGC,EAAGC,EAAGC,MAK9BK,YAAa,SAAUjK,GACnB,GAAIkK,KACA,wBACA,iDACA,6EACA,KACAlK,EAAEmK,gBACJ5B,KAAK,KAEPvI,GAAEoK,SAASlC,QAAU1H,KAAK0H,OAE1B,OAAO,IAAI5C,OAAM+E,gBACbD,SAAUpK,EAAEoK,SACZ9B,aAActI,EAAEsI,cAAgB9H,KAAK8H,aACrC6B,eAAgBD,GAChBI,WAAY,MACZC,UAAW,MACXC,SAAUlF,MAAMmF,WAChBC,IAAK,MACLC,YACIC,YAAa,MAEjBC,QAAS7K,EAAE6K,eAInBC,KAAM,SAAUC,KAAMC,OAClB,IAAKD,KAAK1B,OAAQ,MAClB,IAAI9I,MAAOC,KAAMyK,MAAM,CACvB,IAAIC,WAAaC,QAAWC,QAAWC,YACnCC,WAAa,MAAOC,aAAe,MAAOC,CAE9C,IAAIpB,WACAlG,KAAM1D,KAAK0D,KACXE,UAAW5D,KAAK4D,UAChBgE,WAAY5H,KAAK4H,WAGrB2C,MAAKxJ,QAAQ,SAAUkC,KACnB,GAAIgI,UAAW,KAAMC,SAAW,MAAOC,OACvC,UAAWlI,OAAQ,SAAU,CACzB,GAAImI,KAAMrL,KAAKoI,WAAWkD,KAAKpI,IAC/B,KAAImI,IAAK,MAETH,UAAWG,IAAI,KAAO,GACtBF,UAAWE,IAAI,KAAO,GACtBnI,KAAMmI,IAAI,EACV,IAAIE,MAAOF,IAAI,EACf,IAAIb,QAEJ,IAAGtH,IAAI,KAAO,IAAK,CACf,GAAInD,IAAKyL,SAASC,cAAcvI,IAChC,KAAInD,GAAI,MAERmD,MACIhD,UAAWgD,IAAIwI,QAAQ,IAAK,WAAY,IAAMhB,QAAU,KAAK1C,KAAK,IAClE2D,SAAUJ,KACLxL,GAAGwL,eAAiBK,UAAW7L,GAAGwL,MAAMM,KAAKC,YAAc/L,GAAGwL,MAC7DxL,GAAG+L,YACTC,MAAOhM,GAAGiM,QAAQD,QAAUxI,UAC5B0I,QAASlM,GAAGiM,QAAQC,UAAY1I,UAChCuH,SAAU/K,GAAGiM,QAAQlB,SAAW/K,GAAGiM,QAAQlB,SAASoB,OAAOlJ,MAAM,KAAO,KACxEmJ,SAAUpM,GAAGiM,QAAQG,SAAWpM,GAAGiM,QAAQG,SAASD,OAAOlJ,MAAM,KAAO,UAEzE,CACHE,IAAMlD,KAAKmC,QAAQe,IACnB,KAAKA,IAAK,MACV,IAAIqI,KAAM,CACNrI,IAAMA,IAAI9D,QAAU8D,IAAI9D,QAAQmM,MAAQ,IACxC,KAAKrI,IAAK,MACVA,KAAIhD,SAAWmL,IAAI,GAAK,IAAME,KAAO,KAG7C,GAAIF,IAAI,GAAI,CACRD,KAAOC,IAAI,GAAGa,OAAOlJ,MAAM,MAGnC,GAAIoJ,SAAUlJ,IAAIhD,SAAWgD,IAAIhD,SAAW,aAAgBwK,SAAY,GACxE0B,QAASA,OAAOV,QAAQ,KAAK,IAC7B,IAAIxI,IAAIiJ,SAAU,CACdjJ,IAAIiJ,SAASnL,QAAQ,SAAUqL,EAAG/I,GAC9B,GAAIT,GAAIuI,KAAK9H,EACbqH,QAAOrF,MAAM,YAAahC,EAAG,IAAKT,GAAMA,IAAM,IAAMA,EAAIwJ,GAAIrE,KAAK,IAAI0D,QAAQ,MAAOU,QAAQV,QAAQ,KAAK,QAGjH,GAAIxI,IAAI+I,QAAS,CAAEjB,aAAe,KAClC,GAAI9H,IAAI6I,MAAO,CAAEhB,WAAa,KAC9B,GAAI7H,IAAIyI,SAAU,CAAEhB,OAAOrF,KAAKpC,IAAIyI,SAASD,QAAQ,MAAOU,SAC5D,GAAIlJ,IAAI2G,SAAU,CACd,IAAK,GAAIyC,KAAKpJ,KAAI2G,SAAU,CACxBA,SAASuC,OAASE,GAAKpJ,IAAI2G,SAASyC,IAG5C,GAAIpJ,IAAI4H,SAAU,CACd5H,IAAI4H,SAAS9J,QAAQ,SAAUuL,KAC3BzB,SAASyB,KAAO,OAGxB,GAAIrB,SAAU,CACVL,KAAKvF,MAAM,KAAM8G,OAAQ,QAAWjB,SAAW,mBAAoB,mBAAqB,kBAAkBnD,KAAK,OAGvH,IAAIwE,MAAQlJ,EAAK,MAAOmJ,EAAK,QAASC,EAAK,YACvCC,GAAM,OAAQC,GAAM,OAAQlN,EAAK,OAAOmN,GAAM,OAC9CC,GAAM,OAAQC,GAAK,OAAQC,GAAM,OAAQlJ,EAAK,OAElD,KAAImH,IAAKH,UAAU,CAAEF,KAAKtF,KAAK,aAAe2F,EAAI,KAElD,GAAIgC,UACA,iBAEJpD,UAAS,YAAc5J,KAAKsH,QAE5B,IAAIyD,aAAa,CACZiC,QAAQ3H,KAAK,gDACX,CACF2H,QAAQ3H,KAAK,6BAElB2H,QAAQ3H,KAAK,4BAEbuE,UAAS,UAAY5J,KAAKuH,MAC1BqC,UAAS,aAAe5J,KAAKwH,SAC7BoC,UAAS,cAAgB5J,KAAKyH,UAE9B,IAAIqD,WAAW,CACXkC,QAAQ3H,KAAK,iDACV,CACH2H,QAAQ3H,KAAK,wBAGjB,IAAI2F,IAAKpB,UAAU,CACf,GAAIyC,GAAIzC,SAASoB,EACjBL,MAAKtF,MAAM,UAAWkH,IAAIF,EAAElJ,MAAO6H,EAAG,KAAKjD,KAAK,MAGpD4C,KAAKtF,KAAK,oBACV,IAAI4H,SACAtC,KAAK5C,KAAK,MAAO2C,OAAO3C,KAAK,MAAO,KAChCiF,QAAQjF,KAAK,MAAO6C,KAAK7C,KAAK,MAC9ByC,MAAQ,0BAA4B,yCAA0C,KACpFzC,KAAK,KAEP,IAAIM,UAAWrI,KAAKyJ,aAChBE,eAAgBsD,OAChBrD,SAAUA,UAGd,IAAG5J,KAAKM,QAAQH,WAAW+M,MAAOC,QAAQC,IAAIH,OAAQ5E,SACtD,OAAOA,WAGXgF,QAAS,WACL,GAAItN,MAAOC,KAAMiE,UAAasG,OAC9BvK,MAAKiE,OAAOlD,QAAQ,SAASuM,MACzB,GAAIA,KAAKC,QAASD,KAAKC,WAE3BvN,MAAKI,KAAKW,QAAQ,SAAUiK,GACxB,IAAIA,EAAE,CACFwC,QACA,QAEJ,GAAIvK,KAAK/C,IACT,IAAIkL,KAAMrL,KAAKoI,WAAWkD,KAAKL,EAC/B,KAAII,MAAQA,IAAI,GAAI,MACpBlL,MAAOkL,IAAI,EACXnI,KAAMlD,KAAKmC,QAAQhC,KACnB,KAAK+C,IAAI,CACLsH,KAAKlF,KAAK2F,EACV,QAEJ,GAAI/H,IAAIqK,KAAM,CACVE,QACAvJ,QAAOoB,MAAOiI,KAAMrK,IAAIqK,KAAMxJ,SAAUb,UACrC,IAAIA,IAAIoF,SAAS,CACpBmF,QACAvJ,QAAOoB,MAAOiI,KAAMG,SAASxK,IAAIoF,SAAU,MAAOpF,IAAIyK,IAAK5J,SAAUb,UAClE,CACHsH,KAAKlF,KAAK2F,KAIlB,SAASwC,UACL,IAAKjD,KAAK1B,OAAQ,MAClB5E,QAAOoB,MAAOiI,KAAMG,SAAS1N,KAAKuK,KAAKC,MAAO,OAC9CA,SAGJ,QAASkD,UAAUpF,SAAUkF,QAASjF,QAClC,OACI7E,OAAQ,SAAS/B,SAAUiM,YAAaC,YACpC7N,KAAKqI,WAAWC,SAAUsF,YAAarF,SAG3CiF,QAAS,WACL,GAAIA,QAASlF,SAASkF,YAIlCC,QACAxN,MAAKmF,YAAc,KACnBnF,MAAKiE,OAASA,QAGlB4J,SAAU,SAAU/J,SAAUgK,QAC1B,GAAInM,OAAQ3B,KAAKM,OACjB,IAAIwD,SAASiK,OAAQ,MAAO,MAC5B,IAAIC,WAAYrM,MAAME,aAAe,KAAO,KAC5C,KAAKmM,UAAW,MAAO,MACvB,IAAIF,SAAW9N,KAAKiO,aAAenK,SAASmK,cAAgBnK,SAASoK,QAAS,CAC1E,GAAIC,MAAOxM,MAAMD,SAASgH,SAC1B5E,UAASoK,QAAQC,KAAK1J,MAAO0J,KAAKzJ,cAC3BZ,UAASmK,YAEpB,MAAO,OAGXG,SAAU,SAAUtK,UAChB9D,KAAKkC,QAAQ4B,SAAS7D,UAAY6D,QAClC9D,MAAKmF,YAAc,MAGvBkJ,WAAY,SAAUvK,gBACX9D,MAAKkC,QAAQ4B,SAAS7D,SAC7BD,MAAKmF,YAAc,MAGvB3C,KAAM,SAAUkB,KAAME,WAClB,GAAI7D,MAAOC,KAAMM,QAAUN,KAAKM,QAASoB,SAAWpB,QAAQoB,SAAU4M,OAAShO,QAAQgO,OACnFC,GAAKvO,KAAK6B,aAAc2M,IAAMxO,KAAKqH,QAAS1F,MAAQrB,QAAQwB,QAChE,KAAIyM,KAAO7M,SAAU,CAAE,OACvB,GAAI1B,KAAKoE,cAAe,CACpB,GAAGzC,MAAM8M,eAAgB,CACrB9M,MAAM8M,eAAiB,SAAU/M,SAAUC,MAAOc,QAC9C,GAAI0L,MAAOzM,SAASgH,SACpB,IAAIyF,KAAK1J,QAAU8J,GAAG9J,OAAS0J,KAAKzJ,SAAW6J,GAAG7J,OAAQ,CACtD6J,GAAGL,QAAQC,KAAK1J,MAAO0J,KAAKzJ,OAC5B8J,KAAI,GAAGN,QAAQC,KAAK1J,MAAO0J,KAAKzJ,OAChC8J,KAAI,GAAGN,QAAQC,KAAK1J,MAAO0J,KAAKzJ,OAChC3E,MAAK6H,WAAW3G,MAAMyB,IAAIyL,KAAK1J,MAAO0J,KAAKzJ,OAAQ,EAAEyJ,KAAK1J,MAAO,EAAE0J,KAAKzJ,OACxE3E,MAAKkO,YAAc,IACnBlO,MAAK2O,cAET,GAAGjM,iBAAkBqC,OAAM6J,YAAa,CACpC5O,KAAK6B,QAAUa,OAAOb,YACnB,CACH7B,KAAK6B,QAAQyD,KAAK5C,QAEtB1C,KAAK6O,WAAWlN,SAAUC,MAAOc,aAElC,CACH,GAAIoM,gBAAiBnN,SAAS+B,MAC9B/B,UAAS+B,OAAS,SAAU9B,MAAOc,OAAQZ,aAAc0G,YACrD,GAAI1G,eAAiB0M,GAAI,CACrB,GAAIJ,MAAOzM,SAASgH,SACpB,IAAIyF,KAAK1J,QAAU8J,GAAG9J,OAAS0J,KAAKzJ,SAAW6J,GAAG7J,OAAQ,CACtD6J,GAAGL,QAAQC,KAAK1J,MAAO0J,KAAKzJ,OAC5B8J,KAAI,GAAGN,QAAQC,KAAK1J,MAAO0J,KAAKzJ,OAChC8J,KAAI,GAAGN,QAAQC,KAAK1J,MAAO0J,KAAKzJ,OAChC3E,MAAK6H,WAAW3G,MAAMyB,IAAIyL,KAAK1J,MAAO0J,KAAKzJ,OAAQ,EAAEyJ,KAAK1J,MAAO,EAAE0J,KAAKzJ,OACxE3E,MAAKkO,YAAc,KAEvBlO,KAAK6B,QAAQyD,KAAK5C,QAEtBoM,eAAetP,KAAKmC,SAAUC,MAAOc,OAAQZ,aAAc0G,aAGnEvI,KAAKoE,cAAgB,MAEzBpE,KAAK4B,UACL5B,MAAK0D,KAAKzC,MAAQyC,KAAO,GACzB1D,MAAK4D,UAAU3C,MAAQ2C,UAAY,GAEnC,IAAI5D,KAAKmF,cAAgB,KAAM,CAAEnF,KAAKqN,UAEvCrN,KAAK8O,aAEJ9O,MAAKsH,SAASrG,MAAQjB,KAAK6B,aAAakE,OACxC/F,MAAKuH,OAAOtG,MAAQjB,KAAK6B,aAAaqE,YACtC,IAAIzD,QAASzC,KAAKM,QAAQmC,MAC1BzC,MAAKwH,UAAUvG,MAAQwB,OAAOsM,GAC9B/O,MAAKyH,WAAWxG,MAAQwB,OAAOuM,MAGnCF,YAAc,WACV,GAAIhM,QAAUyL,GAAKvO,KAAK6B,YACxB7B,MAAKiE,OAAOlD,QAAQ,SAAUrB,GAC1B,GAAIA,EAAEoE,UAAYpE,EAAEoE,SAASiK,SAAW,KAAM,MAC9CjL,KAAIuC,KAAK3F,IAEbM,MAAKM,QAAQuB,aAAeiB,IAAI+F,QAAU7I,KAAKM,QAAQ2B,UAAYsM,GAAK,IACxEvO,MAAKkE,QAAUpB,KAEnBiB,KAAM,WACF,GAAIpC,OAAQ3B,KAAKM,QAASoB,SAAWC,MAAMD,SAAU3B,KAAOC,IAC5D,KAAI2B,MAAME,aAAc,CAAE,OAC1B,GAAI0M,IAAK5M,MAAME,aAAc2M,IAAMxO,KAAKqH,OACxCrH,MAAKkE,QAAQnD,QAAQ,SAAUuM,KAAMjK,GACjC,GAAI4L,GAAI5L,EAAImL,IAAInL,EAAI,GAAKkL,EACzBxO,MAAKuH,SAASrG,MAAQgO,EAAElJ,OACxB,IAAIuH,KAAKxJ,UAAYwJ,KAAKxJ,SAASgK,OAAQ/N,KAAK8N,SAASP,KAAKxJ,SAAU,KACxEwJ,MAAKA,KAAK7J,OAAO/B,SAAU2B,EAAItD,KAAKmE,QAAQ2E,OAAS,EAAI2F,IAAKnL,EAAE,EAAK,GAAK,KAAM4L,IAEpFjP,MAAKiO,YAAc,OAGvBS,YAAa,WACT,GAAIpK,YAAatE,KAAKsE,UACtB,IAAIG,OAAQH,WAAWG,KACvB,IAAIC,QAASJ,WAAWI,MACxBJ,YAAWE,KAAOuE,KAAKmG,KAAMzK,MAAQ,GACrCH,YAAWC,KAAOwE,KAAKmG,KAAM5K,WAAWI,OAAS,GACjDJ,YAAWK,SAAS1D,OAAUwD,MAAOC,OAAQ,GAAMqE,KAAKmG,KAAMzK,MAAQ,IAAM,GAAMsE,KAAKmG,KAAMxK,OAAS,IACtGJ,YAAWM,YAAY3D,MAAQ,GAAI6D,OAAMC,YAAa,GAAIoK,YAAY7K,WAAWE,KAAOF,WAAWC,KAAO,GAAKD,WAAWE,KAAMF,WAAWC,OAG/IqK,WAAY,SAAWlN,SAAUC,MAAOc,QACpC,IAAOA,OAAO2M,iBAAmB,MACjC,IAAI9K,YAAatE,KAAKsE,WAAY+K,OAASrP,KAAKqE,eAChD,IAAI8J,MAAOzM,SAASgH,SACpB,IAAI0D,GAAI9H,WAAWM,YAAY3D,MAAMqO,MAAMlP,IAC3C,IAAImP,IAAKjL,WAAWO,aAAa5D,MAAMqO,MAAMlP,IAC7C,IAAIoP,YAAa/M,OAAOgN,kBACxBrD,GAAEsD,KAAM,EACR,IAAIC,QAAS,GAAI7K,OAAM8K,OAEvB,IAAI3L,OACJ,IAAGxB,iBAAkBqC,OAAM6J,YAAa,CACpC1K,SAAY,GAAK,EAAGxB,OAAOb,QAAQ,KAAM,GAAK,GAAKa,OAAOb,QAAQ,SAC/D,CACHqC,QAAU,EAAK,EAAGxB,QAEtBwB,OAAOlD,QAAQ,SAASuM,MACpB+B,OAAOtO,QAAS,SAAW8O,MAAOtK,OAC9BoK,OAAOG,sBAAuBD,MAAM/P,GAAGgC,SAASiO,YAChD,IAAIC,IAAK1L,WAAWG,MAAQ6I,KAAK,EACjC,IAAI2C,IAAK3L,WAAWG,MAAQ6I,KAAK,EACjC,IAAI4C,IAAKnQ,KAAKoQ,YAAa7C,KAAK,GAAIqC,OAAQE,MAAMzP,KAAKgQ,OAAQJ,GAC/DL,QAAOU,aAAcb,WACrBG,QAAOW,QAASf,GAAI,EAAIhK,MACxBgK,IAAI,EAAIhK,MAAQ,GAAMsK,MAAMzP,KAAKgQ,MACjCP,OAAMzP,KAAKmQ,MAAMD,QAASf,GAAI,GAAK,EAAI,EAAIhK,MAC3CgK,IAAI,GAAK,EAAI,EAAIhK,MAAQ,GAAMsK,MAAMzP,KAAKoQ,KAC1C,IAAKN,GAAI,GAAM,GAAKA,GAAI,GAAMF,IAAME,GAAI,GAAM,GAAKA,GAAI,GAAM5L,WAAWI,OAAS,MACjF,IAAKwL,GAAI,GAAM,EAAIA,GAAI,GAAM,CAC7B,IAAKA,GAAI,GAAMF,GAAKE,GAAI,GAAMF,EAC9B,IAAKE,GAAI,GAAM,EAAIA,GAAI,GAAM,CAC7B,IAAKA,GAAI,GAAM5L,WAAWI,OAASwL,GAAI,GAAM5L,WAAWI,MACxD,IAAI+L,IAAK1H,KAAK2H,MAAOnL,MAAQ,GAAKoL,GAAK,EAAMpL,MAAQ,CACrD,KAAM,GAAIlC,GAAI0F,KAAK2H,MAAOR,GAAI,GAAM,IAAM7M,GAAK0F,KAAKmG,KAAMgB,GAAI,GAAM,IAAM7M,IAAO,CAC7E,IAAM,GAAIuN,GAAI7H,KAAK2H,OAAQR,GAAI,GAAMD,IAAM,IAAOW,GAAK7H,KAAKmG,MAAOgB,GAAI,GAAMD,IAAM,IAAMW,IAAO,CAC5FxE,GAAK9H,WAAWE,KAAOnB,EAAIuN,GAAM,EAAIH,KAAQ,GAAKE,QAKlErM,YAAWM,YAAY3D,MAAMkE,YAAc,IAC3Cb,YAAWO,aAAa5D,MAAMkE,YAAc,MAGhDgL,YAAa,WACTvN,EAAI,GAAIkC,OAAM8K,OACd,OAAO,UAAWnN,OAAQoO,IAAK5B,EAAG9F,GAC9B,GAAI7E,YAAatE,KAAKsE,UACtB,IAAIwM,MAAO3H,EAAG4H,KAAO,EAAGC,KAAO1M,WAAWI,OAAQuM,KAAO,EAAGC,GAAK/H,EAAI,EAAGgI,GAAK7M,WAAWI,OAAS,CACjG,KAAM,GAAIrB,GAAI,EAAGA,EAAI,EAAGA,IAAO,CAC3BT,EAAEwO,KAAMP,IACRjO,GAAEqG,GAAK5F,EAAI,EAAI4L,GAAMA,CACrBrM,GAAEsG,GAAK7F,EAAI,EAAI4L,GAAMA,CACrBrM,GAAEyO,GAAKhO,EAAI,EAAI4L,GAAMA,CACrB,IAAIU,QAAS/M,EAAE0O,QAAS7O,OACxB,IAAIwG,GAAM0G,OAAO1G,EAAIiI,GAAOA,EAC5B,IAAIhI,GAAMyG,OAAOzG,EAAIiI,GAAOA,EAC5BL,MAAO/H,KAAKwI,IAAKT,KAAM7H,EACvB8H,MAAOhI,KAAKyI,IAAKT,KAAM9H,EACvB+H,MAAOjI,KAAKwI,IAAKP,KAAM9H,EACvB+H,MAAOlI,KAAKyI,IAAKP,KAAM/H,GAE3B,OAAS4H,KAAMC,KAAMC,KAAMC,aAQlC,SAAU7R,OAAQD,QAASF,qBAEhCA,oBAAoB,EACpBA,qBAAoB,EACpBA,qBAAoB,EACpBA,qBAAoB,EACpBA,qBAAoB,GACpBA,qBAAoB,GACpBA,qBAAoB,GACpBA,qBAAoB,GACpBA,qBAAoB,KAKf,SAAUG,OAAQD,SAIvBS,OAAOa,kBAAkB,WACxBgR,SAAU,KAEPvO,QACFwO,SAAWtO,QAAS,MACdmN,OAASpN,KAAM,QAASC,QAAS,WACvCqB,OAAStB,KAAM,OAAQC,QAAS,GAAI0B,OAAMmD,QAAQ,EAAE,IACpD0J,OAASxO,KAAM,OAAQC,QAAS,GAAI0B,OAAMmD,QAAQ,EAAE,OACpD2J,UAAWzO,KAAM,SAAUC,QAAS,GACpCyO,OAAS1O,KAAM,SAAUC,QAAS,IAClC0O,QAAU1O,QAAS,QAGjBjB,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OAC5C,IAAI8P,OAASrM,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,WACnFjF,MAAK6B,aAAe,GAAIiD,OAAMY,kBAAmB,EAAG,EAAGsM,KAC7DhS,MAAKiS,WAAa,GAAInN,OAAMY,kBAAmB,EAAG,EAAGsM,KACrDhS,MAAKiO,YAAc,IACnBjO,MAAK4H,YAAezE,KAAM,KAAMlC,MAAO,GAAI6D,OAAM+C,QACjD7H,MAAKkS,cACJtK,WAAY5H,KAAK4H,WACR2I,OAASpN,KAAM,IAAKlC,MAAO,GAAI6D,OAAMqN,OAC9C1N,OAAStB,KAAM,KAAMlC,MAAO,MAC5B0Q,OAASxO,KAAM,KAAMlC,MAAO,MAC5B2Q,UAAYzO,KAAM,IAAKlC,MAAO,GAG/BjB,MAAKoS,eAAkBjP,KAAM,KAAMlC,MAAO,GAAI6D,OAAMmD,QAEpDjI,MAAKb,SACJkT,OACC3G,SAAU1L,KAAKqS,MACfzI,SAAU5J,KAAKkS,aACfrH,UAAW,WACXiB,MAAO,MAGRwG,MACC5G,SAAU1L,KAAKsS,KACf1I,UAAYhC,WAAY5H,KAAKkS,aAAatK,WAAY2K,UAAWvS,KAAKoS,eACtEpG,QAAS,MAGXhM,MAAKwS,gBAAkBxS,KAAK+R,OAAOzH,MAAMtK,KAAKb,QAAQkT,OAAQ,KAG9DrS,MAAKyS,aAAezS,KAAK+R,OAAOzH,MAAMtK,KAAKb,QAAQmT,MAAO,KAE1DtS,MAAK4J,UACJ7D,SAAW5C,KAAM,IAAKlC,MAAOjB,KAAK6B,aAAakE,SAGhD/F,MAAK+R,OAAO3D,SAASpO,OAGnBuC,OAAQ,SAAUD,SACpBtC,KAAK+N,QAAU/N,KAAKI,KAAKsR,OACnB1R,MAAKkS,aAAa3B,MAAMtP,MAAMyB,IAAI1C,KAAKI,KAAKmQ,MAClDvQ,MAAKkS,aAAazN,MAAMxD,MAAQjB,KAAKI,KAAKqE,KAC1CzE,MAAKkS,aAAaP,MAAM1Q,MAAQjB,KAAKI,KAAKuR,KAC1C3R,MAAKkS,aAAaN,SAAS3Q,MAAQ,EAAIjB,KAAKI,KAAKwR,UAGlD1D,QAAS,SAAS/E,EAAGC,GACpBD,EAAIJ,KAAKC,MAAMG,EAAInJ,KAAKI,KAAKyR,MAC7BzI,GAAIL,KAAKC,MAAMI,EAAIpJ,KAAKI,KAAKyR,MAC7B7R,MAAK6B,aAAaqM,QAAQ/E,EAAEC,EAC5BpJ,MAAKiS,WAAW/D,QAAQ/E,EAAEC,EAC1BpJ,MAAK4H,WAAW3G,MAAMyB,IAAIyG,EAAGC,EAAG,EAAED,EAAG,EAAEC,IAGxCrF,KAAM,WACL,IAAK/D,KAAK+R,OAAOlE,SAAS7N,KAAM,MAAO,MACvCA,MAAK+R,OAAO3J,WAAWpI,KAAKwS,gBAAiBxS,KAAK6B,aAClD7B,MAAK+R,OAAOzK,SAASrG,MAAQjB,KAAK6B,YAClC,KAAK7B,KAAKI,KAAK0R,OAAQ,MACvB9R,MAAKoS,cAAcnR,MAAMyB,IAAI,EAAE,EAC/B1C,MAAK+R,OAAO3J,WAAWpI,KAAKyS,aAAczS,KAAKiS,WAC/CjS,MAAK+R,OAAOzK,SAASrG,MAAQjB,KAAKiS,UAClCjS,MAAKoS,cAAcnR,MAAMyB,IAAI,EAAE,EAC/B1C,MAAK+R,OAAO3J,WAAWpI,KAAKyS,aAAczS,KAAK6B,eAG7CgB,OAAQ,WACJ7C,KAAK+R,OAAO1D,WAAWrO,OAG3BgM,QAAS,KAETqG,OACF,cAEA,2EACA,2EAGA,uEAEC,aACA,gBACA,WAEA,eACA,eAEA,gCACA,kCACD,+EACM,qEACN,gFACC,IAEA,4BACC,+EACA,uBACD,IACA,2DACD,MACCtK,KAAK,MAEPuK,MACC,sEACA,sBACA,mFACA,mFACA,KACCvK,KAAK,MAEP2D,UACO,sEACA,0CACN,yEACM,KACF3D,KAAK,SAKN,SAAU3I,OAAQD,SAIvBS,OAAOa,kBAAkB,QACrBgR,SAAU,KAEVvO,QACIwP,OAAiBtP,QAAS,GAC1BuP,YAAgBvP,QAAS,IACzBwP,YAAgBxP,QAAS,KACzByP,QAAgBzP,QAAS,OAG7BjB,KAAM,WACFnC,KAAK4J,UACD8I,OAAiBvP,KAAM,IAAKlC,MAAO,GACnC0R,YAAgBxP,KAAM,IAAKlC,MAAO,IAClC2R,YAAgBzP,KAAM,IAAKlC,MAAO,KAClC4R,QAAgB1P,KAAM,IAAKlC,MAAO,MAEtCjB,MAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OACtClC,MAAK+R,OAAO3D,SAASpO,OAGzBuC,OAAQ,WACJ,GAAI6J,GAAIpM,KAAKI,KAAM0S,GAAM9S,KAAK4J,QAC9B,KAAI,GAAIyC,KAAKyG,IAAI,CACb,GAAG1G,EAAEC,GAAIyG,GAAGzG,GAAGpL,MAAQmL,EAAEC,KAIjCxJ,OAAQ,WACJ7C,KAAK+R,OAAO1D,WAAWrO,OAG3B6K,UAAW,UAEXmB,QAAS,KAETN,UACF,uEACA,kCACA,uDACA,2FACA,qEACA,6EACM,sGACN,sCACA,KACC3D,KAAM,SAKJ,SAAU3I,OAAQD,QAASF,qBAIhC,GAAI8T,YAAa9T,oBAAoB,EAErCW,QAAOa,kBAAkB,QACrByC,QAAUE,QAAS,MAEnBjB,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OACtClC,MAAKqI,SAAW,GAAIvD,OAAM+E,gBACtBF,eAAgBoJ,WAAWpJ,eAC3B7B,aAAciL,WAAWjL,aACzB8B,UACItC,SAAUtH,KAAK+R,OAAOzK,SACtBM,YAAczE,KAAM,KAAMlC,MAAO,GAAI6D,OAAMmD,WAGnDjI,MAAK+R,OAAO3D,SAASpO,KACrBA,MAAKiO,YAAc,MAGvB1L,OAAQ,WACJvC,KAAK+N,QAAU/N,KAAKI,MAGxB8N,QAAS,SAAU/E,EAAGC,GAClBpJ,KAAKqI,SAASuB,SAAShC,WAAW3G,MAAMyB,IAAIyG,EAAGC,IAGnD0E,OAAQ,KAERjL,OAAQ,WACJ7C,KAAKqI,SAASkF,SACdvN,MAAK+R,OAAO1D,WAAWrO,UAM1B,SAAUZ,OAAQD,SAIvBC,OAAOD,SACLyK,UACEtC,UAAYnE,KAAM,IAAKlC,MAAO,MAC9B2G,YAAczE,KAAM,KAAMlC,MAAO,GAAI6D,OAAMmD,UAE7CH,aAAc,2pBACd6B,eAAgB,w/IAOb,SAAUvK,OAAQD,QAASF,qBAGhC,GAAI+T,0BAA2B/T,oBAAoB,EAEnD,IAAIgU,gBAAiB,GAAInO,OAAMmD,QAAS,EAAK,EAC7C,IAAIiL,gBAAiB,GAAIpO,OAAMmD,QAAS,EAAK,EAE7CrI,QAAOa,kBAAkB,SACxBgR,SAAU,KAEPvO,QACFiQ,QAAU/P,QAAS,MACbwO,UAAYxO,QAAS,GACrBgN,QAAUhN,QAAS,IACnBgQ,WAAahQ,QAAS,IAC5BiQ,QAAUlQ,KAAM,QAASC,aAGvBjB,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OACtC,IAAI8P,OAASrM,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,WACzFjF,MAAKsT,0BACLtT,MAAKuT,wBACLvT,MAAKwT,MAAQ,CAEbxT,MAAKyT,mBAAqB,GAAI3O,OAAMY,kBAAmB,EAAG,EAAGsM,KAC7DhS,MAAKyT,mBAAmB1N,QAAQ7F,KAAO,wBACvCF,MAAKyT,mBAAmB1N,QAAQC,gBAAkB,KAElD,KAAK,GAAI3C,GAAE,EAAGA,EAAErD,KAAKwT,MAAOnQ,IAAK,CAE7B,GAAIxB,cAAe,GAAIiD,OAAMY,kBAAmB,EAAG,EAAGsM,KAEtDnQ,cAAakE,QAAQ7F,KAAO,oBAAsBmD,CAClDxB,cAAakE,QAAQC,gBAAkB,KAEvChG,MAAKsT,wBAAwBjO,KAAKxD,aAElC,IAAIA,cAAe,GAAIiD,OAAMY,kBAAmB,EAAG,EAAGsM,KAEtDnQ,cAAakE,QAAQ7F,KAAO,oBAAsBmD,CAClDxB,cAAakE,QAAQC,gBAAkB,KAEvChG,MAAKuT,sBAAsBlO,KAAKxD,cAM1C7B,KAAKb,SACJkU,QACCzJ,UACC8J,qBAAyBvQ,KAAM,IAAKlC,MAAO,GAC3C0S,aAAiBxQ,KAAM,IAAKlC,MAAO,KACnC2S,cAAkBzQ,KAAM,IAAKlC,MAAO,GAAI6D,OAAMqN,MAAO,IACrD0B,gBAAqB1Q,KAAM,IAAKlC,MAAO,IAExC+K,QAAS,KACTN,UACC,uEACC,sBACA,2DACA,iEACA,4FACA,4CACD,KACC3D,KAAK,OAIH/H,MAAK8T,uBAAyB,IAE9B9T,MAAK+T,yBACL,IAAIC,kBAAmB,EAAG,EAAG,EAAG,EAAG,GAEnC,KAAK,GAAI3Q,GAAE,EAAGA,EAAErD,KAAKwT,MAAOnQ,IAAK,CAE7BrD,KAAK+T,uBAAuB1O,KAAKrF,KAAKiU,yBAAyBD,gBAAgB3Q,IAE/ErD,MAAK+T,uBAAuB1Q,GAAGuG,SAAU,WAAY3I,MAAQ,GAAI6D,OAAMmD,QAAQ,EAAG,GAKtFjI,KAAKkU,kBAAoBlU,KAAKmU,qBAAqBnU,KAAKwT,MACxDxT,MAAKkU,kBAAkBtK,SAAS,gBAAgB3I,MAAQjB,KAAKuT,sBAAsB,GAAGxN,OACtF/F,MAAKkU,kBAAkBtK,SAAS,gBAAgB3I,MAAQjB,KAAKuT,sBAAsB,GAAGxN,OACtF/F,MAAKkU,kBAAkBtK,SAAS,gBAAgB3I,MAAQjB,KAAKuT,sBAAsB,GAAGxN,OACtF/F,MAAKkU,kBAAkBtK,SAAS,gBAAgB3I,MAAQjB,KAAKuT,sBAAsB,GAAGxN,OACtF/F,MAAKkU,kBAAkBtK,SAAS,gBAAgB3I,MAAQjB,KAAKuT,sBAAsB,GAAGxN,OACtF/F,MAAKkU,kBAAkB/O,YAAc,IAErC,IAAIiP,eAAgB,EAAK,GAAK,GAAK,GAAK,GACxCpU,MAAKkU,kBAAkBtK,SAAS,gBAAgB3I,MAAQmT,YACxDpU,MAAKqU,iBAAmB,GAAIvP,OAAM8K,QAAQ,EAAE,EAAE,GAAI,GAAI9K,OAAM8K,QAAQ,EAAE,EAAE,GAAI,GAAI9K,OAAM8K,QAAQ,EAAE,EAAE,GACrD,GAAI9K,OAAM8K,QAAQ,EAAE,EAAE,GAAI,GAAI9K,OAAM8K,QAAQ,EAAE,EAAE,GAC7F5P,MAAKkU,kBAAkBtK,SAAS,mBAAmB3I,MAAQjB,KAAKqU,eACtErU,MAAKsU,cAAgB,GAAIxP,OAAMqN,KACzBnS,MAAK4J,UACD7D,SAAa5C,KAAM,IAAKlC,MAAOjB,KAAKsT,wBAAwB,IAEhEtT,MAAKiO,YAAc,IACnBjO,MAAK+R,OAAO3D,SAASpO,OAG5BuC,OAAQ,SAAUD,SACjB,GAAIA,QAAQ+Q,SAAWrT,KAAKI,KAAKiT,OAAQ,CACxC,GAAIrT,KAAK8T,uBAAwB9T,KAAK8T,uBAAuBvG,SAC7D,IAAInL,OAAQpC,KAAKI,KAAKiT,OAAOxK,OAAS7I,KAAKI,KAAKiT,QAAUrT,KAAKb,QAAQkU,OACvErT,MAAK8T,uBAAyB9T,KAAK+R,OAAOzH,KAAKlI,MAAO,SAIrD2B,KAAM,SAAUL,MACZ,IAAK1D,KAAKI,KAAK+S,SAAWnT,KAAK+R,OAAOlE,SAAS7N,KAAM,MAAO,MAClE,IAAI2B,OAAQ3B,KAAKF,GAAGQ,OACpB,IAAIoB,UAAWC,MAAMD,QACf,IAAIkM,YAAajM,MAAME,YACvB7B,MAAKsU,cAAclD,KAAM1P,SAAS6S,gBACxCvU,MAAKwU,cAAgB9S,SAAS+S,eAC9B,IAAIC,cAAehT,SAASkH,SAC5BlH,UAASkH,UAAY,KAErBlH,UAASiT,cAAe,GAAI7P,OAAMqN,MAAO,EAAG,EAAG,GAAK,EAGpDnS,MAAK+R,OAAOzK,SAASrG,MAAQ2M,WAAW7H,OACxC/F,MAAKb,QAAQkU,OAAOzJ,SAAU,uBAAwB3I,MAAQjB,KAAKI,KAAKgT;AACxEpT,KAAK+R,OAAO3J,WAAWpI,KAAK8T,uBAAwB9T,KAAKyT,mBAAoB,KAAM,MAGnF,IAAImB,mBAAoB5U,KAAKyT,kBAE7B,KAAI,GAAIpQ,GAAE,EAAGA,EAAErD,KAAKwT,MAAOnQ,IAAK,CAE/BrD,KAAK+T,uBAAuB1Q,GAAGuG,SAAU,gBAAiB3I,MAAQ2T,kBAAkB7O,OAEpF/F,MAAK+T,uBAAuB1Q,GAAGuG,SAAU,aAAc3I,MAAQgS,cAEtDjT,MAAK+R,OAAO3J,WAAWpI,KAAK+T,uBAAuB1Q,GAAIrD,KAAKsT,wBAAwBjQ,GAAI,KAEjGrD,MAAK+T,uBAAuB1Q,GAAGuG,SAAU,gBAAiB3I,MAAQjB,KAAKsT,wBAAwBjQ,GAAG0C,OAElG/F,MAAK+T,uBAAuB1Q,GAAGuG,SAAU,aAAc3I,MAAQiS,cAE/DlT,MAAK+R,OAAO3J,WAAWpI,KAAK+T,uBAAuB1Q,GAAIrD,KAAKuT,sBAAsBlQ,GAAI,KAEtFuR,mBAAoB5U,KAAKuT,sBAAsBlQ,GAIhDrD,KAAKkU,kBAAkBtK,SAAS,iBAAiB3I,MAAQjB,KAAKI,KAAKwR,QACnE5R,MAAKkU,kBAAkBtK,SAAS,eAAe3I,MAAQjB,KAAKI,KAAKgQ,MACjEpQ,MAAKkU,kBAAkBtK,SAAS,mBAAmB3I,MAAQjB,KAAKqU,eAC1DrU,MAAK+R,OAAO3J,WAAWpI,KAAKkU,kBAAmBlU,KAAKsT,wBAAwB,GAAI,KAEtF5R,UAASiT,cAAe3U,KAAKsU,cAAetU,KAAKwU,cACjD9S,UAASkH,UAAY8L,cAGnBxG,QAAS,SAAWzJ,MAAOC,QAE7B,GAAImQ,MAAO9L,KAAKC,MAAMvE,MAAM,EAC5B,IAAIqQ,MAAO/L,KAAKC,MAAMtE,OAAO,EAE7B1E,MAAKyT,mBAAmBvF,QAAQ2G,KAAMC,KAEtC,KAAK,GAAIzR,GAAE,EAAGA,EAAErD,KAAKwT,MAAOnQ,IAAK,CAEhCrD,KAAKsT,wBAAwBjQ,GAAG6K,QAAQ2G,KAAMC,KAC9C9U,MAAKuT,sBAAsBlQ,GAAG6K,QAAQ2G,KAAMC,KAE5C9U,MAAK+T,uBAAuB1Q,GAAGuG,SAAU,WAAY3I,MAAQ,GAAI6D,OAAMmD,QAAQ4M,KAAMC,KAErFD,MAAO9L,KAAKC,MAAM6L,KAAK,EACvBC,MAAO/L,KAAKC,MAAM8L,KAAK,KAItBjS,OAAQ,WACJ7C,KAAK+R,OAAO1D,WAAWrO,KACvB,KAAK,GAAIqD,GAAE,EAAGA,EAAGrD,KAAKsT,wBAAwBzK,OAAQxF,IAAK,CAChErD,KAAKsT,wBAAwBjQ,GAAGkK,UAEjC,IAAK,GAAIlK,GAAE,EAAGA,EAAGrD,KAAKuT,sBAAsB1K,OAAQxF,IAAK,CACxDrD,KAAKuT,sBAAsBlQ,GAAGkK,UAE/BvN,KAAKyT,mBAAmBlG,WAGtB0G,yBAA0B,SAASc,cAErC,MAAO/U,MAAK+R,OAAOtI,aAElBY,SACC2K,cAAkBD,aAClBE,MAAUF,cAGXnL,UACCsL,cAAkBjU,MAAO,MACzBkU,SAAiBlU,MAAO,GAAI6D,OAAMmD,QAAS,GAAK,KAChDsK,WAAmBtR,MAAO,GAAI6D,OAAMmD,QAAS,GAAK,MAGnDH,aACC,wKAUD6B,eACC,ohCAkDHwK,qBAAsB,SAASX,OAE9B,MAAO,IAAI1O,OAAM+E,gBAEhBQ,SACC+K,SAAa5B,OAGd5J,UACCyL,cAAkBpU,MAAO,MACzBqU,cAAkBrU,MAAO,MACzBsU,cAAkBtU,MAAO,MACzBuU,cAAkBvU,MAAO,MACzBwU,cAAkBxU,MAAO,MACzByU,eAAoBzU,MAAO,GAC3BmT,cAAmBnT,MAAO,MAC1BoT,iBAAsBpT,MAAO,MAC7B0U,aAAkB1U,MAAO,IAG1B6G,aACC,wKAUD6B,eACC,ovCAgDHqC,QAAS,KACTE,UAAW,OACRR,UACI,sEACA,+CACA,KACF3D,KAAK,SAKN,SAAU3I,OAAQD,SASvBC,OAAOD,SAELyW,SAAU,qBAEXhM,UAECtC,UAAcnE,KAAM,IAAKlC,MAAO,MAChCyS,qBAAyBvQ,KAAM,IAAKlC,MAAO,GAC3C0S,aAAiBxQ,KAAM,IAAKlC,MAAO,GACnC2S,cAAkBzQ,KAAM,IAAKlC,MAAO,GAAI6D,OAAMqN,MAAO,IACrD0B,gBAAqB1Q,KAAM,IAAKlC,MAAO,IAIxC6G,cAEC,oBAEA,gBAEC,YAEA,4EAED,KAECC,KAAK,MAEP4B,gBAEC,8BACA,6BACA,gCACA,qCACA,6BAEA,oBAEA,gBAEC,2CAEA,2CAEA,oCAEA,+DAEA,yFAEA,mDAED,KAEC5B,KAAK,QAOH,SAAU3I,OAAQD,SAEvBS,OAAOa,kBAAkB,UACrBgR,SAAU,KAEVvO,QACI2S,MAAUzS,QAAS,OACnB0S,KAAS3S,KAAM,YACf4S,UAAc3S,QAAS,OACvB4S,SAAa5S,QAAS,OACtBwD,KAASzD,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACtDqG,KAAS9S,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACtDsG,KAAS/S,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACtDuG,MAAUhT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACvDwG,OAAWjT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACxD2B,KAASpO,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACtD4B,KAASrO,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACtDyG,OAAWlT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,GAAI,GAAI,KAC5D0G,MAAUnT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACvD2G,KAASpT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,EAAE,IACtD4G,OAAWrT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,GAAI,KAC1D6G,MAAUtT,KAAM,OAAQC,QAAS,GAAI0B,OAAM8K,QAAQ,EAAE,GAAI,MAG7DzN,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OACtClC,MAAK4J,UACDhD,KAASzD,KAAM,KAAMlC,MAAO,MAC5BgV,KAAS9S,KAAM,KAAMlC,MAAO,MAC5BiV,KAAS/S,KAAM,KAAMlC,MAAO,MAC5BkV,MAAUhT,KAAM,KAAMlC,MAAO,MAC7BmV,OAAWjT,KAAM,KAAMlC,MAAO,MAC9BsQ,KAASpO,KAAM,KAAMlC,MAAO,MAC5BuQ,KAASrO,KAAM,KAAMlC,MAAO,MAC5BoV,OAAWlT,KAAM,KAAMlC,MAAO,MAC9BqV,MAAUnT,KAAM,KAAMlC,MAAO,MAC7BsV,KAASpT,KAAM,KAAMlC,MAAO,MAC5BuV,OAAWrT,KAAM,KAAMlC,MAAO,MAC9BwV,MAAUtT,KAAM,KAAMlC,MAAO,MAC7B8E,SACI5C,KAAM,IACNlC,MAAO,GAAI6D,OAAM4R,QACbpT,UACAA,UACAA,UACAA,UACAwB,MAAM6R,cACN7R,MAAM6R,gBAIlB3W,MAAKqN,SAELrN,MAAK+R,OAAO3D,SAASpO,OAGzBuC,OAAQ,SAAUD,SACd,GAAI8J,GAAIpM,KAAKI,KAAM0S,GAAM9S,KAAK4J,SAAUgN,aAAe,KAEvD,KAAI,GAAIvK,KAAKyG,IAAI,CACb,GAAG1G,EAAEC,KAAO/I,UAAWwP,GAAGzG,GAAGpL,MAAQmL,EAAEC,KAG3C,IAAGrM,KAAKI,KAAK4V,UAAY1T,QAAQ0T,SAAWhW,KAAKI,KAAK2V,WAAazT,QAAQyT,UAAY/V,KAAKI,KAAKyV,MAAQvT,QAAQuT,KAAM,CACnH7V,KAAKqN,UAGT,GAAGrN,KAAKI,KAAK0V,MAAQxT,QAAQwT,IAAK,CAC9B,KAAM/P,SAAU/F,KAAK4J,SAAS7D,QAAQ9E,KACtC8E,SAAQuJ,MAAQtP,KAAKI,KAAK0V,GAC1B/P,SAAQZ,YAAc,OAI9BtC,OAAQ,WACJ7C,KAAK+R,OAAO1D,WAAWrO,OAG3BqN,QAAS,WACL,GAAIvK,QAAUtD,EAAIQ,KAAKI,KAAKyV,IAC5B,KAAI,GAAIxS,GAAE,EAAGA,EAAI7D,EAAEqJ,OAAQxF,IAAI,CAC3B,GAAIwT,IAAK7W,KAAK8W,IAAItX,EAAE6D,GACpB,IAAGwT,GAAI/T,IAAIuC,KAAKwR,IAGpB7W,KAAK0L,UACD1L,KAAKI,KAAK2V,SAAW,GAAK,0BAC1B/V,KAAKI,KAAK4V,QAAU,wBAA0B,GAC9ChW,KAAK+W,YACLjU,IAAIiF,KAAK,MACT,KACFA,KAAK,KAEP/H,MAAK+R,OAAO5M,YAAc,MAG9B2R,KACItX,EAAK,qBACLwX,EAAK,qBACLtX,EAAK,oCACL0J,EAAK,mCACL6F,EAAK,mCACLxG,EAAK,oDACLwO,EAAK,+BACLC,EAAK,kDACLzX,EAAK,4CACL0X,EAAK,+DACL3T,EAAK,+CACLiJ,EAAK,yFACL5I,EAAK,0BAGTmI,QAAS,KAET+K,aAEI,iCACA,4BACA,wDACA,aAEA,uDAEA,0BACA,+CACA,oDAEA,0BACA,8CACA,mDAEA,0BACA,0FACA,0FAEA,yBACA,qCACA,aAEA,0BACA,0FACA,0FAEA,yBACA,qCACA,aAEA,0DACA,0DAEA,wEACA,uBACA,IAEA,yBAEA,uDACA,wEACA,wEAEA,qCACA,yBACA,+EACA,IAEA,wBACA,IACA,qDACA,wDACA,gEACA,IAEA,sEACA,0BACFhP,KAAK,SAKN,SAAU3I,OAAQD,SAIvBS,OAAOa,kBAAkB,UACrByC,QAAUE,QAAS,MAEnBjB,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OAEtClC,MAAK4J,UACDwN,OAAYjU,KAAM,IAAKlC,MAAOjB,KAAKqX,kBAAmB,KACtDC,QAAanU,KAAM,IAAKlC,MAAO,KAC/BsW,OAAYpU,KAAM,IAAKlC,MAAO,KAC9BuW,MAAYrU,KAAM,IAAKlC,MAAO,KAC9BwW,QAAatU,KAAM,IAAKlC,MAAO,KAC/ByW,QAAavU,KAAM,IAAKlC,MAAO,KAC/B0W,cAAkBxU,KAAM,IAAKlC,MAAO,IACpC2W,cAAkBzU,KAAM,IAAKlC,MAAO,IACpC4W,OAAY1U,KAAM,IAAKlC,MAAO,KAGxCjB,MAAKb,SACJ2Y,QACapM,SAAU1L,KAAK0L,SACf9B,SAAU5J,KAAK4J,UAIvB5J,MAAKqI,SAAWrI,KAAK+R,OAAOzH,MAAMtK,KAAKb,QAAQ2Y,QAE/C9X,MAAK+R,OAAO3D,SAASpO,OAGzB0N,GAAI,KAEJnL,OAAQ,WACJvC,KAAK+N,QAAU/N,KAAKI,IACpBJ,MAAK+X,KAAO,CACZ/X,MAAKgY,mBAGTnV,OAAQ,WACJ7C,KAAK+R,OAAO1D,WAAWrO,OAG3B+D,KAAM,WACF/D,KAAK4J,SAAU,QAAS3I,MAAQ8H,KAAKkP,QAE3C,IAAKjY,KAAK+X,KAAO/X,KAAKkY,OAAS,EAAG,CAEjClY,KAAK4J,SAAU,UAAW3I,MAAQ8H,KAAKkP,SAAW,EAClDjY,MAAK4J,SAAU,SAAU3I,MAAQ6D,MAAMiE,KAAKoP,WAAapP,KAAKqP,GAAIrP,KAAKqP,GACvEpY,MAAK4J,SAAU,UAAW3I,MAAQ6D,MAAMiE,KAAKoP,WAAa,EAAG,EAC7DnY,MAAK4J,SAAU,UAAW3I,MAAQ6D,MAAMiE,KAAKoP,WAAa,EAAG,EAC7DnY,MAAK4J,SAAU,gBAAiB3I,MAAQ6D,MAAMiE,KAAKoP,UAAW,EAAG,EACjEnY,MAAK4J,SAAU,gBAAiB3I,MAAQ6D,MAAMiE,KAAKoP,UAAW,EAAG,EACjEnY,MAAK+X,KAAO,CACZ/X,MAAKgY,sBAEC,IAAKhY,KAAK+X,KAAO/X,KAAKkY,MAAQlY,KAAKkY,MAAQ,EAAI,CAErDlY,KAAK4J,SAAU,UAAW3I,MAAQ8H,KAAKkP,SAAW,EAClDjY,MAAK4J,SAAU,SAAU3I,MAAQ6D,MAAMiE,KAAKoP,WAAapP,KAAKqP,GAAIrP,KAAKqP,GACvEpY,MAAK4J,SAAU,gBAAiB3I,MAAQ6D,MAAMiE,KAAKoP,UAAW,EAAG,EACjEnY,MAAK4J,SAAU,gBAAiB3I,MAAQ6D,MAAMiE,KAAKoP,UAAW,EAAG,EACjEnY,MAAK4J,SAAU,UAAW3I,MAAQ6D,MAAMiE,KAAKoP,WAAa,GAAK,GAC/DnY,MAAK4J,SAAU,UAAW3I,MAAQ6D,MAAMiE,KAAKoP,WAAa,GAAK,IAIhEnY,KAAK+X,QAGHC,gBAAiB,WAEnBhY,KAAKkY,MAAQpT,MAAMiE,KAAKsP,QAAS,IAAK,MAIvChB,kBAAmB,SAAUiB,SAE5B,GAAIC,UAAW,GAAIvT,cAAcsT,QAAUA,QAAU,EACrD,IAAIzP,QAASyP,QAAUA,OAEvB,KAAM,GAAIjV,GAAI,EAAGA,EAAIwF,OAAQxF,IAAO,CAEnC,GAAImV,KAAM1T,MAAMiE,KAAKoP,UAAW,EAAG,EACnCI,UAAUlV,EAAI,EAAI,GAAMmV,GACxBD,UAAUlV,EAAI,EAAI,GAAMmV,GACxBD,UAAUlV,EAAI,EAAI,GAAMmV,IAIzB,GAAIzS,SAAU,GAAIjB,OAAMC,YAAawT,SAAUD,QAASA,QAASxT,MAAM2T,UAAW3T,MAAMI,UACxFa,SAAQZ,YAAc,IACtB,OAAOY,UAIL2F,UACF,wBACC,oEACD,IAEA,uEACE,eACY,8DACZ,0CACA,0CAEA,wDACA,+EACC,kBACC,oCACD,IACA,SACC,uBACD,IACD,IACA,+EACC,qBACC,uBACD,IACA,SACC,oCACD,IACD,IACA,uCACA,uCAEA,2DACA,6CACA,qCACA,6CACA,0CAEA,6EACA,uBACF,KACC3D,KAAM,SAKJ,SAAU3I,OAAQD,SAKvBS,OAAOa,kBAAkB,WACrByC,QACIwV,MAAUvV,KAAM,QAASC,QAAS,WAClCgQ,WAAejQ,KAAM,OAAQC,QAAS,GAAI0B,OAAM+C,QAAQ,EAAE,EAAE,IAC5D8Q,KAASxV,KAAM,WAAYC,QAAS,MACpCwV,WAAexV,QAAS,GACxBiQ,QAAYlQ,KAAM,QAASC,YAC3ByO,OAAWzO,QAAS,MAGxBjB,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OACtC,IAAI8P,OAASrM,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,WAC/FjF,MAAK6Y,SAAW,GAAI/T,OAAMY,kBAAmB,EAAG,EAAGsM,KAC7ChS,MAAK8Y,kBAAoB,GAAIhU,OAAMY,kBAAmB,EAAG,EAAGsM,KAClEhS,MAAK+Y,kBAAoB,GAAIjU,OAAMY,kBAAmB,EAAG,EAAGsM,KAEtDhS,MAAKb,SACDkU,QACIxI,UAAW,WACXjB,UACI8O,MAAUvV,KAAM,IAAKlC,MAAO,GAAI6D,OAAMqN,OACtCiB,WAAejQ,KAAM,KAAMlC,MAAO,GAAI6D,OAAMmD,QAAQ,EAAE,KAE1D6D,MAAO,KACPJ,UACI,uEACA,uHACA,0EACA,KACF3D,KAAM,OAEZuK,MACI1I,UACIoP,MAAQ7V,KAAK,IAAKlC,MAAO,GACzB0X,KAAOxV,KAAM,KAAMlC,MAAO,GAAI6D,OAAM8K,QAAS,GAAK,GAAK,KAE3DlE,UACI,kEACI,iEACA,4BACA,gCACA,qCACA,4BACA,wBACA,sEACA,eACA,sEACA,eACA,sEACA,eACA,sEACA,eACA,sEACA,eACA,sEACA,mBACJ,KAEF3D,KAAM,OAIhB/H,MAAKiZ,wBAA0BjZ,KAAK+R,OAAOzH,MAAMtK,KAAKb,QAAQmT,MAC9DtS,MAAK4J,UACDgP,WAAezV,KAAM,IAAKlC,MAAO,GACjCiY,aAAgB/V,KAAM,IAAKlC,MAAO,GAClC8E,SAAa5C,KAAM,IAAKlC,MAAOjB,KAAK+Y,mBAGxC/Y,MAAKmZ,eAAiB,IAEtBnZ,MAAKiO,YAAc,IACnBjO,MAAK+R,OAAO3D,SAASpO,OAGzBkO,QAAS,SAAU/E,EAAEC,GAClBD,EAAIJ,KAAKC,MAAMG,EAAInJ,KAAKI,KAAKyR,MAC7BzI,GAAIL,KAAKC,MAAMI,EAAIpJ,KAAKI,KAAKyR,MAC7B7R,MAAK8Y,kBAAkB5K,QAAQ/E,EAAEC,EACjCpJ,MAAK+Y,kBAAkB7K,QAAQ/E,EAAEC,EACjCpJ,MAAK6Y,SAAS3K,QAAQ/E,EAAEC,IAG3B7G,OAAQ,SAAUD,SACdtC,KAAKb,QAAQkU,OAAOzJ,SAAS8O,KAAKzX,MAAMyB,IAAI1C,KAAKI,KAAKsY,KACtD1Y,MAAK4J,SAASgP,UAAU3X,MAAQjB,KAAKI,KAAKwY,SAC1C,IAAG5Y,KAAKI,KAAKiT,SAAW/Q,QAAQ+Q,OAAQ,CACpC,GAAGrT,KAAKmZ,eAAgBnZ,KAAKmZ,eAAe5L,SAC5CvN,MAAKmZ,eAAiBnZ,KAAK+R,OAAOzH,KAAKtK,KAAKI,KAAKiT,OAAOxK,OAAS7I,KAAKI,KAAKiT,QAAUrT,KAAKb,QAAQkU,SAEtGrT,KAAK+N,OAAS/N,KAAKI,KAAKuY,MAAQ,MAGpC5U,KAAM,WACF,IAAK/D,KAAK+R,OAAOlE,SAAS7N,KAAM,MAAO,MACvC,IAAID,MAAOC,IAEXA,MAAK+R,OAAOzK,SAASrG,MAAQjB,KAAK+R,OAAOlQ,aAAakE,OACtD/F,MAAK+R,OAAO3J,WAAWpI,KAAKmZ,eAAgBnZ,KAAK6Y,SAAUO,GAE3D,IAAIA,IAAK,SAAU/Q,SAAU5F,OAAQ4W,KACjC,GAAIC,KAAM,GAAIxU,OAAM8K,QAAW2J,IAAM,GAAIzU,OAAM8K,OAC/C,IAAIjD,IAAK5M,KAAKZ,QAAQmT,KAAK1I,SAAU,OAAQ3I,KAC7ClB,MAAKK,KAAKuY,IAAI7W,SAAS0X,iBAAiB7M,GACxClK,QAAO+W,iBAAiBF,IACxB7W,QAAOgX,kBAAkBF,IACzBD,KAAII,IAAI/M,GACR2M,KAAIK,WACJJ,KAAII,WACJ5Z,MAAK6J,SAASsP,YAAYjY,MAAQ8H,KAAKmN,IAAInN,KAAKyI,IAAI,GAAI+H,IAAIK,IAAIN,MAAO,KAEvE3M,IAAG2E,QAAS7O,OACZkK,IAAGjK,KAAKiK,GAAG1D,EAAI,GAAM,GAAI0D,GAAGzD,EAAI,GAAM,EAAG,GAI7C,IAAI2Q,WAAY,CACtB,IAAIC,eAAgB,CAEd,IAAIxM,MAAO,CACX,IAAIyM,SAAUF,UAAY9Q,KAAKmN,IAAK4D,eAAgBxM,KACpDtN,MAAKb,QAAQmT,KAAK1I,SAAU,QAAS3I,MAAQ8Y,OAC7C/Z,MAAK+R,OAAQ,YAAa9Q,MAAQjB,KAAK6Y,SAAS9S,OAChD/F,MAAK+R,OAAO3J,WAAWpI,KAAKiZ,wBAAyBjZ,KAAK+Y,kBAAmBK,GAE7E9L,MAAO,CACPyM,SAAUF,UAAY9Q,KAAKmN,IAAK4D,eAAgBxM,KAChDtN,MAAKb,QAAQmT,KAAK1I,SAAU,QAAS3I,MAAQ8Y,OAC7C/Z,MAAK+R,OAAQ,YAAa9Q,MAAQjB,KAAK+Y,kBAAkBhT,OACzD/F,MAAK+R,OAAO3J,WAAWpI,KAAKiZ,wBAAyBjZ,KAAK8Y,kBAAmBM,GAE7E9L,MAAO,CACPyM,SAAUF,UAAY9Q,KAAKmN,IAAK4D,eAAgBxM,KAChDtN,MAAKb,QAAQmT,KAAK1I,SAAU,QAAS3I,MAAQ8Y,OAC7C/Z,MAAK+R,OAAQ,YAAa9Q,MAAQjB,KAAK8Y,kBAAkB/S,OACzD/F,MAAK+R,OAAO3J,WAAWpI,KAAKiZ,wBAAyBjZ,KAAK+Y,kBAAmBK,KAGjFvW,OAAQ,WACJ7C,KAAK8Y,kBAAkBvL,SACvBvN,MAAK+Y,kBAAkBxL,SACvBvN,MAAK6Y,SAAStL,SAEdvN,MAAKiZ,wBAAwB1L,SAC7BvN,MAAKmZ,eAAe5L,SACpBvN,MAAK+R,OAAO1D,WAAWrO,OAG3BgM,QAAS,KAETN,UACI,gDACA,2CACA,IAEA,6CACA,2GACA,IAEA,4DACH,6EACG,IAEN,uEACA,2CACM,iFACA,KACL3D,KAAM,SAKJ,SAAU3I,OAAQD,QAASF,qBAEhC,GAAI+a,WAAY/a,oBAAoB,GACpC,IAAIgb,wBAAyBhb,oBAAoB,GAEjDW,QAAOa,kBAAkB,QACrByC,QACIgX,SAAa/W,KAAM,SAAUC,QAAS,IACtC+W,OAAWhX,KAAM,SAAUC,QAAS,GACpCgN,QAAYjN,KAAM,SAAUC,QAAS,IACrCyO,OAAWzO,QAAS,IACpBwV,WAAexV,QAAS,GACxBgX,UAAchX,QAAS,KACvBiX,MAAUjX,QAAS,KACnBkX,OAAWlX,QAAS,KACpBmX,YAAgBnX,QAAS,GACzBoX,aAAkBpX,QAAS,KAG/BjB,KAAM,WACFnC,KAAK+R,OAAS/R,KAAKF,GAAGQ,QAAQC,QAAQ2B,OACtC,IAAI8P,OAASrM,UAAWb,MAAMc,aAAcC,UAAWf,MAAMc,aAAcE,OAAQhB,MAAMG,WACzFjF,MAAKya,gBACXza,MAAKya,cAAcpV,KAAK,GAAIP,OAAMY,kBAAmB,EAAG,EAAGsM,MAC3DhS,MAAKya,cAAcpV,KAAK,GAAIP,OAAMY,kBAAmB,EAAG,EAAGsM,MACrDhS,MAAK4J,UACD7D,SAAa5C,KAAM,IAAKlC,MAAOjB,KAAKya,cAAc,GAAG1U,SACrD6S,WAAezV,KAAM,IAAKlC,MAAO,GACjCmZ,UAAcjX,KAAM,IAAKlC,MAAO,KAChCuZ,aAAiBrX,KAAM,IAAKC,QAAS,GAEzCpD,MAAK0a,YAAc,IACnB1a,MAAK2a,cAAgB,IACrB3a,MAAK4a,cAAgB,IACrB5a,MAAK6a,aAAgB1X,KAAM,KAAMlC,MAAO,GAAI6D,OAAMmD,QAClDjI,MAAK+R,OAAO3D,SAASpO,OAGzBuC,OAAQ,SAAUuY,IACd,GAAI1O,GAAIpM,KAAKI,KAAML,KAAKC,IAExBA,MAAKqN,QAAQjB,EAAE+N,QAAUW,GAAGX,OAAS/N,EAAE8N,UAAYY,GAAGZ,QAAS9N,EAAEmO,aAAeO,GAAGP,WACnFva,MAAK4J,SAAS4Q,YAAYvZ,MAAQmL,EAAEoO,WACpCxa,MAAK4J,SAASgP,UAAU3X,MAAQmL,EAAEwM,SAClC5Y,MAAK4J,SAASwQ,SAASnZ,MAAQmL,EAAEgO,QACjCpa,MAAK0a,YAAY9Q,SAASyQ,KAAKpZ,MAAQmL,EAAEiO,IACzCra,MAAK0a,YAAY9Q,SAAS0Q,MAAMrZ,MAAQmL,EAAEkO,KAC1Cta,MAAK0a,YAAY9Q,SAASmL,aAAa9T,MAAQmL,EAAEgE,MACjDpQ,MAAK2a,cAAc/Q,SAAS4Q,YAAYvZ,MAAQmL,EAAEoO,WAClDxa,MAAK4a,cAAchR,SAAS4Q,YAAYvZ,MAAQmL,EAAEoO,aAGtDnN,QAAS,SAAU0N,IAAKzI,MACpB,GAAIlG,GAAIpM,KAAKI,IACb,IAAG2a,IAAK,CACJ,GAAI/a,KAAK0a,YAAa,CAClB1a,KAAK0a,YAAYnN,UAErBvN,KAAK0a,YAAc1a,KAAK+R,OAAOtI,YAAYuQ,UAAU,MAC9Dha,MAAK0a,YAAYrQ,QAAQ,SAAW2Q,SAAS5O,EAAE+N,OAAS,GACxDna,MAAK0a,YAAYrQ,QAAQ,WAAa2Q,SAAS5O,EAAE8N,SAAW,GAC5Dla,MAAK0a,YAAY9Q,SAASpC,UAAYxH,KAAK+R,OAAOvK,SACzCxH,MAAK0a,YAAY9Q,SAASnC,WAAazH,KAAK+R,OAAOtK,WAEvD,GAAG6K,KAAM,CACL,GAAItS,KAAK2a,cAAe,CACpB3a,KAAK2a,cAAcpN,SACnBvN,MAAK4a,cAAcrN,UAEvBvN,KAAK2a,cAAgB3a,KAAK+R,OAAOtI,YAAYwQ,uBAAuB7N,EAAEmO,WAAYnO,EAAEmO,WAAW,EAAG,GAAIzV,OAAMmD,QAAQ,EAAE,IACtHjI,MAAK4a,cAAgB5a,KAAK+R,OAAOtI,YAAYwQ,uBAAuB7N,EAAEmO,WAAYnO,EAAEmO,WAAW,EAAG,GAAIzV,OAAMmD,QAAQ,EAAE,IACtHjI,MAAK2a,cAAc/Q,SAASuE,KAAOnO,KAAK6a,WACxC7a,MAAK4a,cAAchR,SAASuE,KAAOnO,KAAK6a,WACxC7a,MAAK2a,cAAc/Q,SAASpC,UAAYxH,KAAK+R,OAAOvK,SACpDxH,MAAK2a,cAAc/Q,SAASnC,WAAazH,KAAK+R,OAAOtK,UACrDzH,MAAK4a,cAAchR,SAASpC,UAAYxH,KAAK+R,OAAOvK,SACpDxH,MAAK4a,cAAchR,SAASnC,WAAazH,KAAK+R,OAAOtK,aAI7DyG,QAAS,SAAS/E,EAAGC,GACjBD,EAAIJ,KAAKmG,KAAK/F,EAAInJ,KAAKI,KAAKyR,MAC5BzI,GAAIL,KAAKmG,KAAK9F,EAAIpJ,KAAKI,KAAKyR,MAE5B7R,MAAK6a,YAAY5Z,MAAMyB,IAAIyG,EAAEC,EAE7BpJ,MAAKya,cAAc1Z,QAAQ,SAAUwN,IACjCA,GAAGL,QAAQ/E,EAAEC,MAIrBrF,KAAM,SAAUL,MACZ,IAAK1D,KAAK+R,OAAOlE,SAAS7N,KAAM,MAAO,MAEvCA,MAAK0a,YAAY9Q,SAAU,iCAAkC3I,MAAMga,WAAYjb,KAAKF,GAAGQ,QAAQmC,OAAO2M,iBAC5GpP,MAAK0a,YAAY9Q,SAAU,0BAA2B3I,MAAQjB,KAAKF,GAAGQ,QAAQmC,OAAO2M,gBAE/EpP,MAAK0a,YAAY9Q,SAASrC,OAAOtG,MAAQjB,KAAKF,GAAGQ,QAAQuB,aAAaqE,YACtElG,MAAK+R,OAAO3J,WAAWpI,KAAK0a,YAAa1a,KAAKya,cAAc,GAAI,KAEtE,IAAGza,KAAKI,KAAKma,WAAY,CACxBva,KAAK2a,cAAc/Q,SAAStC,SAASrG,MAAQjB,KAAKya,cAAc,GAAG1U,OACnE/F,MAAK+R,OAAO3J,WAAWpI,KAAK2a,cAAe3a,KAAKya,cAAc,GAAI,KAElEza,MAAK4a,cAAchR,SAAStC,SAASrG,MAAQjB,KAAKya,cAAc,GAAG1U,OACnE/F,MAAK+R,OAAO3J,WAAWpI,KAAK4a,cAAe5a,KAAKya,cAAc,GAAI,QAIjE5X,OAAQ,WACJ7C,KAAK0a,YAAYnN,SACjBvN,MAAK2a,cAAcpN,SACnBvN,MAAK4a,cAAcrN,SACnBvN,MAAKya,cAAc,GAAGlN,SACtBvN,MAAKya,cAAc,GAAGlN,SACtBvN,MAAK+R,OAAO1D,WAAWrO,OAG3B6K,UAAW,WAEXiB,MAAO,KAEPE,QAAS,KAETN,UACI,kCACA,oEACA,oEACA,IACN,uEACA,2CACM,0FACA,wEACA,8GACA,KACL3D,KAAM,SAKJ,SAAU3I,OAAQD,SASvBC,OAAOD,QAAU,SAAU+b,SAC1B,OACC7Q,WAEAT,UAECrC,QAAkBpE,KAAM,IAAKlC,MAAO,MAEpCwG,YAAkBtE,KAAM,IAAKlC,MAAO,GACpCuG,WAAkBrE,KAAM,IAAKlC,MAAO,KACpCka,wBAA4BhY,KAAM,KAAMlC,MAAO,GAAI6D,OAAMsW,SACzDC,+BAAmClY,KAAM,KAAMlC,MAAO,GAAI6D,OAAMsW,SAEhEd,OAAkBnX,KAAM,IAAKlC,MAAO,GACpCoZ,MAAkBlX,KAAM,IAAKlC,MAAO,IAEpCqa,eAAmBnY,KAAM,IAAKlC,MAAO,GACrC8T,cAAkB5R,KAAM,IAAKlC,MAAO,IACpCsa,YAAkBpY,KAAM,IAAKlC,MAAO,GACpCmZ,UAAgBjX,KAAM,IAAKlC,MAAO,IAGnC6G,cAEC,oBACA,gBAEC,YAEA,4EAED,KAECC,KAAM,MAER4B,gBAIC,oBACA,qBAEA,oBAEA,4BAEA,4BACA,2BACA,uCACA,8CAEA,uBACA,2BACA,sBACA,8BACA,+BACA,4BACA,0BAGA,iCACA,oEACE,oEACF,IAEA,gCACA,8EACG,wFACA,wDACH,IAGA,2CAEC,kEAED,IAEA,qGAEC,qFACA,kFACA,yBACA,+DAED,IAEA,mFAEC,2EAED,IAEA,iCACA,4CAEA,6HAEC,4DACA,4CACA,uEACA,kKAED,IAGA,kDACA,+CAEA,iEAGC,mCACA,kEACA,oEAGA,gDACA,wDACA,4BACA,2BACA,wBACA,6CACC,qEACA,wBACA,uBAEA,uDACA,2CACC,YACD,IAEA,+CACA,mFACA,4FACA,oBAED,IAEA,kCACA,mCAED,IAGA,gBACC,yCACA,+BAEA,gDACC,WACD,IAEA,+CACA,wEAEA,gFACD,KAEC5B,KAAM,SAOL,SAAU3I,OAAQD,SAavB2F,MAAM0W,iBAELC,oBAAqB,SAAU1G,aAAc2G,QAE5C,GAAIC,UAAW,SAAU1S,EAAGyS,QAC3B,MAAO3S,MAAK6S,MAAS3S,EAAEA,IAAQ,GAAQyS,OAASA,WAAiB3S,KAAK8S,KAAM,EAAM9S,KAAKqP,IAAOsD,QAG/F,IAAII,WAEJ,KAAK,GAAIzY,GAAI,EAAGA,GAAK0R,aAAc1R,IAAO,CACzCyY,QAAQzW,KAAMsW,SAAUtY,EAAGqY,SAG5B,MAAOI,UAGRC,oBAAqB,SAAUhH,aAAciH,aAE5C,GAAIC,WAEJ,KAAK,GAAI5Y,GAAI,EAAGA,GAAK0R,aAAc1R,IAAO,CACzC4Y,QAAQ5W,KAAM2W,YAAYE,QAAQC,eAAgB9Y,IAGnD,MAAO4Y,UAIRG,UAAW,SAAUrH,aAAc2G,OAAQM,aAC1C,OACCK,gBAAmBvX,MAAM0W,gBAAgBO,oBAAqBhH,aAAciH,aAC5EM,cAAiBxX,MAAM0W,gBAAgBC,oBAAqB1G,aAAc2G,UAO7Etc,QAAOD,QAAW,SAAUiR,OAAQsL,OAAQM,aAC3C5L,OAASA,QAAU,CACnB,IAAImM,QAASzX,MAAM0W,gBAAgBY,UAAUhM,OAAQsL,OAAQM,YAC7D,QACC3R,SAEC2K,cAAiB5E,QAIlBxG,UAECtC,UAAsBnE,KAAM,IAAKlC,MAAO,MACxCkN,MAAsBhL,KAAM,KAAMlC,MAAO,GAAI6D,OAAMmD,QAAS,IAAK,MACjEoU,iBAAsBlZ,KAAM,MAAOlC,MAAOsb,OAAOF,iBACjDC,eAAsBnZ,KAAM,MAAOlC,MAAOsb,OAAOD,eACjD9B,aAAsBrX,KAAM,IAAKlC,MAAO,IACxCuG,WAAoBrE,KAAM,IAAKlC,MAAO,GACtCwG,YAAqBtE,KAAM,IAAKlC,MAAO,MAGxC6G,cAEC,oBAEA,qBAEA,oBACA,yBAEA,gBAEC,YACA,yBAEA,4EAED,KAECC,KAAM,MAER4B,gBAEC,oBACA,qBAEA,8BAEA,qDACA,oDACA,6BACA,2BACA,4BAEA,oBACA,yBAEA,iCACA,oEACE,oEACF,IAEA,2CAEC,kEAEA,IACD,gBACC,2CACA,yBACA,qCACA,qCACC,WACD,IACA,0CACA,uCAEA,sCACA,qCAEA,+CAEC,yCACA,uDAEA,wCACA,2CACA,qDAEA,gEAEA,mBACC,mCACA,6BACD,IAEA,mCACA,2CACA,+CAEA,gEAEA,mBACC,mCACA,6BACD,IAED,IAEA,gDAED,KAEC5B,KAAM,SAOL,SAAU3I,OAAQD,SAEvBS,OAAOa,kBAAkB,UACxByC,QACCqN,OAASpN,KAAM,QAASC,QAAS,WACjCgN,QAAUjN,KAAM,SAAUC,QAAS,GACnCoN,OAASrN,KAAM,SAAUC,QAAS,IAGnCjB,KAAM,WACLnC,KAAKF,GAAGQ,QAAQC,QAAQ2B,QAAQkD,SAASpF,OAG1C6C,OAAQ,WACP7C,KAAKF,GAAGQ,QAAQC,QAAQ2B,QAAQoD,YAAYtF,UAMzC,SAAUZ,OAAQD,SAEvB2F,MAAM0X,YAAa,sBAClB,4BACA,yBACA,iCACA,kCACA,UACCzU,KAAM,KAERjD,OAAM0X,YAAa,0BAClB,GACA,4BACA,6EACA,2CACA,8BACA,mCACA,6BACA,mCACA,4BACA,gCACA,8DACA,0BACA,sBACA,+BACA,kDACA,iEACA,kEACA,6CACA,2CACA,2CACA,yCACA,4EACA,oEACA,MACA,IACA,UACCzU,KAAM;AAER,GAAI0U,OAAQ7c,OAAO6c,KAEnB,IAAIC,YAAa,GAAI5X,OAAM6X,iBAC3B,IAAIC,mBAKJhd,QAAOY,eAAe,eACpB0C,QACE2Z,qBAAsB1Z,KAAM,OAC5B2Z,8BAA+B1Z,QAAS,GACxC2Z,+BAAgC5Z,KAAM,QACtC6Z,+BAAgC7Z,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAEjEqH,OAAQpN,KAAM,SAEd8Z,iBAAkB9Z,KAAM,OACxB+Z,mBAAoB9Z,QAAS,GAC7B+Z,kBAAmB/Z,QAAS,IAC5Bga,2BAA4Bja,KAAM,QAClCka,2BAA4Bla,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAC7DoU,UAAWna,KAAM,QAASC,QAAS,QACnCma,mBAAoBna,QAAS,GAC7Boa,QAASpa,QAAS,IAElB8G,KAAM9G,QAAS,MACfsB,QAAStB,QAAS,KAElBqa,WAAYra,QAAS,EAAKmO,IAAK,EAAKC,IAAK,GACzCkM,cAAeva,KAAM,OACrBwa,wBAAyBxa,KAAM,QAC/Bya,wBAAyBza,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAE1D2U,WAAY1a,KAAM,OAClB2a,aAAc3a,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAC/C6U,qBAAsB5a,KAAM,QAC5B6a,qBAAsB7a,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAEvD+U,QAAS9a,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAC1CgV,QAAS/a,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAE1CiV,WAAY/a,QAAS,GAAKmO,IAAK,EAAKC,IAAK,GACzC4M,cAAejb,KAAM,OACrBkb,wBAAyBlb,KAAM,QAC/Bmb,wBAAyBnb,KAAM,OAAQC,SAAU6F,EAAG,EAAGC,EAAG,IAE1DqV,iBAAkBpb,KAAM,OACxBwV,KAAMxV,KAAM,OACZsB,OAAQrB,QAAS,KACjBob,WAAYpb,QAAS,OACrBqb,oBAAqBrb,QAAS,IAOhCjB,KAAM,SAAU/B,MACdJ,KAAKqI,SAAW,GAAIvD,OAAM4Z,qBAAqBC,gBAAgBve,MAC/Dqc,OAAMpU,SAASuW,UAAU5e,KAAMI,KAC/B,IAAIA,KAAKyd,UAAW,CAAEpB,MAAMpU,SAASwW,oBAAoB,SAAU7e,KAAMI,MACzE,GAAIA,KAAK6c,gBAAiB,CAAER,MAAMpU,SAASwW,oBAAoB,eAAgB7e,KAAMI,MACrF,GAAIA,KAAKyc,oBAAqB,CAAEJ,MAAMpU,SAASwW,oBAAoB,mBAAoB7e,KAAMI,MAC7F,GAAIA,KAAKsd,aAAc,CAAEjB,MAAMpU,SAASwW,oBAAoB,YAAa7e,KAAMI,MAC/E,GAAIA,KAAKge,aAAc,CAAE3B,MAAMpU,SAASwW,oBAAoB,YAAa7e,KAAMI,MAC/EJ,KAAK8e,aAAa1e,KACrBJ,MAAKqI,SAAS0W,gBAAkB,SAAWC,QAC1CA,OAAOpV,SAASjF,SAAWsa,MAAMta,QACjCqa,QAAOpV,SAAShF,YAAcqa,MAAMra,WACpCoa,QAAOpV,SAAS/E,aAAeoa,MAAMpa,YACrCma,QAAO3U,QAAS,iBAAoB,IAIpC9H,OAAQ,SAAUnC,MAChBJ,KAAKkf,eAAe9e,KACpBqc,OAAMpU,SAASuW,UAAU5e,KAAMI,KAC/B,IAAIA,KAAKyd,UAAW,CAAEpB,MAAMpU,SAASwW,oBAAoB,SAAU7e,KAAMI,MACzE,GAAIA,KAAK6c,gBAAiB,CAAER,MAAMpU,SAASwW,oBAAoB,eAAgB7e,KAAMI,MACrF,GAAIA,KAAKyc,oBAAqB,CAAEJ,MAAMpU,SAASwW,oBAAoB,mBAAoB7e,KAAMI,MAC7F,GAAIA,KAAKsd,aAAc,CAAEjB,MAAMpU,SAASwW,oBAAoB,YAAa7e,KAAMI,MAC/E,GAAIA,KAAKge,aAAc,CAAE3B,MAAMpU,SAASwW,oBAAoB,YAAa7e,KAAMI,MAC/EJ,KAAK8e,aAAa1e,OASpB8e,eAAgB,SAAU9e,MACxB,GAAIiI,UAAWrI,KAAKqI,QACpBjI,MAAOue,gBAAgBve,KACvBS,QAAOC,KAAKV,MAAMW,QAAQ,SAAUC,KAClCqH,SAASrH,KAAOZ,KAAKY,QAOzB8d,aAAc,SAAU1e,MACtB,GAAIL,MAAOC,IACX,IAAIqI,UAAWrI,KAAKqI,QACpB,IAAImV,QAASpd,KAAKod,MAClB,IAAIe,iBAAkBne,KAAKme,eAG3B,KAAMf,SAAWe,iBAAoBve,KAAKmf,gBAAiB,CACzD9W,SAASmV,OAAS,IAClBnV,UAASlD,YAAc,IACvB,QAEFnF,KAAKmf,gBAAkB,IAGvB,IAAIZ,gBAAiB,CACnBve,KAAKF,GAAGQ,QAAQC,QAAQ8H,SAAS+W,YAAYb,iBAAkB5F,IAAK4F,iBAAkB,QAASc,eAAetZ,SAC5GhG,KAAKof,gBAAkB,KACvBpZ,SAAQuZ,QAAUxa,MAAMya,0BACxBlX,UAASmV,OAASzX,OAClB0W,OAAMpU,SAASmX,oBAAoBzf,KAAKD,GAAIiG,QAC5CsC,UAASlD,YAAc,MAEzB,QAIF,GAAIyX,gBAAgBY,QAAS,CAC3BZ,gBAAgBY,QAAQiC,KAAK,SAAUC,MACrC3f,KAAKof,gBAAkB,KACvB9W,UAASmV,OAASkC,IAClBjD,OAAMpU,SAASmX,oBAAoBzf,KAAKD,GAAI4f,KAC5CrX,UAASlD,YAAc,MAEzB,QAIFyX,gBAAgBY,QAAU,GAAImC,SAAQ,SAAUC,SAC9CnD,MAAMoD,UAAUC,mBAAmBtC,OAAQ,QAASuC,YAAYC,MAC9DtD,WAAWuD,KAAKD,KAAM,SAAUN,MAE9B3f,KAAKof,gBAAkB,KACvB9W,UAASmV,OAASkC,IAClBjD,OAAMpU,SAASmX,oBAAoBzf,KAAKD,GAAI4f,KAC5CE,SAAQF,cAalB,SAASf,iBAAiBve,MACxB,GAAI8f,UACF3P,MAAO,GAAIzL,OAAMqN,MAAM/R,KAAKmQ,OAC5B+M,SAAU,GAAIxY,OAAMqN,MAAM/R,KAAKkd,UAC/BC,kBAAmBnd,KAAKmd,kBACxBrT,IAAK9J,KAAK8J,IACVuT,UAAWrd,KAAKqd,UAChBU,UAAW/d,KAAK+d,UAChBK,UAAWpe,KAAKoe,UAChBC,mBAAoBre,KAAKqe,mBAG3B,IAAIre,KAAKyd,UAAW,CAAEqC,QAAQpC,YAAc1d,KAAK0d,YAEjD,GAAI1d,KAAKyc,oBAAqB,CAAEqD,QAAQC,eAAiB/f,KAAK0c,6BAE9D,GAAI1c,KAAK6c,gBAAiB,CACxBiD,QAAQhD,kBAAoB9c,KAAK8c,iBACjCgD,SAAQ/C,iBAAmB/c,KAAK+c,iBAGlC,MAAO+C","file":"dist/aframe-effects.min.js"} -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | A-Frame Effects 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 21 | 22 | 27 | 28 | 33 | 34 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
135 | 140 | 145 | 150 |
151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | if (!window.AFRAME) { 2 | var Component = function (el, id) { 3 | var self = this; 4 | this.el = el; 5 | this.el; 6 | this.id = id; 7 | this.attrName = this.name + (id ? '__' + id : ''); 8 | this.el.components[this.attrName] = this; 9 | this.data = {}; 10 | }; 11 | 12 | var System = function (el) { 13 | var self = this; 14 | this.el = this.sceneEl = el; 15 | this.el.systems[this.name] = this; 16 | }; 17 | 18 | AFRAME = { 19 | components: {}, 20 | systems: {}, 21 | registerShader: function () {} 22 | }; 23 | 24 | AFRAME.registerComponent = function (name, definition) { 25 | var NewComponent; 26 | var proto = {}; 27 | 28 | Object.keys(definition).forEach(function (key) { 29 | proto[key] = { 30 | value: definition[key], 31 | writable: true 32 | }; 33 | }); 34 | 35 | NewComponent = function (el, attr, id) { 36 | Component.call(this, el, attr, id); 37 | }; 38 | 39 | NewComponent.prototype = Object.create(Component.prototype, proto); 40 | NewComponent.prototype.name = name; 41 | NewComponent.prototype.constructor = NewComponent; 42 | 43 | AFRAME.components[name] = NewComponent; 44 | return NewComponent; 45 | }; 46 | 47 | AFRAME.registerSystem = function (name, definition) { 48 | var NewSystem; 49 | var proto = {}; 50 | 51 | Object.keys(definition).forEach(function (key) { 52 | proto[key] = { 53 | value: definition[key], 54 | writable: true 55 | }; 56 | }); 57 | 58 | NewSystem = function (el, attr, id) { 59 | System.call(this, el, attr, id); 60 | }; 61 | 62 | NewSystem.prototype = Object.create(System.prototype, proto); 63 | NewSystem.prototype.name = name; 64 | NewSystem.prototype.constructor = NewSystem; 65 | 66 | AFRAME.systems[name] = NewSystem; 67 | return NewSystem; 68 | }; 69 | 70 | var fx = function(renderer, scene, cameras) { 71 | this.sceneEl = this; 72 | this.renderTarget = null; 73 | this.renderer = renderer; 74 | this.object3D = scene; 75 | this.cameras = Array.isArray(cameras) ? cameras : [cameras]; 76 | this.components = {}; 77 | this.systems = {}; 78 | this.isPlaying = true; 79 | this.systems.effects = new AFRAME.systems.effects(this) 80 | this.systems.effects.init(); 81 | }; 82 | 83 | fx.prototype = Object.create({}, { 84 | chain: { 85 | value: function(chain) { 86 | var sys = this.systems.effects, self = this; 87 | var oldData = sys.data; 88 | sys.data = chain; 89 | sys.update(oldData); 90 | sys.tick(0,0); 91 | } 92 | }, 93 | 94 | camera: { 95 | set: function(cameras) { 96 | this.cameras = Array.isArray(cameras) ? cameras : [cameras]; 97 | }, 98 | 99 | get: function () { 100 | return this.cameras[0]; 101 | } 102 | }, 103 | 104 | scene: { 105 | set: function(v) { 106 | this.object3D = v; 107 | }, 108 | 109 | get: function () { 110 | return this.object3D; 111 | } 112 | }, 113 | 114 | init: { 115 | value: function(name) { 116 | this.remove(name); 117 | var arr = name.split("__"); 118 | var pro = AFRAME.components[arr[0]]; 119 | if(!pro) return null; 120 | var obj = new pro(this, arr[1]); 121 | if(obj.schema.type || obj.schema.default) { 122 | obj.data = obj.schema.default; 123 | } else { 124 | for(var i in obj.schema) { 125 | obj.data[i] = obj.schema[i].default; 126 | } 127 | } 128 | if(obj.init) obj.init(); 129 | if(obj.update) obj.update({}); 130 | return obj; 131 | } 132 | }, 133 | 134 | update: { 135 | value: function(name, data) { 136 | var obj = this.components[name]; 137 | if(!obj) { obj = this.init(name); } 138 | if(!obj || data === undefined) return; 139 | 140 | var oldData = obj.data, nd = obj.data, schema = obj.schema; 141 | if (obj.schema.type || obj.schema.default) { 142 | obj.data = data; 143 | } else { 144 | oldData = {}; 145 | for(var o in nd) { 146 | oldData[o] = nd[o]; 147 | if (data[o]) nd[o] = data[o]; 148 | } 149 | } 150 | if(obj.update) obj.update(oldData); 151 | } 152 | }, 153 | 154 | remove: { 155 | value: function(name) { 156 | var obj = this.components[name]; 157 | if(obj && obj.remove) { obj.remove(); } 158 | delete this.components[name]; 159 | } 160 | }, 161 | 162 | render: { 163 | value: function(time) { 164 | var behaviors = this.components; 165 | var sys = this.systems.effects; 166 | 167 | var timeDelta = this.time ? time - this.time : 0; 168 | this.time = time; 169 | 170 | for(var b in behaviors) { 171 | var behavior = behaviors[b]; 172 | if (behavior.tick) behavior.tick(time, timeDelta); 173 | } 174 | 175 | sys.tick(time, timeDelta); 176 | sys.cameras = this.cameras; 177 | 178 | for(var b in behaviors) { 179 | var behavior = behaviors[b]; 180 | if (behavior.tock) behavior.tock(time, timeDelta); 181 | } 182 | 183 | sys.tock(time, timeDelta); 184 | } 185 | } 186 | }); 187 | 188 | window.AFRAME.Effects = fx; 189 | } 190 | 191 | require("./systems") 192 | require("./components") 193 | require("./shaders") 194 | -------------------------------------------------------------------------------- /lib/AdaptiveToneMappingPass.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author miibond 3 | * Generate a texture that represents the luminosity of the current scene, adapted over time 4 | * to simulate the optic nerve responding to the amount of light it is receiving. 5 | * Based on a GDC2007 presentation by Wolfgang Engel titled "Post-Processing Pipeline" 6 | * 7 | * Full-screen tone-mapping shader based on http://www.graphics.cornell.edu/~jaf/publications/sig02_paper.pdf 8 | */ 9 | 10 | var LuminosityShader = require("./shaders/LuminosityShader"); 11 | 12 | var CopyShader = require("./shaders/CopyShader") 13 | 14 | var AdaptiveToneMappingPass = module.exports = function ( adaptive, resolution ) { 15 | 16 | THREE.Pass.call( this ); 17 | 18 | this.resolution = ( resolution !== undefined ) ? resolution : 256; 19 | this.needsInit = true; 20 | this.adaptive = adaptive !== undefined ? !! adaptive : true; 21 | 22 | this.luminanceRT = null; 23 | this.previousLuminanceRT = null; 24 | this.currentLuminanceRT = null; 25 | 26 | 27 | var copyShader = CopyShader; 28 | 29 | this.copyUniforms = THREE.UniformsUtils.clone( copyShader.uniforms ); 30 | 31 | this.materialCopy = new THREE.ShaderMaterial( { 32 | 33 | uniforms: this.copyUniforms, 34 | vertexShader: copyShader.vertexShader, 35 | fragmentShader: copyShader.fragmentShader, 36 | blending: THREE.NoBlending, 37 | depthTest: false 38 | 39 | } ); 40 | 41 | this.materialLuminance = new THREE.ShaderMaterial( { 42 | 43 | uniforms: THREE.UniformsUtils.clone( THREE.LuminosityShader.uniforms ), 44 | vertexShader: THREE.LuminosityShader.vertexShader, 45 | fragmentShader: THREE.LuminosityShader.fragmentShader, 46 | blending: THREE.NoBlending 47 | } ); 48 | 49 | this.adaptLuminanceShader = { 50 | defines: { 51 | "MIP_LEVEL_1X1" : ( Math.log( this.resolution ) / Math.log( 2.0 ) ).toFixed( 1 ) 52 | }, 53 | uniforms: { 54 | "lastLum": { value: null }, 55 | "currentLum": { value: null }, 56 | "minLuminance": { value: 0.01 }, 57 | "delta": { value: 0.016 }, 58 | "tau": { value: 1.0 } 59 | }, 60 | vertexShader: [ 61 | "varying vec2 vUv;", 62 | 63 | "void main() {", 64 | 65 | "vUv = uv;", 66 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 67 | 68 | "}" 69 | ].join( '\n' ), 70 | fragmentShader: [ 71 | "varying vec2 vUv;", 72 | 73 | "uniform sampler2D lastLum;", 74 | "uniform sampler2D currentLum;", 75 | "uniform float minLuminance;", 76 | "uniform float delta;", 77 | "uniform float tau;", 78 | 79 | "void main() {", 80 | 81 | "vec4 lastLum = texture2D( lastLum, vUv, MIP_LEVEL_1X1 );", 82 | "vec4 currentLum = texture2D( currentLum, vUv, MIP_LEVEL_1X1 );", 83 | 84 | "float fLastLum = max( minLuminance, lastLum.r );", 85 | "float fCurrentLum = max( minLuminance, currentLum.r );", 86 | 87 | //The adaption seems to work better in extreme lighting differences 88 | //if the input luminance is squared. 89 | "fCurrentLum *= fCurrentLum;", 90 | 91 | // Adapt the luminance using Pattanaik's technique 92 | "float fAdaptedLum = fLastLum + (fCurrentLum - fLastLum) * (1.0 - exp(-delta * tau));", 93 | // "fAdaptedLum = sqrt(fAdaptedLum);", 94 | "gl_FragColor.r = fAdaptedLum;", 95 | "}" 96 | ].join( '\n' ) 97 | }; 98 | 99 | this.materialAdaptiveLum = new THREE.ShaderMaterial( { 100 | 101 | uniforms: THREE.UniformsUtils.clone( this.adaptLuminanceShader.uniforms ), 102 | vertexShader: this.adaptLuminanceShader.vertexShader, 103 | fragmentShader: this.adaptLuminanceShader.fragmentShader, 104 | defines: this.adaptLuminanceShader.defines, 105 | blending: THREE.NoBlending 106 | } ); 107 | 108 | if ( THREE.ToneMapShader === undefined ) 109 | console.error( "THREE.AdaptiveToneMappingPass relies on THREE.ToneMapShader" ); 110 | 111 | this.materialToneMap = new THREE.ShaderMaterial( { 112 | 113 | uniforms: THREE.UniformsUtils.clone( THREE.ToneMapShader.uniforms ), 114 | vertexShader: THREE.ToneMapShader.vertexShader, 115 | fragmentShader: THREE.ToneMapShader.fragmentShader, 116 | blending: THREE.NoBlending 117 | } ); 118 | 119 | this.camera = new THREE.OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); 120 | this.scene = new THREE.Scene(); 121 | 122 | this.quad = new THREE.Mesh( new THREE.PlaneBufferGeometry( 2, 2 ), null ); 123 | this.quad.frustumCulled = false; // Avoid getting clipped 124 | this.scene.add( this.quad ); 125 | 126 | }; 127 | 128 | AdaptiveToneMappingPass.prototype = Object.assign( Object.create( THREE.Pass.prototype ), { 129 | 130 | constructor: THREE.AdaptiveToneMappingPass, 131 | 132 | render: function ( renderer, writeBuffer, readBuffer, delta, maskActive ) { 133 | 134 | if ( this.needsInit ) { 135 | 136 | this.reset( renderer ); 137 | 138 | this.luminanceRT.texture.type = readBuffer.texture.type; 139 | this.previousLuminanceRT.texture.type = readBuffer.texture.type; 140 | this.currentLuminanceRT.texture.type = readBuffer.texture.type; 141 | this.needsInit = false; 142 | 143 | } 144 | 145 | if ( this.adaptive ) { 146 | 147 | //Render the luminance of the current scene into a render target with mipmapping enabled 148 | this.quad.material = this.materialLuminance; 149 | this.materialLuminance.uniforms.tDiffuse.value = readBuffer.texture; 150 | renderer.render( this.scene, this.camera, this.currentLuminanceRT ); 151 | 152 | //Use the new luminance values, the previous luminance and the frame delta to 153 | //adapt the luminance over time. 154 | this.quad.material = this.materialAdaptiveLum; 155 | this.materialAdaptiveLum.uniforms.delta.value = delta; 156 | this.materialAdaptiveLum.uniforms.lastLum.value = this.previousLuminanceRT.texture; 157 | this.materialAdaptiveLum.uniforms.currentLum.value = this.currentLuminanceRT.texture; 158 | renderer.render( this.scene, this.camera, this.luminanceRT ); 159 | 160 | //Copy the new adapted luminance value so that it can be used by the next frame. 161 | this.quad.material = this.materialCopy; 162 | this.copyUniforms.tDiffuse.value = this.luminanceRT.texture; 163 | renderer.render( this.scene, this.camera, this.previousLuminanceRT ); 164 | 165 | } 166 | 167 | return this.luminanceRT.texture; 168 | }, 169 | 170 | reset: function( renderer ) { 171 | 172 | // render targets 173 | if ( this.luminanceRT ) { 174 | 175 | this.luminanceRT.dispose(); 176 | 177 | } 178 | if ( this.currentLuminanceRT ) { 179 | 180 | this.currentLuminanceRT.dispose(); 181 | 182 | } 183 | if ( this.previousLuminanceRT ) { 184 | 185 | this.previousLuminanceRT.dispose(); 186 | 187 | } 188 | 189 | var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }; // was RGB format. changed to RGBA format. see discussion in #8415 / #8450 190 | 191 | this.luminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars ); 192 | this.luminanceRT.texture.name = "AdaptiveToneMappingPass.l"; 193 | this.luminanceRT.texture.generateMipmaps = false; 194 | 195 | this.previousLuminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars ); 196 | this.previousLuminanceRT.texture.name = "AdaptiveToneMappingPass.pl"; 197 | this.previousLuminanceRT.texture.generateMipmaps = false; 198 | 199 | // We only need mipmapping for the current luminosity because we want a down-sampled version to sample in our adaptive shader 200 | pars.minFilter = THREE.LinearMipMapLinearFilter; 201 | this.currentLuminanceRT = new THREE.WebGLRenderTarget( this.resolution, this.resolution, pars ); 202 | this.currentLuminanceRT.texture.name = "AdaptiveToneMappingPass.cl"; 203 | 204 | if ( this.adaptive ) { 205 | 206 | this.materialToneMap.defines[ "ADAPTED_LUMINANCE" ] = ""; 207 | this.materialToneMap.uniforms.luminanceMap.value = this.luminanceRT.texture; 208 | 209 | } 210 | //Put something in the adaptive luminance texture so that the scene can render initially 211 | this.quad.material = new THREE.MeshBasicMaterial( { color: 0x777777 } ); 212 | this.materialLuminance.needsUpdate = true; 213 | this.materialAdaptiveLum.needsUpdate = true; 214 | this.materialToneMap.needsUpdate = true; 215 | // renderer.render( this.scene, this.camera, this.luminanceRT ); 216 | // renderer.render( this.scene, this.camera, this.previousLuminanceRT ); 217 | // renderer.render( this.scene, this.camera, this.currentLuminanceRT ); 218 | 219 | }, 220 | 221 | setAdaptive: function( adaptive ) { 222 | 223 | if ( adaptive ) { 224 | 225 | this.adaptive = true; 226 | this.materialToneMap.defines[ "ADAPTED_LUMINANCE" ] = ""; 227 | this.materialToneMap.uniforms.luminanceMap.value = this.luminanceRT.texture; 228 | 229 | } else { 230 | 231 | this.adaptive = false; 232 | delete this.materialToneMap.defines[ "ADAPTED_LUMINANCE" ]; 233 | this.materialToneMap.uniforms.luminanceMap.value = null; 234 | 235 | } 236 | this.materialToneMap.needsUpdate = true; 237 | 238 | }, 239 | 240 | setAdaptionRate: function( rate ) { 241 | 242 | if ( rate ) { 243 | 244 | this.materialAdaptiveLum.uniforms.tau.value = Math.abs( rate ); 245 | 246 | } 247 | 248 | }, 249 | 250 | setMinLuminance: function( minLum ) { 251 | 252 | if ( minLum ) { 253 | 254 | this.materialToneMap.uniforms.minLuminance.value = minLum; 255 | this.materialAdaptiveLum.uniforms.minLuminance.value = minLum; 256 | 257 | } 258 | 259 | }, 260 | 261 | setMaxLuminance: function( maxLum ) { 262 | 263 | if ( maxLum ) { 264 | 265 | this.materialToneMap.uniforms.maxLuminance.value = maxLum; 266 | 267 | } 268 | 269 | }, 270 | 271 | setAverageLuminance: function( avgLum ) { 272 | 273 | if ( avgLum ) { 274 | 275 | this.materialToneMap.uniforms.averageLuminance.value = avgLum; 276 | 277 | } 278 | 279 | }, 280 | 281 | setMiddleGrey: function( middleGrey ) { 282 | 283 | if ( middleGrey ) { 284 | 285 | this.materialToneMap.uniforms.middleGrey.value = middleGrey; 286 | 287 | } 288 | 289 | }, 290 | 291 | dispose: function() { 292 | 293 | if ( this.luminanceRT ) { 294 | 295 | this.luminanceRT.dispose(); 296 | 297 | } 298 | if ( this.previousLuminanceRT ) { 299 | 300 | this.previousLuminanceRT.dispose(); 301 | 302 | } 303 | if ( this.currentLuminanceRT ) { 304 | 305 | this.currentLuminanceRT.dispose(); 306 | 307 | } 308 | if ( this.materialLuminance ) { 309 | 310 | this.materialLuminance.dispose(); 311 | 312 | } 313 | if ( this.materialAdaptiveLum ) { 314 | 315 | this.materialAdaptiveLum.dispose(); 316 | 317 | } 318 | if ( this.materialCopy ) { 319 | 320 | this.materialCopy.dispose(); 321 | 322 | } 323 | if ( this.materialToneMap ) { 324 | 325 | this.materialToneMap.dispose(); 326 | 327 | } 328 | 329 | } 330 | 331 | } ); 332 | -------------------------------------------------------------------------------- /lib/Detector.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * @author mr.doob / http://mrdoob.com/ 4 | */ 5 | 6 | var Detector = { 7 | 8 | canvas: !! window.CanvasRenderingContext2D, 9 | webgl: ( function () { 10 | 11 | try { 12 | 13 | var canvas = document.createElement( 'canvas' ); return !! ( window.WebGLRenderingContext && ( canvas.getContext( 'webgl' ) || canvas.getContext( 'experimental-webgl' ) ) ); 14 | 15 | } catch ( e ) { 16 | 17 | return false; 18 | 19 | } 20 | 21 | } )(), 22 | workers: !! window.Worker, 23 | fileapi: window.File && window.FileReader && window.FileList && window.Blob, 24 | 25 | getWebGLErrorMessage: function () { 26 | 27 | var element = document.createElement( 'div' ); 28 | element.id = 'webgl-error-message'; 29 | element.style.fontFamily = 'monospace'; 30 | element.style.fontSize = '13px'; 31 | element.style.fontWeight = 'normal'; 32 | element.style.textAlign = 'center'; 33 | element.style.background = '#fff'; 34 | element.style.color = '#000'; 35 | element.style.padding = '1.5em'; 36 | element.style.width = '400px'; 37 | element.style.margin = '5em auto 0'; 38 | 39 | if ( ! this.webgl ) { 40 | 41 | element.innerHTML = window.WebGLRenderingContext ? [ 42 | 'Your graphics card does not seem to support WebGL.
', 43 | 'Find out how to get it here.' 44 | ].join( '\n' ) : [ 45 | 'Your browser does not seem to support WebGL.
', 46 | 'Find out how to get it here.' 47 | ].join( '\n' ); 48 | 49 | } 50 | 51 | return element; 52 | 53 | }, 54 | 55 | addGetWebGLMessage: function ( parameters ) { 56 | 57 | var parent, id, element; 58 | 59 | parameters = parameters || {}; 60 | 61 | parent = parameters.parent !== undefined ? parameters.parent : document.body; 62 | id = parameters.id !== undefined ? parameters.id : 'oldie'; 63 | 64 | element = Detector.getWebGLErrorMessage(); 65 | element.id = id; 66 | 67 | parent.appendChild( element ); 68 | 69 | } 70 | 71 | }; 72 | 73 | // browserify support 74 | if ( typeof module === 'object' ) { 75 | 76 | module.exports = Detector; 77 | 78 | } 79 | -------------------------------------------------------------------------------- /lib/shaders/BlurShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://clara.io 3 | * 4 | * For a horizontal blur, use X_STEP 1, Y_STEP 0 5 | * For a vertical blur, use X_STEP 0, Y_STEP 1 6 | * 7 | */ 8 | 9 | THREE.BlurShader = { 10 | 11 | defines: { 12 | 13 | "KERNEL_RADIUS": 4 14 | 15 | }, 16 | 17 | uniforms: { 18 | 19 | "tDiffuse": { type: "t", value: null }, 20 | "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, 21 | "sampleUvOffsets": { type: "v2v", value: [ new THREE.Vector2( 0, 0 ) ] }, 22 | "sampleWeights": { type: "1fv", value: [ 1.0 ] }, 23 | 24 | }, 25 | 26 | vertexShader: [ 27 | 28 | "#include ", 29 | 30 | "varying vec2 vUv;", 31 | 32 | "void main() {", 33 | 34 | "vUv = uv;", 35 | 36 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 37 | 38 | "}" 39 | 40 | ].join( "\n" ), 41 | 42 | fragmentShader: [ 43 | 44 | "uniform sampler2D tDiffuse;", 45 | "uniform vec2 size;", 46 | 47 | "uniform vec2 sampleUvOffsets[ KERNEL_RADIUS + 1 ];", 48 | "uniform float sampleWeights[ KERNEL_RADIUS + 1 ];", 49 | 50 | "varying vec2 vUv;", 51 | 52 | "void main() {", 53 | 54 | "vec2 invSize = 1.0 / size;", 55 | 56 | "float weightSum = sampleWeights[0];", 57 | "vec4 diffuseSum = texture2D( tDiffuse, vUv ) * weightSum;", 58 | 59 | "for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {", 60 | 61 | "float weight = sampleWeights[i];", 62 | "vec2 sampleUvOffset = sampleUvOffsets[i] * invSize;", 63 | "diffuseSum += ( texture2D( tDiffuse, vUv + sampleUvOffset ) + texture2D( tDiffuse, vUv - sampleUvOffset ) ) * weight;", 64 | "weightSum += 2.0 * weight;", 65 | 66 | "}", 67 | 68 | "gl_FragColor =diffuseSum / weightSum;", 69 | 70 | "}" 71 | 72 | ].join( "\n" ) 73 | 74 | }; 75 | 76 | 77 | THREE.BlurShaderUtils = { 78 | 79 | createSampleWeights: function( kernelRadius, stdDev ) { 80 | 81 | var gaussian = function( x, stdDev ) { 82 | return Math.exp( - ( x*x ) / ( 2.0 * ( stdDev * stdDev ) ) ) / ( Math.sqrt( 2.0 * Math.PI ) * stdDev ); 83 | }; 84 | 85 | var weights = []; 86 | 87 | for( var i = 0; i <= kernelRadius; i ++ ) { 88 | weights.push( gaussian( i, stdDev ) ); 89 | } 90 | 91 | return weights; 92 | }, 93 | 94 | createSampleOffsets: function( kernelRadius, uvIncrement ) { 95 | 96 | var offsets = []; 97 | 98 | for( var i = 0; i <= kernelRadius; i ++ ) { 99 | offsets.push( uvIncrement.clone().multiplyScalar( i ) ); 100 | } 101 | 102 | return offsets; 103 | 104 | }, 105 | 106 | configure: function( material, kernelRadius, stdDev, uvIncrement ) { 107 | 108 | material.defines[ 'KERNEL_RADIUS' ] = kernelRadius; 109 | material.uniforms[ 'sampleUvOffsets' ].value = THREE.BlurShaderUtils.createSampleOffsets( kernelRadius, uvIncrement ); 110 | material.uniforms[ 'sampleWeights' ].value = THREE.BlurShaderUtils.createSampleWeights( kernelRadius, stdDev ); 111 | material.needsUpdate = true; 112 | 113 | } 114 | 115 | }; 116 | -------------------------------------------------------------------------------- /lib/shaders/CopyShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * Full-screen textured quad shader 5 | */ 6 | 7 | var CopyShader = module.exports = { 8 | 9 | uniforms: { 10 | 11 | "tDiffuse": { value: null }, 12 | "opacity": { value: 1.0 } 13 | 14 | }, 15 | 16 | vertexShader: [ 17 | 18 | "varying vec2 vUv;", 19 | 20 | "void main() {", 21 | 22 | "vUv = uv;", 23 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 24 | 25 | "}" 26 | 27 | ].join( "\n" ), 28 | 29 | fragmentShader: [ 30 | 31 | "uniform float opacity;", 32 | 33 | "uniform sampler2D tDiffuse;", 34 | 35 | "varying vec2 vUv;", 36 | 37 | "void main() {", 38 | 39 | "vec4 texel = texture2D( tDiffuse, vUv );", 40 | "gl_FragColor = opacity * texel;", 41 | 42 | "}" 43 | 44 | ].join( "\n" ) 45 | 46 | }; 47 | -------------------------------------------------------------------------------- /lib/shaders/DepthLimitedBlurShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://clara.io 3 | * 4 | * For a horizontal blur, use X_STEP 1, Y_STEP 0 5 | * For a vertical blur, use X_STEP 0, Y_STEP 1 6 | * 7 | * 8 | */ 9 | 10 | // Adapted by wizgrav to pack depth and AO in a single rgba texture 11 | 12 | THREE.BlurShaderUtils = { 13 | 14 | createSampleWeights: function( kernelRadius, stdDev ) { 15 | 16 | var gaussian = function( x, stdDev ) { 17 | return Math.exp( - ( x*x ) / ( 2.0 * ( stdDev * stdDev ) ) ) / ( Math.sqrt( 2.0 * Math.PI ) * stdDev ); 18 | }; 19 | 20 | var weights = []; 21 | 22 | for( var i = 0; i <= kernelRadius; i ++ ) { 23 | weights.push( gaussian( i, stdDev ) ); 24 | } 25 | 26 | return weights; 27 | }, 28 | 29 | createSampleOffsets: function( kernelRadius, uvIncrement ) { 30 | 31 | var offsets = []; 32 | 33 | for( var i = 0; i <= kernelRadius; i ++ ) { 34 | offsets.push( uvIncrement.clone().multiplyScalar( i ) ); 35 | } 36 | 37 | return offsets; 38 | 39 | }, 40 | 41 | configure: function( kernelRadius, stdDev, uvIncrement ) { 42 | return { 43 | 'sampleUvOffsets': THREE.BlurShaderUtils.createSampleOffsets( kernelRadius, uvIncrement ), 44 | 'sampleWeights': THREE.BlurShaderUtils.createSampleWeights( kernelRadius, stdDev ) 45 | } 46 | } 47 | 48 | }; 49 | 50 | 51 | module.exports = function (radius, stdDev, uvIncrement) { 52 | radius = radius || 4; 53 | var config = THREE.BlurShaderUtils.configure(radius, stdDev, uvIncrement ) 54 | return { 55 | defines: { 56 | 57 | "KERNEL_RADIUS": radius, 58 | 59 | }, 60 | 61 | uniforms: { 62 | 63 | "tDiffuse": { type: "t", value: null }, 64 | "size": { type: "v2", value: new THREE.Vector2( 512, 512 ) }, 65 | "sampleUvOffsets": { type: "v2v", value: config.sampleUvOffsets }, 66 | "sampleWeights": { type: "1fv", value: config.sampleWeights }, 67 | "depthCutoff": { type: "f", value: 10 }, 68 | "cameraFar": { type: "f", value: 1 }, 69 | "cameraNear": { type: "f", value: 1000 } 70 | }, 71 | 72 | vertexShader: [ 73 | 74 | "#include ", 75 | 76 | "uniform vec2 size;", 77 | 78 | "varying vec2 vUv;", 79 | "varying vec2 vInvSize;", 80 | 81 | "void main() {", 82 | 83 | "vUv = uv;", 84 | "vInvSize = 1.0 / size;", 85 | 86 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 87 | 88 | "}" 89 | 90 | ].join( "\n" ), 91 | 92 | fragmentShader: [ 93 | 94 | "#include ", 95 | "#include ", 96 | 97 | "uniform sampler2D tDiffuse;", 98 | 99 | "uniform vec2 sampleUvOffsets[ KERNEL_RADIUS + 1 ];", 100 | "uniform float sampleWeights[ KERNEL_RADIUS + 1 ];", 101 | "uniform float depthCutoff;", 102 | "uniform float cameraFar;", 103 | "uniform float cameraNear;", 104 | 105 | "varying vec2 vUv;", 106 | "varying vec2 vInvSize;", 107 | 108 | "float unpackDepth(vec3 pack) {", 109 | " float depth = dot( pack, 1.0 / vec3(1.0, 256.0, 256.0*256.0) );", 110 | " return depth * (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0);", 111 | "}", 112 | 113 | "float getViewZ( const in float depth ) {", 114 | 115 | "return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );", 116 | 117 | "}", 118 | "void main() {", 119 | "vec4 texel = texture2D( tDiffuse, vUv );", 120 | "vec3 orig = texel.xyz;", 121 | "float depth = unpackDepth( orig );", 122 | "if( depth >= ( 1.0 - EPSILON ) ) {", 123 | "discard;", 124 | "}", 125 | "float centerViewZ = -getViewZ( depth );", 126 | "bool rBreak = false, lBreak = false;", 127 | 128 | "float weightSum = sampleWeights[0];", 129 | "float AOSum = texel.a * weightSum;", 130 | 131 | "for( int i = 1; i <= KERNEL_RADIUS; i ++ ) {", 132 | 133 | "float sampleWeight = sampleWeights[i];", 134 | "vec2 sampleUvOffset = sampleUvOffsets[i] * vInvSize;", 135 | 136 | "vec2 sampleUv = vUv + sampleUvOffset;", 137 | "texel = textureVR( tDiffuse, sampleUv );", 138 | "float viewZ = -getViewZ(unpackDepth( texel.xyz ));", 139 | 140 | "if( abs( viewZ - centerViewZ ) > depthCutoff ) rBreak = true;", 141 | 142 | "if( ! rBreak ) {", 143 | "AOSum += texel.a * sampleWeight;", 144 | "weightSum += sampleWeight;", 145 | "}", 146 | 147 | "sampleUv = vUv - sampleUvOffset;", 148 | "texel = textureVR( tDiffuse, sampleUv );", 149 | "viewZ = -getViewZ(unpackDepth( texel.xyz ));", 150 | 151 | "if( abs( viewZ - centerViewZ ) > depthCutoff ) lBreak = true;", 152 | 153 | "if( ! lBreak ) {", 154 | "AOSum += texel.a * sampleWeight;", 155 | "weightSum += sampleWeight;", 156 | "}", 157 | 158 | "}", 159 | 160 | "gl_FragColor = vec4(orig, AOSum / weightSum);", 161 | 162 | "}" 163 | 164 | ].join( "\n" ) 165 | 166 | }; 167 | } -------------------------------------------------------------------------------- /lib/shaders/FXAAShader.js: -------------------------------------------------------------------------------- 1 | 2 | // Adapted from https://github.com/mattdesl/three-shader-fxaa 3 | module.exports = { 4 | uniforms: { 5 | tDiffuse: { type: 't', value: null }, 6 | resolution: { type: 'v2', value: new THREE.Vector2() } 7 | }, 8 | vertexShader: "#define GLSLIFY 1\nvarying vec2 vUv;\n\nvarying vec2 v_rgbNW;\nvarying vec2 v_rgbNE;\nvarying vec2 v_rgbSW;\nvarying vec2 v_rgbSE;\nvarying vec2 v_rgbM;\n\nuniform vec2 resolution;\n\nvoid main() {\n vUv = uv;\n vec2 fragCoord = uv * resolution;\n vec2 inverseVP = 1.0 / resolution.xy;\n v_rgbNW = (fragCoord + vec2(-1.0, -1.0)) * inverseVP;\n v_rgbNE = (fragCoord + vec2(1.0, -1.0)) * inverseVP;\n v_rgbSW = (fragCoord + vec2(-1.0, 1.0)) * inverseVP;\n v_rgbSE = (fragCoord + vec2(1.0, 1.0)) * inverseVP;\n v_rgbM = vec2(fragCoord * inverseVP);\n\n gl_Position = projectionMatrix *\n modelViewMatrix *\n vec4(position,1.0);\n}\n", 9 | fragmentShader: "#define GLSLIFY 1\nvarying vec2 vUv;\n\n//texcoords computed in vertex step\n//to avoid dependent texture reads\nvarying vec2 v_rgbNW;\nvarying vec2 v_rgbNE;\nvarying vec2 v_rgbSW;\nvarying vec2 v_rgbSE;\nvarying vec2 v_rgbM;\n\n//make sure to have a resolution uniform set to the screen size\nuniform vec2 resolution;\nuniform sampler2D tDiffuse;\n\n/**\nBasic FXAA implementation based on the code on geeks3d.com with the\nmodification that the texture2DLod stuff was removed since it's\nunsupported by WebGL.\n\n--\n\nFrom:\nhttps://github.com/mitsuhiko/webgl-meincraft\n\nCopyright (c) 2011 by Armin Ronacher.\n\nSome rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are\nmet:\n\n * Redistributions of source code must retain the above copyright\n notice, this list of conditions and the following disclaimer.\n\n * Redistributions in binary form must reproduce the above\n copyright notice, this list of conditions and the following\n disclaimer in the documentation and/or other materials provided\n with the distribution.\n\n * The names of the contributors may not be used to endorse or\n promote products derived from this software without specific\n prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\nOWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\nSPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\nLIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n*/\n\n#ifndef FXAA_REDUCE_MIN\n #define FXAA_REDUCE_MIN (1.0/ 128.0)\n#endif\n#ifndef FXAA_REDUCE_MUL\n #define FXAA_REDUCE_MUL (1.0 / 8.0)\n#endif\n#ifndef FXAA_SPAN_MAX\n #define FXAA_SPAN_MAX 8.0\n#endif\n\n//optimized version for mobile, where dependent \n//texture reads can be a bottleneck\nvec4 fxaa_1540259130(sampler2D tex, vec2 fragCoord, vec2 resolution,\n vec2 v_rgbNW, vec2 v_rgbNE, \n vec2 v_rgbSW, vec2 v_rgbSE, \n vec2 v_rgbM) {\n vec4 color;\n mediump vec2 inverseVP = vec2(1.0 / resolution.x, 1.0 / resolution.y);\n vec3 rgbNW = texture2D(tex, v_rgbNW).xyz;\n vec3 rgbNE = texture2D(tex, v_rgbNE).xyz;\n vec3 rgbSW = texture2D(tex, v_rgbSW).xyz;\n vec3 rgbSE = texture2D(tex, v_rgbSE).xyz;\n vec4 texColor = texture2D(tex, v_rgbM);\n vec3 rgbM = texColor.xyz;\n vec3 luma = vec3(0.299, 0.587, 0.114);\n float lumaNW = dot(rgbNW, luma);\n float lumaNE = dot(rgbNE, luma);\n float lumaSW = dot(rgbSW, luma);\n float lumaSE = dot(rgbSE, luma);\n float lumaM = dot(rgbM, luma);\n float lumaMin = min(lumaM, min(min(lumaNW, lumaNE), min(lumaSW, lumaSE)));\n float lumaMax = max(lumaM, max(max(lumaNW, lumaNE), max(lumaSW, lumaSE)));\n \n mediump vec2 dir;\n dir.x = -((lumaNW + lumaNE) - (lumaSW + lumaSE));\n dir.y = ((lumaNW + lumaSW) - (lumaNE + lumaSE));\n \n float dirReduce = max((lumaNW + lumaNE + lumaSW + lumaSE) *\n (0.25 * FXAA_REDUCE_MUL), FXAA_REDUCE_MIN);\n \n float rcpDirMin = 1.0 / (min(abs(dir.x), abs(dir.y)) + dirReduce);\n dir = min(vec2(FXAA_SPAN_MAX, FXAA_SPAN_MAX),\n max(vec2(-FXAA_SPAN_MAX, -FXAA_SPAN_MAX),\n dir * rcpDirMin)) * inverseVP;\n \n vec3 rgbA = 0.5 * (\n texture2D(tex, fragCoord * inverseVP + dir * (1.0 / 3.0 - 0.5)).xyz +\n texture2D(tex, fragCoord * inverseVP + dir * (2.0 / 3.0 - 0.5)).xyz);\n vec3 rgbB = rgbA * 0.5 + 0.25 * (\n texture2D(tex, fragCoord * inverseVP + dir * -0.5).xyz +\n texture2D(tex, fragCoord * inverseVP + dir * 0.5).xyz);\n\n float lumaB = dot(rgbB, luma);\n if ((lumaB < lumaMin) || (lumaB > lumaMax))\n color = vec4(rgbA, texColor.a);\n else\n color = vec4(rgbB, texColor.a);\n return color;\n}\n\nvoid main() {\n vec2 fragCoord = vUv * resolution; \n gl_FragColor = fxaa_1540259130(tDiffuse, fragCoord, resolution, v_rgbNW, v_rgbNE, v_rgbSW, v_rgbSE, v_rgbM);\n}\n" 10 | } 11 | 12 | -------------------------------------------------------------------------------- /lib/shaders/LuminosityHighPassShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://clara.io/ 3 | * 4 | * Luminosity 5 | * http://en.wikipedia.org/wiki/Luminosity 6 | */ 7 | 8 | module.exports = { 9 | 10 | shaderID: "luminosityHighPass", 11 | 12 | uniforms: { 13 | 14 | "tDiffuse": { type: "t", value: null }, 15 | "luminosityThreshold": { type: "f", value: 1.0 }, 16 | "smoothWidth": { type: "f", value: 1.0 }, 17 | "defaultColor": { type: "c", value: new THREE.Color( 0x000000 ) }, 18 | "defaultOpacity": { type: "f", value: 0.0 } 19 | 20 | }, 21 | 22 | vertexShader: [ 23 | 24 | "varying vec2 vUv;", 25 | 26 | "void main() {", 27 | 28 | "vUv = uv;", 29 | 30 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 31 | 32 | "}" 33 | 34 | ].join("\n"), 35 | 36 | fragmentShader: [ 37 | 38 | "uniform sampler2D tDiffuse;", 39 | "uniform vec3 defaultColor;", 40 | "uniform float defaultOpacity;", 41 | "uniform float luminosityThreshold;", 42 | "uniform float smoothWidth;", 43 | 44 | "varying vec2 vUv;", 45 | 46 | "void main() {", 47 | 48 | "vec4 texel = texture2D( tDiffuse, vUv );", 49 | 50 | "vec3 luma = vec3( 0.299, 0.587, 0.114 );", 51 | 52 | "float v = dot( texel.xyz, luma );", 53 | 54 | "vec4 outputColor = vec4( defaultColor.rgb, defaultOpacity );", 55 | 56 | "float alpha = smoothstep( luminosityThreshold, luminosityThreshold + smoothWidth, v );", 57 | 58 | "gl_FragColor = mix( outputColor, texel, alpha );", 59 | 60 | "}" 61 | 62 | ].join("\n") 63 | 64 | }; 65 | -------------------------------------------------------------------------------- /lib/shaders/LuminosityShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author alteredq / http://alteredqualia.com/ 3 | * 4 | * Luminosity 5 | * http://en.wikipedia.org/wiki/Luminosity 6 | */ 7 | 8 | module.exports = { 9 | 10 | uniforms: { 11 | 12 | "tDiffuse": { value: null } 13 | 14 | }, 15 | 16 | vertexShader: [ 17 | 18 | "varying vec2 vUv;", 19 | 20 | "void main() {", 21 | 22 | "vUv = uv;", 23 | 24 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 25 | 26 | "}" 27 | 28 | ].join( "\n" ), 29 | 30 | fragmentShader: [ 31 | 32 | "uniform sampler2D tDiffuse;", 33 | 34 | "varying vec2 vUv;", 35 | 36 | "void main() {", 37 | 38 | "vec4 texel = texture2D( tDiffuse, vUv );", 39 | 40 | "vec3 luma = vec3( 0.299, 0.587, 0.114 );", 41 | 42 | "float v = dot( texel.xyz, luma );", 43 | 44 | "gl_FragColor = vec4( v, v, v, texel.w );", 45 | 46 | "}" 47 | 48 | ].join( "\n" ) 49 | 50 | }; 51 | -------------------------------------------------------------------------------- /lib/shaders/SAOShader.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author bhouston / http://clara.io/ 3 | * 4 | * Scalable Ambient Occlusion 5 | * 6 | */ 7 | 8 | module.exports = function (isFirst) { 9 | return { 10 | defines: {}, 11 | 12 | uniforms: { 13 | 14 | "tDepth": { type: "t", value: null }, 15 | 16 | "cameraNear": { type: "f", value: 1 }, 17 | "cameraFar": { type: "f", value: 100 }, 18 | "cameraProjectionMatrix": { type: "m4", value: new THREE.Matrix4() }, 19 | "cameraInverseProjectionMatrix": { type: "m4", value: new THREE.Matrix4() }, 20 | 21 | "scale": { type: "f", value: 1.0 }, 22 | "bias": { type: "f", value: 0.5 }, 23 | 24 | "minResolution": { type: "f", value: 0.0 }, 25 | "kernelRadius": { type: "f", value: 0.5 }, 26 | "randomSeed": { type: "f", value: 0.0 }, 27 | "maxDepth": { type: "f", value: 1.0 } 28 | }, 29 | 30 | vertexShader: [ 31 | 32 | "varying vec2 vUv;", 33 | "void main() {", 34 | 35 | "vUv = uv;", 36 | 37 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 38 | 39 | "}" 40 | 41 | ].join( "\n" ), 42 | 43 | fragmentShader: [ 44 | 45 | // total number of samples at each fragment", 46 | 47 | "#include ", 48 | "#include ", 49 | 50 | "varying vec2 vUv;", 51 | 52 | "uniform sampler2D tDepth;", 53 | 54 | "uniform float cameraNear;", 55 | "uniform float cameraFar;", 56 | "uniform mat4 cameraProjectionMatrix;", 57 | "uniform mat4 cameraInverseProjectionMatrix;", 58 | 59 | "uniform float scale;", 60 | "uniform float intensity;", 61 | "uniform float bias;", 62 | "uniform float kernelRadius;", 63 | "uniform float minResolution;", 64 | "uniform float randomSeed;", 65 | "uniform float maxDepth;", 66 | 67 | 68 | "float unpackDepth(vec3 pack) {", 69 | " float depth = dot( pack, 1.0 / vec3(1.0, 256.0, 256.0*256.0) );", 70 | " return depth * (256.0*256.0*256.0) / (256.0*256.0*256.0 - 1.0);", 71 | "}", 72 | 73 | "vec3 packDepth(float depth) {", 74 | " float depthVal = depth * (256.0*256.0*256.0 - 1.0) / (256.0*256.0*256.0);", 75 | " vec4 encode = fract( depthVal * vec4(1.0, 256.0, 256.0*256.0, 256.0*256.0*256.0) );", 76 | " return encode.xyz - encode.yzw / 256.0 + 1.0/512.0;", 77 | "}", 78 | 79 | 80 | "float getViewZ( const in float depth ) {", 81 | 82 | "return perspectiveDepthToViewZ( depth, cameraNear, cameraFar );", 83 | 84 | "}", 85 | 86 | "vec3 getViewPosition( const in vec2 screenPosition, const in float depth, const in float viewZ ) {", 87 | 88 | "float clipW = cameraProjectionMatrix[2][3] * viewZ + cameraProjectionMatrix[3][3];", 89 | "vec4 clipPosition = vec4( ( vec3( screenPosition, depth ) - 0.5 ) * 2.0, 1.0 );", 90 | "clipPosition *= clipW;", // unprojection. 91 | "return ( cameraInverseProjectionMatrix * clipPosition ).xyz;", 92 | 93 | "}", 94 | 95 | "vec3 getViewNormal( const in vec3 viewPosition, const in vec2 screenPosition ) {", 96 | 97 | "return normalize( cross( dFdx( viewPosition ), dFdy( viewPosition ) ) );", 98 | 99 | "}", 100 | 101 | "float scaleDividedByCameraFar;", 102 | "float minResolutionMultipliedByCameraFar;", 103 | 104 | "float getOcclusion( const in vec3 centerViewPosition, const in vec3 centerViewNormal, const in vec3 sampleViewPosition ) {", 105 | 106 | "vec3 viewDelta = sampleViewPosition - centerViewPosition;", 107 | "float viewDistance = length( viewDelta );", 108 | "float scaledScreenDistance = scaleDividedByCameraFar * viewDistance;", 109 | "return max(0.0, (dot(centerViewNormal, viewDelta) - minResolutionMultipliedByCameraFar) / scaledScreenDistance - bias) / (1.0 + pow2( scaledScreenDistance ) );", 110 | 111 | "}", 112 | 113 | // moving costly divides into consts 114 | "const float ANGLE_STEP = PI2 * RINGS / SAMPLES;", 115 | "const float INV_NUM_SAMPLES = 1.0 / SAMPLES;", 116 | 117 | "float getAmbientOcclusion( const in vec3 centerViewPosition) {", 118 | 119 | // precompute some variables require in getOcclusion. 120 | "scaleDividedByCameraFar = scale;", 121 | "minResolutionMultipliedByCameraFar = minResolution * cameraFar;", 122 | "vec3 centerViewNormal = getViewNormal( centerViewPosition, vUv );", 123 | 124 | // jsfiddle that shows sample pattern: https://jsfiddle.net/a16ff1p7/ 125 | "float angle = rand( vUv + randomSeed ) * PI2;", 126 | "vec2 radius = vec2( kernelRadius * INV_NUM_SAMPLES );", 127 | "vec2 radiusStep = radius;", 128 | "float occlusionSum = 0.;", 129 | "float weightSum = 0.;", 130 | "for( int i = 0; i < int(SAMPLES); i ++ ) {", 131 | "vec2 sampleUv = vUv + vec2( cos( angle ), sin( angle ) ) * radius;", 132 | "radius += radiusStep;", 133 | "angle += ANGLE_STEP;", 134 | 135 | "float sampleDepth = textureVR( tDepth, sampleUv ).x;", 136 | "if( sampleDepth >= ( 1.0 - EPSILON ) ) {", 137 | "continue;", 138 | "}", 139 | 140 | "float sampleViewZ = getViewZ( sampleDepth );", 141 | "vec3 sampleViewPosition = getViewPosition( sampleUv, sampleDepth, sampleViewZ );", 142 | "occlusionSum += getOcclusion( centerViewPosition, centerViewNormal, sampleViewPosition );", 143 | "weightSum += 1.0;", 144 | 145 | "}", 146 | 147 | "if( weightSum == 0.0 ) discard;", 148 | "return occlusionSum / weightSum;", 149 | 150 | "}", 151 | 152 | 153 | "void main() {", 154 | "vec4 texel = texture2D( tDepth, vUv );", 155 | "float centerDepth = texel.x;", 156 | 157 | "if( centerDepth >= ( maxDepth - EPSILON ) ) {", 158 | "discard;", 159 | "}", 160 | 161 | "float centerViewZ = getViewZ( centerDepth );", 162 | "vec3 viewPosition = getViewPosition( vUv, centerDepth, centerViewZ );", 163 | 164 | "gl_FragColor = vec4(packDepth(texel.x), getAmbientOcclusion( viewPosition));", 165 | "}" 166 | 167 | ].join( "\n" ) 168 | 169 | }; 170 | } -------------------------------------------------------------------------------- /lib/shaders/ShaderGodRays.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author huwb / http://huwbowles.com/ 3 | * 4 | * God-rays (crepuscular rays) 5 | * 6 | * Similar implementation to the one used by Crytek for CryEngine 2 [Sousa2008]. 7 | * Blurs a mask generated from the depth map along radial lines emanating from the light 8 | * source. The blur repeatedly applies a blur filter of increasing support but constant 9 | * sample count to produce a blur filter with large support. 10 | * 11 | * My implementation performs 3 passes, similar to the implementation from Sousa. I found 12 | * just 6 samples per pass produced acceptible results. The blur is applied three times, 13 | * with decreasing filter support. The result is equivalent to a single pass with 14 | * 6*6*6 = 216 samples. 15 | * 16 | * References: 17 | * 18 | * Sousa2008 - Crysis Next Gen Effects, GDC2008, http://www.crytek.com/sites/default/files/GDC08_SousaT_CrysisEffects.ppt 19 | */ 20 | 21 | module.exports = { 22 | 23 | /** 24 | * The god-ray generation shader. 25 | * 26 | * First pass: 27 | * 28 | * The input is the depth map. I found that the output from the 29 | * THREE.MeshDepthMaterial material was directly suitable without 30 | * requiring any treatment whatsoever. 31 | * 32 | * The depth map is blurred along radial lines towards the "sun". The 33 | * output is written to a temporary render target (I used a 1/4 sized 34 | * target). 35 | * 36 | * Pass two & three: 37 | * 38 | * The results of the previous pass are re-blurred, each time with a 39 | * decreased distance between samples. 40 | */ 41 | uniforms: { 42 | 43 | tInput: { 44 | value: null 45 | }, 46 | fStepSize: { 47 | value: 1.0 48 | }, 49 | vSunPositionScreenSpace: { 50 | value: new THREE.Vector3( 0.5, 0.5, 0. ) 51 | }, 52 | uvrb: { 53 | value: new THREE.Vector4() 54 | } 55 | 56 | }, 57 | 58 | vertexShader: [ 59 | 60 | "varying vec2 vUv;", 61 | 62 | "void main() {", 63 | 64 | "vUv = uv;", 65 | "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );", 66 | 67 | "}" 68 | 69 | ].join( "\n" ), 70 | 71 | fragmentShader: [ 72 | 73 | "#define TAPS_PER_PASS 6.0", 74 | 75 | "varying vec2 vUv;", 76 | 77 | "uniform sampler2D tInput;", 78 | 79 | "uniform vec3 vSunPositionScreenSpace;", 80 | "uniform float fStepSize;", // filter step size 81 | "uniform vec4 uvrb;", 82 | "vec2 uvr(vec2 uv) { return vec2(clamp(uv.x * uvrb.x + uvrb.y, uvrb.z, uvrb.w), uv.y); }", 83 | 84 | "void main() {", 85 | 86 | // delta from current pixel to "sun" position 87 | 88 | "vec2 delta = vSunPositionScreenSpace.xy - vUv;", 89 | "float dist = length( delta );", 90 | 91 | // Step vector (uv space) 92 | 93 | "vec2 stepv = fStepSize * delta / dist;", 94 | 95 | // Number of iterations between pixel and sun 96 | 97 | "float iters = dist/fStepSize;", 98 | 99 | "vec2 uv = uvr(vUv).xy;", 100 | "float col = 0.0;", 101 | 102 | // This breaks ANGLE in Chrome 22 103 | // - see http://code.google.com/p/chromium/issues/detail?id=153105 104 | 105 | /* 106 | // Unrolling didnt do much on my hardware (ATI Mobility Radeon 3450), 107 | // so i've just left the loop 108 | 109 | "for ( float i = 0.0; i < TAPS_PER_PASS; i += 1.0 ) {", 110 | 111 | // Accumulate samples, making sure we dont walk past the light source. 112 | 113 | // The check for uv.y < 1 would not be necessary with "border" UV wrap 114 | // mode, with a black border colour. I don't think this is currently 115 | // exposed by three.js. As a result there might be artifacts when the 116 | // sun is to the left, right or bottom of screen as these cases are 117 | // not specifically handled. 118 | 119 | "col += ( i <= iters && uv.y < 1.0 ? texture2D( tInput, uvr(uv) ).r : 0.0 );", 120 | "uv += stepv;", 121 | 122 | "}", 123 | */ 124 | 125 | // Unrolling loop manually makes it work in ANGLE 126 | 127 | "if ( 0.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uvr(uv) ).r;", 128 | "uv += stepv;", 129 | 130 | "if ( 1.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uvr(uv) ).r;", 131 | "uv += stepv;", 132 | 133 | "if ( 2.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uvr(uv) ).r;", 134 | "uv += stepv;", 135 | 136 | "if ( 3.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uvr(uv) ).r;", 137 | "uv += stepv;", 138 | 139 | "if ( 4.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uvr(uv) ).r;", 140 | "uv += stepv;", 141 | 142 | "if ( 5.0 <= iters && uv.y < 1.0 ) col += texture2D( tInput, uvr(uv) ).r;", 143 | "uv += stepv;", 144 | 145 | // Should technically be dividing by 'iters', but 'TAPS_PER_PASS' smooths out 146 | // objectionable artifacts, in particular near the sun position. The side 147 | // effect is that the result is darker than it should be around the sun, as 148 | // TAPS_PER_PASS is greater than the number of samples actually accumulated. 149 | // When the result is inverted (in the shader 'godrays_combine', this produces 150 | // a slight bright spot at the position of the sun, even when it is occluded. 151 | 152 | "gl_FragColor = vec4( col/TAPS_PER_PASS );", 153 | "gl_FragColor.a = 1.0;", 154 | 155 | "}" 156 | 157 | ].join( "\n" ) 158 | 159 | } -------------------------------------------------------------------------------- /lib/stats.min.js: -------------------------------------------------------------------------------- 1 | // stats.js - http://github.com/mrdoob/stats.js 2 | var Stats=function(){function h(a){c.appendChild(a.dom);return a}function k(a){for(var d=0;de+1E3&&(r.update(1E3*a/(c-e),100),e=c,a=0,t)){var d=performance.memory;t.update(d.usedJSHeapSize/1048576,d.jsHeapSizeLimit/1048576)}return c},update:function(){g=this.end()},domElement:c,setMode:k}}; 4 | Stats.Panel=function(h,k,l){var c=Infinity,g=0,e=Math.round,a=e(window.devicePixelRatio||1),r=80*a,f=48*a,t=3*a,u=2*a,d=3*a,m=15*a,n=74*a,p=30*a,q=document.createElement("canvas");q.width=r;q.height=f;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,f);b.fillStyle=k;b.fillText(h,t,u);b.fillRect(d,m,n,p);b.fillStyle=l;b.globalAlpha=.9;b.fillRect(d,m,n,p);return{dom:q,update:function(f, 5 | v){c=Math.min(c,f);g=Math.max(g,f);b.fillStyle=l;b.globalAlpha=1;b.fillRect(0,0,r,m);b.fillStyle=k;b.fillText(e(f)+" "+h+" ("+e(c)+"-"+e(g)+")",t,u);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,e((1-f/v)*p))}}};"object"===typeof module&&(module.exports=Stats); 6 | -------------------------------------------------------------------------------- /lut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizgrav/aframe-effects/634940eb38588f20ae1be5cc572a2747723d7ad5/lut.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aframe-effects", 3 | "version": "0.8.1", 4 | "description": "A VR-Ready Post processing framework for A-Frame and/or Threejs", 5 | "main": "./index.js", 6 | "local-web-server": { 7 | "port": 8100, 8 | "forbid": "*.json" 9 | }, 10 | "scripts": { 11 | "dist": "webpack index.js dist/aframe-effects.js && uglifyjs dist/aframe-effects.js -o dist/aframe-effects.min.js --source-map dist/afrane-effects.min.js.map", 12 | "server": "ws" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/wizgrav/aframe-effects.git" 17 | }, 18 | "keywords": [ 19 | "aframe", 20 | "webgl", 21 | "grading", 22 | "postprocessing", 23 | "effect", 24 | "bloom", 25 | "outline", 26 | "sobel", 27 | "freichen", 28 | "edge", 29 | "colors", 30 | "ssao", 31 | "ambient", 32 | "depth", 33 | "occlusion", 34 | "fxaa", 35 | "antialiasing", 36 | "godrays", 37 | "sunshafts", 38 | "three", 39 | "threejs", 40 | "uber", 41 | "shader", 42 | "fusion", 43 | "grain", 44 | "film", 45 | "fuse", 46 | "tiled", 47 | "forward", 48 | "lighting", 49 | "forward+" 50 | ], 51 | "author": "Yannis Gravezas ", 52 | "license": "MIT", 53 | "bugs": { 54 | "url": "https://github.com/wizgrav/aframe-effects/issues" 55 | }, 56 | "homepage": "https://github.com/wizgrav/aframe-effects#readme", 57 | "devDependencies": { 58 | "webpack": "^1.13.0", 59 | "uglifyjs": "^2.4.10", 60 | "local-web-server": "^2.6.0" 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /screen.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wizgrav/aframe-effects/634940eb38588f20ae1be5cc572a2747723d7ad5/screen.png -------------------------------------------------------------------------------- /shaders/index.js: -------------------------------------------------------------------------------- 1 | THREE.ShaderChunk[ 'lights_pars_maps' ] += [ 2 | '#if defined TILED_FORWARD', 3 | 'uniform vec4 tileData;', 4 | 'uniform sampler2D tileTexture;', 5 | 'uniform sampler2D lightTexture;', 6 | '#endif' 7 | ].join( '\n' ); 8 | 9 | THREE.ShaderChunk[ 'lights_fragment_maps' ] += [ 10 | '', 11 | '#if defined TILED_FORWARD', 12 | 'vec2 tUv = floor(gl_FragCoord.xy / tileData.xy * 32.) / 32. + tileData.zw;', 13 | 'vec4 tile = texture2D(tileTexture, tUv);', 14 | 'for (int i=0; i < 4; i++) {', 15 | ' float tileVal = tile.x * 255.;', 16 | ' tile.xyzw = tile.yzwx;', 17 | ' if(tileVal == 0.){ continue; }', 18 | ' float tileDiv = 128.;', 19 | ' for (int j=0; j < 8; j++) {', 20 | ' if (tileVal < tileDiv) { tileDiv *= 0.5; continue; }', 21 | ' tileVal -= tileDiv;', 22 | ' tileDiv *= 0.5;', 23 | ' PointLight pointlight;', 24 | ' float uvx = (float(8 * i + j) + 0.5) / 32.;', 25 | ' vec4 lightData = texture2D(lightTexture, vec2(uvx, 0.));', 26 | ' vec4 lightColor = texture2D(lightTexture, vec2(uvx, 1.));', 27 | ' pointlight.position = lightData.xyz;', 28 | ' pointlight.distance = lightData.w;', 29 | ' pointlight.color = lightColor.rgb;', 30 | ' pointlight.decay = lightColor.a;', 31 | ' getPointDirectLightIrradiance( pointlight, geometry, directLight );', 32 | ' RE_Direct( directLight, geometry, material, reflectedLight );', 33 | ' }', 34 | '}', 35 | '#endif' 36 | ].join( '\n' ); 37 | 38 | var utils = AFRAME.utils; 39 | 40 | var CubeLoader = new THREE.CubeTextureLoader(); 41 | var texturePromises = {}; 42 | 43 | /** 44 | * Standard (physically-based) shader with tiled forward lighting. 45 | */ 46 | AFRAME.registerShader('standard-fx', { 47 | schema: { 48 | ambientOcclusionMap: {type: 'map'}, 49 | ambientOcclusionMapIntensity: {default: 1}, 50 | ambientOcclusionTextureOffset: {type: 'vec2'}, 51 | ambientOcclusionTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}}, 52 | 53 | color: {type: 'color'}, 54 | 55 | displacementMap: {type: 'map'}, 56 | displacementScale: {default: 1}, 57 | displacementBias: {default: 0.5}, 58 | displacementTextureOffset: {type: 'vec2'}, 59 | displacementTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}}, 60 | emissive: {type: 'color', default: '#000'}, 61 | emissiveIntensity: {default: 1}, 62 | envMap: {default: ''}, 63 | 64 | fog: {default: true}, 65 | height: {default: 256}, 66 | 67 | metalness: {default: 0.0, min: 0.0, max: 1.0}, 68 | metalnessMap: {type: 'map'}, 69 | metalnessTextureOffset: {type: 'vec2'}, 70 | metalnessTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}}, 71 | 72 | normalMap: {type: 'map'}, 73 | normalScale: {type: 'vec2', default: {x: 1, y: 1}}, 74 | normalTextureOffset: {type: 'vec2'}, 75 | normalTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}}, 76 | 77 | offset: {type: 'vec2', default: {x: 0, y: 0}}, 78 | repeat: {type: 'vec2', default: {x: 1, y: 1}}, 79 | 80 | roughness: {default: 0.5, min: 0.0, max: 1.0}, 81 | roughnessMap: {type: 'map'}, 82 | roughnessTextureOffset: {type: 'vec2'}, 83 | roughnessTextureRepeat: {type: 'vec2', default: {x: 1, y: 1}}, 84 | 85 | sphericalEnvMap: {type: 'map'}, 86 | src: {type: 'map'}, 87 | width: {default: 512}, 88 | wireframe: {default: false}, 89 | wireframeLinewidth: {default: 2} 90 | }, 91 | 92 | /** 93 | * Initializes the shader. 94 | * Adds a reference from the scene to this entity as the camera. 95 | */ 96 | init: function (data) { 97 | this.material = new THREE.MeshStandardMaterial(getMaterialData(data)); 98 | utils.material.updateMap(this, data); 99 | if (data.normalMap) { utils.material.updateDistortionMap('normal', this, data); } 100 | if (data.displacementMap) { utils.material.updateDistortionMap('displacement', this, data); } 101 | if (data.ambientOcclusionMap) { utils.material.updateDistortionMap('ambientOcclusion', this, data); } 102 | if (data.metalnessMap) { utils.material.updateDistortionMap('metalness', this, data); } 103 | if (data.roughnessMap) { utils.material.updateDistortionMap('roughness', this, data); } 104 | this.updateEnvMap(data); 105 | this.material.onBeforeCompile = function ( shader ) { 106 | shader.uniforms.tileData = State.tileData; 107 | shader.uniforms.tileTexture = State.tileTexture; 108 | shader.uniforms.lightTexture = State.lightTexture; 109 | shader.defines[ 'TILED_FORWARD' ] = 1; 110 | } 111 | }, 112 | 113 | update: function (data) { 114 | this.updateMaterial(data); 115 | utils.material.updateMap(this, data); 116 | if (data.normalMap) { utils.material.updateDistortionMap('normal', this, data); } 117 | if (data.displacementMap) { utils.material.updateDistortionMap('displacement', this, data); } 118 | if (data.ambientOcclusionMap) { utils.material.updateDistortionMap('ambientOcclusion', this, data); } 119 | if (data.metalnessMap) { utils.material.updateDistortionMap('metalness', this, data); } 120 | if (data.roughnessMap) { utils.material.updateDistortionMap('roughness', this, data); } 121 | this.updateEnvMap(data); 122 | }, 123 | 124 | /** 125 | * Updating existing material. 126 | * 127 | * @param {object} data - Material component data. 128 | * @returns {object} Material. 129 | */ 130 | updateMaterial: function (data) { 131 | var material = this.material; 132 | data = getMaterialData(data); 133 | Object.keys(data).forEach(function (key) { 134 | material[key] = data[key]; 135 | }); 136 | }, 137 | 138 | /** 139 | * Handle environment cubemap. Textures are cached in texturePromises. 140 | */ 141 | updateEnvMap: function (data) { 142 | var self = this; 143 | var material = this.material; 144 | var envMap = data.envMap; 145 | var sphericalEnvMap = data.sphericalEnvMap; 146 | 147 | // No envMap defined or already loading. 148 | if ((!envMap && !sphericalEnvMap) || this.isLoadingEnvMap) { 149 | material.envMap = null; 150 | material.needsUpdate = true; 151 | return; 152 | } 153 | this.isLoadingEnvMap = true; 154 | 155 | // if a spherical env map is defined then use it. 156 | if (sphericalEnvMap) { 157 | this.el.sceneEl.systems.material.loadTexture(sphericalEnvMap, {src: sphericalEnvMap}, function textureLoaded (texture) { 158 | self.isLoadingEnvMap = false; 159 | texture.mapping = THREE.SphericalReflectionMapping; 160 | material.envMap = texture; 161 | utils.material.handleTextureEvents(self.el, texture); 162 | material.needsUpdate = true; 163 | }); 164 | return; 165 | } 166 | 167 | // Another material is already loading this texture. Wait on promise. 168 | if (texturePromises[envMap]) { 169 | texturePromises[envMap].then(function (cube) { 170 | self.isLoadingEnvMap = false; 171 | material.envMap = cube; 172 | utils.material.handleTextureEvents(self.el, cube); 173 | material.needsUpdate = true; 174 | }); 175 | return; 176 | } 177 | 178 | // Material is first to load this texture. Load and resolve texture. 179 | texturePromises[envMap] = new Promise(function (resolve) { 180 | utils.srcLoader.validateCubemapSrc(envMap, function loadEnvMap (urls) { 181 | CubeLoader.load(urls, function (cube) { 182 | // Texture loaded. 183 | self.isLoadingEnvMap = false; 184 | material.envMap = cube; 185 | utils.material.handleTextureEvents(self.el, cube); 186 | resolve(cube); 187 | }); 188 | }); 189 | }); 190 | } 191 | }); 192 | 193 | /** 194 | * Builds and normalize material data, normalizing stuff along the way. 195 | * 196 | * @param {object} data - Material data. 197 | * @returns {object} data - Processed material data. 198 | */ 199 | function getMaterialData (data) { 200 | var newData = { 201 | color: new THREE.Color(data.color), 202 | emissive: new THREE.Color(data.emissive), 203 | emissiveIntensity: data.emissiveIntensity, 204 | fog: data.fog, 205 | metalness: data.metalness, 206 | roughness: data.roughness, 207 | wireframe: data.wireframe, 208 | wireframeLinewidth: data.wireframeLinewidth 209 | }; 210 | 211 | if (data.normalMap) { newData.normalScale = data.normalScale; } 212 | 213 | if (data.ambientOcclusionMap) { newData.aoMapIntensity = data.ambientOcclusionMapIntensity; } 214 | 215 | if (data.displacementMap) { 216 | newData.displacementScale = data.displacementScale; 217 | newData.displacementBias = data.displacementBias; 218 | } 219 | 220 | return newData; 221 | } -------------------------------------------------------------------------------- /sponza/copyright.txt: -------------------------------------------------------------------------------- 1 | http://hdri.cgtechniques.com/~sponza/files/ 2 | 3 | Sponza modeled by Marko Dabrovic, with UVs and crack errors fixed by Kenzie Lamar at Vicarious Visions. 4 | Bump maps painted by Morgan McGuire. 5 | -------------------------------------------------------------------------------- /sponza/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Hello SSAO! 7 | 8 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 25 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 40 |
41 | 42 | 43 | -------------------------------------------------------------------------------- /systems/README.md: -------------------------------------------------------------------------------- 1 | Effects system 2 | ===================== 3 | 4 | The effects system is the coordinator and final composer of the post processing pipeline. Its schema is a single array property which defines the order of the blending chain. 5 | 6 | The elements in the array can be names of components, which should be already attached somewhere in the scene so they can get picked up. They can also be ids of elements that define script effects. 7 | 8 | 9 | 10 | The system fuses together as many fusable components as it can and creates a chain of passes. In the final composing step the chain is passed the scene's renderTarget as the initial input and full sized render targets are ping ponged and finally outputs to the canvas. 11 | 12 | Effect components must register and unregister to make the system aware of them. 13 | 14 | ``` 15 | init: function() { 16 | this.el.sceneEl.systems.effects.register(this); 17 | }, 18 | 19 | remove: function () { 20 | this.el.sceneEl.systems.effects.unregister(this); 21 | } 22 | ``` 23 | 24 | The system also exposes several methods to assist in effect component writing. 25 | 26 | 27 | #### system.isActive( behavior, shouldResize ) 28 | 29 | ``` 30 | 31 | // inside a component generating intermediate textures 32 | tock: function () { 33 | 34 | // If this effect is not meant to run this frame, 35 | // skip the generation of intermediate textures 36 | // But if it does and the component has a setSize(w,h) 37 | // defined and a resize has happened this frame 38 | // and the second argument of isActive is set to true 39 | // then call setSize and pass it the canvas width and height 40 | 41 | if( ! this.el.sceneEl.systems.effects.isActive(this, true) ) { 42 | return; 43 | } 44 | 45 | // generate the textures, set uniforms etc 46 | 47 | } 48 | 49 | ``` 50 | 51 | #### system.materialize( shaderMaterialDefinition ) 52 | 53 | This method returns a ShaderMaterial in which it injects the shared uniforms system.tDiffuse and system.uvClamp. It also prepends the fragment source with a textureVR definition to be used instead of texture2D whenever proper clamping according to view is needed(computed UVs) 54 | 55 | #### system.fuse( arrayOfFusableComponents, alpha ) 56 | 57 | This method accepts an array of objects that contain the properties required to define fusable components. It returns a single ShaderMaterial. The alpha argument toggles setting the final alpha as 1.0 or leaving it as is. 58 | 59 | ``` 60 | init: function () { 61 | 62 | // The following is good practice, could be provided by A-Frame itself 63 | this.system = this.el.sceneEl.systems.effects; 64 | 65 | this.materialSobel = this.system.fuse( 66 | [ 67 | { 68 | // Glsl chunk for fusion 69 | fragment: this.sobel, 70 | 71 | // Object exposing uniforms needed by the fragment 72 | uniforms: this.sobelUniforms, 73 | 74 | // These will only be included once for all fusables 75 | includes: ["packing"], 76 | 77 | // We only need the value from the depth texture 78 | depth: true 79 | 80 | // So we don't set diffuse for this one 81 | } 82 | ] 83 | ); 84 | 85 | } 86 | ``` 87 | 88 | -------------------------------------------------------------------------------- /systems/effects.js: -------------------------------------------------------------------------------- 1 | // Copyright 2017-2019 Yannis Gravezas MIT licensed 2 | 3 | var sizeVector = new THREE.Vector2(); 4 | 5 | AFRAME.registerSystem("effects", { 6 | schema: { type: "array", default: [] }, 7 | 8 | init: function () { 9 | this.effects = {}; 10 | this.passes = []; 11 | this._passes = []; 12 | this.cameras = []; 13 | this.setupPostState(); 14 | this.needsOverride = true; 15 | this.lightComponents = []; 16 | this.LightState = { 17 | rows: 0, 18 | cols: 0, 19 | width: 0, 20 | height: 0, 21 | tileData: { value: null }, 22 | tileTexture: { value: null }, 23 | lightTexture: { 24 | value: new THREE.DataTexture( new Float32Array( 32 * 2 * 4 ), 32, 2, THREE.RGBAFormat, THREE.FloatType ) 25 | }, 26 | }; 27 | }, 28 | 29 | update: function () { 30 | this.needsUpdate = true; 31 | }, 32 | 33 | addLight: function (behavior) { 34 | this.lightComponents.push(behavior); 35 | }, 36 | 37 | removeLight: function (behavior) { 38 | var index = this.lightComponents.indexOf(behavior); 39 | this.lightComponents.splice(index); 40 | }, 41 | 42 | setupPostState: function () { 43 | this.renderTarget = new THREE.WebGLRenderTarget(1, 1, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }); 44 | this.renderTarget.texture.generateMipmaps = false; 45 | this.renderTarget.depthBuffer = true; 46 | this.renderTarget.depthTexture = new THREE.DepthTexture(); 47 | this.renderTarget.depthTexture.type = THREE.UnsignedShortType; 48 | this.renderTarget.depthTexture.minFilter = THREE.LinearFilter; 49 | this.renderTarget.stencilBuffer = false; 50 | this.scene = new THREE.Scene(); 51 | this.camera = new THREE.OrthographicCamera(-1, 1, 1, -1, 0, 1); 52 | this.quad = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2), null); 53 | this.quad.frustumCulled = false; 54 | this.scene.add(this.quad); 55 | this.sceneLeft = new THREE.Scene(); 56 | this.quadLeft = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2), null); 57 | this.quadLeft.geometry.attributes.uv.array.set([0, 1, 0.5, 1, 0, 0, 0.5, 0]); 58 | this.quadLeft.frustumCulled = false; 59 | this.sceneLeft.add(this.quadLeft); 60 | this.sceneRight = new THREE.Scene(); 61 | this.quadRight = new THREE.Mesh(new THREE.PlaneBufferGeometry(2, 2), null); 62 | this.quadRight.geometry.attributes.uv.array.set([0.5, 1, 1, 1, 0.5, 0, 1, 0]); 63 | this.quadRight.frustumCulled = false; 64 | this.sceneRight.add(this.quadRight); 65 | this.targets = [ 66 | new THREE.WebGLRenderTarget(1, 1, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }), 67 | new THREE.WebGLRenderTarget(1, 1, { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat }) 68 | ]; 69 | 70 | this.tDiffuse = {type: "t", value: null}; 71 | this.tDepth = {type: "t", value: this.renderTarget.depthTexture}; 72 | this.cameraFar = {type: "f", value: 0}; 73 | this.cameraNear = {type: "f", value: 0}; 74 | this.time = { type: "f", value: 0 }; 75 | this.timeDelta = { type: "f", value: 0 }; 76 | this.uvClamp = { type: "v2", value: this.uvBoth }; 77 | this.resolution = { type: "v4", value: new THREE.Vector4() }; 78 | 79 | }, 80 | 81 | vertexShader: [ 82 | '#include ', 83 | 'varying vec2 vUv;', 84 | 'void main() {', 85 | ' vUv = uv;', 86 | ' gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );', 87 | '}' 88 | ].join('\n'), 89 | 90 | uvLeft: new THREE.Vector2(0, 0.5), 91 | uvRight: new THREE.Vector2(0.5, 1), 92 | uvBoth: new THREE.Vector2(0, 1), 93 | 94 | parseToken: /([#a-z0-9\-\_]+)\.{0,1}([#a-z0-9\-\_]*)\s*\({0,1}\s*([\$a-z0-9\-\_\.\s]*)\){0,1}([\!\?]{0,1})/i, 95 | 96 | renderPass: function (material, renderTarget, viewCb, forceClear){ 97 | var renderer = this.sceneEl.renderer; 98 | this.quad.material = material; 99 | var isFn = typeof viewCb === "function"; 100 | var s = renderTarget || renderer.getSize(sizeVector); 101 | this.resolution.value.set(s.width || sizeVector.x, s.height || sizeVector.y, 1/(s.width || sizeVector.x), 1/(s.height || sizeVector.y)); 102 | var oldClear = renderer.autoClear; 103 | renderer.autoClear = false; 104 | if (viewCb) { 105 | if (this.cameras.length > 1){ 106 | this.quadLeft.material = material; 107 | this.uvClamp.value = this.uvLeft; 108 | setView(0, 0, Math.round(s.width * 0.5), s.height); 109 | if (isFn) viewCb(material, this.cameras[0], -1); 110 | renderer.setRenderTarget(renderTarget); 111 | renderer.render(this.sceneLeft, this.camera); 112 | renderer.setRenderTarget(null); 113 | this.quadRight.material = material; 114 | this.uvClamp.value = this.uvRight; 115 | setView(Math.round(s.width * 0.5), 0, Math.round(s.width * 0.5), s.height); 116 | if (isFn) viewCb(material, this.cameras[1], 1); 117 | renderer.setRenderTarget(renderTarget); 118 | renderer.render( this.sceneRight, this.camera); 119 | renderer.setRenderTarget(null); 120 | 121 | this.uvClamp.value = this.uvBoth; 122 | setView(0, 0, s.width, s.height); 123 | } else { 124 | setView(0, 0, s.width, s.height); 125 | if (isFn) viewCb(material, this.sceneEl.camera, 0); 126 | renderer.setRenderTarget(renderTarget); 127 | renderer.render( this.scene, this.camera); 128 | renderer.setRenderTarget(null); 129 | } 130 | } else { 131 | setView(0, 0, s.width, s.height); 132 | renderer.setRenderTarget(renderTarget); 133 | renderer.render(this.scene, this.camera); 134 | renderer.setRenderTarget(null); 135 | } 136 | renderer.autoClear = oldClear; 137 | function setView(x,y,w,h) { 138 | if (renderTarget) { 139 | renderTarget.viewport.set( x, y, w, h ); 140 | renderTarget.scissor.set( x, y, w, h ); 141 | } else { 142 | renderer.setViewport( x, y, w, h ); 143 | renderer.setScissor( x, y, w, h ); 144 | } 145 | } 146 | }, 147 | 148 | materialize: function (m) { 149 | var fs = [ 150 | "uniform vec2 uvClamp;", 151 | "vec4 textureVR( sampler2D sampler, vec2 uv ) {", 152 | " return texture2D(sampler, vec2(clamp(uv.x, uvClamp.x, uvClamp.y), uv.y));", 153 | "} ", 154 | m.fragmentShader 155 | ].join("\n"); 156 | 157 | m.uniforms.uvClamp = this.uvClamp; 158 | 159 | return new THREE.ShaderMaterial({ 160 | uniforms: m.uniforms, 161 | vertexShader: m.vertexShader || this.vertexShader, 162 | fragmentShader: fs, 163 | depthWrite: false, 164 | depthTest: false, 165 | blending: THREE.NoBlending, 166 | fog: false, 167 | extensions: { 168 | derivatives: true 169 | }, 170 | defines: m.defines || {} 171 | }); 172 | }, 173 | 174 | fuse: function (temp, alpha) { 175 | if (!temp.length) return; 176 | var self = this, count=0; 177 | var chunks = [], head = [], main = [], includes = {}, 178 | needsDepth = false, needsDiffuse = false, k; 179 | 180 | var uniforms = { 181 | time: this.time, 182 | timeDelta: this.timeDelta, 183 | resolution: this.resolution 184 | }; 185 | 186 | temp.forEach(function (obj) { 187 | var callMain = true, swapMain = false, args=[]; 188 | if (typeof obj === "string") { 189 | var tok = self.parseToken.exec(obj); 190 | if(!tok) return; 191 | 192 | callMain = tok[4] !== "!"; 193 | swapMain = tok[4] === "?"; 194 | obj = tok[1]; 195 | var prop = tok[2]; 196 | var temp = {}; 197 | 198 | if(obj[0] === "#") { 199 | var el = document.querySelector(obj); 200 | if(!el) return; 201 | 202 | obj = { 203 | attrName: [obj.replace("#", "script_"), "_", (count++), "_"].join(""), 204 | fragment: prop ? 205 | (el[prop] instanceof Document ? el[prop].body.textContent : el[prop]) 206 | : el.textContent, 207 | depth: el.dataset.depth !== undefined, 208 | diffuse: el.dataset.diffuse !== undefined, 209 | includes: el.dataset.includes ? el.dataset.includes.trim().split(" ") : null, 210 | defaults: el.dataset.defaults ? el.dataset.defaults.trim().split(" ") : null 211 | }; 212 | } else { 213 | obj = self.effects[obj]; 214 | if (!obj) return; 215 | if (prop) { 216 | obj = obj.exports ? obj.exports[prop] : null; 217 | if (!obj) return; 218 | obj.attrName = tok[1] + "_" + prop + "_"; 219 | } 220 | } 221 | if (tok[3]) { 222 | args = tok[3].trim().split(" "); 223 | } 224 | } 225 | var prefix = (obj.attrName ? obj.attrName : "undefined_" + (count++)) + "_"; 226 | prefix = prefix.replace("__","_"); 227 | if (obj.defaults) { 228 | obj.defaults.forEach(function (d, i) { 229 | var v = args[i]; 230 | chunks.push(["#define $", i, " ", v && v !== "$" ? v : d ].join("").replace(/\$/g, prefix).replace("__","_")); 231 | }); 232 | } 233 | if (obj.diffuse) { needsDiffuse = true; } 234 | if (obj.depth) { needsDepth = true; } 235 | if (obj.fragment) { chunks.push(obj.fragment.replace(/\$/g, prefix)); } 236 | if (obj.uniforms) { 237 | for (var u in obj.uniforms) { 238 | uniforms[prefix + u] = obj.uniforms[u]; 239 | } 240 | }; 241 | if (obj.includes) { 242 | obj.includes.forEach(function (inc) { 243 | includes[inc] = true; 244 | }); 245 | } 246 | if (callMain) { 247 | main.push([" ", prefix, "main(", ( swapMain ? "origColor, color": "color, origColor"), ", vUv, depth);"].join("")); 248 | } 249 | }); 250 | var t2u = { "i": "int", "f": "float", "t": "sampler2D", 251 | "v2": "vec2", "v3": "vec3", "c": "vec3","v4": "vec4", 252 | "m2": "mat2", "m3":"mat3", "m4": "mat4", "b": "bool" }; 253 | 254 | for(k in includes) { head.push("#include <" + k + ">"); } 255 | 256 | var premain = [ 257 | "void main () {" 258 | ]; 259 | uniforms["tDiffuse"] = this.tDiffuse; 260 | 261 | if (needsDiffuse){ 262 | premain.push(" vec4 color = texture2D(tDiffuse, vUv);"); 263 | } else { 264 | premain.push(" vec4 color = vec4(0.0);"); 265 | } 266 | premain.push(" vec4 origColor = color;"); 267 | 268 | uniforms["tDepth"] = this.tDepth; 269 | uniforms["cameraFar"] = this.cameraFar; 270 | uniforms["cameraNear"] = this.cameraNear; 271 | 272 | if (needsDepth){ 273 | premain.push(" float depth = texture2D(tDepth, vUv).x;"); 274 | } else { 275 | premain.push(" float depth = 0.0;"); 276 | } 277 | 278 | for(k in uniforms) { 279 | var u = uniforms[k]; 280 | head.push(["uniform", t2u[u.type], k, ";"].join(" ")); 281 | } 282 | 283 | head.push("varying vec2 vUv;"); 284 | var source = [ 285 | head.join("\n"), chunks.join("\n"), "\n", 286 | premain.join("\n"), main.join("\n"), 287 | alpha ? " gl_FragColor = color;" : " gl_FragColor = vec4(color.rgb, 1.0);", "}" 288 | ].join("\n"); 289 | 290 | var material = this.materialize({ 291 | fragmentShader: source, 292 | uniforms: uniforms 293 | }); 294 | 295 | if(this.sceneEl.components.debug) console.log(source, material); 296 | return material; 297 | }, 298 | 299 | rebuild: function () { 300 | var self = this, passes = [], temp = []; 301 | this.passes.forEach(function(pass){ 302 | if (pass.dispose) pass.dispose(); 303 | }); 304 | this.data.forEach(function (k) { 305 | if(!k){ 306 | pickup(); 307 | return; 308 | } 309 | var obj, name; 310 | var tok = self.parseToken.exec(k); 311 | if(!tok || !tok[1]) return; 312 | name = tok[1]; 313 | obj = self.effects[name]; 314 | if (!obj){ 315 | temp.push(k); 316 | return; 317 | } 318 | if (obj.pass) { 319 | pickup(); 320 | passes.push({ pass: obj.pass, behavior: obj } ); 321 | } else if (obj.material){ 322 | pickup(); 323 | passes.push({ pass: makepass(obj.material, false, obj.vr), behavior: obj }); 324 | } else { 325 | temp.push(k); 326 | } 327 | }); 328 | 329 | function pickup () { 330 | if (!temp.length) return; 331 | passes.push({ pass: makepass(self.fuse(temp), true)}); 332 | temp = []; 333 | } 334 | 335 | function makepass (material, dispose, viewCb) { 336 | return { 337 | render: function(renderer, writeBuffer, readBuffer){ 338 | self.renderPass(material, writeBuffer, viewCb); 339 | }, 340 | 341 | dispose: function () { 342 | if (dispose) material.dispose(); 343 | } 344 | } 345 | } 346 | pickup(); 347 | this.needsUpdate = false; 348 | this.passes = passes; 349 | }, 350 | 351 | isActive: function (behavior, resize) { 352 | var scene = this.sceneEl; 353 | if (behavior.bypass) return false; 354 | var isEnabled = scene.renderTarget ? true : false; 355 | if (!isEnabled) return false; 356 | if (resize && (this.needsResize || behavior.needsResize) && behavior.setSize) { 357 | var size = scene.renderer.getSize(sizeVector); 358 | behavior.setSize(sizeVector.x, sizeVector.y); 359 | delete behavior.needsResize; 360 | } 361 | return true; 362 | }, 363 | 364 | register: function (behavior) { 365 | this.effects[behavior.attrName] = behavior; 366 | this.needsUpdate = true; 367 | }, 368 | 369 | unregister: function (behavior) { 370 | delete this.effects[behavior.attrName]; 371 | this.needsUpdate = true; 372 | }, 373 | 374 | tick: function (time, timeDelta) { 375 | var self = this, sceneEl = this.sceneEl, renderer = sceneEl.renderer, effect = sceneEl.effect, 376 | rt = this.renderTarget, rts = this.targets, scene = sceneEl.object3D; 377 | if(!rt || !renderer) { return; } 378 | if (this.needsOverride) { 379 | if(scene.onBeforeRender) { 380 | scene.onBeforeRender = function (renderer, scene, camera) { 381 | var size = renderer.getSize(sizeVector); 382 | if (sizeVector.x !== rt.width || sizeVector.y !== rt.height) { 383 | rt.setSize(size.width, size.height); 384 | rts[0].setSize(size.width, size.height); 385 | rts[1].setSize(size.width, size.height); 386 | self.resolution.value.set(size.width, size.height, 1/size.width, 1/size.height); 387 | self.needsResize = true; 388 | self.resizeTiles(); 389 | } 390 | if(camera instanceof THREE.ArrayCamera) { 391 | self.cameras = camera.cameras; 392 | } else { 393 | self.cameras.push(camera); 394 | } 395 | self.tileLights(renderer, scene, camera); 396 | } 397 | } else { 398 | var rendererRender = renderer.render; 399 | renderer.render = function (scene, camera, renderTarget, forceClear) { 400 | if (renderTarget === rt) { 401 | var size = renderer.getSize(sizeVector); 402 | if (sizeVector.x !== rt.width || sizeVector.y !== rt.height) { 403 | rt.setSize(size.width, size.height); 404 | rts[0].setSize(size.width, size.height); 405 | rts[1].setSize(size.width, size.height); 406 | self.resolution.value.set(size.width, size.height, 1/size.width, 1/size.height); 407 | self.needsResize = true; 408 | } 409 | self.cameras.push(camera); 410 | } 411 | renderer.setRenderTarget(renderTarget); 412 | rendererRender.call(renderer, scene, camera); 413 | renderer.setRenderTarget(null); 414 | } 415 | } 416 | this.needsOverride = false; 417 | } 418 | this.cameras = []; 419 | this.time.value = time / 1000; 420 | this.timeDelta.value = timeDelta / 1000; 421 | 422 | if (this.needsUpdate === true) { this.rebuild(); } 423 | 424 | this.setupPasses(); 425 | 426 | this.tDiffuse.value = this.renderTarget.texture; 427 | this.tDepth.value = this.renderTarget.depthTexture; 428 | var camera = this.sceneEl.camera; 429 | this.cameraFar.value = camera.far; 430 | this.cameraNear.value = camera.near; 431 | }, 432 | 433 | setupPasses : function () { 434 | var arr = [], rt = this.renderTarget; 435 | this.passes.forEach(function (p) { 436 | if (p.behavior && p.behavior.bypass === true) return; 437 | arr.push(p); 438 | }); 439 | this.sceneEl.renderTarget = arr.length && this.sceneEl.isPlaying ? rt : null; 440 | this._passes = arr; 441 | }, 442 | tock: function () { 443 | var scene = this.sceneEl, renderer = scene.renderer, self = this; 444 | if(!scene.renderTarget) { return; } 445 | var rt = scene.renderTarget, rts = this.targets; 446 | this._passes.forEach(function (pass, i) { 447 | var r = i ? rts[i & 1] : rt; 448 | self.tDiffuse.value = r.texture; 449 | if (pass.behavior && pass.behavior.resize) self.isActive(pass.behavior, true); 450 | pass.pass.render(renderer, i < self._passes.length - 1 ? rts[(i+1) & 1] : null, r); 451 | }); 452 | this.needsResize = false; 453 | }, 454 | 455 | resizeTiles: function () { 456 | var LightState = this.LightState; 457 | var width = LightState.width; 458 | var height = LightState.height; 459 | LightState.cols = Math.ceil( width / 32 ); 460 | LightState.rows = Math.ceil( LightState.height / 32 ); 461 | LightState.tileData.value = [ width, height, 0.5 / Math.ceil( width / 32 ), 0.5 / Math.ceil( height / 32 ) ]; 462 | LightState.tileTexture.value = new THREE.DataTexture( new Uint8Array( LightState.cols * LightState.rows * 4 ), LightState.cols, LightState.rows ); 463 | }, 464 | 465 | tileLights: function ( renderer, scene, camera ) { 466 | if ( ! camera.projectionMatrix ) return; 467 | var LightState = this.LightState, lights = this.lightComponents; 468 | var size = renderer.getSize(sizeVector); 469 | var d = LightState.tileTexture.value.image.data; 470 | var ld = LightState.lightTexture.value.image.data; 471 | var viewMatrix = camera.matrixWorldInverse; 472 | d.fill( 0 ); 473 | var vector = new THREE.Vector3(); 474 | 475 | var passes; 476 | if(camera instanceof THREE.ArrayCamera) { 477 | passes = [ [0.5, 0, camera.cameras[0]], [0.5, 0.5, camera.cameras[1]]]; 478 | } else { 479 | passes = [1.0, 0, camera]; 480 | } 481 | passes.forEach(function(pass){ 482 | lights.forEach( function ( light, index ) { 483 | vector.setFromMatrixPosition( light.el.object3D.matrixWorld ); 484 | var pw = LightState.width * pass[0]; 485 | var pm = LightState.width * pass[1]; 486 | var bs = self.lightBounds( pass[2], vector, light.data.radius, pw ); 487 | vector.applyMatrix4( viewMatrix ); 488 | vector.toArray( ld, 4 * index ); 489 | ld[ 4 * index + 3 ] = light.data.radius; 490 | light.data.color.toArray( ld, 32 * 4 + 4 * index ); 491 | ld[ 32 * 4 + 4 * index + 3 ] = light.data.decay; 492 | if ( bs[ 1 ] < 0 || bs[ 0 ] > pw || bs[ 3 ] < 0 || bs[ 2 ] > LightState.height ) return; 493 | if ( bs[ 0 ] < 0 ) bs[ 0 ] = 0; 494 | if ( bs[ 1 ] > pw ) bs[ 1 ] = pw; 495 | if ( bs[ 2 ] < 0 ) bs[ 2 ] = 0; 496 | if ( bs[ 3 ] > LightState.height ) bs[ 3 ] = LightState.height; 497 | var i4 = Math.floor( index / 8 ), i8 = 7 - ( index % 8 ); 498 | for ( var i = Math.floor( bs[ 2 ] / 32 ); i <= Math.ceil( bs[ 3 ] / 32 ); i ++ ) { 499 | for ( var j = Math.floor( (bs[ 0 ] + pm) / 32 ); j <= Math.ceil( (bs[ 1 ] + pm) / 32 ); j ++ ) { 500 | d[ ( LightState.cols * i + j ) * 4 + i4 ] |= 1 << i8; 501 | } 502 | } 503 | } ); 504 | }); 505 | LightState.tileTexture.value.needsUpdate = true; 506 | LightState.lightTexture.value.needsUpdate = true; 507 | }, 508 | 509 | lightBounds: function () { 510 | v = new THREE.Vector3(); 511 | return function ( camera, pos, r, w ) { 512 | var LightState = this.LightState; 513 | var minX = w, maxX = 0, minY = LightState.height, maxY = 0, hw = w / 2, hh = LightState.height / 2; 514 | for ( var i = 0; i < 8; i ++ ) { 515 | v.copy( pos ); 516 | v.x += i & 1 ? r : - r; 517 | v.y += i & 2 ? r : - r; 518 | v.z += i & 4 ? r : - r; 519 | var vector = v.project( camera ); 520 | var x = ( vector.x * hw ) + hw; 521 | var y = ( vector.y * hh ) + hh; 522 | minX = Math.min( minX, x ); 523 | maxX = Math.max( maxX, x ); 524 | minY = Math.min( minY, y ); 525 | maxY = Math.max( maxY, y ); 526 | } 527 | return [ minX, maxX, minY, maxY ]; 528 | }; 529 | }() 530 | }); 531 | -------------------------------------------------------------------------------- /systems/index.js: -------------------------------------------------------------------------------- 1 | require("./effects"); 2 | -------------------------------------------------------------------------------- /three.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | three.js webgl - geometries 5 | 6 | 7 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 32 | 33 | 216 |
217 | 222 | 227 | 232 |
233 | 234 | 235 | 236 | 237 | 238 | 239 | 241 | 242 | 243 | three.html --------------------------------------------------------------------------------