_draw() {
        // enable/disable depth test
        this.renderer.setDepthTest(this._depthTest);

        // face culling
        this.renderer.setFaceCulling(this.cullFace);

        // update all uniforms set up by the user
        this._program.updateUniforms();

        // bind plane attributes buffers
        // TODO ideally we should only bind the attributes buffers if the geometry changed
        // however it is leading to some bugs on macOS & iOS and should therefore be tested extensively
        // for now we'll disable this feature even tho it is ready to be used
        //if(this.renderer.state.currentGeometryID !== this._geometry.definition.id || this.renderer.state.forceBufferUpdate) {
        this._geometry.bindBuffers();
        this.renderer.state.forceBufferUpdate = false;
        //}

        // draw all our plane textures
        for(let i = 0; i < this.textures.length; i++) {
            // draw (bind and maybe update) our texture
            this.textures[i]._draw();

            // do not draw mesh if one of the active texture is not bound yet
            if(this.textures[i]._sampler.isActive && !this.textures[i]._sampler.isTextureBound) {
                return;
            }
        }

        // the draw call!
        this._geometry.draw();

        // reset active texture
        this.renderer.state.activeTexture = null;

        // callback after draw
        this._onAfterRenderCallback && this._onAfterRenderCallback();
    }
We draw the plane, ie bind the buffers, set the active textures and draw it
*