webGL fixes
diff --git a/player/index.html b/player/index.html
index 21aa730..f7f893f 100644
--- a/player/index.html
+++ b/player/index.html
@@ -17,8 +17,8 @@
             height:100%;
             /*width:1000px;
             height:500px;*/
-            width:550px;
-            height:400px;
+            width:1200px;
+            height:600px;
             display:block;
             overflow: hidden;
             transform: translate3d(0,0,0);
@@ -147,6 +147,7 @@
     <script src="js/elements/webglElements/WebGLCompElement.js" data-builds="webgl,webgl_light"></script>
     <script src="js/elements/webglElements/WebGLShapeElement.js" data-builds="webgl,webgl_light"></script>
     <script src="js/elements/webglElements/WebGLMaskElement.js" data-builds="webgl,webgl_light"></script>
+    <script src="js/elements/webglElements/WebGLCamera.js" data-builds="webgl,webgl_light"></script>
     <script src="js/elements/webglElements/WebGLTrackMatte.js" data-builds="webgl,webgl_light"></script>
     <script src="js/elements/webglElements/WebGLEffects.js" data-builds="webgl,webgl_light"></script>
     <script src="js/elements/webglElements/effects/WebGLTintEffect.js" data-builds="webgl,webgl_light"></script>
@@ -211,6 +212,7 @@
     };
     // lottie.setQuality('low');
     lottie.registerEffect('ADBE Twirl', WTwirlEffect)
+    lottie.registerEffect('ADBE Tint', WTintFilter)
     anim = lottie.loadAnimation(animData);
     anim.setSubframe(false);
     anim.onError = function(errorType, nativeError, errorProps) {
diff --git a/player/js/elements/webglElements/WebGLBaseElement.js b/player/js/elements/webglElements/WebGLBaseElement.js
index 59f8366..ed9c1e7 100644
--- a/player/js/elements/webglElements/WebGLBaseElement.js
+++ b/player/js/elements/webglElements/WebGLBaseElement.js
@@ -36,7 +36,7 @@
         }
     },
     renderFrame: function() {
-        console.log('RENDER FRAME')
+        // console.log('RENDER FRAME')
         if (this.hidden || this.data.hd) {
             return;
         }
@@ -91,6 +91,7 @@
             var p = tr.props;
             newTransform.transform(p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12],p[13],p[14],p[15]);
             //TODO: only update the uniform if needed. This is costly.
+            // console.log(this.localTransform.props)
             this.glContext.uniformMatrix4fv(this.mat4UniformLoc, false, this.localTransform.props);
         }
     },
