unity-shader-normal

效果图

资源图

NormalInWorld.shader

NormalInWorld.shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
Shader "Popo/NormalInWorld"
{
Properties
{
_Color("Color", Color) = (1, 1, 1, 1)
_MainTex("Main Tex", 2D) = "white" {}
_NormalTex("Normal Tex", 2D) = "bump" {}
_NormalFac("Normal Fac", Float) = 1.0
_SpecularColor("Specular Color", Color) = (1, 1, 1, 1)
_SpecularGloss("Specular Gloss", Range(1.0, 256)) = 8
}

SubShader
{
Pass
{
Tags {"LightMode" = "ForwardBase"}

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "Lighting.cginc"

fixed4 _Color; // 主颜色
sampler2D _MainTex; // 主纹理
float4 _MainTex_ST; // 漫反射纹理系数
sampler2D _NormalTex; // 法线纹理
float4 _NormalTex_ST; // 法线纹理系数
float _NormalFac; // 法线系数
fixed4 _SpecularColor; // 高光颜色
float _SpecularGloss; // 高光因子

struct a2v{
float4 vertex : POSITION; // 顶点坐标
float3 normal : NORMAL; // 顶点法线
float4 tangent : TANGENT; // 顶点切线
float4 texcoord : TEXCOORD0; // 顶点UV
};

struct v2f{
float4 pos : SV_POSITION; // 顶点裁剪坐标
float4 uv : TEXCOORD0; // 存放顶点漫反射纹理uv和法线纹理uv
float4 TtoW0 : TEXCOORD1; // 存放切线空间信息+世界坐标
float4 TtoW1 : TEXCOORD2; // 存放切线空间信息+世界坐标
float4 TtoW2 : TEXCOORD3; // 存放切线空间信息+世界坐标
};

v2f vert(a2v v){
v2f o;

// 计算裁剪坐标
// o.pos = mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1.0)));
o.pos = UnityObjectToClipPos(v.vertex);

// 计算漫反射纹理和法线纹理uv
o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
o.uv.zw = v.texcoord.xy * _NormalTex_ST.xy + _NormalTex_ST.zw;

// 计算切线空间各轴
float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

// fixed3 worldNormal = normalize(mul(v.normal, (float3x3)unity_WorldToObject));
fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);

// fixed3 worldTangent = normalize(mul((float3x3)unity_ObjectToWorld, v.tangent.xyz));
fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);

fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w;

// 把切线空间的轴信息存起来
o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);

return o;
}

fixed4 frag(v2f i) : SV_Target{

// 还原世界坐标
float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);

// 计算世界空间的光照方向
// fixed3 lightDir = normalize(_WorldSpaceLightPos0.xyz - worldPos * _WorldSpaceLightPos0.w);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));

// 计算世界空间的视图方向
// fixed3 viewDir = normalize(_WorldSpaceCameraPos.xyz - worldPos);
fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

// 采样法线
// fixed4 texNormal = tex2D(_NormalTex, i.uv.zw);
// texNormal.x *= texNormal.w;
// fixed3 normal;
// normal.xy = texNormal.xy * 2 - 1;
// normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));
// fixed3 tNormal = normal;
fixed3 tNormal = UnpackNormal(tex2D(_NormalTex, i.uv.zw));

// 法线调整
tNormal.xy *= _NormalFac;
tNormal.z = sqrt(1.0 - saturate(dot(tNormal.xy, tNormal.xy)));

// 法线变换到世界空间
tNormal = normalize(half3(dot(i.TtoW0.xyz, tNormal), dot(i.TtoW1.xyz, tNormal), dot(i.TtoW2.xyz, tNormal)));

// 采样漫反射纹理
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;

// 环境光计算
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

// 漫反射颜色计算
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tNormal, lightDir));

// 高光计算
fixed3 halfDir = normalize(lightDir + viewDir);
fixed3 specular = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(tNormal, halfDir)), _SpecularGloss);

return fixed4(ambient + diffuse + specular, 1.0);
}

ENDCG
}
}

FallBack "Specular"
}

NormalInTangent.shader

