├── .babelrc ├── .editorconfig ├── .eslintrc ├── .gitignore ├── LICENSE ├── Lensflare.js ├── README.md ├── dist ├── aframe-lensflare-component.js ├── aframe-lensflare-component.js.map ├── aframe-lensflare-component.min.js └── aframe-lensflare-component.min.js.map ├── examples ├── basic │ ├── images │ │ ├── aframe-lensflare-low.gif │ │ ├── aframe-lensflare.gif │ │ ├── flare.jpg │ │ ├── flare2.jpg │ │ ├── flare3.jpg │ │ ├── floor.jpg │ │ ├── sky.jpg │ │ └── sky2.jpg │ └── index.html ├── build.js ├── index.html └── main.js ├── gh-pages ├── basic │ ├── images │ │ ├── flare.jpg │ │ └── flare2.jpg │ └── index.html ├── build.js ├── index.html └── main.js ├── index.js ├── package-lock.json ├── package.json ├── tests ├── __init.test.js ├── helpers.js ├── index.test.js └── karma.conf.js └── webpack.config.js /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["es2015"] 3 | } 4 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # http://editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | # editorconfig-tools is unable to ignore longs strings or urls 20 | max_line_length = null 21 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "parserOptions": { 3 | "ecmaVersion": 2017 4 | }, 5 | 6 | "env": { 7 | "es6": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /gh-pages 6 | 7 | # testing 8 | /coverage 9 | 10 | # production 11 | /build 12 | 13 | # misc 14 | .DS_Store 15 | .env 16 | npm-debug.log* 17 | yarn-debug.log* 18 | yarn-error.log* 19 | 20 | #CSS is generated 21 | src/**/*.css 22 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Mo Kargas 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 | -------------------------------------------------------------------------------- /Lensflare.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @author Mugen87 / https://github.com/Mugen87 3 | * @author mrdoob / http://mrdoob.com/ 4 | */ 5 | 6 | THREE.Lensflare = function () { 7 | 8 | THREE.Mesh.call( this, THREE.Lensflare.Geometry, new THREE.MeshBasicMaterial( { opacity: 0, transparent: true } ) ); 9 | 10 | this.type = 'Lensflare'; 11 | this.frustumCulled = false; 12 | this.renderOrder = Infinity; 13 | 14 | // 15 | 16 | var positionScreen = new THREE.Vector3(); 17 | var positionView = new THREE.Vector3(); 18 | 19 | // textures 20 | 21 | var tempMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat ); 22 | tempMap.minFilter = THREE.NearestFilter; 23 | tempMap.magFilter = THREE.NearestFilter; 24 | tempMap.wrapS = THREE.ClampToEdgeWrapping; 25 | tempMap.wrapT = THREE.ClampToEdgeWrapping; 26 | tempMap.needsUpdate = true; 27 | 28 | var occlusionMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat ); 29 | occlusionMap.minFilter = THREE.NearestFilter; 30 | occlusionMap.magFilter = THREE.NearestFilter; 31 | occlusionMap.wrapS = THREE.ClampToEdgeWrapping; 32 | occlusionMap.wrapT = THREE.ClampToEdgeWrapping; 33 | occlusionMap.needsUpdate = true; 34 | 35 | // material 36 | 37 | var geometry = THREE.Lensflare.Geometry; 38 | 39 | var material1a = new THREE.RawShaderMaterial( { 40 | uniforms: { 41 | 'scale': { value: null }, 42 | 'screenPosition': { value: null } 43 | }, 44 | vertexShader: [ 45 | 46 | 'precision highp float;', 47 | 48 | 'uniform vec3 screenPosition;', 49 | 'uniform vec2 scale;', 50 | 51 | 'attribute vec3 position;', 52 | 53 | 'void main() {', 54 | 55 | ' gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', 56 | 57 | '}' 58 | 59 | ].join( '\n' ), 60 | fragmentShader: [ 61 | 62 | 'precision highp float;', 63 | 64 | 'void main() {', 65 | 66 | ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );', 67 | 68 | '}' 69 | 70 | ].join( '\n' ), 71 | depthTest: true, 72 | depthWrite: false, 73 | transparent: false 74 | } ); 75 | 76 | var material1b = new THREE.RawShaderMaterial( { 77 | uniforms: { 78 | 'map': { value: tempMap }, 79 | 'scale': { value: null }, 80 | 'screenPosition': { value: null } 81 | }, 82 | vertexShader: [ 83 | 84 | 'precision highp float;', 85 | 86 | 'uniform vec3 screenPosition;', 87 | 'uniform vec2 scale;', 88 | 89 | 'attribute vec3 position;', 90 | 'attribute vec2 uv;', 91 | 92 | 'varying vec2 vUV;', 93 | 94 | 'void main() {', 95 | 96 | ' vUV = uv;', 97 | 98 | ' gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', 99 | 100 | '}' 101 | 102 | ].join( '\n' ), 103 | fragmentShader: [ 104 | 105 | 'precision highp float;', 106 | 107 | 'uniform sampler2D map;', 108 | 109 | 'varying vec2 vUV;', 110 | 111 | 'void main() {', 112 | 113 | ' gl_FragColor = texture2D( map, vUV );', 114 | 115 | '}' 116 | 117 | ].join( '\n' ), 118 | depthTest: false, 119 | depthWrite: false, 120 | transparent: false 121 | } ); 122 | 123 | // the following object is used for occlusionMap generation 124 | 125 | var mesh1 = new THREE.Mesh( geometry, material1a ); 126 | 127 | // 128 | 129 | var elements = []; 130 | 131 | var shader = THREE.LensflareElement.Shader; 132 | 133 | var material2 = new THREE.RawShaderMaterial( { 134 | uniforms: { 135 | 'map': { value: null }, 136 | 'occlusionMap': { value: occlusionMap }, 137 | 'color': { value: new THREE.Color( 0xffffff ) }, 138 | 'scale': { value: new THREE.Vector2() }, 139 | 'screenPosition': { value: new THREE.Vector3() } 140 | }, 141 | vertexShader: shader.vertexShader, 142 | fragmentShader: shader.fragmentShader, 143 | blending: THREE.AdditiveBlending, 144 | transparent: true, 145 | depthWrite: false 146 | } ); 147 | 148 | var mesh2 = new THREE.Mesh( geometry, material2 ); 149 | 150 | this.addElement = function ( element ) { 151 | 152 | elements.push( element ); 153 | 154 | }; 155 | 156 | // 157 | 158 | var scale = new THREE.Vector2(); 159 | var screenPositionPixels = new THREE.Vector2(); 160 | var validArea = new THREE.Box2(); 161 | var viewport = new THREE.Vector4(); 162 | 163 | this.onBeforeRender = function ( renderer, scene, camera ) { 164 | 165 | renderer.getCurrentViewport( viewport ); 166 | 167 | var invAspect = viewport.w / viewport.z; 168 | var halfViewportWidth = viewport.z / 2.0; 169 | var halfViewportHeight = viewport.w / 2.0; 170 | 171 | var size = 16 / viewport.w; 172 | scale.set( size * invAspect, size ); 173 | 174 | validArea.min.set( viewport.x, viewport.y ); 175 | validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); 176 | 177 | // calculate position in screen space 178 | 179 | positionView.setFromMatrixPosition( this.matrixWorld ); 180 | positionView.applyMatrix4( camera.matrixWorldInverse ); 181 | 182 | if ( positionView.z > 0 ) return; // lensflare is behind the camera 183 | 184 | positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); 185 | 186 | // horizontal and vertical coordinate of the lower left corner of the pixels to copy 187 | 188 | screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8; 189 | screenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8; 190 | 191 | // screen cull 192 | 193 | if ( validArea.containsPoint( screenPositionPixels ) ) { 194 | 195 | // save current RGB to temp texture 196 | 197 | renderer.copyFramebufferToTexture( screenPositionPixels, tempMap ); 198 | 199 | // render pink quad 200 | 201 | var uniforms = material1a.uniforms; 202 | uniforms[ "scale" ].value = scale; 203 | uniforms[ "screenPosition" ].value = positionScreen; 204 | 205 | renderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null ); 206 | 207 | // copy result to occlusionMap 208 | 209 | renderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap ); 210 | 211 | // restore graphics 212 | 213 | var uniforms = material1b.uniforms; 214 | uniforms[ "scale" ].value = scale; 215 | uniforms[ "screenPosition" ].value = positionScreen; 216 | 217 | renderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null ); 218 | 219 | // render elements 220 | 221 | var vecX = - positionScreen.x * 2; 222 | var vecY = - positionScreen.y * 2; 223 | 224 | for ( var i = 0, l = elements.length; i < l; i ++ ) { 225 | 226 | var element = elements[ i ]; 227 | 228 | var uniforms = material2.uniforms; 229 | 230 | uniforms[ "color" ].value.copy( element.color ); 231 | uniforms[ "map" ].value = element.texture; 232 | uniforms[ "screenPosition" ].value.x = positionScreen.x + vecX * element.distance; 233 | uniforms[ "screenPosition" ].value.y = positionScreen.y + vecY * element.distance; 234 | 235 | var size = element.size / viewport.w; 236 | var invAspect = viewport.w / viewport.z; 237 | 238 | uniforms[ "scale" ].value.set( size * invAspect, size ); 239 | 240 | material2.uniformsNeedUpdate = true; 241 | 242 | renderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null ); 243 | 244 | } 245 | 246 | } 247 | 248 | }; 249 | 250 | this.dispose = function () { 251 | 252 | material1a.dispose(); 253 | material1b.dispose(); 254 | material2.dispose(); 255 | 256 | tempMap.dispose(); 257 | occlusionMap.dispose(); 258 | 259 | for ( var i = 0, l = elements.length; i < l; i ++ ) { 260 | 261 | elements[ i ].texture.dispose(); 262 | 263 | } 264 | 265 | }; 266 | 267 | }; 268 | 269 | THREE.Lensflare.prototype = Object.create( THREE.Mesh.prototype ); 270 | THREE.Lensflare.prototype.constructor = THREE.Lensflare; 271 | THREE.Lensflare.prototype.isLensflare = true; 272 | 273 | // 274 | 275 | THREE.LensflareElement = function ( texture, size, distance, color ) { 276 | 277 | this.texture = texture; 278 | this.size = size || 1; 279 | this.distance = distance || 0; 280 | this.color = color || new THREE.Color( 0xffffff ); 281 | 282 | }; 283 | 284 | THREE.LensflareElement.Shader = { 285 | 286 | uniforms: { 287 | 288 | 'map': { value: null }, 289 | 'occlusionMap': { value: null }, 290 | 'color': { value: null }, 291 | 'scale': { value: null }, 292 | 'screenPosition': { value: null } 293 | 294 | }, 295 | 296 | vertexShader: [ 297 | 298 | 'precision highp float;', 299 | 300 | 'uniform vec3 screenPosition;', 301 | 'uniform vec2 scale;', 302 | 303 | 'uniform sampler2D occlusionMap;', 304 | 305 | 'attribute vec3 position;', 306 | 'attribute vec2 uv;', 307 | 308 | 'varying vec2 vUV;', 309 | 'varying float vVisibility;', 310 | 311 | 'void main() {', 312 | 313 | ' vUV = uv;', 314 | 315 | ' vec2 pos = position.xy;', 316 | 317 | ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', 318 | ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', 319 | ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', 320 | ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', 321 | ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', 322 | ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', 323 | ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', 324 | ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', 325 | ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', 326 | 327 | ' vVisibility = visibility.r / 9.0;', 328 | ' vVisibility *= 1.0 - visibility.g / 9.0;', 329 | ' vVisibility *= visibility.b / 9.0;', 330 | 331 | ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', 332 | 333 | '}' 334 | 335 | ].join( '\n' ), 336 | 337 | fragmentShader: [ 338 | 339 | 'precision highp float;', 340 | 341 | 'uniform sampler2D map;', 342 | 'uniform vec3 color;', 343 | 344 | 'varying vec2 vUV;', 345 | 'varying float vVisibility;', 346 | 347 | 'void main() {', 348 | 349 | ' vec4 texture = texture2D( map, vUV );', 350 | ' texture.a *= vVisibility;', 351 | ' gl_FragColor = texture;', 352 | ' gl_FragColor.rgb *= color;', 353 | 354 | '}' 355 | 356 | ].join( '\n' ) 357 | 358 | }; 359 | 360 | THREE.Lensflare.Geometry = ( function () { 361 | 362 | var geometry = new THREE.BufferGeometry(); 363 | 364 | var float32Array = new Float32Array( [ 365 | - 1, - 1, 0, 0, 0, 366 | 1, - 1, 0, 1, 0, 367 | 1, 1, 0, 1, 1, 368 | - 1, 1, 0, 0, 1 369 | ] ); 370 | 371 | var interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 ); 372 | 373 | geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); 374 | geometry.addAttribute( 'position', new THREE.InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); 375 | geometry.addAttribute( 'uv', new THREE.InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); 376 | 377 | return geometry; 378 | 379 | } )(); 380 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # aframe-lensflare-component 2 | 3 | [![Version](http://img.shields.io/npm/v/aframe-lensflare-component.svg?style=flat-square)](https://npmjs.org/package/aframe-lensflare-component) [![License](http://img.shields.io/npm/l/aframe-lensflare-component.svg?style=flat-square)](https://npmjs.org/package/aframe-lensflare-component) 4 | 5 | A component to add a configurable lens-flare (and optional light) to an entity that wraps THREE.JS Lensflares. 6 | 7 | Examples: [See Here](https://mokargas.github.io/aframe-lensflare-component) 8 | 9 | For [A-Frame](https://aframe.io). 10 | 11 | ![Example of Lensflares](https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/master/examples/basic/images/aframe-lensflare-low.gif "Example of Lensflares") 12 | 13 | ## API 14 | 15 | Property | Description | Default Value 16 | ------------- | ------------------------------------------------------------------------------------------------------------- | -------------------- 17 | src | Asset Image to use | none 18 | createLight | Whether to create a light along with this flare | true 19 | position | This is the position of the flare. | true 20 | relative | Whether to position this flare relative to the parent entity (The position property above becomes an *offset* ) | true 21 | target | DOM id of the object to point the Flare's spotlight at | none 22 | size | Size of the flare graphic (Use power of 2 images for best results) | 500 23 | intensity | If using `createLight:true`, this is the intensity of the light emitted | 5 24 | lightType | If using `createLight:true`, this is a string corresponding to A-Frame light types. Either 'directional', 'point', 'spot' | 'spot' 25 | lightColor | If `createLight:true`, Color of the light and (currently) flare tint | 'rgb(255, 255, 255)' 26 | lightDistance | Distance of the light (if enabled) | 500 27 | lightAngle | Maximum extent of the light in radians (from its direction). Valid for directional and spotlight type lights | PI/3 28 | lightPenumbra | If using `createLight:true`: Percent of the light cone that is attenuated due to penumbra. Takes values between zero and 1. Valid only for spotlights | 0.077 29 | lightDecay | If using `createLight:true`: The amount the light dims along the light's distance | 1 30 | 31 | ## Installation 32 | 33 | ### Browser 34 | 35 | Install and use by directly including the [browser files](dist): 36 | 37 | ```html 38 | 39 | My A-Frame Scene 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | Test Lensflare Asset 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | ``` 59 | 60 | 61 | 62 | ### npm 63 | 64 | Install via npm: 65 | 66 | ```bash 67 | npm install aframe-lensflare-component 68 | ``` 69 | 70 | Then require and use. 71 | 72 | ```javascript 73 | require('aframe'); 74 | require('aframe-lensflare-component'); 75 | 76 | //Or if supported by your stack (babel, webpack): 77 | 78 | import 'aframe'; 79 | import 'aframe-lensflare-component'; 80 | 81 | ``` 82 | 83 | ## TODO 84 | 85 | - Seperate Flare colorisation and Light Color 86 | -------------------------------------------------------------------------------- /dist/aframe-lensflare-component.js: -------------------------------------------------------------------------------- 1 | /******/ (function(modules) { // webpackBootstrap 2 | /******/ // The module cache 3 | /******/ var installedModules = {}; 4 | /******/ 5 | /******/ // The require function 6 | /******/ function __webpack_require__(moduleId) { 7 | /******/ 8 | /******/ // Check if module is in cache 9 | /******/ if(installedModules[moduleId]) 10 | /******/ return installedModules[moduleId].exports; 11 | /******/ 12 | /******/ // Create a new module (and put it into the cache) 13 | /******/ var module = installedModules[moduleId] = { 14 | /******/ exports: {}, 15 | /******/ id: moduleId, 16 | /******/ loaded: false 17 | /******/ }; 18 | /******/ 19 | /******/ // Execute the module function 20 | /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); 21 | /******/ 22 | /******/ // Flag the module as loaded 23 | /******/ module.loaded = true; 24 | /******/ 25 | /******/ // Return the exports of the module 26 | /******/ return module.exports; 27 | /******/ } 28 | /******/ 29 | /******/ 30 | /******/ // expose the modules object (__webpack_modules__) 31 | /******/ __webpack_require__.m = modules; 32 | /******/ 33 | /******/ // expose the module cache 34 | /******/ __webpack_require__.c = installedModules; 35 | /******/ 36 | /******/ // __webpack_public_path__ 37 | /******/ __webpack_require__.p = ""; 38 | /******/ 39 | /******/ // Load entry module and return exports 40 | /******/ return __webpack_require__(0); 41 | /******/ }) 42 | /************************************************************************/ 43 | /******/ ([ 44 | /* 0 */ 45 | /***/ (function(module, exports, __webpack_require__) { 46 | 47 | 'use strict'; 48 | 49 | /* global AFRAME */ 50 | /* global THREE */ 51 | 52 | if (typeof AFRAME === 'undefined') { 53 | throw new Error('Component attempted to register before AFRAME was available.'); 54 | } 55 | 56 | if (typeof THREE === 'undefined') { 57 | throw new Error('Component attempted to register before THREE was available.'); 58 | } 59 | 60 | //https://github.com/mrdoob/three.js/blob/master/examples/js/objects/Lensflare.js 61 | __webpack_require__(1); 62 | 63 | /** 64 | * A-Frame Lensflare Component component for A-Frame. 65 | */ 66 | AFRAME.registerComponent('lensflare', { 67 | schema: { 68 | src: { 69 | type: 'asset' 70 | }, 71 | createLight: { 72 | type: 'boolean', 73 | default: true 74 | }, 75 | position: { 76 | type: 'vec3' 77 | }, 78 | target: { 79 | type: 'string' 80 | }, 81 | intensity: { 82 | type: 'number', 83 | default: 5 84 | }, 85 | relative: { 86 | type: 'boolean', 87 | default: true 88 | }, 89 | size: { 90 | type: 'number', 91 | default: 500 92 | }, 93 | lightColor: { 94 | type: 'string', 95 | default: 'rgb(255, 255, 255)' 96 | }, 97 | lightDistance: { 98 | type: 'number', 99 | default: 4.0 100 | }, 101 | lightAngle: { 102 | type: 'number', 103 | default: Math.PI / 3 104 | }, 105 | lightPenumbra: { 106 | type: 'number', 107 | default: 0.077 108 | }, 109 | lightDecay: { 110 | type: 'number', 111 | default: 1 112 | }, 113 | lightType: { 114 | default: 'spot', 115 | oneOf: ['directional', 'point', 'spot'] 116 | } 117 | }, 118 | 119 | /** 120 | * Set if component needs multiple instancing. 121 | */ 122 | multiple: true, 123 | 124 | /** 125 | * setLightType - Create a light based on lightType 126 | * 127 | * @param {String} type Type of the light, supplied as a string. 128 | * @param {Object} settings Additional settings to pass to the light. E.g. angle and decay 129 | * @return {THREE.Light} A THREE.JS light object 130 | */ 131 | setLightType: function setLightType(type, settings) { 132 | switch (type) { 133 | case 'spot': 134 | return new THREE.SpotLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightAngle, settings.lightPenumbra, settings.lightDecay); 135 | case 'point': 136 | return new THREE.PointLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightDecay); 137 | case 'directional': 138 | return new THREE.DirectionalLight(new THREE.Color(settings.lightColor), settings.intensity); 139 | } 140 | }, 141 | /** 142 | * Called once when component is attached. Generally for initial setup. 143 | */ 144 | init: function init() { 145 | 146 | var scene = document.querySelector('a-scene').object3D; 147 | var parentEl = this.el.object3D; 148 | var sceneEl = this.el.sceneEl.object3D; 149 | 150 | //Determine positioning 151 | var position = this.data.relative ? new THREE.Vector3(0, 0, 0) : this.data.position; 152 | 153 | //Load texture (Three r84 upward doesn't support progress) 154 | var textureLoader = new THREE.TextureLoader(); 155 | var textureFlare = textureLoader.load(this.data.src.currentSrc, function (texture) { 156 | return texture; 157 | }, undefined, function (error) { 158 | throw new Error('An error occured loading the Flare texture'); 159 | }); 160 | 161 | this.lensFlare = new THREE.Lensflare(); 162 | this.lensFlareElement = new THREE.LensflareElement(textureFlare, this.data.size, 0.0, new THREE.Color(this.data.lightColor)); 163 | this.lensFlare.addElement(this.lensFlareElement); 164 | this.lensFlare.position.copy(position); 165 | 166 | //Determine if the user wants a light 167 | if (this.data.createLight) { 168 | 169 | var light = this.setLightType(this.data.lightType.toLowerCase(), this.data); 170 | 171 | //Has a target been supplied? 172 | var hasTarget = this.data.target ? this.data.target : false; 173 | 174 | //Set light target. 175 | if (hasTarget) { 176 | light.target = document.querySelector(this.data.target).object3D; 177 | sceneEl.add(light.target); 178 | sceneEl.updateMatrixWorld(); 179 | } 180 | light.position.set(position.x, position.y, position.z); 181 | 182 | //If relative, we want to attach the lensflare, and the light as child objects and call updateMatrixWorld once. 183 | if (this.data.relative) { 184 | light.add(this.lensFlare); 185 | parentEl.add(light); 186 | sceneEl.updateMatrixWorld(); 187 | } else { 188 | scene.add(light); 189 | } 190 | } else { 191 | //If relative, we want to attach the lensflare as a child object. This is so our lensflare works with animation updates. 192 | if (this.data.relative) { 193 | parentEl.add(this.lensFlare); 194 | sceneEl.updateMatrixWorld(); 195 | } else { 196 | scene.add(this.lensFlare); 197 | } 198 | } 199 | }, 200 | 201 | /** 202 | * Called when component is attached and when component data changes. 203 | * Generally modifies the entity based on the data. 204 | */ 205 | update: function update(oldData) {}, 206 | 207 | /** 208 | * Called when a component is removed (e.g., via removeAttribute). 209 | * Generally undoes all modifications to the entity. 210 | */ 211 | remove: function remove() {}, 212 | 213 | /** 214 | * Called on each scene tick. 215 | */ 216 | // tick: function (t) { }, 217 | 218 | /** 219 | * Called when entity pauses. 220 | * Use to stop or remove any dynamic or background behavior such as events. 221 | */ 222 | pause: function pause() {}, 223 | 224 | /** 225 | * Called when entity resumes. 226 | * Use to continue or add any dynamic or background behavior such as events. 227 | */ 228 | play: function play() {} 229 | }); 230 | 231 | /***/ }), 232 | /* 1 */ 233 | /***/ (function(module, exports) { 234 | 235 | 'use strict'; 236 | 237 | /** 238 | * @author Mugen87 / https://github.com/Mugen87 239 | * @author mrdoob / http://mrdoob.com/ 240 | */ 241 | 242 | THREE.Lensflare = function () { 243 | 244 | THREE.Mesh.call(this, THREE.Lensflare.Geometry, new THREE.MeshBasicMaterial({ opacity: 0, transparent: true })); 245 | 246 | this.type = 'Lensflare'; 247 | this.frustumCulled = false; 248 | this.renderOrder = Infinity; 249 | 250 | // 251 | 252 | var positionScreen = new THREE.Vector3(); 253 | var positionView = new THREE.Vector3(); 254 | 255 | // textures 256 | 257 | var tempMap = new THREE.DataTexture(new Uint8Array(16 * 16 * 3), 16, 16, THREE.RGBFormat); 258 | tempMap.minFilter = THREE.NearestFilter; 259 | tempMap.magFilter = THREE.NearestFilter; 260 | tempMap.wrapS = THREE.ClampToEdgeWrapping; 261 | tempMap.wrapT = THREE.ClampToEdgeWrapping; 262 | tempMap.needsUpdate = true; 263 | 264 | var occlusionMap = new THREE.DataTexture(new Uint8Array(16 * 16 * 3), 16, 16, THREE.RGBFormat); 265 | occlusionMap.minFilter = THREE.NearestFilter; 266 | occlusionMap.magFilter = THREE.NearestFilter; 267 | occlusionMap.wrapS = THREE.ClampToEdgeWrapping; 268 | occlusionMap.wrapT = THREE.ClampToEdgeWrapping; 269 | occlusionMap.needsUpdate = true; 270 | 271 | // material 272 | 273 | var geometry = THREE.Lensflare.Geometry; 274 | 275 | var material1a = new THREE.RawShaderMaterial({ 276 | uniforms: { 277 | 'scale': { value: null }, 278 | 'screenPosition': { value: null } 279 | }, 280 | vertexShader: ['precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'attribute vec3 position;', 'void main() {', ' gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', '}'].join('\n'), 281 | fragmentShader: ['precision highp float;', 'void main() {', ' gl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );', '}'].join('\n'), 282 | depthTest: true, 283 | depthWrite: false, 284 | transparent: false 285 | }); 286 | 287 | var material1b = new THREE.RawShaderMaterial({ 288 | uniforms: { 289 | 'map': { value: tempMap }, 290 | 'scale': { value: null }, 291 | 'screenPosition': { value: null } 292 | }, 293 | vertexShader: ['precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'attribute vec3 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'void main() {', ' vUV = uv;', ' gl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );', '}'].join('\n'), 294 | fragmentShader: ['precision highp float;', 'uniform sampler2D map;', 'varying vec2 vUV;', 'void main() {', ' gl_FragColor = texture2D( map, vUV );', '}'].join('\n'), 295 | depthTest: false, 296 | depthWrite: false, 297 | transparent: false 298 | }); 299 | 300 | // the following object is used for occlusionMap generation 301 | 302 | var mesh1 = new THREE.Mesh(geometry, material1a); 303 | 304 | // 305 | 306 | var elements = []; 307 | 308 | var shader = THREE.LensflareElement.Shader; 309 | 310 | var material2 = new THREE.RawShaderMaterial({ 311 | uniforms: { 312 | 'map': { value: null }, 313 | 'occlusionMap': { value: occlusionMap }, 314 | 'color': { value: new THREE.Color(0xffffff) }, 315 | 'scale': { value: new THREE.Vector2() }, 316 | 'screenPosition': { value: new THREE.Vector3() } 317 | }, 318 | vertexShader: shader.vertexShader, 319 | fragmentShader: shader.fragmentShader, 320 | blending: THREE.AdditiveBlending, 321 | transparent: true, 322 | depthWrite: false 323 | }); 324 | 325 | var mesh2 = new THREE.Mesh(geometry, material2); 326 | 327 | this.addElement = function (element) { 328 | 329 | elements.push(element); 330 | }; 331 | 332 | // 333 | 334 | var scale = new THREE.Vector2(); 335 | var screenPositionPixels = new THREE.Vector2(); 336 | var validArea = new THREE.Box2(); 337 | var viewport = new THREE.Vector4(); 338 | 339 | this.onBeforeRender = function (renderer, scene, camera) { 340 | 341 | renderer.getCurrentViewport(viewport); 342 | 343 | var invAspect = viewport.w / viewport.z; 344 | var halfViewportWidth = viewport.z / 2.0; 345 | var halfViewportHeight = viewport.w / 2.0; 346 | 347 | var size = 16 / viewport.w; 348 | scale.set(size * invAspect, size); 349 | 350 | validArea.min.set(viewport.x, viewport.y); 351 | validArea.max.set(viewport.x + (viewport.z - 16), viewport.y + (viewport.w - 16)); 352 | 353 | // calculate position in screen space 354 | 355 | positionView.setFromMatrixPosition(this.matrixWorld); 356 | positionView.applyMatrix4(camera.matrixWorldInverse); 357 | 358 | if (positionView.z > 0) return; // lensflare is behind the camera 359 | 360 | positionScreen.copy(positionView).applyMatrix4(camera.projectionMatrix); 361 | 362 | // horizontal and vertical coordinate of the lower left corner of the pixels to copy 363 | 364 | screenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8; 365 | screenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8; 366 | 367 | // screen cull 368 | 369 | if (validArea.containsPoint(screenPositionPixels)) { 370 | 371 | // save current RGB to temp texture 372 | 373 | renderer.copyFramebufferToTexture(screenPositionPixels, tempMap); 374 | 375 | // render pink quad 376 | 377 | var uniforms = material1a.uniforms; 378 | uniforms["scale"].value = scale; 379 | uniforms["screenPosition"].value = positionScreen; 380 | 381 | renderer.renderBufferDirect(camera, null, geometry, material1a, mesh1, null); 382 | 383 | // copy result to occlusionMap 384 | 385 | renderer.copyFramebufferToTexture(screenPositionPixels, occlusionMap); 386 | 387 | // restore graphics 388 | 389 | var uniforms = material1b.uniforms; 390 | uniforms["scale"].value = scale; 391 | uniforms["screenPosition"].value = positionScreen; 392 | 393 | renderer.renderBufferDirect(camera, null, geometry, material1b, mesh1, null); 394 | 395 | // render elements 396 | 397 | var vecX = -positionScreen.x * 2; 398 | var vecY = -positionScreen.y * 2; 399 | 400 | for (var i = 0, l = elements.length; i < l; i++) { 401 | 402 | var element = elements[i]; 403 | 404 | var uniforms = material2.uniforms; 405 | 406 | uniforms["color"].value.copy(element.color); 407 | uniforms["map"].value = element.texture; 408 | uniforms["screenPosition"].value.x = positionScreen.x + vecX * element.distance; 409 | uniforms["screenPosition"].value.y = positionScreen.y + vecY * element.distance; 410 | 411 | var size = element.size / viewport.w; 412 | var invAspect = viewport.w / viewport.z; 413 | 414 | uniforms["scale"].value.set(size * invAspect, size); 415 | 416 | material2.uniformsNeedUpdate = true; 417 | 418 | renderer.renderBufferDirect(camera, null, geometry, material2, mesh2, null); 419 | } 420 | } 421 | }; 422 | 423 | this.dispose = function () { 424 | 425 | material1a.dispose(); 426 | material1b.dispose(); 427 | material2.dispose(); 428 | 429 | tempMap.dispose(); 430 | occlusionMap.dispose(); 431 | 432 | for (var i = 0, l = elements.length; i < l; i++) { 433 | 434 | elements[i].texture.dispose(); 435 | } 436 | }; 437 | }; 438 | 439 | THREE.Lensflare.prototype = Object.create(THREE.Mesh.prototype); 440 | THREE.Lensflare.prototype.constructor = THREE.Lensflare; 441 | THREE.Lensflare.prototype.isLensflare = true; 442 | 443 | // 444 | 445 | THREE.LensflareElement = function (texture, size, distance, color) { 446 | 447 | this.texture = texture; 448 | this.size = size || 1; 449 | this.distance = distance || 0; 450 | this.color = color || new THREE.Color(0xffffff); 451 | }; 452 | 453 | THREE.LensflareElement.Shader = { 454 | 455 | uniforms: { 456 | 457 | 'map': { value: null }, 458 | 'occlusionMap': { value: null }, 459 | 'color': { value: null }, 460 | 'scale': { value: null }, 461 | 'screenPosition': { value: null } 462 | 463 | }, 464 | 465 | vertexShader: ['precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'uniform sampler2D occlusionMap;', 'attribute vec3 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'varying float vVisibility;', 'void main() {', ' vUV = uv;', ' vec2 pos = position.xy;', ' vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', ' visibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', ' vVisibility = visibility.r / 9.0;', ' vVisibility *= 1.0 - visibility.g / 9.0;', ' vVisibility *= visibility.b / 9.0;', ' gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', '}'].join('\n'), 466 | 467 | fragmentShader: ['precision highp float;', 'uniform sampler2D map;', 'uniform vec3 color;', 'varying vec2 vUV;', 'varying float vVisibility;', 'void main() {', ' vec4 texture = texture2D( map, vUV );', ' texture.a *= vVisibility;', ' gl_FragColor = texture;', ' gl_FragColor.rgb *= color;', '}'].join('\n') 468 | 469 | }; 470 | 471 | THREE.Lensflare.Geometry = function () { 472 | 473 | var geometry = new THREE.BufferGeometry(); 474 | 475 | var float32Array = new Float32Array([-1, -1, 0, 0, 0, 1, -1, 0, 1, 0, 1, 1, 0, 1, 1, -1, 1, 0, 0, 1]); 476 | 477 | var interleavedBuffer = new THREE.InterleavedBuffer(float32Array, 5); 478 | 479 | geometry.setIndex([0, 1, 2, 0, 2, 3]); 480 | geometry.addAttribute('position', new THREE.InterleavedBufferAttribute(interleavedBuffer, 3, 0, false)); 481 | geometry.addAttribute('uv', new THREE.InterleavedBufferAttribute(interleavedBuffer, 2, 3, false)); 482 | 483 | return geometry; 484 | }(); 485 | 486 | /***/ }) 487 | /******/ ]); 488 | //# sourceMappingURL=aframe-lensflare-component.js.map -------------------------------------------------------------------------------- /dist/aframe-lensflare-component.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///webpack/bootstrap 2c280269332efe31211c","webpack:///./index.js","webpack:///./Lensflare.js"],"names":["AFRAME","Error","THREE","require","registerComponent","schema","src","type","createLight","default","position","target","intensity","relative","size","lightColor","lightDistance","lightAngle","Math","PI","lightPenumbra","lightDecay","lightType","oneOf","multiple","setLightType","settings","SpotLight","Color","PointLight","DirectionalLight","init","scene","document","querySelector","object3D","parentEl","el","sceneEl","data","Vector3","textureLoader","TextureLoader","textureFlare","load","currentSrc","texture","undefined","error","lensFlare","Lensflare","lensFlareElement","LensflareElement","addElement","copy","light","toLowerCase","hasTarget","add","updateMatrixWorld","set","x","y","z","update","oldData","remove","pause","play","Mesh","call","Geometry","MeshBasicMaterial","opacity","transparent","frustumCulled","renderOrder","Infinity","positionScreen","positionView","tempMap","DataTexture","Uint8Array","RGBFormat","minFilter","NearestFilter","magFilter","wrapS","ClampToEdgeWrapping","wrapT","needsUpdate","occlusionMap","geometry","material1a","RawShaderMaterial","uniforms","value","vertexShader","join","fragmentShader","depthTest","depthWrite","material1b","mesh1","elements","shader","Shader","material2","Vector2","blending","AdditiveBlending","mesh2","element","push","scale","screenPositionPixels","validArea","Box2","viewport","Vector4","onBeforeRender","renderer","camera","getCurrentViewport","invAspect","w","halfViewportWidth","halfViewportHeight","min","max","setFromMatrixPosition","matrixWorld","applyMatrix4","matrixWorldInverse","projectionMatrix","containsPoint","copyFramebufferToTexture","renderBufferDirect","vecX","vecY","i","l","length","color","distance","uniformsNeedUpdate","dispose","prototype","Object","create","constructor","isLensflare","BufferGeometry","float32Array","Float32Array","interleavedBuffer","InterleavedBuffer","setIndex","addAttribute","InterleavedBufferAttribute"],"mappings":";AAAA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA,uBAAe;AACf;AACA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;AACA;;;AAGA;AACA;;AAEA;AACA;;AAEA;AACA;;AAEA;AACA;;;;;;;;;ACtCA;AACA;;AAEA,KAAI,OAAOA,MAAP,KAAkB,WAAtB,EAAmC;AACjC,SAAM,IAAIC,KAAJ,CAAU,8DAAV,CAAN;AACD;;AAED,KAAI,OAAOC,KAAP,KAAiB,WAArB,EAAkC;AAChC,SAAM,IAAID,KAAJ,CAAU,6DAAV,CAAN;AACD;;AAED;AACA,oBAAAE,CAAQ,CAAR;;AAEA;;;AAGAH,QAAOI,iBAAP,CAAyB,WAAzB,EAAsC;AACpCC,WAAQ;AACNC,UAAK;AACHC,aAAM;AADH,MADC;AAINC,kBAAa;AACXD,aAAM,SADK;AAEXE,gBAAS;AAFE,MAJP;AAQNC,eAAU;AACRH,aAAM;AADE,MARJ;AAWNI,aAAQ;AACNJ,aAAM;AADA,MAXF;AAcNK,gBAAW;AACTL,aAAM,QADG;AAETE,gBAAS;AAFA,MAdL;AAkBNI,eAAU;AACRN,aAAM,SADE;AAERE,gBAAS;AAFD,MAlBJ;AAsBNK,WAAM;AACJP,aAAM,QADF;AAEJE,gBAAS;AAFL,MAtBA;AA0BNM,iBAAY;AACVR,aAAM,QADI;AAEVE,gBAAS;AAFC,MA1BN;AA8BNO,oBAAe;AACbT,aAAM,QADO;AAEbE,gBAAS;AAFI,MA9BT;AAkCNQ,iBAAY;AACVV,aAAM,QADI;AAEVE,gBAASS,KAAKC,EAAL,GAAU;AAFT,MAlCN;AAsCNC,oBAAe;AACbb,aAAM,QADO;AAEbE,gBAAS;AAFI,MAtCT;AA0CNY,iBAAY;AACVd,aAAM,QADI;AAEVE,gBAAS;AAFC,MA1CN;AA8CNa,gBAAW;AACTb,gBAAS,MADA;AAETc,cAAO,CAAC,aAAD,EAAgB,OAAhB,EAAyB,MAAzB;AAFE;AA9CL,IAD4B;;AAqDpC;;;AAGAC,aAAU,IAxD0B;;AA0DpC;;;;;;;AAOAC,iBAAc,sBAAUlB,IAAV,EAAgBmB,QAAhB,EAA0B;AACtC,aAAQnB,IAAR;AACE,YAAK,MAAL;AACE,gBAAO,IAAIL,MAAMyB,SAAV,CAAoB,IAAIzB,MAAM0B,KAAV,CAAgBF,SAASX,UAAzB,CAApB,EAA0DW,SAASd,SAAnE,EAA8Ec,SAASV,aAAvF,EAAsGU,SAAST,UAA/G,EAA2HS,SAASN,aAApI,EAAmJM,SAASL,UAA5J,CAAP;AACF,YAAK,OAAL;AACE,gBAAO,IAAInB,MAAM2B,UAAV,CAAqB,IAAI3B,MAAM0B,KAAV,CAAgBF,SAASX,UAAzB,CAArB,EAA2DW,SAASd,SAApE,EAA+Ec,SAASV,aAAxF,EAAuGU,SAASL,UAAhH,CAAP;AACF,YAAK,aAAL;AACE,gBAAO,IAAInB,MAAM4B,gBAAV,CAA2B,IAAI5B,MAAM0B,KAAV,CAAgBF,SAASX,UAAzB,CAA3B,EAAiEW,SAASd,SAA1E,CAAP;AANJ;AAQD,IA1EmC;AA2EpC;;;AAGAmB,SAAM,gBAAY;;AAEhB,SAAMC,QAAQC,SAASC,aAAT,CAAuB,SAAvB,EAAkCC,QAAhD;AACA,SAAMC,WAAW,KAAKC,EAAL,CAAQF,QAAzB;AACA,SAAMG,UAAU,KAAKD,EAAL,CAAQC,OAAR,CAAgBH,QAAhC;;AAEA;AACA,SAAMzB,WAAW,KAAK6B,IAAL,CAAU1B,QAAV,GAAqB,IAAIX,MAAMsC,OAAV,CAAkB,CAAlB,EAAqB,CAArB,EAAwB,CAAxB,CAArB,GAAkD,KAAKD,IAAL,CAAU7B,QAA7E;;AAEA;AACA,SAAM+B,gBAAgB,IAAIvC,MAAMwC,aAAV,EAAtB;AACA,SAAMC,eAAeF,cAAcG,IAAd,CAAmB,KAAKL,IAAL,CAAUjC,GAAV,CAAcuC,UAAjC,EACnB,UAAUC,OAAV,EAAmB;AACjB,cAAOA,OAAP;AACD,MAHkB,EAInBC,SAJmB,EAKnB,UAAUC,KAAV,EAAiB;AACf,aAAM,IAAI/C,KAAJ,CAAU,4CAAV,CAAN;AACD,MAPkB,CAArB;;AAUA,UAAKgD,SAAL,GAAiB,IAAI/C,MAAMgD,SAAV,EAAjB;AACA,UAAKC,gBAAL,GAAwB,IAAIjD,MAAMkD,gBAAV,CAA2BT,YAA3B,EAAyC,KAAKJ,IAAL,CAAUzB,IAAnD,EAAyD,GAAzD,EAA8D,IAAIZ,MAAM0B,KAAV,CAAgB,KAAKW,IAAL,CAAUxB,UAA1B,CAA9D,CAAxB;AACA,UAAKkC,SAAL,CAAeI,UAAf,CAA0B,KAAKF,gBAA/B;AACA,UAAKF,SAAL,CAAevC,QAAf,CAAwB4C,IAAxB,CAA6B5C,QAA7B;;AAIA;AACA,SAAI,KAAK6B,IAAL,CAAU/B,WAAd,EAA2B;;AAEzB,WAAM+C,QAAQ,KAAK9B,YAAL,CAAkB,KAAKc,IAAL,CAAUjB,SAAV,CAAoBkC,WAApB,EAAlB,EAAqD,KAAKjB,IAA1D,CAAd;;AAEA;AACA,WAAMkB,YAAY,KAAKlB,IAAL,CAAU5B,MAAV,GAAmB,KAAK4B,IAAL,CAAU5B,MAA7B,GAAsC,KAAxD;;AAEA;AACA,WAAI8C,SAAJ,EAAe;AACbF,eAAM5C,MAAN,GAAesB,SAASC,aAAT,CAAuB,KAAKK,IAAL,CAAU5B,MAAjC,EAAyCwB,QAAxD;AACAG,iBAAQoB,GAAR,CAAYH,MAAM5C,MAAlB;AACA2B,iBAAQqB,iBAAR;AACD;AACDJ,aAAM7C,QAAN,CAAekD,GAAf,CAAmBlD,SAASmD,CAA5B,EAA+BnD,SAASoD,CAAxC,EAA2CpD,SAASqD,CAApD;;AAEA;AACA,WAAI,KAAKxB,IAAL,CAAU1B,QAAd,EAAwB;AACtB0C,eAAMG,GAAN,CAAU,KAAKT,SAAf;AACAb,kBAASsB,GAAT,CAAaH,KAAb;AACAjB,iBAAQqB,iBAAR;AACD,QAJD,MAIO;AACL3B,eAAM0B,GAAN,CAAUH,KAAV;AACD;AACF,MAvBD,MAuBO;AACL;AACA,WAAI,KAAKhB,IAAL,CAAU1B,QAAd,EAAwB;AACtBuB,kBAASsB,GAAT,CAAa,KAAKT,SAAlB;AACAX,iBAAQqB,iBAAR;AACD,QAHD,MAGO;AACL3B,eAAM0B,GAAN,CAAU,KAAKT,SAAf;AACD;AACF;AAGF,IA7ImC;;AA+IpC;;;;AAIAe,WAAQ,gBAAUC,OAAV,EAAmB,CAE1B,CArJmC;;AAuJpC;;;;AAIAC,WAAQ,kBAAY,CAAG,CA3Ja;;AA6JpC;;;AAGA;;AAEA;;;;AAIAC,UAAO,iBAAY,CAAG,CAtKc;;AAwKpC;;;;AAIAC,SAAM,gBAAY,CAAG;AA5Ke,EAAtC,E;;;;;;;;ACjBA;;;;;AAKAlE,OAAMgD,SAAN,GAAkB,YAAY;;AAE7BhD,QAAMmE,IAAN,CAAWC,IAAX,CAAiB,IAAjB,EAAuBpE,MAAMgD,SAAN,CAAgBqB,QAAvC,EAAiD,IAAIrE,MAAMsE,iBAAV,CAA6B,EAAEC,SAAS,CAAX,EAAcC,aAAa,IAA3B,EAA7B,CAAjD;;AAEA,OAAKnE,IAAL,GAAY,WAAZ;AACA,OAAKoE,aAAL,GAAqB,KAArB;AACA,OAAKC,WAAL,GAAmBC,QAAnB;;AAEA;;AAEA,MAAIC,iBAAiB,IAAI5E,MAAMsC,OAAV,EAArB;AACA,MAAIuC,eAAe,IAAI7E,MAAMsC,OAAV,EAAnB;;AAEA;;AAEA,MAAIwC,UAAU,IAAI9E,MAAM+E,WAAV,CAAuB,IAAIC,UAAJ,CAAgB,KAAK,EAAL,GAAU,CAA1B,CAAvB,EAAsD,EAAtD,EAA0D,EAA1D,EAA8DhF,MAAMiF,SAApE,CAAd;AACAH,UAAQI,SAAR,GAAoBlF,MAAMmF,aAA1B;AACAL,UAAQM,SAAR,GAAoBpF,MAAMmF,aAA1B;AACAL,UAAQO,KAAR,GAAgBrF,MAAMsF,mBAAtB;AACAR,UAAQS,KAAR,GAAgBvF,MAAMsF,mBAAtB;AACAR,UAAQU,WAAR,GAAsB,IAAtB;;AAEA,MAAIC,eAAe,IAAIzF,MAAM+E,WAAV,CAAuB,IAAIC,UAAJ,CAAgB,KAAK,EAAL,GAAU,CAA1B,CAAvB,EAAsD,EAAtD,EAA0D,EAA1D,EAA8DhF,MAAMiF,SAApE,CAAnB;AACAQ,eAAaP,SAAb,GAAyBlF,MAAMmF,aAA/B;AACAM,eAAaL,SAAb,GAAyBpF,MAAMmF,aAA/B;AACAM,eAAaJ,KAAb,GAAqBrF,MAAMsF,mBAA3B;AACAG,eAAaF,KAAb,GAAqBvF,MAAMsF,mBAA3B;AACAG,eAAaD,WAAb,GAA2B,IAA3B;;AAEA;;AAEA,MAAIE,WAAW1F,MAAMgD,SAAN,CAAgBqB,QAA/B;;AAEA,MAAIsB,aAAa,IAAI3F,MAAM4F,iBAAV,CAA6B;AAC7CC,aAAU;AACT,aAAS,EAAEC,OAAO,IAAT,EADA;AAET,sBAAkB,EAAEA,OAAO,IAAT;AAFT,IADmC;AAK7CC,iBAAc,CAEb,wBAFa,EAIb,8BAJa,EAKb,qBALa,EAOb,0BAPa,EASb,eATa,EAWb,wFAXa,EAab,GAba,EAeZC,IAfY,CAeN,IAfM,CAL+B;AAqB7CC,mBAAgB,CAEf,wBAFe,EAIf,eAJe,EAMf,6CANe,EAQf,GARe,EAUdD,IAVc,CAUR,IAVQ,CArB6B;AAgC7CE,cAAW,IAhCkC;AAiC7CC,eAAY,KAjCiC;AAkC7C3B,gBAAa;AAlCgC,GAA7B,CAAjB;;AAqCA,MAAI4B,aAAa,IAAIpG,MAAM4F,iBAAV,CAA6B;AAC7CC,aAAU;AACT,WAAO,EAAEC,OAAOhB,OAAT,EADE;AAET,aAAS,EAAEgB,OAAO,IAAT,EAFA;AAGT,sBAAkB,EAAEA,OAAO,IAAT;AAHT,IADmC;AAM7CC,iBAAc,CAEb,wBAFa,EAIb,8BAJa,EAKb,qBALa,EAOb,0BAPa,EAQb,oBARa,EAUb,mBAVa,EAYb,eAZa,EAcb,YAda,EAgBb,wFAhBa,EAkBb,GAlBa,EAoBZC,IApBY,CAoBN,IApBM,CAN+B;AA2B7CC,mBAAgB,CAEf,wBAFe,EAIf,wBAJe,EAMf,mBANe,EAQf,eARe,EAUf,wCAVe,EAYf,GAZe,EAcdD,IAdc,CAcR,IAdQ,CA3B6B;AA0C7CE,cAAW,KA1CkC;AA2C7CC,eAAY,KA3CiC;AA4C7C3B,gBAAa;AA5CgC,GAA7B,CAAjB;;AA+CA;;AAEA,MAAI6B,QAAQ,IAAIrG,MAAMmE,IAAV,CAAgBuB,QAAhB,EAA0BC,UAA1B,CAAZ;;AAEA;;AAEA,MAAIW,WAAW,EAAf;;AAEA,MAAIC,SAASvG,MAAMkD,gBAAN,CAAuBsD,MAApC;;AAEA,MAAIC,YAAY,IAAIzG,MAAM4F,iBAAV,CAA6B;AAC5CC,aAAU;AACT,WAAO,EAAEC,OAAO,IAAT,EADE;AAET,oBAAgB,EAAEA,OAAOL,YAAT,EAFP;AAGT,aAAS,EAAEK,OAAO,IAAI9F,MAAM0B,KAAV,CAAiB,QAAjB,CAAT,EAHA;AAIT,aAAS,EAAEoE,OAAO,IAAI9F,MAAM0G,OAAV,EAAT,EAJA;AAKT,sBAAkB,EAAEZ,OAAO,IAAI9F,MAAMsC,OAAV,EAAT;AALT,IADkC;AAQ5CyD,iBAAcQ,OAAOR,YARuB;AAS5CE,mBAAgBM,OAAON,cATqB;AAU5CU,aAAU3G,MAAM4G,gBAV4B;AAW5CpC,gBAAa,IAX+B;AAY5C2B,eAAY;AAZgC,GAA7B,CAAhB;;AAeA,MAAIU,QAAQ,IAAI7G,MAAMmE,IAAV,CAAgBuB,QAAhB,EAA0Be,SAA1B,CAAZ;;AAEA,OAAKtD,UAAL,GAAkB,UAAW2D,OAAX,EAAqB;;AAEtCR,YAASS,IAAT,CAAeD,OAAf;AAEA,GAJD;;AAMA;;AAEA,MAAIE,QAAQ,IAAIhH,MAAM0G,OAAV,EAAZ;AACA,MAAIO,uBAAuB,IAAIjH,MAAM0G,OAAV,EAA3B;AACA,MAAIQ,YAAY,IAAIlH,MAAMmH,IAAV,EAAhB;AACA,MAAIC,WAAW,IAAIpH,MAAMqH,OAAV,EAAf;;AAEA,OAAKC,cAAL,GAAsB,UAAWC,QAAX,EAAqBzF,KAArB,EAA4B0F,MAA5B,EAAqC;;AAE1DD,YAASE,kBAAT,CAA6BL,QAA7B;;AAEA,OAAIM,YAAYN,SAASO,CAAT,GAAaP,SAASvD,CAAtC;AACA,OAAI+D,oBAAoBR,SAASvD,CAAT,GAAa,GAArC;AACA,OAAIgE,qBAAqBT,SAASO,CAAT,GAAa,GAAtC;;AAEA,OAAI/G,OAAO,KAAKwG,SAASO,CAAzB;AACAX,SAAMtD,GAAN,CAAW9C,OAAO8G,SAAlB,EAA6B9G,IAA7B;;AAEAsG,aAAUY,GAAV,CAAcpE,GAAd,CAAmB0D,SAASzD,CAA5B,EAA+ByD,SAASxD,CAAxC;AACAsD,aAAUa,GAAV,CAAcrE,GAAd,CAAmB0D,SAASzD,CAAT,IAAeyD,SAASvD,CAAT,GAAa,EAA5B,CAAnB,EAAqDuD,SAASxD,CAAT,IAAewD,SAASO,CAAT,GAAa,EAA5B,CAArD;;AAEA;;AAEA9C,gBAAamD,qBAAb,CAAoC,KAAKC,WAAzC;AACApD,gBAAaqD,YAAb,CAA2BV,OAAOW,kBAAlC;;AAEA,OAAKtD,aAAahB,CAAb,GAAiB,CAAtB,EAA0B,OAnBgC,CAmBxB;;AAElCe,kBAAexB,IAAf,CAAqByB,YAArB,EAAoCqD,YAApC,CAAkDV,OAAOY,gBAAzD;;AAEA;;AAEAnB,wBAAqBtD,CAArB,GAAyByD,SAASzD,CAAT,GAAeiB,eAAejB,CAAf,GAAmBiE,iBAAlC,GAAwDA,iBAAxD,GAA4E,CAArG;AACAX,wBAAqBrD,CAArB,GAAyBwD,SAASxD,CAAT,GAAegB,eAAehB,CAAf,GAAmBiE,kBAAlC,GAAyDA,kBAAzD,GAA8E,CAAvG;;AAEA;;AAEA,OAAKX,UAAUmB,aAAV,CAAyBpB,oBAAzB,CAAL,EAAuD;;AAEtD;;AAEAM,aAASe,wBAAT,CAAmCrB,oBAAnC,EAAyDnC,OAAzD;;AAEA;;AAEA,QAAIe,WAAWF,WAAWE,QAA1B;AACAA,aAAU,OAAV,EAAoBC,KAApB,GAA4BkB,KAA5B;AACAnB,aAAU,gBAAV,EAA6BC,KAA7B,GAAqClB,cAArC;;AAEA2C,aAASgB,kBAAT,CAA6Bf,MAA7B,EAAqC,IAArC,EAA2C9B,QAA3C,EAAqDC,UAArD,EAAiEU,KAAjE,EAAwE,IAAxE;;AAEA;;AAEAkB,aAASe,wBAAT,CAAmCrB,oBAAnC,EAAyDxB,YAAzD;;AAEA;;AAEA,QAAII,WAAWO,WAAWP,QAA1B;AACAA,aAAU,OAAV,EAAoBC,KAApB,GAA4BkB,KAA5B;AACAnB,aAAU,gBAAV,EAA6BC,KAA7B,GAAqClB,cAArC;;AAEA2C,aAASgB,kBAAT,CAA6Bf,MAA7B,EAAqC,IAArC,EAA2C9B,QAA3C,EAAqDU,UAArD,EAAiEC,KAAjE,EAAwE,IAAxE;;AAEA;;AAEA,QAAImC,OAAO,CAAE5D,eAAejB,CAAjB,GAAqB,CAAhC;AACA,QAAI8E,OAAO,CAAE7D,eAAehB,CAAjB,GAAqB,CAAhC;;AAEA,SAAM,IAAI8E,IAAI,CAAR,EAAWC,IAAIrC,SAASsC,MAA9B,EAAsCF,IAAIC,CAA1C,EAA6CD,GAA7C,EAAoD;;AAEnD,SAAI5B,UAAUR,SAAUoC,CAAV,CAAd;;AAEA,SAAI7C,WAAWY,UAAUZ,QAAzB;;AAEAA,cAAU,OAAV,EAAoBC,KAApB,CAA0B1C,IAA1B,CAAgC0D,QAAQ+B,KAAxC;AACAhD,cAAU,KAAV,EAAkBC,KAAlB,GAA0BgB,QAAQlE,OAAlC;AACAiD,cAAU,gBAAV,EAA6BC,KAA7B,CAAmCnC,CAAnC,GAAuCiB,eAAejB,CAAf,GAAmB6E,OAAO1B,QAAQgC,QAAzE;AACAjD,cAAU,gBAAV,EAA6BC,KAA7B,CAAmClC,CAAnC,GAAuCgB,eAAehB,CAAf,GAAmB6E,OAAO3B,QAAQgC,QAAzE;;AAEA,SAAIlI,OAAOkG,QAAQlG,IAAR,GAAewG,SAASO,CAAnC;AACA,SAAID,YAAYN,SAASO,CAAT,GAAaP,SAASvD,CAAtC;;AAEAgC,cAAU,OAAV,EAAoBC,KAApB,CAA0BpC,GAA1B,CAA+B9C,OAAO8G,SAAtC,EAAiD9G,IAAjD;;AAEA6F,eAAUsC,kBAAV,GAA+B,IAA/B;;AAEAxB,cAASgB,kBAAT,CAA6Bf,MAA7B,EAAqC,IAArC,EAA2C9B,QAA3C,EAAqDe,SAArD,EAAgEI,KAAhE,EAAuE,IAAvE;AAEA;AAED;AAED,GArFD;;AAuFA,OAAKmC,OAAL,GAAe,YAAY;;AAE1BrD,cAAWqD,OAAX;AACA5C,cAAW4C,OAAX;AACAvC,aAAUuC,OAAV;;AAEAlE,WAAQkE,OAAR;AACAvD,gBAAauD,OAAb;;AAEA,QAAM,IAAIN,IAAI,CAAR,EAAWC,IAAIrC,SAASsC,MAA9B,EAAsCF,IAAIC,CAA1C,EAA6CD,GAA7C,EAAoD;;AAEnDpC,aAAUoC,CAAV,EAAc9F,OAAd,CAAsBoG,OAAtB;AAEA;AAED,GAfD;AAiBA,EArQD;;AAuQAhJ,OAAMgD,SAAN,CAAgBiG,SAAhB,GAA4BC,OAAOC,MAAP,CAAenJ,MAAMmE,IAAN,CAAW8E,SAA1B,CAA5B;AACAjJ,OAAMgD,SAAN,CAAgBiG,SAAhB,CAA0BG,WAA1B,GAAwCpJ,MAAMgD,SAA9C;AACAhD,OAAMgD,SAAN,CAAgBiG,SAAhB,CAA0BI,WAA1B,GAAwC,IAAxC;;AAEA;;AAEArJ,OAAMkD,gBAAN,GAAyB,UAAWN,OAAX,EAAoBhC,IAApB,EAA0BkI,QAA1B,EAAoCD,KAApC,EAA4C;;AAEpE,OAAKjG,OAAL,GAAeA,OAAf;AACA,OAAKhC,IAAL,GAAYA,QAAQ,CAApB;AACA,OAAKkI,QAAL,GAAgBA,YAAY,CAA5B;AACA,OAAKD,KAAL,GAAaA,SAAS,IAAI7I,MAAM0B,KAAV,CAAiB,QAAjB,CAAtB;AAEA,EAPD;;AASA1B,OAAMkD,gBAAN,CAAuBsD,MAAvB,GAAgC;;AAE/BX,YAAU;;AAET,UAAO,EAAEC,OAAO,IAAT,EAFE;AAGT,mBAAgB,EAAEA,OAAO,IAAT,EAHP;AAIT,YAAS,EAAEA,OAAO,IAAT,EAJA;AAKT,YAAS,EAAEA,OAAO,IAAT,EALA;AAMT,qBAAkB,EAAEA,OAAO,IAAT;;AANT,GAFqB;;AAY/BC,gBAAc,CAEb,wBAFa,EAIb,8BAJa,EAKb,qBALa,EAOb,iCAPa,EASb,0BATa,EAUb,oBAVa,EAYb,mBAZa,EAab,4BAba,EAeb,eAfa,EAiBb,YAjBa,EAmBb,0BAnBa,EAqBb,iEArBa,EAsBb,6DAtBa,EAuBb,6DAvBa,EAwBb,6DAxBa,EAyBb,6DAzBa,EA0Bb,6DA1Ba,EA2Bb,6DA3Ba,EA4Bb,6DA5Ba,EA6Bb,6DA7Ba,EA+Bb,2CA/Ba,EAgCb,2CAhCa,EAiCb,2CAjCa,EAmCb,uFAnCa,EAqCb,GArCa,EAuCZC,IAvCY,CAuCN,IAvCM,CAZiB;;AAqD/BC,kBAAgB,CAEf,wBAFe,EAIf,wBAJe,EAKf,qBALe,EAOf,mBAPe,EAQf,4BARe,EAUf,eAVe,EAYf,wCAZe,EAaf,4BAbe,EAcf,0BAde,EAef,6BAfe,EAiBf,GAjBe,EAmBdD,IAnBc,CAmBR,IAnBQ;;AArDe,EAAhC;;AA4EAhG,OAAMgD,SAAN,CAAgBqB,QAAhB,GAA6B,YAAY;;AAExC,MAAIqB,WAAW,IAAI1F,MAAMsJ,cAAV,EAAf;;AAEA,MAAIC,eAAe,IAAIC,YAAJ,CAAkB,CACpC,CAAE,CADkC,EAC/B,CAAE,CAD6B,EAC1B,CAD0B,EACvB,CADuB,EACpB,CADoB,EAEpC,CAFoC,EAEjC,CAAE,CAF+B,EAE5B,CAF4B,EAEzB,CAFyB,EAEtB,CAFsB,EAGpC,CAHoC,EAGjC,CAHiC,EAG9B,CAH8B,EAG3B,CAH2B,EAGxB,CAHwB,EAIpC,CAAE,CAJkC,EAI/B,CAJ+B,EAI5B,CAJ4B,EAIzB,CAJyB,EAItB,CAJsB,CAAlB,CAAnB;;AAOA,MAAIC,oBAAoB,IAAIzJ,MAAM0J,iBAAV,CAA6BH,YAA7B,EAA2C,CAA3C,CAAxB;;AAEA7D,WAASiE,QAAT,CAAmB,CAAE,CAAF,EAAK,CAAL,EAAQ,CAAR,EAAW,CAAX,EAAc,CAAd,EAAiB,CAAjB,CAAnB;AACAjE,WAASkE,YAAT,CAAuB,UAAvB,EAAmC,IAAI5J,MAAM6J,0BAAV,CAAsCJ,iBAAtC,EAAyD,CAAzD,EAA4D,CAA5D,EAA+D,KAA/D,CAAnC;AACA/D,WAASkE,YAAT,CAAuB,IAAvB,EAA6B,IAAI5J,MAAM6J,0BAAV,CAAsCJ,iBAAtC,EAAyD,CAAzD,EAA4D,CAA5D,EAA+D,KAA/D,CAA7B;;AAEA,SAAO/D,QAAP;AAEA,EAnB0B,EAA3B,C","file":"aframe-lensflare-component.js","sourcesContent":[" \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 2c280269332efe31211c","/* global AFRAME */\n/* global THREE */\n\nif (typeof AFRAME === 'undefined') {\n throw new Error('Component attempted to register before AFRAME was available.')\n}\n\nif (typeof THREE === 'undefined') {\n throw new Error('Component attempted to register before THREE was available.')\n}\n\n//https://github.com/mrdoob/three.js/blob/master/examples/js/objects/Lensflare.js\nrequire('./Lensflare')\n\n/**\n * A-Frame Lensflare Component component for A-Frame.\n */\nAFRAME.registerComponent('lensflare', {\n schema: {\n src: {\n type: 'asset'\n },\n createLight: {\n type: 'boolean',\n default: true\n },\n position: {\n type: 'vec3'\n },\n target: {\n type: 'string'\n },\n intensity: {\n type: 'number',\n default: 5\n },\n relative: {\n type: 'boolean',\n default: true\n },\n size: {\n type: 'number',\n default: 500\n },\n lightColor: {\n type: 'string',\n default: 'rgb(255, 255, 255)'\n },\n lightDistance: {\n type: 'number',\n default: 4.0,\n },\n lightAngle: {\n type: 'number',\n default: Math.PI / 3,\n },\n lightPenumbra: {\n type: 'number',\n default: 0.077,\n },\n lightDecay: {\n type: 'number',\n default: 1,\n },\n lightType: {\n default: 'spot',\n oneOf: ['directional', 'point', 'spot']\n }\n },\n\n /**\n * Set if component needs multiple instancing.\n */\n multiple: true,\n\n /**\n * setLightType - Create a light based on lightType\n *\n * @param {String} type Type of the light, supplied as a string.\n * @param {Object} settings Additional settings to pass to the light. E.g. angle and decay\n * @return {THREE.Light} A THREE.JS light object\n */\n setLightType: function (type, settings) {\n switch (type) {\n case 'spot':\n return new THREE.SpotLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightAngle, settings.lightPenumbra, settings.lightDecay)\n case 'point':\n return new THREE.PointLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightDecay)\n case 'directional':\n return new THREE.DirectionalLight(new THREE.Color(settings.lightColor), settings.intensity)\n }\n },\n /**\n * Called once when component is attached. Generally for initial setup.\n */\n init: function () {\n\n const scene = document.querySelector('a-scene').object3D;\n const parentEl = this.el.object3D\n const sceneEl = this.el.sceneEl.object3D\n\n //Determine positioning\n const position = this.data.relative ? new THREE.Vector3(0, 0, 0) : this.data.position\n\n //Load texture (Three r84 upward doesn't support progress)\n const textureLoader = new THREE.TextureLoader()\n const textureFlare = textureLoader.load(this.data.src.currentSrc,\n function (texture) {\n return texture\n },\n undefined,\n function (error) {\n throw new Error('An error occured loading the Flare texture')\n }\n )\n\n this.lensFlare = new THREE.Lensflare()\n this.lensFlareElement = new THREE.LensflareElement(textureFlare, this.data.size, 0.0, new THREE.Color(this.data.lightColor))\n this.lensFlare.addElement(this.lensFlareElement);\n this.lensFlare.position.copy(position)\n\n\n\n //Determine if the user wants a light\n if (this.data.createLight) {\n\n const light = this.setLightType(this.data.lightType.toLowerCase(), this.data)\n\n //Has a target been supplied?\n const hasTarget = this.data.target ? this.data.target : false\n\n //Set light target.\n if (hasTarget) {\n light.target = document.querySelector(this.data.target).object3D\n sceneEl.add(light.target)\n sceneEl.updateMatrixWorld()\n }\n light.position.set(position.x, position.y, position.z)\n\n //If relative, we want to attach the lensflare, and the light as child objects and call updateMatrixWorld once.\n if (this.data.relative) {\n light.add(this.lensFlare)\n parentEl.add(light)\n sceneEl.updateMatrixWorld()\n } else {\n scene.add(light)\n }\n } else {\n //If relative, we want to attach the lensflare as a child object. This is so our lensflare works with animation updates.\n if (this.data.relative) {\n parentEl.add(this.lensFlare)\n sceneEl.updateMatrixWorld()\n } else {\n scene.add(this.lensFlare)\n }\n }\n\n\n },\n\n /**\n * Called when component is attached and when component data changes.\n * Generally modifies the entity based on the data.\n */\n update: function (oldData) {\n\n },\n\n /**\n * Called when a component is removed (e.g., via removeAttribute).\n * Generally undoes all modifications to the entity.\n */\n remove: function () { },\n\n /**\n * Called on each scene tick.\n */\n // tick: function (t) { },\n\n /**\n * Called when entity pauses.\n * Use to stop or remove any dynamic or background behavior such as events.\n */\n pause: function () { },\n\n /**\n * Called when entity resumes.\n * Use to continue or add any dynamic or background behavior such as events.\n */\n play: function () { }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./index.js","/**\r\n * @author Mugen87 / https://github.com/Mugen87\r\n * @author mrdoob / http://mrdoob.com/\r\n */\r\n\r\nTHREE.Lensflare = function () {\r\n\r\n\tTHREE.Mesh.call( this, THREE.Lensflare.Geometry, new THREE.MeshBasicMaterial( { opacity: 0, transparent: true } ) );\r\n\r\n\tthis.type = 'Lensflare';\r\n\tthis.frustumCulled = false;\r\n\tthis.renderOrder = Infinity;\r\n\r\n\t//\r\n\r\n\tvar positionScreen = new THREE.Vector3();\r\n\tvar positionView = new THREE.Vector3();\r\n\r\n\t// textures\r\n\r\n\tvar tempMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );\r\n\ttempMap.minFilter = THREE.NearestFilter;\r\n\ttempMap.magFilter = THREE.NearestFilter;\r\n\ttempMap.wrapS = THREE.ClampToEdgeWrapping;\r\n\ttempMap.wrapT = THREE.ClampToEdgeWrapping;\r\n\ttempMap.needsUpdate = true;\r\n\r\n\tvar occlusionMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );\r\n\tocclusionMap.minFilter = THREE.NearestFilter;\r\n\tocclusionMap.magFilter = THREE.NearestFilter;\r\n\tocclusionMap.wrapS = THREE.ClampToEdgeWrapping;\r\n\tocclusionMap.wrapT = THREE.ClampToEdgeWrapping;\r\n\tocclusionMap.needsUpdate = true;\r\n\r\n\t// material\r\n\r\n\tvar geometry = THREE.Lensflare.Geometry;\r\n\r\n\tvar material1a = new THREE.RawShaderMaterial( {\r\n\t\tuniforms: {\r\n\t\t\t'scale': { value: null },\r\n\t\t\t'screenPosition': { value: null }\r\n\t\t},\r\n\t\tvertexShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'uniform vec3 screenPosition;',\r\n\t\t\t'uniform vec2 scale;',\r\n\r\n\t\t\t'attribute vec3 position;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tgl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tfragmentShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tdepthTest: true,\r\n\t\tdepthWrite: false,\r\n\t\ttransparent: false\r\n\t} );\r\n\r\n\tvar material1b = new THREE.RawShaderMaterial( {\r\n\t\tuniforms: {\r\n\t\t\t'map': { value: tempMap },\r\n\t\t\t'scale': { value: null },\r\n\t\t\t'screenPosition': { value: null }\r\n\t\t},\r\n\t\tvertexShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'uniform vec3 screenPosition;',\r\n\t\t\t'uniform vec2 scale;',\r\n\r\n\t\t\t'attribute vec3 position;',\r\n\t\t\t'attribute vec2 uv;',\r\n\r\n\t\t\t'varying vec2 vUV;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tvUV = uv;',\r\n\r\n\t\t\t'\tgl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tfragmentShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'uniform sampler2D map;',\r\n\r\n\t\t\t'varying vec2 vUV;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tgl_FragColor = texture2D( map, vUV );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tdepthTest: false,\r\n\t\tdepthWrite: false,\r\n\t\ttransparent: false\r\n\t} );\r\n\r\n\t// the following object is used for occlusionMap generation\r\n\r\n\tvar mesh1 = new THREE.Mesh( geometry, material1a );\r\n\r\n\t//\r\n\r\n\tvar elements = [];\r\n\r\n\tvar shader = THREE.LensflareElement.Shader;\r\n\r\n\tvar material2 = new THREE.RawShaderMaterial( {\r\n\t\tuniforms: {\r\n\t\t\t'map': { value: null },\r\n\t\t\t'occlusionMap': { value: occlusionMap },\r\n\t\t\t'color': { value: new THREE.Color( 0xffffff ) },\r\n\t\t\t'scale': { value: new THREE.Vector2() },\r\n\t\t\t'screenPosition': { value: new THREE.Vector3() }\r\n\t\t},\r\n\t\tvertexShader: shader.vertexShader,\r\n\t\tfragmentShader: shader.fragmentShader,\r\n\t\tblending: THREE.AdditiveBlending,\r\n\t\ttransparent: true,\r\n\t\tdepthWrite: false\r\n\t} );\r\n\r\n\tvar mesh2 = new THREE.Mesh( geometry, material2 );\r\n\r\n\tthis.addElement = function ( element ) {\r\n\r\n\t\telements.push( element );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tvar scale = new THREE.Vector2();\r\n\tvar screenPositionPixels = new THREE.Vector2();\r\n\tvar validArea = new THREE.Box2();\r\n\tvar viewport = new THREE.Vector4();\r\n\r\n\tthis.onBeforeRender = function ( renderer, scene, camera ) {\r\n\r\n\t\trenderer.getCurrentViewport( viewport );\r\n\r\n\t\tvar invAspect = viewport.w / viewport.z;\r\n\t\tvar halfViewportWidth = viewport.z / 2.0;\r\n\t\tvar halfViewportHeight = viewport.w / 2.0;\r\n\r\n\t\tvar size = 16 / viewport.w;\r\n\t\tscale.set( size * invAspect, size );\r\n\r\n\t\tvalidArea.min.set( viewport.x, viewport.y );\r\n\t\tvalidArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );\r\n\r\n\t\t// calculate position in screen space\r\n\r\n\t\tpositionView.setFromMatrixPosition( this.matrixWorld );\r\n\t\tpositionView.applyMatrix4( camera.matrixWorldInverse );\r\n\r\n\t\tif ( positionView.z > 0 ) return; // lensflare is behind the camera\r\n\r\n\t\tpositionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix );\r\n\r\n\t\t// horizontal and vertical coordinate of the lower left corner of the pixels to copy\r\n\r\n\t\tscreenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8;\r\n\t\tscreenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8;\r\n\r\n\t\t// screen cull\r\n\r\n\t\tif ( validArea.containsPoint( screenPositionPixels ) ) {\r\n\r\n\t\t\t// save current RGB to temp texture\r\n\r\n\t\t\trenderer.copyFramebufferToTexture( screenPositionPixels, tempMap );\r\n\r\n\t\t\t// render pink quad\r\n\r\n\t\t\tvar uniforms = material1a.uniforms;\r\n\t\t\tuniforms[ \"scale\" ].value = scale;\r\n\t\t\tuniforms[ \"screenPosition\" ].value = positionScreen;\r\n\r\n\t\t\trenderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null );\r\n\r\n\t\t\t// copy result to occlusionMap\r\n\r\n\t\t\trenderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap );\r\n\r\n\t\t\t// restore graphics\r\n\r\n\t\t\tvar uniforms = material1b.uniforms;\r\n\t\t\tuniforms[ \"scale\" ].value = scale;\r\n\t\t\tuniforms[ \"screenPosition\" ].value = positionScreen;\r\n\r\n\t\t\trenderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null );\r\n\r\n\t\t\t// render elements\r\n\r\n\t\t\tvar vecX = - positionScreen.x * 2;\r\n\t\t\tvar vecY = - positionScreen.y * 2;\r\n\r\n\t\t\tfor ( var i = 0, l = elements.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar element = elements[ i ];\r\n\r\n\t\t\t\tvar uniforms = material2.uniforms;\r\n\r\n\t\t\t\tuniforms[ \"color\" ].value.copy( element.color );\r\n\t\t\t\tuniforms[ \"map\" ].value = element.texture;\r\n\t\t\t\tuniforms[ \"screenPosition\" ].value.x = positionScreen.x + vecX * element.distance;\r\n\t\t\t\tuniforms[ \"screenPosition\" ].value.y = positionScreen.y + vecY * element.distance;\r\n\r\n\t\t\t\tvar size = element.size / viewport.w;\r\n\t\t\t\tvar invAspect = viewport.w / viewport.z;\r\n\r\n\t\t\t\tuniforms[ \"scale\" ].value.set( size * invAspect, size );\r\n\r\n\t\t\t\tmaterial2.uniformsNeedUpdate = true;\r\n\r\n\t\t\t\trenderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tthis.dispose = function () {\r\n\r\n\t\tmaterial1a.dispose();\r\n\t\tmaterial1b.dispose();\r\n\t\tmaterial2.dispose();\r\n\r\n\t\ttempMap.dispose();\r\n\t\tocclusionMap.dispose();\r\n\r\n\t\tfor ( var i = 0, l = elements.length; i < l; i ++ ) {\r\n\r\n\t\t\telements[ i ].texture.dispose();\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n};\r\n\r\nTHREE.Lensflare.prototype = Object.create( THREE.Mesh.prototype );\r\nTHREE.Lensflare.prototype.constructor = THREE.Lensflare;\r\nTHREE.Lensflare.prototype.isLensflare = true;\r\n\r\n//\r\n\r\nTHREE.LensflareElement = function ( texture, size, distance, color ) {\r\n\r\n\tthis.texture = texture;\r\n\tthis.size = size || 1;\r\n\tthis.distance = distance || 0;\r\n\tthis.color = color || new THREE.Color( 0xffffff );\r\n\r\n};\r\n\r\nTHREE.LensflareElement.Shader = {\r\n\r\n\tuniforms: {\r\n\r\n\t\t'map': { value: null },\r\n\t\t'occlusionMap': { value: null },\r\n\t\t'color': { value: null },\r\n\t\t'scale': { value: null },\r\n\t\t'screenPosition': { value: null }\r\n\r\n\t},\r\n\r\n\tvertexShader: [\r\n\r\n\t\t'precision highp float;',\r\n\r\n\t\t'uniform vec3 screenPosition;',\r\n\t\t'uniform vec2 scale;',\r\n\r\n\t\t'uniform sampler2D occlusionMap;',\r\n\r\n\t\t'attribute vec3 position;',\r\n\t\t'attribute vec2 uv;',\r\n\r\n\t\t'varying vec2 vUV;',\r\n\t\t'varying float vVisibility;',\r\n\r\n\t\t'void main() {',\r\n\r\n\t\t'\tvUV = uv;',\r\n\r\n\t\t'\tvec2 pos = position.xy;',\r\n\r\n\t\t'\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );',\r\n\r\n\t\t'\tvVisibility = visibility.r / 9.0;',\r\n\t\t'\tvVisibility *= 1.0 - visibility.g / 9.0;',\r\n\t\t'\tvVisibility *= visibility.b / 9.0;',\r\n\r\n\t\t'\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );',\r\n\r\n\t\t'}'\r\n\r\n\t].join( '\\n' ),\r\n\r\n\tfragmentShader: [\r\n\r\n\t\t'precision highp float;',\r\n\r\n\t\t'uniform sampler2D map;',\r\n\t\t'uniform vec3 color;',\r\n\r\n\t\t'varying vec2 vUV;',\r\n\t\t'varying float vVisibility;',\r\n\r\n\t\t'void main() {',\r\n\r\n\t\t'\tvec4 texture = texture2D( map, vUV );',\r\n\t\t'\ttexture.a *= vVisibility;',\r\n\t\t'\tgl_FragColor = texture;',\r\n\t\t'\tgl_FragColor.rgb *= color;',\r\n\r\n\t\t'}'\r\n\r\n\t].join( '\\n' )\r\n\r\n};\r\n\r\nTHREE.Lensflare.Geometry = ( function () {\r\n\r\n\tvar geometry = new THREE.BufferGeometry();\r\n\r\n\tvar float32Array = new Float32Array( [\r\n\t\t- 1, - 1, 0, 0, 0,\r\n\t\t1, - 1, 0, 1, 0,\r\n\t\t1, 1, 0, 1, 1,\r\n\t\t- 1, 1, 0, 0, 1\r\n\t] );\r\n\r\n\tvar interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 );\r\n\r\n\tgeometry.setIndex( [ 0, 1, 2,\t0, 2, 3 ] );\r\n\tgeometry.addAttribute( 'position', new THREE.InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );\r\n\tgeometry.addAttribute( 'uv', new THREE.InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );\r\n\r\n\treturn geometry;\r\n\r\n} )();\r\n\n\n\n// WEBPACK FOOTER //\n// ./Lensflare.js"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/aframe-lensflare-component.min.js: -------------------------------------------------------------------------------- 1 | !function(e){function t(r){if(i[r])return i[r].exports;var n=i[r]={exports:{},id:r,loaded:!1};return e[r].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t,i){"use strict";if("undefined"==typeof AFRAME)throw new Error("Component attempted to register before AFRAME was available.");if("undefined"==typeof THREE)throw new Error("Component attempted to register before THREE was available.");i(1),AFRAME.registerComponent("lensflare",{schema:{src:{type:"asset"},createLight:{type:"boolean",default:!0},position:{type:"vec3"},target:{type:"string"},intensity:{type:"number",default:5},relative:{type:"boolean",default:!0},size:{type:"number",default:500},lightColor:{type:"string",default:"rgb(255, 255, 255)"},lightDistance:{type:"number",default:4},lightAngle:{type:"number",default:Math.PI/3},lightPenumbra:{type:"number",default:.077},lightDecay:{type:"number",default:1},lightType:{default:"spot",oneOf:["directional","point","spot"]}},multiple:!0,setLightType:function(e,t){switch(e){case"spot":return new THREE.SpotLight(new THREE.Color(t.lightColor),t.intensity,t.lightDistance,t.lightAngle,t.lightPenumbra,t.lightDecay);case"point":return new THREE.PointLight(new THREE.Color(t.lightColor),t.intensity,t.lightDistance,t.lightDecay);case"directional":return new THREE.DirectionalLight(new THREE.Color(t.lightColor),t.intensity)}},init:function(){var e=document.querySelector("a-scene").object3D,t=this.el.object3D,i=this.el.sceneEl.object3D,r=this.data.relative?new THREE.Vector3(0,0,0):this.data.position,n=new THREE.TextureLoader,a=n.load(this.data.src.currentSrc,function(e){return e},void 0,function(e){throw new Error("An error occured loading the Flare texture")});if(this.lensFlare=new THREE.Lensflare,this.lensFlareElement=new THREE.LensflareElement(a,this.data.size,0,new THREE.Color(this.data.lightColor)),this.lensFlare.addElement(this.lensFlareElement),this.lensFlare.position.copy(r),this.data.createLight){var o=this.setLightType(this.data.lightType.toLowerCase(),this.data),l=!!this.data.target&&this.data.target;l&&(o.target=document.querySelector(this.data.target).object3D,i.add(o.target),i.updateMatrixWorld()),o.position.set(r.x,r.y,r.z),this.data.relative?(o.add(this.lensFlare),t.add(o),i.updateMatrixWorld()):e.add(o)}else this.data.relative?(t.add(this.lensFlare),i.updateMatrixWorld()):e.add(this.lensFlare)},update:function(e){},remove:function(){},pause:function(){},play:function(){}})},function(e,t){"use strict";THREE.Lensflare=function(){THREE.Mesh.call(this,THREE.Lensflare.Geometry,new THREE.MeshBasicMaterial({opacity:0,transparent:!0})),this.type="Lensflare",this.frustumCulled=!1,this.renderOrder=1/0;var e=new THREE.Vector3,t=new THREE.Vector3,i=new THREE.DataTexture(new Uint8Array(768),16,16,THREE.RGBFormat);i.minFilter=THREE.NearestFilter,i.magFilter=THREE.NearestFilter,i.wrapS=THREE.ClampToEdgeWrapping,i.wrapT=THREE.ClampToEdgeWrapping,i.needsUpdate=!0;var r=new THREE.DataTexture(new Uint8Array(768),16,16,THREE.RGBFormat);r.minFilter=THREE.NearestFilter,r.magFilter=THREE.NearestFilter,r.wrapS=THREE.ClampToEdgeWrapping,r.wrapT=THREE.ClampToEdgeWrapping,r.needsUpdate=!0;var n=THREE.Lensflare.Geometry,a=new THREE.RawShaderMaterial({uniforms:{scale:{value:null},screenPosition:{value:null}},vertexShader:["precision highp float;","uniform vec3 screenPosition;","uniform vec2 scale;","attribute vec3 position;","void main() {","\tgl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["precision highp float;","void main() {","\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );","}"].join("\n"),depthTest:!0,depthWrite:!1,transparent:!1}),o=new THREE.RawShaderMaterial({uniforms:{map:{value:i},scale:{value:null},screenPosition:{value:null}},vertexShader:["precision highp float;","uniform vec3 screenPosition;","uniform vec2 scale;","attribute vec3 position;","attribute vec2 uv;","varying vec2 vUV;","void main() {","\tvUV = uv;","\tgl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );","}"].join("\n"),fragmentShader:["precision highp float;","uniform sampler2D map;","varying vec2 vUV;","void main() {","\tgl_FragColor = texture2D( map, vUV );","}"].join("\n"),depthTest:!1,depthWrite:!1,transparent:!1}),l=new THREE.Mesh(n,a),s=[],c=THREE.LensflareElement.Shader,u=new THREE.RawShaderMaterial({uniforms:{map:{value:null},occlusionMap:{value:r},color:{value:new THREE.Color(16777215)},scale:{value:new THREE.Vector2},screenPosition:{value:new THREE.Vector3}},vertexShader:c.vertexShader,fragmentShader:c.fragmentShader,blending:THREE.AdditiveBlending,transparent:!0,depthWrite:!1}),p=new THREE.Mesh(n,u);this.addElement=function(e){s.push(e)};var E=new THREE.Vector2,v=new THREE.Vector2,d=new THREE.Box2,f=new THREE.Vector4;this.onBeforeRender=function(c,h,m){c.getCurrentViewport(f);var y=f.w/f.z,g=f.z/2,T=f.w/2,R=16/f.w;if(E.set(R*y,R),d.min.set(f.x,f.y),d.max.set(f.x+(f.z-16),f.y+(f.w-16)),t.setFromMatrixPosition(this.matrixWorld),t.applyMatrix4(m.matrixWorldInverse),!(t.z>0)&&(e.copy(t).applyMatrix4(m.projectionMatrix),v.x=f.x+e.x*g+g-8,v.y=f.y+e.y*T+T-8,d.containsPoint(v))){c.copyFramebufferToTexture(v,i);var x=a.uniforms;x.scale.value=E,x.screenPosition.value=e,c.renderBufferDirect(m,null,n,a,l,null),c.copyFramebufferToTexture(v,r);var x=o.uniforms;x.scale.value=E,x.screenPosition.value=e,c.renderBufferDirect(m,null,n,o,l,null);for(var w=2*-e.x,H=2*-e.y,b=0,M=s.length;b 0) return; // lensflare is behind the camera\n\t\n\t\t\tpositionScreen.copy(positionView).applyMatrix4(camera.projectionMatrix);\n\t\n\t\t\t// horizontal and vertical coordinate of the lower left corner of the pixels to copy\n\t\n\t\t\tscreenPositionPixels.x = viewport.x + positionScreen.x * halfViewportWidth + halfViewportWidth - 8;\n\t\t\tscreenPositionPixels.y = viewport.y + positionScreen.y * halfViewportHeight + halfViewportHeight - 8;\n\t\n\t\t\t// screen cull\n\t\n\t\t\tif (validArea.containsPoint(screenPositionPixels)) {\n\t\n\t\t\t\t// save current RGB to temp texture\n\t\n\t\t\t\trenderer.copyFramebufferToTexture(screenPositionPixels, tempMap);\n\t\n\t\t\t\t// render pink quad\n\t\n\t\t\t\tvar uniforms = material1a.uniforms;\n\t\t\t\tuniforms[\"scale\"].value = scale;\n\t\t\t\tuniforms[\"screenPosition\"].value = positionScreen;\n\t\n\t\t\t\trenderer.renderBufferDirect(camera, null, geometry, material1a, mesh1, null);\n\t\n\t\t\t\t// copy result to occlusionMap\n\t\n\t\t\t\trenderer.copyFramebufferToTexture(screenPositionPixels, occlusionMap);\n\t\n\t\t\t\t// restore graphics\n\t\n\t\t\t\tvar uniforms = material1b.uniforms;\n\t\t\t\tuniforms[\"scale\"].value = scale;\n\t\t\t\tuniforms[\"screenPosition\"].value = positionScreen;\n\t\n\t\t\t\trenderer.renderBufferDirect(camera, null, geometry, material1b, mesh1, null);\n\t\n\t\t\t\t// render elements\n\t\n\t\t\t\tvar vecX = -positionScreen.x * 2;\n\t\t\t\tvar vecY = -positionScreen.y * 2;\n\t\n\t\t\t\tfor (var i = 0, l = elements.length; i < l; i++) {\n\t\n\t\t\t\t\tvar element = elements[i];\n\t\n\t\t\t\t\tvar uniforms = material2.uniforms;\n\t\n\t\t\t\t\tuniforms[\"color\"].value.copy(element.color);\n\t\t\t\t\tuniforms[\"map\"].value = element.texture;\n\t\t\t\t\tuniforms[\"screenPosition\"].value.x = positionScreen.x + vecX * element.distance;\n\t\t\t\t\tuniforms[\"screenPosition\"].value.y = positionScreen.y + vecY * element.distance;\n\t\n\t\t\t\t\tvar size = element.size / viewport.w;\n\t\t\t\t\tvar invAspect = viewport.w / viewport.z;\n\t\n\t\t\t\t\tuniforms[\"scale\"].value.set(size * invAspect, size);\n\t\n\t\t\t\t\tmaterial2.uniformsNeedUpdate = true;\n\t\n\t\t\t\t\trenderer.renderBufferDirect(camera, null, geometry, material2, mesh2, null);\n\t\t\t\t}\n\t\t\t}\n\t\t};\n\t\n\t\tthis.dispose = function () {\n\t\n\t\t\tmaterial1a.dispose();\n\t\t\tmaterial1b.dispose();\n\t\t\tmaterial2.dispose();\n\t\n\t\t\ttempMap.dispose();\n\t\t\tocclusionMap.dispose();\n\t\n\t\t\tfor (var i = 0, l = elements.length; i < l; i++) {\n\t\n\t\t\t\telements[i].texture.dispose();\n\t\t\t}\n\t\t};\n\t};\n\t\n\tTHREE.Lensflare.prototype = Object.create(THREE.Mesh.prototype);\n\tTHREE.Lensflare.prototype.constructor = THREE.Lensflare;\n\tTHREE.Lensflare.prototype.isLensflare = true;\n\t\n\t//\n\t\n\tTHREE.LensflareElement = function (texture, size, distance, color) {\n\t\n\t\tthis.texture = texture;\n\t\tthis.size = size || 1;\n\t\tthis.distance = distance || 0;\n\t\tthis.color = color || new THREE.Color(0xffffff);\n\t};\n\t\n\tTHREE.LensflareElement.Shader = {\n\t\n\t\tuniforms: {\n\t\n\t\t\t'map': { value: null },\n\t\t\t'occlusionMap': { value: null },\n\t\t\t'color': { value: null },\n\t\t\t'scale': { value: null },\n\t\t\t'screenPosition': { value: null }\n\t\n\t\t},\n\t\n\t\tvertexShader: ['precision highp float;', 'uniform vec3 screenPosition;', 'uniform vec2 scale;', 'uniform sampler2D occlusionMap;', 'attribute vec3 position;', 'attribute vec2 uv;', 'varying vec2 vUV;', 'varying float vVisibility;', 'void main() {', '\tvUV = uv;', '\tvec2 pos = position.xy;', '\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );', '\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );', '\tvVisibility = visibility.r / 9.0;', '\tvVisibility *= 1.0 - visibility.g / 9.0;', '\tvVisibility *= visibility.b / 9.0;', '\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );', '}'].join('\\n'),\n\t\n\t\tfragmentShader: ['precision highp float;', 'uniform sampler2D map;', 'uniform vec3 color;', 'varying vec2 vUV;', 'varying float vVisibility;', 'void main() {', '\tvec4 texture = texture2D( map, vUV );', '\ttexture.a *= vVisibility;', '\tgl_FragColor = texture;', '\tgl_FragColor.rgb *= color;', '}'].join('\\n')\n\t\n\t};\n\t\n\tTHREE.Lensflare.Geometry = function () {\n\t\n\t\tvar geometry = new THREE.BufferGeometry();\n\t\n\t\tvar float32Array = new Float32Array([-1, -1, 0, 0, 0, 1, -1, 0, 1, 0, 1, 1, 0, 1, 1, -1, 1, 0, 0, 1]);\n\t\n\t\tvar interleavedBuffer = new THREE.InterleavedBuffer(float32Array, 5);\n\t\n\t\tgeometry.setIndex([0, 1, 2, 0, 2, 3]);\n\t\tgeometry.addAttribute('position', new THREE.InterleavedBufferAttribute(interleavedBuffer, 3, 0, false));\n\t\tgeometry.addAttribute('uv', new THREE.InterleavedBufferAttribute(interleavedBuffer, 2, 3, false));\n\t\n\t\treturn geometry;\n\t}();\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// aframe-lensflare-component.min.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\texports: {},\n \t\t\tid: moduleId,\n \t\t\tloaded: false\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.loaded = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(0);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 2c280269332efe31211c","/* global AFRAME */\n/* global THREE */\n\nif (typeof AFRAME === 'undefined') {\n throw new Error('Component attempted to register before AFRAME was available.')\n}\n\nif (typeof THREE === 'undefined') {\n throw new Error('Component attempted to register before THREE was available.')\n}\n\n//https://github.com/mrdoob/three.js/blob/master/examples/js/objects/Lensflare.js\nrequire('./Lensflare')\n\n/**\n * A-Frame Lensflare Component component for A-Frame.\n */\nAFRAME.registerComponent('lensflare', {\n schema: {\n src: {\n type: 'asset'\n },\n createLight: {\n type: 'boolean',\n default: true\n },\n position: {\n type: 'vec3'\n },\n target: {\n type: 'string'\n },\n intensity: {\n type: 'number',\n default: 5\n },\n relative: {\n type: 'boolean',\n default: true\n },\n size: {\n type: 'number',\n default: 500\n },\n lightColor: {\n type: 'string',\n default: 'rgb(255, 255, 255)'\n },\n lightDistance: {\n type: 'number',\n default: 4.0,\n },\n lightAngle: {\n type: 'number',\n default: Math.PI / 3,\n },\n lightPenumbra: {\n type: 'number',\n default: 0.077,\n },\n lightDecay: {\n type: 'number',\n default: 1,\n },\n lightType: {\n default: 'spot',\n oneOf: ['directional', 'point', 'spot']\n }\n },\n\n /**\n * Set if component needs multiple instancing.\n */\n multiple: true,\n\n /**\n * setLightType - Create a light based on lightType\n *\n * @param {String} type Type of the light, supplied as a string.\n * @param {Object} settings Additional settings to pass to the light. E.g. angle and decay\n * @return {THREE.Light} A THREE.JS light object\n */\n setLightType: function (type, settings) {\n switch (type) {\n case 'spot':\n return new THREE.SpotLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightAngle, settings.lightPenumbra, settings.lightDecay)\n case 'point':\n return new THREE.PointLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightDecay)\n case 'directional':\n return new THREE.DirectionalLight(new THREE.Color(settings.lightColor), settings.intensity)\n }\n },\n /**\n * Called once when component is attached. Generally for initial setup.\n */\n init: function () {\n\n const scene = document.querySelector('a-scene').object3D;\n const parentEl = this.el.object3D\n const sceneEl = this.el.sceneEl.object3D\n\n //Determine positioning\n const position = this.data.relative ? new THREE.Vector3(0, 0, 0) : this.data.position\n\n //Load texture (Three r84 upward doesn't support progress)\n const textureLoader = new THREE.TextureLoader()\n const textureFlare = textureLoader.load(this.data.src.currentSrc,\n function (texture) {\n return texture\n },\n undefined,\n function (error) {\n throw new Error('An error occured loading the Flare texture')\n }\n )\n\n this.lensFlare = new THREE.Lensflare()\n this.lensFlareElement = new THREE.LensflareElement(textureFlare, this.data.size, 0.0, new THREE.Color(this.data.lightColor))\n this.lensFlare.addElement(this.lensFlareElement);\n this.lensFlare.position.copy(position)\n\n\n\n //Determine if the user wants a light\n if (this.data.createLight) {\n\n const light = this.setLightType(this.data.lightType.toLowerCase(), this.data)\n\n //Has a target been supplied?\n const hasTarget = this.data.target ? this.data.target : false\n\n //Set light target.\n if (hasTarget) {\n light.target = document.querySelector(this.data.target).object3D\n sceneEl.add(light.target)\n sceneEl.updateMatrixWorld()\n }\n light.position.set(position.x, position.y, position.z)\n\n //If relative, we want to attach the lensflare, and the light as child objects and call updateMatrixWorld once.\n if (this.data.relative) {\n light.add(this.lensFlare)\n parentEl.add(light)\n sceneEl.updateMatrixWorld()\n } else {\n scene.add(light)\n }\n } else {\n //If relative, we want to attach the lensflare as a child object. This is so our lensflare works with animation updates.\n if (this.data.relative) {\n parentEl.add(this.lensFlare)\n sceneEl.updateMatrixWorld()\n } else {\n scene.add(this.lensFlare)\n }\n }\n\n\n },\n\n /**\n * Called when component is attached and when component data changes.\n * Generally modifies the entity based on the data.\n */\n update: function (oldData) {\n\n },\n\n /**\n * Called when a component is removed (e.g., via removeAttribute).\n * Generally undoes all modifications to the entity.\n */\n remove: function () { },\n\n /**\n * Called on each scene tick.\n */\n // tick: function (t) { },\n\n /**\n * Called when entity pauses.\n * Use to stop or remove any dynamic or background behavior such as events.\n */\n pause: function () { },\n\n /**\n * Called when entity resumes.\n * Use to continue or add any dynamic or background behavior such as events.\n */\n play: function () { }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./index.js","/**\r\n * @author Mugen87 / https://github.com/Mugen87\r\n * @author mrdoob / http://mrdoob.com/\r\n */\r\n\r\nTHREE.Lensflare = function () {\r\n\r\n\tTHREE.Mesh.call( this, THREE.Lensflare.Geometry, new THREE.MeshBasicMaterial( { opacity: 0, transparent: true } ) );\r\n\r\n\tthis.type = 'Lensflare';\r\n\tthis.frustumCulled = false;\r\n\tthis.renderOrder = Infinity;\r\n\r\n\t//\r\n\r\n\tvar positionScreen = new THREE.Vector3();\r\n\tvar positionView = new THREE.Vector3();\r\n\r\n\t// textures\r\n\r\n\tvar tempMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );\r\n\ttempMap.minFilter = THREE.NearestFilter;\r\n\ttempMap.magFilter = THREE.NearestFilter;\r\n\ttempMap.wrapS = THREE.ClampToEdgeWrapping;\r\n\ttempMap.wrapT = THREE.ClampToEdgeWrapping;\r\n\ttempMap.needsUpdate = true;\r\n\r\n\tvar occlusionMap = new THREE.DataTexture( new Uint8Array( 16 * 16 * 3 ), 16, 16, THREE.RGBFormat );\r\n\tocclusionMap.minFilter = THREE.NearestFilter;\r\n\tocclusionMap.magFilter = THREE.NearestFilter;\r\n\tocclusionMap.wrapS = THREE.ClampToEdgeWrapping;\r\n\tocclusionMap.wrapT = THREE.ClampToEdgeWrapping;\r\n\tocclusionMap.needsUpdate = true;\r\n\r\n\t// material\r\n\r\n\tvar geometry = THREE.Lensflare.Geometry;\r\n\r\n\tvar material1a = new THREE.RawShaderMaterial( {\r\n\t\tuniforms: {\r\n\t\t\t'scale': { value: null },\r\n\t\t\t'screenPosition': { value: null }\r\n\t\t},\r\n\t\tvertexShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'uniform vec3 screenPosition;',\r\n\t\t\t'uniform vec2 scale;',\r\n\r\n\t\t\t'attribute vec3 position;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tgl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tfragmentShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tgl_FragColor = vec4( 1.0, 0.0, 1.0, 1.0 );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tdepthTest: true,\r\n\t\tdepthWrite: false,\r\n\t\ttransparent: false\r\n\t} );\r\n\r\n\tvar material1b = new THREE.RawShaderMaterial( {\r\n\t\tuniforms: {\r\n\t\t\t'map': { value: tempMap },\r\n\t\t\t'scale': { value: null },\r\n\t\t\t'screenPosition': { value: null }\r\n\t\t},\r\n\t\tvertexShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'uniform vec3 screenPosition;',\r\n\t\t\t'uniform vec2 scale;',\r\n\r\n\t\t\t'attribute vec3 position;',\r\n\t\t\t'attribute vec2 uv;',\r\n\r\n\t\t\t'varying vec2 vUV;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tvUV = uv;',\r\n\r\n\t\t\t'\tgl_Position = vec4( position.xy * scale + screenPosition.xy, screenPosition.z, 1.0 );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tfragmentShader: [\r\n\r\n\t\t\t'precision highp float;',\r\n\r\n\t\t\t'uniform sampler2D map;',\r\n\r\n\t\t\t'varying vec2 vUV;',\r\n\r\n\t\t\t'void main() {',\r\n\r\n\t\t\t'\tgl_FragColor = texture2D( map, vUV );',\r\n\r\n\t\t\t'}'\r\n\r\n\t\t].join( '\\n' ),\r\n\t\tdepthTest: false,\r\n\t\tdepthWrite: false,\r\n\t\ttransparent: false\r\n\t} );\r\n\r\n\t// the following object is used for occlusionMap generation\r\n\r\n\tvar mesh1 = new THREE.Mesh( geometry, material1a );\r\n\r\n\t//\r\n\r\n\tvar elements = [];\r\n\r\n\tvar shader = THREE.LensflareElement.Shader;\r\n\r\n\tvar material2 = new THREE.RawShaderMaterial( {\r\n\t\tuniforms: {\r\n\t\t\t'map': { value: null },\r\n\t\t\t'occlusionMap': { value: occlusionMap },\r\n\t\t\t'color': { value: new THREE.Color( 0xffffff ) },\r\n\t\t\t'scale': { value: new THREE.Vector2() },\r\n\t\t\t'screenPosition': { value: new THREE.Vector3() }\r\n\t\t},\r\n\t\tvertexShader: shader.vertexShader,\r\n\t\tfragmentShader: shader.fragmentShader,\r\n\t\tblending: THREE.AdditiveBlending,\r\n\t\ttransparent: true,\r\n\t\tdepthWrite: false\r\n\t} );\r\n\r\n\tvar mesh2 = new THREE.Mesh( geometry, material2 );\r\n\r\n\tthis.addElement = function ( element ) {\r\n\r\n\t\telements.push( element );\r\n\r\n\t};\r\n\r\n\t//\r\n\r\n\tvar scale = new THREE.Vector2();\r\n\tvar screenPositionPixels = new THREE.Vector2();\r\n\tvar validArea = new THREE.Box2();\r\n\tvar viewport = new THREE.Vector4();\r\n\r\n\tthis.onBeforeRender = function ( renderer, scene, camera ) {\r\n\r\n\t\trenderer.getCurrentViewport( viewport );\r\n\r\n\t\tvar invAspect = viewport.w / viewport.z;\r\n\t\tvar halfViewportWidth = viewport.z / 2.0;\r\n\t\tvar halfViewportHeight = viewport.w / 2.0;\r\n\r\n\t\tvar size = 16 / viewport.w;\r\n\t\tscale.set( size * invAspect, size );\r\n\r\n\t\tvalidArea.min.set( viewport.x, viewport.y );\r\n\t\tvalidArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) );\r\n\r\n\t\t// calculate position in screen space\r\n\r\n\t\tpositionView.setFromMatrixPosition( this.matrixWorld );\r\n\t\tpositionView.applyMatrix4( camera.matrixWorldInverse );\r\n\r\n\t\tif ( positionView.z > 0 ) return; // lensflare is behind the camera\r\n\r\n\t\tpositionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix );\r\n\r\n\t\t// horizontal and vertical coordinate of the lower left corner of the pixels to copy\r\n\r\n\t\tscreenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8;\r\n\t\tscreenPositionPixels.y = viewport.y + ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8;\r\n\r\n\t\t// screen cull\r\n\r\n\t\tif ( validArea.containsPoint( screenPositionPixels ) ) {\r\n\r\n\t\t\t// save current RGB to temp texture\r\n\r\n\t\t\trenderer.copyFramebufferToTexture( screenPositionPixels, tempMap );\r\n\r\n\t\t\t// render pink quad\r\n\r\n\t\t\tvar uniforms = material1a.uniforms;\r\n\t\t\tuniforms[ \"scale\" ].value = scale;\r\n\t\t\tuniforms[ \"screenPosition\" ].value = positionScreen;\r\n\r\n\t\t\trenderer.renderBufferDirect( camera, null, geometry, material1a, mesh1, null );\r\n\r\n\t\t\t// copy result to occlusionMap\r\n\r\n\t\t\trenderer.copyFramebufferToTexture( screenPositionPixels, occlusionMap );\r\n\r\n\t\t\t// restore graphics\r\n\r\n\t\t\tvar uniforms = material1b.uniforms;\r\n\t\t\tuniforms[ \"scale\" ].value = scale;\r\n\t\t\tuniforms[ \"screenPosition\" ].value = positionScreen;\r\n\r\n\t\t\trenderer.renderBufferDirect( camera, null, geometry, material1b, mesh1, null );\r\n\r\n\t\t\t// render elements\r\n\r\n\t\t\tvar vecX = - positionScreen.x * 2;\r\n\t\t\tvar vecY = - positionScreen.y * 2;\r\n\r\n\t\t\tfor ( var i = 0, l = elements.length; i < l; i ++ ) {\r\n\r\n\t\t\t\tvar element = elements[ i ];\r\n\r\n\t\t\t\tvar uniforms = material2.uniforms;\r\n\r\n\t\t\t\tuniforms[ \"color\" ].value.copy( element.color );\r\n\t\t\t\tuniforms[ \"map\" ].value = element.texture;\r\n\t\t\t\tuniforms[ \"screenPosition\" ].value.x = positionScreen.x + vecX * element.distance;\r\n\t\t\t\tuniforms[ \"screenPosition\" ].value.y = positionScreen.y + vecY * element.distance;\r\n\r\n\t\t\t\tvar size = element.size / viewport.w;\r\n\t\t\t\tvar invAspect = viewport.w / viewport.z;\r\n\r\n\t\t\t\tuniforms[ \"scale\" ].value.set( size * invAspect, size );\r\n\r\n\t\t\t\tmaterial2.uniformsNeedUpdate = true;\r\n\r\n\t\t\t\trenderer.renderBufferDirect( camera, null, geometry, material2, mesh2, null );\r\n\r\n\t\t\t}\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n\tthis.dispose = function () {\r\n\r\n\t\tmaterial1a.dispose();\r\n\t\tmaterial1b.dispose();\r\n\t\tmaterial2.dispose();\r\n\r\n\t\ttempMap.dispose();\r\n\t\tocclusionMap.dispose();\r\n\r\n\t\tfor ( var i = 0, l = elements.length; i < l; i ++ ) {\r\n\r\n\t\t\telements[ i ].texture.dispose();\r\n\r\n\t\t}\r\n\r\n\t};\r\n\r\n};\r\n\r\nTHREE.Lensflare.prototype = Object.create( THREE.Mesh.prototype );\r\nTHREE.Lensflare.prototype.constructor = THREE.Lensflare;\r\nTHREE.Lensflare.prototype.isLensflare = true;\r\n\r\n//\r\n\r\nTHREE.LensflareElement = function ( texture, size, distance, color ) {\r\n\r\n\tthis.texture = texture;\r\n\tthis.size = size || 1;\r\n\tthis.distance = distance || 0;\r\n\tthis.color = color || new THREE.Color( 0xffffff );\r\n\r\n};\r\n\r\nTHREE.LensflareElement.Shader = {\r\n\r\n\tuniforms: {\r\n\r\n\t\t'map': { value: null },\r\n\t\t'occlusionMap': { value: null },\r\n\t\t'color': { value: null },\r\n\t\t'scale': { value: null },\r\n\t\t'screenPosition': { value: null }\r\n\r\n\t},\r\n\r\n\tvertexShader: [\r\n\r\n\t\t'precision highp float;',\r\n\r\n\t\t'uniform vec3 screenPosition;',\r\n\t\t'uniform vec2 scale;',\r\n\r\n\t\t'uniform sampler2D occlusionMap;',\r\n\r\n\t\t'attribute vec3 position;',\r\n\t\t'attribute vec2 uv;',\r\n\r\n\t\t'varying vec2 vUV;',\r\n\t\t'varying float vVisibility;',\r\n\r\n\t\t'void main() {',\r\n\r\n\t\t'\tvUV = uv;',\r\n\r\n\t\t'\tvec2 pos = position.xy;',\r\n\r\n\t\t'\tvec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.1 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.1 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.5 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.9, 0.9 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.9 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.9 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.1, 0.5 ) );',\r\n\t\t'\tvisibility += texture2D( occlusionMap, vec2( 0.5, 0.5 ) );',\r\n\r\n\t\t'\tvVisibility = visibility.r / 9.0;',\r\n\t\t'\tvVisibility *= 1.0 - visibility.g / 9.0;',\r\n\t\t'\tvVisibility *= visibility.b / 9.0;',\r\n\r\n\t\t'\tgl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );',\r\n\r\n\t\t'}'\r\n\r\n\t].join( '\\n' ),\r\n\r\n\tfragmentShader: [\r\n\r\n\t\t'precision highp float;',\r\n\r\n\t\t'uniform sampler2D map;',\r\n\t\t'uniform vec3 color;',\r\n\r\n\t\t'varying vec2 vUV;',\r\n\t\t'varying float vVisibility;',\r\n\r\n\t\t'void main() {',\r\n\r\n\t\t'\tvec4 texture = texture2D( map, vUV );',\r\n\t\t'\ttexture.a *= vVisibility;',\r\n\t\t'\tgl_FragColor = texture;',\r\n\t\t'\tgl_FragColor.rgb *= color;',\r\n\r\n\t\t'}'\r\n\r\n\t].join( '\\n' )\r\n\r\n};\r\n\r\nTHREE.Lensflare.Geometry = ( function () {\r\n\r\n\tvar geometry = new THREE.BufferGeometry();\r\n\r\n\tvar float32Array = new Float32Array( [\r\n\t\t- 1, - 1, 0, 0, 0,\r\n\t\t1, - 1, 0, 1, 0,\r\n\t\t1, 1, 0, 1, 1,\r\n\t\t- 1, 1, 0, 0, 1\r\n\t] );\r\n\r\n\tvar interleavedBuffer = new THREE.InterleavedBuffer( float32Array, 5 );\r\n\r\n\tgeometry.setIndex( [ 0, 1, 2,\t0, 2, 3 ] );\r\n\tgeometry.addAttribute( 'position', new THREE.InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) );\r\n\tgeometry.addAttribute( 'uv', new THREE.InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) );\r\n\r\n\treturn geometry;\r\n\r\n} )();\r\n\n\n\n// WEBPACK FOOTER //\n// ./Lensflare.js"],"sourceRoot":""} -------------------------------------------------------------------------------- /examples/basic/images/aframe-lensflare-low.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/aframe-lensflare-low.gif -------------------------------------------------------------------------------- /examples/basic/images/aframe-lensflare.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/aframe-lensflare.gif -------------------------------------------------------------------------------- /examples/basic/images/flare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/flare.jpg -------------------------------------------------------------------------------- /examples/basic/images/flare2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/flare2.jpg -------------------------------------------------------------------------------- /examples/basic/images/flare3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/flare3.jpg -------------------------------------------------------------------------------- /examples/basic/images/floor.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/floor.jpg -------------------------------------------------------------------------------- /examples/basic/images/sky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/sky.jpg -------------------------------------------------------------------------------- /examples/basic/images/sky2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/examples/basic/images/sky2.jpg -------------------------------------------------------------------------------- /examples/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A-Frame Lensflare Component Component - Basic 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Test Lensflare Asset 16 | Test Lensflare Asset 2 17 | Test Lensflare Asset 3 18 | 19 | Skymap 20 | Floor 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 22 | 23 | 24 |

