function Mesh(renderer) {
      var _this23 = this;

      var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : "Mesh";

      var _ref8 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {},
          vertexShaderID = _ref8.vertexShaderID,
          fragmentShaderID = _ref8.fragmentShaderID,
          vertexShader = _ref8.vertexShader,
          fragmentShader = _ref8.fragmentShader,
          _ref8$uniforms = _ref8.uniforms,
          uniforms = _ref8$uniforms === void 0 ? {} : _ref8$uniforms,
          _ref8$widthSegments = _ref8.widthSegments,
          widthSegments = _ref8$widthSegments === void 0 ? 1 : _ref8$widthSegments,
          _ref8$heightSegments = _ref8.heightSegments,
          heightSegments = _ref8$heightSegments === void 0 ? 1 : _ref8$heightSegments,
          _ref8$renderOrder = _ref8.renderOrder,
          renderOrder = _ref8$renderOrder === void 0 ? 0 : _ref8$renderOrder,
          _ref8$depthTest = _ref8.depthTest,
          depthTest = _ref8$depthTest === void 0 ? true : _ref8$depthTest,
          _ref8$cullFace = _ref8.cullFace,
          cullFace = _ref8$cullFace === void 0 ? "back" : _ref8$cullFace,
          _ref8$texturesOptions = _ref8.texturesOptions,
          texturesOptions = _ref8$texturesOptions === void 0 ? {} : _ref8$texturesOptions,
          _ref8$crossOrigin = _ref8.crossOrigin,
          crossOrigin = _ref8$crossOrigin === void 0 ? "anonymous" : _ref8$crossOrigin;

      _classCallCheck(this, Mesh);

      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(function () {
          if (_this23._onErrorCallback) {
            _this23._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(function () {
          if (_this23._onErrorCallback) {
            _this23._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(function () {
          return _this23._onErrorCallback && _this23._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
*