前面的话

unitychan是日本unity官方团队提供的一个Demo,里面有很好的卡通渲染效果,值得参考学习

上图是我整理出来的shader结构,可以看到Unity娘被拆分成了很多个小的部件,我想主要是为了挂动态骨骼吧。因为有很多部件的材质,shader其实都是一样的可以合并成少数几个

我打算分3个部分来学习

  1. CharaMain.cginc 主要用于衣服等材质
  2. CharaSkin.cginc 皮肤效果
  3. Hair 头发、眼睛、睫毛等部位的渲染

CharaMain.cginc

本篇先写第一部分body材质。CharaMain.cginc中包含漫反射、高光、反射、边缘光、阴影等效果的实现,接下来我们详细拆解

基础着色效果(模拟漫反射)

这里是用视角向量跟法线点积(但这样的做法就不会受光照角度变化),然后用结果采样一张类似这样的衰减纹理

	// Falloff. Convert the angle between the normal and the camera direction into a lookup for the gradient
float_t normalDotEye = dot( normalVec, i.eyeDir.xyz );
float_t falloffU = clamp( 1.0 - abs( normalDotEye ), 0.02, 0.98 );
float4_t falloffSamplerColor = FALLOFF_POWER * tex2D( _FalloffSampler, float2( falloffU, 0.25f ) );
float3_t shadowColor = diffSamplerColor.rgb * diffSamplerColor.rgb;
float3_t combinedColor = lerp( diffSamplerColor.rgb, shadowColor, falloffSamplerColor.r );
combinedColor *= ( 1.0 + falloffSamplerColor.rgb * falloffSamplerColor.a );



效果如下,边缘较白

但我感觉加上采样颜色后效果不是很明显,边缘颜色会深一些。

高光效果

	// Use the eye vector as the light vector
float4_t reflectionMaskColor = tex2D( _SpecularReflectionSampler, i.uv.xy );
float_t specularDot = dot( normalVec, i.eyeDir.xyz );
float4_t lighting = lit( normalDotEye, specularDot, _SpecularPower );
float3_t specularColor = saturate( lighting.z ) * reflectionMaskColor.rgb * diffSamplerColor.rgb;
combinedColor += specularColor;

这个高光的计算很奇葩,也是用法线跟视角向量的点积,最后的效果就是有一点淡淡的高光。也是跟真正的灯光角度无关的。

这里还用到了一张贴图,高光会用到这张图的rgb通道,后面要写的反射,会用到这张图的a通道。

大概就是描出来那些地方高光强一些

反射

// Reflection
float3_t reflectVector = reflect( -i.eyeDir.xyz, normalVec ).xzy;
float2_t sphereMapCoords = 0.5 * ( float2_t( 1.0, 1.0 ) + reflectVector.xy );
float3_t reflectColor = tex2D( _EnvMapSampler, sphereMapCoords ).rgb;
reflectColor = GetOverlayColor( reflectColor, combinedColor ); combinedColor = lerp( combinedColor, reflectColor, reflectionMaskColor.a );
combinedColor *= _Color.rgb * _LightColor0.rgb;
float opacity = diffSamplerColor.a * _Color.a * _LightColor0.a;

这里是采样一张环境贴图,为啥用张这样的图呢?我觉得他主要是为了能反射出这种银色的色调罢了。你想要什么色调就换啥样的环境图。

GetOverlayColor这个函数是用来融合自身贴图颜色,跟反射环境贴图颜色的。里面用了很多小技巧

先来看看直接输出反射贴图是什么样

通过GetOverlayColor融合后的反射颜色

然后这里会用到高光反射贴图的A通道,来表示某些区域的反射的强度。

用alpha通道做差值后会发现,大部分区域的反射颜色都不见了,因为大部分是黑色。只有少数白色区域,能看到一些反射效果

接收阴影处理

这里是计算其他物体投射在身上的阴影,这里插入了一个自定义的阴影颜色,为了明显一点我直接调成纯黑,然后弄了一个物体挡住了unity酱~ 效果如图

使用LIGHT_ATTENUATION指令对阴影贴图采样并且返回数据供你使用。如果你想知道LIGHT_ATTENUATION指令具体做了些什么,检查 AutoLight.cginc文件

#ifdef ENABLE_CAST_SHADOWS
// Cast shadows
shadowColor = _ShadowColor.rgb * combinedColor;
float_t attenuation = saturate( 2.0 * LIGHT_ATTENUATION( i ) - 1.0 );
combinedColor = lerp( shadowColor, combinedColor, attenuation );
#endif

边缘高光

终于这里有一个跟着光照角度变换的效果了,哈哈

一般我们会使用菲尼尔效应来实现边缘光,而unitychan里面则是采用了一张边缘光贴图

用N.L计算出来的值域在[-1,1]之间,*0.5+1后,转成[0,1]区间,然后对这张1维的rim图采样。

我们从右边打一盏平行灯,来看看采样的效果。跟光向量夹角越小的值越接近1,也就越白

但是边缘光效果要收到漫反射影响,所以他这里乘上了之前采样出来的漫反射渐变,可以看到高光被控制在了边缘

falloffU = saturate( rimlightDot * falloffU );

完整效果

总结

CharaMain.cginc中用了很多的小技巧实现了漫反射、高光、反射、边缘光。她没有传统卡通渲染赛璐璐的阴影渐变,也没有油腻的高光。她的效果都有种欲出还收的感觉。

我还是觉得效果太淡了一些

