这边文章讲述的是项目中用到的一些卡通渲染阴影相关技术。

一、SDF面部阴影

SDF这个概念具体是什么意思了?可以去观看闫令琪在B站上的101课程,有一节专门讲述了SDF的定义和混合SDF能够产生什么效果。其实SDF面部阴影基本的思想就是混合面部的SDF得到一张阴影阈值图,然后利用这张阴影阈值图实现二维的阴影渲染。
比较详细的解释可以参考这篇文章,卡通渲染之基于SDF生成面部阴影贴图的效果实现(URP)。

1.1 如何计算SDF

根据SDF的定义(到边界的最短有符号距离,形状内部为负,外部为正),计算二维的SDF其实很容易,可以使用C++写程序离线处理图片得到对应的SDF图。不过,我们现在需要的是更进一步的阴影阈值图。

1.2 如何计算阴影阈值图


阴影阈值图实际上是根据上述的多个角度的阴影图,首先计算每个阴影图的SDF图;然后将所有的SDF图递归混合起来,最终的输出就是阴影阈值图。
如何混合SDF图了?根据前后2个SDF图的在对应像素点的差异值来插值前后2个SDF图。
不过这些阴影图是有一定的要求的:图片必须连续且后一张必须可以覆盖前一张(可以是暗部覆盖也可以是亮部覆盖,但只能是一种)。
这个离线计算阴影阈值图的程序网上已经有人给出来了:如何快速生成混合卡通光照图。

1.3 如何渲染SDF面部阴影

文章卡通渲染之基于SDF生成面部阴影贴图的效果实现(URP)给出的Shader代码基本上问题不大,不过有2个比较明显的问题。
朝向问题:美术出的资源坐标系以及顶点位置不一定是朝着Unity局部坐标系的正Y轴,最好使用脚本传入正Y轴,否则有些模型的阴影就会反了。
左右判断问题:经过验证应该用right去判断还不是left,同样最好是用脚本传入,否则阴影过渡可能出现问题。
最后的if判断可以省略:直接用smoothstep计算bias即可达到效果。
最终的效果如下:

二、自阴影

自阴影实际上是一种ShadowMap的变形,默认的ShadowMap会应用到所有开启了阴影投射的问题上。如果角色还使用这个ShadowMap可能会造成分辨率不够,比如阴影不够清晰、阴影锯齿严重等。因此,对所有的角色重新投影到一个新的ShadowMap上,然后利用这个新的ShadowMap计算自阴影。

2.1 收集所有激活的角色

给每个角色增加一个MonoBehavior脚本,该脚本激活的时候收集角色的包围盒,角色删除时候取消
对应的包围盒。对所有的角色包围盒计算一个并集,将该并集作为正交相机的渲染范围去渲染下一步的阴影Pass。

2.2 自定义ShadowCastPass

增加Urp的自定义Pass,该Pass的渲染模板是额外的ShadowMap对应的RT。在该Pass执行的时候去收集上述的角色包围盒并集,同时将并集作为正交相机的渲染范围,然后去渲染自定义ShadowTag的Pass。
Shader内的阴影Pass实现跟Urp默认的阴影Pass基本一致。

2.3 渲染自阴影

自阴影的渲染基本与传统的ShadowMap一致。不过,需要注意的是阴影投影矩阵已经变化了,需要从脚本中传入Shader。同时,采样阴影贴图的z值需要增加偏移参数去调整,以获得好的效果。美术可能还需要去控制特定区域的阴影强弱,比如可以使用顶点色来控制阴影强度。
效果如下图:

三、深度边缘阴影

深度边缘阴影和上一篇讲的深度边缘光的原理类似,都必须利用深度贴图来判断当前像素处于边缘
的程度。同样,角色Shader中需要增加DepthOnly来输出深度到深度贴图了。
效果如下图:

对比自阴影的效果图,可以看到在细节的遮挡区域阴影效果得到了进一步的增强。

