본문으로 건너뛰기
H

dsh-plugin-backdrop

huguangyu666/dsh-plugin-backdrop

DeepSeek Harness 插件:把官网 Harness 鲸鱼背景注入 dsh Web UI——WebGL2 流体 + 字符鲸鱼游动(循环接缝赛博朋克故障转场)+ 发光鱼群 + 点线网格。

설치

dsh plugin --profile web add github:huguangyu666/dsh-plugin-backdrop

README

dsh-plugin-backdrop — DeepSeek Harness 动态背景插件

把 DeepSeek Harness 官网 hero 的完整氛围(流体 + 平滑鲸鱼 + 发光鱼群 + 点线网格) 注入 dsh Web UI 作为动态背景。当前实现为混合渲染:

  • 流体背景沿用 WebGL2(原官网 GLSL 逆向)
  • 鲸鱼 / 鱼群使用 Canvas 2D 预渲染精灵,全分辨率平滑渲染
  • 点线网格沿用 Canvas 2D

完整技术原理见 docs/ARCHITECTURE.md; 新版 Canvas 渲染说明见 docs/CANVAS_RENDERING.md


目录


效果一览

截图:docs/screenshot.png(效果预览,可用浏览器 F12 对 3090 实例截图后放入)。

  • 流体背景:WebGL2 flowmap 双缓冲 + fbm/curl-noise 域扭曲,5 层深蓝-暖金渐变, 自发光 bloom + 虚拟光源(跟随鼠标 X)+ 颗粒噪点 + 暗角
  • 路径复刻鲸鱼:视频抽帧的游动动画(35 帧字符画,~6fps), 整只鲸鱼在界面里水平无缝漫游、上下呼吸浮动、气泡; 循环接缝赛博朋克故障:视频末帧与首帧不重合(循环重启会"拉回"), 在接缝瞬间自动打一个故障爆发(白闪 + RGB 色差 + 横条撕裂 + 品红残影 + 掉帧跳变 + 扫描线 + 噪点)把位置跳变盖住——曲线救国式赛博朋克转场
  • 发光鱼群:55 条预渲染平滑鱼形精灵(4 配色 × 6 帧尾摆), 鱼群中心弧线漫游,鱼在群内绕圈跟随;带转弯侧倾、呼吸缩放、深度透明、气泡
  • 点线网格:90px 点阵 + 邻点连线 + 鼠标波纹推开(canvas 2D)
  • UI 融入:dsh 页面级容器透明化(已知类名 + 全视口扫描 fallback), 强制 dsh 官方暗色主题保证文字可读性(实测对比度 9~19:1)
  • 性能:四层全部 30fps 节流 + 视口外停帧 + 静止自停 + dpr 上限 1.5

安装启用

先理解插件解析机制(盲测发现新用户卡在这): cordis.patch.yml / --patch 里的 name: 'dsh-plugin-backdrop' 会先尝试从 dsh 安装 解析,再从 profile 的 node_modules~/.dsh/profiles/web/node_modules)解析。 所以本地测试必须先把包放进该目录(下面第 1 步),否则启动会报 plugin not found

方式 A:本地源码开发(推荐,改代码立即生效)

前提:仓库源码在你机器上,例如 C:\Users\www13\Documents\AAA项目集\dsh-plugins\dsh-plugin-backdrop

  1. 链接到 profile(junction,指向源码目录;改源码 build 后无需重装):
    New-Item -ItemType Junction -Path "$env:USERPROFILE\.dsh\profiles\web\node_modules\dsh-plugin-backdrop" -Target "C:\Users\www13\Documents\AAA项目集\dsh-plugins\dsh-plugin-backdrop"
    
  2. 挂载到配置:编辑 ~/.dsh/profiles/web/cordis.patch.yml
    - insert:
        - id: backdrop
          name: 'dsh-plugin-backdrop'
    
  3. 重启 dsh web(重启会断开当前会话,挑空闲时操作),刷新页面。

方式 B:发布安装(插件已发 npm 时)

