constructor(renderer, type = "Mesh", {
        // program
        vertexShaderID,
        fragmentShaderID,
        vertexShader,
        fragmentShader,
        uniforms = {},

        // geometry
        widthSegments = 1,
        heightSegments = 1,

        // render order
        renderOrder = 0,

        // drawing
        depthTest = true,
        cullFace = "back",

        // textures
        texturesOptions = {},
        crossOrigin = "anonymous"
    } = {}) {
        this.type = type;

        // we could pass our curtains object OR our curtains renderer object
        renderer = renderer && renderer.renderer || renderer;

        if(!renderer || renderer.type !== "Renderer") {
            throwError(this.type + ": Curtains not passed as first argument or Curtains Renderer is missing", renderer);
            // no renderer, we can't use the renderer nextRender method
            setTimeout(() => {
                if(this._onErrorCallback) {
                    this._onErrorCallback();
                }
            }, 0);
        }
        this.renderer = renderer;
        this.gl = this.renderer.gl;

        if(!this.gl) {
            if(!this.renderer.production) throwError(this.type + ": Unable to create a " + this.type + " because the Renderer WebGL context is not defined");

            // we should assume there's still no renderer here, so no nextRender method
            setTimeout(() => {
                if(this._onErrorCallback) {
                    this._onErrorCallback();
                }
            }, 0);

            // return if no gl context
            return;
        }

        this._canDraw = false;
        this.renderOrder = renderOrder;

        // depth test
        this._depthTest = depthTest;
        // face culling
        this.cullFace = cullFace;
        if(
            this.cullFace !== "back"
            && this.cullFace !== "front"
            && this.cullFace !== "none"
        ) {
            this.cullFace = "back";
        }

        // textures
        this.textures = [];
        // default textures options depends on the type of Mesh and WebGL context

        this._texturesOptions = Object.assign({
            premultiplyAlpha: false,
            anisotropy: 1,

            floatingPoint: "none", // accepts "none", "half-float" or "float"

            wrapS: this.gl.CLAMP_TO_EDGE,
            wrapT: this.gl.CLAMP_TO_EDGE,

            minFilter: this.gl.LINEAR,
            magFilter: this.gl.LINEAR,
        }, texturesOptions);

        this.crossOrigin = crossOrigin;

        // handling shaders
        if(!vertexShader && vertexShaderID && document.getElementById(vertexShaderID)) {
            vertexShader = document.getElementById(vertexShaderID).innerHTML;
        }

        if(!fragmentShader && fragmentShaderID && document.getElementById(fragmentShaderID)) {
            fragmentShader = document.getElementById(fragmentShaderID).innerHTML;
        }

        // init sizes and loader
        this._initMesh();

        // geometry
        // set plane attributes
        widthSegments = parseInt(widthSegments);
        heightSegments = parseInt(heightSegments);
        this._geometry = new Geometry(this.renderer, {
            width: widthSegments,
            height: heightSegments,
            // using a special ID for shader passes to avoid weird buffer binding bugs on mac devices
            //id: this.type === "ShaderPass" ? 1 : widthSegments * heightSegments + widthSegments
        });

        this._program = new Program(this.renderer, {
            parent: this,
            vertexShader: vertexShader,
            fragmentShader: fragmentShader,
        });

        if(this._program.compiled) {
            // create and set program uniforms
            this._program.createUniforms(uniforms);

            // make uniforms accessible directly
            this.uniforms = this._program.uniformsManager.uniforms;

            // geometry
            // set plane attributes
            this._geometry.setProgram(this._program);

            // we've added a new object, keep Curtains class in sync with our renderer
            this.renderer.onSceneChange();
        }
        else {
            this.renderer.nextRender.add(() => this._onErrorCallback && this._onErrorCallback());
        }
    }
Here we create our Mesh object
 We will create an object containing the program that handles shaders and uniforms, a geometry that handles attributes
 Also handles anything that relates to textures creation and basic drawing operations

 params:
 @renderer (Curtains renderer or Renderer class object): our curtains object OR our curtains renderer object
 @type (string): Object type (should be either "Plane" or "ShaderPass")

 @vertexShaderID (string, optional): the vertex shader script ID. If not specified, will look for a data attribute data-vs-id on the plane HTML element.
 @fragmentShaderID (string, optional): the fragment shader script ID. If not specified, will look for a data attribute data-fs-id on the plane HTML element.
 @vertexShader (string, optional): the vertex shader as a string. Will look for a vertexShaderID if not specified.
 @fragmentShader (string, optional): the fragment shader as a string. Will look for a fragmentShaderID if not specified.
 @uniforms (object, optional): the uniforms that will be passed to the shaders.
 @widthSegments (int, optional): mesh definition along the X axis (1 by default)
 @heightSegments (int, optional): mesh definition along the Y axis (1 by default)
 @renderOrder (int, optional): mesh render order in the scene draw stacks (0 by default)
 @depthTest (bool, optional): if the mesh should enable or disable the depth test. Default to true.
 @cullFace (string, optional): which face of the mesh should be culled. Could either be "back", "front" or "none". Default to "back".
 @texturesOptions (object, optional): options and parameters to apply to the textures loaded by the mesh's loader. See the Texture class object.
 @crossorigin (string, optional): defines the crossOrigin process to load images if any (default to "anonymous").

 returns:
 @this: our Mesh element
*