package.src.render.draw_fill_extrusion.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of mapbox-gl Show documentation
Show all versions of mapbox-gl Show documentation
A WebGL interactive maps library
The newest version!
// @flow
import DepthMode from '../gl/depth_mode';
import StencilMode from '../gl/stencil_mode';
import ColorMode from '../gl/color_mode';
import CullFaceMode from '../gl/cull_face_mode';
import {
fillExtrusionUniformValues,
fillExtrusionPatternUniformValues,
} from './program/fill_extrusion_program';
import type Painter from './painter';
import type SourceCache from '../source/source_cache';
import type FillExtrusionStyleLayer from '../style/style_layer/fill_extrusion_style_layer';
import type FillExtrusionBucket from '../data/bucket/fill_extrusion_bucket';
import type {OverscaledTileID} from '../source/tile_id';
export default draw;
function draw(painter: Painter, source: SourceCache, layer: FillExtrusionStyleLayer, coords: Array) {
const opacity = layer.paint.get('fill-extrusion-opacity');
if (opacity === 0) {
return;
}
if (painter.renderPass === 'translucent') {
const depthMode = new DepthMode(painter.context.gl.LEQUAL, DepthMode.ReadWrite, painter.depthRangeFor3D);
if (opacity === 1 && !layer.paint.get('fill-extrusion-pattern').constantOr((1: any))) {
const colorMode = painter.colorModeForRenderPass();
drawExtrusionTiles(painter, source, layer, coords, depthMode, StencilMode.disabled, colorMode);
} else {
// Draw transparent buildings in two passes so that only the closest surface is drawn.
// First draw all the extrusions into only the depth buffer. No colors are drawn.
drawExtrusionTiles(painter, source, layer, coords, depthMode,
StencilMode.disabled,
ColorMode.disabled);
// Then draw all the extrusions a second type, only coloring fragments if they have the
// same depth value as the closest fragment in the previous pass. Use the stencil buffer
// to prevent the second draw in cases where we have coincident polygons.
drawExtrusionTiles(painter, source, layer, coords, depthMode,
painter.stencilModeFor3D(),
painter.colorModeForRenderPass());
}
}
}
function drawExtrusionTiles(painter, source, layer, coords, depthMode, stencilMode, colorMode) {
const context = painter.context;
const gl = context.gl;
const patternProperty = layer.paint.get('fill-extrusion-pattern');
const image = patternProperty.constantOr((1: any));
const crossfade = layer.getCrossfadeParameters();
const opacity = layer.paint.get('fill-extrusion-opacity');
for (const coord of coords) {
const tile = source.getTile(coord);
const bucket: ?FillExtrusionBucket = (tile.getBucket(layer): any);
if (!bucket) continue;
const programConfiguration = bucket.programConfigurations.get(layer.id);
const program = painter.useProgram(image ? 'fillExtrusionPattern' : 'fillExtrusion', programConfiguration);
if (image) {
painter.context.activeTexture.set(gl.TEXTURE0);
tile.imageAtlasTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
programConfiguration.updatePaintBuffers(crossfade);
}
const constantPattern = patternProperty.constantOr(null);
if (constantPattern && tile.imageAtlas) {
const atlas = tile.imageAtlas;
const posTo = atlas.patternPositions[constantPattern.to.toString()];
const posFrom = atlas.patternPositions[constantPattern.from.toString()];
if (posTo && posFrom) programConfiguration.setConstantPatternPositions(posTo, posFrom);
}
const matrix = painter.translatePosMatrix(
coord.posMatrix,
tile,
layer.paint.get('fill-extrusion-translate'),
layer.paint.get('fill-extrusion-translate-anchor'));
const shouldUseVerticalGradient = layer.paint.get('fill-extrusion-vertical-gradient');
const uniformValues = image ?
fillExtrusionPatternUniformValues(matrix, painter, shouldUseVerticalGradient, opacity, coord, crossfade, tile) :
fillExtrusionUniformValues(matrix, painter, shouldUseVerticalGradient, opacity);
program.draw(context, context.gl.TRIANGLES, depthMode, stencilMode, colorMode, CullFaceMode.backCCW,
uniformValues, layer.id, bucket.layoutVertexBuffer, bucket.indexBuffer,
bucket.segments, layer.paint, painter.transform.zoom,
programConfiguration);
}
}