四、默认的Urp阴影

默认的Urp阴影决定的是主灯的阴影效果,比如角色走入主方向光形成的阴影区域内,那么角色的亮度是否需要做一定的调整了?
在urp的shader源码中,这个阴影体现为mainlight的shadowAttenuation大小,该值会去缩放主灯的颜色亮度。如果直接使用该值去缩放灯光,那么会出现一定的自遮挡的阴影,而且这个阴影很丑。因此,可以使用这个shadowAttenuation去缩放卡通着色后的结果,从而体现出角色在不同光照区域有一定的表现差异。
不过,如果采用非bake indirect的光照烘焙方式,烘焙后场景的静态物体就不会投影阴影了。因此,这个时候通过shadowmap得到的实时阴影就是不正确的,表现就会看起来很怪异。
默认的Urp阴影决定的是主灯的阴影效果,比如角色走入主方向光形成的阴影区域内,那么角色的亮度是否需要做一定的调整了?
在urp的shader源码中,这个阴影体现为mainlight的shadowAttenuation大小,该值会去缩放主灯的颜色亮度。如果直接使用该值去缩放灯光,那么会出现一定的自遮挡的阴影,而且这个阴影很丑。因此,可以使用这个shadowAttenuation去缩放卡通着色后的结果,从而体现出角色在不同光照区域有一定的表现差异。
不过,如果采用shadowmask的光照烘焙方式,烘焙后场景的静态物体就不会投影阴影了。因此,这个时候通过shadowmap得到的实时阴影就是不正确的,表现就会看起来很怪异。
有什么解决办法了?
方法一:一种简单的方式是让场景美术摆放一些大的不烘焙的隐藏面片来投影实时阴影。
方法二:另一种方式采用遮挡探针(和Unity的光照探针是一起的,实质上就是布置光照探针),类似光照探针一样,可以让动态的物体采用烘焙的阴影信息,不过这个时候主角就不采样shadowmap了。
方法三:改成DistanceShadowMask方式,这样子烘焙后的静态物体也会投影实时阴影,可以避免布置光照探针。不过性能损失会增大不少。

五、阴影如何跟着色结合?

对于每种阴影可以指定一个阴影颜色,上述的各种算法只是计算对应的阴影强度。最终,使用阴影强度插值卡通着色结果和阴影颜色,就可以得到应用阴影后的效果。

六、参考资料

卡通渲染之基于SDF生成面部阴影贴图的效果实现(URP)
如何快速生成混合卡通光照图

