关于 3d-retina-resolution
这份指南介绍如何在 3D Web 项目中处理 Retina 和明确指定的 200% 渲染,面向调整画布分辨率的开发者。内容涵盖渲染器与后处理尺寸同步、输入坐标、性能测量和回退行为。
主要功能
- 01区分固定 200% 与有上限的自动模式
- 02同步渲染器和后处理缓冲区尺寸
- 03处理缩放、显隐、浏览器缩放和显示器变化
- 04使用 CSS 坐标归一化指针输入
- 05测量 GPU 开销并制定回退行为
- 06验证输出尺寸和交互对齐
适用场景
- 01为 3D 视图添加明确的 200% 画质选项
- 02提高像素比时保持后处理清晰
- 03排查画面模糊或指针选择错位
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ mengto/ skills --skill 3d-retina-resolution安装后在 Claude Code 中输入/3d-retina-resolution确认已加载。
附带文件agents/openai.yamlREFERENCES.md
详细介绍
3D Retina 分辨率
将明确的 200% 渲染请求视为每个维度上每个 CSS 像素对应两个绘图缓冲区像素。因此,1200 × 800 CSS 像素的画布会使用 2400 × 1600 的绘图缓冲区,像素数是 100% 时的四倍。布局和摄像机取景保持不变。
有意选择缩放比例
- **固定 200%:**有效像素比为
2,不受设备像素比影响。当用户明确要求 200% 时,这是默认设置。 - **自动 Retina,最高 2×:**有效像素比为
Math.min(window.devicePixelRatio || 1, 2)。普通显示器上可能以 1× 渲染;应标记为“自动”,而不是声称始终以 200% 渲染。 - **相对于原生分辨率:**只有用户明确要求这种含义时,才将原生 DPR 相乘。原生 2× 再乘以 2 后,每个维度就是 4×,即 CSS 像素数的十六倍。
将明确的画质选项与自动适配区分开。更改尺寸之前,先检查项目的渲染器和后期处理架构。
同步渲染管线
使用 CSS 设置画布及其容器的尺寸,然后以 CSS 像素测量容器。在 Three.js WebGL 中,一种一致的做法是使用逻辑尺寸加像素比:
function resize3D(width, height, ratio = 2) {
if (!Number.isFinite(width) || !Number.isFinite(height) || width <= 0 || height <= 0) return;
if (!Number.isFinite(ratio) || ratio <= 0) throw new RangeError('Invalid render ratio');
renderer.setPixelRatio(ratio);
renderer.setSize(width, height, false); // CSS owns displayed dimensions
camera.aspect = width / height; // perspective camera
camera.updateProjectionMatrix();
if (composer) {
composer.setPixelRatio(ratio);
composer.setSize(width, height); // logical pixels; do not multiply again
}
const physicalWidth = renderer.domElement.width;
const physicalHeight = renderer.domElement.height;
resizeCustomTargets(physicalWidth, physicalHeight);
}
此代码片段假设已有 renderer、透视 camera、可选的 composer(或 null),以及由应用提供的 resizeCustomTargets 适配器。对于正交摄像机,应按照现有取景策略更新其边界,而不是设置 aspect。
此适配器只更新应用自有的目标和 uniforms;composer 管理的通道已通过 composer 接收尺寸设置。将全分辨率深度/法线目标设为物理尺寸。按有意设置的缩放比例调整低分辨率 AO、bloom 或 ray 目标。将采样分辨率 uniforms 设为实际采样纹理的尺寸;如果着色器需要,也应包含倒数分辨率。
渲染器和 composer 各自维护像素比。只更新画布可能会导致低分辨率中间图像被拉伸到 Retina 输出。反过来,如果向 DPR 为 2 的 composer 传入已加倍的尺寸,就会分配 4× 尺寸。请参阅 渲染器 和 composer 的尺寸设置 API。
处理布局和显示变化
使用 ResizeObserver 监听画布容器,将通知合并处理,并且仅在尺寸或有效像素比变化时调整大小。跳过尺寸为零的隐藏视图,并在其显示后重试。在自动模式下,浏览器缩放或显示设备变化时重新评估原生 DPR,即使 CSS 尺寸保持不变也要如此。如果使用分辨率媒体查询监听器,则在每次 DPR 变化后重新创建该监听器。
使用 canvas.getBoundingClientRect() 进行指针归一化:(clientX - rect.left) / rect.width,Y 坐标同理。光线投射使用从 CSS 空间导出的归一化坐标,而不是绘图缓冲区像素。只有像素读取等 API 才需要单独转换为物理像素。
Retina 输出不会自动改善模糊的纹理、粗糙的模型、阴影贴图或低分辨率反射。请分别检查这些来源。不要用 CSS 缩放或 image-rendering: pixelated 替代正确的绘图缓冲区。更高分辨率和抗锯齿能解决相关但不同的瑕疵。
预算与回退
使用同一台相机,以 1× 和 2× 测量场景。跟踪帧耗时、目标尺寸、分配失败次数和总通道数。在分配特别大的目标前,检查 GPU 限制,包括纹理/渲染缓冲区最大尺寸和视口限制。
优先降低可选后期效果的分辨率或采样数,再考虑影响所请求的清晰主视图。自动模式可在帧耗时持续较差后逐步降低,并通过滞后来恢复;不要每隔几帧就调整尺寸。除非发生需要明显回退的具体硬件/分配故障,否则固定的 200% 选项应保持不变。应报告实际生效的比例,不要显示 200% 却悄悄以更低比例渲染。
暂停隐藏视图,并按需渲染静态场景。在减少动态效果的设置下,保留清晰的静止图像;减少动画并不意味着要降低分辨率。释放已替换的渲染目标。
验证
- 在固定 200% 下,对比画布的 CSS 尺寸与
canvas.width/canvas.height和renderer.getDrawingBufferSize();预期每个轴约为 2×,并进行整数舍入。 - 确认合成器缓冲区为全分辨率,并确认任何缩小尺寸的通道都是有意设置的。
- 调整视图宽度(宽 ↔ 窄)、隐藏/显示视图,并在自动模式下测试浏览器缩放或显示设置变化。
- 在相同的显示尺寸下检查细边缘和细节丰富的材质;指针选取和 UI 对齐必须保持正确。
- 在 DPR 1 显示器和 Retina 显示器上测试:固定 200% 始终保持 2×;自动模式遵循其上限。
请阅读 REFERENCES.md,了解 API 和参考项目。Seijaku 设有多项渲染器质量上限和自适应主渲染路径;这些数值仅供参考,不能证明其主视图已经以固定 200% 渲染。