{"version":3,"sources":["../../../app/vendors/fss.js"],"names":["FSS","FRONT","BACK","DOUBLE","SVGNS","Array","Float32Array","Utils","isNumber","value","isNaN","parseFloat","isFinite","document","getElementById","lastTime","vendors","x","length","window","requestAnimationFrame","cancelAnimationFrame","callback","element","currentTime","Date","getTime","timeToCall","Math","max","id","setTimeout","clearTimeout","PIM2","PI","PID2","randomInRange","min","random","clamp","Vector3","create","y","z","vector","this","set","clone","a","copy","target","setX","setY","setZ","add","addVectors","b","addScalar","s","subtract","subtractVectors","subtractScalar","multiply","multiplyVectors","multiplyScalar","divide","divideVectors","divideScalar","cross","crossVectors","limit","setLength","dot","normalise","negate","distanceSquared","dx","dy","dz","distance","sqrt","lengthSquared","l","Vector4","w","setW","Color","hex","opacity","rgba","prototype","replace","size","parseInt","substring","hexify","channel","ceil","toString","format","r","g","Object","position","setPosition","Light","ambient","diffuse","call","ray","Vertex","Triangle","c","vertices","u","v","centroid","normal","color","polygon","createElementNS","setAttributeNS","computeCentroid","computeNormal","Geometry","triangles","dirty","update","t","triangle","Plane","width","height","segments","slices","segmentWidth","sliceHeight","v0","v1","v2","v3","vertex","offsetX","offsetY","push","t0","t1","Material","slave","Mesh","geometry","material","side","visible","lights","calculate","light","illuminance","abs","Scene","meshes","object","indexOf","remove","splice","Renderer","halfWidth","halfHeight","setSize","clear","render","scene","CanvasRenderer","createElement","style","display","setAttribute","context","getContext","setTransform","clearRect","m","mesh","lineJoin","lineWidth","beginPath","moveTo","lineTo","closePath","globalAlpha","strokeStyle","fillStyle","stroke","fill","WebGLRenderer","parameters","preserveDrawingBuffer","premultipliedAlpha","antialias","stencil","alpha","gl","unsupported","clearColor","enable","DEPTH_TEST","canvas","error","console","viewport","COLOR_BUFFER_BIT","DEPTH_BUFFER_BIT","tl","attribute","uniform","buffer","data","location","index","vl","buildProgram","program","attributes","setBufferData","bindBuffer","ARRAY_BUFFER","bufferData","DYNAMIC_DRAW","enableVertexAttribArray","vertexAttribPointer","FLOAT","uniforms","resolution","lightPosition","lightAmbient","lightDiffuse","structure","uniform3f","uniform3fv","uniform4fv","drawArrays","TRIANGLES","i","vs","VS","fs","FS","code","createProgram","vertexShader","buildShader","VERTEX_SHADER","fragmentShader","FRAGMENT_SHADER","attachShader","linkProgram","getProgramParameter","LINK_STATUS","getError","status","VALIDATE_STATUS","deleteShader","buildBuffer","useProgram","type","source","shader","createShader","shaderSource","compileShader","getShaderParameter","COMPILE_STATUS","getShaderInfoLog","identifier","count","createBuffer","getAttribLocation","getUniformLocation","join","SVGRenderer","childNodes","removeChild","points","parentNode","appendChild","formatPoint","formatStyle","initialise","createRenderer","createScene","createMesh","createLights","addEventListeners","resize","container","offsetWidth","offsetHeight","animate","canvasRenderer","setRenderer","RENDER","renderer","output","MESH","anchor","step","time","LIGHT","ambientHex","diffuseHex","mass","velocity","acceleration","force","ring","core","center","now","start","ox","oy","oz","offset","depth","bounds","xyScalar","attractor","zOffset","autopilot","sin","speed","cos","D","minDistance","maxDistance","F","gravity","dampening","minLimit","maxLimit","xRange","yRange","zRange","draw","lx","ly","arc","addEventListener","onWindowResize","event","initFFS"],"mappings":"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","file":"shader.js","sourcesContent":["//============================================================\n//\n// Copyright (C) 2013 Matthew Wagerfield\n//\n// Twitter: https://twitter.com/mwagerfield\n//\n// Permission is hereby granted, free of charge, to any\n// person obtaining a copy of this software and associated\n// documentation files (the \"Software\"), to deal in the\n// Software without restriction, including without limitation\n// the rights to use, copy, modify, merge, publish, distribute,\n// sublicense, and/or sell copies of the Software, and to\n// permit persons to whom the Software is furnished to do\n// so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice\n// shall be included in all copies or substantial portions\n// of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY\n// OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\n// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\n// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO\n// EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE\n// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN\n// AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE\n// OR OTHER DEALINGS IN THE SOFTWARE.\n//\n//============================================================\n\n/**\n * Defines the Flat Surface Shader namespace for all the awesomeness to exist upon.\n * @author Matthew Wagerfield\n */\nFSS = {\n FRONT : 0,\n BACK : 1,\n DOUBLE : 2,\n SVGNS : 'http://www.w3.org/2000/svg'\n};\n\n/**\n * @class Array\n * @author Matthew Wagerfield\n */\nFSS.Array = typeof Float32Array === 'function' ? Float32Array : Array;\n\n/**\n * @class Utils\n * @author Matthew Wagerfield\n */\nFSS.Utils = {\n isNumber: function(value) {\n return !isNaN(parseFloat(value)) && isFinite(value);\n }\n};\n\n/**\n * Request Animation Frame Polyfill.\n * @author Paul Irish\n * @see https://gist.github.com/paulirish/1579671\n */\n(function() {\n if(document.getElementById('ffshadeoutput') === null){\n return false;\n }\n\n var lastTime = 0;\n var vendors = ['ms', 'moz', 'webkit', 'o'];\n\n for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {\n window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];\n window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame'] || window[vendors[x]+'CancelRequestAnimationFrame'];\n }\n\n if (!window.requestAnimationFrame) {\n window.requestAnimationFrame = function(callback, element) {\n var currentTime = new Date().getTime();\n var timeToCall = Math.max(0, 16 - (currentTime - lastTime));\n var id = window.setTimeout(function() {\n callback(currentTime + timeToCall);\n }, timeToCall);\n lastTime = currentTime + timeToCall;\n return id;\n };\n }\n\n if (!window.cancelAnimationFrame) {\n window.cancelAnimationFrame = function(id) {\n clearTimeout(id);\n };\n }\n\n}());\n\n/**\n * @object Math Augmentation\n * @author Matthew Wagerfield\n */\nMath.PIM2 = Math.PI*2;\nMath.PID2 = Math.PI/2;\nMath.randomInRange = function(min, max) {\n return min + (max - min) * Math.random();\n};\nMath.clamp = function(value, min, max) {\n value = Math.max(value, min);\n value = Math.min(value, max);\n return value;\n};\n\n/**\n * @object Vector3\n * @author Matthew Wagerfield\n */\nFSS.Vector3 = {\n create: function(x, y, z) {\n var vector = new FSS.Array(3);\n this.set(vector, x, y, z);\n return vector;\n },\n clone: function(a) {\n var vector = this.create();\n this.copy(vector, a);\n return vector;\n },\n set: function(target, x, y, z) {\n target[0] = x || 0;\n target[1] = y || 0;\n target[2] = z || 0;\n return this;\n },\n setX: function(target, x) {\n target[0] = x || 0;\n return this;\n },\n setY: function(target, y) {\n target[1] = y || 0;\n return this;\n },\n setZ: function(target, z) {\n target[2] = z || 0;\n return this;\n },\n copy: function(target, a) {\n target[0] = a[0];\n target[1] = a[1];\n target[2] = a[2];\n return this;\n },\n add: function(target, a) {\n target[0] += a[0];\n target[1] += a[1];\n target[2] += a[2];\n return this;\n },\n addVectors: function(target, a, b) {\n target[0] = a[0] + b[0];\n target[1] = a[1] + b[1];\n target[2] = a[2] + b[2];\n return this;\n },\n addScalar: function(target, s) {\n target[0] += s;\n target[1] += s;\n target[2] += s;\n return this;\n },\n subtract: function(target, a) {\n target[0] -= a[0];\n target[1] -= a[1];\n target[2] -= a[2];\n return this;\n },\n subtractVectors: function(target, a, b) {\n target[0] = a[0] - b[0];\n target[1] = a[1] - b[1];\n target[2] = a[2] - b[2];\n return this;\n },\n subtractScalar: function(target, s) {\n target[0] -= s;\n target[1] -= s;\n target[2] -= s;\n return this;\n },\n multiply: function(target, a) {\n target[0] *= a[0];\n target[1] *= a[1];\n target[2] *= a[2];\n return this;\n },\n multiplyVectors: function(target, a, b) {\n target[0] = a[0] * b[0];\n target[1] = a[1] * b[1];\n target[2] = a[2] * b[2];\n return this;\n },\n multiplyScalar: function(target, s) {\n target[0] *= s;\n target[1] *= s;\n target[2] *= s;\n return this;\n },\n divide: function(target, a) {\n target[0] /= a[0];\n target[1] /= a[1];\n target[2] /= a[2];\n return this;\n },\n divideVectors: function(target, a, b) {\n target[0] = a[0] / b[0];\n target[1] = a[1] / b[1];\n target[2] = a[2] / b[2];\n return this;\n },\n divideScalar: function(target, s) {\n if (s !== 0) {\n target[0] /= s;\n target[1] /= s;\n target[2] /= s;\n } else {\n target[0] = 0;\n target[1] = 0;\n target[2] = 0;\n }\n return this;\n },\n cross: function(target, a) {\n var x = target[0];\n var y = target[1];\n var z = target[2];\n target[0] = y*a[2] - z*a[1];\n target[1] = z*a[0] - x*a[2];\n target[2] = x*a[1] - y*a[0];\n return this;\n },\n crossVectors: function(target, a, b) {\n target[0] = a[1]*b[2] - a[2]*b[1];\n target[1] = a[2]*b[0] - a[0]*b[2];\n target[2] = a[0]*b[1] - a[1]*b[0];\n return this;\n },\n min: function(target, value) {\n if (target[0] < value) { target[0] = value; }\n if (target[1] < value) { target[1] = value; }\n if (target[2] < value) { target[2] = value; }\n return this;\n },\n max: function(target, value) {\n if (target[0] > value) { target[0] = value; }\n if (target[1] > value) { target[1] = value; }\n if (target[2] > value) { target[2] = value; }\n return this;\n },\n clamp: function(target, min, max) {\n this.min(target, min);\n this.max(target, max);\n return this;\n },\n limit: function(target, min, max) {\n var length = this.length(target);\n if (min !== null && length < min) {\n this.setLength(target, min);\n } else if (max !== null && length > max) {\n this.setLength(target, max);\n }\n return this;\n },\n dot: function(a, b) {\n return a[0]*b[0] + a[1]*b[1] + a[2]*b[2];\n },\n normalise: function(target) {\n return this.divideScalar(target, this.length(target));\n },\n negate: function(target) {\n return this.multiplyScalar(target, -1);\n },\n distanceSquared: function(a, b) {\n var dx = a[0] - b[0];\n var dy = a[1] - b[1];\n var dz = a[2] - b[2];\n return dx*dx + dy*dy + dz*dz;\n },\n distance: function(a, b) {\n return Math.sqrt(this.distanceSquared(a, b));\n },\n lengthSquared: function(a) {\n return a[0]*a[0] + a[1]*a[1] + a[2]*a[2];\n },\n length: function(a) {\n return Math.sqrt(this.lengthSquared(a));\n },\n setLength: function(target, l) {\n var length = this.length(target);\n if (length !== 0 && l !== length) {\n this.multiplyScalar(target, l / length);\n }\n return this;\n }\n};\n\n/**\n * @object Vector4\n * @author Matthew Wagerfield\n */\nFSS.Vector4 = {\n create: function(x, y, z, w) {\n var vector = new FSS.Array(4);\n this.set(vector, x, y, z);\n return vector;\n },\n set: function(target, x, y, z, w) {\n target[0] = x || 0;\n target[1] = y || 0;\n target[2] = z || 0;\n target[3] = w || 0;\n return this;\n },\n setX: function(target, x) {\n target[0] = x || 0;\n return this;\n },\n setY: function(target, y) {\n target[1] = y || 0;\n return this;\n },\n setZ: function(target, z) {\n target[2] = z || 0;\n return this;\n },\n setW: function(target, w) {\n target[3] = w || 0;\n return this;\n },\n add: function(target, a) {\n target[0] += a[0];\n target[1] += a[1];\n target[2] += a[2];\n target[3] += a[3];\n return this;\n },\n multiplyVectors: function(target, a, b) {\n target[0] = a[0] * b[0];\n target[1] = a[1] * b[1];\n target[2] = a[2] * b[2];\n target[3] = a[3] * b[3];\n return this;\n },\n multiplyScalar: function(target, s) {\n target[0] *= s;\n target[1] *= s;\n target[2] *= s;\n target[3] *= s;\n return this;\n },\n min: function(target, value) {\n if (target[0] < value) { target[0] = value; }\n if (target[1] < value) { target[1] = value; }\n if (target[2] < value) { target[2] = value; }\n if (target[3] < value) { target[3] = value; }\n return this;\n },\n max: function(target, value) {\n if (target[0] > value) { target[0] = value; }\n if (target[1] > value) { target[1] = value; }\n if (target[2] > value) { target[2] = value; }\n if (target[3] > value) { target[3] = value; }\n return this;\n },\n clamp: function(target, min, max) {\n this.min(target, min);\n this.max(target, max);\n return this;\n }\n};\n\n/**\n * @class Color\n * @author Matthew Wagerfield\n */\nFSS.Color = function(hex, opacity) {\n this.rgba = FSS.Vector4.create();\n this.hex = hex || '#000000';\n this.opacity = FSS.Utils.isNumber(opacity) ? opacity : 1;\n this.set(this.hex, this.opacity);\n};\n\nFSS.Color.prototype = {\n set: function(hex, opacity) {\n hex = hex.replace('#', '');\n var size = hex.length / 3;\n this.rgba[0] = parseInt(hex.substring(size*0, size*1), 16) / 255;\n this.rgba[1] = parseInt(hex.substring(size*1, size*2), 16) / 255;\n this.rgba[2] = parseInt(hex.substring(size*2, size*3), 16) / 255;\n this.rgba[3] = FSS.Utils.isNumber(opacity) ? opacity : this.rgba[3];\n return this;\n },\n hexify: function(channel) {\n var hex = Math.ceil(channel*255).toString(16);\n if (hex.length === 1) { hex = '0' + hex; }\n return hex;\n },\n format: function() {\n var r = this.hexify(this.rgba[0]);\n var g = this.hexify(this.rgba[1]);\n var b = this.hexify(this.rgba[2]);\n this.hex = '#' + r + g + b;\n return this.hex;\n }\n};\n\n/**\n * @class Object\n * @author Matthew Wagerfield\n */\nFSS.Object = function() {\n this.position = FSS.Vector3.create();\n};\n\nFSS.Object.prototype = {\n setPosition: function(x, y, z) {\n FSS.Vector3.set(this.position, x, y, z);\n return this;\n }\n};\n\n/**\n * @class Light\n * @author Matthew Wagerfield\n */\nFSS.Light = function(ambient, diffuse) {\n FSS.Object.call(this);\n this.ambient = new FSS.Color(ambient || '#FFFFFF');\n this.diffuse = new FSS.Color(diffuse || '#FFFFFF');\n this.ray = FSS.Vector3.create();\n};\n\nFSS.Light.prototype = Object.create(FSS.Object.prototype);\n\n/**\n * @class Vertex\n * @author Matthew Wagerfield\n */\nFSS.Vertex = function(x, y, z) {\n this.position = FSS.Vector3.create(x, y, z);\n};\n\nFSS.Vertex.prototype = {\n setPosition: function(x, y, z) {\n FSS.Vector3.set(this.position, x, y, z);\n return this;\n }\n};\n\n/**\n * @class Triangle\n * @author Matthew Wagerfield\n */\nFSS.Triangle = function(a, b, c) {\n this.a = a || new FSS.Vertex();\n this.b = b || new FSS.Vertex();\n this.c = c || new FSS.Vertex();\n this.vertices = [this.a, this.b, this.c];\n this.u = FSS.Vector3.create();\n this.v = FSS.Vector3.create();\n this.centroid = FSS.Vector3.create();\n this.normal = FSS.Vector3.create();\n this.color = new FSS.Color();\n this.polygon = document.createElementNS(FSS.SVGNS, 'polygon');\n this.polygon.setAttributeNS(null, 'stroke-linejoin', 'round');\n this.polygon.setAttributeNS(null, 'stroke-miterlimit', '1');\n this.polygon.setAttributeNS(null, 'stroke-width', '1');\n this.computeCentroid();\n this.computeNormal();\n};\n\nFSS.Triangle.prototype = {\n computeCentroid: function() {\n this.centroid[0] = this.a.position[0] + this.b.position[0] + this.c.position[0];\n this.centroid[1] = this.a.position[1] + this.b.position[1] + this.c.position[1];\n this.centroid[2] = this.a.position[2] + this.b.position[2] + this.c.position[2];\n FSS.Vector3.divideScalar(this.centroid, 3);\n return this;\n },\n computeNormal: function() {\n FSS.Vector3.subtractVectors(this.u, this.b.position, this.a.position);\n FSS.Vector3.subtractVectors(this.v, this.c.position, this.a.position);\n FSS.Vector3.crossVectors(this.normal, this.u, this.v);\n FSS.Vector3.normalise(this.normal);\n return this;\n }\n};\n\n/**\n * @class Geometry\n * @author Matthew Wagerfield\n */\nFSS.Geometry = function() {\n this.vertices = [];\n this.triangles = [];\n this.dirty = false;\n};\n\nFSS.Geometry.prototype = {\n update: function() {\n if (this.dirty) {\n var t,triangle;\n for (t = this.triangles.length - 1; t >= 0; t--) {\n triangle = this.triangles[t];\n triangle.computeCentroid();\n triangle.computeNormal();\n }\n this.dirty = false;\n }\n return this;\n }\n};\n\n/**\n * @class Plane\n * @author Matthew Wagerfield\n */\nFSS.Plane = function(width, height, segments, slices) {\n FSS.Geometry.call(this);\n this.width = width || 100;\n this.height = height || 100;\n this.segments = segments || 4;\n this.slices = slices || 4;\n this.segmentWidth = this.width / this.segments;\n this.sliceHeight = this.height / this.slices;\n\n // Cache Variables\n var x, y, v0, v1, v2, v3,\n vertex, triangle, vertices = [],\n offsetX = this.width * -0.5,\n offsetY = this.height * 0.5;\n\n // Add Vertices\n for (x = 0; x <= this.segments; x++) {\n vertices.push([]);\n for (y = 0; y <= this.slices; y++) {\n vertex = new FSS.Vertex(offsetX + x*this.segmentWidth, offsetY - y*this.sliceHeight);\n vertices[x].push(vertex);\n this.vertices.push(vertex);\n }\n }\n\n // Add Triangles\n for (x = 0; x < this.segments; x++) {\n for (y = 0; y < this.slices; y++) {\n v0 = vertices[x+0][y+0];\n v1 = vertices[x+0][y+1];\n v2 = vertices[x+1][y+0];\n v3 = vertices[x+1][y+1];\n t0 = new FSS.Triangle(v0, v1, v2);\n t1 = new FSS.Triangle(v2, v1, v3);\n this.triangles.push(t0, t1);\n }\n }\n};\n\nFSS.Plane.prototype = Object.create(FSS.Geometry.prototype);\n\n/**\n * @class Material\n * @author Matthew Wagerfield\n */\nFSS.Material = function(ambient, diffuse) {\n this.ambient = new FSS.Color(ambient || '#444444');\n this.diffuse = new FSS.Color(diffuse || '#000');\n this.slave = new FSS.Color();\n};\n\n/**\n * @class Mesh\n * @author Matthew Wagerfield\n */\nFSS.Mesh = function(geometry, material) {\n FSS.Object.call(this);\n this.geometry = geometry || new FSS.Geometry();\n this.material = material || new FSS.Material();\n this.side = FSS.FRONT;\n this.visible = true;\n};\n\nFSS.Mesh.prototype = Object.create(FSS.Object.prototype);\n\nFSS.Mesh.prototype.update = function(lights, calculate) {\n var t,triangle, l,light, illuminance;\n\n // Update Geometry\n this.geometry.update();\n\n // Calculate the triangle colors\n if (calculate) {\n\n // Iterate through Triangles\n for (t = this.geometry.triangles.length - 1; t >= 0; t--) {\n triangle = this.geometry.triangles[t];\n\n // Reset Triangle Color\n FSS.Vector4.set(triangle.color.rgba);\n\n // Iterate through Lights\n for (l = lights.length - 1; l >= 0; l--) {\n light = lights[l];\n\n // Calculate Illuminance\n FSS.Vector3.subtractVectors(light.ray, light.position, triangle.centroid);\n FSS.Vector3.normalise(light.ray);\n illuminance = FSS.Vector3.dot(triangle.normal, light.ray);\n if (this.side === FSS.FRONT) {\n illuminance = Math.max(illuminance, 0);\n } else if (this.side === FSS.BACK) {\n illuminance = Math.abs(Math.min(illuminance, 0));\n } else if (this.side === FSS.DOUBLE) {\n illuminance = Math.max(Math.abs(illuminance), 0);\n }\n\n // Calculate Ambient Light\n FSS.Vector4.multiplyVectors(this.material.slave.rgba, this.material.ambient.rgba, light.ambient.rgba);\n FSS.Vector4.add(triangle.color.rgba, this.material.slave.rgba);\n\n // Calculate Diffuse Light\n FSS.Vector4.multiplyVectors(this.material.slave.rgba, this.material.diffuse.rgba, light.diffuse.rgba);\n FSS.Vector4.multiplyScalar(this.material.slave.rgba, illuminance);\n FSS.Vector4.add(triangle.color.rgba, this.material.slave.rgba);\n }\n\n // Clamp & Format Color\n FSS.Vector4.clamp(triangle.color.rgba, 0, 1);\n }\n }\n return this;\n};\n\n/**\n * @class Scene\n * @author Matthew Wagerfield\n */\nFSS.Scene = function() {\n this.meshes = [];\n this.lights = [];\n};\n\nFSS.Scene.prototype = {\n add: function(object) {\n if (object instanceof FSS.Mesh && !~this.meshes.indexOf(object)) {\n this.meshes.push(object);\n } else if (object instanceof FSS.Light && !~this.lights.indexOf(object)) {\n this.lights.push(object);\n }\n return this;\n },\n remove: function(object) {\n if (object instanceof FSS.Mesh && ~this.meshes.indexOf(object)) {\n this.meshes.splice(this.meshes.indexOf(object), 1);\n } else if (object instanceof FSS.Light && ~this.lights.indexOf(object)) {\n this.lights.splice(this.lights.indexOf(object), 1);\n }\n return this;\n }\n};\n\n/**\n * @class Renderer\n * @author Matthew Wagerfield\n */\nFSS.Renderer = function() {\n this.width = 0;\n this.height = 0;\n this.halfWidth = 0;\n this.halfHeight = 0;\n};\n\nFSS.Renderer.prototype = {\n setSize: function(width, height) {\n if (this.width === width && this.height === height) return;\n this.width = width;\n this.height = height;\n this.halfWidth = this.width * 0.5;\n this.halfHeight = this.height * 0.5;\n return this;\n },\n clear: function() {\n return this;\n },\n render: function(scene) {\n return this;\n }\n};\n\n/**\n * @class Canvas Renderer\n * @author Matthew Wagerfield\n */\nFSS.CanvasRenderer = function() {\n FSS.Renderer.call(this);\n this.element = document.createElement('canvas');\n this.element.style.display = 'block';\n this.element.setAttribute(\"id\", \"myCanvas\"); \n this.context = this.element.getContext('2d'); \n //this.element.style.filter = \"blur(10px)\";\n this.setSize(this.element.width, this.element.height);\n};\n\nFSS.CanvasRenderer.prototype = Object.create(FSS.Renderer.prototype);\n\nFSS.CanvasRenderer.prototype.setSize = function(width, height) {\n FSS.Renderer.prototype.setSize.call(this, width, height);\n this.element.width = width;\n this.element.height = height;\n this.context.setTransform(1, 0, 0, -1, this.halfWidth, this.halfHeight);\n return this;\n};\n\nFSS.CanvasRenderer.prototype.clear = function() {\n FSS.Renderer.prototype.clear.call(this);\n this.context.clearRect(-this.halfWidth, -this.halfHeight, this.width, this.height);\n return this;\n};\n\nFSS.CanvasRenderer.prototype.render = function(scene) {\n FSS.Renderer.prototype.render.call(this, scene);\n var m,mesh, t,triangle, color;\n\n // Clear Context\n this.clear();\n\n // Configure Context\n this.context.lineJoin = 'round';\n this.context.lineWidth = 1;\n\n // Update Meshes\n for (m = scene.meshes.length - 1; m >= 0; m--) {\n mesh = scene.meshes[m];\n if (mesh.visible) {\n mesh.update(scene.lights, true);\n\n // Render Triangles\n for (t = mesh.geometry.triangles.length - 1; t >= 0; t--) {\n triangle = mesh.geometry.triangles[t];\n color = triangle.color.format();\n this.context.beginPath();\n this.context.moveTo(triangle.a.position[0], triangle.a.position[1]);\n this.context.lineTo(triangle.b.position[0], triangle.b.position[1]);\n this.context.lineTo(triangle.c.position[0], triangle.c.position[1]);\n this.context.closePath();\n this.context.globalAlpha = 0.3;\n this.context.strokeStyle = color;\n this.context.fillStyle = color;\n this.context.stroke();\n this.context.fill();\n }\n }\n }\n return this;\n};\n\n/**\n * @class WebGL Renderer\n * @author Matthew Wagerfield\n */\nFSS.WebGLRenderer = function() {\n FSS.Renderer.call(this);\n this.element = document.createElement('canvas');\n this.element.style.display = 'block';\n\n // Set initial vertex and light count\n this.vertices = null;\n this.lights = null;\n\n // Create parameters object\n var parameters = {\n preserveDrawingBuffer: false,\n premultipliedAlpha: true,\n antialias: true,\n stencil: true,\n alpha: true\n };\n\n // Create and configure the gl context\n this.gl = this.getContext(this.element, parameters);\n\n // Set the internal support flag\n this.unsupported = !this.gl;\n\n // Setup renderer\n if (this.unsupported) {\n return 'WebGL is not supported by your browser.';\n } else {\n this.gl.clearColor(0.0, 0.0, 0.0, 0.0);\n this.gl.enable(this.gl.DEPTH_TEST);\n this.setSize(this.element.width, this.element.height);\n }\n};\n\nFSS.WebGLRenderer.prototype = Object.create(FSS.Renderer.prototype);\n\nFSS.WebGLRenderer.prototype.getContext = function(canvas, parameters) {\n var context = false;\n try {\n if (!(context = canvas.getContext('experimental-webgl', parameters))) {\n throw 'Error creating WebGL context.';\n }\n } catch (error) {\n console.error(error);\n }\n return context;\n};\n\nFSS.WebGLRenderer.prototype.setSize = function(width, height) {\n FSS.Renderer.prototype.setSize.call(this, width, height);\n if (this.unsupported) return;\n\n // Set the size of the canvas element\n this.element.width = width;\n this.element.height = height;\n\n // Set the size of the gl viewport\n this.gl.viewport(0, 0, width, height);\n return this;\n};\n\nFSS.WebGLRenderer.prototype.clear = function() {\n FSS.Renderer.prototype.clear.call(this);\n if (this.unsupported) return;\n this.gl.clear(this.gl.COLOR_BUFFER_BIT | this.gl.DEPTH_BUFFER_BIT);\n return this;\n};\n\nFSS.WebGLRenderer.prototype.render = function(scene) {\n FSS.Renderer.prototype.render.call(this, scene);\n if (this.unsupported) return;\n var m,mesh, t,tl,triangle, l,light,\n attribute, uniform, buffer, data, location,\n update = false, lights = scene.lights.length,\n index, v,vl,vetex,vertices = 0;\n\n // Clear context\n this.clear();\n\n // Build the shader program\n if (this.lights !== lights) {\n this.lights = lights;\n if (this.lights > 0) {\n this.buildProgram(lights);\n } else {\n return;\n }\n }\n\n // Update program\n if (!!this.program) {\n\n // Increment vertex counter\n for (m = scene.meshes.length - 1; m >= 0; m--) {\n mesh = scene.meshes[m];\n if (mesh.geometry.dirty) update = true;\n mesh.update(scene.lights, false);\n vertices += mesh.geometry.triangles.length*3;\n }\n\n // Compare vertex counter\n if (update || this.vertices !== vertices) {\n this.vertices = vertices;\n\n // Build buffers\n for (attribute in this.program.attributes) {\n buffer = this.program.attributes[attribute];\n buffer.data = new FSS.Array(vertices*buffer.size);\n\n // Reset vertex index\n index = 0;\n\n // Update attribute buffer data\n for (m = scene.meshes.length - 1; m >= 0; m--) {\n mesh = scene.meshes[m];\n\n for (t = 0, tl = mesh.geometry.triangles.length; t < tl; t++) {\n triangle = mesh.geometry.triangles[t];\n\n for (v = 0, vl = triangle.vertices.length; v < vl; v++) {\n vertex = triangle.vertices[v];\n switch (attribute) {\n case 'side':\n this.setBufferData(index, buffer, mesh.side);\n break;\n case 'position':\n this.setBufferData(index, buffer, vertex.position);\n break;\n case 'centroid':\n this.setBufferData(index, buffer, triangle.centroid);\n break;\n case 'normal':\n this.setBufferData(index, buffer, triangle.normal);\n break;\n case 'ambient':\n this.setBufferData(index, buffer, mesh.material.ambient.rgba);\n break;\n case 'diffuse':\n this.setBufferData(index, buffer, mesh.material.diffuse.rgba);\n break;\n }\n index++;\n }\n }\n }\n\n // Upload attribute buffer data\n this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer.buffer);\n this.gl.bufferData(this.gl.ARRAY_BUFFER, buffer.data, this.gl.DYNAMIC_DRAW);\n this.gl.enableVertexAttribArray(buffer.location);\n this.gl.vertexAttribPointer(buffer.location, buffer.size, this.gl.FLOAT, false, 0, 0);\n }\n }\n\n // Build uniform buffers\n this.setBufferData(0, this.program.uniforms.resolution, [this.width, this.height, this.width]);\n for (l = lights-1; l >= 0; l--) {\n light = scene.lights[l];\n this.setBufferData(l, this.program.uniforms.lightPosition, light.position);\n this.setBufferData(l, this.program.uniforms.lightAmbient, light.ambient.rgba);\n this.setBufferData(l, this.program.uniforms.lightDiffuse, light.diffuse.rgba);\n }\n\n // Update uniforms\n for (uniform in this.program.uniforms) {\n buffer = this.program.uniforms[uniform];\n location = buffer.location;\n data = buffer.data;\n switch (buffer.structure) {\n case '3f':\n this.gl.uniform3f(location, data[0], data[1], data[2]);\n break;\n case '3fv':\n this.gl.uniform3fv(location, data);\n break;\n case '4fv':\n this.gl.uniform4fv(location, data);\n break;\n }\n }\n }\n\n // Draw those lovely triangles\n this.gl.drawArrays(this.gl.TRIANGLES, 0, this.vertices);\n return this;\n};\n\nFSS.WebGLRenderer.prototype.setBufferData = function(index, buffer, value) {\n if (FSS.Utils.isNumber(value)) {\n buffer.data[index*buffer.size] = value;\n } else {\n for (var i = value.length - 1; i >= 0; i--) {\n buffer.data[index*buffer.size+i] = value[i];\n }\n }\n};\n\n/**\n * Concepts taken from three.js WebGLRenderer\n * @see https://github.com/mrdoob/three.js/blob/master/src/renderers/WebGLRenderer.js\n */\nFSS.WebGLRenderer.prototype.buildProgram = function(lights) {\n if (this.unsupported) return;\n\n // Create shader source\n var vs = FSS.WebGLRenderer.VS(lights);\n var fs = FSS.WebGLRenderer.FS(lights);\n\n // Derive the shader fingerprint\n var code = vs + fs;\n\n // Check if the program has already been compiled\n if (!!this.program && this.program.code === code) return;\n\n // Create the program and shaders\n var program = this.gl.createProgram();\n var vertexShader = this.buildShader(this.gl.VERTEX_SHADER, vs);\n var fragmentShader = this.buildShader(this.gl.FRAGMENT_SHADER, fs);\n\n // Attach an link the shader\n this.gl.attachShader(program, vertexShader);\n this.gl.attachShader(program, fragmentShader);\n this.gl.linkProgram(program);\n\n // Add error handling\n if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {\n var error = this.gl.getError();\n var status = this.gl.getProgramParameter(program, this.gl.VALIDATE_STATUS);\n console.error('Could not initialise shader.\\nVALIDATE_STATUS: '+status+'\\nERROR: '+error);\n return null;\n }\n\n // Delete the shader\n this.gl.deleteShader(fragmentShader);\n this.gl.deleteShader(vertexShader);\n\n // Set the program code\n program.code = code;\n\n // Add the program attributes\n program.attributes = {\n side: this.buildBuffer(program, 'attribute', 'aSide', 1, 'f' ),\n position: this.buildBuffer(program, 'attribute', 'aPosition', 3, 'v3'),\n centroid: this.buildBuffer(program, 'attribute', 'aCentroid', 3, 'v3'),\n normal: this.buildBuffer(program, 'attribute', 'aNormal', 3, 'v3'),\n ambient: this.buildBuffer(program, 'attribute', 'aAmbient', 4, 'v4'),\n diffuse: this.buildBuffer(program, 'attribute', 'aDiffuse', 4, 'v4')\n };\n\n // Add the program uniforms\n program.uniforms = {\n resolution: this.buildBuffer(program, 'uniform', 'uResolution', 3, '3f', 1 ),\n lightPosition: this.buildBuffer(program, 'uniform', 'uLightPosition', 3, '3fv', lights),\n lightAmbient: this.buildBuffer(program, 'uniform', 'uLightAmbient', 4, '4fv', lights),\n lightDiffuse: this.buildBuffer(program, 'uniform', 'uLightDiffuse', 4, '4fv', lights)\n };\n\n // Set the renderer program\n this.program = program;\n\n // Enable program\n this.gl.useProgram(this.program);\n\n // Return the program\n return program;\n};\n\nFSS.WebGLRenderer.prototype.buildShader = function(type, source) {\n if (this.unsupported) return;\n\n // Create and compile shader\n var shader = this.gl.createShader(type);\n this.gl.shaderSource(shader, source);\n this.gl.compileShader(shader);\n\n // Add error handling\n if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {\n console.error(this.gl.getShaderInfoLog(shader));\n return null;\n }\n\n // Return the shader\n return shader;\n};\n\nFSS.WebGLRenderer.prototype.buildBuffer = function(program, type, identifier, size, structure, count) {\n var buffer = {buffer:this.gl.createBuffer(), size:size, structure:structure, data:null};\n\n // Set the location\n switch (type) {\n case 'attribute':\n buffer.location = this.gl.getAttribLocation(program, identifier);\n break;\n case 'uniform':\n buffer.location = this.gl.getUniformLocation(program, identifier);\n break;\n }\n\n // Create the buffer if count is provided\n if (!!count) {\n buffer.data = new FSS.Array(count*size);\n }\n\n // Return the buffer\n return buffer;\n};\n\nFSS.WebGLRenderer.VS = function(lights) {\n var shader = [\n\n // Precision\n 'precision mediump float;',\n\n // Lights\n '#define LIGHTS ' + lights,\n\n // Attributes\n 'attribute float aSide;',\n 'attribute vec3 aPosition;',\n 'attribute vec3 aCentroid;',\n 'attribute vec3 aNormal;',\n 'attribute vec4 aAmbient;',\n 'attribute vec4 aDiffuse;',\n\n // Uniforms\n 'uniform vec3 uResolution;',\n 'uniform vec3 uLightPosition[LIGHTS];',\n 'uniform vec4 uLightAmbient[LIGHTS];',\n 'uniform vec4 uLightDiffuse[LIGHTS];',\n\n // Varyings\n 'varying vec4 vColor;',\n\n // Main\n 'void main() {',\n\n // Create color\n 'vColor = vec4(0.0);',\n\n // Calculate the vertex position\n 'vec3 position = aPosition / uResolution * 2.0;',\n\n // Iterate through lights\n 'for (int i = 0; i < LIGHTS; i++) {',\n 'vec3 lightPosition = uLightPosition[i];',\n 'vec4 lightAmbient = uLightAmbient[i];',\n 'vec4 lightDiffuse = uLightDiffuse[i];',\n\n // Calculate illuminance\n 'vec3 ray = normalize(lightPosition - aCentroid);',\n 'float illuminance = dot(aNormal, ray);',\n 'if (aSide == 0.0) {',\n 'illuminance = max(illuminance, 0.0);',\n '} else if (aSide == 1.0) {',\n 'illuminance = abs(min(illuminance, 0.0));',\n '} else if (aSide == 2.0) {',\n 'illuminance = max(abs(illuminance), 0.0);',\n '}',\n\n // Calculate ambient light\n 'vColor += aAmbient * lightAmbient;',\n\n // Calculate diffuse light\n 'vColor += aDiffuse * lightDiffuse * illuminance;',\n '}',\n\n // Clamp color\n 'vColor = clamp(vColor, 0.0, 1.0);',\n\n // Set gl_Position\n 'gl_Position = vec4(position, 1.0);',\n\n '}'\n\n // Return the shader\n ].join('\\n');\n return shader;\n};\n\nFSS.WebGLRenderer.FS = function(lights) {\n var shader = [\n\n // Precision\n 'precision mediump float;',\n\n // Varyings\n 'varying vec4 vColor;',\n\n // Main\n 'void main() {',\n\n // Set gl_FragColor\n 'gl_FragColor = vColor;',\n\n '}'\n\n // Return the shader\n ].join('\\n');\n return shader;\n};\n\n/**\n * @class SVG Renderer\n * @author Matthew Wagerfield\n */\nFSS.SVGRenderer = function() {\n FSS.Renderer.call(this);\n this.element = document.createElementNS(FSS.SVGNS, 'svg');\n this.element.setAttribute('xmlns', FSS.SVGNS);\n this.element.setAttribute('version', '1.1');\n this.element.style.display = 'block';\n this.setSize(300, 150);\n};\n\nFSS.SVGRenderer.prototype = Object.create(FSS.Renderer.prototype);\n\nFSS.SVGRenderer.prototype.setSize = function(width, height) {\n FSS.Renderer.prototype.setSize.call(this, width, height);\n this.element.setAttribute('width', width);\n this.element.setAttribute('height', height);\n return this;\n};\n\nFSS.SVGRenderer.prototype.clear = function() {\n FSS.Renderer.prototype.clear.call(this);\n for (var i = this.element.childNodes.length - 1; i >= 0; i--) {\n this.element.removeChild(this.element.childNodes[i]);\n }\n return this;\n};\n\nFSS.SVGRenderer.prototype.render = function(scene) {\n FSS.Renderer.prototype.render.call(this, scene);\n var m,mesh, t,triangle, points, style;\n\n // Update Meshes\n for (m = scene.meshes.length - 1; m >= 0; m--) {\n mesh = scene.meshes[m];\n if (mesh.visible) {\n mesh.update(scene.lights, true);\n\n // Render Triangles\n for (t = mesh.geometry.triangles.length - 1; t >= 0; t--) {\n triangle = mesh.geometry.triangles[t];\n if (triangle.polygon.parentNode !== this.element) {\n this.element.appendChild(triangle.polygon);\n }\n points = this.formatPoint(triangle.a)+' ';\n points += this.formatPoint(triangle.b)+' ';\n points += this.formatPoint(triangle.c);\n style = this.formatStyle(triangle.color.format());\n triangle.polygon.setAttributeNS(null, 'points', points);\n triangle.polygon.setAttributeNS(null, 'style', style);\n }\n }\n }\n return this;\n};\n\nFSS.SVGRenderer.prototype.formatPoint = function(vertex) {\n return (this.halfWidth+vertex.position[0])+','+(this.halfHeight-vertex.position[1]);\n};\n\nFSS.SVGRenderer.prototype.formatStyle = function(color) {\n var style = 'fill:'+color+';';\n style += 'stroke:'+color+';';\n return style;\n};\n\n\n\n////////////////////////////////\n////////////////////////////////\n////////////////////////////////\n\n\n(function(){\n if(!document.getElementById('ffshadeoutput')){\n return false;\n }\n //------------------------------\n // Mesh Properties\n //------------------------------\n var MESH = {\n width: 1.8,\n height: 1.8,\n depth: 10,\n segments: 16,\n slices: 8,\n xRange: 0.8,\n yRange: 0.1,\n zRange: 1.0,\n ambient: '#555555',\n diffuse: '#696969',\n speed: 0.0001\n };\n\n //------------------------------\n // Light Properties\n //------------------------------\n var LIGHT = {\n count: 2,\n xyScalar: 1,\n zOffset: 100,\n ambient: '#1C2B36',\n diffuse: '#3BC0C3',\n speed: 0.0002,\n gravity: 500,\n dampening: 0.95,\n minLimit: 10,\n maxLimit: null,\n minDistance: 20,\n maxDistance: 400,\n autopilot: true,\n draw: false,\n bounds: FSS.Vector3.create(),\n step: FSS.Vector3.create(\n Math.randomInRange(0.2, 1.0),\n Math.randomInRange(0.2, 1.0),\n Math.randomInRange(0.2, 1.0)\n )\n };\n\n //------------------------------\n // Render Properties\n //------------------------------\n\n var RENDER = {\n renderer: 'canvas'\n };\n\n //------------------------------\n // Global Properties\n //------------------------------\n var now, start = Date.now();\n var center = FSS.Vector3.create();\n var attractor = FSS.Vector3.create();\n var container = document.getElementById('ffshade');\n var output = document.getElementById('ffshadeoutput');\n var renderer, scene, mesh, geometry, material;\n var canvasRenderer;\n var gui, autopilotController;\n //------------------------------\n // Methods\n //------------------------------\n function initialise() {\n createRenderer();\n createScene();\n createMesh();\n createLights();\n addEventListeners();\n resize(container.offsetWidth, container.offsetHeight);\n animate();\n }\n\n function createRenderer() {\n canvasRenderer = new FSS.CanvasRenderer();\n setRenderer(RENDER.renderer);\n }\n\n function setRenderer(index) {\n if (renderer) {\n output.removeChild(renderer.element);\n }\n\n renderer = canvasRenderer;\n\n renderer.setSize(container.offsetWidth, container.offsetHeight);\n output.appendChild(renderer.element);\n }\n\n function createScene() {\n scene = new FSS.Scene();\n }\n\n function createMesh() {\n scene.remove(mesh);\n renderer.clear();\n geometry = new FSS.Plane(MESH.width * renderer.width, MESH.height * renderer.height, MESH.segments, MESH.slices);\n material = new FSS.Material(MESH.ambient, MESH.diffuse);\n mesh = new FSS.Mesh(geometry, material);\n scene.add(mesh);\n\n // Augment vertices for animation\n var v, vertex;\n for (v = geometry.vertices.length - 1; v >= 0; v--) {\n vertex = geometry.vertices[v];\n vertex.anchor = FSS.Vector3.clone(vertex.position);\n vertex.step = FSS.Vector3.create(\n Math.randomInRange(0.2, 1.0),\n Math.randomInRange(0.2, 1.0),\n Math.randomInRange(0.2, 1.0)\n );\n vertex.time = Math.randomInRange(0, Math.PIM2);\n }\n }\n\n function createLights() {\n var l, light;\n for (l = scene.lights.length - 1; l >= 0; l--) {\n light = scene.lights[l];\n scene.remove(light);\n }\n renderer.clear();\n for (l = 0; l < LIGHT.count; l++) {\n light = new FSS.Light(LIGHT.ambient, LIGHT.diffuse);\n light.ambientHex = light.ambient.format();\n light.diffuseHex = light.diffuse.format();\n scene.add(light);\n\n // Augment light for animation\n light.mass = Math.randomInRange(0.5, 1);\n light.velocity = FSS.Vector3.create();\n light.acceleration = FSS.Vector3.create();\n light.force = FSS.Vector3.create();\n\n // Ring SVG Circle\n light.ring = document.createElementNS(FSS.SVGNS, 'circle');\n light.ring.setAttributeNS(null, 'stroke', light.ambientHex);\n light.ring.setAttributeNS(null, 'stroke-width', '0.5');\n light.ring.setAttributeNS(null, 'fill', 'none');\n light.ring.setAttributeNS(null, 'r', '10');\n\n // Core SVG Circle\n light.core = document.createElementNS(FSS.SVGNS, 'circle');\n light.core.setAttributeNS(null, 'fill', light.diffuseHex);\n light.core.setAttributeNS(null, 'r', '4');\n }\n }\n\n function resize(width, height) {\n renderer.setSize(width, height);\n FSS.Vector3.set(center, renderer.halfWidth, renderer.halfHeight);\n createMesh();\n }\n\n function animate() {\n now = Date.now() - start;\n update();\n render();\n requestAnimationFrame(animate);\n }\n\n function update() {\n var ox, oy, oz, l, light, v, vertex, offset = MESH.depth/2;\n\n // Update Bounds\n FSS.Vector3.copy(LIGHT.bounds, center);\n FSS.Vector3.multiplyScalar(LIGHT.bounds, LIGHT.xyScalar);\n\n // Update Attractor\n FSS.Vector3.setZ(attractor, LIGHT.zOffset);\n\n // Overwrite the Attractor position\n if (LIGHT.autopilot) {\n ox = Math.sin(LIGHT.step[0] * now * LIGHT.speed);\n oy = Math.cos(LIGHT.step[1] * now * LIGHT.speed);\n FSS.Vector3.set(attractor,\n LIGHT.bounds[0]*ox,\n LIGHT.bounds[1]*oy,\n LIGHT.zOffset);\n }\n\n // Animate Lights\n for (l = scene.lights.length - 1; l >= 0; l--) {\n light = scene.lights[l];\n\n // Reset the z position of the light\n FSS.Vector3.setZ(light.position, LIGHT.zOffset);\n\n // Calculate the force Luke!\n var D = Math.clamp(FSS.Vector3.distanceSquared(light.position, attractor), LIGHT.minDistance, LIGHT.maxDistance);\n var F = LIGHT.gravity * light.mass / D;\n FSS.Vector3.subtractVectors(light.force, attractor, light.position);\n FSS.Vector3.normalise(light.force);\n FSS.Vector3.multiplyScalar(light.force, F);\n\n // Update the light position\n FSS.Vector3.set(light.acceleration);\n FSS.Vector3.add(light.acceleration, light.force);\n FSS.Vector3.add(light.velocity, light.acceleration);\n FSS.Vector3.multiplyScalar(light.velocity, LIGHT.dampening);\n FSS.Vector3.limit(light.velocity, LIGHT.minLimit, LIGHT.maxLimit);\n FSS.Vector3.add(light.position, light.velocity);\n }\n\n // Animate Vertices\n for (v = geometry.vertices.length - 1; v >= 0; v--) {\n vertex = geometry.vertices[v];\n ox = Math.sin(vertex.time + vertex.step[0] * now * MESH.speed);\n oy = Math.cos(vertex.time + vertex.step[1] * now * MESH.speed);\n oz = Math.sin(vertex.time + vertex.step[2] * now * MESH.speed);\n FSS.Vector3.set(vertex.position,\n MESH.xRange*geometry.segmentWidth*ox,\n MESH.yRange*geometry.sliceHeight*oy,\n MESH.zRange*offset*oz - offset);\n FSS.Vector3.add(vertex.position, vertex.anchor);\n }\n\n // Set the Geometry to dirty\n geometry.dirty = true;\n }\n\n function render() {\n renderer.render(scene);\n\n // Draw Lights\n if (LIGHT.draw) {\n var l, lx, ly, light;\n for (l = scene.lights.length - 1; l >= 0; l--) {\n light = scene.lights[l];\n lx = light.position[0];\n ly = light.position[1];\n renderer.context.lineWidth = 0.5;\n renderer.context.beginPath();\n renderer.context.arc(lx, ly, 10, 0, Math.PIM2);\n renderer.context.strokeStyle = light.ambientHex;\n renderer.context.stroke();\n renderer.context.beginPath();\n renderer.context.arc(lx, ly, 4, 0, Math.PIM2);\n renderer.context.fillStyle = light.diffuseHex;\n renderer.context.fill();\n \n }\n }\n }\n\n function addEventListeners() {\n window.addEventListener('resize', onWindowResize);\n //container.addEventListener('mousemove', onMouseMove);\n }\n\n //------------------------------\n // Callbacks\n //------------------------------\n\n function onMouseMove(event) {\n FSS.Vector3.set(attractor, event.x, renderer.height - event.y);\n FSS.Vector3.subtract(attractor, center);\n }\n\n function onWindowResize(event) {\n resize(container.offsetWidth, container.offsetHeight);\n render();\n }\n\n\n // Let there be light!\n if(output !== null){\n //initialise();\n window.initFFS = initialise;\n }\n\n})(); "]}