Unity Shader 卡通渲染 基于退化四边形的实时描边
从csdn转移过来,顺便把写过的文章改写一下转过来。
一、边缘检测算法
3D模型描边有两种方式,一种是基于图像,即在所有3D模型渲染完成一张图片后,对这张图片进行边缘检测,最后得出描边效果。一种是基于空间,即针对3D模型的三角面三个顶点构成的线条做边缘检测(注:和基于图像的边缘检测的检测方式是不同的,但都叫边缘检测)。在本文中使用的是基于空间的3D模型的描边。
空间的3D模型的描边的边是有类型的,大致总结有4种:轮廓边、边界边、折缝边、材质边。其中前3种是本文认为卡通渲染所必须有的。
图1 空间中的边分类 来自文献[1]
轮廓边的检测根据定义就是,1条边的2个邻接面的法线分别和视线方向的点乘结果再相乘,结果小于0就是轮廓边。数学上表达就是:(N1·V)*(N2·V) < 0,N1和N2是2个邻接面的法向量,V是视线方向。
边界边的检测比较简单,如果1条边只有1个面邻接,那么这条边就是边界边。
折缝边的检测需要使用1个角度参数α,1条边的2个邻接面的夹角和这个参数做大小比较。一般在0~180度,但本文选择在0~90度,并规定小于参数α的就是折缝边。
总结:要在3D模型上实现这3类边的绘制,只需要知道构成1条边的2个邻接面即可完成3类边的检测。在学术上有人把这2个邻接面当做1个点输入到着色器中,并作为1条边作为输出,并称这2个邻接面为退化四边形。

图2 退化四边形
二、具体实现
本文使用目前最主流的Uinty3D游戏引擎实现,由于这是脱离正常真实感渲染的算法,因此如果不能自定义这部分渲染流程,那么实现起来就无比困难,幸运Unity3D支持自定义渲染流程,其中使用到的关键类为CommandBuffer、ComputeBuffer。
由于不同的图形引擎,对图形接口的高级用法支持程度并不一致,例如Unity3D的几何着色器就没办法获取邻接三角形。因此预处理是有必要的。
实现步骤:
步骤1:预处理阶段,在这个阶段找出模型所有的边,以及边所对应的2个邻接面(默认所有边都是由2个邻接面相交构成,不规范的请自行处理)。
步骤2:把预处理阶段的数据保存下来,Uinty3D提供了很好接口ScriptableObject 。(注:默认保存退化四边形4个顶点的索引,如果保存的不是顶点索引,请自行处理)
步骤3:通过CommandBuffer、ComputeBuffer把预处理据保输入到显卡(GPU)中进行检测和绘制。
shader中边缘检测步骤:
步骤1:通过退化四边形4个顶点数据,计算出2个邻接面的法向量。如果顶点数不足4个则表明该边只有1个邻接面,因此它是边界边。
步骤2:计算出2个邻接面的法向量和视线方向的点乘结果dot(N1, V) * dot(N2, V),如果结果为负则是轮廓边。
步骤3:pow(dot(N1, N2) / cos(α), 2)在[0, PI/2]上单调递增, 可避免开方的特点,完成和dot(N1, N1) * dot(N2, N2)比较,如果小于则为折缝边。
三、实验结果
由于Uinty3D的帧数实在看不太懂,运算量低的时候帧数基本保持在90帧左右,运算量高一点点的时候就跑到120帧,估计是内部做了优化,因此运行结果仅供参考,并不准确,运行环境I5-4210M,GTX765M。

