Unity制作二次元材质角色

回到目录

大家好,我是阿赵。
这里继续来讲二次元角色的材质。上次讲了光影的色阶化问题,这次继续讲光照模型效果的问题。
之前我们说过,光照模型的最后效果是:
环境色+漫反射+高光+反射。
这里我们可以先忽略环境光,然后之前做了漫反射,用的是HalfLambert,剩下的就是高光和反射了

一、高光

继续套用之前学过的高光光照模型,习惯上是使用BlinnPhong。

//获取BlinnPhong高光
float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal)
{
float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));
float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz));
float specDir = max(dot(normalize(worldNormal), halfDir), 0);
float specVal = pow(specDir, _shininess);
return specVal;
}
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);half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert);//高光half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal);   half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal) + _specColor * specVal;half alpha = col.a;return half4(finalRGB,alpha);
}

加上高光之后,模型就变成这样了,高光有点强过头了。先不管,把效果都加上,最后再调。

二、反射

熟悉我的朋友都知道了,加反射效果,阿赵一般是推荐Matcap的,特别是这种不需要真反射,只是要一点环境假反射的情况。
于是又找到Matcap的代码,加上去。

float2 GetMatCapUV(float3 normalWorld)
{float3 normalView = mul(UNITY_MATRIX_IT_MV, normalWorld);return normalView.xy*0.5 + 0.5;
}
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);//高光half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal);//matcapfloat2 MatCapUV = GetMatCapUV(i.worldNormal)*_MatCapUVScale;float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity;MatCapCol = pow(MatCapCol, _MatCapPow);half3 finalRGB = col.rgb*toonVal + sssCol  * (1 - toonVal)+_specColor* specVal;finalRGB = finalRGB * MatCapCol.rgb;half alpha = col.a;return half4(finalRGB,alpha);
}

这个效果,已经加上了BlinnPhong高光、Matcap反射。但明显效果是不对的,角色像一个少林寺十八铜人似的。

三、ILM贴图

上面把高光和反射加上去之后,发现效果不对。那么需要怎样去修正呢?
我们可以分析一下,效果不对的原因是什么:
1、某些部位的反射强度不对,比如皮肤,不应该反射这么强烈
2、高光的范围不对,有些部位的高光范围应该被控制在一个局部
3、反射的范围不对,反射不应该所有地方都一样的强度,应该根据实际的材质来显示,比如皮肤是不会反射的,皮衣可能有一点,吉他的金属漆部分应该有比较强的反射。
那么,我们应该怎样去控制这些强度和范围呢?这里我们需要回顾一下,之前分析资源时,得到的ILM贴图的实际情况:
由于已经知道ILM贴图的A通道是内描线,所以这里先忽略,只看RGB三个通道:
首先是R通道:

然后是G通道:

然后是B通道:

这里可以猜测一下,三个通道的作用了。
比较明显的是R通道,他明显是控制高光强弱的。
G通道的作用不是很明显,只有脸部和身上某些部位是比较白,其他的颜色都一样。这样应该是控制影子强度的,
B通道只有某些局部亮起来,大部分都是黑的,可以理解成,是用来控制高光和反射的形状范围的。
于是我们可以把ILM贴图对应的通道的值,加在之前的高光和反射上面。
首先来看高光部分:

half4 frag (v2f i) : SV_Target
{// sample the texturehalf4 col = tex2D(_BaseMap, i.uv);half4 sssCol = tex2D(_SSSMap, i.uv);half4 ilmCol = tex2D(_ILMMap, i.uv);//色阶化half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert);//高光half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal);half3 finalRGB = col.rgb*toonVal + sssCol  * (1 - toonVal)+_specColor* specVal*ilmCol.r+ _specColor * specVal*ilmCol.b*_SpecAdd;      half alpha = col.a;return half4(finalRGB,alpha);
}

使用ILM贴图的R通道控制高光强度,本来ILM贴图的B通道是控制形状的,我这里修改了一下用法,变成了在R通道控制完强度之后,使用B通道把某些区域的高光加强一下,比如胸部的光点,衣服上的金属边的高光点等。于是就得到了这样的效果:

再来看Matcap部分,直接用B通道控制范围,为了看得更清楚一些,所以暂时把高光去掉:

half4 frag (v2f i) : SV_Target
{// sample the texturehalf4 col = tex2D(_BaseMap, i.uv);half4 sssCol = tex2D(_SSSMap, i.uv);half4 ilmCol = tex2D(_ILMMap, i.uv);//色阶化half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert);float2 MatCapUV = GetMatCapUV(i.worldNormal)*_MatCapUVScale;float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity;MatCapCol = pow(MatCapCol, _MatCapPow);half3 finalRGB = col.rgb*toonVal + sssCol * (1 - toonVal);finalRGB = finalRGB * (1-ilmCol.b) +MatCapCol.rgb*ilmCol.b;half alpha = col.a;return half4(finalRGB,alpha);
}

