Files
workinf_Blender_Wasm/docs/status/WEB_UI_PBR_20261111.md
mes123456 d1e6b63d54
Some checks failed
M6 deployable RC / quick (push) Has been cancelled
M6 deployable RC / chromium (push) Has been cancelled
M6 deployable RC / release (push) Has been cancelled
chore: checkpoint web Blender feature-gap work, docs and tests
- update native web_engine sources and rebuilt wasm artifacts
- add task cards, status notes and tooling scripts
- add web e2e specs, tutorial UI sources and tutorial assets
- sync golden task manifests and audit records

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-11-11 10:46:55 +08:00

7.6 KiB
Raw Blame History

Web UI 对标 + PBR 真实案例实现状态(2026-11-11)

  • 状态:in_progress(实现证据,不宣称验收)
  • 范围:Outliner React treeview、着色器编辑器 React Flow、真实 PBR 资产链路与色彩管理
  • 验收:NOT_CLAIMED

已实现

Outliner

  • 新增 web/app/src/app/ui/OutlinerTreeView.tsx、outliner-tree-data.ts、outliner-tree.css。
  • 使用 react-accessible-treeview@2.11.2 渲染原生 tree.rows;保留选择、展开、拖放 payload、重命名、Remap、可见性、截断提示。
  • App.tsx 原生行渲染改为 treeview renderRow,并保留 role="treeitem" 可访问名、data-node-id/data-active、.tree-node-name、展开按钮可访问名。
  • 修复 treeview 受控展开反馈环:不再由库自动触发 OUTLINER_TOGGLE_EXPAND,仅用户按钮/键盘触发。

着色器编辑器(React Flow)

  • 新增 web/app/src/app/ui/ShaderNodeCanvas.tsx、ShaderNode.tsx、shader-flow-adapter.ts、shader-node-catalog.ts、shader-node.css。
  • WasmShaderEditor.tsx 画布主体切换到 @xyflow/react@12.12.1:
    • 节点拖动 → MOVE
    • 端口拖拽 → LINK,边删除 → UNLINK
    • 节点内 socket 编辑 → SET_SOCKET
    • Shift+A / 工具栏添加节点 → ADD
    • 节点属性(Mix data/blend、Mapping vector type、Normal Map space、Bump invert、UV Map 名称)→ SET_PROPERTY
    • Image Texture 换图 → SET_IMAGE
    • 只读链接材质、revision 冲突、未知节点占位、全部端口折叠。
  • 坐标约定 position={x, -y};读回 fromSocket/toSocket 与命令 fromSocketId/toSocketId 由适配器唯一转换。
  • SSE/React Flow 要求:CSP 增加 style-src-attr 'unsafe-inline',脚本/Worker 仍严格;去掉 attribution 隐藏。

原生读回与编辑

  • web_engine_blend_reader.cpp:节点类型补齐 MIX/MAPPING/TEX_COORD/UV_MAP/BUMP/SEPARATE_COLOR/OBJECT_INFO;socket available/hidden;节点属性(dataType/blendType/vectorType/space/invert/projection/interpolation/extension/uvMap/mode);材质 textureBindings;normalImageId 真正赋值;Image colorSpace 读取(当前资产未返回,见残余)。
  • web_engine_main_state.cpp:editShaderNode 新增 SET_PROPERTY/SET_IMAGE,ADD 支持 UV_MAP/OBJECT_INFO/SEPARATE_COLOR;setShaderGraph 类型扩展并按 socket identifier 绑定(修复 Mix 同名 socket)。
  • 新增 packImage:外部 PNG/JPEG 字节直接打包进已有 Image,保留节点链接,允许 0 尺寸由调用方按文件头提供。
  • 新增 assignMaterialSlot:把已有材质装入对象槽(BKE_object_material_slot_add + BKE_object_material_assign),属性面板材质槽下拉已接入。
  • web_engine_api.cpp、web/protocol/web-engine.ts、web-engine.worker.ts、web-engine-capabilities.ts 同步命令。

PBR 显示

  • three-adapter/pbr.ts:按场景 colorManagement.viewTransform 选择 AgX/Standard/Neutral/ACES;toneMappingExposure = 2 ** exposure;data-tone-mapping 场景驱动。
  • three-adapter/texture-assets.ts:应用 map、normalMap+strength、metalnessMap、roughnessMap、emissiveMap、alphaMap、bumpMap;贴图驱动时中性化 factor。
  • texture-assets.applyEnvironment 使用 WorldIR.environmentRotation。
  • render-assets.ts 纹理用途扩展;scene-ir.ts 校验新节点类型/属性/textureBindings。
  • 外部贴图 UI:着色器编辑器“外部贴图”列表;文件先 StorageClient.putAsset 写入 OPFS,再 packImage;项目保存继续走 StorageClient.saveProject(OPFS)。

