Add Chromium-only Blender WebEngine parity work

This commit is contained in:
mes123456
2026-08-12 04:47:48 -04:00
commit 9fd26010f6
18225 changed files with 11622124 additions and 0 deletions

View 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` | 线性 RGBalpha 独立处理 |
| 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-Dlinked material 继续拒绝写回NaN/Infinity 继续由 native 阻断。
### PBR-002 Blender Main authoringdone
- PBR-002-A自建 Principled 节点补齐五个 Blender 5.2 socket。
- PBR-002-B命令写入 Base/Roughness/Metallic/IOR/Specular/Transmission/Coat/Emission。
- PBR-002-Cnative reader 从真实 socket 读取并生成 SceneIR。
- PBR-002-DMain 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-DWorker 恢复 UV、corner color 和多材质 triangle group。
### PBR-004 色彩管理和曝光done
- PBR-004-A线性输入、sRGB output、ACES Filmic。
- PBR-004-BWorld exposure 按 stop 映射并限制极端值。
- PBR-004-C通过 canvas profile 属性和像素非空门验证双后端。
### PBR-005 灯光和阴影done_current_scope
- PBR-005-APOINT/SUN/SPOT/AREA 类型映射。
- PBR-005-B修复 SUN/SPOT 方向 target。
- PBR-005-CSUN/SPOT/POINT PCF 阴影、bias 和 shadow camera 边界。
- PBR-005-D待补能量单位校准 fixture、级联太阳阴影、AREA 阴影替代和 caster budget。
### PBR-006 材质 Inspectordone_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_progressAssetPayload/解码已完成GPU 生命周期仍有安全门)
- PBR-007-Adone_current_scope`render-assets.ts` 定义 schema v1、SHA-256、MIME/尺寸/字节预算和稳定错误码App 从 `requestAsset` 生成载荷并同时写入 OPFS。
- PBR-007-Bdone_current_scopeBase Color/Emission 使用 sRGBNormal/Data 使用 non-color/linear主线程和 Worker 使用相同 `GPUTextureStore`
- PBR-007-Cin_progressImageBitmap 解码、旧 Texture dispose、状态回传已完成mipmap、anisotropy、GPU context-loss 恢复和全局显存预算仍未开放。
- PBR-007-DNormal Map 切线空间、UV Map 选择、wrap/filter 和缺失纹理 fallback。
- PBR-007-Ein_progress双后端同一载荷正例已覆盖context-loss/Worker crash 后重新上传仍属于 PBR-011 故障注入门。
### PBR-008 UDIM 与外部资源in_progressmanifest/阻断已完成,多 tile 采样未声明)
- PBR-008-Adone_current_scope`UDIMManifest` 校验 1001..1999、u/v 坐标、重复 tile、数量上限和 packed 状态;每个 tile 进入同一 SHA-256 载荷。
- PBR-008-Bin_progress当前只允许单 tile 安全上传,多 tile 返回 `UDIM_MULTI_TILE_UNAVAILABLE`尚未实现分页、LRU 和 GPU atlas/array 采样。
- PBR-008-Cdone_current_scopelinked library、外部路径和缺 tile 使用结构化门,禁止任意路径读取。
- PBR-008-Ddone_current_scopegenerated/sequence/movie 不生成静态 GPU 载荷,保持独立 capability。
### PBR-009 IBL 和 World Nodesin_progress有限 raster equirectangular IBL
- PBR-009-Ain_progresspacked PNG/JPEG equirectangular 环境可经 GPU 载荷、PMREMGenerator 生成反射环境HDR/EXR 解码尚未实现并返回 `IBL_FORMAT_UNSUPPORTED`
- PBR-009-Bin_progressWorldIR 已携带 environment image/strength/rotation 字段,当前只消费 strength旋转、跨场景缓存和完整 HDR 色域仍待安全门。
- PBR-009-Cdone_current_scope`backgroundVisible``scene.environment` 生命周期分离,旧 PMREM target 会释放。
- PBR-009-Ddone_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-Dadvanced extension fixture 已验证桌面 Blender 对 IOR、Specular IOR Level、Transmission、Coat 和 Emission Strength 的导入数值。
### PBR-011 性能、容错和跨浏览器planned
- PBR-011-A100k/1M 三角形下记录 CPU/GPU 帧时、draw call、shader compile 和显存。
- PBR-011-BChromium 主线程/OffscreenCanvas 的 ACES、transmission 与 shadow 差异矩阵。
- PBR-011-CWebGL context loss、Worker crash、纹理解码失败和 GPU OOM 故障注入。
- PBR-011-D自动降档必须可观测且不修改权威数据。
### PBR-012 高级渲染in_progress能力查询/阻断协议,运行时家族仍未声明)
- PBR-012-Adone_current_scope`queryRenderCapability` 明确返回 `WEBGPU_RENDERER_UNAVAILABLE`,没有 WebGPU renderer bundle 时不伪装为 WebGPU。
- PBR-012-Bdone_current_scope安全门BLOOM/SSAO/SSR/TAA/DOF/MOTION_BLUR 未有真实 pass 时返回 `POSTPROCESS_PASS_UNAVAILABLE`,未声明假实现。
- PBR-012-Cdone_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 控件都不构成完成。