From 282a12cfcc38784e6947e686ed782383f7930480 Mon Sep 17 00:00:00 2001 From: Ansis Brammanis Date: Thu, 28 Jan 2016 15:04:04 -0800 Subject: [PATCH] simplify conversion from pixels to tile units adds tile.pixelsToTileUnits(pixelValue, zoom) and removes tile.pixelRatio --- js/render/draw_fill.js | 28 ++++++++++++++-------------- js/render/draw_line.js | 27 ++++++++++++++++----------- js/render/draw_symbol.js | 2 +- js/render/painter.js | 5 ++--- js/source/tile.js | 19 ++++++++++++++++++- test/js/source/tile_pyramid.test.js | 6 ++---- 6 files changed, 53 insertions(+), 34 deletions(-) diff --git a/js/render/draw_fill.js b/js/render/draw_fill.js index 2d17cda1131..991e2655253 100644 --- a/js/render/draw_fill.js +++ b/js/render/draw_fill.js @@ -136,33 +136,33 @@ function drawFill(painter, source, layer, coord) { gl.uniform1f(shader.u_opacity, opacity); gl.uniform1f(shader.u_mix, image.t); - var scale = Math.pow(2, painter.transform.tileZoom - tile.coord.z); - var imageSizeScaledA = [ - (imagePosA.size[0] * image.fromScale) / scale, - (imagePosA.size[1] * image.fromScale) / scale + (imagePosA.size[0] * image.fromScale), + (imagePosA.size[1] * image.fromScale) ]; var imageSizeScaledB = [ - (imagePosB.size[0] * image.toScale) / scale, - (imagePosB.size[1] * image.toScale) / scale + (imagePosB.size[0] * image.toScale), + (imagePosB.size[1] * image.toScale) ]; gl.uniform2fv(shader.u_patternscale_a, [ - 1 / (imageSizeScaledA[0] * tile.pixelRatio), - 1 / (imageSizeScaledA[1] * tile.pixelRatio) + 1 / tile.pixelsToTileUnits(imageSizeScaledA[0], painter.transform.tileZoom), + 1 / tile.pixelsToTileUnits(imageSizeScaledA[1], painter.transform.tileZoom) ]); gl.uniform2fv(shader.u_patternscale_b, [ - 1 / (imageSizeScaledB[0] * tile.pixelRatio), - 1 / (imageSizeScaledB[1] * tile.pixelRatio) + 1 / tile.pixelsToTileUnits(imageSizeScaledB[0], painter.transform.tileZoom), + 1 / tile.pixelsToTileUnits(imageSizeScaledB[1], painter.transform.tileZoom) ]); + var tileSizeAtNearestZoom = tile.tileSize * Math.pow(2, painter.transform.tileZoom - tile.coord.z); + // shift images to match at tile boundaries - var offsetAx = ((tile.tileSize % imageSizeScaledA[0]) * (tile.coord.x + coord.w * Math.pow(2, tile.coord.z))) / imageSizeScaledA[0]; - var offsetAy = ((tile.tileSize % imageSizeScaledA[1]) * tile.coord.y) / imageSizeScaledA[1]; + var offsetAx = ((tileSizeAtNearestZoom / imageSizeScaledA[0]) % 1) * (tile.coord.x + coord.w * Math.pow(2, tile.coord.z)); + var offsetAy = ((tileSizeAtNearestZoom / imageSizeScaledA[1]) % 1) * tile.coord.y; - var offsetBx = ((tile.tileSize % imageSizeScaledB[0]) * (tile.coord.x + coord.w * Math.pow(2, tile.coord.z))) / imageSizeScaledB[0]; - var offsetBy = ((tile.tileSize % imageSizeScaledB[1]) * tile.coord.y) / imageSizeScaledB[1]; + var offsetBx = ((tileSizeAtNearestZoom / imageSizeScaledB[0]) % 1) * (tile.coord.x + coord.w * Math.pow(2, tile.coord.z)); + var offsetBy = ((tileSizeAtNearestZoom / imageSizeScaledB[1]) % 1) * tile.coord.y; gl.uniform2fv(shader.u_offset_a, [offsetAx, offsetAy]); gl.uniform2fv(shader.u_offset_b, [offsetBx, offsetBy]); diff --git a/js/render/draw_line.js b/js/render/draw_line.js index 31d28f846ba..2970dbe093f 100644 --- a/js/render/draw_line.js +++ b/js/render/draw_line.js @@ -136,25 +136,30 @@ module.exports = function drawLine(painter, source, layer, coords) { gl.setPosMatrix(posMatrix); gl.setExMatrix(painter.transform.exMatrix); - var ratio = painter.transform.scale / (1 << coord.z) / tile.pixelRatio; - + var zoom = painter.transform.zoom; + var ratio = 1 / tile.pixelsToTileUnits(1, zoom); if (dasharray) { - var patternratio = Math.pow(2, Math.floor(Math.log(painter.transform.scale) / Math.LN2) - coord.z) / tile.pixelRatio; - var scaleA = [patternratio / posA.width / dasharray.fromScale, -posA.height / 2]; - var gammaA = painter.lineAtlas.width / (dasharray.fromScale * posA.width * 256 * browser.devicePixelRatio) / 2; - var scaleB = [patternratio / posB.width / dasharray.toScale, -posB.height / 2]; - var gammaB = painter.lineAtlas.width / (dasharray.toScale * posB.width * 256 * browser.devicePixelRatio) / 2; + var widthA = posA.width * dasharray.fromScale; + var widthB = posB.width * dasharray.toScale; + var scaleA = [1 / tile.pixelsToTileUnits(widthA, zoom), -posA.height / 2]; + var scaleB = [1 / tile.pixelsToTileUnits(widthB, zoom), -posB.height / 2]; + var gamma = painter.lineAtlas.width / (Math.min(widthA, widthB) * 256 * browser.devicePixelRatio) / 2; gl.uniform1f(shader.u_ratio, ratio); gl.uniform2fv(shader.u_patternscale_a, scaleA); gl.uniform2fv(shader.u_patternscale_b, scaleB); - gl.uniform1f(shader.u_sdfgamma, Math.max(gammaA, gammaB)); + gl.uniform1f(shader.u_sdfgamma, gamma); } else if (image) { - var factor = tile.pixelRatio / Math.pow(2, painter.transform.tileZoom - coord.z); gl.uniform1f(shader.u_ratio, ratio); - gl.uniform2fv(shader.u_pattern_size_a, [imagePosA.size[0] * factor * image.fromScale, imagePosB.size[1] ]); - gl.uniform2fv(shader.u_pattern_size_b, [imagePosB.size[0] * factor * image.toScale, imagePosB.size[1] ]); + gl.uniform2fv(shader.u_pattern_size_a, [ + tile.pixelsToTileUnits(imagePosA.size[0] * image.fromScale, painter.transform.tileZoom), + imagePosB.size[1] + ]); + gl.uniform2fv(shader.u_pattern_size_b, [ + tile.pixelsToTileUnits(imagePosB.size[0] * image.toScale, painter.transform.tileZoom), + imagePosB.size[1] + ]); } else { gl.uniform1f(shader.u_ratio, ratio); diff --git a/js/render/draw_symbol.js b/js/render/draw_symbol.js index 660d6b0c55c..08ca4f6d715 100644 --- a/js/render/draw_symbol.js +++ b/js/render/draw_symbol.js @@ -86,7 +86,7 @@ function drawSymbol(painter, layer, posMatrix, tile, elementGroups, prefix, sdf, if (skewed) { exMatrix = mat4.create(); - s = tile.pixelRatio / Math.pow(2, painter.transform.zoom - tile.coord.z); + s = tile.pixelsToTileUnits(1, painter.transform.zoom); gammaScale = 1 / Math.cos(tr._pitch); } else { exMatrix = mat4.clone(painter.transform.exMatrix); diff --git a/js/render/painter.js b/js/render/painter.js index 2bcca09a0c0..30059eb9964 100644 --- a/js/render/painter.js +++ b/js/render/painter.js @@ -350,10 +350,9 @@ Painter.prototype.translatePosMatrix = function(matrix, tile, translate, anchor) ]; } - var ratio = this.transform.scale / (1 << tile.coord.z) / tile.pixelRatio; var translation = [ - translate[0] / ratio, - translate[1] / ratio, + tile.pixelsToTileUnits(translate[0], this.transform.zoom), + tile.pixelsToTileUnits(translate[1], this.transform.zoom), 0 ]; diff --git a/js/source/tile.js b/js/source/tile.js index 20920cab1cd..0b8b091886f 100644 --- a/js/source/tile.js +++ b/js/source/tile.js @@ -21,11 +21,28 @@ function Tile(coord, size, sourceMaxZoom) { this.uses = 0; this.tileSize = size; this.sourceMaxZoom = sourceMaxZoom; - this.pixelRatio = EXTENT / size; } Tile.prototype = { + /** + * Converts a pixel value at a the given zoom level to tile units. + * + * The shaders mostly calculate everything in tile units so style + * properties need to be converted from pixels to tile units using this. + * + * For example, a translation by 30 pixels at zoom 6.5 will be a + * translation by pixelsToTileUnits(30, 6.5) tile units. + * + * @param {number} pixelValue + * @param {number} z + * @returns {number} value in tile units + * @private + */ + pixelsToTileUnits: function(pixelValue, z) { + return pixelValue * (EXTENT / (this.tileSize * Math.pow(2, z - this.coord.z))); + }, + /** * Given a coordinate position, zoom that coordinate to my zoom and * scale and return a position in x, y, scale diff --git a/test/js/source/tile_pyramid.test.js b/test/js/source/tile_pyramid.test.js index 85574e17552..6cdb5c6f2fd 100644 --- a/test/js/source/tile_pyramid.test.js +++ b/test/js/source/tile_pyramid.test.js @@ -513,8 +513,7 @@ test('TilePyramid#tilesIn', function (t) { loaded: true, uses: 1, tileSize: 512, - sourceMaxZoom: 14, - pixelRatio: 16 + sourceMaxZoom: 14 }, minX: 4096, maxX: 12288, @@ -527,8 +526,7 @@ test('TilePyramid#tilesIn', function (t) { loaded: true, uses: 1, tileSize: 512, - sourceMaxZoom: 14, - pixelRatio: 16 + sourceMaxZoom: 14 }, minX: -4096, maxX: 4096,