Skip to content

Commit

Permalink
fix: 在 WebGL2 拾取事件冒泡延迟问题 (#2511)
Browse files Browse the repository at this point in the history
* wip: 验证 readPixels 方法

* fix: 在 WebGL2 拾取事件冒泡延迟问题

* chore: add changeset
  • Loading branch information
lvisei authored May 29, 2024
1 parent aca779d commit a5f57ed
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 10 deletions.
5 changes: 5 additions & 0 deletions .changeset/polite-apples-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@antv/l7-core': patch
---

fix: 在 WebGL2 拾取事件冒泡延迟问题
38 changes: 28 additions & 10 deletions packages/core/src/services/interaction/PickingService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ export default class PickingService implements IPickingService {
{ x, y, lngLat, type, target }: IInteractionTarget,
) => {
let isPicked = false;
const { readPixelsAsync, getViewportSize } = this.rendererService;
const { readPixels, readPixelsAsync, getViewportSize, queryVerdorInfo } = this.rendererService;
const { width, height } = getViewportSize();
const { enableHighlight, enableSelect } = layer.getLayerConfig();
const xInDevicePixel = x * DOM.DPR;
Expand All @@ -190,15 +190,33 @@ export default class PickingService implements IPickingService {
) {
return false;
}
const pickedColors: Uint8Array | undefined = await readPixelsAsync({
x: Math.floor(xInDevicePixel / this.pickBufferScale),
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
y: Math.floor((height - (y + 1) * DOM.DPR) / this.pickBufferScale),
width: 1,
height: 1,
data: new Uint8Array(1 * 1 * 4),
framebuffer: this.pickingFBO,
});

let pickedColors: Uint8Array | undefined;

// readPixelsAsync 比 readPixels 慢,会造成拾取事件冒泡延迟,优先使用 readPixelsAsync,WebGPU 只支持 readPixelsAsync API
const isWebGPU = queryVerdorInfo() === 'WebGPU';
if (isWebGPU) {
pickedColors = await readPixelsAsync({
x: Math.floor(xInDevicePixel / this.pickBufferScale),
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
y: Math.floor((height - (y + 1) * DOM.DPR) / this.pickBufferScale),
width: 1,
height: 1,
data: new Uint8Array(1 * 1 * 4),
framebuffer: this.pickingFBO,
});
} else {
pickedColors = readPixels({
x: Math.floor(xInDevicePixel / this.pickBufferScale),
// 视口坐标系原点在左上,而 WebGL 在左下,需要翻转 Y 轴
y: Math.floor((height - (y + 1) * DOM.DPR) / this.pickBufferScale),
width: 1,
height: 1,
data: new Uint8Array(1 * 1 * 4),
framebuffer: this.pickingFBO,
});
}

this.pickedColors = pickedColors;

if (pickedColors[0] !== 0 || pickedColors[1] !== 0 || pickedColors[2] !== 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import BaseNormalPass from './BaseNormalPass';
/**
* color-based PixelPickingPass
* @see https://github.com/antvis/L7/blob/next/dev-docs/PixelPickingEngine.md
* @deprecated
* 目前未使用
*/
export default class PixelPickingPass<
InitializationOptions = {},
Expand Down
12 changes: 12 additions & 0 deletions packages/renderer/src/device/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,19 @@ export default class DeviceRendererService implements IRendererService {
height,
new Uint8Array(width * height * 4),
) as Uint8Array;

// Since we use U8_RGBA_RT format in render target, need to change bgranorm -> rgba here.
if (this.viewportOrigin !== ViewportOrigin.LOWER_LEFT) {
for (let j = 0; j < result.length; j += 4) {
// Switch b and r components.
const t = result[j];
result[j] = result[j + 2];
result[j + 2] = t;
}
}

readback.destroy();

return result;
};

Expand Down

0 comments on commit a5f57ed

Please sign in to comment.