Initial commit
This commit is contained in:
190
skills/web-shader-extractor/references/shaders-com.md
Executable file
190
skills/web-shader-extractor/references/shaders-com.md
Executable file
@@ -0,0 +1,190 @@
|
||||
# shaders.com 提取工作流
|
||||
|
||||
shaders.com 是一个 shader 设计工具,使用 Nuxt.js + Three.js r183 TSL + Supabase。
|
||||
|
||||
## 识别特征
|
||||
|
||||
- URL: `shaders.com/collection/{slug}/{presetId}` 或 `shaders.com/preset/{id}`
|
||||
- Canvas: `data-renderer="shaders"` + `data-engine="three.js r183"`
|
||||
- Nuxt.js (`_nuxt/` 路径)
|
||||
- Clerk 认证
|
||||
- Supabase 存储 (`data.shaders.com/storage/v1/`)
|
||||
|
||||
## 关键架构差异
|
||||
|
||||
与 Unicorn Studio 完全不同:
|
||||
- **不使用 GLSL** — 使用 Three.js TSL (Three Shader Language) 节点系统
|
||||
- **87 种组件类型** — 每种有自己的 TSL `fragmentNode` 函数
|
||||
- **定义数据是 XOR + base64 编码的**
|
||||
- **组件可嵌套** — 树形结构(Glass 的 children 是其内部效果)
|
||||
|
||||
## 数据获取
|
||||
|
||||
### API 端点
|
||||
|
||||
```bash
|
||||
# 集合变体(含编码定义)— 公开,无需认证
|
||||
curl -s "https://shaders.com/api/collections/{slug}/{variantId}"
|
||||
|
||||
# 预览 API(含编码定义 + 水印注入)
|
||||
curl -s "https://shaders.com/api/preview/preset/{presetId}"
|
||||
|
||||
# Nuxt payload(只含元数据,不含 shader 定义)
|
||||
curl -s "https://shaders.com/collection/{slug}/{id}/_payload.json"
|
||||
```
|
||||
|
||||
### 定义解码
|
||||
|
||||
定义使用 XOR + base64 编码,有两套密钥:
|
||||
|
||||
1. **网站 API**(`/api/collections/`):
|
||||
- 混淆密钥: `a5e7244ad0973f07e10285bfa75ddbe4`(来自 Nuxt runtime config)
|
||||
- 组件/属性名用短代码(`C52`=Plasma, `p06`=angle, 等)
|
||||
- 解码: `JSON.parse(XOR(base64decode(encoded), keyBytes))`
|
||||
- 然后需要 code→name 映射表还原可读名称
|
||||
|
||||
2. **预览 API**(`/api/preview/`):
|
||||
- 密钥: `shaders-preview-key`
|
||||
- 使用人类可读属性名(无需映射)
|
||||
- 注意:会注入水印 `ImageTexture` 组件
|
||||
|
||||
### 代码映射表
|
||||
|
||||
87 种组件按字母排序编号 `C00-C86`,233 种属性按字母排序编号 `p00-p232`。
|
||||
映射表可从 JS bundle 中提取。
|
||||
|
||||
## 已知陷阱
|
||||
|
||||
### Y 轴翻转(反复出现!)
|
||||
|
||||
**SDF 纹理和 UV 坐标系统性 Y 翻转** — 已在多次提取中确认:
|
||||
|
||||
shaders.com 的 SDF 二进制(`.bin`)使用**图像坐标系**(Y=0 在顶部),
|
||||
而 WebGL 纹理坐标 Y=0 在底部。直接加载会导致形状上下翻转。
|
||||
|
||||
```glsl
|
||||
// 错误:直接用 shapeUV 采样
|
||||
float sdf = texture(tSDF, shapeUV).r;
|
||||
|
||||
// 正确:翻转 Y
|
||||
vec2 sdfUV = vec2(shapeUV.x, 1.0 - shapeUV.y);
|
||||
float sdf = texture(tSDF, sdfUV).r;
|
||||
|
||||
// 注意:梯度的 Y 分量也需要取反
|
||||
float dSdy = -(texture(tSDF, sdfUV - vec2(0, eps)).r - sdf) / eps;
|
||||
```
|
||||
|
||||
同样,组件定义中的 `center.y` 使用 DOM 坐标(Y=0 在顶部),
|
||||
在 Glass shader 中需要翻转:`center.y = 1.0 - center.y`。
|
||||
|
||||
### SDF 二进制格式
|
||||
|
||||
- 格式:512×512 Float32 单通道(1,048,576 bytes = 512² × 4)
|
||||
- 值域:有符号距离,负值=内部,正值=外部(如 [-0.065, 0.486])
|
||||
- **不需要重映射**(不要做 `*2-1`),直接使用原始值
|
||||
- 需要 `OES_texture_float_linear` 扩展做线性过滤
|
||||
- WebGL2 加载:`gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, 512, 512, 0, gl.RED, gl.FLOAT, data)`
|
||||
|
||||
## 组件类型速查
|
||||
|
||||
| 类别 | 组件 | 复杂度 |
|
||||
|------|------|--------|
|
||||
| 纹理 | Plasma, Godrays, SimplexNoise, LinearGradient, RadialGradient | 中 |
|
||||
| 形状 | Glass, Blob, Circle, Ring, Star, RoundedRect, Polygon | 高(Glass 最复杂) |
|
||||
| 畸变 | WaveDistortion, ChromaticAberration, Liquify, Twirl, Bulge | 低-中 |
|
||||
| 风格化 | FilmGrain, Halftone, Ascii, Dither, Glow, Bloom | 低-中 |
|
||||
| 后处理 | Blur, ProgressiveBlur, BrightnessContrast, HueShift | 低 |
|
||||
|
||||
## 渲染管线
|
||||
|
||||
```
|
||||
Three.js r183 TSL 渲染器
|
||||
├─ 优先尝试 WebGPU,降级到 WebGL
|
||||
├─ 正交相机 + 单个全屏四边形
|
||||
├─ 组件树从底到顶合成
|
||||
├─ 有 children 的组件用 RTT (render-to-texture) 捕获子内容
|
||||
├─ blend mode 用自定义混合函数
|
||||
└─ Glass 组件最复杂:SDF 评估 → 梯度法线 → 折射 → 色差 → 模糊 → 着色 → 高光 → 菲涅尔 → 合成
|
||||
```
|
||||
|
||||
## 移植策略
|
||||
|
||||
1. **TSL 不能直接复制** — 需要翻译为 GLSL
|
||||
2. **从 JS bundle 提取 TSL `fragmentNode`** → 反混淆 → 翻译为 GLSL
|
||||
3. **组件树 → multi-pass FBO 管线**
|
||||
4. **SDF 纹理需要 Y-flip**(见上方陷阱)
|
||||
5. **Glass 组件参数多**(20+),需要精确匹配每个值
|
||||
|
||||
## 颜色空间处理(关键)
|
||||
|
||||
shaders.com 的 Three.js 渲染器全程在 **linear 空间** 工作:
|
||||
- 组件定义中的 hex 颜色(如 `#2c2c42`)是 **sRGB** 值
|
||||
- TSL 的 `color()` 函数自动将 sRGB→linear
|
||||
- 所有中间 FBO 均存储 linear 值
|
||||
- 最终由渲染器做 linear→sRGB 输出编码
|
||||
|
||||
移植时:
|
||||
```glsl
|
||||
// 1. 颜色定义时:sRGB hex → linear
|
||||
vec3 colorA = pow(vec3(0.173, 0.173, 0.259), vec3(2.2)); // #2c2c42
|
||||
|
||||
// 2. 中间 pass:全部在 linear 空间计算,不做 gamma
|
||||
// 3. 最终输出 pass(仅一次):linear → sRGB
|
||||
fragColor = vec4(pow(color.rgb, vec3(1.0/2.2)), color.a);
|
||||
```
|
||||
|
||||
**常见错误**:在中间 pass 做 gamma 校正,导致后续 pass 在错误空间累加高光/菲涅尔。
|
||||
|
||||
## 参数精确对齐原则
|
||||
|
||||
**绝对禁止手动调参**。所有参数必须严格匹配 TSL 翻译中的公式和乘数:
|
||||
|
||||
```
|
||||
TSL 原始乘数 → GLSL 必须使用的值
|
||||
aberration * 0.06 → 不能改为 0.12
|
||||
fresnelSoftness * 0.06 → 不能改为 0.12
|
||||
fresnel (0.17) → 不能改为 0.4
|
||||
SDF gradient eps = 0.01 → 不能改为 0.005
|
||||
```
|
||||
|
||||
如果视觉效果不匹配,应检查:
|
||||
1. 颜色空间是否正确(sRGB/linear 混乱是最常见原因)
|
||||
2. 噪声函数实现差异(Perlin 实现 vs `mx_noise_float`)
|
||||
3. 时间基准是否正确
|
||||
4. FBO 管线顺序是否与组件树匹配
|
||||
|
||||
**不要**通过修改乘数来"补偿"视觉差异 — 这会在其他参数配置下崩溃。
|
||||
|
||||
## TSL 时间约定
|
||||
|
||||
`timerLocal(speed)` = 每秒递增 `speed` 单位。移植时:`uTime = seconds * speed`。
|
||||
|
||||
然后 shader 内部再乘自己的系数:
|
||||
|
||||
| 组件 | speed 参数 | shader 内部乘数 | 实际速率/秒 |
|
||||
|------|-----------|----------------|------------|
|
||||
| Plasma | 2 | × 0.125 | 0.25 |
|
||||
| Godrays | 0.7 | × 0.2 | 0.14 |
|
||||
| WaveDistortion | 0.8 | × 0.5 | 0.4 |
|
||||
| FilmGrain | — | 无时间(静态) | 0 |
|
||||
|
||||
## TSL→GLSL 标识符映射(SPCVwBqR.js)
|
||||
|
||||
常用映射(随构建版本变化,需动态提取):
|
||||
|
||||
| 本地名 | TSL 函数 | GLSL |
|
||||
|--------|---------|------|
|
||||
| C / z | vec4() | vec4 |
|
||||
| x / D | vec2() | vec2 |
|
||||
| q / N | vec3() | vec3 |
|
||||
| P / J | resolution | u_resolution |
|
||||
| A / $ | uv | vUv |
|
||||
| se / Oe | sin() | sin() |
|
||||
| W / I | cos() | cos() |
|
||||
| ne | mix() | mix() |
|
||||
| D | smoothstep() | smoothstep() |
|
||||
| fe | clamp() | clamp() |
|
||||
| ar | mx_noise_float() | perlinNoise3D() |
|
||||
| dr / Gt | timerLocal() | u_time × speed |
|
||||
| Me / wt | rtt() | FBO pass |
|
||||
| Ce | renderOutput() | fragColor |
|
||||
Reference in New Issue
Block a user