这时候可以看到,之前十八铜人一般的全身反射已经没有了,变成了只有指定的部位出现了反射效果。
最后,把ILM对高光和反射的影响一起加上,就得到了:

四、完整Shader

Shader "azhao/ToonBodyLight"
{Properties{_BaseMap ("BaseMap", 2D) = "white" {}_SSSMap("SSSMap", 2D) = "white" {}_ILMMap("ILMMap", 2D) = "white" {}_specColor("specColor",Color) = (1,1,1,1)_shininess("shininess", Range(1 , 100)) = 1_SpecAdd("SpecAdd",float) = 1.0_GradationMin("GradationMin",Range(0.0,1.0)) = 0.0_GradationMax("GradationMax",Range(0.0,1.0)) = 1.0_MatCapTex("MatCapTex", 2D) = "white" {}_MatCapIntensity("MatCapIntensity",Range(0,2)) = 1_MatCapPow("MatCapPow",Range(0,5)) = 1_MatCapUVScale("MatCapUVScale",Range(0,1)) = 1}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;sampler2D _ILMMap;float4 _specColor;float _shininess;float _SpecAdd;float _GradationMin;float _GradationMax;sampler2D _MatCapTex;float _MatCapIntensity;float _MatCapPow;float _MatCapUVScale;//获取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;}//获取BlinnPhong高光float GetBlinnPhongSpec(float3 worldPos, float3 worldNormal){float3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));float3 halfDir = normalize((viewDir + _WorldSpaceLightPos0.xyz));float specDir = max(dot(normalize(worldNormal), halfDir), 0);float specVal = pow(specDir, _shininess);return specVal;}float2 GetMatCapUV(float3 normalWorld){float3 normalView = mul(UNITY_MATRIX_IT_MV, normalWorld);return normalView.xy*0.5 + 0.5;}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);half4 ilmCol = tex2D(_ILMMap, i.uv);//色阶化half halfLambert = GetHalfLambertDiffuse(i.worldPos, i.worldNormal);half toonVal = smoothstep(_GradationMin, _GradationMax, halfLambert);//高光half specVal = GetBlinnPhongSpec(i.worldPos, i.worldNormal);//matcapfloat2 MatCapUV = GetMatCapUV(i.worldNormal)*_MatCapUVScale;float4 MatCapCol = tex2D(_MatCapTex, MatCapUV)*_MatCapIntensity;MatCapCol = pow(MatCapCol, _MatCapPow);half3 finalRGB = col.rgb*toonVal + sssCol  * (1 - toonVal)+_specColor* specVal*ilmCol.r+ _specColor * specVal*ilmCol.b*_SpecAdd;finalRGB = finalRGB * (1-ilmCol.b) +MatCapCol.rgb*ilmCol.b;half alpha = col.a;return half4(finalRGB,alpha);}ENDCG}}
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. 从对ML一窍不通到斩获AT等special offer,拿下大厂算法岗就靠它了
  2. 【Ethereum】以太坊ERC20 Token标准完整说明
  3. 计算机组成定时方式,2019考研408计算机组成原理知识:总线操作和定时
  4. python os详解
  5. JavaSE基础——Object类中的常用方法
  6. java设计模式--创建模式--单例模式
  7. java fup spring
  8. Cox模型中的时间依存协变量和时间依存系数(R语言)第一部分
  9. Intellij IDEA之mybatis-generator自动生成
  10. 判断一个数是否为素数(调用函数)
  11. Linux rpm -ivm,PowerLinux 7R1项目实施手册PDF
  12. node.js命令行程序在Windows系统和Linux系统下的部署
  13. Ubuntu平台下ROS系统查看RGB摄像头和深度摄像头的连接
  14. SUP桨板电动气泵方案——鼎盛合方案
  15. adb 输入回车命令_Android超级终端(Adb Shell)常用命令、命令大全-持续更新 | 何连超的博客小站...
  16. ASM介绍及简易教程
  17. 关于直播网站的搭建--第一步:获取直播源
  18. 似然函数的意义与极大似然估计
  19. 数据备份与重复数据删除
  20. 交换机的重要技术参数

热门文章

  1. java控制台输出不同颜色文字
  2. 惠州学院采购JKTD-1000型铁电材料测试仪
  3. 0-10岁儿童体重、身高参考值
  4. 软件项目管理--复习资料
  5. 计算机专业可评测绘职称没,本科专业不对口评职称可以不?
  6. 图像分割UNet系列------UNet3+(UNet3plus)详解
  7. 人脸识别算法FaceNet论文解读
  8. 拉普拉斯算子和梯度算子
  9. C语言——第一个只出现一次的字符
  10. 硬件术语大全—CPU、内存、主板、硬盘、显卡、显示器