├── LICENSE ├── README.md ├── index.html └── leaflet-tilelayer-glue.js /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Yuzo Matsuzawa 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # leaflet-tilelayer-glue 2 | Yet another implementation of leaflet-tilelayer-gl, WebGL shaders are applied to combined tiles 3 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | leaflet-tilelayer-glue 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 129 | 130 | 131 | 132 | -------------------------------------------------------------------------------- /leaflet-tilelayer-glue.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | var defaultVertexShader = (function() { 4 | /* 5 | attribute vec2 clip; 6 | void main() { 7 | gl_Position = vec4(clip,0,1); 8 | } 9 | */ 10 | }).toString().split("/*")[1].split("*/")[0]; 11 | 12 | var defaultfragmentShader = (function() { 13 | /* 14 | precision mediump float; 15 | uniform sampler2D image; 16 | uniform vec2 unit; 17 | uniform vec4 argv; 18 | uniform float zoom; 19 | void main() { 20 | vec2 p = vec2(gl_FragCoord.x,1.0 / unit.y - gl_FragCoord.y); 21 | gl_FragColor = texture2D(image,p * unit); 22 | } 23 | */ 24 | }).toString().split("/*")[1].split("*/")[0]; 25 | 26 | 27 | L.TileLayer.GLUE = L.TileLayer.extend({ 28 | options: { 29 | crossOrigin: true, 30 | vertexShader: defaultVertexShader, 31 | fragmentShader: defaultfragmentShader, 32 | errorTileColor: "#7f0000", 33 | argv: [0, 0, 0, 0] 34 | }, 35 | _initContainer: function() { 36 | L.TileLayer.prototype._initContainer.call(this); 37 | 38 | var canvas = this._canvas = document.createElement('canvas'); 39 | canvas.style.zIndex = 10000; 40 | canvas.style.position = "absolute"; 41 | 42 | var gl = this._gl = canvas.getContext('webgl', null) || canvas.getContext('experimental-webgl'); 43 | var vs = gl.createShader(gl.VERTEX_SHADER); 44 | gl.shaderSource(vs, this.options.vertexShader); 45 | gl.compileShader(vs); 46 | var fs = gl.createShader(gl.FRAGMENT_SHADER); 47 | gl.shaderSource(fs, this.options.fragmentShader); 48 | gl.compileShader(fs); 49 | var pg = this._pg = gl.createProgram(); 50 | gl.attachShader(pg, vs); 51 | gl.attachShader(pg, fs); 52 | gl.linkProgram(pg); 53 | if (gl.getProgramParameter(pg, gl.LINK_STATUS)) { 54 | gl.useProgram(pg); 55 | } else { 56 | console.log(gl.getProgramInfoLog(pg)); 57 | return; 58 | } 59 | 60 | this._map.on("moveend", function() { 61 | this.repaint(false); 62 | }, this); 63 | 64 | this.on("tileload", function(event) { 65 | event.tile.style.display = "none"; 66 | }); 67 | this.on("tileload load loading", function(event) { 68 | this.repaint(false); 69 | }, this); 70 | }, 71 | 72 | repaint: function(immediate) { 73 | L.Util.requestAnimFrame(this._doPaint, this, immediate); 74 | }, 75 | _doPaint: function() { 76 | 77 | if (!this._map) return; 78 | 79 | var center = this._map.getCenter(); 80 | var pixelBounds = this._getTiledPixelBounds(center); 81 | var tileRange = this._pxBoundsToTileRange(pixelBounds); 82 | var size = tileRange.getSize().add([1, 1]).scaleBy(this.getTileSize()); 83 | var canvas = this._canvas; 84 | var shadow = document.createElement("canvas"); 85 | canvas.width = shadow.width = size.x; 86 | canvas.height = shadow.height = size.y; 87 | canvas.style.width = size.x + "px"; 88 | canvas.style.height = size.y + "px"; 89 | this._level.el.appendChild(canvas); 90 | var context = shadow.getContext("2d"); 91 | context.fillStyle = this.options.errorTileColor; 92 | context.fillRect(0, 0, size.x, size.y); 93 | var origin = this._getTilePos(tileRange.min); 94 | for (var key in this._tiles) { 95 | var tile = this._tiles[key]; 96 | if (tile.current) { 97 | var pos = this._getTilePos(tile.coords).subtract(origin); 98 | try { 99 | context.drawImage(tile.el, pos.x, pos.y); 100 | } catch (ex) {} 101 | } 102 | } 103 | L.DomUtil.setPosition(canvas, origin); 104 | 105 | var image = shadow; 106 | var gl = this._gl; 107 | var program = this._pg; 108 | 109 | var w = image.width; 110 | var h = image.height; 111 | var clipLocation = gl.getAttribLocation(program, "clip"); 112 | var unitLocation = gl.getUniformLocation(program, "unit"); 113 | var zoomLocation = gl.getUniformLocation(program, "zoom"); 114 | var argvLocation = gl.getUniformLocation(program, "argv"); 115 | 116 | var clipBuffer = gl.createBuffer(); 117 | gl.bindBuffer(gl.ARRAY_BUFFER, clipBuffer); 118 | gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW); 119 | 120 | // Create a texture. 121 | var texture = gl.createTexture(); 122 | gl.bindTexture(gl.TEXTURE_2D, texture); 123 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); 124 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); 125 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); 126 | gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); 127 | gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image); 128 | 129 | gl.viewport(0, 0, w, h); 130 | gl.enableVertexAttribArray(clipLocation); 131 | gl.bindBuffer(gl.ARRAY_BUFFER, clipBuffer); 132 | gl.vertexAttribPointer(clipLocation, 2, gl.FLOAT, false, 0, 0); 133 | gl.uniform2f(unitLocation, 1 / w, 1 / h); 134 | gl.uniform1f(zoomLocation, this._tileZoom); 135 | 136 | var argv = this.options.argv; 137 | gl.uniform4f(argvLocation, argv[0], argv[1], argv[2], argv[3]); 138 | gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4); 139 | } 140 | }); 141 | 142 | L.tileLayer.glue = function(url, options) { 143 | return new L.TileLayer.GLUE(url, options); 144 | }; 145 | 146 | })(); 147 | --------------------------------------------------------------------------------