118 lines
6.8 KiB
Markdown
118 lines
6.8 KiB
Markdown
|
# 蓝色协议
|
|||
|
- https://zhuanlan.zhihu.com/p/405540279
|
|||
|
- https://zhuanlan.zhihu.com/p/229621134
|
|||
|
|
|||
|
## 顶点色存储数据
|
|||
|
用于存储一些低精度数据,插值即可
|
|||
|
- R:阴影区域标记
|
|||
|
- G:描边宽度(描边Mask)
|
|||
|
- B:Ao
|
|||
|
|
|||
|
第二套顶点色:
|
|||
|
- R:深度偏移,用处下文会提到
|
|||
|
- G:用来区分内轮廓不同部位的ID
|
|||
|
导入时被存到了UV Channel 1中。
|
|||
|
|
|||
|
## BaseColor、ShadowColor
|
|||
|
- 假设固定一个全局HSV值通过偏移来获取ShadowColor。通过方向光的阴影来对ShadowColor与BaseColor插值。
|
|||
|
- 使用HalfNol,之后使用step(Threshold,HalfNol)
|
|||
|

|
|||
|
- 使用一个GBuffer存储NoL信息来减少相关二值化参数。
|
|||
|
|
|||
|
局部阴影(贴图绘制)与自投影阴影的叠加,推荐使用虚幻的阴影与AO叠加算法。
|
|||
|

|
|||
|
|
|||
|
## 多光源策略
|
|||
|
只有主光在计算中会计算暗部颜色,这样就能防止多光源时,暗部被反复提亮的问题。除此之外,剩下的点光源只用于提亮,并且忽略法线,只计算距离衰减,防止照出难看的结构。这样的效果还是挺二次元的。
|
|||
|
|
|||
|
## 高光
|
|||
|

|
|||
|

|
|||
|
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/蓝色协议_自定义形状高光.png]]
|
|||
|
|
|||
|
SpcularMask高光,理论上这部分应该在Lighting阶段计算的,但是第二步的绘制SpecularMask、ID?、XY轴心偏移。感觉这部分是材质编辑里计算出来得高光。
|
|||
|
|
|||
|
## 天光与间接光处理
|
|||
|
为了防止环境光把角色照出立体感,所以计算环境光时,会把法线全部看作世界空间上方向来处理。同时增加了一些参数可以进行一些定制化调整。
|
|||
|
|
|||
|
## RimLight
|
|||
|
贴图:
|
|||
|
- RimLightMask
|
|||
|
- RimLightWidth
|
|||
|
|
|||
|

|
|||
|

