UNPKG

mapbox-gl

Version:
80 lines (61 loc) 2.93 kB
'use strict'; var TilePyramid = require('../source/tile_pyramid'); var pyramid = new TilePyramid({ tileSize: 512 }); var util = require('../util/util'); var EXTENT = require('../data/buffer').EXTENT; module.exports = drawBackground; function drawBackground(painter, source, layer) { var gl = painter.gl; var transform = painter.transform; var color = util.premultiply(layer.paint['background-color'], layer.paint['background-opacity']); var image = layer.paint['background-pattern']; var opacity = layer.paint['background-opacity']; var shader; var imagePosA = image ? painter.spriteAtlas.getPosition(image.from, true) : null; var imagePosB = image ? painter.spriteAtlas.getPosition(image.to, true) : null; painter.setDepthSublayer(0); if (imagePosA && imagePosB) { if (painter.isOpaquePass) return; // Draw texture fill shader = painter.patternShader; gl.switchShader(shader); gl.uniform1i(shader.u_image, 0); gl.uniform2fv(shader.u_pattern_tl_a, imagePosA.tl); gl.uniform2fv(shader.u_pattern_br_a, imagePosA.br); gl.uniform2fv(shader.u_pattern_tl_b, imagePosB.tl); gl.uniform2fv(shader.u_pattern_br_b, imagePosB.br); gl.uniform1f(shader.u_opacity, opacity); gl.uniform1f(shader.u_mix, image.t); var factor = (EXTENT / transform.tileSize) / Math.pow(2, 0); gl.uniform2fv(shader.u_patternscale_a, [ 1 / (imagePosA.size[0] * factor * image.fromScale), 1 / (imagePosA.size[1] * factor * image.fromScale) ]); gl.uniform2fv(shader.u_patternscale_b, [ 1 / (imagePosB.size[0] * factor * image.toScale), 1 / (imagePosB.size[1] * factor * image.toScale) ]); painter.spriteAtlas.bind(gl, true); } else { // Draw filling rectangle. if (painter.isOpaquePass !== (color[3] === 1)) return; shader = painter.fillShader; gl.switchShader(shader); gl.uniform4fv(shader.u_color, color); } gl.disable(gl.STENCIL_TEST); gl.bindBuffer(gl.ARRAY_BUFFER, painter.tileExtentBuffer); gl.vertexAttribPointer(shader.a_pos, painter.tileExtentBuffer.itemSize, gl.SHORT, false, 0, 0); // We need to draw the background in tiles in order to use calculatePosMatrix // which applies the projection matrix (transform.projMatrix). Otherwise // the depth and stencil buffers get into a bad state. // This can be refactored into a single draw call once earcut lands and // we don't have so much going on in the stencil buffer. var coords = pyramid.coveringTiles(transform); for (var c = 0; c < coords.length; c++) { gl.setPosMatrix(painter.calculatePosMatrix(coords[c])); gl.drawArrays(gl.TRIANGLE_STRIP, 0, painter.tileExtentBuffer.itemCount); } gl.stencilMask(0x00); gl.stencilFunc(gl.EQUAL, 0x80, 0x80); }