cd ~/.dsh/profiles/web
pnpm add dsh-plugin-backdrop
# 然后同样在 cordis.patch.yml 加 insert 片段,重启

快速预览(不动正式实例)

插件已按方式 A 链接好的前提下:

# 1. 建 overlay 文件(放哪都行,建议 profile 目录,命令里用绝对路径)
#    C:\Users\www13\.dsh\profiles\web\overlay-backdrop.yml 内容:
#    - insert:
#        - id: backdrop
#          name: 'dsh-plugin-backdrop'
# 2. 起预览实例
dsh --patch "C:\Users\www13\.dsh\profiles\web\overlay-backdrop.yml" --profile web --port 3090
# 3. 浏览器打开 http://127.0.0.1:3090/

注意:如果 cordis.patch.yml 已经包含 backdrop,不要再加 --patch, 否则报 duplicate loader entry id: backdrop。此时直接 dsh --profile web --port 3090 即可。


配置

配置存 localStorage['dsh-backdrop-config'](JSON)。首次加载用默认值; 通过 window.__backdrop.setConfig() 修改会自动持久化。

{
  "enabled": true,
  "opacity": 1,
  "layers": { "fluid": true, "whale": true, "fish": true, "grid": true },

  "fluid": {
    "glowIntensity": 0.07, "lightCore": 0.1, "lightHalo": 0.12,
    "vignette": 0.42, "interactive": false
  },

  "whale": {
    "density": 60, "spin": false, "loose": 1,
    "swim": true, "swimSpeed": 1.35, "swimTurn": 0.6,
    "light": { "x": 4.5, "y": 5.5, "z": 3, "range": 14, "shadeMin": 0.2, "shadeMax": 1.35, "followX": 1.05 },
    "mouse": { "radius": 4.9, "strength": 0.8, "decay": 0.2, "distort": 5 },
    "offsetRight": 0,
    "glitch": {
      "enabled": true, "burstWidth": 0.06, "intensity": 1,
      "rgbSplit": 26, "slices": 8, "maxShift": 56,
      "flash": true, "ghost": true, "flicker": true,
      "scanlines": false, "scanAlpha": 0.5, "sliceEdges": false,
      "noise": 0.5, "vBars": false
    }
  },

  "fish": {
    "count": 55, "density": 40, "scaleMin": 0.22, "scaleMax": 0.5,
    "speedBase": 2.6, "speedVary": 1.3,
    "schoolSpeed": 1.25, "schoolRadius": 6.0, "opacity": 0.95,
    "light": { "x": 4.5, "y": 5.5, "z": 3, "range": 14, "shadeMin": 0.3, "shadeMax": 1.5, "followX": 1.05 },
    "color": { "r": 0.62, "g": 0.82, "b": 1.0 }
  },

  "grid": { "lineOpacity": 0.06, "dotOpacity": 0.12 },

  "themeMode": "force-dark"
}

字段说明

