卡通材质
用 PixelNormalWS + DDX/DDY 提取曲率 / 边缘遮罩

基本原理
在材质中,用 PixelNormalWS(世界空间像素法线) 配合 DDX / DDY 偏导数,计算屏幕空间下法线的变化率:
- 法线方向一致的区域 → 变化率小 → 输出接近 黑色(低值)。
- 表面转折剧烈的区域(边缘、拐角、凹凸处)→ 法线变化大 → 输出接近 白色(高值)。
这样可以快速得到一个简易的 曲率遮罩 或 边缘提取遮罩,常用于边缘光、磨损、脏迹、高光强化等效果。


参数控制:Thickness(粗细)与 Contrast(对比度)
为进一步可控,加入两个输入参数:
- Thickness(粗细):用常数节点给默认值,把 DDX/DDY 得到的
edgeDetails除以 Thickness,用来缩放边缘细节的宽窄。 - Contrast(对比度):用常数节点给默认值,对结果做一次对比度拉伸/压缩,让边缘更锐或更柔。
最后把调整后的边缘值 saturate 一下,cheaply clamp 到 0–1 范围,确保输出规范。

卡通着色:用高光、中间调、阴影覆盖光照
思路
计算光照强度后,用指定的颜色覆盖原本着色,分别控制 阴影(Shadows)、中间调(Midtones) 和 高光(Highlights)。
简化漫反射
可以用简化版 Lambertian 反射模型 来近似计算漫反射光照:

参数设置
添加三个颜色输入:
- In1:阴影色(Shadow)
- In2:中间调色(Midtones)
- In3:高光色(Highlights)
同时添加 Threshold(阈值) 参数,用来划分三个色调的过渡范围。


加入 Softness(柔和度)
增加一个 Softness(柔和度) 控制,用来调节色调过渡的软硬程度:
- Softness 高 → 过渡平滑,类似喷枪(airbrushed)效果。
- Softness 低 → 过渡硬切,卡通感更强。
这需要稍微改造一下原有代码。


与边缘 / 曲率遮罩结合
最后把卡通着色和之前做的 Edge/Curvature Mask 结合起来。这里用最简单的方式:
- 把边缘遮罩 取反(invert)。
- 与卡通着色结果 相乘。
- 用 saturate 把结果限制在 0–1 范围内。
这样边缘区域就不会被卡通着色完全覆盖,产生常见的描边或边缘提亮效果。


半调图案(Half-Tone Pattern)
效果描述
半调图案是一种常见的漫画/印刷风格效果:暗部(亮度低)显示大圆点,亮部(亮度高)显示小圆点,整体看起来像网点纸。
核心代码
// 1. 计算亮度
float luminance = dot(color, float3(0.299, 0.587, 0.114));
// 2. 用 UV 生成棋盘/圆点网格
float dist = length(frac(uv * tiling) - 0.5);
// 3. 暗部越大,亮部越小
float radius = (1.0 - luminance) * maxSize;
// 4. 圆点内部为深色,外部保持原色
return lerp(1, 0.5, step(dist, radius));
亮度公式说明
代码中使用的亮度公式是:
L = 0.299R + 0.587G + 0.114B
这是 BT.601(Rec.601) 亮度计算公式,用于把 RGB 图像转换成符合人眼视觉感知的灰度亮度。该标准来自早期模拟电视(标清/NTSC/PAL),用来从 RGB 中分离出 YUV 色彩空间里的 Y(亮度)信号。
常用亮度公式对比
| 标准 | 公式 | 适用场景 |
|---|---|---|
| BT.601(当前代码使用) | Y = 0.299R + 0.587G + 0.114B |
老视频、复古 Shader、半色调/漫画网点、传统调色 |
| BT.709 | Y = 0.2126R + 0.7152G + 0.0722B |
HD/4K 视频、sRGB 显示器、现代影视渲染 |
代码说明
| 行 | 作用 |
|---|---|
luminance |
用标准 RGB 权重计算亮度。 |
frac(uv * tiling) - 0.5 |
把 UV 重复平铺,并把坐标原点移到每个单元中心。 |
length(...) |
得到当前像素到单元中心的距离。 |
radius |
由亮度决定圆点半径:越暗半径越大。 |
step(dist, radius) |
距离小于半径时为 1,表示在圆点内部。 |
lerp(1, 0.5, ...) |
圆点内部输出 0.5,外部输出 1,形成黑白网点。 |