四、总结
这个描边算法在很早就被提出,这种基于空间的描边极大程度的得到模型丰富的描边细节,可惜在市面上貌似并不为人所知。某崩公司貌似是使用了这种算法,结合其他卡通渲染算法,画面效果惊人,把同行远远甩在后面。因此如果想让自己的作品更有竞争力,开发人员应该静下心来学习一下放到发霉的论文(金子)。本文的后续工作是控制线条的大小,理论上应该是可以在裁剪空间实现近粗远细的线条算法,但由于刚刚踏足这一块,还有很多其他工需要去研究,本文到此结束,谢谢。
附:源码
参考文献:
[1]基于着色器技术实时卡通渲染的的研究
[2]基于GPU实时非真实感渲染的研究与实现
[3]3D日式卡通人物渲染的经验分享
[4]Unity网格编程篇(二) 非常详细的Mesh编程入门文章
[5]Unity Shader入门精要
[6]Geometry Shader Input: GL_TRIANGLES_ADJACENCY
[7]Adjacency information in geometry shaders
[8]Direct X 12 – Geometry Shader 几何着色器
[9]OpenGL 图元处理
原文在这,比较凌乱,不再建议阅读。
Unity Shader 卡通渲染 基于退化四边形的实时描边的更多相关文章
- Unity酱~ 卡通渲染技术分析(二)
前面的话 上一篇Unity酱~ 卡通渲染技术分析(一) 写了CharaMain.cginc,服装的渲染是怎么实现的.这篇来分析一下头发跟皮肤的实现 头发 本来以为unitychan的头发会有各向异性的 ...
- Unity Shader 之 渲染流水线
Unity Shader 之渲染流水线 什么是渲染流水线 一个渲染流程分成3个步骤: 应用阶段(Application stage) 几何阶段(Geometry stage) 光栅化阶段(Raster ...
- [Unity Shader笔记]渲染路径--Forward渲染路径
[Unity Shader笔记]渲染路径--Forward渲染路径 (2014-04-22 20:08:25) 转载▼ 标签: shader unity renderingpath forward 游 ...
- Unity酱~ 卡通渲染技术分析(一)
前面的话 unitychan是日本unity官方团队提供的一个Demo,里面有很好的卡通渲染效果,值得参考学习 上图是我整理出来的shader结构,可以看到Unity娘被拆分成了很多个小的部件,我想主 ...
- 【我的书】Unity Shader的书 — 文件夹(2015.12.21更新)
写在前面 感谢全部点进来看的朋友.没错.我眼下打算写一本关于Unity Shader的书. 出书的目的有以下几个: 总结我接触Unity Shader以来的历程,给其它人一个借鉴.我非常明确学Shad ...
- 【我的书】Unity Shader的书 — 目录(2016.5.19最后一次更新)
写在前面 感谢所有点进来看的朋友.没错,我目前打算写一本关于Unity Shader的书. 出书的目的有下面几个: 总结我接触Unity Shader以来的历程,给其他人一个借鉴.我非常明白学Shad ...
- Unity Shader入门精要学习笔记 - 第8章 透明效果
转载自 冯乐乐的 <Unity Shader入门精要> 透明是游戏中经常要使用的一种效果.在实时渲染中要实现透明效果,通常会在渲染模型时控制它的透明通道.当开启透明混合后,当一个物体被渲染 ...
- Unity Shader 之 透明效果
透明效果 透明效果一般有两种实现方法: 第一种,使用透明度测试(Alpha Test) 第二种,使用透明度混合(Alpha Blending) 透明度测试和透明度混合机制: 透明度测试(Alpha T ...
- 基于Unity 5的次世代卡通渲染技术 -- Unite 2017 米哈游总监贺甲分享实录
在5月12日Unite2017开发者大会上,米哈游技术总监兼美术指导贺甲进行了主题为次世代卡通渲染的演讲.一下为详细分享内容: 大家好,首先自我介绍一下,我叫贺甲,在米哈游担任技术总监和美术指导工作, ...
随机推荐
- linux初学者-用户管理篇
linux的用户管理是非常以后工作中重要的一部分,也是linux系统安全的防线. 1.用户理解 那么到底什么是用户呢?用户就是系统使用者的身份. 用户是以怎样的方式储存在计算机中的呢?在系统中用户存储 ...
- Python 之父撰文回忆:为什么要创造 pgen 解析器?
花下猫语: 近日,Python 之父在 Medium 上开通了博客,并发布了一篇关于 PEG 解析器的文章(参见我翻的 全文译文).据我所知,他有自己的博客,为什么还会跑去 Medium 上写文呢?好 ...
- 【Java】点击 JButton 修改 Jlabel 的文字和字体颜色
要求: 点击 JButton 后执行一个方法 m(比较耗时),点击时改变 JLabel 的字体和颜色,方法 m 运行结束后再次修改 JLabel 的字体和颜色. 刚开始点击,都是方法 m 运行结束后, ...
- Rust生命周期bound用于泛型的引用
在实际编程中,可能会出现泛型引用这种情况,我们会编写如下的代码: struct Inner<'a, T> { data: &'a T, } 会产生编译错误: error[E0309 ...
- BGP属性控制实验
目录 实验拓扑 实验需求 实验步骤 个人小结: 实验拓扑 实验需求 更改BGP路由的属性让R4访问R1优先选R2这条路 实验步骤 1. 按照图示配置IP地址及环回口地址 R1 [R1]int g0/0 ...
- java课堂 动手动脑3
(1) 该函数没有赋初值再就是如果类提供一个自定义的构造方法,将导致系统不在提供默认的构造方法. (2) public class test { public static void main(Str ...
- Activiti6系列(3)- 快速体验
一.部署启动activiti 1.部署,将两个war包拷贝到Tomcat下即可. 2.启动tomcat,访问http://127.0.0.1:8080/activiti-app 默认账号密码:admi ...
- Go中配置文件读取的几种方式
日常开发中读取配置文件包含以下几种格式: json 格式字符串 K=V 键值对 xml 文件 yml 格式文件 toml 格式文件 前面两种书写简单,解析过程也比较简单.xml形式书写比较累赘,yml ...
- Go中的反射reflect
前面我们在学习到struct结构体的时候,因为结构体中的字段首字母大写,而我们想把json文件映射到该结构体上时,需要在在结构体字段后面加上json标签,表明结构体字段和json字段的映射关系.这其中 ...
- python语言特点简介 以及在Windows以及Mac中安装以及配置的注意事项
正如前一篇随笔所提到的,python属于解释型语言 python语言有两个特点: 1.胶水语言(历史遗留问题,原来Perl语言作为Unix内置标准件,获得极大追捧,作为竞争者的python一开始是作为 ...
