mapbox-gl
Version:
A WebGL interactive maps library
130 lines (97 loc) • 4.09 kB
JavaScript
;
var util = require('../util/util');
module.exports = drawRaster;
function drawRaster(painter, source, layer, coords) {
if (painter.isOpaquePass) return;
var gl = painter.gl;
// Change depth function to prevent double drawing in areas where tiles overlap.
gl.depthFunc(gl.LESS);
for (var i = coords.length - 1; i >= 0; i--) {
drawRasterTile(painter, source, layer, coords[i]);
}
gl.depthFunc(gl.LEQUAL);
}
function drawRasterTile(painter, source, layer, coord) {
painter.setDepthSublayer(0);
var gl = painter.gl;
gl.disable(gl.STENCIL_TEST);
var tile = source.getTile(coord);
var posMatrix = painter.calculatePosMatrix(coord, source.maxzoom);
var shader = painter.rasterShader;
gl.switchShader(shader, posMatrix);
// color parameters
gl.uniform1f(shader.u_brightness_low, layer.paint['raster-brightness-min']);
gl.uniform1f(shader.u_brightness_high, layer.paint['raster-brightness-max']);
gl.uniform1f(shader.u_saturation_factor, saturationFactor(layer.paint['raster-saturation']));
gl.uniform1f(shader.u_contrast_factor, contrastFactor(layer.paint['raster-contrast']));
gl.uniform3fv(shader.u_spin_weights, spinWeights(layer.paint['raster-hue-rotate']));
var parentTile = tile.source && tile.source._pyramid.findLoadedParent(coord, 0, {}),
opacities = getOpacities(tile, parentTile, layer, painter.transform);
var parentScaleBy, parentTL;
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, tile.texture);
if (parentTile) {
gl.activeTexture(gl.TEXTURE1);
gl.bindTexture(gl.TEXTURE_2D, parentTile.texture);
parentScaleBy = Math.pow(2, parentTile.coord.z - tile.coord.z);
parentTL = [tile.coord.x * parentScaleBy % 1, tile.coord.y * parentScaleBy % 1];
} else {
opacities[1] = 0;
}
// cross-fade parameters
gl.uniform2fv(shader.u_tl_parent, parentTL || [0, 0]);
gl.uniform1f(shader.u_scale_parent, parentScaleBy || 1);
gl.uniform1f(shader.u_buffer_scale, 1);
gl.uniform1f(shader.u_opacity0, opacities[0]);
gl.uniform1f(shader.u_opacity1, opacities[1]);
gl.uniform1i(shader.u_image0, 0);
gl.uniform1i(shader.u_image1, 1);
gl.bindBuffer(gl.ARRAY_BUFFER, tile.boundsBuffer || painter.tileExtentBuffer);
gl.vertexAttribPointer(shader.a_pos, 2, gl.SHORT, false, 8, 0);
gl.vertexAttribPointer(shader.a_texture_pos, 2, gl.SHORT, false, 8, 4);
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
}
function spinWeights(angle) {
angle *= Math.PI / 180;
var s = Math.sin(angle);
var c = Math.cos(angle);
return [
(2 * c + 1) / 3,
(-Math.sqrt(3) * s - c + 1) / 3,
(Math.sqrt(3) * s - c + 1) / 3
];
}
function contrastFactor(contrast) {
return contrast > 0 ?
1 / (1 - contrast) :
1 + contrast;
}
function saturationFactor(saturation) {
return saturation > 0 ?
1 - 1 / (1.001 - saturation) :
-saturation;
}
function getOpacities(tile, parentTile, layer, transform) {
var opacity = [1, 0];
var fadeDuration = layer.paint['raster-fade-duration'];
if (tile.source && fadeDuration > 0) {
var now = new Date().getTime();
var sinceTile = (now - tile.timeAdded) / fadeDuration;
var sinceParent = parentTile ? (now - parentTile.timeAdded) / fadeDuration : -1;
var idealZ = tile.source._pyramid.coveringZoomLevel(transform);
var parentFurther = parentTile ? Math.abs(parentTile.coord.z - idealZ) > Math.abs(tile.coord.z - idealZ) : false;
if (!parentTile || parentFurther) {
// if no parent or parent is older
opacity[0] = util.clamp(sinceTile, 0, 1);
opacity[1] = 1 - opacity[0];
} else {
// parent is younger, zooming out
opacity[0] = util.clamp(1 - sinceParent, 0, 1);
opacity[1] = 1 - opacity[0];
}
}
var op = layer.paint['raster-opacity'];
opacity[0] *= op;
opacity[1] *= op;
return opacity;
}