-
-
Notifications
You must be signed in to change notification settings - Fork 823
/
Copy pathdraw_color_relief.ts
110 lines (93 loc) · 4.61 KB
/
draw_color_relief.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
import {Texture} from './texture';
import type {StencilMode} from '../gl/stencil_mode';
import {DepthMode} from '../gl/depth_mode';
import {CullFaceMode} from '../gl/cull_face_mode';
import {type ColorMode} from '../gl/color_mode';
import {
colorReliefUniformValues
} from './program/color_relief_program';
import type {Painter, RenderOptions} from './painter';
import type {SourceCache} from '../source/source_cache';
import type {ColorReliefStyleLayer} from '../style/style_layer/color_relief_style_layer';
import type {OverscaledTileID} from '../source/tile_id';
import type {Context} from '../gl/context';
export function drawColorRelief(painter: Painter, sourceCache: SourceCache, layer: ColorReliefStyleLayer, tileIDs: Array<OverscaledTileID>, renderOptions: RenderOptions) {
if (painter.renderPass !== 'translucent') return;
if (!tileIDs.length) return;
const {isRenderingToTexture} = renderOptions;
const projection = painter.style.projection;
const useSubdivision = projection.useSubdivision;
const depthMode = painter.getDepthModeForSublayer(0, DepthMode.ReadOnly);
const colorMode = painter.colorModeForRenderPass();
// Globe (or any projection with subdivision) needs two-pass rendering to avoid artifacts when rendering texture tiles.
// See comments in draw_raster.ts for more details.
if (useSubdivision) {
// Two-pass rendering
const [stencilBorderless, stencilBorders, coords] = painter.stencilConfigForOverlapTwoPass(tileIDs);
renderColorRelief(painter, sourceCache, layer, coords, stencilBorderless, depthMode, colorMode, false, isRenderingToTexture); // draw without borders
renderColorRelief(painter, sourceCache, layer, coords, stencilBorders, depthMode, colorMode, true, isRenderingToTexture); // draw with borders
} else {
// Simple rendering
const [stencil, coords] = painter.getStencilConfigForOverlapAndUpdateStencilID(tileIDs);
renderColorRelief(painter, sourceCache, layer, coords, stencil, depthMode, colorMode, false, isRenderingToTexture);
}
}
function renderColorRelief(
painter: Painter,
sourceCache: SourceCache,
layer: ColorReliefStyleLayer,
coords: Array<OverscaledTileID>,
stencilModes: {[_: number]: Readonly<StencilMode>},
depthMode: Readonly<DepthMode>,
colorMode: Readonly<ColorMode>,
useBorder: boolean,
isRenderingToTexture: boolean
) {
const projection = painter.style.projection;
const context = painter.context;
const transform = painter.transform;
const gl = context.gl;
const program = painter.useProgram('colorRelief');
const align = !painter.options.moving;
if(layer.colorRamp) {
const colorRampTexture = getColorRampTexture(context, layer);
context.activeTexture.set(gl.TEXTURE5);
colorRampTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
}
for (const coord of coords) {
const tile = sourceCache.getTile(coord);
const dem = tile.dem;
if (!dem || !dem.data) {
continue;
}
const textureStride = dem.stride;
const pixelData = dem.getPixels();
context.activeTexture.set(gl.TEXTURE0);
context.pixelStoreUnpackPremultiplyAlpha.set(false);
tile.demTexture = tile.demTexture || painter.getTileTexture(textureStride);
if (tile.demTexture) {
const demTexture = tile.demTexture;
demTexture.update(pixelData, {premultiply: false});
demTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
} else {
tile.demTexture = new Texture(context, pixelData, gl.RGBA, {premultiply: false});
tile.demTexture.bind(gl.LINEAR, gl.CLAMP_TO_EDGE);
}
const mesh = projection.getMeshFromTileID(context, coord.canonical, useBorder, true, 'raster');
const terrainData = painter.style.map.terrain?.getTerrainData(coord);
const projectionData = transform.getProjectionData({
overscaledTileID: coord,
aligned: align,
applyGlobeMatrix: !isRenderingToTexture,
applyTerrainMatrix: true
});
program.draw(context, gl.TRIANGLES, depthMode, stencilModes[coord.overscaledZ], colorMode, CullFaceMode.backCCW,
colorReliefUniformValues(layer, tile.dem, layer.elevationRange), terrainData, projectionData, layer.id, mesh.vertexBuffer, mesh.indexBuffer, mesh.segments);
}
}
function getColorRampTexture(context: Context, layer: ColorReliefStyleLayer): Texture {
if (!layer.colorRampTexture) {
layer.colorRampTexture = new Texture(context, layer.colorRamp, context.gl.RGBA);
}
return layer.colorRampTexture;
}