上一篇传送门:

https://blog.csdn.net/qq_27534999/article/details/100925621

顶点色在卡通渲染中有挺多应用,本篇会在上一篇的基础上,运用模型顶点色来控制细节。塞尔达荒野之息不一定是用这种方法,也可能是用额外的贴图来实现,这里算是抛砖引玉一下,扩展一下思路。(不过这方法效果还挺不错哦!)

用顶点色控制细节还是有很多好处的,首先就是效果比较平滑(毕竟自动插值),之前曾尝试过用额外贴图控制,结果到处都是狗牙锯齿你懂的,挺难受的。

先上顶点色调整后的最终效果:

然后看看之前的效果:

之前的效果还是比较粗糙的,有许多细节不是很完美:

①脖子部分被头遮盖,应该有阴影

②脸部不希望有太多阴影,应尽量保持明亮

③除了头发外,其他地方不希望出现高光

④大腿部分的边缘光不够明显,头发部分的边缘光又过多了

可知,①、②属于阴影问题,③属于高光问题,④属于边缘光问题。

有些问题,可以通过拆分模型,给不同的材质球参数来解决,但是这样会让材质球个数变多,从而SetPassCall变多,在移动端上可能造成性能问题。因此,顶点色处理无疑是个好办法,我们可以用顶点色的R、G、B通道分别控制阴影、高光、边缘光。

接下来将一步步讲解如何用顶点色来对细节做修正:

一、准备模型

首先确认模型是否带有顶点色信息,在 Unity 内选中模型 Mesh 资源,即可在右下角观察。

如果是跟我一样下载的模型的话,很遗憾地会发现只有 uv 和 skin ,没有顶点色信息,这里得自己用 3ds max 或 maya 重新导出一下(随意指定一下顶点色后导出即可)。

之后,观察到窗口里有 colors 就没问题了。

二、准备工具

可以直接在 3ds Max 或者 Maya 里绘制顶点色,不过个人还是习惯在 Unity 里绘制,这样也方便观察调整。

