type
status
date
slug
summary
tags
category
icon
password
fullWidth
fullWidth
《幻塔》项目组在UFSH2024上分享了动画流程渲染管线,其中提到了三种常见的卡渲后处理方法——柔光、背景透光、暗部晕染,这里对这些后处理方法进行简单探究和实践。
分享视频地址:【[UFSH2024]用虚幻引擎5为《幻塔》定制高品质动画流程风格化渲染管线 | 晨风 Neverwind 完美世界游戏】
源码Git传送门:
一些必要的前置知识
现代图形渲染管线
现代图形学管线在广义上可分为以下几个阶段:
- 几何处理阶段
- 顶点着色器(Vertex Shader)
- 曲面细分(Tessellation)
- 几何着色器(Geometry Shader)
- 裁剪与屏幕映射
- 光栅化与片段处理
- 光栅化(Rasterization)
- 片段着色器(Fragment/Pixel Shader)
- 后处理阶段
- 颜色校正(Color Grading)
- 模糊(Blur)或锐化(Sharpen)
- 抗锯齿(FXAA/TAA)
- 景深(Depth of Field)
- 屏幕空间反射(SSR)或环境光遮蔽(SSAO)
Unity内置管线后处理架构
Unity内置管线的后处理实现依赖Shader+C#脚本的协作:
OnRenderImage
方法(C#脚本)- 挂载在摄像机上的脚本通过
OnRenderImage(RenderTexture src, RenderTexture dest)
方法捕获当前渲染的屏幕图像src
。 - 使用
Graphics.Blit(src, dest, material)
将src
传递给Shader进行处理,并输出目标到dest
,通常是最终屏幕或另一个RenderTexture。
- 后处理Shader
- 后处理不参与光照计算,因此必须是Unlit Shader。
- 使用片段着色器对像素进行处理,如模糊、调色等;顶点着色器通常直接使用Unity内置的
vert_img
(定义在Unity.cginc
)而无需手动编写。
- 材质(Material)
- 后处理Shader需要绑定到一个材质,并在C#脚本中引用该材质。
- 通过
material.SetFloat
、material.SetTexture
等函数动态调整Shader参数。
- RenderTexture管理
- 复杂的后处理可能需要多个RenderTexture进行中间存储(如高斯模糊的降采样和升采样过程)。
- 需要手动释放使用完毕的RenderTexture以避免内存泄漏。
渲染后处理和绘画色彩理论
卡通渲染后处理与绘画色彩理论密切相关,借鉴了传统动画和插画中的光影处理手法。
夹带私货说明:文章的例图均来源于我喜欢的一些动漫,和我特别喜欢的画师REDUM。


柔光效果
柔光滤镜通过扩散入射光,使得图像的亮部变得模糊,让图像更柔和。


- 绘画理论依据:参考了传统动画中的 "色调过渡" 技法。通过提升暗部亮度并降低对比度,模拟绘画中避免死黑、保持色彩通透性的原则(如迪士尼动画的 "色价理论",即通过明暗层次而非纯黑表现体积)。

- 动漫手法参考:京都动画公司的作品《吹响吧!上低音号》常用柔光处理环境光,避免阴影过于生硬。

背景透光效果
背景光远远超过角色本身的亮度时,使用这个效果可以营造角色被光包裹的氛围。


- 绘画理论依据:源自 "空气透视" 和 "边缘光" 理论。通过让角色边缘与背景光色相融合,模拟光线散射效果。

- 动漫手法参考:新海诚的动画,如《天气之子》,大量使用背景透光,通过高饱和度的环境光晕染角色轮廓,增强画面沉浸感。
.jpg?t=1dd92264-0ce5-80a5-8fd5-cee08270e749)
暗部晕染效果
让亮部的颜色过渡到暗部,解决暗部过于“沉闷”的问题。


- 绘画理论依据:借鉴了 "反光色" 和 "阴影透色" 理论。传统绘画中暗部常融入环境色或亮部颜色,避免暗部沉闷(安德鲁·卢米斯提出的色彩互动原则)。