diff --git a/player/js/elements/webglElements/WebGLCamera.js b/player/js/elements/webglElements/WebGLCamera.js
new file mode 100644
index 0000000..f2aed59
--- /dev/null
+++ b/player/js/elements/webglElements/WebGLCamera.js
@@ -0,0 +1,171 @@
+function WebGLCamera(data,globalData,comp){
+    if(!data) {
+        data = {
+            ks: {
+                p: {
+                    k: [0,0,0]
+                },
+                a: {
+                    k: [0,0,0]
+                },
+                or: {
+                    k: [0,0,0]
+                },
+                rx: {
+                    k: 0
+                },
+                ry: {
+                    k: 0
+                },
+                rz: {
+                    k: 0
+                }
+            },
+            pe: {
+                k: 1666 // This is the default zoom on a AE camera
+            }
+        }
+    }
+    this.initFrame();
+    this.initBaseData(data,globalData,comp);
+    this.initHierarchy();
+    var getProp = PropertyFactory.getProp;
+    this.pe = getProp(this,data.pe,0,0,this);
+    if(data.ks.p.s){
+        this.px = getProp(this,data.ks.p.x,1,0,this);
+        this.py = getProp(this,data.ks.p.y,1,0,this);
+        this.pz = getProp(this,data.ks.p.z,1,0,this);
+    }else{
+        this.p = getProp(this,data.ks.p,1,0,this);
+    }
+    if(data.ks.a){
+        this.a = getProp(this,data.ks.a,1,0,this);
+    }
+    if(data.ks.or.k.length && data.ks.or.k[0].to){
+        var i,len = data.ks.or.k.length;
+        for(i=0;i<len;i+=1){
+            data.ks.or.k[i].to = null;
+            data.ks.or.k[i].ti = null;
+        }
+    }
+    this.or = getProp(this,data.ks.or,1,degToRads,this);
+    this.or.sh = true;
+    this.rx = getProp(this,data.ks.rx,0,degToRads,this);
+    this.ry = getProp(this,data.ks.ry,0,degToRads,this);
+    this.rz = getProp(this,data.ks.rz,0,degToRads,this);
+    this.mat = new Matrix();
+    this._prevMat = new Matrix();
+    this._isFirstFrame = true;
+    
+    // TODO: find a better way to make the HCamera element to be compatible with the LayerInterface and TransformInterface.
+    this.finalTransform = {
+        mProp: this
+    };
+}
+extendPrototype([BaseElement, FrameElement, HierarchyElement], WebGLCamera);
+
+WebGLCamera.prototype.setup = function() {
+    var i, len = this.comp.threeDElements.length, comp;
+    for(i=0;i<len;i+=1){
+        //[perspectiveElem,container]
+        comp = this.comp.threeDElements[i];
+        if(comp.type === '3d') {
+            comp.perspectiveElem.style.perspective = comp.perspectiveElem.style.webkitPerspective = this.pe.v+'px';
+            comp.container.style.transformOrigin = comp.container.style.mozTransformOrigin = comp.container.style.webkitTransformOrigin = "0px 0px 0px";
+            comp.perspectiveElem.style.transform = comp.perspectiveElem.style.webkitTransform = 'matrix3d(1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1)';
+        }
+    }
+};
+
+WebGLCamera.prototype.createElements = function(){
+};
+
+WebGLCamera.prototype.hide = function(){
+};
+
+WebGLCamera.prototype.addPerspectiveProjection = function(){
+
+}
+
+WebGLCamera.prototype.renderFrame = function(){
+    var _mdf = this._isFirstFrame;
+    var i, len;
+    if(this.hierarchy){
+        len = this.hierarchy.length;
+        for(i=0;i<len;i+=1){
+            _mdf = this.hierarchy[i].finalTransform.mProp._mdf || _mdf;
+        }
+    }
+    if(_mdf || this.pe._mdf || (this.p && this.p._mdf) || (this.px && (this.px._mdf || this.py._mdf || this.pz._mdf)) || this.rx._mdf || this.ry._mdf || this.rz._mdf || this.or._mdf || (this.a && this.a._mdf)) {
+        this.mat.reset();
+
+        if(this.hierarchy){
+            var mat;
+            len = this.hierarchy.length - 1;
+            for (i = len; i >= 0; i -= 1) {
+                var mTransf = this.hierarchy[i].finalTransform.mProp;
+                this.mat.translate(-mTransf.p.v[0],-mTransf.p.v[1],mTransf.p.v[2]);
+                this.mat.rotateX(-mTransf.or.v[0]).rotateY(-mTransf.or.v[1]).rotateZ(mTransf.or.v[2]);
+                this.mat.rotateX(-mTransf.rx.v).rotateY(-mTransf.ry.v).rotateZ(mTransf.rz.v);
+                this.mat.scale(1/mTransf.s.v[0],1/mTransf.s.v[1],1/mTransf.s.v[2]);
+                this.mat.translate(mTransf.a.v[0],mTransf.a.v[1],mTransf.a.v[2]);
+            }
+        }
+        if (this.p) {
+            this.mat.translate(-this.p.v[0],-this.p.v[1],this.p.v[2]);
+        } else {
+            this.mat.translate(-this.px.v,-this.py.v,this.pz.v);
+        }
+        if (this.a) {
+            var diffVector
+            if (this.p) {
+                diffVector = [this.p.v[0] - this.a.v[0], this.p.v[1] - this.a.v[1], this.p.v[2] - this.a.v[2]];
+            } else {
+                diffVector = [this.px.v - this.a.v[0], this.py.v - this.a.v[1], this.pz.v - this.a.v[2]];
+            }
+            var mag = Math.sqrt(Math.pow(diffVector[0],2)+Math.pow(diffVector[1],2)+Math.pow(diffVector[2],2));
+            var lookDir = [diffVector[0]/mag,diffVector[1]/mag,diffVector[2]/mag];
+            var lookLengthOnXZ = Math.sqrt( lookDir[2]*lookDir[2] + lookDir[0]*lookDir[0] );
+            var m_rotationX = (Math.atan2( lookDir[1], lookLengthOnXZ ));
+            var m_rotationY = (Math.atan2( lookDir[0], -lookDir[2]));
+            this.mat.rotateY(m_rotationY).rotateX(-m_rotationX);
+
+        }
+        this.mat.rotateX(-this.rx.v).rotateY(-this.ry.v).rotateZ(this.rz.v);
+        this.mat.rotateX(-this.or.v[0]).rotateY(-this.or.v[1]).rotateZ(this.or.v[2]);
+        this.mat.translate(this.globalData.compSize.w/2,this.globalData.compSize.h/2,0);
+        this.mat.translate(0,0,this.pe.v);
+        this.addPerspectiveProjection();
+        this.mat.scale(1, 1, 1 / this.pe.v);
+
+
+        
+
+        var hasMatrixChanged = !this._prevMat.equals(this.mat);
+        /*if((hasMatrixChanged || this.pe._mdf) && this.comp.threeDElements) {
+            len = this.comp.threeDElements.length;
+            var comp;
+            for(i=0;i<len;i+=1){
+                comp = this.comp.threeDElements[i];
+                if(comp.type === '3d') {
+                    if(hasMatrixChanged) {
+                        comp.container.style.transform = comp.container.style.webkitTransform = this.mat.toCSS();
+                    }
+                    if(this.pe._mdf) {
+                        comp.perspectiveElem.style.perspective = comp.perspectiveElem.style.webkitPerspective = this.pe.v+'px';
+                    }
+                }
+            }
+            this.mat.clone(this._prevMat);
+        }*/
+    }
+    this._isFirstFrame = false;
+};
+
+WebGLCamera.prototype.prepareFrame = function(num) {
+    this.prepareProperties(num, true);
+};
+
+WebGLCamera.prototype.destroy = function(){
+};
+WebGLCamera.prototype.getBaseElement = function(){return null;};
\ No newline at end of file
diff --git a/player/js/elements/webglElements/WebGLEffects.js b/player/js/elements/webglElements/WebGLEffects.js
index e73ec13..e211539 100644
--- a/player/js/elements/webglElements/WebGLEffects.js
+++ b/player/js/elements/webglElements/WebGLEffects.js
@@ -5,6 +5,7 @@
     for(i=0;i<len;i+=1){
         filterManager = null;
         var effect = effectsRegisterer.getEffect(elem.data.ef[i].mn) || effectsRegisterer.getEffect(elem.data.ef[i].nm);
+
         if(effect) {
             filterManager = new effect(elem.effectsManager.effectElements[i], elem, WebGLProgramFactory);
             this.filters.push(filterManager);
diff --git a/player/js/elements/webglElements/WebGLImageElement.js b/player/js/elements/webglElements/WebGLImageElement.js
index f7c7c4b..2bc14c6 100644
--- a/player/js/elements/webglElements/WebGLImageElement.js
+++ b/player/js/elements/webglElements/WebGLImageElement.js
@@ -20,9 +20,6 @@
     glContext.enableVertexAttribArray(this.positionAttributeLocation);
     this.mat4UniformLoc = glContext.getUniformLocation(this.program, "uMatrix");
     this.localmat4UniformLoc = glContext.getUniformLocation(this.program, "localMatrix");
-    this.texcoordLocation = glContext.getAttribLocation(this.program, "a_texCoord");
-    glContext.enableVertexAttribArray(this.texcoordLocation);
-    glContext.vertexAttribPointer(this.texcoordLocation, 2, glContext.FLOAT, false, 0, 0);
 
     var localMatrix = new Matrix();
     localMatrix.scale(this.assetData.w, this.assetData.h);
diff --git a/player/js/elements/webglElements/effects/WebGLTintEffect.js b/player/js/elements/webglElements/effects/WebGLTintEffect.js
index 8866dcb..9eed347 100644
--- a/player/js/elements/webglElements/effects/WebGLTintEffect.js
+++ b/player/js/elements/webglElements/effects/WebGLTintEffect.js
@@ -1,38 +1,38 @@
-function WTintFilter(filterManager, elem){
-    var gl = elem.globalData.canvasContext;
+function WTintFilter(filterManager, elem, WebGLProgramFactory){
+    var glContext = elem.globalData.glContext;
     var vsh = get_shader('base_effect_shader_vert');
 
     var fsh = get_shader('tint_shader_frag');
 
-    var vertexShader = WebGLProgramFactory.createShader(gl, gl.VERTEX_SHADER, vsh);
-    var fragmentShader = WebGLProgramFactory.createShader(gl, gl.FRAGMENT_SHADER, fsh);
-    this.program = WebGLProgramFactory.createProgram(gl, vertexShader, fragmentShader);
+    var vertexShader = WebGLProgramFactory.createShader(glContext, glContext.VERTEX_SHADER, vsh);
+    var fragmentShader = WebGLProgramFactory.createShader(glContext, glContext.FRAGMENT_SHADER, fsh);
+    this.program = WebGLProgramFactory.createProgram(glContext, vertexShader, fragmentShader);
 
-    gl.useProgram(this.program);
-    this.positionAttributeLocation = gl.getAttribLocation(this.program, "a_position");
-    gl.enableVertexAttribArray(this.positionAttributeLocation);
-    gl.vertexAttribPointer(this.positionAttributeLocation, 2,gl.FLOAT, false, 0, 0);
+    glContext.useProgram(this.program);
+    this.positionAttributeLocation = glContext.getAttribLocation(this.program, "a_position");
+    glContext.enableVertexAttribArray(this.positionAttributeLocation);
+    glContext.vertexAttribPointer(this.positionAttributeLocation, 2,glContext.FLOAT, false, 0, 0);
 
 
-    this.blackToColorLoc = gl.getUniformLocation(this.program, "blackToColor");
-    this.whiteToColorLoc = gl.getUniformLocation(this.program, "whiteToColor");
-    this.amountLoc = gl.getUniformLocation(this.program, "color_amount");
-    gl.uniform1f(this.amountLoc, 0.5);
+    this.blackToColorLoc = glContext.getUniformLocation(this.program, "blackToColor");
+    this.whiteToColorLoc = glContext.getUniformLocation(this.program, "whiteToColor");
+    this.amountLoc = glContext.getUniformLocation(this.program, "color_amount");
+    glContext.uniform1f(this.amountLoc, 0.5);
 
 
     this.filterManager = filterManager;
-    this.gl = gl;
+    this.glContext = glContext;
     this.currentBlackColor = [-1,-1,-1,-1];
     this.currentWhiteColor = [-1,-1,-1,-1];
     this.currentAmount = -1;
 }
 
 WTintFilter.prototype.renderFrame = function(forceRender, buffer){
-    this.gl.useProgram(this.program);
+    this.glContext.useProgram(this.program);
     var col = this.filterManager.effectElements[0].p.v;
     var currCol = this.currentBlackColor;
     if(currCol[0] !== col[0] || currCol[1] !== col[1] || currCol[2] !== col[2]) {
-        this.gl.uniform4fv(this.blackToColorLoc, col);
+        this.glContext.uniform4fv(this.blackToColorLoc, col);
         currCol[0] = col[0];
         currCol[1] = col[1];
         currCol[2] = col[2];
@@ -40,16 +40,16 @@
     col = this.filterManager.effectElements[1].p.v;
     currCol = this.currentWhiteColor;
     if(currCol[0] !== col[0] || currCol[1] !== col[1] || currCol[2] !== col[2]) {
-        this.gl.uniform4fv(this.whiteToColorLoc, col);
+        this.glContext.uniform4fv(this.whiteToColorLoc, col);
         currCol[0] = col[0];
         currCol[1] = col[1];
         currCol[2] = col[2];
     }
     if(this.currentAmount !== this.filterManager.effectElements[2].p.v/100) {
-        this.gl.uniform1f(this.amountLoc, this.filterManager.effectElements[2].p.v/100);
+        this.glContext.uniform1f(this.amountLoc, this.filterManager.effectElements[2].p.v/100);
         this.currentAmount = this.filterManager.effectElements[2].p.v/100;
     }
-    this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
+    this.glContext.drawArrays(this.glContext.TRIANGLES, 0, 6);
          
     if(forceRender || this.filterManager._mdf){
     }
diff --git a/player/js/elements/webglElements/effects/WebGLTwirlEffect.js b/player/js/elements/webglElements/effects/WebGLTwirlEffect.js
index 4d8c46b..2b3bd3d 100644
--- a/player/js/elements/webglElements/effects/WebGLTwirlEffect.js
+++ b/player/js/elements/webglElements/effects/WebGLTwirlEffect.js
@@ -21,7 +21,6 @@
 }
 
 WTwirlEffect.prototype.renderFrame = function(forceRender, buffer){
-    console.log('TWI')
     var effectElements = this.filterManager.effectElements;
     this.glContext.useProgram(this.program);
     this.glContext.uniform1f(this.angleLocation, effectElements[0].p.v);
diff --git a/player/js/renderers/BaseRenderer.js b/player/js/renderers/BaseRenderer.js
index 17b6fb8..6148fe5 100644
--- a/player/js/renderers/BaseRenderer.js
+++ b/player/js/renderers/BaseRenderer.js
@@ -36,7 +36,7 @@
 };
 
 BaseRenderer.prototype.createCamera = function(){
-    throw new Error('You\'re using a 3d camera. Try the html renderer.');
+    throw new Error('You\'re using a 3d camera. Try the html or webgl renderer.');
 };
 
 BaseRenderer.prototype.buildAllItems = function(){
diff --git a/player/js/renderers/WebGLRenderer.js b/player/js/renderers/WebGLRenderer.js
index 78d5442..ac9f6e7 100644
--- a/player/js/renderers/WebGLRenderer.js
+++ b/player/js/renderers/WebGLRenderer.js
@@ -43,35 +43,36 @@
 
         // ////
         var _debug = false;
-        this.glContext = new Proxy(glc, {
+        if (_debug) {
 
-            get(target, propKey, receiver) {
-                if (typeof target[propKey] === 'function') {
-                    const origMethod = target[propKey];
-                    return function (...args) {
-                        const result = origMethod.apply(target, args);
-                        if (_debug) {
+            this.glContext = new Proxy(glc, {
+
+                get(target, propKey, receiver) {
+                    if (typeof target[propKey] === 'function') {
+                        const origMethod = target[propKey];
+                        return function (...args) {
+                            const result = origMethod.apply(target, args);
                             console.log('==========')
                             console.log(propKey)
-                        }
-                        // args.forEach(arg => {
-                        //     console.log(arg)
-                        // })
-                        // console.log('==========')
-                        // console.log(propKey + JSON.stringify(args)
-                        //     + ' -> ' + JSON.stringify(result));
-                        return result;
-                    };
-                } else {
-                    if (_debug) {
+                            // args.forEach(arg => {
+                            //     console.log(arg)
+                            // })
+                            // console.log('==========')
+                            // console.log(propKey + JSON.stringify(args)
+                            //     + ' -> ' + JSON.stringify(result));
+                            return result;
+                        };
+                    } else {
                         console.log('GETTING: ', propKey)
+                        return target[propKey]
                     }
-                    return target[propKey]
                 }
-            }
-          })
+            })
+        } else {
+            this.glContext = glc
+        }
 
-        // this.glContext = glc
+        // 
         ////
 
         // Enabled blend and sets blend func to handle opacity.
@@ -96,6 +97,10 @@
     this.layers = animData.layers;
     this.setupGlobalData(animData, document.body);
     this.globalData.glContext = this.glContext;
+    if (!this.camera) {
+        console.log('PASO 1')
+        this.camera = new WebGLCamera(null, this.globalData, this);
+    }
     
     // Position buffer data
     var glContext = this.glContext;
@@ -167,14 +172,17 @@
     	scaleX = (this.transformCanvas.w * this.transformCanvas.sx) / elementWidth;
     }
 
+    this.scaleX = scaleX;
+    this.scaleY = scaleY;
 
-    this.transformMat.reset();
-	this.transformMat.scale(scaleX, scaleY);
-	this.transformMat.scale(1 / this.data.w, 1 / this.data.h);
-	this.transformMat.scale(2, 2);
-	this.transformMat.translate(-1, -1);
-	this.transformMat.translate(1 - scaleX, 1 - scaleY);
-	this.transformMat.scale(1, -1);
+
+ //    this.transformMat.reset();
+	// this.transformMat.scale(scaleX, scaleY);
+	// this.transformMat.scale(1 / this.data.w, 1 / this.data.h, 1 / 1666);
+	// this.transformMat.scale(2, 2);
+	// this.transformMat.translate(-1, -1);
+	// this.transformMat.translate(1 - scaleX, 1 - scaleY);
+	// this.transformMat.scale(1, -1);
     this.resetViewport();
 };
 
@@ -213,6 +221,11 @@
     return new WShapeElement(data,this.globalData,this);
 };
 
+WebGLRenderer.prototype.createCamera = function (data) {
+    this.camera = new WebGLCamera(data, this.globalData, this);
+    return this.camera;
+};
+
 WebGLRenderer.prototype.checkPendingElements  = function(){
     while(this.pendingElements.length){
         var element = this.pendingElements.pop();
@@ -224,6 +237,28 @@
     return this.transformCanvas;
 }
 
+WebGLRenderer.prototype.applyCameraTransformation = function(){
+    this.transformMat.reset();
+    this.transformMat.scale(this.scaleX, this.scaleY);
+    var p = this.camera.mat.props;
+    console.log(p)
+    this.transformMat.transform(p[0], p[1], p[2], p[3]
+        ,p[4], p[5], p[6], p[7]
+        ,p[8], p[9], p[10], p[11]
+        ,p[12], p[13], p[14], p[15]);
+
+    // convert values to range [0, 1]
+    this.transformMat.scale(1 / this.data.w, 1 / this.data.h, 1);
+    // convert values to range [0, 2]
+    this.transformMat.scale(2, 2);
+    // convert values to range [-1, 1]
+    this.transformMat.translate(-1, -1);
+    // convert values to fit inside actual canvas
+    this.transformMat.translate(1 - this.scaleX, 1 - this.scaleY);
+    // invert Y axis
+    this.transformMat.scale(1, -1);
+}
+
 WebGLRenderer.prototype.renderFrame = function(num){
     if((this.renderedFrame == num && this.renderConfig.clearCanvas === true) || this.destroyed || num === -1){
         return;
@@ -241,6 +276,7 @@
         this.checkLayers(num);
     }
 
+    this.camera.prepareFrame(num);
     for (i = 0; i < len; i++) {
         if(this.completeLayers || this.elements[i]){
             this.elements[i].prepareFrame(num - this.layers[i].st);
@@ -250,6 +286,9 @@
 		this.glContext.clearColor(0, 0, 0, 0);
 		this.glContext.clear(this.glContext.COLOR_BUFFER_BIT | this.glContext.DEPTH_BUFFER_BIT);
 
+        this.camera.renderFrame();
+        this.applyCameraTransformation();
+
         // TODO: Look into rendering track mattes first
         for (i = len - 1; i >= 0; i-=1) {
             if(!this.elements[i].data.td) {
diff --git a/player/js/utils/webgl/shader_provider.js b/player/js/utils/webgl/shader_provider.js
index bcff5e9..c03fbf6 100644
--- a/player/js/utils/webgl/shader_provider.js
+++ b/player/js/utils/webgl/shader_provider.js
@@ -7,7 +7,7 @@
 shaders["gaussian_blur_shader_frag"] = "// gaussian_blur_shader.frag\nprecision mediump float;\nuniform sampler2D u_image;\nuniform float weights[100];\nuniform int blurriness;\nvarying vec2 vUv;\n\nvec4 calculateColorSum(vec2 onePixel) {\n	// vec4 colorSum = vec4(0.0, 0.0, 0.0, 1.0);\n	vec4 colorSum = vec4(0.0, 0.0, 0.0, 1.0);\n	// vec4 colorSum = texture2D(u_image, vUv);\n	for(int i = 0; i < 50; i += 1) {\n		if(i >= blurriness / 2) {\n			return colorSum;\n		}\n		colorSum += texture2D(u_image, vUv + onePixel * vec2(-1 * ((blurriness / 2) - i), 0)) * weights[i];\n		colorSum += texture2D(u_image, vUv + onePixel * vec2(1 * ((blurriness / 2) - i), 0)) * weights[i];\n\n		// colorSum += vec4(0.0, 1.0, 0.0, 1.0) * weights[i];\n		// colorSum += vec4(0.0, 1.0, 0.0, 1.0) * weights[i];\n		// colorSum += texture2D(u_image, vUv) * weights[i];\n		// colorSum += texture2D(u_image, vUv + onePixel * vec2(1 * ((blurriness / 2) - i), 0)) * weights[i];\n		/* vec4 texturePoint = texture2D(u_image, vUv);\n		if(texturePoint.r == 1.0) {\n			colorSum = vec4(0.0, 0.0, 1.0, 1.0);\n		} */\n	}\n	return colorSum;\n}\n\nvoid main() {\n	vec2 u_textureSize = vec2(1200.0 * 2.5, 600.0 * 2.5);\n	vec2 onePixel = vec2(1.0, 0.0) / u_textureSize;\n	gl_FragColor = calculateColorSum(onePixel);\n	// gl_FragColor = texture2D(u_image, vUv);\n}";
 shaders["gaussian_blur_shader_vert"] = "// gaussian_blur_shader.vert\nattribute vec4 a_position;\nattribute vec2 a_texCoord;\nvarying vec2 v_texCoord;\nvarying vec2 vUv;\nvoid main() {\n	vec4 zeroToOne = a_position / 1.0;\n	vec4 zeroToTwo = zeroToOne * 2.0;\n	vec4 clipSpace = zeroToTwo - 1.0;\n	gl_Position = vec4(clipSpace);\n	vUv = a_texCoord;\n}";
 shaders["image_layer_shader_frag"] = "// image_layer_shader.frag\nprecision mediump float;\nuniform sampler2D u_image;\nvarying vec2 v_texCoord;\nvoid main() {\n	gl_FragColor = texture2D(u_image, v_texCoord);\n}";
-shaders["image_layer_shader_vert"] = "// image_layer_shader.vert\nattribute vec4 a_position;\nuniform mat4 uMatrix;\nuniform mat4 localMatrix;\nvarying vec2 v_texCoord;\nattribute vec2 a_texCoord;\nvoid main() {\n	gl_Position = uMatrix * localMatrix * a_position;\n	v_texCoord = a_texCoord;\n}";
+shaders["image_layer_shader_vert"] = "// image_layer_shader.vert\nattribute vec3 a_position;\nuniform mat4 uMatrix;\nuniform mat4 localMatrix;\nvarying vec2 v_texCoord;\nvoid main() {\n	gl_Position = uMatrix * localMatrix * vec4(a_position, 1);\n	v_texCoord = a_position.xy;\n}";
 shaders["mask_shader_frag"] = "// mask_shader.frag\nprecision mediump float;\nuniform sampler2D original_image;\nuniform sampler2D mask_image;\nvarying vec2 v_texCoord;\nvoid main() {\n	vec4 original_color = texture2D(original_image, v_texCoord);\n	vec4 mask_color = texture2D(mask_image, v_texCoord);\n	gl_FragColor = vec4(original_color.rgb, mask_color.a * original_color.a);\n}";
 shaders["mask_shader_vert"] = "// mask_shader.vert\nattribute vec4 a_position;\nvarying vec2 v_texCoord;\nattribute vec2 a_texCoord;\nvoid main() {\n	vec4 zeroToOne = a_position / 1.0;\n	vec4 zeroToTwo = zeroToOne * 2.0;\n	vec4 clipSpace = zeroToTwo - 1.0;\n	gl_Position = vec4(clipSpace);\n	v_texCoord = a_texCoord;\n}";
 shaders["noop_effect_shader_frag"] = "// noop_effect_shader.frag\nprecision mediump float;\nvoid main() {\n	gl_FragColor = vec4(1.0,1.0,0.0,1.0);\n}";
diff --git a/player/js/utils/webgl/shaders/image_layer_shader.vert b/player/js/utils/webgl/shaders/image_layer_shader.vert
index 21cbfc7..eadb2f2 100644
--- a/player/js/utils/webgl/shaders/image_layer_shader.vert
+++ b/player/js/utils/webgl/shaders/image_layer_shader.vert
@@ -1,9 +1,8 @@
-attribute vec4 a_position;
+attribute vec3 a_position;
 uniform mat4 uMatrix;
 uniform mat4 localMatrix;
 varying vec2 v_texCoord;
-attribute vec2 a_texCoord;
 void main() {
-	gl_Position = uMatrix * localMatrix * a_position;
-	v_texCoord = a_texCoord;
+	gl_Position = uMatrix * localMatrix * vec4(a_position, 1);
+	v_texCoord = a_position.xy;
 }
\ No newline at end of file
diff --git a/tasks/shaders_task.js b/tasks/shaders_task.js
index 3046933..a4408fb 100644
--- a/tasks/shaders_task.js
+++ b/tasks/shaders_task.js
@@ -39,34 +39,34 @@
 
 
 
-fs.watch(templates_folder, (eventType, filename) => {
-	var shaders_string = 'var shaders = {}\n'
-	fs.readdir(templates_folder, (err, files) => {
-	  files.forEach(file => {
-	  	if(!file.match(/\.vert$/) && !file.match(/\.frag$/)) {
-        // Only process .vert and .frag files
-        return;
-      }
-	  	if(file.indexOf('.bkp') === -1) {
-		  	var file_content = fs.readFileSync(watching_folder + '/' + file, 'utf8');
-		  	shaders_string += 'shaders["' + file.replace(/\./g,'_') + '"] = "';
-        if (add_shader_name) {
-          shaders_string += '// ' + file + '\\n';
-        }
-        if (strip_comments) {
-          file_content = file_content.replace(/\/\/.*/g, '');
-        }
-        var line_separator = join_lines ? '' : '\\n';
-		  	shaders_string += file_content.replace(/\r\n/g, line_separator).replace(/\n/g, line_separator) + '";\n';
-	  	}
-	  })
-	shaders_string += 'function get_shader(name) {\n'
-	shaders_string += 'return shaders[name];\n';
-	shaders_string += '}\n';
-	fs.writeFile("player/js/utils/webgl/template_shader_provider.js", shaders_string, function(err) {
-	    if(err) {
-	        return console.log(err);
-	    }
-	}); 
-	})
-})
\ No newline at end of file
+// fs.watch(templates_folder, (eventType, filename) => {
+// 	var shaders_string = 'var shaders = {}\n'
+// 	fs.readdir(templates_folder, (err, files) => {
+// 	  files.forEach(file => {
+// 	  	if(!file.match(/\.vert$/) && !file.match(/\.frag$/)) {
+//         // Only process .vert and .frag files
+//         return;
+//       }
+// 	  	if(file.indexOf('.bkp') === -1) {
+// 		  	var file_content = fs.readFileSync(watching_folder + '/' + file, 'utf8');
+// 		  	shaders_string += 'shaders["' + file.replace(/\./g,'_') + '"] = "';
+//         if (add_shader_name) {
+//           shaders_string += '// ' + file + '\\n';
+//         }
+//         if (strip_comments) {
+//           file_content = file_content.replace(/\/\/.*/g, '');
+//         }
+//         var line_separator = join_lines ? '' : '\\n';
+// 		  	shaders_string += file_content.replace(/\r\n/g, line_separator).replace(/\n/g, line_separator) + '";\n';
+// 	  	}
+// 	  })
+// 	shaders_string += 'function get_shader(name) {\n'
+// 	shaders_string += 'return shaders[name];\n';
+// 	shaders_string += '}\n';
+// 	fs.writeFile("player/js/utils/webgl/template_shader_provider.js", shaders_string, function(err) {
+// 	    if(err) {
+// 	        return console.log(err);
+// 	    }
+// 	}); 
+// 	})
+// })
\ No newline at end of file