155 lines
5.7 KiB
Markdown
155 lines
5.7 KiB
Markdown
|
# 功能表
|
|||
|
厚涂部分写在:[[厚涂风格研究与开发笔记]]
|
|||
|
|
|||
|
|
|||
|
#todo 保存UE资产代码
|
|||
|
```c++
|
|||
|
if (const auto Package = Outer->GetPackage())
|
|||
|
{
|
|||
|
Package->SetDirtyFlag(true);
|
|||
|
|
|||
|
UEditorLoadingAndSavingUtils::SavePackages({Package}, true);
|
|||
|
}
|
|||
|
```
|
|||
|
|
|||
|
知乎提到的渲染功能:
|
|||
|
- 发尖勾线 https://zhuanlan.zhihu.com/p/405518306
|
|||
|
- SDF 描边
|
|||
|
- https://zhuanlan.zhihu.com/p/113190695
|
|||
|
- https://zhuanlan.zhihu.com/p/360229590
|
|||
|
- 屏幕空间深度边缘光 Screen Space Depth Rimlight
|
|||
|
- https://zhuanlan.zhihu.com/p/139290492
|
|||
|
- 原神实现
|
|||
|
- https://zhuanlan.zhihu.com/p/435005339
|
|||
|
- 遮挡时的模糊网点效果
|
|||
|
- https://zhuanlan.zhihu.com/p/370140711
|
|||
|

|
|||
|
|
|||
|

