mapbox gl js:使用中间渲染步骤作为自定义层的掩码
mapbox gl js: use intermediate rendering step as mask for custom layer
my objective 是有一个 mapbox 地图,上面覆盖了一个自定义图层。该自定义图层应被其他 mapbox 地图遮盖。
用例:
我有一些默认地图。最重要的是我想渲染一些特殊的热图。该热图只能显示在道路上方。
当前方法:
- 向 mapbox 添加图层以生成所有道路均为白色且背景为黑色的地图
- 添加一个自定义层,将帧缓冲区的内容复制到纹理
- 添加图层以渲染一些默认地图
- 添加使用上述纹理作为遮罩绘制特殊热图的自定义图层。
问题:
渲染图层的顺序似乎与它们添加到 mapbox 的顺序不匹配。这个例子有一个自定义层,它在调用时输出帧缓冲区中中心像素的颜色:
var map = window.map = new mapboxgl.Map({
container: 'map',
zoom: 16,
center: [8.30468, 47.05232],
style: {
"version":8,
"name":"test",
"sources": {
"openmaptiles": {
"type": "vector",
"url": "https://api.maptiler.com/tiles/v3/tiles.json?key=X0HhMcrAjHfR6MvFLSSn"
}
},
"layers":[]}
});
var getPixelLayer = {
id: 'highlight',
type: 'custom',
onAdd: function (map, gl) { },
render: function (gl, matrix) {
var pixels = new Uint8Array(4);
gl.readPixels(Math.round(gl.drawingBufferWidth/2), Math.round(gl.drawingBufferHeight/2), 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
document.getElementById("color").innerHTML = pixels[0]+","+pixels[1]+","+pixels[2];
}
};
map.on('load', function() {
//expected output: "255,255,255" everywhere
//actual output: "0,0,0" everywhere
/*
map.addLayer({"id":"bkg1","paint":{"background-color":"rgb(255, 255, 255)"},"type":"background"});
map.addLayer(getPixelLayer);
map.addLayer({"id":"bkg2","paint":{"background-color":"rgb(0, 0, 0)"},"type":"background"});
*/
//expected output: "0,0,0" everywhere
//actual output: "177,177,177" above buildings
// "0,0,0" above streets
// "0,0,0" above background
map.addLayer({"id":"bkg1","paint":{"background-color":"rgb(0, 0, 0)"},"type":"background"});
map.addLayer(getPixelLayer);
map.addLayer({"id":"roads","layout":{"line-cap":"round","line-join":"round","visibility":"visible"},"paint":{"line-color":"#fff","line-offset":0,"line-width":{"base":1.4,"stops":[[8,1.2],[16,12]]}},"source":"openmaptiles","source-layer":"transportation","type":"line"});
map.addLayer({"id":"building","paint":{"fill-color":"rgb(177, 177, 177)"},"source":"openmaptiles","source-layer":"building","type":"fill"});
});
https://jsfiddle.net/t31cj5v0/
可以看出渲染顺序似乎是背景->建筑物->custom_layer->街道而不是背景->custom_layer->街道->建筑物。最后,图层顺序在屏幕上显示正确,但无法像这样做我想做的事。
有谁知道导致这种行为的原因以及如何避免这种情况?
我尝试过的其他实现:
我还尝试通过同步移动将黑白街道地图渲染到不同的地图框对象。这可行,但由于每个 mapbox 都有自己的 webgl 上下文,我不能在其他上下文中使用生成的黑白纹理。
功能请求 (?)
如果可以实现一些 "mask" 层来本地完成此 objective,那将是非常好的。但现在我只是在寻找一些技巧来做到这一点。提前致谢。
mapbox 图层在 3 个渲染通道中绘制。 "offscreen"、"opaque" 和 "translucent"。 "offscreen" 并不重要,因为后续的遍历总是会覆盖它。出现问题是因为首先绘制了所有分类为 "opaque" 的图层,然后绘制了所有分类为 "translucent" 的图层(在渲染过程中尊重图层顺序)。因此渲染顺序与声明的顺序不匹配。
自定义图层在 "translucent" 通道中绘制,但由于上述原因,可能会发生后面的图层已经渲染(如果 "opaque")。通常这不是问题,因为 mapbox 使用模板缓冲区来跟踪哪一层去 under/over 哪一层,即使它们没有按顺序绘制。
要使渲染顺序匹配,请在创建 mapbox 实例后添加此行。它将禁用 "opaque" 渲染通道并强制 "opaque" 的每一层为 "translucent":
map.painter.opaquePassEnabledForLayer = function() { return false; }
my objective 是有一个 mapbox 地图,上面覆盖了一个自定义图层。该自定义图层应被其他 mapbox 地图遮盖。
用例:
我有一些默认地图。最重要的是我想渲染一些特殊的热图。该热图只能显示在道路上方。
当前方法:
- 向 mapbox 添加图层以生成所有道路均为白色且背景为黑色的地图
- 添加一个自定义层,将帧缓冲区的内容复制到纹理
- 添加图层以渲染一些默认地图
- 添加使用上述纹理作为遮罩绘制特殊热图的自定义图层。
问题:
渲染图层的顺序似乎与它们添加到 mapbox 的顺序不匹配。这个例子有一个自定义层,它在调用时输出帧缓冲区中中心像素的颜色:
var map = window.map = new mapboxgl.Map({
container: 'map',
zoom: 16,
center: [8.30468, 47.05232],
style: {
"version":8,
"name":"test",
"sources": {
"openmaptiles": {
"type": "vector",
"url": "https://api.maptiler.com/tiles/v3/tiles.json?key=X0HhMcrAjHfR6MvFLSSn"
}
},
"layers":[]}
});
var getPixelLayer = {
id: 'highlight',
type: 'custom',
onAdd: function (map, gl) { },
render: function (gl, matrix) {
var pixels = new Uint8Array(4);
gl.readPixels(Math.round(gl.drawingBufferWidth/2), Math.round(gl.drawingBufferHeight/2), 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels);
document.getElementById("color").innerHTML = pixels[0]+","+pixels[1]+","+pixels[2];
}
};
map.on('load', function() {
//expected output: "255,255,255" everywhere
//actual output: "0,0,0" everywhere
/*
map.addLayer({"id":"bkg1","paint":{"background-color":"rgb(255, 255, 255)"},"type":"background"});
map.addLayer(getPixelLayer);
map.addLayer({"id":"bkg2","paint":{"background-color":"rgb(0, 0, 0)"},"type":"background"});
*/
//expected output: "0,0,0" everywhere
//actual output: "177,177,177" above buildings
// "0,0,0" above streets
// "0,0,0" above background
map.addLayer({"id":"bkg1","paint":{"background-color":"rgb(0, 0, 0)"},"type":"background"});
map.addLayer(getPixelLayer);
map.addLayer({"id":"roads","layout":{"line-cap":"round","line-join":"round","visibility":"visible"},"paint":{"line-color":"#fff","line-offset":0,"line-width":{"base":1.4,"stops":[[8,1.2],[16,12]]}},"source":"openmaptiles","source-layer":"transportation","type":"line"});
map.addLayer({"id":"building","paint":{"fill-color":"rgb(177, 177, 177)"},"source":"openmaptiles","source-layer":"building","type":"fill"});
});
https://jsfiddle.net/t31cj5v0/
可以看出渲染顺序似乎是背景->建筑物->custom_layer->街道而不是背景->custom_layer->街道->建筑物。最后,图层顺序在屏幕上显示正确,但无法像这样做我想做的事。
有谁知道导致这种行为的原因以及如何避免这种情况?
我尝试过的其他实现:
我还尝试通过同步移动将黑白街道地图渲染到不同的地图框对象。这可行,但由于每个 mapbox 都有自己的 webgl 上下文,我不能在其他上下文中使用生成的黑白纹理。
功能请求 (?)
如果可以实现一些 "mask" 层来本地完成此 objective,那将是非常好的。但现在我只是在寻找一些技巧来做到这一点。提前致谢。
mapbox 图层在 3 个渲染通道中绘制。 "offscreen"、"opaque" 和 "translucent"。 "offscreen" 并不重要,因为后续的遍历总是会覆盖它。出现问题是因为首先绘制了所有分类为 "opaque" 的图层,然后绘制了所有分类为 "translucent" 的图层(在渲染过程中尊重图层顺序)。因此渲染顺序与声明的顺序不匹配。
自定义图层在 "translucent" 通道中绘制,但由于上述原因,可能会发生后面的图层已经渲染(如果 "opaque")。通常这不是问题,因为 mapbox 使用模板缓冲区来跟踪哪一层去 under/over 哪一层,即使它们没有按顺序绘制。
要使渲染顺序匹配,请在创建 mapbox 实例后添加此行。它将禁用 "opaque" 渲染通道并强制 "opaque" 的每一层为 "translucent":
map.painter.opaquePassEnabledForLayer = function() { return false; }