大量标记与散点
万级点的瓶颈是 draw call,不是 VS 里多几个 MAD。场景图(id、世界坐标、业务字段)留在 CPU;GPU 只吃一条四边形几何 + 一条 instance buffer。不要每点 drawArrays,也不要从颜色反推「这是哪只股票」。
1. 场景怎么切
CPU 文档:id / worldXY / 颜色 / 选中态
↓ 视口裁剪、像素去重
instance buffer(投影)
↓ drawArraysInstanced 一次
drawing buffer
相机是 世界单位 + viewProj。点的真值在世界;CSS 盒只决定可见范围。轴/网格另走低频 pass 或 DOM,不要和点抢同一条 instance。
export type ScatterPoint = {
id: number;
x: number;
y: number;
r: number;
g: number;
b: number;
};
export type Camera2D = {
x: number;
y: number;
scale: number;
};
export function packVisible(
camera: Camera2D,
cssW: number,
cssH: number,
points: readonly ScatterPoint[],
): { packed: Float32Array; ids: number[] } {
const maxX = camera.x + cssW * camera.scale;
const maxY = camera.y + cssH * camera.scale;
const inv = 1 / camera.scale;
const seen = new Set<number>();
const tmp: number[] = [];
const ids: number[] = [];
for (const p of points) {
if (p.x < camera.x || p.x > maxX || p.y < camera.y || p.y > maxY) continue;
const key = (Math.round((p.x - camera.x) * inv) << 16) ^ Math.round((p.y - camera.y) * inv);
if (seen.has(key)) continue;
seen.add(key);
tmp.push(p.x, p.y, p.r, p.g, p.b);
ids.push(p.id);
}
return { packed: new Float32Array(tmp), ids };
}
ids[i] 与 instance 第 i 行对齐,拾取只查这份可见投影。像素去重是屏幕密度,不是统计 bin;热力图要另做 grid count。
适用:监控散点、行情点、地图 POI,量级从几千到几十万。
不适用:每点不同 mesh / 不同 program(那是多条合批,见 实例化);< 2k 且只要轴+tooltip,先看 Canvas 散点。
2. 哪层必须 CPU,哪层进 GPU
| 层 | 归属 |
|---|---|
| 点列表、id、业务字段、选中集 | CPU 文档 |
| 视口裁剪、像素 LOD、空间索引 | CPU,相机变了才重打 |
| 四边形几何、instance buffer、viewProj | GPU 投影 |
| tooltip / 图例 | DOM overlay,见 Overlay |
相机动、点不动:只改 uniform。点增删或裁剪结果变了:bufferSubData 脏区,不要每帧 bufferData 十万行。合批键必须同一 shader + 同一图集,见 合批。
拾取默认 CPU:可见 ids + 网格,比距离。点是圆/AABB 时不要开 ID pass。三角标牌互交、半透明叠完才知道点到谁,再走 GPU 拾取 且只读 1px。热路径禁止全屏 readPixels。
GPU-driven 剔除 + drawIndirect 是 WebGPU 的活:先 requestAdapter(),失败就留在 WebGL2 实例化。不要为散点默认切 WebGPU。
3. 失败形态
| 症状 | 原因 |
|---|---|
| 一万点 10fps | 每点一次 drawArrays |
| hover 错点 | 用 CSS 像素去比世界坐标,或裁剪后 ids 没对齐 |
| 缩轴后点变成椭圆 | 半径写进世界单位,没按 view 尺度 |
| 拖一个点全体跳 | world 当 uniform,不是 instance 行 |
| 一拾取就卡 | 读了整张 ID 图 |
权威资料
核对日期:2026-08-26