updateUniforms() {
        if(this.uniforms) {
            for(const key in this.uniforms) {
                const uniform = this.uniforms[key];
                let shouldUpdate = false;

                if(uniform._internalFormat === "Vec2") {
                    if(!uniform.value.equals(uniform.lastValue)) {
                        shouldUpdate = true;
                        uniform.lastValue.copy(uniform.value);
                    }
                }
                else if(uniform._internalFormat === "Vec3") {
                    if(!uniform.value.equals(uniform.lastValue)) {
                        shouldUpdate = true;
                        uniform.lastValue.copy(uniform.value);
                    }
                }
                else if(uniform._internalFormat === "Quat") {
                    if(!uniform.value.equals(uniform.lastValue)) {
                        shouldUpdate = true;
                        uniform.lastValue.copy(uniform.value);
                    }
                }
                else if(!uniform.value.length) {
                    if(uniform.value !== uniform.lastValue) {
                        shouldUpdate = true;
                        uniform.lastValue = uniform.value;
                    }
                }
                else if(JSON.stringify(uniform.value) !== JSON.stringify(uniform.lastValue)) { // compare two arrays
                    shouldUpdate = true;
                    // copy array
                    uniform.lastValue = Array.from(uniform.value);
                }

                if(shouldUpdate) {
                    // update our uniforms
                    uniform.update && uniform.update(uniform);
                }
            }
        }
    }
This updates all uniforms of an object that were set by the user
     It is called at each draw call
*