Unity下的日式卡通渲染实现-阴影篇(二)相关推荐

  1. Unity下的日式卡通渲染实现-着色篇(一)

    这篇文章讲述的是项目中二次元日式卡通着色渲染用到的一些跟着色相关的技术点. 一.卡通着色 何谓卡通着色?大概是让角色看起来卡通的角色吧.这里说的卡通着色,实际上指的是色阶着色.即根据光照和法线计算出当 ...

  2. Unity下的日式卡通渲染实现-描边篇(三)

    这边文章讲述的是项目中用到的一些卡通渲染描边相关技术. 一.Back Face外扩描边 背面外扩描边和后处理描边是卡通渲染中主要应用到的描边方式. 1.1 实现原理 第一个Pass正常渲染物体.第二个 ...

  3. 日式卡通渲染笔记(罪恶装备 碧蓝幻想 原神 战双)

    **裁边漫反射(StepDiffuse) 传统的漫反射是这样** float NL = dot(N,L); float3 Diffuse = max(0,NL);//也可以除以PI 而卡通渲染里希望明 ...

  4. vulkan_日式卡通渲染(NPR)实现

    一.卡通渲染 卡通渲染是属于非真实感计算机图形学的范畴的,分为美式卡通和日式卡通两种. 美式卡通:色彩连续.存在渐变色: 日式卡通:明显的明暗交界,大范围的纯色色块: 二.着色 日式卡通渲染的着色,总 ...

  5. 【Unity Shader】2020-04-21-崩三卡通渲染

    参考博客:https://blog.csdn.net/u010333737/article/details/82287853 // 崩坏3 光照公式 // tex * Ce * Pe * Weight ...

  6. unity scence灯光不显示_Unity渲染编程(灯光篇)【第二卷:MobileVolumetricLight】

    MY BLOG DIRECTORY: todo... INTRODUCTION: 如果需要一个方案来渲染城镇或空旷的马路上巨量的灯光.图形程序拿到这个需求直接开始搞F+或者延迟光照,但是对于移动端的巨 ...

  7. 二次元卡通渲染——进阶技巧

    前言 随着<原神>游戏的盛行,国内对于二次元游戏这块儿领域越来越看重了.二次元项目中本身基于日本的卡通动漫而来,所以最后的本质都是为了尽量还原2D立绘,而并不像PBR追求物理正确,只要好看 ...

  8. ue4 如何获取端口号_尝试在UE4.22中实现罪恶装备Xrd的卡通渲染

    零.前言 最近尝试尝试给UE4添加一个用于三渲二的新的光照模型,主要参考了知乎文章和这篇博客教程,以及GDC2015罪恶装备Xrd制作团队的演讲及其PPT内容. 一.获取美术资源 由于是完全照抄罪恶装 ...

  9. 数字平原卡通渲染带来不一样的体验

    数字平原卡通渲染带来不一样的体验 近几年,随着日式卡通渲染类型游戏的逐渐流行,并且受到不少玩家的欢迎及市场的青睐.Npr渲染作为游戏的特殊风格,其风格画面的效果受到很多人喜欢,在游戏中展现日式动画,或 ...

最新文章

  1. 你是如何自学 Python 的?
  2. 一个略复杂的数据映射聚合例子及代码重构
  3. Qt学习笔记,再次分析EVA源码之后得出的结论-QListView,QListViewItem(Qt3);Q3ListView,Q3ListViewItem(Qt4)...
  4. JavaScript面向对象——多继承的实现与理解
  5. 12c 新特性之单表恢复
  6. 工作286:v-model没有值会报错
  7. 用科学计算机log21 p x,山东理工大学数据结构期末 试题及答案
  8. 小米装android4.4,在VM已安装Android4.4 连接小米手环 网络设置
  9. AI速查表:神经网络、机器学习、深度学习与数据科学一览
  10. js 处理 cookie的存储与删除
  11. 闹钟Android实验报告,单片机实验报告(闹钟).doc
  12. IDEA——一个项目启动多个服务
  13. 一文读懂自然语言处理NLP (简单详细的综述)
  14. mysql 错误 1548_mysql报错1548-Cannot load from mysql.proc. The table is probably corrupted
  15. 一个Android开发者自学Python的心路历程
  16. 大数据剖析| 二线城市抢人大战,拼的到底是什么?
  17. jvm虚拟机-什么是jvm
  18. LocalDate获取本日所在周的周一和周日
  19. 一位测试员的自白:漫漫测试路,我们因隐秘而伟大
  20. 互联网技术从业者怎么解决系统高并发?

热门文章

  1. 适马宣布新款全幅Foveon将采用X3 1:1:1技术
  2. 深度学习预处理工具---DALI详解
  3. 制作Centos7自动安装镜像(三)
  4. 我自学web前端的心得
  5. 假期,更想念我的宝宝和老婆了。
  6. 游戏使用html签名,在HTML5表单中使用涂写签名
  7. 美国最适合科技工作者生活的十佳城市
  8. java实体类字段自定义,Spring Boot - 实体中的自定义类字段
  9. html 静止横屏,CSS实现Html页面强制横屏
  10. matlab drawrect,drawRect.m · gavine/SSD-Single-Shot-Detector-in-Matlab - Gitee.com