Unity酱~ 卡通渲染技术分析(一)的更多相关文章

  1. Unity酱~ 卡通渲染技术分析(二)

    前面的话 上一篇Unity酱~ 卡通渲染技术分析(一) 写了CharaMain.cginc,服装的渲染是怎么实现的.这篇来分析一下头发跟皮肤的实现 头发 本来以为unitychan的头发会有各向异性的 ...

  2. 基于Unity 5的次世代卡通渲染技术 -- Unite 2017 米哈游总监贺甲分享实录

    在5月12日Unite2017开发者大会上,米哈游技术总监兼美术指导贺甲进行了主题为次世代卡通渲染的演讲.一下为详细分享内容: 大家好,首先自我介绍一下,我叫贺甲,在米哈游担任技术总监和美术指导工作, ...

  3. Unity Shader 卡通渲染 基于退化四边形的实时描边

    从csdn转移过来,顺便把写过的文章改写一下转过来. 一.边缘检测算法 3D模型描边有两种方式,一种是基于图像,即在所有3D模型渲染完成一张图片后,对这张图片进行边缘检测,最后得出描边效果.一种是基于 ...

  4. Unite 2018 | 《崩坏3》:在Unity中实现高品质的卡通渲染(上)

    http://forum.china.unity3d.com/thread-32271-1-1.html 我们已经发布了Unite 2018 江毅冰的<发条乐师>.Hit-Point的&l ...

  5. Unite 2018 | 《崩坏3》:在Unity中实现高品质的卡通渲染(下)

    http://forum.china.unity3d.com/thread-32273-1-1.html 今天我们继续分享米哈游技术总监贺甲在Unite Beijing 2018大会上的演讲<在 ...

  6. Unity Shader入门精要学习笔记 - 第16章 Unity中的渲染优化技术

    转自冯乐乐的 <Unity Shader 入门精要> 移动平台的特点 为了尽可能一处那些隐藏的表面,减少overdraw(即一个像素被绘制多次),PowerVR芯片(通常用于ios设备和某 ...

  7. Turing渲染着色器网格技术分析

    Turing渲染着色器网格技术分析 图灵体系结构通过使用 网格着色器 引入了一种新的可编程几何着色管道.新的着色器将计算编程模型引入到图形管道中,因为协同使用线程在芯片上直接生成紧凑网格( meshl ...

  8. Unity——卡通渲染实现

    效果展示: 原模型: 一.简单分析 卡通渲染又叫非真实渲染(None-Physical Rendering-NPR),一般日漫里的卡通风格有几个特点: 1.人物有描边 2.有明显的阴影分界线,没有太平 ...

  9. Unity Shader NPR 卡通渲染

    卡通渲染的主要原理包含两个方面: 1.轮廓线的描边效果 2.模型漫反射离散和纯色高光区域的模拟 描边: 描边的实现方法采用将模型的轮廓线顶点向法线(或顶点)的方向扩展一定的像素得到.也可通过边缘检测( ...

随机推荐

  1. nginx 负载均衡及反向代理

    Nginx简介 Nginx是一款高性能的http 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.由俄罗斯的程序设计师开发,官方测试nginx能够支支撑5万并发链接,并且cpu.内存 ...

  2. 通过例子学习C++(二)最小公倍数

    本文是通过例子学习C++的第二篇,通过这个例子可以快速入门c++相关的语法. 题目要求:输入两个整数,求其最小公倍数. 解答方法一:两个数的最小公倍数,是这两个数中的大数,或者是这2个数的倍数中的最小 ...

  3. kettle连接oracle数据库报错,ORA-12505

    报错信息: Error connecting to database: (using class oracle.jdbc.driver.OracleDriver) Listener refused t ...

  4. java 字典 map 和 list.forEach

    1.keySet  key 集 2.values value 集(为何不叫valueSet)... 3.entrySet key value 集 List<?> 循环 1.Iterable ...

  5. day6 相对定位:position:relative

    相对定位:position:relative 特点:a.相对于自己原来位置的定位,以自己的左上角为基准. b.相对定位原来的位置仍然算位置,不会出现浮动现象. 以下为初始位置:(可以看出设置margi ...

  6. NMI计算

    NMI计算 NMI(Normalized Mutual Information)标准化互信息,常用在聚类中,度量两个聚类结果的相近程度.是社区发现(community detection)的重要衡量指 ...

  7. __init__.py在导包中起到的作用

    说明:__init__.py这个文件本人使用频率不高 例子: __init__.py文件作用:初始化这个包 1.v1.py def vi(): return 'views' 2.views->_ ...

  8. 龙芯2f 8089D 笔记本 Debian 系统安装配置

    版权声明:原创文章,未经博主允许不得转载 正文主要讲述安装社区版Debian6镜像(也有7和8,方法大同小异) 最后简单介绍了网络安装原版Debian 小记 非网络安装,没网也没事,再也不用担心网速度 ...

  9. API文档自动生成,Swagger的配置

    ASP.NET的部署方式 第一步:引用程序集 打开NuGet程序包管理器,搜索Swagger,安装第一个,注意画圈的地方, 已经包含主程序和UI了,安装完成后会在根目录App_Start文件夹下生成S ...

  10. 3分钟接入socket.io使用

    WebSocket 简介 传统的客户端和服务器通信协议是HTTP:客户端发起请求,服务端进行响应,服务端从不主动勾搭客户端. 这种模式有个明显软肋,就是同步状态.而实际应用中有大量需要客户端和服务器实 ...