字段含义备注
layers.*四层独立开关whalefish 可同时开
opacity背景层整体透明度0~1,聊天时调低可降存在感
fluid.interactive流体鼠标笔刷(flowmap)聊天场景必须 false,否则"一团光斑跟手"
fluid.glowIntensity鼠标光晕强度0 关闭
whale.swim是否让鲸鱼自由漫游false 时鲸鱼停在初始位置
whale.swimSpeed鲸鱼漫游速度系数默认 1.35,越大游得越快
whale.swimTurn鲸鱼转弯/漫游幅度默认 0.6
whale.glitch.enabled循环接缝赛博朋克故障开关false = 保留生硬接缝(还原旧行为)
whale.glitch.burstWidth故障爆发窗口(循环比例)默认 0.06 = 循环前后各 6%(≈±0.35s),峰值命中接缝
whale.glitch.intensity故障整体幅度主控0~1
whale.glitch.rgbSplitRGB 色差峰值(px)默认 26
whale.glitch.slices/maxShift横向切片数 / 位移峰值默认 8 / 56(切片越少越厚、切口越明显)
whale.glitch.flash接缝白闪默认开
whale.glitch.ghost品红残影错位默认开
whale.glitch.flicker掉帧/闪烁(坏帧跳变)默认开
whale.glitch.scanlines/scanAlpha扫描横线开关 / 强度默认关(嫌横线多),想开设 true
whale.glitch.sliceEdges切片分隔横线默认关(靠平移缺口已够明显),想开切块描边设 true
whale.glitch.noise噪点小方块强度0~1,默认 0.5
whale.glitch.vBarsCRT 竖条(满高竖线)默认 false(嫌竖线多,关掉);想开设 true
whale.density/light/mouse/offsetRight旧版 WebGL 瓦片参数新版 Canvas 渲染已不使用,保留仅为兼容旧配置
fish.count鱼数量默认 55 条
fish.scaleMin/Max鱼的大小比例相对视口尺寸,默认 0.22~0.5
fish.speedBase/Vary游动速度系数默认 2.6 / 1.3
fish.schoolSpeed鱼群中心漫游速度默认 1.25
fish.schoolRadius鱼群散布半径默认 6.0,越大鱼群越散
fish.opacity鱼群整体透明度默认 0.95
fish.density/light旧版瓦片参数新版 Canvas 渲染已不使用,保留仅为兼容旧配置
themeModeforce-dark 强制暗色 / follow 跟随用户主题force-dark 才能保证可读性

最小配置示例

只要鲸鱼、其他全关:

__backdrop.setConfig({
  layers: { fluid: false, whale: true, fish: false, grid: false },
  opacity: 0.8,
});

只要鱼群、鲸鱼也留:

__backdrop.setConfig({
  layers: { fluid: false, whale: true, fish: true, grid: false },
});

调试 API

浏览器 F12 控制台:

window.__backdrop.toggleLayer('whale', false)        // 关鲸鱼层
window.__backdrop.toggleLayer('fish', true)          // 开鱼群层
window.__backdrop.setOpacity(0.6)                    // 整体透明度
window.__backdrop.setConfig({                        // 实时调参(自动存 localStorage)
  whale: { swimSpeed: 2.2, glitch: { burstWidth: 0.08, noise: 0.8 } },
  fish: { count: 30, scaleMax: 0.8 },
  fluid: { interactive: true },                      // 想要"鼠标划出光痕"再开
});
window.__backdrop.config                            // 查看当前生效配置
window.__backdrop.dispose()                          // 卸载背景(还原主题与容器)

新版鲸鱼为字符帧动画(视频抽帧),src 换剪影仅旧版瓦片引擎支持、 现在无效;想调鲸鱼就调 whale.swim*whale.glitch.*。 手动爆一次故障:__backdrop 下的鲸鱼实例暴露 pokeBurst(),预览页有对应按钮。

whale.src 接受 Image.src 支持的格式:URL、data URI(如 data:image/svg+xml;utf8,...)。 换 src 会自动重新采样并重建瓦片,无需刷新。


工作原理

┌─ body
│  ├─ #root → dsh UI(容器透明化后透出背景)
│  └─ .backdrop-root(z-index:0,pointer-events:none)   ← 插件注入
│     ├─ canvas#fluid  流体背景(WebGL2,mask 底部渐隐)
│     ├─ canvas#whale  瓦片鲸鱼(Three.js,screen 混合,右移)
│     ├─ canvas#fish   瓦片鱼群(Three.js,screen 混合,全屏)
│     └─ canvas#grid   点线网格(canvas 2D,mask 渐隐)
  • 注入client-source.jsapply() 时向 body 插入背景容器 + 覆盖 CSS,不依赖 React
  • 透明化:硬编码 rc.6 类名(.pI_x6G_frame 等)+ transparentizeFullscreenSolids() 全视口扫描兜底(覆盖 ≥90% 视口且实底的容器置透明)
  • 主题:默认给 <body>data-ds-dark-theme(dsh 官方暗色属性), 组件级配色整体切暗、文字变白,可读性由 dsh 自己的样式保证; MutationObserver 在用户手动切主题时把属性挂回去
  • 可读性实测:新会话按钮 9.18:1 / 侧边栏 13.14:1 / 输入框 18.95:1(WCAG ≥4.5 达标)

