用 AI 系统学习任何东西的教练。当用户要"学 XX""怎么入门""帮我制定学习计划""我想搞懂 XX""考证/备考""复习"时使用。不是直接讲答案,而是带着走完整的学习循环:定目标→输入→主动回忆→输出→纠错→间隔复习→项目交付。
The English summary is being prepared. Showing the original description.
国风 3D 网页渲染。当用户要"水墨风 3D""中国风网页特效""Three.js 水墨""国风 H5""青绿山水 3D""非真实感渲染 NPR""古风 WebGL"时使用。提供可运行的中式渲染 shader 与实现方法,不是通用 Three.js 教程。
The English summary is being prepared. Showing the original description.
Run score Not tested
See how to installReview the instructions the agent will receive before you install.
定位说明:通用 Three.js 教程已经很多(英文社区有大量高质量资源)。 这个技能只做一件他们不做的事——中式美学的实时渲染。
中国风官网 / 文旅 H5 / 品牌活动页 / 水墨风交互 / 国风游戏原型 / 非真实感渲染(NPR)。
不适用:通用 3D 建模、物理仿真、写实渲染——那些去看 Three.js 官方文档更好。
⚠️ 移动端警告:Three.js + 自定义 shader 在中低端安卓上会明显发热掉帧。 H5 项目务必先确认目标机型,必要时降级为静态图。
水墨效果不是加个滤镜,是三件事的组合:
真实光照是连续的,水墨是分层的。把明暗量化成 5 阶:
float lam = max(dot(N, normalize(uLight)), 0.0);
float steps = 5.0;
float q = floor(clamp(lam, 0.0, 1.0) * steps) / (steps - 1.0);
vec3 col = mix(uInk, uPaper, q); // 浓墨 → 纸白
阶数太多(>8)失去水墨感,太少(<3)像色块。5 阶是甜点。
毛笔在轮廓处停留更久,墨更浓。用视线与法线夹角模拟:
float rim = 1.0 - max(dot(N, normalize(vV)), 0.0);
float edge = smoothstep(0.45, 0.95, rim);
col = mix(col, uInk, edge * 0.85);
纯数学量化的边界太整齐,不像手绘。在量化前扰动光照值:
float n = noise(vP * 5.5 + uTime * 0.06);
lam += (n - 0.5) * 0.16; // 扰动幅度别超过 0.2
再叠一层细噪声当宣纸颗粒:
col *= 0.97 + 0.03 * noise(vP * 40.0);
这个方案没有引入任何新技术——描边用的是和 gongbi-demo.html 完全同一套反向外壳,
连代码都一样。唯一的差别是 uLine 传进去的是暖金而不是墨黑。
但气质完全不同。demo 里的「墨线对照」档就是为了证明这件事: 同样的山、同样的青绿配色,只换线色,「金碧山水」的贵气立刻消失。 「金碧山水」这个名字,就是从那条金线来的。
这是青绿山水的固定语法:山脚石绿、山顶石青。不是随机分色,也不是用明暗分:
// 顶点着色器里把世界坐标传出来
vW = (modelMatrix * vec4(position, 1.0)).xyz;
// 片元着色器:按 y 取海拔,归一化范围要贴合实际山高
float alt = clamp((vW.y + 1.45) / 3.05, 0.0, 1.0);
alt = smoothstep(0.08, 0.92, alt);
vec3 base = mix(uLow, uHigh, alt); // uLow=石绿, uHigh=石青
⚠️ 归一化范围一定要贴合实际模型高度。初版系数没对上,alt 大部分时间挤在中段,
青绿两色根本分不开,看着就是一片墨绿。
除了描边,受光的山脊再敷一层金粉,「金碧」才立得住:
float ridge = smoothstep(0.72, 0.98, lam) * smoothstep(0.35, 0.8, alt);
col = mix(col, uLine, ridge * uGold * 0.42);
uGold = 0 时这条完全不生效,正好用来做墨线对照档。
暗部下限压太狠。初版 mix(base * 0.55, base, q),矿物色的饱和度全被吃掉,
整片山糊成墨绿——和敦煌那次是同一个错误。改成 0.78 才对。
青绿山水(尤其《千里江山图》)以鲜艳著称,把它画暗就丢了根本特征。
水面也一样:初版 11×6 的平面四条硬边全在画面里,像一块灰绿托盘; 放大到 46×34 让边缘出画,再把不透明度压到 0.13 —— 青绿山水的水多是 留白加一点淡色,让绢底透上来才对。
前三个方案(水墨、工笔、剪纸)里噪声都是配角——用来打破机械感的微扰。 敦煌反过来:噪声是主角,幅度大一个量级。
一句话概括这个方案:敦煌壁画好看,很大程度上是因为它旧了。
把做旧关掉,剩下的只是三色平涂,一点特征都没有。demo 里的「初绘」档就是这个对照——
同一套 shader、同样的配色,只把 uAge 从 1.0 降到 0.15,敦煌感立刻消失。
剥落是自然破坏,天然多尺度。单层噪声一眼假,要叠:
float fbm(vec3 p){
float s = 0.0, a = 0.5;
for (int i = 0; i < 4; i++) { s += a * noise(p); p *= 2.03; a *= 0.5; }
return s;
}
然后按尺度分工:大块剥落 fbm(vP*3.4)、中等起甲 fbm(vP*11.0)、颗粒 noise(vP*46.0)。
不是把颜色调暗,是颜料层没了、露出白垩地仗。所以是往地仗色混,不是往黑里混:
float loss = smoothstep(0.52, 0.34, flake * 0.65 + mottle * 0.35);
col = mix(col, uPlaster, clamp(loss * uAge, 0.0, 0.92));
龟裂用噪声的等值线取细缝(两个反向 smoothstep 相乘):
float c = fbm(vP * 18.0);
float crack = smoothstep(0.495, 0.5, c) * smoothstep(0.515, 0.505, c);
敦煌壁画里人物"脸是黑的",不是当年就那么画的——唐代用的铅丹(红色) 氧化后变成深褐近黑。所以这个效果要满足两个条件才对:
float oxid = smoothstep(0.55, 0.85, fbm(vP * 5.2));
float isRed = step(region, 0.40);
col = mix(col, vec3(0.13, 0.10, 0.09), oxid * isRed * uAge * 0.75);
vP.y 方向的色带做主结构、噪声只负责把边界啃毛。uRecede
压暗并去饱和,图与底才分得开。z=+1.4
把前面的浮雕全挡住;改缓弧又因为 thetaStart 朝向不好控变成一块悬空小板。
壁画本来就画在平墙上,PlaneGeometry 没这些坑。工笔和水墨的差别不在"画得细",在于它是线主导的。所以除了把色阶从 5 阶提到 9 阶、 把墨换成矿物色之外,真正的难点是那条线怎么画。
按 SKILL.md 的性能建议「能在材质里做的就在材质里做」,先试了材质内的两种做法:
| 做法 | 结果 |
|---|---|
fwidth(N) 检测法线突变画结构折边 | ❌ 光滑有机形体上基本无效。这类形体没有硬转折,length(fwidth(N)) 全场趋近 0,调阈值救不回来 |
rim(1 - dot(N,V))压出轮廓暗边 | ❌ 能压出边,但那是渐变带不是线,宽度随曲率变化,没有勒线该有的等宽感 |
反向外壳(沿法线外扩 + side: BackSide) | ✅ 真正等宽的线,且不需要后处理 |
调试这类"看不见的效果"有个省事办法:把各个分量分别输出到 r/g 通道, 一眼就能看出哪个在工作、哪个是 0。我就是这么发现
fwidth那条全场为零的。
反向外壳的做法:
const outlineMaterial = new THREE.ShaderMaterial({
uniforms: { uLine, uThickness: { value: 0.018 } },
side: THREE.BackSide, // 只渲染背面
vertexShader: `
uniform float uThickness;
void main() {
vec3 p = position + normalize(normal) * uThickness; // 沿法线外扩
gl_Position = projectionMatrix * modelViewMatrix * vec4(p, 1.0);
}`,
fragmentShader: `uniform vec3 uLine; void main(){ gl_FragColor = vec4(uLine, 1.0); }`,
});
// 每个本体挂一个外壳作为子对象,跟着一起变换
mesh.add(new THREE.Mesh(geo, outlineMaterial));
反向外壳虽然不引 EffectComposer,但它不免费:每个物体多渲染一遍, demo 里实测 draw call 3 → 6、三角面 25,248 → 50,496,正好翻倍。
所以「材质内做」和「后处理」的取舍不是一句"别引 EffectComposer"能概括的:
deep 很接近,
而 rim 线恰好落在最暗处——深色画在深色上,等于没画。工笔的线本来就是墨线,直接用近黑最稳。水墨方案的三步是「量化明暗 → 边缘压深 → 噪声扰动」。剪纸皮影每一步都要反着做, 这也是为什么它值得单独实现一遍——能验证这套思路不是只会「色调分离」一招。
dot(N, L)皮影是一张平的皮子,正面背面一个色,没有受光面和背光面。所以片元着色器里 刻意不引入光照项:
// 水墨: float lam = max(dot(N, uLight), 0.0); → 再量化
// 皮影: 直接就是纸的本色,颜色不随朝向变化
vec3 col = uPaper;
同样是 rim,方向完全相反:水墨用它压出浓墨,皮影用它表现灯光从薄边透出来。
float rim = 1.0 - max(dot(N, normalize(vV)), 0.0);
float bleed = smoothstep(0.05, 0.75, rim);
col = mix(col, uGlow, bleed * 0.95); // 水墨这里是 mix(col, uInk, ...)
阈值要放低、范围要拉宽,否则只有镂空边缘发光、外轮廓是死的。
剪纸没有明暗层次可用,全靠轮廓和镂空说话,所以几何体要用 Shape + holes
而不是现成的球/环:
pow(abs(cos(n*t/2)), 1.9) 把峰压尖、谷压宽。用圆润的
正弦花瓣会像齿轮,不像刀剪的。Path.absellipse(..., rotation) 让长轴对准圆心。皮影的光源在幕布后面,画面是「暗幕布上一盏灯」,不是满屏发光。 灯晕范围和强度都要收着用,否则背景过曝会把剪影吞掉。
复用中国传统色,三套起步:
| 风格 | 纸色 | 浓墨 | 中间调 |
|---|---|---|---|
| 水墨 | #F7F5F0 | #2E2A26 | #5A5550 |
| 青绿 | #F2F5F2 | #14322B | #2F6B5E |
| 朱砂 | #FBF7F4 | #3A1512 | #B23A2E |
关键:背景色要和纸色一致,否则物体像贴在画上而不是画在纸上。
demo.html —— 水墨(Three.js r170 + importmap,单文件无需构建):
qinglv-demo.html —— 青绿山水(2026-08-22 新增):
dunhuang-demo.html —— 敦煌壁画(2026-08-22 新增):
uAge
从 1.0 降到 0.15,画面立刻变成鲜艳平涂,一点"敦煌感"都没有gongbi-demo.html —— 工笔(2026-08-20 新增):
papercut-demo.html —— 剪纸皮影(2026-08-20 新增):
在线预览:https://sanhuang520-ship-it.github.io/awesome-chinese-ai-tools/themes/ink3d.html
用户明确说“不修改、不运行,只做技术方案或检查现成 Demo”时,先给结论,限制读取范围:
demo.html 中与问题直接相关的行;不要整文件输出,也不要读取 intro-demo.html,除非用户问开场动画。静态审查应控制在:技术结论 → 移动端风险 → Demo 路径 → 未验证项,不要因为仓库里已有源码就展开成逐行代码审计。
字数上限是硬门槛,不是大致篇幅。先在内部压缩并计数字符,再只输出成品;不要把过程说明、长绝对路径或额外寒暄计入最终答案。中文短审查优先使用下面的紧凑结构:
结论:静态思路可行,未运行。
技法:①…;②…;③…。
风险:①…;②…;③…。
路径:`skills/guofeng-threejs/demo.html`;`skills/guofeng-threejs/intro-demo.html`。
未实测:FPS/功耗/内存、目标机型与 WebView、降级和上下文恢复。
<= 300;拿不准就压到约 220–260 字留余量。rg / 定点读取等静态核对;不要启动浏览器、服务器、构建或 Demo。| 风格 | 关键技法 |
|---|---|
| 青绿山水 | ✅ 已实现,见 qinglv-demo.html 与下节 |
| 敦煌壁画 | ✅ 已实现,见 dunhuang-demo.html 与下节 |
| 剪纸皮影 | ✅ 已实现,见 papercut-demo.html 与下节 |
| 工笔 | ✅ 已实现,见 gongbi-demo.html 与下节(描边没用 Sobel,原因写在那里) |
noise(vP * 40.0) 的纸纹改成贴图采样。InstancedMesh。renderer.setPixelRatio(Math.min(devicePixelRatio, 2)),否则高分屏直接卡死。guochao-visual-cn —— 国潮视觉(AI 出图用)chinese-web-themes —— 中式网页主题(2D 排版用)No reviews yet. Tell others what you thought.
No login needed. Share how it worked for you, ask a question, or note where it did not run.
No comments yet. Be the first to write one.
用 AI 系统学习任何东西的教练。当用户要"学 XX""怎么入门""帮我制定学习计划""我想搞懂 XX""考证/备考""复习"时使用。不是直接讲答案,而是带着走完整的学习循环:定目标→输入→主动回忆→输出→纠错→间隔复习→项目交付。
The English summary is being prepared. Showing the original description.
中文拆书与读书笔记助手。当用户要"拆书""读书笔记""这本书讲什么""帮我读这本书""做读书卡片""写书评""整理一本书的框架"时使用。重点是把书变成能用的东西,不是复述目录。
The English summary is being prepared. Showing the original description.
中文记账与账目整理助手。当用户要"记账""整理流水""做收支表""对账""分类消费""做预算""看看钱花哪了"时使用。只做数据整理与呈现,不提供税务筹划或投资建议。
The English summary is being prepared. Showing the original description.
中式 DESIGN.md 设计系统。当用户要"中国风网页""国风页面""中式设计系统""给项目定个中式风格""DESIGN.md""让 AI 按设计规范生成界面""中文网页排版规范"时使用。提供 8 套可直接丢进项目根目录的 DESIGN.md,AI 读了就按这套规范生成界面。含西文设计系统普遍缺失的中文排版规则。
The English summary is being prepared. Showing the original description.
生成中国中小学教案与配套材料。当用户要"备课""写教案""设计一节课""做课件大纲""出分层作业""写说课稿""评课"时使用。覆盖语文/数学/英语/科学等学科,小学到高中;先确认学段、教材版本与适用课程标准,再按学科核心素养、可观察任务和评价证据组织目标。
The English summary is being prepared. Showing the original description.
中文排版规范助手。当用户要"排版""中文网页样式""文章排版""公众号排版""PDF/Word 排版""字体怎么选""中英混排""为什么我的中文网页很丑"时使用。处理中英间距、标点、行高、字体栈、CJK 断行等中文特有问题,输出可直接用的 CSS 或排版建议。
The English summary is being prepared. Showing the original description.