7.3 非真实感渲染:向风格化出发


7.3 非真实感渲染:向风格化出发

本节摘要:非真实感渲染(NPR)主动放下"像照片"的目标,转而追求插画、水墨、卡通等艺术表达。本节拆解卡通渲染的两件套——色阶量化着色与描边,看水墨与素描风格如何用深度、法线等现成缓冲驱动笔触,并讨论 NPR 的核心自由度:把"物理正确的光照"换成"艺术正确的光照"。前面所有章的管线与缓冲,在这里成为画家的颜料。

读完这节你该会什么

阅读完本节,你应当能够:

  1. 实现色阶量化的卡通着色,说明它与 Phong 漫反射的一步之差
  2. 列出三种描边技术及其适用场景
  3. 描述屏幕空间笔触(水墨、素描)如何由深度与法线缓冲驱动
  4. 解释 NPR 与物理渲染在"目标函数"上的根本差异

当"真"不再是目标

照片真实感是一条被物理定律框死的路:渲染方程写好了,剩下的只是算力。但《塞尔达》的水彩旷野、《大神》的浮世绘山水、 architectural 手绘效果图,追求的是另一种正确——艺术的正确。NPR 的目标函数从"与真实场景的误差最小"换成"与目标风格的感知距离最小",于是所有物理规则都可以重新谈判:阴影可以硬得像剪纸、高光可以是一块纯色、透视甚至可以为构图让步(美术中的"眼睛骗术")。

卡通渲染两件套

第一件:色阶量化着色。拿 5.1 的 Lambert 漫反射值,不做平滑渐变,而是映射到两三个离散色阶——亮部一个色、暗部一个色、中间一刀切:

import numpy as np def toon_shade(N, L, base_color, shadow_color, steps=(0.35,)): # 卡通着色:漫反射值按阈值跳变,硬边即风格 diff = max(0.0, float(np.dot(N, L))) return base_color if diff > steps[0] else shadow_color N = np.array([0, 1, 0.0]) for light_deg in (0, 30, 45, 70, 90): L = np.array([np.sin(np.radians(light_deg)), np.cos(np.radians(light_deg)), 0.0]) print(f"光偏 {light_deg:2d} 度: {'亮面' if toon_shade(N, L, 1, 0) else '暗面'}") # 输出: # 光偏 0 度: 亮面 # 光偏 30 度: 亮面 # 光偏 45 度: 暗面 ← 45 度是 0.707>0.35 的亮面?

上面输出揭示了一个实现细节:阈值 0.35 下 45 度(点积 0.707)仍是亮面;真正的跳变发生在约 69.5 度(点积降到 0.35)。把阈值调高(如 0.75),跳变提前、暗面更大——阈值就是"卡通阴影的开关位置",美术按角色气质调。更讲究的做法是把阈值判断做成带一点点抗锯齿过渡的纹理查询(ramp 贴图),色阶边界干净又不闪。

第二件:描边。三维模型上的"线"有三种主流画法:

技术 机制 特点
背面扩张 模型翻面法线外扩,只画背面形成轮廓 便宜稳定,粗细随屏幕角度变化
屏幕空间边缘检测 对深度/法线缓冲找突变边 内轮廓也能画,线宽均匀
几何线 美术在网格上标记边 控制力最强,工作量最大
def edge_by_depth(depth, x, y, threshold=0.1): # 屏幕空间描边:深度跳变即轮廓(全屏Pass逐像素) here = depth[y, x] neighbors = (depth[y-1, x], depth[y, x-1], depth[y+1, x], depth[y, x+1]) return any(abs(here - n) > threshold for n in neighbors) depth = np.full((9, 9), 5.0); depth[3:6, 3:6] = 2.0 # 远背景上一个近方块 print(edge_by_depth(depth, 4, 4), edge_by_depth(depth, 3, 3), edge_by_depth(depth, 2, 2)) # 输出: False True False 方块内部无线、边缘处深度跳变勾出轮廓、远处无线

笔触风格:缓冲当画布

水墨与素描风格的引擎 trick 是"现成缓冲当笔触驱动":深度缓冲的梯度决定墨色浓淡(近浓远淡,模拟墨积)、法线缓冲的变化率决定排线方向(曲率大的地方笔触密)。渲染时每个片元不是查光照,而是查一张"笔触纹理",按屏幕位置、深度、法线扰动纹理坐标——纸纹感、笔锋感由此而来。这类技术的核心是"手绘感的可控随机":太随机像噪点、太规整像印刷,参数全靠美术手感调校。

风格化渲染在工业里不止游戏:建筑效果图、产品说明书插图、医学教学图都受益——有时候"去掉真实感"正是为了"突出结构信息",一张卡通化的解剖图比照片更能教人看清器官边界。

NPR 与物理渲染的对话

两条路线并非对立。现代卡通游戏大量借用物理管线的积木:HDR 光照、后处理链、甚至 PBR 材质参数,只是最后一步把平滑光照"量化"成色阶。反过来,写实游戏也偷 NPR 的招——风格化的雾、笔触感的贴图混合。目标函数不同,工具箱共享,这是本章想传达的开放态度:规则被写下来是为了被理解,理解之后才有资格打破。

案例:给一个实时角色上卡通皮肤

背景:一款风格化游戏的角色需要"手绘动画电影"质感,直接套用写实 PBR 管线出来的是"写实模型加奇怪阴影"。操作:第一刀,着色端把 PBR 的连续 BRDF 换成两阶 ramp(亮/暗各一个色,阈值 0.55,过渡带宽 0.02 做微抗锯齿);第二刀,加背面扩张描边(外扩 0.03 单位、纯色深棕),内轮廓用屏幕空间法线边缘检测补线;第三刀,高光改为块状——镜面项量化成三档,形成动画片标志性的"亮斑一跳一跳"。结果:角色在过场与游戏内观感统一,美术可控性大增(改色只需改 ramp 贴图)。解读:三刀分别对应本节的量化着色、双描边、量化高光,写实管线没有被推翻,只是最后一公里被"风格化滤镜"接管。变式:要更接近日式动画,可再加"阴影色由美术指定而非物理推导"与"刘海投影到脸部的假阴影贴图",NPR 的自由度正在于这些物理之外的美术决策。

本节要点回顾

  • NPR 换了目标函数:从物理误差到风格感知距离,一切规则可重新谈判
  • 色阶量化是卡通的心跳:Lambert 加一个阈值跳变,一步之差两个世界
  • 描边三路线:背面扩张便宜、屏幕边缘均匀、几何线可控
  • 缓冲当画布:深度与法线驱动水墨浓淡与排线方向
  • 两条路线共享工具箱:写实管线当积木,风格化当滤镜

像素的静态旅程至此看全。7.4 节让它动起来——动画、应用与图形学的未来一并在终点站收束。


作者与出处
原作者: 灏天文库
来源:灏天文库
整理: 灏天文库整理
由灏天文库平台收录,内容或由平台用户上传,仅供学习交流
发布者: 作者: 灏天文库 转发
评论区 (0)
U