Unity制作二次元材质角色

回到目录

大家好,我是阿赵。
这里继续讲二次元角色渲染。之前说过,最基本的卡通渲染,包含了色阶化光影和描边二个元素。所以这里先来说一下色阶化光影的多种做法对比。

一、光照模型和色阶化的说明

从上一篇文章里面可以知道,这个模型提供了2套贴图,分别是baseMap和sssMap

baseMap

sssMap

这两张贴图的作用,很明显作为亮部和暗部显示用的。
那么需要怎样使用这两张贴图呢?
其实很简单,还是自定义光照模型。我之前写过文章介绍怎样自己写光照模型。然后我之后做了很多例子,如果各位如果有留意看,估计也发现,自定义光照模型是很多效果的基础。
这里我也同样的先做一个HalfLambert漫反射光照:

//获取HalfLambert漫反射值
float GetHalfLambertDiffuse(float3 worldPos, float3 worldNormal)
{
float3 lightDir = UnityWorldSpaceLightDir(worldPos);
float NDotL = dot(worldNormal, lightDir);
float halfVal = NDotL * 0.5 + 0.5;
return halfVal;
}
half4 frag (v2f i) : SV_Target
{
half4 col = tex2D(_BaseMap, i.uv);
half4 sssCol = tex2D(_SSSMap, i.uv);
half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);
half3 finalRGB = col.rgb*halfLambert + sssCol * (1 - halfLambert);
half alpha = col.a;
return half4(finalRGB,alpha);
}


这个时候,通过获取漫反射的光照值来混合baseMap和sssMap,会得到这种效果。
不过这只是正常普通的HalfLambert光照效果,在卡通渲染里面,因为是模拟漫画的涂色方式,光影之间一般来说会有一个硬边的过渡,比如:

这种情况,我们会称为色阶化。意思就是,把一个渐变过渡的光影效果,变成了一段一段色阶的跳跃性过渡。

二、实现色阶化的多种手段介绍

做色阶化的方法比较多,比如:

1、通过一个色阶图去采样

这个方法需要准备一张色阶图:

然后通过光照模型的值作为x坐标去采样这张贴图

half4 frag (v2f i) : SV_Target
{
//色阶化
half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);
half4 GradationCol = tex2D(_GradationMap, float2(halfLambert, 0.5));
return GradationCol;
}

会得到这个效果:

可以看出,刚才的色阶图的三个颜色都出现在模型身上了,而且三段颜色的占比,可以通过调节色阶图的颜色范围来控制。
接下来可以把这个色阶图的采样结果,和baseMap做一个混合,就得到了:

half4 frag (v2f i) : SV_Target
{
half4 col = tex2D(_BaseMap, i.uv);
half4 sssCol = tex2D(_SSSMap, i.uv);//色阶化
half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);
half4 GradationCol = tex2D(_GradationMap, float2(halfLambert, 0.5));half3 finalRGB = col.rgb*GradationCol+ sssCol*(1- GradationCol);
half alpha = col.a;
return half4(finalRGB,alpha);
}

先忽略脸部,之后我会有专门的一篇文章讲脸部的问题。看一下身体的部分,可以看出现在的影子已经变成了色阶化了。
色阶图的做法的好处是,喜欢多少段色阶影子都可以,可以通过调整色阶图来控制影子的深浅和范围。

2、使用渐变图做色阶

色阶图其实也有缺点,如果想做到某些部位的色阶化强烈一点,某些部位的色阶化弱一点,其实是很难做到的。
所以出现了另外一种色阶图的做法,是渐变的

可以看出,这张渐变图下面是硬过渡,上面是软过渡,如果我们采样的时候,可以不同部位控制采样uv的y轴不一样,那么得到的软硬过渡程度也可以不一样。代码的写法和上面的色阶图是一样的,只是采样uv的y坐标不一样,所以就不重复写一遍了,只说一下原理。
那么怎样去控制UV坐标的y轴呢?方法很多,给一张专门的贴图去控制,或者直接用顶点颜色的某个通道去控制,都可以。
一般会使用顶点颜色去控制,配合着实时编辑顶点颜色的工具,可以比较快速的看到效果的改变。

3、使用step函数

不使用其他贴图,而是用step函数,也能实现色阶化:

half4 frag (v2f i) : SV_Target
{
//色阶化
half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);
half toonVal = step(0, halfLambert- _stepVal);
return half4(toonVal.xxx,1);
}

加上了baseMap和sssMap的混合,效果就是:

step的做法,好处是简单,不需要额外的贴图资源,直接用一个变量就能控制阴影的范围。

4、使用smoothstep函数

step函数的做法是很简单的,但有一个缺点,不能控制阴影边缘的软硬程度
所以可以使用smoothstep函数来替代step函数,这样就可以控制阴影的软硬程度

half4 frag (v2f i) : SV_Target
{
//色阶化
half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);
half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert);
return half4(toonVal.xxx,1);
}

可以看到,在使用smoothstep函数之后,通过控制smoothstep的最大值和最小值的参数,我们实现了不同部位的影子过渡程度不一样的效果了,甚至可以在某些部位减弱影子的效果。
混合了baseMap和sssMap,就是这种效果:

做色阶化的方法很多,可以自己再发散一下思维。已经列举出的几种方式,综合评价了一下,我觉得用smoothstep函数的方法会比较容易实现,容易控制,然后效果也还不错。所以我在这个例子里面最终是使用了smoothstep函数的方法来做色阶化光影的。

三、完整Shader