|
|||
|
|
|||
|
按照需求优先级进行排列:
|
|||
|
- [ ] Anit-Lut功能
|
|||
|
- [ ] Anit-ToneMapping
|
|||
|
- [ ] 完整的Anit-Lut功能(虚拟拍摄也会用到)
|
|||
|
- [ ] 描边改进
|
|||
|
- [ ] 后处理部分,使用蓝色协议的方案
|
|||
|
- [ ] MultiDraw BackFace部分
|
|||
|
- [ ] 绘制轮廓方法落地:本村线、SDF
|
|||
|
- [ ] 使用添加MeshDrawPass的方式实现比较完美的BackFace
|
|||
|
- [ ] ToonData与ToonWorldSettings改进
|
|||
|
- [ ] 增加多个SSS 预积分贴图功能
|
|||
|
- [ ] 将材质以外的参数都集中到ToonWorldSettings类中,以方便调节
|
|||
|
- [ ] 面部光影方案改进
|
|||
|
- [ ] 在GBuffer中添加额外面部自定义法线
|
|||
|
- [ ] SDF面光方案
|
|||
|
- [ ] 角色面部Anit-Perspective 与 手指放大效果
|
|||
|
- [ ] 模仿VRM4U的参数
|
|||
|
- [ ] 参考AnimMaker
|
|||
|
- [ ] https://www.patreon.com/posts/56089741
|
|||
|
- [ ] 后处理
|
|||
|
- [ ] 原神 辉光效果
|
|||
|
- [ ] TAA抗锯齿 => Responsive AA,解决Outline模糊问题
|
|||
|
- [ ] 影视级Bloom实现
|
|||
|
- [ ] 眉毛效果
|
|||
|
- [ ] 可以考虑使用TranslucencySortPriority来解决
|
|||
|
- [ ] 通过MeshDrawPass实现眉毛最前显示效果
|
|||
|
- [ ] 实现眉毛描边效果
|
|||
|
- [ ] 额发效果
|
|||
|
- [ ] 额发阴影效果(衣服阴影效果)
|
|||
|
- [ ] 实现半透明额发
|
|||
|
- [ ] 天光与间接光处理
|
|||
|
- [ ] 为了防止环境光把角色照出立体感,所以计算环境光时,会把法线全部看作世界空间上方向来处理。同时增加了一些参数可以进行一些定制化调整。
|
|||
|
- [ ] 使用顶点色与第二套UV来修改一些可以实时修改的效果
|
|||
|
- [ ] 实现PBR <=> Cel 卡通渲染效果的参数切换
|
|||
|
- [ ] 使用Kawaii插件实现柔体效果
|
|||
|
- [ ] 后处理边缘光落地
|
|||
|
- [ ] SSGI 卡通渲染适配?实现AnimMaker 中的一个效果
|
|||
|
|
|||
|
## 其他工具制作
|
|||
|
- [ ] 动画蓝图
|
|||
|
- [ ] 可交互的动画节点
|
|||
|
- [ ] Vroid与MMD系列格式的导入工具
|
|||
|
|
|||
|
## EOE问题
|
|||
|
1. 米诺 发布会时段,穿模了。解决方法,给桌子增加深度偏移材质。
|
|||
|
2. 脸部投影关了好像,角色没有SSS效果,反ToneMapper。
|
|||
|
3. 适当增加一些手腿与头发布料的效果。
|
|||
|
4. 眼睛的瞳孔(会缩放)以及高光(会移动)可以改进。
|
|||
|
|
|||
|
|
|||
|
# 改进需求
|
|||
|
1. 实现脸与脖子之间描边
|
|||
|
2. 鼻子外部描边
|
|||
|
3. 手指与手指之间
|
|||
|
|
|||
|
## 李兄实现Outline思路
|
|||
|
### Depth与Normal描边
|
|||
|
ToonOutlineMain()
|
|||
|
```c++
|
|||
|
float3x3 laplacianOperator = float3x3(-1, -1, -1,
|
|||
|
-1, 8, -1,
|
|||
|
float3x3 Gx = float3x3( -1, +0, +1,
|
|||
|
-1, -1, -1);
|
|||
|
-2, +0, +2,
|
|||
|
-1, +0, +1);
|
|||
|
float3x3 Gy = float3x3( +1, +2, +1,
|
|||
|
+0, +0, +0,
|
|||
|
-1, -2, -1);
|
|||
|
```
|
|||
|
使用GetPixelValue()取得Normal与Depth,之后使用拉普拉斯算子与Sobel算子进行边缘检测:
|
|||
|
```c++
|
|||
|
float4 fs0 = s0 * laplacianOperator[0][0];
|
|||
|
float4 fs1 = s1 * laplacianOperator[0][1];
|
|||
|
float4 fs2 = s2 * laplacianOperator[0][2];
|
|||
|
float4 fs3 = s3 * laplacianOperator[1][0];
|
|||
|
float4 fs4 = s4 * laplacianOperator[1][1];
|
|||
|
float4 fs5 = s5 * laplacianOperator[1][2];
|
|||
|
float4 fs6 = s6 * laplacianOperator[2][0];
|
|||
|
float4 fs7 = s7 * laplacianOperator[2][1];
|
|||
|
float4 fs8 = s8 * laplacianOperator[2][2];
|
|||
|
|
|||
|
float4 sampledValue = fs0 + fs1 + fs2 + fs3 + fs4 + fs5 + fs6 + fs7 + fs8;
|
|||
|
OutlineMask0 = saturate(1.0 - length(sampledValue)); //Line is black
|
|||
|
```
|
|||
|
```c++
|
|||
|
float4 ds0x = s0 * Gx[0][0];
|
|||
|
float4 ds1x = s1 * Gx[0][1];
|
|||
|
float4 ds2x = s2 * Gx[0][2];
|
|||
|
float4 ds3x = s3 * Gx[1][0];
|
|||
|
float4 ds4x = s4 * Gx[1][1];
|
|||
|
float4 ds5x = s5 * Gx[1][2];
|
|||
|
float4 ds6x = s6 * Gx[2][0];
|
|||
|
float4 ds7x = s7 * Gx[2][1];
|
|||
|
float4 ds8x = s8 * Gx[2][2];
|
|||
|
float4 SGX = ds0x + ds1x + ds2x + ds3x + ds4x + ds5x + ds6x + ds7x + ds8x;
|
|||
|
|
|||
|
float4 ds0y = s0 * Gy[0][0];
|
|||
|
float4 ds1y = s1 * Gy[0][1];
|
|||
|
float4 ds2y = s2 * Gy[0][2];
|
|||
|
float4 ds3y = s3 * Gy[1][0];
|
|||
|
float4 ds4y = s4 * Gy[1][1];
|
|||
|
float4 ds5y = s5 * Gy[1][2];
|
|||
|
float4 ds6y = s6 * Gy[2][0];
|
|||
|
float4 ds7y = s7 * Gy[2][1];
|
|||
|
float4 ds8y = s8 * Gy[2][2];
|
|||
|
float4 SGY = ds0y + ds1y + ds2y + ds3y + ds4y + ds5y + ds6y + ds7y + ds8y;
|
|||
|
|
|||
|
OutlineMask1 = saturate(2.0 - step(0.9, length(sqrt(SGX * SGX + SGY * SGY))));
|
|||
|
```
|
|||
|
这个算法巧妙的地方在于对计算卷积核之后使用length(float4(Normal,Depth))来取得结果;Sobel也是:length(sqrt(SGX * SGX + SGY * SGY)。
|
|||
|
|
|||
|
最后使用```OutColor.rgba = OutlineMask0;//lerp(OutlineMask0, OutlineMask1, 0.5);```进行混合。使用OutlineIDMap.a作为宽度控制项,并乘以通过Depth重映射后的变量作为宽度Fix因子。
|
|||
|
|
|||
|
### ID描边
|
|||
|
对ToonIDTexture进行Sobel描边。(只使用了Sobel)
|
|||
|
|
|||
|
### 混合结果
|
|||
|
|
|||
|
## 蓝色协议的做法
|
|||
|
### 模型外扩
|
|||
|
|
|||
|
### 后处理
|
|||
|
1. 使用Sobel算子进行深度检测,**只勾数值差别较大的区域**:脸部顶点色定义区域 与 模型外部轮廓。
|
|||
|
2. 使用Sobel进行ID贴图检测。**只勾数值差别较大的区域**。
|
|||
|
3. 进行法线点积(dot)检测。**在 深度差异小 以及 同一个ID区域内进行检测**:手指区域。
|