dsh-shadertoy-skin 0.2.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,8 +8,10 @@
8
8
 
9
9
  Realtime [ShaderToy](https://www.shadertoy.com/) background skin for DeepSeek Harness (desktop & web): a zero-runtime-dependency WebGL2 player, a background library, and a translucent glass shell.
10
10
 
11
- > **推荐去 [www.shadertoy.com](https://www.shadertoy.com/) 逛逛** —— 插件自带的三个作品只是开胃菜。ShaderToy 上有几万个社区作品(搜 `background`、`seascape`、`raymarching` 这类关键词,或在 Browse 里按分类翻),挑喜欢的装进「背景库」、按自己的口味调亮度 / 速度 / 代码,就是一张专属桌面。
12
- > **改好了欢迎分享**:截图、参数、改进思路都可以提到 [Issues](https://github.com/zdjmrq/dsh-shadertoy-skin/issues),或者直接 PR(作品代码要看原作者的许可证,默认 CC BY-NC-SA 3.0:署名、非商业、同样方式共享;本仓库本身只收录 MIT 代码)。
11
+ > **推荐去 [www.shadertoy.com](https://www.shadertoy.com/) 逛逛** —— 插件自带的 5 个预设只是开胃菜。ShaderToy 上有几万个社区作品(搜 `background`、`seascape`、`raymarching` 这类关键词,或在 Browse 里按分类翻),挑喜欢的装进「背景库」、按自己的口味调亮度 / 速度 / 代码,就是一张专属桌面。
12
+ > **改好了欢迎分享**:截图、参数、改进思路都可以提到 [Issues](https://github.com/zdjmrq/dsh-shadertoy-skin/issues),或者直接 PR(作品代码要看原作者的许可证,默认 CC BY-NC-SA 3.0:署名、非商业、同样方式共享;本仓库自写代码是 MIT,两个第三方预设按各自许可证收录)。
13
+ > **欢迎 issue 和 PR**:装不上、画面不对、想要新功能 → 开 [Issue](https://github.com/zdjmrq/dsh-shadertoy-skin/issues)(附截图和 `$DSH_HOME/shader-skin.json` 里对应条目更好排查);bug 修复、文档修正、自写预设 → 直接提 [PR](https://github.com/zdjmrq/dsh-shadertoy-skin/pulls)。
14
+ > **欢迎分享你发现的 / 自己改过的 ShaderToy 作品**:作品链接、截图、调好的参数都行,开 [Issue](https://github.com/zdjmrq/dsh-shadertoy-skin/issues) 贴出来大家就能直接用;想让它进内置预设就提 PR(先确认原作者的许可证允许再分发)。
13
15
  >
14
16
  > **Recommended: browse [shadertoy.com](https://www.shadertoy.com/)** — import any piece into the background library, tune it to your taste, and feel free to share screenshots, settings or improvements via Issues / PRs.
15
17
 
@@ -19,12 +21,12 @@ https://github.com/user-attachments/assets/c8801ca1-e96e-4bfe-83bc-6e99b5551cf4
19
21
 
20
22
  https://github.com/user-attachments/assets/001acdf6-90e2-4b2c-85fc-e9d076678597
21
23
 
22
- *演示 2 · [Seascape](https://www.shadertoy.com/view/Ms2SD1)(© TDM,CC BY-NC-SA 3.0)的个人修改版:摄像机抬到近地轨道,只留海面*
24
+ *演示 2 · [Seascape](https://www.shadertoy.com/view/Ms2SD1)(© TDM,CC BY-NC-SA 3.0)的个人修改版:摄像机抬到近地轨道,只留海面 —— 已作为内置预设「海面(Seascape)」随插件提供*
23
25
 
24
26
  ![马里奥像素画背景](https://raw.githubusercontent.com/zdjmrq/dsh-shadertoy-skin/main/docs/verify/readme-mario.jpg)
25
27
  ![代码页:查看 / 修改 / 保存并运行当前作品的着色器](https://raw.githubusercontent.com/zdjmrq/dsh-shadertoy-skin/main/docs/verify/readme-code.jpg)
26
28
 
27
- > 视频与截图里的 ShaderToy 作品版权归原作者:像素马里奥(作者见对应作品页)、Seascape(© TDM,CC BY-NC-SA 3.0)。**视频与截图仅作效果展示**,本仓库代码仍是 MIT,且不收录这些作品代码。
29
+ > 视频与截图里的 ShaderToy 作品版权归原作者:像素马里奥「Mario」(© Inigo Quilez)、Seascape(© Alexander Alekseev aka TDM),两者均以 **CC BY-NC-SA 3.0** 收录为内置预设(非 MIT,见文末许可证)。**视频与截图仅作效果展示**,插件自写代码仍是 MIT。
28
30
 
29
31
  ## 名字 / 包名(认准这两个)
30
32
 
@@ -41,10 +43,10 @@ npm view dsh-shadertoy-skin version # 确认 npm 上真实存在的版本
41
43
 
42
44
  ## 从 ShaderToy 装一个作品
43
45
 
44
- 插件自带三个 MIT 自写着色器,但真正好玩的是把你喜欢的 ShaderToy 作品装进来。**三种做法,任选一种:**
46
+ 插件自带 5 个预设(3 个自写 MIT + 2 个第三方 CC BY-NC-SA 3.0,见文末许可证),但真正好玩的是把你喜欢的 ShaderToy 作品装进来。**三种做法,任选一种:**
45
47
 
46
48
  > **推荐一试**:[`shadertoy.com/view/4dfXWj`](https://www.shadertoy.com/view/4dfXWj) —— 装进来效果挺带感,导入方式见下面任意一种。
47
- > 这只是个起点:**大家完全可以根据自己的喜好随便挑别的作品,也可以自己写着色器**(写好了走同样的导入流程)。ShaderToy 作品的许可证由原作者决定(默认 CC BY-NC-SA 3.0),装在本机自己玩没问题,但别把作品代码提交进仓库或随包再分发。
49
+ > 这只是个起点:**大家完全可以根据自己的喜好随便挑别的作品,也可以自己写着色器**(写好了走同样的导入流程)。ShaderToy 作品的许可证由原作者决定(默认 CC BY-NC-SA 3.0):装在本机自己玩没问题;想提交进仓库或随包分发,先确认许可证允许,并带上署名与相同许可证(本仓库的两个第三方预设就是这么收录的)。
48
50
 
49
51
  ### 1. 粘贴代码(最稳,不用抓网页)
50
52
 
@@ -133,6 +135,7 @@ $DSH_HOME/shader-skin/presets/ (Windows 默认 C:\Users\<你>\.dsh\shad
133
135
  - [x] **画面循环**:有些作品播一次就停住,可设周期把 `iTime` 归零重播(只重置画面)
134
136
  - [x] 设置页配色改用 **DSH 品牌蓝**(亮色 `#3568dc` / 暗色 `#7aaaff`),小字号数值也清楚
135
137
  - [x] **背景库**:内置 + 我的背景列表、切换、改名、删除;粘贴代码导入、文件导入(ShaderToy JSON / GLSL)、从 `$DSH_HOME/shader-skin/presets/` 导入
138
+ - [x] **随包 5 个预设**:自写的「极光 / 流体色带 / 脉冲」(MIT)+ 第三方「海面(Seascape)」「马里奥」(CC BY-NC-SA 3.0,署名/非商业/相同方式共享,背景库和下拉里带 `CC BY-NC-SA` 标)
136
139
  - [x] **代码页**:查看当前运行作品的 Image / Sound 源码,直接改 → **保存并运行**(内置作品会自动另存为「我的副本」,原件不动;编辑器里 Ctrl/⌘+S 同样保存)
137
140
  - [x] **iMouse 只在「按住左键 + 从空白处开始拖动」时驱动**:点按钮、拖滚动条、选中/复制回复文字都不会再带动背景;松手发一次释放(`iMouse.z < 0`)
138
141
  - [x] **卡片透明度三档**(不透明 / 半透明 / 透明):控制卡片、代码块、弹层、输入框、聊天输入栏的底色,让背景能透进这些「框」里
@@ -235,9 +238,21 @@ dsh plugin --profile web add dsh-shadertoy-skin@latest
235
238
 
236
239
  ## 预设与许可证(重要)
237
240
 
238
- - 随包只有**自写**的 MIT 着色器,**不包含任何 ShaderToy 作品代码**。
239
- - ShaderToy 作品默认受 **CC BY-NC-SA 3.0**(作者未另行声明时)保护,**不能**随 MIT 包再分发。自己收藏/自用没问题,但别把作品代码提交到 git、别打进要发布的包。
240
- - 「我的背景」只存在本机 `$DSH_HOME/shader-skin.json`,不会上传。
241
+ 随包预设分两类(完整清单见 [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md)):
242
+
243
+ | 预设 | 来源 | 许可证 |
244
+ |---|---|---|
245
+ | `极光` / `流体色带` / `脉冲(带音乐)` | 本项目自写 | **MIT**(可商用、随便改) |
246
+ | `海面(Seascape)` | [Seascape](https://www.shadertoy.com/view/Ms2SD1),© Alexander Alekseev aka TDM | **CC BY-NC-SA 3.0**(非 MIT) |
247
+ | `马里奥(带音乐)` | [Mario](https://www.shadertoy.com/user/iq),© Inigo Quilez | **CC BY-NC-SA 3.0**(非 MIT) |
248
+
249
+ 两个第三方作品是**按上游许可证收录的**(上游允许再分发),所以:
250
+
251
+ - **署名**:保留作者与许可证声明(文件头、`presets/index.json`、背景库里的红色 `CC BY-NC-SA` 标记);
252
+ - **非商业**:这两个 shader 不能用于商业用途。要把这个插件用于商业产品,请先删掉 `native-dist/presets/seascape.glsl`、`mario.glsl`、`mario-sound.glsl`(或只保留自写预设);
253
+ - **相同方式共享**:改过的版本再分发时仍要留在 CC BY-NC-SA 3.0 下。设置页「代码」里另存的「我的副本」同样受这个约束。
254
+
255
+ 其余从 ShaderToy 导入的作品(默认 CC BY-NC-SA 3.0,作者可另行声明)**只存在本机** `$DSH_HOME/shader-skin.json`,不会上传,也不会进包;想把自己的修改提交进仓库/随包分发,先确认许可证允许,并带上署名与相同的许可证。
241
256
 
242
257
  ## 开发
243
258
 
@@ -273,13 +288,21 @@ native-dist/
273
288
  player.html 零依赖 WebGL2 播放器(渲染 + 滤镜 + mainSound 音频)
274
289
  panel.html 设置页(参数 / 背景库 / 代码,深浅色自适应)
275
290
  defaults.json 全部默认参数(改这里就改默认值)
276
- presets/*.glsl 随包 MIT 着色器 + `pulse-sound.glsl`
291
+ presets/*.glsl 随包预设:3 个自写 MIT + 2 个第三方 CC BY-NC-SA 3.0(`seascape` / `mario`)
277
292
  presets/dev/ 测试夹具(不进 npm 包)
278
293
  locale/ icon.svg 插件管理器展示资源
279
294
  tools/ 开发服务器 / 包检查 / 渲染冒烟 / 音频冒烟 / 实机检查
295
+ THIRD-PARTY-NOTICES.md 第三方作品的作者 / 来源 / 许可证清单
280
296
  .github/workflows/ CI + npm 发布(OIDC trusted publishing)
281
297
  ```
282
298
 
299
+ ## 参与(issue / PR 都欢迎)
300
+
301
+ - **报问题**:直接[开 Issue](https://github.com/zdjmrq/dsh-shadertoy-skin/issues)。附上 DSH 版本、系统/显卡、截图,以及 `$DSH_HOME/shader-skin.json` 里对应预设的条目(贴之前先删掉不想公开的内容);播放器自己的诊断行也能帮大忙。
302
+ - **提改进**:bug 修复、文档修正、新的自写预设都欢迎 [PR](https://github.com/zdjmrq/dsh-shadertoy-skin/pulls)。自写预设请标 MIT;第三方作品要带作者与许可证(参考 [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md))。
303
+ - **分享 ShaderToy 作品**:发现了特别适合当聊天背景的作品,或者自己把它改得更好看、更省电(比如调机位、修 NaN、降负载),都欢迎[开 Issue](https://github.com/zdjmrq/dsh-shadertoy-skin/issues) 贴作品链接 + 截图 + 参数。想让它变成内置预设就提 PR:自写的标 MIT,第三方作品带作者与许可证(参考 [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md))。
304
+ - **分享你的背景**:装了什么作品、参数怎么调的,开 Issue 贴截图就行。
305
+
283
306
  ## License
284
307
 
285
- [MIT](LICENSE)。第三方着色器代码的许可证由其作者决定,本仓库不收录。
308
+ [MIT](LICENSE) 适用于插件代码与三个自写预设。**随包的两个第三方作品(`seascape` / `mario`)不是 MIT**,它们按上游的 [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) 收录,署名见文件头与 [`THIRD-PARTY-NOTICES.md`](THIRD-PARTY-NOTICES.md)。
@@ -0,0 +1,33 @@
1
+ # Third-party notices
2
+
3
+ This repository and the npm package `dsh-shadertoy-skin` contain code under two
4
+ different licences:
5
+
6
+ - **The plugin itself** (`index.js`, `client.js`, `native-dist/player.html`,
7
+ `native-dist/panel.html`, `native-dist/defaults.json`, `tools/`, and the
8
+ self-written presets `aurora` / `flow` / `pulse`) is **MIT** — see `LICENSE`.
9
+ - **Two bundled ShaderToy works** are **CC BY-NC-SA 3.0** and are **not MIT**.
10
+ They are included as ready-to-use presets, with attribution, because the
11
+ upstream licences allow redistribution (non-commercially, share-alike).
12
+
13
+ ## Bundled presets with third-party licences
14
+
15
+ | preset id | work | author | source | licence | changes |
16
+ |---|---|---|---|---|---|
17
+ | `seascape` | "Seascape" (2014) | Alexander Alekseev aka TDM | <https://www.shadertoy.com/view/Ms2SD1> | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) | desktop-background modifications plus verifiable performance work and fixes: sky early-out, bounded regula-falsi tracing (32→16 steps), integer-hash noise, `pow(max(color, 0.0))` NaN fix, specular base clamp, dithering. Details in the file header. |
18
+ | `mario` + `mario-sound` | "Mario" (2014) | Inigo Quilez (iq) | <https://www.shadertoy.com/user/iq> | [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/) | bundled as a preset as-is (pixel art + one music piece). |
19
+
20
+ What **CC BY-NC-SA 3.0** means for these two files:
21
+
22
+ - **Attribution** — credit the authors (TDM / Inigo Quilez) and keep the licence notice.
23
+ - **NonCommercial** — you may not use these two shaders for commercial purposes.
24
+ If you want to use this plugin commercially, delete `native-dist/presets/seascape.glsl`,
25
+ `native-dist/presets/mario.glsl` and `native-dist/presets/mario-sound.glsl`
26
+ (or ship your own MIT shaders only).
27
+ - **ShareAlike** — if you redistribute modified versions of these shaders, they
28
+ must stay under CC BY-NC-SA 3.0.
29
+
30
+ Everything you import yourself from ShaderToy stays on your machine
31
+ (`$DSH_HOME/shader-skin.json` / `$DSH_HOME/shader-skin/presets/`); it is never
32
+ uploaded and never shipped in this package. ShaderToy works are CC BY-NC-SA 3.0
33
+ unless the author states otherwise.
@@ -209,6 +209,7 @@
209
209
  .item .name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
210
210
  .item .badge { flex: 0 0 auto; font-size: 9px; color: var(--faint); border: 1px solid var(--line); border-radius: 999px; padding: 0 6px; line-height: 16px; }
211
211
  .item .badge.sound { color: var(--accent); border-color: var(--accent); }
212
+ .item .badge.nc { color: var(--danger); border-color: var(--danger); }
212
213
  .item .tools { display: flex; gap: 4px; flex: 0 0 auto; }
213
214
  .import-box { border: 1px dashed var(--line); border-radius: 10px; padding: 10px; margin-top: 10px; }
214
215
  .import-box h2 { margin: 0 0 8px; font-size: 11px; letter-spacing: .06em; color: var(--muted); font-weight: 500; }
@@ -519,7 +520,12 @@
519
520
  return entryById(state.activeId) ? Boolean(preset.code?.sound) : Boolean(preset.hasSound)
520
521
  }
521
522
  const presetOptions = () => [
522
- ...manifest.map(item => ({ value: item.id, text: item.name || item.id, kind: '内置' })),
523
+ ...manifest.map(item => ({
524
+ value: item.id,
525
+ text: item.name || item.id,
526
+ // bundled ShaderToy works keep their own licence; surface it right in the picker
527
+ kind: item.license && item.license !== 'MIT' ? `内置 · ${item.license}` : '内置',
528
+ })),
523
529
  ...state.entries.map(item => ({ value: item.id, text: item.name || item.id, kind: '我的' })),
524
530
  ]
525
531
  const textOfPreset = option => `${option.text}${option.kind ? ` · ${option.kind}` : ''}`
@@ -834,8 +840,8 @@
834
840
  function renderLibrary() {
835
841
  const list = $('lib-list')
836
842
  const rows = [
837
- ...manifest.map(item => ({ id: item.id, name: item.name || item.id, kind: '内置', sound: Boolean(item.hasSound), entry: null })),
838
- ...state.entries.map(item => ({ id: item.id, name: item.name, kind: '我的', sound: Boolean(item.code?.sound), entry: item })),
843
+ ...manifest.map(item => ({ id: item.id, name: item.name || item.id, kind: '内置', license: item.license, sound: Boolean(item.hasSound), entry: null })),
844
+ ...state.entries.map(item => ({ id: item.id, name: item.name, kind: '我的', license: null, sound: Boolean(item.code?.sound), entry: item })),
839
845
  ]
840
846
  list.replaceChildren(...rows.map(row => {
841
847
  const name = el('span', { className: 'name' })
@@ -843,6 +849,12 @@
843
849
  name.title = row.name
844
850
  const badge = el('span', { className: 'badge' })
845
851
  badge.textContent = row.kind
852
+ // Third-party presets must not look MIT: flag the licence on the row.
853
+ const foreign = Boolean(row.license && row.license !== 'MIT')
854
+ const licence = el('span', { className: 'badge nc' })
855
+ licence.textContent = foreign ? 'CC BY-NC-SA' : ''
856
+ licence.hidden = !foreign
857
+ licence.title = foreign ? `第三方作品:${row.license}(署名 / 非商业 / 相同方式共享),不是 MIT` : ''
846
858
  const sound = el('span', { className: 'badge sound' })
847
859
  sound.textContent = row.sound ? '有声' : ''
848
860
  sound.hidden = !row.sound
@@ -882,7 +894,7 @@
882
894
  })
883
895
  tools.append(rename, remove)
884
896
  }
885
- return el('div', { className: `item${state.activeId === row.id ? ' active' : ''}` }, name, sound, badge, tools)
897
+ return el('div', { className: `item${state.activeId === row.id ? ' active' : ''}` }, name, sound, licence, badge, tools)
886
898
  }))
887
899
  }
888
900
 
@@ -1023,7 +1035,9 @@
1023
1035
  $('code-title').textContent = name
1024
1036
  $('code-hint').textContent = `${editable
1025
1037
  ? '正在编辑「我的」背景:保存后立刻重新编译运行,改动只存在本机。'
1026
- : '内置作品只读:保存会另存为「我的副本」并立刻运行,内置原件不动。'} 两个代码框都能拖下面的把手调高度(聚焦把手后按 ↑/↓ 也行),会记住。`
1038
+ : '内置作品只读:保存会另存为「我的副本」并立刻运行,内置原件不动。'} 两个代码框都能拖下面的把手调高度(聚焦把手后按 ↑/↓ 也行),会记住。${builtin && builtin.license && builtin.license !== 'MIT'
1039
+ ? ` 注意:这个内置作品是 ${builtin.license}(署名 / 非商业 / 相同方式共享),不是 MIT;另存的副本同样受它约束。`
1040
+ : ''}`
1027
1041
  updateCodeInfo()
1028
1042
  setCodeNote('')
1029
1043
  }
@@ -1,7 +1,7 @@
1
1
  [
2
2
  {
3
3
  "id": "aurora",
4
- "name": "极光(自写)",
4
+ "name": "极光",
5
5
  "file": "aurora.glsl",
6
6
  "license": "MIT",
7
7
  "author": "dsh-shadertoy-skin",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  {
12
12
  "id": "flow",
13
- "name": "流体色带(自写)",
13
+ "name": "流体色带",
14
14
  "file": "flow.glsl",
15
15
  "license": "MIT",
16
16
  "author": "dsh-shadertoy-skin",
@@ -19,12 +19,35 @@
19
19
  },
20
20
  {
21
21
  "id": "pulse",
22
- "name": "脉冲(自写,带音乐)",
22
+ "name": "脉冲(带音乐)",
23
23
  "file": "pulse.glsl",
24
24
  "soundFile": "pulse-sound.glsl",
25
25
  "license": "MIT",
26
26
  "author": "dsh-shadertoy-skin",
27
27
  "hasSound": true,
28
28
  "note": "程序化电子乐 + 随节拍呼吸的画面,用来验证音频链路"
29
+ },
30
+ {
31
+ "id": "seascape",
32
+ "name": "海面(Seascape)",
33
+ "file": "seascape.glsl",
34
+ "license": "CC BY-NC-SA 3.0",
35
+ "licenseUrl": "https://creativecommons.org/licenses/by-nc-sa/3.0/",
36
+ "author": "Alexander Alekseev aka TDM",
37
+ "sourceUrl": "https://www.shadertoy.com/view/Ms2SD1",
38
+ "hasSound": false,
39
+ "note": "第三方作品(非商业):桌面背景修改版,修过 NaN 粉块并做了等价优化"
40
+ },
41
+ {
42
+ "id": "mario",
43
+ "name": "马里奥(带音乐)",
44
+ "file": "mario.glsl",
45
+ "soundFile": "mario-sound.glsl",
46
+ "license": "CC BY-NC-SA 3.0",
47
+ "licenseUrl": "https://creativecommons.org/licenses/by-nc-sa/3.0/",
48
+ "author": "Inigo Quilez",
49
+ "sourceUrl": "https://www.shadertoy.com/user/iq",
50
+ "hasSound": true,
51
+ "note": "第三方作品(非商业):像素画 + 一首曲子,适合「音乐只播一次」"
29
52
  }
30
53
  ]
@@ -0,0 +1,199 @@
1
+ // Bundled with dsh-shadertoy-skin under CC BY-NC-SA 3.0 (NOT MIT).
2
+ // Source: https://www.shadertoy.com/user/iq (see THIRD-PARTY-NOTICES.md)
3
+ // Created by inigo quilez - iq/2014
4
+ // License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
5
+
6
+
7
+ //----------------------------------------------------------------------------------------
8
+
9
+ float noise( float x )
10
+ {
11
+ return fract(sin(1371.1*x)*43758.5453);
12
+ }
13
+
14
+ float saw( float x, float a)
15
+ {
16
+ float f = fract( x );
17
+ return clamp(f/a,0.0,1.0)-clamp((f-a)/(1.0-a),0.0,1.0);
18
+ }
19
+
20
+ //----------------------------------------------------------------------------------------
21
+
22
+ float instr1( float f, float t )
23
+ {
24
+ float y = 0.6*saw(1.0*f*t,0.1)*clamp( 1.2 - 1.0*0.01*f*t, 0.0, 1.0 );
25
+ y += 0.3*saw(2.0*f*t,0.2)*clamp( 1.2 - 2.0*0.01*f*t, 0.0, 1.0 );
26
+ y += 0.1*saw(4.0*f*t,0.4)*clamp( 1.2 - 4.0*0.01*f*t, 0.0, 1.0 );
27
+ y *= 0.9 + 0.1*cos(60.0*t);
28
+ return y;
29
+ }
30
+
31
+ float instr2( float f, float t )
32
+ {
33
+ return instr1(f,t);
34
+ }
35
+
36
+ float instr3( float f, float t )
37
+ {
38
+ return 1.5*cos(0.5*6.2831*f*t)*exp(-0.005*f*t );
39
+ }
40
+
41
+ float instr4( float f, float t )
42
+ {
43
+ float y = noise( t );
44
+ y *= exp(-20.0*t );
45
+ return 0.7*y;
46
+
47
+ }
48
+
49
+ // music data
50
+ float doChannel1( float time );
51
+ float doChannel2( float time );
52
+ float doChannel3( float time );
53
+ float doChannel4( float time );
54
+
55
+ //----------------------------------------------------------------------------------------
56
+ // sound shader entrypoint
57
+ //
58
+ // input: time in seconds
59
+ // ouput: stereo wave valuie at "time"
60
+ //----------------------------------------------------------------------------------------
61
+
62
+ vec2 mainSound( in int samp, float time )
63
+ {
64
+ vec2 y = vec2(0.0);
65
+ y += vec2(0.75,0.25)*doChannel1( time ); // main instrument
66
+ y += vec2(0.25,0.75)*doChannel2( time ); // secondary instrument
67
+ y += vec2(0.25,0.25)*doChannel3( time ); // bass
68
+ y += vec2(0.25,0.25)*doChannel4( time ); // drum
69
+
70
+ y *= 1.0 - smoothstep( 55.0, 60.0, time ); // fade out
71
+
72
+ return vec2( y );
73
+ }
74
+
75
+ //----------------------------------------------------------------------------------------
76
+
77
+ float note2freq( in float x ) { return 440.0*pow( 2.0, (x-69.0)/12.0 ); }
78
+
79
+ #define D(u,v) b+=float(u);if(t>b){x=b;n=float(v);}
80
+ #define B(u) b+=float(u);if(t>b){x=b;}
81
+ #define tint 0.048
82
+
83
+ float doChannel1( float t )
84
+ {
85
+ float b = 0.0;
86
+ float n = 0.0;
87
+ float x = 0.0;
88
+ t /= tint;
89
+ D( 0,76)D( 3,76)D( 6,76)D( 6,72)D( 3,76)D( 6,79)D(24,72)D( 9,67)D( 9,64)D( 9,69)
90
+ D( 6,71)D( 6,70)D( 3,69)D( 6,67)D( 4,76)D( 4,79)D( 4,81)D( 6,77)D( 3,79)D( 6,76)
91
+ D( 6,72)D( 3,74)D( 3,71)D( 9,72)D( 9,67)D( 9,64)D( 9,69)D( 6,71)D( 6,70)D( 3,69)
92
+ D( 6,67)D( 4,76)D( 4,79)D( 4,81)D( 6,77)D( 3,79)D( 6,76)D( 6,72)D( 3,74)D( 3,71)
93
+ D(15,79)D( 3,78)D( 3,77)D( 3,75)D( 6,76)D( 6,68)D( 3,69)D( 3,72)D( 6,69)D( 3,72)
94
+ D( 3,74)D( 9,79)D( 3,78)D( 3,77)D( 3,75)D( 6,76)D( 6,84)D( 6,84)D( 3,84)D(18,79)
95
+ D( 3,78)D( 3,77)D( 3,75)D( 6,76)D( 6,68)D( 3,69)D( 3,72)D( 6,69)D( 3,72)D( 3,74)
96
+ D( 9,75)D( 9,74)D( 9,72)D(30,79)D( 3,78)D( 3,77)D( 3,75)D( 6,76)D( 6,68)D( 3,69)
97
+ D( 3,72)D( 6,69)D( 3,72)D( 3,74)D( 9,79)D( 3,78)D( 3,77)D( 3,75)D( 6,76)D( 6,84)
98
+ D( 6,84)D( 3,84)D(18,79)D( 3,78)D( 3,77)D( 3,75)D( 6,76)D( 6,68)D( 3,69)D( 3,72)
99
+ D( 6,69)D( 3,72)D( 3,74)D( 9,75)D( 9,74)D( 9,72)D(24,72)D( 3,72)D( 6,72)D( 6,72)
100
+ D( 3,74)D( 6,76)D( 3,72)D( 6,69)D( 3,67)D(12,72)D( 3,72)D( 6,72)D( 6,72)D( 3,74)
101
+ D( 3,76)D(27,72)D( 3,72)D( 6,72)D( 6,72)D( 3,74)D( 6,76)D( 3,72)D( 6,69)D( 3,67)
102
+ D(12,76)D( 3,76)D( 6,76)D( 6,72)D( 3,76)D( 6,79)D(24,72)D( 9,67)D( 9,64)D( 9,69)
103
+ D( 6,71)D( 6,70)D( 3,69)D( 6,67)D( 4,76)D( 4,79)D( 4,81)D( 6,77)D( 3,79)D( 6,76)
104
+ D( 6,72)D( 3,74)D( 3,71)D( 9,72)D( 9,67)D( 9,64)D( 9,69)D( 6,71)D( 6,70)D( 3,69)
105
+ D( 6,67)D( 4,76)D( 4,79)D( 4,81)D( 6,77)D( 3,79)D( 6,76)D( 6,72)D( 3,74)D( 3,71)
106
+ D( 9,76)D( 3,72)D( 6,67)D( 9,68)D( 6,69)D( 3,77)D( 6,77)D( 3,69)D(12,71)D( 4,81)
107
+ D( 4,81)D( 4,81)D( 4,79)D( 4,77)D( 4,76)D( 3,72)D( 6,69)D( 3,67)D(12,76)D( 3,72)
108
+ D( 6,67)D( 9,68)D( 6,69)D( 3,77)D( 6,77)D( 3,69)D(12,71)D( 3,77)D( 6,77)D( 3,77)
109
+ D( 4,76)D( 4,74)D( 4,72)D(24,76)D( 3,72)D( 6,67)D( 9,68)D( 6,69)D( 3,77)D( 6,77)
110
+ D( 3,69)D(12,71)
111
+ return instr1( note2freq( n ), tint*(t-x) );
112
+ }
113
+
114
+ float doChannel2( float t )
115
+ {
116
+ float b = 0.0;
117
+ float n = 0.0;
118
+ float x = 0.0;
119
+ t /= tint;
120
+ D( 0,66)D( 3,66)D( 6,66)D( 6,66)D( 3,66)D( 6,71)D(12,67)D(12,64)D( 9,60)D( 9,55)
121
+ D( 9,60)D( 6,62)D( 6,61)D( 3,60)D( 6,60)D( 4,67)D( 4,71)D( 4,72)D( 6,69)D( 3,71)
122
+ D( 6,69)D( 6,64)D( 3,65)D( 3,62)D( 9,64)D( 9,60)D( 9,55)D( 9,60)D( 6,62)D( 6,61)
123
+ D( 3,60)D( 6,60)D( 4,67)D( 4,71)D( 4,72)D( 6,69)D( 3,71)D( 6,69)D( 6,64)D( 3,65)
124
+ D( 3,62)D(15,76)D( 3,75)D( 3,74)D( 3,71)D( 6,72)D( 6,64)D( 3,65)D( 3,67)D( 6,60)
125
+ D( 3,64)D( 3,65)D( 9,76)D( 3,75)D( 3,74)D( 3,71)D( 6,72)D( 6,77)D( 6,77)D( 3,77)
126
+ D(18,76)D( 3,75)D( 3,74)D( 3,71)D( 6,72)D( 6,64)D( 3,65)D( 3,67)D( 6,60)D( 3,64)
127
+ D( 3,65)D( 9,68)D( 9,65)D( 9,64)D(30,76)D( 3,75)D( 3,74)D( 3,71)D( 6,72)D( 6,64)
128
+ D( 3,65)D( 3,67)D( 6,60)D( 3,64)D( 3,65)D( 9,76)D( 3,75)D( 3,74)D( 3,71)D( 6,72)
129
+ D( 6,77)D( 6,77)D( 3,77)D(18,76)D( 3,75)D( 3,74)D( 3,71)D( 6,72)D( 6,64)D( 3,65)
130
+ D( 3,67)D( 6,60)D( 3,64)D( 3,65)D( 9,68)D( 9,65)D( 9,64)D(24,68)D( 3,68)D( 6,68)
131
+ D( 6,68)D( 3,70)D( 6,67)D( 3,64)D( 6,64)D( 3,60)D(12,68)D( 3,68)D( 6,68)D( 6,68)
132
+ D( 3,70)D( 3,67)D(27,68)D( 3,68)D( 6,68)D( 6,68)D( 3,70)D( 6,67)D( 3,64)D( 6,64)
133
+ D( 3,60)D(12,66)D( 3,66)D( 6,66)D( 6,66)D( 3,66)D( 6,71)D(12,67)D(12,64)D( 9,60)
134
+ D( 9,55)D( 9,60)D( 6,62)D( 6,61)D( 3,60)D( 6,60)D( 4,67)D( 4,71)D( 4,72)D( 6,69)
135
+ D( 3,71)D( 6,69)D( 6,64)D( 3,65)D( 3,62)D( 9,64)D( 9,60)D( 9,55)D( 9,60)D( 6,62)
136
+ D( 6,61)D( 3,60)D( 6,60)D( 4,67)D( 4,71)D( 4,72)D( 6,69)D( 3,71)D( 6,69)D( 6,64)
137
+ D( 3,65)D( 3,62)D( 9,72)D( 3,69)D( 6,64)D( 9,64)D( 6,65)D( 3,72)D( 6,72)D( 3,65)
138
+ D(12,67)D( 4,77)D( 4,77)D( 4,77)D( 4,76)D( 4,74)D( 4,72)D( 3,69)D( 6,65)D( 3,64)
139
+ D(12,72)D( 3,69)D( 6,64)D( 9,64)D( 6,65)D( 3,72)D( 6,72)D( 3,65)D(12,67)D( 3,74)
140
+ D( 6,74)D( 3,74)D( 4,72)D( 4,71)D( 4,67)D( 3,64)D( 6,64)D( 3,60)D(12,72)D( 3,69)
141
+ D( 6,64)D( 9,64)D( 6,65)D( 3,72)D( 6,72)D( 3,65)D(12,67)
142
+ return instr2( note2freq( n ), tint*(t-x) );
143
+ }
144
+
145
+ float doChannel3( float t )
146
+ {
147
+ float b = 0.0;
148
+ float n = 0.0;
149
+ float x = 0.0;
150
+ t /= tint;
151
+ D( 0,50)D( 3,50)D( 6,50)D( 6,50)D( 3,50)D( 6,67)D(12,55)D(12,55)D( 9,52)D( 9,48)
152
+ D( 9,53)D( 6,55)D( 6,54)D( 3,53)D( 6,52)D( 4,60)D( 4,64)D( 4,65)D( 6,62)D( 3,64)
153
+ D( 6,60)D( 6,57)D( 3,59)D( 3,55)D( 9,55)D( 9,52)D( 9,48)D( 9,53)D( 6,55)D( 6,54)
154
+ D( 3,53)D( 6,52)D( 4,60)D( 4,64)D( 4,65)D( 6,62)D( 3,64)D( 6,60)D( 6,57)D( 3,59)
155
+ D( 3,55)D( 9,48)D( 9,55)D( 9,60)D( 6,53)D( 9,60)D( 3,60)D( 6,53)D( 6,48)D( 9,52)
156
+ D( 9,55)D( 3,60)D( 6,79)D( 6,79)D( 3,79)D( 6,55)D( 6,48)D( 9,55)D( 9,60)D( 6,53)
157
+ D( 9,60)D( 3,60)D( 6,53)D( 6,48)D( 6,56)D( 9,58)D( 9,60)D( 9,55)D( 3,55)D( 6,48)
158
+ D( 6,48)D( 9,55)D( 9,60)D( 6,53)D( 9,60)D( 3,60)D( 6,53)D( 6,48)D( 9,52)D( 9,55)
159
+ D( 3,60)D( 6,79)D( 6,79)D( 3,79)D( 6,55)D( 6,48)D( 9,55)D( 9,60)D( 6,53)D( 9,60)
160
+ D( 3,60)D( 6,53)D( 6,48)D( 6,56)D( 9,58)D( 9,60)D( 9,55)D( 3,55)D( 6,48)D( 6,44)
161
+ D( 9,51)D( 9,56)D( 6,55)D( 9,48)D( 9,43)D( 6,44)D( 9,51)D( 9,56)D( 6,55)D( 9,48)
162
+ D( 9,43)D( 6,44)D( 9,51)D( 9,56)D( 6,55)D( 9,48)D( 9,43)D( 6,50)D( 3,50)D( 6,50)
163
+ D( 6,50)D( 3,50)D( 6,67)D(12,55)D(12,55)D( 9,52)D( 9,48)D( 9,53)D( 6,55)D( 6,54)
164
+ D( 3,53)D( 6,52)D( 4,60)D( 4,64)D( 4,65)D( 6,62)D( 3,64)D( 6,60)D( 6,57)D( 3,59)
165
+ D( 3,55)D( 9,55)D( 9,52)D( 9,48)D( 9,53)D( 6,55)D( 6,54)D( 3,53)D( 6,52)D( 4,60)
166
+ D( 4,64)D( 4,65)D( 6,62)D( 3,64)D( 6,60)D( 6,57)D( 3,59)D( 3,55)D( 9,48)D( 9,54)
167
+ D( 3,55)D( 6,60)D( 6,53)D( 6,53)D( 6,60)D( 3,60)D( 3,53)D( 6,50)D( 9,53)D( 3,55)
168
+ D( 6,59)D( 6,55)D( 6,55)D( 6,60)D( 3,60)D( 3,55)D( 6,48)D( 9,54)D( 3,55)D( 6,60)
169
+ D( 6,53)D( 6,53)D( 6,60)D( 3,60)D( 3,53)D( 6,55)D( 3,55)D( 6,55)D( 3,55)D( 4,57)
170
+ D( 4,59)D( 4,60)D( 6,55)D( 6,48)D(12,48)D( 9,54)D( 3,55)D( 6,60)D( 6,53)D( 6,53)
171
+ D( 6,60)D( 3,60)D( 3,53)D( 6,50)
172
+ return instr3( note2freq( n ), tint*(t-x) );
173
+ }
174
+
175
+ float doChannel4( float t )
176
+ {
177
+ float b = 0.0;
178
+ float x = 0.0;
179
+ t /= tint;
180
+ B(0)B(6)B(3)B(6)B(3)B(6)B(9)B(6)B(3)B(3)B(3)B(6)B(4)B(2)B(6)B(4)
181
+ B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)
182
+ B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)
183
+ B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)
184
+ B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)
185
+ B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)
186
+ B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)
187
+ B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)
188
+ B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)
189
+ B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(3)B(6)B(3)B(6)
190
+ B(9)B(6)B(3)B(3)B(3)B(6)B(3)B(6)B(3)B(6)B(9)B(6)B(3)B(3)B(3)B(6)
191
+ B(3)B(6)B(3)B(6)B(9)B(6)B(3)B(3)B(3)B(6)B(3)B(6)B(3)B(6)B(9)B(6)
192
+ B(3)B(3)B(3)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)
193
+ B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)
194
+ B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)B(6)B(4)B(2)
195
+ B(6)B(4)B(2)B(9)B(3)B(6)B(6)B(9)B(3)B(6)B(6)B(9)B(3)B(6)B(6)B(9)
196
+ B(3)B(6)B(6)B(9)B(3)B(6)B(6)B(9)B(3)B(6)B(6)B(9)B(3)B(6)B(6)B(9)
197
+ B(3)B(6)B(6)B(9)B(3)B(6)B(6)B(9)B(3)B(6)B(6)
198
+ return instr4( note2freq( 42.0 ), tint*(t-x) );
199
+ }
@@ -0,0 +1,84 @@
1
+ /*
2
+ * "Mario" by Inigo Quilez (iq), 2014
3
+ * License: Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported
4
+ * https://creativecommons.org/licenses/by-nc-sa/3.0/
5
+ * Source: https://www.shadertoy.com/user/iq
6
+ * Bundled with dsh-shadertoy-skin as a preset under that same licence
7
+ * (NOT MIT). See THIRD-PARTY-NOTICES.md in the repository root.
8
+ */
9
+ // Created by inigo quilez - iq/2014
10
+ // https://www.youtube.com/c/InigoQuilez
11
+ // https://iquilezles.org/
12
+
13
+
14
+ // pack 12 pixels into a 24 bit integer
15
+ #define pack(a,b,c,d,e,f,g,h,i,j,k,l) (a+4*(b+4*(c+4*(d+4*(e+4*(f+4*(g+4*(h+4*(i+4*(j+4*(k+4*(l))))))))))))
16
+ #define _ 0
17
+
18
+ // 64 bytes (only 48 used)
19
+ const int bm[16] = int[16](
20
+ pack( _,_,_,3,3,3,3,3,_,_,_,_ ),
21
+ pack( _,_,3,3,3,3,3,3,3,3,3,_ ),
22
+ pack( _,_,1,1,1,2,2,1,2,_,_,_ ),
23
+ pack( _,1,2,1,2,2,2,1,2,2,2,_ ),
24
+ pack( _,1,2,1,1,2,2,2,1,2,2,2 ),
25
+ pack( _,1,1,2,2,2,2,2,1,1,1,_ ),
26
+ pack( _,_,_,2,2,2,2,2,2,2,_,_ ),
27
+ pack( _,_,1,1,3,1,1,1,_,_,_,_ ),
28
+ pack( _,1,1,1,3,1,1,3,1,1,_,_ ),
29
+ pack( 1,1,1,1,3,3,3,3,1,1,1,1 ),
30
+ pack( 2,2,1,3,2,3,3,2,3,1,2,2 ),
31
+ pack( 2,2,2,3,3,3,3,3,3,2,2,2 ),
32
+ pack( 2,2,3,3,3,3,3,3,3,3,2,2 ),
33
+ pack( _,_,3,3,3,_,_,3,3,3,_,_ ),
34
+ pack( _,1,1,1,_,_,_,_,1,1,1,_ ),
35
+ pack( 1,1,1,1,_,_,_,_,1,1,1,1 )
36
+ );
37
+
38
+ vec3 mario( in vec3 col, in vec2 p )
39
+ {
40
+ ivec2 q = ivec2(floor(p*10.0)) + ivec2(5,8);
41
+
42
+ if( q.x<0 || q.x>11 || q.y<0 || q.y>15 ) return col;
43
+
44
+ int c = (bm[15-q.y]>>(q.x+q.x)) & 3;
45
+
46
+ if( c==1 ) col = vec3(0.5,0.4,0.1);
47
+ if( c==2 ) col = vec3(1.0,0.6,0.0);
48
+ if( c==3 ) col = vec3(1.0,0.0,0.0);
49
+
50
+ return col;
51
+ }
52
+
53
+ void mainImage( out vec4 fragColor, in vec2 fragCoord )
54
+ {
55
+ vec2 p = (2.0*fragCoord-iResolution.xy)/iResolution.y;
56
+
57
+ // background
58
+ vec2 q = vec2( atan(p.y,p.x), length(p) );
59
+ float f = smoothstep( -0.1, 0.1, sin(q.x*10.0 + iTime) );
60
+ vec3 col = mix( vec3(0.42,0.55,1.0), vec3(0.6,0.7,1.0), f );
61
+
62
+ // soft shadow
63
+ float sha = 0.0;
64
+ for( int j=0; j<5; j++ )
65
+ for( int i=0; i<5; i++ )
66
+ {
67
+ vec3 s = mario( vec3(0.0), p + 15.0*vec2(float(i-4),float(j+1))/iResolution.y );
68
+ sha += step(0.1,s.x);
69
+ }
70
+ sha /= 25.0;
71
+ col *= 1.0-0.6*sha;
72
+
73
+ // color
74
+ col = mario( col, p);
75
+
76
+ // vignetting
77
+ col *= 1.0 - 0.2*length(p);
78
+
79
+ // fade in/out
80
+ col *= smoothstep( 0.0, 2.0, iTime );
81
+ col *= 1.0 - smoothstep( 55.0, 60.0, iTime );
82
+
83
+ fragColor = vec4( col, 1.0 );
84
+ }
@@ -0,0 +1,248 @@
1
+ /*
2
+ * "Seascape" by Alexander Alekseev aka TDM - 2014
3
+ * License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.
4
+ * Contact: tdmaav@gmail.com
5
+ *
6
+ * Source: https://www.shadertoy.com/view/Ms2SD1
7
+ * Bundled with dsh-shadertoy-skin as a preset under the SAME CC BY-NC-SA 3.0
8
+ * licence (NOT MIT). Attribution: Alexander Alekseev aka TDM (2014).
9
+ * See THIRD-PARTY-NOTICES.md in the repository root.
10
+ *
11
+ * 优化/修复版 v12("同一片海",只做可证明等价的加速 + 明确的缺陷修复)
12
+ *
13
+ * 性能(都保持画面等价/近等价)
14
+ * 1) 天空精确早退:dir.y >= 0 时混合权重 w = pow(smoothstep(0,-0.02,dir.y),0.2) 恒为 0,
15
+ * 像素就是纯 getSkyColor(dir),跳过追踪/法线/海面着色(mix(a,b,0)==a,逐位相同)。
16
+ * dir.y <= -0.02 时 w == 1,同理省掉第二次 getSkyColor。
17
+ * 2) 有界 regula-falsi:海面高度 h <= HMAX,故 p.y = -0.05 处 map() 必为负 =>
18
+ * t=(3.5+0.05)/(-dir.y) 是真括号上界;迭代 32 -> 16,命中点用收敛后的括号求值。
19
+ * 3) choppy == 4.0(每层第一个八度)用两次平方代替 pow()。
20
+ *
21
+ * 缺陷修复
22
+ * 4) post 用 pow(max(color,0)):负色 pow() 在 Intel Arc/ANGLE 上产生 NaN 粉块(实测 25% 像素)。
23
+ * 5) specular 的 pow 底数 clamp 到 [0,1]:fromEuler() 非正交使 |dir| ~1.04,
24
+ * dot(reflect,l) 可 >1,pow(...,139) 会炸出纯白点(实测 2135 个)。
25
+ * 6) 地平线:去掉 "hx>0 就当作 1000 单位外有命中" 的早退分支——那是假命中,
26
+ * 会在混合带上画出一条 1px、逐列跳动的硬边。现在最浅的射线也用真括号追踪。
27
+ * 7) 时间轴不再叠加 iMouse.x:播放器只在拖拽时送 iMouse,原式会让海面瞬移。
28
+ * 8) post 加 ±0.5/255 interleaved-gradient 抖动,打散天空 8bit 阶梯。
29
+ */
30
+ const int NUM_STEPS = 16;
31
+ const float PI = 3.141592;
32
+ const float EPSILON = 1e-3;
33
+ #define EPSILON_NRM (0.1 / iResolution.x)
34
+ //#define AA
35
+ //#define HORIZON_AA
36
+
37
+ // sea
38
+ const int ITER_GEOMETRY = 3;
39
+ const int ITER_FRAGMENT = 5;
40
+ const float SEA_HEIGHT = 0.6;
41
+ const float SEA_CHOPPY = 4.0;
42
+ const float SEA_SPEED = 0.8;
43
+ const float SEA_FREQ = 0.16;
44
+ const vec3 SEA_BASE = vec3(0.0,0.09,0.18);
45
+ const vec3 SEA_WATER_COLOR = vec3(0.8,0.9,0.6)*0.6;
46
+ #define SEA_TIME (1.0 + iTime * SEA_SPEED)
47
+ const mat2 octave_m = mat2(1.6,1.2,-1.2,1.6);
48
+
49
+ // math
50
+ mat3 fromEuler(vec3 ang) {
51
+ vec2 a1 = vec2(sin(ang.x),cos(ang.x));
52
+ vec2 a2 = vec2(sin(ang.y),cos(ang.y));
53
+ vec2 a3 = vec2(sin(ang.z),cos(ang.z));
54
+ mat3 m;
55
+ m[0] = vec3(a1.y*a3.y+a1.x*a2.x*a3.x,a1.y*a2.x*a3.x+a3.y*a1.x,-a2.y*a3.x);
56
+ m[1] = vec3(-a2.y*a1.x,a1.y*a2.y,a2.x);
57
+ m[2] = vec3(a3.y*a1.x*a2.x+a1.y*a3.x,a1.x*a3.x-a1.y*a3.y*a2.x,a2.y*a3.y);
58
+ return m;
59
+ }
60
+ float hash( vec2 p ) {
61
+ // Hash without sine: integer lattice + bit mixing. A shared lattice point always
62
+ // hashes identically no matter how the driver contracts surrounding float math.
63
+ ivec2 q = ivec2(floor(p));
64
+ uint h = uint(q.x) * 1597334677u ^ uint(q.y) * 3812015801u;
65
+ h ^= h >> 16;
66
+ h *= 0x7feb352du;
67
+ h ^= h >> 15;
68
+ h *= 0x846ca68bu;
69
+ h ^= h >> 16;
70
+ return float(h) * (1.0 / 4294967295.0);
71
+ }
72
+ float noise( in vec2 p ) {
73
+ vec2 f = fract( p );
74
+ vec2 u = f*f*(3.0-2.0*f);
75
+ return -1.0+2.0*mix(
76
+ mix(hash(floor(p + vec2(0.0,0.0))), hash(floor(p + vec2(1.0,0.0))), u.x),
77
+ mix(hash(floor(p + vec2(0.0,1.0))), hash(floor(p + vec2(1.0,1.0))), u.x),
78
+ u.y);
79
+ }
80
+
81
+ // lighting
82
+ float diffuse(vec3 n,vec3 l,float p) {
83
+ return pow(dot(n,l) * 0.4 + 0.6,p);
84
+ }
85
+ float specular(vec3 n,vec3 l,vec3 e,float s) {
86
+ float nrm = (s + 8.0) / (PI * 8.0);
87
+ // clamp 底数:fromEuler 非正交 => e 非单位 => base 可 >1,pow 会爆白
88
+ return pow(clamp(dot(reflect(e,n),l),0.0,1.0),s) * nrm;
89
+ }
90
+
91
+ // sky
92
+ vec3 getSkyColor(vec3 e) {
93
+ e.y = (max(e.y,0.0)*0.8+0.2)*0.8;
94
+ return vec3(pow(1.0-e.y,2.0), 1.0-e.y, 0.6+(1.0-e.y)*0.4) * 1.1;
95
+ }
96
+
97
+ // sea
98
+ float sea_octave(vec2 uv, float choppy) {
99
+ uv += noise(uv);
100
+ vec2 wv = 1.0-abs(sin(uv));
101
+ vec2 swv = abs(cos(uv));
102
+ wv = mix(wv,swv,wv);
103
+ float inner = 1.0-pow(wv.x * wv.y,0.65);
104
+ if(choppy == 4.0) { float i2 = inner*inner; return i2*i2; } // pow(x,4) => 两次平方
105
+ return pow(inner,choppy);
106
+ }
107
+
108
+ float map(vec3 p) {
109
+ float freq = SEA_FREQ;
110
+ float amp = SEA_HEIGHT;
111
+ float choppy = SEA_CHOPPY;
112
+ vec2 uv = p.xz; uv.x *= 0.75;
113
+
114
+ float d, h = 0.0;
115
+ for(int i = 0; i < ITER_GEOMETRY; i++) {
116
+ d = sea_octave((uv+SEA_TIME)*freq,choppy);
117
+ d += sea_octave((uv-SEA_TIME)*freq,choppy);
118
+ h += d * amp;
119
+ uv *= octave_m; freq *= 1.9; amp *= 0.22;
120
+ choppy = mix(choppy,1.0,0.2);
121
+ }
122
+ return p.y - h;
123
+ }
124
+
125
+ float map_detailed(vec3 p) {
126
+ float freq = SEA_FREQ;
127
+ float amp = SEA_HEIGHT;
128
+ float choppy = SEA_CHOPPY;
129
+ vec2 uv = p.xz; uv.x *= 0.75;
130
+
131
+ float d, h = 0.0;
132
+ for(int i = 0; i < ITER_FRAGMENT; i++) {
133
+ d = sea_octave((uv+SEA_TIME)*freq,choppy);
134
+ d += sea_octave((uv-SEA_TIME)*freq,choppy);
135
+ h += d * amp;
136
+ uv *= octave_m; freq *= 1.9; amp *= 0.22;
137
+ choppy = mix(choppy,1.0,0.2);
138
+ }
139
+ return p.y - h;
140
+ }
141
+
142
+ vec3 getSeaColor(vec3 p, vec3 n, vec3 l, vec3 eye, vec3 dist) {
143
+ float fresnel = clamp(1.0 - dot(n, -eye), 0.0, 1.0);
144
+ fresnel = min(fresnel * fresnel * fresnel, 0.5);
145
+
146
+ vec3 reflected = getSkyColor(reflect(eye, n));
147
+ vec3 refracted = SEA_BASE + diffuse(n, l, 80.0) * SEA_WATER_COLOR * 0.12;
148
+
149
+ vec3 color = mix(refracted, reflected, fresnel);
150
+
151
+ float atten = max(1.0 - dot(dist, dist) * 0.001, 0.0);
152
+ color += SEA_WATER_COLOR * (p.y - SEA_HEIGHT) * 0.18 * atten;
153
+
154
+ color += specular(n, l, eye, 600.0 * inversesqrt(dot(dist,dist)));
155
+
156
+ return color;
157
+ }
158
+
159
+ // tracing
160
+ vec3 getNormal(vec3 p, float eps) {
161
+ vec3 n;
162
+ n.y = map_detailed(p);
163
+ n.x = map_detailed(vec3(p.x+eps,p.y,p.z)) - n.y;
164
+ n.z = map_detailed(vec3(p.x,p.y,p.z+eps)) - n.y;
165
+ n.y = eps;
166
+ return normalize(n);
167
+ }
168
+
169
+ // 有界 regula falsi:h <= SEA_HEIGHT*2*(1+0.22+0.22^2) 保证 p.y=-0.05 处 map() < 0
170
+ float heightMapTracing(vec3 ori, vec3 dir, out vec3 p) {
171
+ float tx = (ori.y + 0.05) / (-dir.y); // p.y == -0.05 => map <= -0.05 < 0
172
+ float hx = map(ori + dir * tx);
173
+ float tm = 0.0;
174
+ float hm = map(ori);
175
+ for(int i = 0; i < NUM_STEPS; i++) {
176
+ float tmid = mix(tm, tx, hm / (hm - hx));
177
+ p = ori + dir * tmid;
178
+ float hmid = map(p);
179
+ if(hmid < 0.0) {
180
+ tx = tmid;
181
+ hx = hmid;
182
+ } else {
183
+ tm = tmid;
184
+ hm = hmid;
185
+ }
186
+ if(abs(hmid) < EPSILON) break;
187
+ }
188
+ float t = mix(tm, tx, hm / (hm - hx));
189
+ p = ori + dir * t;
190
+ return t;
191
+ }
192
+
193
+ // 单条射线的完整着色(AA 与常规路径共用)
194
+ vec3 shadeRay(vec3 ori, vec3 dir) {
195
+ vec3 p;
196
+ heightMapTracing(ori,dir,p);
197
+ vec3 dist = p - ori;
198
+ vec3 n = getNormal(p, dot(dist,dist) * EPSILON_NRM);
199
+ vec3 light = normalize(vec3(0.0,1.0,0.8));
200
+ return getSeaColor(p,n,light,dir,dist);
201
+ }
202
+
203
+ vec3 getPixel(in vec2 coord, float time) {
204
+ vec2 uv = coord / iResolution.xy;
205
+ uv = uv * 2.0 - 1.0;
206
+ uv.x *= iResolution.x / iResolution.y;
207
+
208
+ // ray (相机数学与上游完全一致)
209
+ vec3 ang = vec3(sin(time*3.0)*0.1,sin(time)*0.2+0.3,time);
210
+ vec3 ori = vec3(0.0,3.5,time*5.0);
211
+ vec3 dir = normalize(vec3(uv.xy,-2.0)); dir.z += length(uv) * 0.14;
212
+ dir = normalize(dir) * fromEuler(ang);
213
+
214
+ // 天空:w 恒为 0,纯天空色
215
+ if(dir.y >= 0.0) return getSkyColor(dir);
216
+
217
+ float w = pow(smoothstep(0.0,-0.02,dir.y),0.2);
218
+ #ifdef HORIZON_AA
219
+ // 只在天空/海面过渡带(占 ~2% 像素)做 2x2 超采样,消地平线硬边与爬行
220
+ if(w > 0.02 && w < 0.98) {
221
+ vec3 acc = vec3(0.0);
222
+ for(int j = 0; j < 2; j++) {
223
+ for(int i = 0; i < 2; i++) {
224
+ vec2 uv2 = uv + (vec2(float(i),float(j)) - 0.5) * (1.0 / iResolution.y);
225
+ vec3 d2 = normalize(vec3(uv2.xy,-2.0)); d2.z += length(uv2) * 0.14;
226
+ d2 = normalize(d2) * fromEuler(ang);
227
+ float w2 = pow(smoothstep(0.0,-0.02,d2.y),0.2);
228
+ acc += (d2.y >= 0.0) ? getSkyColor(d2) : mix(getSkyColor(d2), shadeRay(ori,d2), w2);
229
+ }
230
+ }
231
+ return acc * 0.25;
232
+ }
233
+ #endif
234
+
235
+ vec3 sea = shadeRay(ori,dir);
236
+ return mix(getSkyColor(dir), sea, w);
237
+ }
238
+
239
+ // main
240
+ void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
241
+ float time = iTime * 0.3; // 去掉 iMouse.x:拖拽会让海面瞬移
242
+ vec3 color = getPixel(fragCoord, time);
243
+
244
+ // post:max() 修 NaN;±0.5/255 抖动去天空 banding
245
+ vec3 c = pow(max(color,vec3(0.0)),vec3(0.65));
246
+ float dith = fract(52.9829189 * fract(dot(fragCoord, vec2(0.06711056, 0.00583715))));
247
+ fragColor = vec4(c + (dith - 0.5) * (1.0 / 255.0), 1.0);
248
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-shadertoy-skin",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Realtime ShaderToy background skin for DeepSeek Harness — a zero-runtime-dependency WebGL2 player, background library and glass UI integration.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -45,8 +45,12 @@
45
45
  "native-dist/presets/flow.glsl",
46
46
  "native-dist/presets/pulse.glsl",
47
47
  "native-dist/presets/pulse-sound.glsl",
48
+ "native-dist/presets/seascape.glsl",
49
+ "native-dist/presets/mario.glsl",
50
+ "native-dist/presets/mario-sound.glsl",
48
51
  "README.md",
49
- "LICENSE"
52
+ "LICENSE",
53
+ "THIRD-PARTY-NOTICES.md"
50
54
  ],
51
55
  "dsh": {
52
56
  "bundle": {