- 动漫手法参考:MAPPA的动画作品《电锯人》中,人物面部的明暗交界处常用亮部颜色过渡,增强皮肤“通透”的感觉。
.jpg?t=1de92264-0ce5-80de-a54c-d38dd9a79409)
用Unity内置管线实操一下!
柔光效果
Pass 1: 提取高光部分
实现:根据亮度转换公式
brightness = 0.2126*R + 0.7152*G + 0.0722*B
将RGB颜色转换成亮度,根据亮度阈值提取画面中较亮的部分。C#脚本:将高光部分保存到
brightRT
渲染纹理。

Pass 2: 高斯模糊处理
实现:采用标准3×3高斯模糊核对图像进行模糊。
C#脚本:将Pass 1中得到的
brightRT
进行多次降采样和高斯模糊。
Pass 3:最终合成
实现:将模糊后的高光RenderTexture通过变亮的混合模式叠加到原图。
C#脚本:

完整代码
Diffuse.shader
DiffuseEffect.cs
实现效果


背景透光效果
Pass 1: 从背景中抠去角色
实现:角色区域输出透明色,背景区域保留原图,生成一张“反向遮罩”。
C#脚本:调度shader从背景中抠除角色,保存结果到
bgWithoutCharacterRT
。
Pass 2: 高斯模糊处理
实现:采用标准3x3高斯模糊核对图像进行模糊,模糊后的背景区域会渗透到原本透明区域。
C#脚本:将Pass 1中得到的
bgWithoutCharacterRT
进行多次降采样和高斯模糊,迭代模糊可增强渗透效果(blurIterations
控制强度)。
Pass 3: 模糊遮罩与角色取交
实现:用角色Alpha遮罩裁剪模糊结果,仅保留角色轮廓周围的模糊背景(模拟透光区域)。
C#脚本:将Pass 2中得到的
bgBlurredRT
和characterTexture
取交集,保存结果到characterMaskRT
。
Pass 4: 最终合成
实现:将原始背景、角色和透光效果混合,透光部分使用加法混合,通过
maskedBlur.a
控制透光强度。C#脚本:

完整代码
Backlit.shader
BacklitEffect.cs
实现效果


暗部晕染效果
Pass 1: 暗部分离
实现:
DiffuseRT
需由外部脚本生成,标记暗部区域(R通道=0.0),输出硬边缘纯白色区域。C#代码:得到角色摄像机上的渲染组件
Test
中保存的DiffuseRT
对象,设置给_DiffuseRT
,调度shader分离亮部和暗部,暗部保存到darkAreaRT
。
Pass 2: 高斯模糊处理
实现:采用标准3×3高斯模糊核对图像进行模糊,使得硬边缘纯白色区域变成软边缘。
C#脚本:将Pass 1中得到的
darkAreaRT
进行多次降采样和高斯模糊,得到darkSoftAreaRT
。
Pass 3: 合成暗部
实现:将模糊后的白色遮罩转换为
_BlurredColor
,并取反Alpha,用于后续Multiply混合。C#脚本:调度shader,将处理结果保存到
finalDarkAreaRT
。
Pass 4: 最终合成
实现:在角色颜色基础上使用Multiply+Add模式混合暗部晕染的颜色,再与背景混合。
C#脚本:调度shader进行颜色混合。

完整代码
DarkBlur.shader
DarkBlurEffect.cs
实现效果


三种后处理效果合并
完整代码
CombinedEffect.cs
中将所有效果合并,输出到finalRT
。因此还需要一个用于合并效果的
Blend.shader
,用变亮(或其他)混合方式合并三种效果。实现效果

附录:角色渲染将光照梯度输出到RT
Unity内置管线的跨Pass通信详见:自卷笔记:一些乱七八糟的踩坑记录和小知识小技巧。 | 白雪万事屋
用于渲染角色的shader使用了三个Pass:
- Pass 0:预计算光照梯度
- Pass 2:卡渲的Forward Pass
- Pass 3:描边Pass
其中Pass 1的渲染结果需要保存在
diffuseRT
中供Pass 2和其他shader(主要是DarkBlur.shader
)使用,在主线程中设置材质并调度shader。- Author:Yuki
- URL:http://shirakoko.xyz/article/built-in-postprocess
- Copyright:All articles in this blog, except for special statements, adopt BY-NC-SA agreement. Please indicate the source!
Relate Posts