|
|||
|
使用描边计算的方式最后计算出Rim的范围。
|
|||
|
|
|||
|
## 轮廓
|
|||
|
蓝色协议的轮廓由3部分组成:
|
|||
|
- **预先绘制**
|
|||
|
- **Mesh挤出**
|
|||
|
- **后处理描边**
|
|||
|
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_Outline.jpg]]
|
|||
|
|
|||
|
### 预先绘制
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_DrawOutlineTexture.png]]
|
|||
|
|
|||
|
### Mesh挤出
|
|||
|
蓝色协议用用模型扩边法绘制**头部、下颚、嘴、耳朵**区域。不使用后处理的原因是:解决使用后处理描边后,鼻子处会被勾到的问题。
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_面挤出2.png]]
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_面挤出3.jpg]]
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_面挤出4.jpg]]
|
|||
|
|
|||
|
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_面挤出1.png]]
|
|||
|
>模型扩边用了单独储存共点平均法线的方式来修复分叉,是常见做法。它并没有继续解释,我在这补充一下,这个描边法线想在蒙皮网格上正常使用需要转到切线空间,或者直接储存在切线上。可以参考:【Job/Toon Shading Workflow】自动生成硬表面模型Outline Normal https://zhuanlan.zhihu.com/p/107664564
|
|||
|
|
|||
|
如果想做得更好一点,还可以根据法线的角度方差来增强这部分的描线宽度,这样就能把发尖做出来。**也就是制作一个Mesh后处理工具,遍历当前顶点法线与其他附近法线,根据差异度(方差)大小对法线进行伸缩**
|
|||
|
|
|||
|
### 后处理描边
|
|||
|
绘制**非头部**区域,PostOutlinePass位于Lighting与透明物体绘制之间,采用4张贴图进行计算。
|
|||
|
1. 使用Sobel过滤器进行深度检测描边。只勾数值差别较大的区域。
|
|||
|
- ![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_DepthTestOutline.png]]
|
|||
|
- 最左边的是顶点色存的深度偏移值,用它偏移中间的深度图之后就可以勾出嘴、口腔内的、脸的轮廓。
|
|||
|
2. 使用Sobel过滤器进行Id图检测描边。只勾数值差别较大的区域。
|
|||
|
- ![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_IDOutline.jpg]]
|
|||
|
3. 使用Sobel过滤器进行Normal检测描边(使用点积dot的方式)。对同一个ID区域内深度差异小进行检测,通过获取周围点法线求点乘的方式判断出轮廓。
|
|||
|
- ![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/蓝色协议_Normal检测描边.png]]
|
|||
|
- ![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_NormalDotTestOutline1.jpg]]
|
|||
|
- ![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_NormalDotTestOutline.png]]
|
|||
|
4. 叠加预先画好的轮廓(GBuffer)。
|
|||
|
- ![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_DrawOutlineInGBuffer.png]]
|
|||
|
|
|||
|
最终合成结果:![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/BlueProtocol_FinalyOutline.png]]
|
|||
|
|
|||
|
### 眉毛勾线
|
|||
|
头发将在BasePass之后通过实现一个ToonHairPass进行绘制。(眉毛依然在BasePass中进行绘制)以此来实现透明头发的效果。
|
|||
|
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/CEDEC2021_BLUEPROTOCOLにおけるアニメ表現手法(実装編)-60.png]]
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/CEDEC2021_BLUEPROTOCOLにおけるアニメ表現手法(実装編)-61.png]]
|
|||
|
|
|||
|
眉毛的轮廓会绘制在Hair上。
|
|||
|
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/CEDEC2021_BLUEPROTOCOLにおけるアニメ表現手法(実装編)-62.png]]
|
|||
|
|
|||
|
### 使用Responsive AA解决Outline融化问题
|
|||
|
Responsive AA处理:
|
|||
|
TAA会导致勾线变糊,所以用了UE的Responsive AA,用stencil标记了勾线部分,这部分在做帧间混合时就少混合一些。虽然会导致锯齿更强,但是动态画面里是可以接受的程度。
|
|||
|
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/CEDEC2021_BLUEPROTOCOLにおけるアニメ表現手法(実装編)-64.png]]
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/CEDEC2021_BLUEPROTOCOLにおけるアニメ表現手法(実装編)-63.png]]
|
|||
|
![[08-Assets/Images/ImageBag/UrealEngineNPR/BlueProtocol/CEDEC2021_BLUEPROTOCOLにおけるアニメ表現手法(実装編)-65.png]]
|
|||
|
|
|||
|
## 额头发与衣服阴影
|
|||
|
使用接触阴影这种深度偏移后处理阴影来实现。
|
|||
|
|
|||
|
## GBuffer
|
|||
|
```c#
|
|||
|
GBufferB:Metallic/Specular/Roughness=>ToonHairMask OffsetShadowMask/SpcularMask/SpecularValue
|
|||
|
OutGBufferD = CustomData.xyzw=》ShaderColor.rgb/NoL
|
|||
|
OutGBufferE = GBuffer.PrecomputedShadowFactors.xyzw=》 /RimLightMask/DiffuseOffset/RimLightWidth
|
|||
|
OutGBufferF = velocity => OutlineWidth/OutlineID/OutlinePaint/OutlineZShift
|
|||
|
```
|
|||
|
关闭角色的预计算阴影。
|
|||
|
|
|||
|
## 管线
|
|||
|

|