NormalInTangent.shader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
Shader "Popo/NormalInTangent"
{
Properties
{
_Color("Color", Color) = (1, 1, 1, 1)
_MainTex("Main Tex", 2D) = "white" {}
_NormalTex("Normal Tex", 2D) = "bump" {}
_NormalFac("Normal Fac", Float) = 1.0
_SpecularColor("Specular Color", Color) = (1, 1, 1, 1)
_SpecularGloss("Specular Gloss", Range(1.0, 256)) = 8
}

SubShader
{
Pass
{
Tags { "LightMode" = "ForwardBase" }

CGPROGRAM

#pragma vertex vert
#pragma fragment frag

#include "Lighting.cginc"

fixed4 _Color; // 主颜色
sampler2D _MainTex; // 主纹理
float4 _MainTex_ST; // 漫反射纹理系数
sampler2D _NormalTex; // 法线纹理
float4 _NormalTex_ST; // 法线纹理系数
float _NormalFac; // 法线系数
fixed4 _SpecularColor; // 高光颜色
float _SpecularGloss; // 高光因子

struct a2v{
float4 vertex : POSITION; // 顶点坐标
float3 normal : NORMAL; // 顶点法线
float4 tangent : TANGENT; // 顶点切线
float4 texcoord : TEXCOORD0; // 顶点UV
};

struct v2f {
float4 pos : SV_POSITION; // 顶点裁剪坐标
float4 uv : TEXCOORD0; // 存放顶点漫反射纹理uv和法线纹理uv
float3 lightDir: TEXCOORD1; // 切线空间的光照方向
float3 viewDir : TEXCOORD2; // 切线空间的视窗方向
};

v2f vert(a2v v) {
v2f o;

// 计算裁剪坐标
// o.pos = mul(UNITY_MATRIX_VP, mul(unity_ObjectToWorld, float4(v.vertex.xyz, 1.0)));
o.pos = UnityObjectToClipPos(v.vertex);

// 计算漫反射纹理和法线纹理uv
o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
o.uv.zw = v.texcoord.xy * _NormalTex_ST.xy + _NormalTex_ST.zw;

// 计算切线空间变换矩阵
// float3 binormal = cross( normalize(v.normal), normalize(v.tangent.xyz) ) * v.tangent.w;
// float3x3 rotation = float3x3( v.tangent.xyz, binormal, v.normal );
TANGENT_SPACE_ROTATION;

// 光照方向从模型空间变换到切线空间
// float3 objSpaceLightPos = mul(unity_WorldToObject, _WorldSpaceLightPos0).xyz;
// float3 oSpaceLightDir = objSpaceLightPos.xyz - v.vertex.xyz * _WorldSpaceLightPos0.w;
float3 oSpaceLightDir = ObjSpaceLightDir(v.vertex);
o.lightDir = mul(rotation, oSpaceLightDir).xyz;

// 视窗方向从模型空间变换到切线空间
// float3 objSpaceCameraPos = mul(unity_WorldToObject, float4(_WorldSpaceCameraPos.xyz, 1)).xyz;
// float3 oSpaceViewDir = objSpaceCameraPos - v.vertex.xyz;
float3 oSpaceViewDir = ObjSpaceViewDir(v.vertex);
o.viewDir = mul(rotation, oSpaceViewDir).xyz;

return o;
}

fixed4 frag(v2f i) : SV_Target{
// 标准化光照和视窗方向变量
fixed3 tangentLightDir = normalize(i.lightDir);
fixed3 tangentViewDir = normalize(i.viewDir);

// 采样法线纹理
fixed4 packedNormal = tex2D(_NormalTex, i.uv.zw);

// packedNormal.x *= packedNormal.w;
// fixed3 normal;
// normal.xy = packedNormal.xy * 2 - 1;
// normal.z = sqrt(1 - saturate(dot(normal.xy, normal.xy)));
// fixed3 tNormal = normal;
fixed3 tNormal = UnpackNormal(packedNormal);

// 法线调整
tNormal.xy *= _NormalFac;
tNormal.z = sqrt(1.0 - saturate(dot(tNormal.xy, tNormal.xy)));

// 采样漫反射纹理
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _Color.rgb;

// 环境光计算
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

// 漫反射颜色计算
fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(tNormal, tangentLightDir));

// 高光计算
fixed3 halfDir = normalize(tangentLightDir + tangentViewDir);
fixed3 specular = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(tNormal, halfDir)), _SpecularGloss);

return fixed4(ambient + diffuse + specular, 1.0);
}

ENDCG
}
}

FallBack "Specular"
}