小地图与第二视图
小地图是 第二台相机,不是把主 drawing buffer readPixels 缩小贴角落。主视图全屏再缩,等于每帧多付一次全场景光栅,还插入 CPU–GPU 同步。两台相机共享 CPU 世界;GPU 是两份 viewProj 投到两张(或一块 scissor)目标。
1. 场景怎么切
CPU 世界(同一份文档)
├─ 主相机 viewProj → 主 FBO / 默认 FB
└─ 小地图相机 viewProj → 低分辨率 overview FBO
视口框、点击跳转:CPU 把世界 AABB 映到 mini CSS
主相机随便 pan/zoom。小地图相机只在 世界包围盒变了 时重算(地图扩边)。每帧只更新视口框几何,不要重烘概览。
export type Camera2D = { x: number; y: number; scale: number };
export type WorldAabb = { minX: number; minY: number; maxX: number; maxY: number };
export function miniCamera(world: WorldAabb, cssW: number, cssH: number): Camera2D {
const w = Math.max(1e-6, world.maxX - world.minX);
const h = Math.max(1e-6, world.maxY - world.minY);
const scale = Math.max(w / cssW, h / cssH);
const viewW = cssW * scale;
const viewH = cssH * scale;
return {
scale,
x: world.minX - (viewW - w) / 2,
y: world.minY - (viewH - h) / 2,
};
}
export function viewportOnMini(
main: Camera2D,
mini: Camera2D,
mainCssW: number,
mainCssH: number,
): { x: number; y: number; w: number; h: number } {
const a = { x: main.x, y: main.y };
const b = { x: main.x + mainCssW * main.scale, y: main.y + mainCssH * main.scale };
const p1 = { x: (a.x - mini.x) / mini.scale, y: (a.y - mini.y) / mini.scale };
const p2 = { x: (b.x - mini.x) / mini.scale, y: (b.y - mini.y) / mini.scale };
return {
x: Math.min(p1.x, p2.x),
y: Math.min(p1.y, p2.y),
w: Math.abs(p2.x - p1.x),
h: Math.abs(p2.y - p1.y),
};
}
点击:mini CSS → 世界点 → 主相机把该点放到视口中心。矩阵与 相机 同一套,禁止第二套 clientX 换算。
适用:地图/游戏概览、第二正交视图、调试用的自由相机。
不适用:用主缓冲当缩略图源;把小地图当可访问控件却不提供 DOM 替代,见 GPU 无障碍。
2. 哪层必须 CPU,哪层进 GPU
| 层 | 归属 |
|---|---|
| 世界文档、两台 Camera2D、包围盒 | CPU |
| 概览 FBO(低清、简化 pass:无粒子、无手柄) | GPU 投影 |
| 视口框、点击热区 | DOM / 第二张小 canvas 上的 2D,或 GL 线框 |
| 跳转、拖框 | CPU 改主相机 |
概览 FBO 尺寸 ≈ mini CSS × dpr,不要等于主 drawingBuffer。静态层节流烘(地图未改就不画)。主 pass 与 mini pass 可以同一上下文里切 viewport/FBO,也可以第二张 <canvas> 各自 webgl2。同一元素不能再要 2d。
禁止:readPixels 主缓冲再 texImage2D 缩小;toDataURL 当小地图。读回规则见 读回陷阱。框比小地图还大时夹紧绘制,不要 clip 到点不到。2D 产品对照 Canvas 小地图。
3. 失败形态
| 症状 | 原因 |
|---|---|
| 开小地图掉一半帧 | 每帧按主场景全细节重画 mini,或读主缓冲缩小 |
| 框和主视图对不上 | 两套世界原点,或一边忘了 letterbox |
| 点击跳转偏一截 | mini CSS 当了世界,或 Y 没和主相机同约定 |
| 导出带小地图框 | 把 chrome 画进了主 FBO |
| 拾取点到 mini 物体 | 命中仍用主 viewProj |
权威资料
核对日期:2026-08-26