详见 docs/ARCHITECTURE.md


常见问题 FAQ

Q: 字看不清 / 界面还是亮的? A: 确认 themeMode: "force-dark"(默认)。旧版本(强制文字 token 方案)会导致白字浅底, 已废弃。改配置后 location.reload()

Q: 鼠标拖着"一大坨光斑"跑? A: fluid.interactive 被设成了 true。设为 false(默认)并刷新。 官网在 Windows 上本来就默认关闭此交互。

Q: 鱼不像鱼 / 鱼在甩头? A: 确认 fish.density ≥ 30。旧版尾摆方向与鱼形相反(鱼头朝右但 shader 按尾巴在 +x 摆动), 已修复为 smoothstep(-4.5, -0.5, x)。还觉得丑就把 FISH_SVG 换成自己画的剪影(src/engine/fish-school.js)。

Q: 鲸鱼循环时"被拉回"一下? A: 这是视频抽帧动画的固有跳变(末帧与首帧位置不重合)。当前用接缝赛博朋克故障盖住它: 接缝瞬间自动白闪 + 色差 + 撕裂 + 噪点。如果不想要故障,把 whale.glitch.enabledfalse (会回到生硬拉回)。想调凶一点:whale.glitch = { maxShift: 90, rgbSplit: 44, noise: 0.9 }

Q: 想换成别的形状(logo、猫、狗)? A: 新版鲸鱼是视频抽帧的字符动画(帧内嵌在 src/engine/whale-ascii-frames.js), src 换剪影只对旧版瓦片引擎有效、现在无效。真想换形状要重新抽帧生成字符帧。 (旧版瓦片引擎备份在 src/engine/whale-engine.js,仍可换回。)

Q: 升级 dsh 后背景不显示了 / 容器又变白? A: dsh 的容器类名是 CSS Modules hash,升级可能变化。fallback 扫描会自动透明化全视口实底容器; 若失效,把新类名补进 client-source.js 的 CSS 覆盖列表。

Q: 想完全还原回默认界面? A: localStorage.removeItem('dsh-backdrop-config'); location.reload(), 再在 cordis.patch.yml 里删掉 backdrop 条目并重启。


开发指南

# 改代码后重新构建(产出 lib/index.js + lib/client.js)
node build.mjs

# 重启预览实例(两种情形二选一):
#   · cordis.patch.yml 已含 backdrop → 直接起
dsh --profile web --port 3090
#   · patch 未写入正式配置 → 用 overlay(见"安装启用 → 快速预览")
dsh --patch "C:\Users\www13\.dsh\profiles\web\overlay-backdrop.yml" --profile web --port 3090

# headless 验证注入状态(backdrop-root/canvas 数/容器透明/主题)
node verify-inject.mjs "http://127.0.0.1:3090/" out.png 25000

本地开发要点

  • 引擎在 src/engine/,全部 ESM、零框架依赖;client-source.js 负责注入与配置
  • client bundle 会把 three.js + 四引擎 + GLSL + 鲸鱼 SVG(dataurl) 全部内联(~780KB), 改引擎后必须 node build.mjs 再重启
  • 想加第五层:写引擎 → client-source.js 里创建 canvas + 启动 + 加进 toggleLayer map → build

