|
【前言】
本方法完全没有理论支撑,效果不严谨,仅适合不想改uv的懒人,而且就目前的测试来看只适用于【整体形状规则,大体接近球形】的头发模型,有的角度会有点怪(怎么限制这么多),各位轻喷ww。
如果不介意以上问题的话可以继续往下看了。
【正文】
一、先看效果:
blender里的效果
unity里面的效果
头发部分的UV,并不是直的
模型使用的是 模之屋:【深空之眼】诗蔻蒂
二、思路
这个效果其实是很偶然做出来的,当既不懂blender又不懂unity的我照着别人的代码在blender里面做出了这个效果时,我以为一切都是正常的。结果当我尝试在unity里面复现效果时,乱七八糟的高光给了我深深的疑惑==。
代码学习了这一篇Shader学习 (16)非物理各向异性Shader 作者:九猫
后来我细品了一下我在blender里面的做法,节点如下:
发现问题就出在黄字部分,它输入的“切向(正切)”和我们在unity中理解的并不一样。我们直接输出“切向(正切)”看一下:
看起来是世界空间的,而且也跟uv没有什么关系,但是居然能得到还算不错的结果,那我们就直接在unity里面抄一下吧。
1、首先,找个能做出上图效果的东西,我想到的是物体在模型空间的坐标,要注意:在blender中我把头发部分拆成了单独的物体(意味着头发的原点在头发的中心),但是unity中没有,所以头发的模型空间坐标的Y值会很大,Z值也有一点偏差,解决方法是直接把Y的值归零,Z值加上一个偏移值(自己调个差不多的就行)。
然后结果和blender可能还是有点不一样的:
2、我们知道unity的坐标系和blender不同,所以这里输出的蓝色(Z值)相当于blender中的绿色(Y值),除此之外,红色和蓝色分布的地方也不对,调整一下位置即可:
float3 FakeTangent= normalize(float3(i.modelpos.x,0,i.modelpos.z+_Zbias));
FakeTangent= float4(FakeTangent.z,FakeTangent.y,-FakeTangent.x,1);3、好了,接下来把这个假切线和法线叉乘一下得到假副切线,然后用常规的方法算高光就可以了。有可能遇到法线不够平整的问题会出现奇怪的结果(我在blender里面也是使用了平滑光照),可以把模型法线平滑一下看看
4、高光shader代码
Shader "test/hair"
{
Properties
{
_Shift1("_Shift1",Range(-2,2)) = 0
_Gloss1("_Gloss1",Range(0,600)) = 1
_Zbias("_Zbias", Range(-0.1, 0.1)) = 0
_LightDir("_LightDir",Vector) = (1,0,1,1)
}
SubShader
{
Pass
{
CULL OFF
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert2
#pragma fragment frag
#include "UnityCG.cginc"
float _Shift1;
float _Gloss1;
float _Zbias;
float4 _LightDir;
struct appdata2
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
float3 normal : NORMAL;
};
struct v2f2
{
float2 uv : TEXCOORD0;
float4 pos : SV_POSITION;
float4 worldPos :TEXCOORD5;
float3 normalDir : TEXCOORD2;
float3 modelpos:TEXCOORD4;
};
v2f2 vert2 (appdata2 v)
{
v2f2 o;
o.pos = UnityObjectToClipPos(v.vertex);
o.uv = v.uv;
float4 worldPos = mul(UNITY_MATRIX_M, v.vertex);
o.worldPos.xyz = worldPos.xyz;
o.worldPos.w = 1;
o.normalDir = UnityObjectToWorldDir(v.normal);
o.modelpos=v.vertex.xyz;
return o;
}
fixed4 frag (v2f2 i) : SV_Target
{
float3 FakeTangent= normalize(float3(i.modelpos.x,0,i.modelpos.z+_Zbias));//用来算头发高光的
FakeTangent= float4(FakeTangent.z,FakeTangent.y,-FakeTangent.x,1);
float3 normalDir = normalize(i.normalDir);
float3 FakeBionormal=cross( normalDir,FakeTangent);
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz);
float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos.xyz);
float3 tangent1 = normalize(FakeBionormal + _Shift1 * normalDir);
float3 H1 = (normalize(_LightDir) + 0.8*viewDir);//这里0.8随便写的,减少视线方向的影响使效果更稳定
float dotTH1 = dot(tangent1, H1);
float sinTH1 = sqrt(1.0 - dotTH1 * dotTH1);
float dirAtten1 = smoothstep(-1, 0, dotTH1);
float S1 =pow(sinTH1, _Gloss1);
return S1;
}
ENDCG
}
// shadow casting support
UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
}
Fallback "Diffuse"
}我自己调整的参数:
Gloss1有点太离谱了,可以用其他方法优化一下
最后整合到自己的shader里面,感觉高光效果还可以
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|