Chromium 实测(手动探针,实现证据)

  • tests/files/web/m12_glb_main_v1/pbr.blend:Outliner 树、React Flow 2 节点/1 连线;拖动、连线、断开、改 Roughness、添加 Mapping 均发出正确原生命令;保存后重开 Roughness=0.7、Mapping 位置/连线保留;Ctrl+Z / Ctrl+Shift+Z 恢复 0.28 / 0.7。
  • blender-5.2.0/tests/files/io_tests/blend_geometry/materials_pbr.blend:ImageTexture/Principled 读回;三张外部 PNG 经 OPFS→packImage 变为 PACKED;viewport 显示红/金属黑 PBR 立方体;data-tone-mapping 场景驱动。
  • cubes_with_textures.blend:读回 MAPPING/UV_MAP/SEPARATE_COLOR/IMAGE_TEXTURE;textureBindings 含 BASE_COLOR/ROUGHNESS/NORMAL/EMISSION,normalImageId 已赋值。
  • user-testing/WEB_Blender_Robot_Tool_20260916/outputs/robot-project.blend:18 对象、7 个 link 材质;着色器材质列表可见。

Playwright 用例

  • web/tests/e2e/outliner-treeview-production.spec.ts:通过。
  • web/tests/e2e/shader-editor-flow-production.spec.ts:通过(headless 合成指针的节点拖动不稳定,拖动由手动 Chromium 探针覆盖;其余连线/删除/添加/参数/保存重开在用例内)。
  • web/tests/e2e/pbr-real-assets-production.spec.ts:通过。三张外部 PNG 在 Web UI(?ui=web)下经 OPFS→packImage 打包,SceneIR 依次 r7/r10/r13,外部贴图列表清空。
  • 三条用例合并运行:3 passed (37.3s)。
  • 注意:测试使用 ?ui=web(React UI 模式)以避免 headless SwiftShader 下原生 GPU 节点编辑器绘制抛 WASM_INIT_FAILED;这不是 React UI 路径的缺陷。

残余缺口

  1. Image colorSpace 未从 .blend 读出(undefined);当前按纹理用途推断 sRGB/Non-Color,颜色贴图默认正确,非默认色彩空间未覆盖。
  2. robot-project.blend 保存工作区中 Outliner 深层的展开按钮发送选择而非 OUTLINER_TOGGLE_EXPAND;pbr.blend/basic_scene.blend 展开正常。需继续定位该工程的 workspace/area 映射。
  3. Headless Playwright 合成鼠标拖动 React Flow 节点不稳定;真实 Chromium 手动拖拽正常。
  4. Compositor 原生 setCompositorNodeGraph 仍未实现;Geometry Nodes 尚未复用 React Flow 画布。
  5. 非 Principled BSDF(Glass/Hair/Anisotropic 等)、Subsurface/Volume/UDIM/HDRI 仍按 capability block 或后续批次处理。
  6. 本轮未运行全量回归、未生成正式 candidate receipt;构建哈希与证据需在后续批次绑定。

构建与构件

  • 原生:cmake --build build_web_blender6 --target web_engine -- -j8
  • 同步:node tools/web/sync-web-engine-runtime.mjs
  • 前端:cd web && npm run build
  • web_engine.wasm SHA-256:84fc21e7728b580579424f97495d27275d30c01f2898ccadf4e368ea37d646ea(与 web/app/src/vendor/blender/web_engine.wasm 一致)
  • web/dist/index.html SHA-256:d36f002b7793b7684f3ac570537bd33527143a6ea64fb43b3dabff0d3d313a8e

CSP 与样式加载

  • React Flow 需要内联 style 属性;部署 CSP 改为 style-src 'self'; style-src-attr 'unsafe-inline',脚本/Worker 指令保持严格。
  • React Flow 与新增组件 CSS 通过 web/app/index.html 的同源 <link> 引入(ui/xyflow.css、ui/outliner-tree.css、ui/shader-node.css),避免 Vite dev 的内联 <style> 注入被 CSP 阻断;生产构建提取为 CSS 文件。
  • tools/web/check-csp-policy.mjs 已改为仅对脚本/Worker 指令拒绝 'unsafe-inline',并断言 style-src-attr 的最小放宽。既有 tests/golden/M13-05A/csp-report.json 需在后续验收批次重新生成。

OPFS 资产策略

  • 渲染用 packed 图像:cachePackedAssets 在每次快照后通过 StorageClient.putAsset 写入 OPFS。
  • 外部贴图:用户选择文件后先 putAsset(OPFS),再 packImage 进工程;项目保存走 StorageClient.saveProject(OPFS)。
  • 打开工程时提供的库 .blend 文件在 openBlend 前写入项目 OPFS(application/x-blender)。
  • 资产库/OBJ/多分辨率/VDB 等既有导入路径继续使用 putAsset。