A-Frame Lensflare Component Component

25 | Basic 26 |

This is a basic example.

27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /examples/main.js: -------------------------------------------------------------------------------- 1 | require('aframe'); 2 | require('../index.js'); 3 | -------------------------------------------------------------------------------- /gh-pages/basic/images/flare.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/gh-pages/basic/images/flare.jpg -------------------------------------------------------------------------------- /gh-pages/basic/images/flare2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mokargas/aframe-lensflare-component/314e2481def732c27c1a738114c818f198023d40/gh-pages/basic/images/flare2.jpg -------------------------------------------------------------------------------- /gh-pages/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | A-Frame Lensflare Component Component - Basic 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | Test Lensflare Asset 16 | Test Lensflare Asset 2 17 | Test Lensflare Asset 3 18 | 19 | Skymap 20 | Floor 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 22 | 23 | 24 |

A-Frame Lensflare Component Component

25 | Basic 26 |

This is a basic example.

27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /gh-pages/main.js: -------------------------------------------------------------------------------- 1 | require('aframe'); 2 | require('../index.js'); 3 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /* global AFRAME */ 2 | /* global THREE */ 3 | 4 | if (typeof AFRAME === 'undefined') { 5 | throw new Error('Component attempted to register before AFRAME was available.') 6 | } 7 | 8 | if (typeof THREE === 'undefined') { 9 | throw new Error('Component attempted to register before THREE was available.') 10 | } 11 | 12 | //https://github.com/mrdoob/three.js/blob/master/examples/js/objects/Lensflare.js 13 | require('./Lensflare') 14 | 15 | /** 16 | * A-Frame Lensflare Component component for A-Frame. 17 | */ 18 | AFRAME.registerComponent('lensflare', { 19 | schema: { 20 | src: { 21 | type: 'asset' 22 | }, 23 | createLight: { 24 | type: 'boolean', 25 | default: true 26 | }, 27 | position: { 28 | type: 'vec3' 29 | }, 30 | target: { 31 | type: 'string' 32 | }, 33 | intensity: { 34 | type: 'number', 35 | default: 5 36 | }, 37 | relative: { 38 | type: 'boolean', 39 | default: true 40 | }, 41 | size: { 42 | type: 'number', 43 | default: 500 44 | }, 45 | lightColor: { 46 | type: 'string', 47 | default: 'rgb(255, 255, 255)' 48 | }, 49 | lightDistance: { 50 | type: 'number', 51 | default: 4.0, 52 | }, 53 | lightAngle: { 54 | type: 'number', 55 | default: Math.PI / 3, 56 | }, 57 | lightPenumbra: { 58 | type: 'number', 59 | default: 0.077, 60 | }, 61 | lightDecay: { 62 | type: 'number', 63 | default: 1, 64 | }, 65 | lightType: { 66 | default: 'spot', 67 | oneOf: ['directional', 'point', 'spot'] 68 | } 69 | }, 70 | 71 | /** 72 | * Set if component needs multiple instancing. 73 | */ 74 | multiple: true, 75 | 76 | /** 77 | * setLightType - Create a light based on lightType 78 | * 79 | * @param {String} type Type of the light, supplied as a string. 80 | * @param {Object} settings Additional settings to pass to the light. E.g. angle and decay 81 | * @return {THREE.Light} A THREE.JS light object 82 | */ 83 | setLightType: function (type, settings) { 84 | switch (type) { 85 | case 'spot': 86 | return new THREE.SpotLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightAngle, settings.lightPenumbra, settings.lightDecay) 87 | case 'point': 88 | return new THREE.PointLight(new THREE.Color(settings.lightColor), settings.intensity, settings.lightDistance, settings.lightDecay) 89 | case 'directional': 90 | return new THREE.DirectionalLight(new THREE.Color(settings.lightColor), settings.intensity) 91 | } 92 | }, 93 | /** 94 | * Called once when component is attached. Generally for initial setup. 95 | */ 96 | init: function () { 97 | 98 | const scene = document.querySelector('a-scene').object3D; 99 | const parentEl = this.el.object3D 100 | const sceneEl = this.el.sceneEl.object3D 101 | 102 | //Determine positioning 103 | const position = this.data.relative ? new THREE.Vector3(0, 0, 0) : this.data.position 104 | 105 | //Load texture (Three r84 upward doesn't support progress) 106 | const textureLoader = new THREE.TextureLoader() 107 | const textureFlare = textureLoader.load(this.data.src.currentSrc, 108 | function (texture) { 109 | return texture 110 | }, 111 | undefined, 112 | function (error) { 113 | throw new Error('An error occured loading the Flare texture') 114 | } 115 | ) 116 | 117 | this.lensFlare = new THREE.Lensflare() 118 | this.lensFlareElement = new THREE.LensflareElement(textureFlare, this.data.size, 0.0, new THREE.Color(this.data.lightColor)) 119 | this.lensFlare.addElement(this.lensFlareElement); 120 | this.lensFlare.position.copy(position) 121 | 122 | 123 | 124 | //Determine if the user wants a light 125 | if (this.data.createLight) { 126 | 127 | const light = this.setLightType(this.data.lightType.toLowerCase(), this.data) 128 | 129 | //Has a target been supplied? 130 | const hasTarget = this.data.target ? this.data.target : false 131 | 132 | //Set light target. 133 | if (hasTarget) { 134 | light.target = document.querySelector(this.data.target).object3D 135 | sceneEl.add(light.target) 136 | sceneEl.updateMatrixWorld() 137 | } 138 | light.position.set(position.x, position.y, position.z) 139 | 140 | //If relative, we want to attach the lensflare, and the light as child objects and call updateMatrixWorld once. 141 | if (this.data.relative) { 142 | light.add(this.lensFlare) 143 | parentEl.add(light) 144 | sceneEl.updateMatrixWorld() 145 | } else { 146 | scene.add(light) 147 | } 148 | } else { 149 | //If relative, we want to attach the lensflare as a child object. This is so our lensflare works with animation updates. 150 | if (this.data.relative) { 151 | parentEl.add(this.lensFlare) 152 | sceneEl.updateMatrixWorld() 153 | } else { 154 | scene.add(this.lensFlare) 155 | } 156 | } 157 | 158 | 159 | }, 160 | 161 | /** 162 | * Called when component is attached and when component data changes. 163 | * Generally modifies the entity based on the data. 164 | */ 165 | update: function (oldData) { 166 | 167 | }, 168 | 169 | /** 170 | * Called when a component is removed (e.g., via removeAttribute). 171 | * Generally undoes all modifications to the entity. 172 | */ 173 | remove: function () { }, 174 | 175 | /** 176 | * Called on each scene tick. 177 | */ 178 | // tick: function (t) { }, 179 | 180 | /** 181 | * Called when entity pauses. 182 | * Use to stop or remove any dynamic or background behavior such as events. 183 | */ 184 | pause: function () { }, 185 | 186 | /** 187 | * Called when entity resumes. 188 | * Use to continue or add any dynamic or background behavior such as events. 189 | */ 190 | play: function () { } 191 | }); 192 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "aframe-lensflare-component", 3 | "version": "1.0.3", 4 | "description": "A component to add a configurable lens-flare (and optional light) to an entity", 5 | "main": "index.js", 6 | "cdn": "dist/aframe-lensflare-component.min.js", 7 | "scripts": { 8 | "build": "browserify examples/main.js -o examples/build.js -t babelify", 9 | "dev": "budo examples/main.js:build.js --dir examples --port 8000 --live --open", 10 | "dist": "webpack", 11 | "olddist": "webpack index.js dist/aframe-lensflare-component.js && webpack -p index.js dist/aframe-lensflare-component.min.js", 12 | "lint": "semistandard -v | snazzy", 13 | "prepublish": "npm run dist", 14 | "preghpages": "npm run build && shx rm -rf gh-pages && shx mkdir gh-pages && shx cp -r examples/* gh-pages", 15 | "ghpages": "npm run preghpages && ghpages -p gh-pages", 16 | "start": "npm run dev", 17 | "test": "karma start ./tests/karma.conf.js", 18 | "test:firefox": "karma start ./tests/karma.conf.js --browsers Firefox", 19 | "test:chrome": "karma start ./tests/karma.conf.js --browsers Chrome" 20 | }, 21 | "repository": { 22 | "type": "git", 23 | "url": "git+https://github.com/mokargas/aframe-lensflare-component.git" 24 | }, 25 | "keywords": [ 26 | "aframe", 27 | "aframe-component", 28 | "aframe-vr", 29 | "vr", 30 | "mozvr", 31 | "webvr", 32 | "lensflare" 33 | ], 34 | "author": "mo@devlad.com", 35 | "license": "MIT", 36 | "bugs": { 37 | "url": "https://github.com/mokargas/aframe-lensflare-component/issues" 38 | }, 39 | "homepage": "https://github.com/mokargas/aframe-lensflare-component#readme", 40 | "devDependencies": { 41 | "aframe": "^0.9.2", 42 | "babel-cli": "^6.24.0", 43 | "babel-loader": "^6.4.1", 44 | "babel-preset-es2015": "^6.24.0", 45 | "babelify": "^7.3.0", 46 | "browserify": "^13.0.0", 47 | "budo": "^8.2.2", 48 | "chai": "^3.4.1", 49 | "chai-shallow-deep-equal": "^1.3.0", 50 | "ghpages": "^0.0.8", 51 | "karma": "^0.13.15", 52 | "karma-browserify": "^4.4.2", 53 | "karma-chai-shallow-deep-equal": "0.0.4", 54 | "karma-chrome-launcher": "2.0.0", 55 | "karma-env-preprocessor": "^0.1.1", 56 | "karma-firefox-launcher": "^0.1.7", 57 | "karma-mocha": "^0.2.1", 58 | "karma-mocha-reporter": "^1.1.3", 59 | "karma-sinon-chai": "^1.3.4", 60 | "mocha": "^2.3.4", 61 | "randomcolor": "^0.4.4", 62 | "semistandard": "^8.0.0", 63 | "shelljs": "^0.7.8", 64 | "shx": "^0.1.1", 65 | "sinon": "^1.17.5", 66 | "sinon-chai": "^2.14.0", 67 | "snazzy": "^4.0.0", 68 | "webpack": "^1.15.0" 69 | }, 70 | "semistandard": { 71 | "ignore": [ 72 | "examples/build.js", 73 | "dist/**" 74 | ] 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /tests/__init.test.js: -------------------------------------------------------------------------------- 1 | /* global sinon, setup, teardown */ 2 | 3 | /** 4 | * __init.test.js is run before every test case. 5 | */ 6 | window.debug = true; 7 | var AScene = require('aframe').AScene 8 | 9 | navigator.getVRDisplays = function () { 10 | var resolvePromise = Promise.resolve(); 11 | var mockVRDisplay = { 12 | requestPresent: resolvePromise, 13 | exitPresent: resolvePromise, 14 | getPose: function () { return {orientation: null, position: null}; }, 15 | requestAnimationFrame: function () { return 1; } 16 | }; 17 | return Promise.resolve([mockVRDisplay]); 18 | }; 19 | 20 | setup(function () { 21 | this.sinon = sinon.sandbox.create(); 22 | // Stubs to not create a WebGL context since Travis CI runs headless. 23 | this.sinon.stub(AScene.prototype, 'render'); 24 | this.sinon.stub(AScene.prototype, 'resize'); 25 | this.sinon.stub(AScene.prototype, 'setupRenderer'); 26 | }); 27 | 28 | teardown(function () { 29 | // Clean up any attached elements. 30 | var attachedEls = ['canvas', 'a-assets', 'a-scene']; 31 | var els = document.querySelectorAll(attachedEls.join(',')); 32 | for (var i = 0; i < els.length; i++) { 33 | els[i].parentNode.removeChild(els[i]); 34 | } 35 | this.sinon.restore(); 36 | }); 37 | -------------------------------------------------------------------------------- /tests/helpers.js: -------------------------------------------------------------------------------- 1 | /* global suite */ 2 | 3 | /** 4 | * Helper method to create a scene, create an entity, add entity to scene, 5 | * add scene to document. 6 | * 7 | * @returns {object} An `` element. 8 | */ 9 | module.exports.entityFactory = function (opts) { 10 | var scene = document.createElement('a-scene'); 11 | var assets = document.createElement('a-assets'); 12 | var entity = document.createElement('a-entity'); 13 | scene.appendChild(assets); 14 | scene.appendChild(entity); 15 | 16 | opts = opts || {}; 17 | 18 | if (opts.assets) { 19 | opts.assets.forEach(function (asset) { 20 | assets.appendChild(asset); 21 | }); 22 | } 23 | 24 | document.body.appendChild(scene); 25 | return entity; 26 | }; 27 | 28 | /** 29 | * Creates and attaches a mixin element (and an `` element if necessary). 30 | * 31 | * @param {string} id - ID of mixin. 32 | * @param {object} obj - Map of component names to attribute values. 33 | * @param {Element} scene - Indicate which scene to apply mixin to if necessary. 34 | * @returns {object} An attached `` element. 35 | */ 36 | module.exports.mixinFactory = function (id, obj, scene) { 37 | var mixinEl = document.createElement('a-mixin'); 38 | mixinEl.setAttribute('id', id); 39 | Object.keys(obj).forEach(function (componentName) { 40 | mixinEl.setAttribute(componentName, obj[componentName]); 41 | }); 42 | 43 | var assetsEl = scene ? scene.querySelector('a-assets') : document.querySelector('a-assets'); 44 | assetsEl.appendChild(mixinEl); 45 | 46 | return mixinEl; 47 | }; 48 | 49 | /** 50 | * Test that is only run locally and is skipped on CI. 51 | */ 52 | module.exports.getSkipCISuite = function () { 53 | if (window.__env__.TEST_ENV === 'ci') { 54 | return suite.skip; 55 | } else { 56 | return suite; 57 | } 58 | }; 59 | -------------------------------------------------------------------------------- /tests/index.test.js: -------------------------------------------------------------------------------- 1 | /* global assert, setup, suite, test */ 2 | require('aframe'); 3 | require('../index.js'); 4 | var entityFactory = require('./helpers').entityFactory; 5 | 6 | suite('lensflare component', function () { 7 | var component; 8 | var el; 9 | 10 | setup(function (done) { 11 | el = entityFactory(); 12 | el.addEventListener('componentinitialized', function (evt) { 13 | if (evt.detail.name !== 'lensflare') { return; } 14 | component = el.components['lensflare']; 15 | done(); 16 | }); 17 | el.setAttribute('lensflare', {}); 18 | }); 19 | 20 | suite('foo property', function () { 21 | test('is good', function () { 22 | assert.equal(1, 1); 23 | }); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /tests/karma.conf.js: -------------------------------------------------------------------------------- 1 | // Karma configuration. 2 | module.exports = function (config) { 3 | config.set({ 4 | basePath: '../', 5 | browserify: { 6 | debug: true, 7 | paths: ['./'] 8 | }, 9 | browsers: ['Firefox', 'Chrome'], 10 | client: { 11 | captureConsole: true, 12 | mocha: {ui: 'tdd'} 13 | }, 14 | envPreprocessor: ['TEST_ENV'], 15 | files: [ 16 | // Define test files. 17 | {pattern: 'tests/**/*.test.js'}, 18 | // Serve test assets. 19 | {pattern: 'tests/assets/**/*', included: false, served: true} 20 | ], 21 | frameworks: ['mocha', 'sinon-chai', 'chai-shallow-deep-equal', 'browserify'], 22 | preprocessors: {'tests/**/*.js': ['browserify', 'env']}, 23 | reporters: ['mocha'] 24 | }); 25 | }; 26 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | 3 | 4 | module.exports = { 5 | entry: { 6 | "aframe-lensflare-component": "./index.js", 7 | "aframe-lensflare-component.min": "./index.js", 8 | }, 9 | devtool: "source-map", 10 | output: { 11 | path: "./dist", 12 | filename: "[name].js" 13 | }, 14 | module: { 15 | loaders: [{ 16 | test: /\.js?$/, 17 | exclude: /(node_modules|bower_components)/, 18 | loader: 'babel' 19 | }] 20 | }, 21 | plugins: [ 22 | new webpack.optimize.UglifyJsPlugin({ 23 | include: /\.min\.js$/, 24 | minimize: true 25 | }) 26 | ] 27 | }; 28 | --------------------------------------------------------------------------------