Add Chromium-only Blender WebEngine parity work
This commit is contained in:
196
docs/PBR_RENDERING_IMPLEMENTATION_PLAN.md
Normal file
196
docs/PBR_RENDERING_IMPLEMENTATION_PLAN.md
Normal file
@@ -0,0 +1,196 @@
|
||||
# Web Blender PBR 渲染实现与任务分解
|
||||
|
||||
更新日期:2026-08-09
|
||||
|
||||
## 1. 目标和声明边界
|
||||
|
||||
目标是在浏览器 3D Viewport 中提供与 Blender Principled 工作流一致、可保存、可重开的
|
||||
PBR 预览。材质参数必须来自 Blender Main,经 SceneIR 传输并由主线程和 OffscreenCanvas
|
||||
Worker 使用相同映射,禁止只修改 Three.js 临时状态。
|
||||
|
||||
当前能力称为 `physical-v1`,不是 Cycles、EEVEE 或 Blender Shader Node 的逐像素等价实现。
|
||||
它保证的是有界 Principled 参数、线性色彩输入、sRGB 输出、ACES Filmic tone mapping、
|
||||
World exposure、场景灯光和有界 PCF 阴影的一致 WebGL 渲染。未声明节点、谱渲染、光程、体积、
|
||||
次表面、多次散射和离线 path tracing 必须继续结构化阻断或降级并给出 warning。
|
||||
|
||||
## 2. 权威数据流
|
||||
|
||||
```text
|
||||
Blender Main
|
||||
-> .blend writer/save/reopen
|
||||
-> native blend reader
|
||||
-> SceneIR MaterialIR/LightIR/WorldIR
|
||||
-> transferable mesh buffers
|
||||
-> shared pbr.ts mapping
|
||||
-> main-thread WebGLRenderer
|
||||
-> OffscreenCanvas render Worker
|
||||
```
|
||||
|
||||
编辑链路为:Inspector 控件 -> `setMaterialPrincipled` -> EngineWorker -> Blender Main 节点
|
||||
socket -> 新 revision SceneIR -> 视口重建。任何新增参数必须同时通过命令校验、Main 写回、
|
||||
reader、SceneIR parser、保存重开和双后端验收。
|
||||
|
||||
## 3. Blender 到 Web 的材质映射
|
||||
|
||||
| Blender 5.2 Principled 输入 | SceneIR | Three.js | 范围/说明 |
|
||||
| --- | --- | --- | --- |
|
||||
| Base Color | `baseColor` | `color` | 线性 RGB,alpha 独立处理 |
|
||||
| Roughness | `roughness` | `roughness` | `[0,1]` |
|
||||
| Metallic | `metallic` | `metalness` | `[0,1]` |
|
||||
| IOR | `ior` | `ior` | 当前限定 `[1,2.333]` |
|
||||
| Specular IOR Level | `specularIORLevel` | `specularIntensity` | Blender 中性值 0.5 映射到 Three 中性值 1.0;高半区有界截断 |
|
||||
| Transmission Weight | `transmissionWeight` | `transmission` | `[0,1]`,使用物理透射 pass |
|
||||
| Coat Weight | `coatWeight` | `clearcoat` | `[0,1]` |
|
||||
| Coat Roughness | `coatRoughness` | `clearcoatRoughness` | `[0,1]` |
|
||||
| Emission Color | `emissionColor` | `emissive` | 线性 RGB |
|
||||
| Emission Strength | `emissionStrength` | `emissiveIntensity` | `[0,1000000]` |
|
||||
| Alpha | `alpha` | `opacity/transparent/depthWrite` | alpha blend 时关闭 depth write |
|
||||
|
||||
材质选择高亮保存原始 emission 和强度,取消选择后恢复,不再破坏自发光材质。所有网格、
|
||||
实例和 LOD 都启用一致的 cast/receive shadow 标志。
|
||||
|
||||
## 4. 色彩、灯光和阴影
|
||||
|
||||
- Blender/SceneIR 数值按线性工作空间进入材质和灯光。
|
||||
- WebGL 输出固定为 `SRGBColorSpace`,tone mapping 固定为 `ACESFilmicToneMapping`。
|
||||
- `WorldIR.exposure` 按摄影 stop 转换为 `2 ** exposure`,并限制在 `[-8,8]`。
|
||||
- 无场景灯时使用低强度中性 Hemisphere fill 和有阴影的 key light,确保空场景可检查。
|
||||
- POINT、SUN、SPOT、AREA 均从 `LightIR` 创建。SUN/SPOT 根据 Blender 本地 `-Z`
|
||||
方向创建真实 Three target,不再错误地全部指向世界原点。
|
||||
- SUN、SPOT、POINT 使用 `PCFShadowMap`,第一质量档为 1024 平方 shadow map,并设置
|
||||
有界 bias、normal bias、near/far。AREA 受 Three WebGL 能力限制,当前不声明阴影等价。
|
||||
- 主线程与 Worker 暴露 `data-pbr-profile`、`data-tone-mapping` 和 `data-shadow-map`,供
|
||||
自动化测试核对真实后端配置。
|
||||
|
||||
## 5. 资产和纹理边界
|
||||
|
||||
当前 SceneIR 已表达 UV、Image Texture、Normal Map、packed image 和资源状态,但纹理像素
|
||||
进入 GPU 的链路必须继续遵守 EngineWorker/StorageWorker 权威模型。浏览器渲染器不得根据
|
||||
`.blend` 内路径自行访问文件系统或网络。
|
||||
|
||||
PBR-007 已建立 `GPUTextureAsset` 只读载荷:`assetId`、`imageId`、SHA-256、MIME、尺寸、
|
||||
颜色空间、用途、UDIM tile 和 `ArrayBuffer` 必须通过字节数、64 MiB 单图、16384 维度和
|
||||
SHA-256 校验后才可进入 `ImageBitmap`/Three `Texture`。主线程与 Offscreen Worker 共享同一
|
||||
`GPUTextureStore` 逻辑,载荷状态和拒绝字节数可观测;路径仍只能由 EngineWorker/StorageWorker
|
||||
解析,浏览器不得访问 `.blend` 内路径。当前不把 context-loss 自动恢复、mipmap/anisotropy
|
||||
策略和完整 UV Map 节点映射误报为完成。
|
||||
|
||||
## 6. 质量档和性能预算
|
||||
|
||||
| 档位 | 阴影 | DPR | 透射 | 目标 |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| Low | 关闭或 512 | 1 | 关闭 | 低内存移动设备 |
|
||||
| Medium | PCF 1024 | `min(device,1.5)` | 0.5 分辨率 | 默认移动/集显 |
|
||||
| High | PCF 1024/2048 | `min(device,2)` | 全分辨率 | 默认桌面 |
|
||||
|
||||
`physical-v1` 当前实现 High 的有界子集。后续自动降档的输入包括 GPU tier、draw call、
|
||||
transmission material 数、shadow caster 数、WASM/GPU 内存压力和帧时间 P95。质量切换只能
|
||||
改变表现质量,不得改变 Main 或保存语义。
|
||||
|
||||
## 7. 任务分解与执行顺序
|
||||
|
||||
### PBR-001 协议与安全门:done
|
||||
|
||||
- PBR-001-A:扩展 `MaterialIR` 五个物理参数,保持旧 snapshot 可解析。
|
||||
- PBR-001-B:对比例参数验证 `[0,1]`,对 emission strength 设硬上限。
|
||||
- PBR-001-C:扩展 `setMaterialPrincipled`,所有字段保持 optional 兼容旧客户端。
|
||||
- PBR-001-D:linked material 继续拒绝写回;NaN/Infinity 继续由 native 阻断。
|
||||
|
||||
### PBR-002 Blender Main authoring:done
|
||||
|
||||
- PBR-002-A:自建 Principled 节点补齐五个 Blender 5.2 socket。
|
||||
- PBR-002-B:命令写入 Base/Roughness/Metallic/IOR/Specular/Transmission/Coat/Emission。
|
||||
- PBR-002-C:native reader 从真实 socket 读取并生成 SceneIR。
|
||||
- PBR-002-D:Main round-trip 和 save/reopen 核对每个物理参数误差小于 `1e-5`。
|
||||
|
||||
### PBR-003 共享物理材质适配器:done
|
||||
|
||||
- PBR-003-A:用 `MeshPhysicalMaterial` 替代两条路径的 Standard/fixed material。
|
||||
- PBR-003-B:集中 clamp、默认值、透明深度策略和 selection emission 恢复。
|
||||
- PBR-003-C:主线程、Worker、实例和 LOD 使用同一映射。
|
||||
- PBR-003-D:Worker 恢复 UV、corner color 和多材质 triangle group。
|
||||
|
||||
### PBR-004 色彩管理和曝光:done
|
||||
|
||||
- PBR-004-A:线性输入、sRGB output、ACES Filmic。
|
||||
- PBR-004-B:World exposure 按 stop 映射并限制极端值。
|
||||
- PBR-004-C:通过 canvas profile 属性和像素非空门验证双后端。
|
||||
|
||||
### PBR-005 灯光和阴影:done_current_scope
|
||||
|
||||
- PBR-005-A:POINT/SUN/SPOT/AREA 类型映射。
|
||||
- PBR-005-B:修复 SUN/SPOT 方向 target。
|
||||
- PBR-005-C:SUN/SPOT/POINT PCF 阴影、bias 和 shadow camera 边界。
|
||||
- PBR-005-D:待补能量单位校准 fixture、级联太阳阴影、AREA 阴影替代和 caster budget。
|
||||
|
||||
### PBR-006 材质 Inspector:done_current_scope
|
||||
|
||||
- PBR-006-A:增加 IOR、Specular、Transmission、Coat、Coat Roughness、Emission Strength。
|
||||
- PBR-006-B:应用命令保留 alpha 和 emission color。
|
||||
- PBR-006-C:待补材质槽选择、emission color、alpha mode、双面和 blend mode 面板。
|
||||
|
||||
### PBR-007 纹理像素闭环:in_progress(AssetPayload/解码已完成,GPU 生命周期仍有安全门)
|
||||
|
||||
- PBR-007-A:done_current_scope;`render-assets.ts` 定义 schema v1、SHA-256、MIME/尺寸/字节预算和稳定错误码,App 从 `requestAsset` 生成载荷并同时写入 OPFS。
|
||||
- PBR-007-B:done_current_scope;Base Color/Emission 使用 sRGB,Normal/Data 使用 non-color/linear,主线程和 Worker 使用相同 `GPUTextureStore`。
|
||||
- PBR-007-C:in_progress;ImageBitmap 解码、旧 Texture dispose、状态回传已完成;mipmap、anisotropy、GPU context-loss 恢复和全局显存预算仍未开放。
|
||||
- PBR-007-D:Normal Map 切线空间、UV Map 选择、wrap/filter 和缺失纹理 fallback。
|
||||
- PBR-007-E:in_progress;双后端同一载荷正例已覆盖,context-loss/Worker crash 后重新上传仍属于 PBR-011 故障注入门。
|
||||
|
||||
### PBR-008 UDIM 与外部资源:in_progress(manifest/阻断已完成,多 tile 采样未声明)
|
||||
|
||||
- PBR-008-A:done_current_scope;`UDIMManifest` 校验 1001..1999、u/v 坐标、重复 tile、数量上限和 packed 状态;每个 tile 进入同一 SHA-256 载荷。
|
||||
- PBR-008-B:in_progress;当前只允许单 tile 安全上传,多 tile 返回 `UDIM_MULTI_TILE_UNAVAILABLE`,尚未实现分页、LRU 和 GPU atlas/array 采样。
|
||||
- PBR-008-C:done_current_scope;linked library、外部路径和缺 tile 使用结构化门,禁止任意路径读取。
|
||||
- PBR-008-D:done_current_scope;generated/sequence/movie 不生成静态 GPU 载荷,保持独立 capability。
|
||||
|
||||
### PBR-009 IBL 和 World Nodes:in_progress(有限 raster equirectangular IBL)
|
||||
|
||||
- PBR-009-A:in_progress;packed PNG/JPEG equirectangular 环境可经 GPU 载荷、PMREMGenerator 生成反射环境;HDR/EXR 解码尚未实现并返回 `IBL_FORMAT_UNSUPPORTED`。
|
||||
- PBR-009-B:in_progress;WorldIR 已携带 environment image/strength/rotation 字段,当前只消费 strength;旋转、跨场景缓存和完整 HDR 色域仍待安全门。
|
||||
- PBR-009-C:done_current_scope;`backgroundVisible` 与 `scene.environment` 生命周期分离,旧 PMREM target 会释放。
|
||||
- PBR-009-D:done_current_scope;任意 World Shader Node 不进入纹理上传,保持结构化阻断。
|
||||
|
||||
### PBR-010 GLB PBR 扩展:done_current_scope
|
||||
|
||||
- PBR-010-A:已导出 `KHR_materials_ior`、`transmission`、`clearcoat`、`specular`、`emissive_strength`,并保留无完整节点图时的有界 `imageIds` Base Color/Normal 路径。
|
||||
- PBR-010-B:桌面 Blender 再导入比较覆盖 8x8 packed texture、骨骼、shape key、动作和材质基础值。
|
||||
- PBR-010-C:不支持的 Blender 图返回 `SHADER_GRAPH_UNMAPPABLE`,禁止静默烘焙。
|
||||
- PBR-010-D:advanced extension fixture 已验证桌面 Blender 对 IOR、Specular IOR Level、Transmission、Coat 和 Emission Strength 的导入数值。
|
||||
|
||||
### PBR-011 性能、容错和跨浏览器:planned
|
||||
|
||||
- PBR-011-A:100k/1M 三角形下记录 CPU/GPU 帧时、draw call、shader compile 和显存。
|
||||
- PBR-011-B:Chromium 主线程/OffscreenCanvas 的 ACES、transmission 与 shadow 差异矩阵。
|
||||
- PBR-011-C:WebGL context loss、Worker crash、纹理解码失败和 GPU OOM 故障注入。
|
||||
- PBR-011-D:自动降档必须可观测且不修改权威数据。
|
||||
|
||||
### PBR-012 高级渲染:in_progress(能力查询/阻断协议,运行时家族仍未声明)
|
||||
|
||||
- PBR-012-A:done_current_scope;`queryRenderCapability` 明确返回 `WEBGPU_RENDERER_UNAVAILABLE`,没有 WebGPU renderer bundle 时不伪装为 WebGPU。
|
||||
- PBR-012-B:done_current_scope(安全门);BLOOM/SSAO/SSR/TAA/DOF/MOTION_BLUR 未有真实 pass 时返回 `POSTPROCESS_PASS_UNAVAILABLE`,未声明假实现。
|
||||
- PBR-012-C:done_current_scope(安全门);Volume/SSS 返回独立 `VOLUME_SHADER_UNAVAILABLE`/`SUBSURFACE_SHADER_UNAVAILABLE`,任意 Shader node 返回 `SHADER_NODE_UNSUPPORTED`。
|
||||
- PBR-012-D:浏览器 path tracer 若引入,作为独立 Render backend,不声称 Cycles 等价。
|
||||
|
||||
## 8. 当前验收
|
||||
|
||||
```bash
|
||||
source tools/web/emscripten-env.sh
|
||||
cmake --build build_web_blender6 --target web_engine -- -j8
|
||||
bash tools/web/install-web-engine-assets.sh
|
||||
npm --prefix web run typecheck
|
||||
npm --prefix web run lint
|
||||
npm --prefix web test
|
||||
npm --prefix web run test:authoring-roundtrip
|
||||
WEB_TEST_PORT=5209 npm --prefix web run test:e2e -- -g "PBR|Principled|local UV|packed raster|OffscreenCanvas"
|
||||
```
|
||||
|
||||
发布前还要运行完整 E2E、跨浏览器、GLB Blender round-trip 和离线包门。桌面与移动截图必须
|
||||
检查 canvas 非空、模型构图、材质高光/阴影可见、控件不遮挡以及页面无异常横向溢出。
|
||||
|
||||
## 9. 完成定义
|
||||
|
||||
一个 PBR 子任务只有在以下条件全部满足后才能标记 done:协议字段可验证;Main 可写;
|
||||
保存重开等价;主线程和 Worker 可渲染;资源可释放;错误稳定且结构化;至少一个正例和一个
|
||||
边界反例;桌面/移动像素与截图门通过;状态文档同步。仅识别 Blender socket、仅构造
|
||||
SceneIR 或仅显示 UI 控件都不构成完成。
|
||||
Reference in New Issue
Block a user