Shader "azhao/ToonBodyBase"
{Properties{_BaseMap ("BaseMap", 2D) = "white" {}_SSSMap("SSSMap", 2D) = "white" {}_GradationMin("GradationMin",Range(0.0,1.0)) = 0.0_GradationMax("GradationMax",Range(0.0,1.0)) = 1.0}SubShader{Tags { "RenderType"="Opaque" }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"#pragma multi_compile_fwdbase#include "AutoLight.cginc"struct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;float2 uv2 : TEXCOORD1;float3 normal:NORMAL;};struct v2f{                float4 pos : SV_POSITION;float2 uv : TEXCOORD0;float2 uv2 : TEXCOORD1;float3 worldPos :TEXCOORD2;float3 worldNormal :TEXCOORD3;};sampler2D _BaseMap;float4 _BaseMap_ST;sampler2D _SSSMap;float _GradationMin;float _GradationMax;//获取HalfLambert漫反射值float GetHalfLambertDiffuse(float3 worldPos, float3 worldNormal){float3 lightDir = UnityWorldSpaceLightDir(worldPos);float NDotL = dot(worldNormal, lightDir);float halfVal = NDotL * 0.5 + 0.5;return halfVal;}v2f vert (appdata v){v2f o;o.pos = UnityObjectToClipPos(v.vertex);o.uv = TRANSFORM_TEX(v.uv, _BaseMap);o.uv2 = TRANSFORM_TEX(v.uv2, _BaseMap);o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;o.worldNormal = UnityObjectToWorldNormal(v.normal);return o;}half4 frag (v2f i) : SV_Target{// sample the texturehalf4 col = tex2D(_BaseMap, i.uv);half4 sssCol = tex2D(_SSSMap, i.uv);//色阶化half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert);half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal);half alpha = col.a;return half4(finalRGB,alpha);}ENDCG}}
}

Unity制作二次元卡通渲染角色材质——2、色阶化光影的多种做法对比相关推荐

  1. Unity制作二次元卡通渲染角色材质——4 、内外描边和细节添加

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵. 这里继续讲二次元角色材质.这次打算讲一下描边和细节的添加. 一.外描边 外描边的做法也不止一种,比如后处理方法的偏导数ddx/ddy之类的, ...

  2. Unity制作二次元卡通渲染角色材质——5、脸部的特殊处理

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵. 这里继续讲二次元角色材质的制作.这次是讲头部的做法. 1.脸部 之前在分析资源的时候,其实已经发现了这个模型的脸部法线有问题,导致在做光照模 ...

  3. Unity制作二次元卡通渲染角色材质——1、资源分析

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵. 开始制作二次元角色材质之前,我觉得应该是先分析一下,我手上拿到的这个角色模型资源,总共有哪些信息是我们能用的. 所以这篇文章我不会分享具体的 ...

  4. Unity制作二次元卡通渲染角色材质——3、高光反射与ILM贴图

    Unity制作二次元材质角色 回到目录 大家好,我是阿赵. 这里继续来讲二次元角色的材质.上次讲了光影的色阶化问题,这次继续讲光照模型效果的问题. 之前我们说过,光照模型的最后效果是: 环境色+漫反射 ...

  5. 二次元卡通渲染之描边

    前言 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商业项 ...

  6. 二次元卡通渲染-着色

    前言 本文为"优梦创客"原创文章,您可以自由转载,但必须加入完整的版权声明 更多学习资源请加QQ:1517069595获取(企业级性能优化/热更新/Shader特效/服务器/商业项 ...

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

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

  8. 腾讯游戏主美:二次元卡通渲染有哪些黑科技?

    今年,<原神>的出现让行业注意到了三渲二这种独特的画风.但在二次元游戏中,<原神>其实并非第一个吃螃蟹的人.作为腾讯游戏魔方工作室群<王牌战士>项目组的主美,谢海天 ...

  9. Unity Shader 实现卡通渲染效果

    本文参考博客Unity Toon Shader 卡通着色器(一):卡通着色 这是我实现的最后效果 我们先一步一步来 最开始我们实现一个只有漫反射效果的Shader,效果和代码如下 Shader &qu ...

最新文章

  1. 转载非原创:修改BB 的内容,回车后修改CC 的值
  2. 【Java 网络编程】TCP 数据传输示例 ( 客户端参数设置 | 服务器端参数设置 | ByteBuffer 存放读取数据类型 )
  3. IOS8 Playground介绍
  4. 【2012百度之星/初赛上】D:轮子上的度度熊
  5. java的websocket_java 实现websocket的两种方式实例详解
  6. 光纤通道如何过渡到SAN
  7. HDLBits答案(8)_Verilog半加器、全加器和行波进位加法器原理与设计
  8. 《UNIXLinux程序设计教程》一2.1 UNIX 输入输出基本概念
  9. UML建模系列文章总结 [转]
  10. 构建面向对象的应用软件系统框架
  11. 驾乘华为云 成就 AI 开发者的不凡
  12. 转:GCC,LLVM,Clang编译器对比
  13. 定时器的实现原理 不消耗cpu_空闲CPU在做什么?
  14. yandex alice语音开发
  15. winform使用字体图标
  16. LabWindows/CVI学习总结——前言
  17. 以太网的CSMA/CD协议
  18. win7计算机设置成不黑屏,教你win7开机黑屏
  19. 如何解决HEVC编码格式不能播放的问题?
  20. Android之集成极光推送消息

热门文章

  1. Learning DevOps
  2. 不出门就和朋友们一起在家观看电影?只需要这款 Chrome 插件
  3. 【软件测试】你需要的面试技巧全在这里,细节满满
  4. 去掉chrome开发者提示
  5. 怀胎的历程及注意事项
  6. Android Dialog总结
  7. 我的年终总结---致逝去的2018
  8. python战反爬虫:爬取猫眼电影数据 (一)
  9. svn: E210005: No repository found in 解决方案
  10. 关于使用fgetc函数和feof函数的一些注意事项