(想在 3dsMax 里刷顶点色的请看下一篇:https://blog.csdn.net/qq_27534999/article/details/101080649)

一般这类工具会有公司的程序专门来开发,如果没有的话,可以去 Unity 的 Asset Store 搜索插件来用,这边推荐一个 TOZ Vertex Painter,小巧且免费。

插件导入后,在 Window -> TOZ -> Tools -> Vertex Painter 打开面板,如下图所示:

此时点击模型时,窗口可能会报错。会提示模型这边需要添加 Mesh Collider,且要使用 Mesh Filter 和 Mesh Renderer (这个插件不支持 Skinned Mesh Renderer),这些都要处理一下。模型设置如下图所示:

这时候再选中模型,就可以愉快地刷顶点色了~!刷完后点击 SAVE NEW MESH 会另存为一个新的模型文件。

三、Shader 修改

接下来是 Shader 的修改,获取顶点色信息然后对阴影、高光做出调整。

首先,在结构体中加入顶点色,当然别忘了 vert 中要赋值:

struct appdata
{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;fixed4 color : COLOR;
};struct v2f
{float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;UNITY_FOG_COORDS(3)float4 vertex : SV_POSITION;fixed4 color : COLOR;
};...v2f vert (appdata v)
{v2f o;...o.color = v.color;...return o;
}

然后是针对阴影、高光、边缘光的计算略有修改,R通道控制阴影,G通道控制高光,B通道控制边缘光。

R通道:原点乘值区间为[-1,1],这里我希望控制阴影顶点色的修改能够覆盖这个区间,因为有些部位我希望永远是暗部,这样最极端的情况是把点乘值-1修正为1,这里用  (顶点色 - 0.5)* 4。

G、B通道:高光、边缘光两个通道的点乘值,稍微修正就好,不需要太大的调整,因此这里用 (顶点色 - 0.5)* 2。

fixed diffValue = dot(worldNormal, worldLightDir)+(i.color.r-0.5)*4;
...
fixed spec = dot(worldNormal, worldHalfDir)+(i.color.g-0.5)*2;
...
fixed rimValue = pow(1 - dot(worldNormal, worldViewDir+(i.color.b-0.5)*2), _RimPower);

这样,Shader的修改就完成了。

四、刷顶点色

刚改完Shader后,视觉表现会很奇怪(见左图),这是因为顶点色默认黑色(0, 0, 0)。

如果要恢复到原来的状态,根据我们之前修改 Shader 的公式,只要将所有顶点色涂上灰色(0.5, 0.5, 0.5)即可(见左图)。

接下来着手解决之前提出的四个问题,根据我们的需求,对顶点色RGB进行调整即可。

①脖子部分被头遮盖,应该有阴影 —— 脖子部分 R 值为0

②脸部不希望有太多阴影,应尽量保持明亮 —— 脸部 R 值调高

③除了头发外,其他地方不希望出现高光 —— 除头发外其他部位 G 值为0

④大腿部分的边缘光不够明显,头发部分的边缘光又过多了 —— 大腿 B值调高,头发 B值调低

调整后的效果如下图所示:

效果明显比之前要好多了~!

五、成果

按照惯例,最后给出完整 Shader 如下:

Shader "Custom/ToonShadingSimple_v3"
{Properties{[Header(Main)]_MainTex ("Texture", 2D) = "white" {}_Color ("Color", Color) = (1.0, 1.0, 1.0, 1.0)_RimColor ("RimColor", Color) = (1.0, 1.0, 1.0, 1.0)_ShadowThreshold ("ShadowThreshold", Range(-1.0, 1.0)) = 0.2_ShadowBrightness ("ShadowBrightness", Range(0.0, 1.0)) = 0.6_RimThreshold ("RimThreshold", Range(0.0, 1.0)) = 0.35_RimPower ("RimPower", Range(0.0, 16)) = 4.0_Specular ("Specular", Color) = (1, 1, 1, 1)_SpecularScale("Specular Scale", Range(0, 0.1)) = 0.02}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{Cull BackTags { "LightMode"="ForwardBase" }CGPROGRAM#pragma vertex vert#pragma fragment frag// make fog work#pragma multi_compile_fog#include "UnityCG.cginc"#include "Lighting.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float3 normal : NORMAL;fixed4 color : COLOR;};struct v2f{float2 uv : TEXCOORD0;float3 worldNormal : TEXCOORD1;float3 worldPos : TEXCOORD2;UNITY_FOG_COORDS(3)float4 vertex : SV_POSITION;fixed4 color : COLOR;};sampler2D _MainTex;float4 _MainTex_ST;fixed4 _Color;fixed4 _RimColor;fixed _ShadowThreshold;fixed _ShadowBrightness;fixed _RimThreshold;half _RimPower;fixed4 _Specular;fixed _SpecularScale;v2f vert (appdata v){v2f o;o.vertex = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _MainTex);o.worldNormal = mul(v.normal, (float3x3)unity_WorldToObject);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.color = v.color;UNITY_TRANSFER_FOG(o,o.vertex);return o;}fixed4 frag (v2f i) : SV_Target{//return i.color;fixed3 worldNormal = normalize(i.worldNormal); //法线 Nfixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos)); //光照方向 Lfixed3 worldViewDir = normalize(UnityWorldSpaceViewDir(i.worldPos)); //视角方向 Vfixed3 worldHalfDir = normalize(worldLightDir + worldViewDir); //高光计算用// sample the texturefixed4 col = tex2D(_MainTex, i.uv); fixed spec = dot(worldNormal, worldHalfDir)+(i.color.g-0.5)*2;// w值也可用一个较小的值代替,效果差别不大fixed w = fwidth(spec)*2.0;fixed4 specular = _Specular * lerp(0,1,smoothstep(-w, w, spec+_SpecularScale-1)) * step(0.001, _SpecularScale);fixed diffValue = dot(worldNormal, worldLightDir)+(i.color.r-0.5)*4;fixed diffStep = smoothstep(-w+_ShadowThreshold, w+_ShadowThreshold, diffValue);fixed4 light = _LightColor0 * 0.5 + 0.5;fixed4 diffuse = light * col * (diffStep + (1 - diffStep) * _ShadowBrightness) * _Color;// 模仿参考文章的方法,感觉效果不是太好// fixed rimValue = 1 - dot(worldNormal, worldViewDir);// fixed rimStep = step(_RimThreshold, rimValue * pow(dot(worldNormal,worldLightDir), _RimPower));fixed rimValue = pow(1 - dot(worldNormal, worldViewDir)+(i.color.b-0.5)*2, _RimPower);fixed rimStep = smoothstep(-w+_RimThreshold, w+_RimThreshold, rimValue);fixed4 rim = light * rimStep * 0.5 * diffStep * _RimColor;fixed4 final = diffuse + rim + specular;// apply fogUNITY_APPLY_FOG(i.fogCoord, final);return  final;}ENDCG}}
}

谢谢观赏~!

应美术需求,下一篇将讲解如何在 3dsMax 里加载自定义 Shader 刷顶点色

下一篇传送门:

https://blog.csdn.net/qq_27534999/article/details/101080649

参考资料:

没有具体参考资料,算是对顶点色应用的一次尝试吧

Unity Shader 卡通渲染 (三):仿塞尔达荒野之息 Shader(顶点色控制细节)相关推荐

  1. Unity Shader 卡通渲染 (一):仿塞尔达荒野之息 Shader(简易版)

    温馨提示: 本系列文章面向那些 Shader 刚刚入门,想寻求进一步提升的群体,如果对 Shader 一无所知的话,建议自行搜索其他 Shader入门教程观看学习,再食用本系列文章. 前言: 说起卡通 ...

  2. RenderDoc塞尔达荒野之息抓帧分析

    RenderDoc是一种抓帧工具,主要用来分析游戏开发中渲染流程,官网: https://renderdoc.org/ 我是用的版本是RenderDoc_1.14_64.zip 塞尔达荒野之息使用Ce ...

  3. 分享几张塞尔达荒野之息精彩壁纸

    分享几张塞尔达荒野之息精彩壁纸 001-荒野之息经典封面.jpg 002-林克醒来看向海拉陆大陆经典场面.jpg 003-林克射箭特写.jpg 004-海拉鲁荒野之息.jpg 005-林克攀爬峭壁.j ...

  4. 塞尔达荒野之息vs艾尔登法环

    玩了荒野之息(switch版本)再去玩艾尔登法环,感觉艾尔登法环完全没有外界宣扬的那么好.我是七彩虹3060显卡,特效全开了,一开始场景还比较精致的,后面也很多场景比较粗糙. 然后就是感觉这个人物很笨 ...

  5. 塞尔达amiibo_塞尔达荒野之息pC版(附带全Amiibo)安装教程,最无敌的游戏

    点击上方「蓝字」关注我们 给你最好的 <塞尔达传说:荒野之息(The Legend of Zelda: Breath of the Wild)>是任天堂旗下经典角色扮演游戏系列<塞尔 ...

  6. Unity UI xlua 热更:还原塞尔达旷野之息 (持续更新:已补充箭头动效)

    整了个小Demo仿照<塞尔达传说:旷野之息>,实现 鼠标悬停在Button上时,能够改变Button-Text颜色,并且在Button前显示一个小箭头 标题鼠标指针悬停和移走,改变标题颜色 ...

  7. Unity 程序化动画:还原塞尔达旷野之息 守护者 (六足)

    又整了个小Demo,感觉程序化动画还挺好玩.先上效果图,使用到的所有模型均来源于网络. 程序化动画生成守护者移动 实现思路:守护者共6条腿,初始化先激活两条腿14可移动,每移动完一条腿顺序激活下一条腿 ...

  8. 微信小程序前端页面Demo系列之仿塞尔达攻略助手首页

    前言 Hello!小伙伴! 非常感谢您阅读海轰的文章,倘若文中有错误的地方,欢迎您指出-   自我介绍 ଘ(੭ˊᵕˋ)੭ 昵称:海轰 标签:程序猿|C++选手|学生 简介:因C语言结识编程,随后转入计 ...

  9. Unity Shader 卡通渲染 (五):仿日式赛璐珞风格 Shader(顶点外扩描边)

    上一篇传送门: https://blog.csdn.net/qq_27534999/article/details/101080649 一.赛璐璐风格简介 有些人可能会问,什么是赛璐珞风格? 赛璐珞是 ...

最新文章

  1. 【Xamarin】揭秘生成配置
  2. hdu4995 (不错的小模拟)
  3. html5 拖拽滚动条,js 简易版滚动条实例(适用于移动端H5开发)
  4. 记次浙大月赛 134 - ZOJ Monthly, June 2014
  5. 宝刀不老: Cookie (转)
  6. CISCO 路由器启动自动配置
  7. Kotlin的匿名方法实现接口回调
  8. 数据机房灾备的重要性
  9. 创客匠人知识付费SaaS系统功能介绍
  10. 用java实现皮尔逊相关系数计算
  11. ARC083简要题解
  12. php 招聘要求 转载
  13. ubuntu18添加中文输入法
  14. 学习笔记之——汉明码(Hamming Code)
  15. 蚁群算法优化旅行问题
  16. 1.6 例子:CIFAR-10分类
  17. BCG 使用之CBCGPEdit控件
  18. The Unarchiver-解决Mac解压后文件名乱码问题_我是亲民_新浪博客
  19. 【时间序列】001-推断统计
  20. 电脑文件被误删别急,这样设置操作可恢复数据

热门文章

  1. centos Iptables学习笔记
  2. “中国十大名校”之争,缘何让百度气急败坏封贴?
  3. 微信无法连接服务器1-500,GIF表情超过500kb无法添加到微信的解决方法
  4. 关系模式(关系模式必须遵循)
  5. [UER #6]逃跑
  6. 企业上云的选择及好处
  7. 360度全景图片怎么拍摄?
  8. 安卓手机 ADB 操作指令
  9. AEC非线性处理模块
  10. D38 Java智能电话项目本————创建实体类