踩坑记录

  1. setConfig 覆盖引用 bugObject.assign(cfg, patch) 会把 patch.light 整体覆盖 cfg.light 引用,导致 uLightPos = (NaN, undefined, z),鲸鱼变全透明但"看起来没渲染"。 必须逐字段合并(见 whale-engine.jssetConfig)。
  2. three.min.js(UMD)无法被 esbuild 打包导出import * as THREE 拿到空对象。 改用 npm three@0.150.1(纯 ESM)。
  3. 尾摆方向:官网 shader 假设尾巴在 +x;鱼形头朝右时尾摆反了(鱼甩头)。 fish 引擎里把 tail 因子替换为 smoothstep(-4.5, -0.5, x)
  4. light 模式可读性:强制文字 token 变白但组件背景仍是浅色 → 白字浅底看不清。 正确做法是挂 data-ds-dark-theme 让 dsh 自己的暗色样式接管。
  5. headless 验证:SwiftShader 下 readPixels 极慢且 present 后缓冲不可读; 用 CDP 截图 + DOM 计算(背景色/对比度)验证,别读像素。
  6. Windows 中文路径new URL(import.meta.url).pathname 是 percent-encoded, 静态服务器需 decodeURIComponent,否则 404。
  7. PowerShell 内联后台任务Start-Job 随调用进程退出被杀死;长驻进程 必须用工具的后台任务机制。
  8. 重复挂载报错 duplicate loader entry id: backdrop:cordis.patch.yml 和 --patch overlay 同时挂同一插件导致;二选一。

文件结构

dsh-plugin-backdrop/
├── package.json               # dsh.bundle.patch + dsh.client 声明
├── cordis.patch.yml           # 插件挂载片段
├── build.mjs                  # esbuild 打包(host ESM + client CJS 包装)
├── README.md                  # 本文档
├── docs/
│   ├── ARCHITECTURE.md        # 架构与技术原理(含旧版瓦片逆向记录)
│   └── CANVAS_RENDERING.md    # 新版 Canvas 鲸鱼/鱼群渲染说明
├── verify-inject.mjs          # headless 验证工具(注入状态 + 截图)
├── probe-*.mjs                # 调试探针(对比度/鱼群/交互开关)
└── src/
    ├── index.js               # host 端(挂载点,预留配置服务)
    ├── client-source.js       # client 端:DOM 注入 + 透明化 + 主题联动 + 配置
    ├── hero-whale.svg         # 官网原版鲸鱼剪影
    └── engine/
        ├── whale-canvas.js        # 字符动画鲸鱼 + 循环接缝赛博朋克故障(当前)
        ├── whale-ascii-frames.js  # 视频抽帧的鲸鱼字符帧数据(35 帧)
        ├── whale-video-paths.js   # 从视频提取的鲸鱼关键帧轮廓数据
        ├── fish-canvas.js         # 新版 Canvas 发光鱼群(预渲染精灵)
        ├── fluid-background.js    # 流体背景(WebGL2 flowmap 双缓冲)
        ├── grid-background.js     # 点线网格(canvas 2D)
        ├── fluid-shaders.js       # 流体 GLSL(官网 page chunk 原样提取)
        ├── whale-engine.js        # 旧版瓦片鲸鱼(保留,未使用)
        ├── fish-school.js         # 旧版瓦片鱼群(保留,未使用)
        └── shaders.js             # 旧版瓦片 shader(保留,未使用)

已知限制

  • UI 容器类名是 CSS Modules hash(rc.6 硬编码),dsh 升级后可能失效; fallback 扫描兜底,极端情况下可能误伤全屏弹层(有白名单可调)
  • force-dark 会覆盖用户手动选择的亮色主题(可在设置里改 themeMode: "follow",但亮色下背景融入效果差)
  • 鱼群共享几何导致每条鱼内部瓦片抖动相位一致(mesh 级尾摆仍有差异), 追求个体差异可改为每鱼独立几何
  • 官网原版在 Windows 上默认关鼠标扰动;本插件流体笔刷默认关闭,鲸鱼/网格交互保留

逆向来源

  • deepseek.com/harness → chunk 776.7b3219fa93f8a656.js(HeroDigitileR3F 瓦片鲸鱼)
  • deepseek.com/harness → page chunk u 组件(WebGL2 流体)、m 组件(点线网格)
  • 完整逆向过程与独立 demo:见同仓库 whale-demo/(浏览器直接打开可玩)

관련 플러그인