forked from przemyslawzaworski/Unity3D-CG-programming
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathterrain_shader_tessellation_diffuse.shader
169 lines (154 loc) · 6.14 KB
/
terrain_shader_tessellation_diffuse.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//Author: Przemyslaw Zaworski
//Shader supports maximum four splat textures (Splat and Normal maps) with triangle tessellation.
//Works seamlessly with built-in Terrain Component. Lambert light model (directional) with shadow casting and receiving.
Shader "Terrain Shader Tessellation Diffuse"
{
Properties
{
[HideInInspector] _Control ("Control (RGBA)", 2D) = "red" {}
[HideInInspector] _Splat3 ("Layer 3 (A)", 2D) = "white" {}
[HideInInspector] _Splat2 ("Layer 2 (B)", 2D) = "white" {}
[HideInInspector] _Splat1 ("Layer 1 (G)", 2D) = "white" {}
[HideInInspector] _Splat0 ("Layer 0 (R)", 2D) = "white" {}
[HideInInspector] _Normal3 ("Normal 3 (A)", 2D) = "bump" {}
[HideInInspector] _Normal2 ("Normal 2 (B)", 2D) = "bump" {}
[HideInInspector] _Normal1 ("Normal 1 (G)", 2D) = "bump" {}
[HideInInspector] _Normal0 ("Normal 0 (R)", 2D) = "bump" {}
_TessellationFactor ("Tessellation Factor", Range(0, 64)) = 16
}
SubShader
{
Tags {"RenderType" = "Opaque"}
Pass
{
Tags {"LightMode" = "ForwardBase" "SplatCount" = "4" "Queue" = "Geometry-100"}
CGPROGRAM
#pragma vertex vertex_shader
#pragma hull hull_shader
#pragma domain domain_shader
#pragma fragment pixel_shader
#pragma target 5.0
#pragma multi_compile_fwdbase
#include "AutoLight.cginc"
sampler2D _Control;
float4 _Control_ST;
sampler2D _Splat0;
sampler2D _Splat1;
sampler2D _Splat2;
sampler2D _Splat3;
float4 _Splat0_ST;
float4 _Splat1_ST;
float4 _Splat2_ST;
float4 _Splat3_ST;
float _TessellationFactor;
float4 _LightColor0;
sampler2D _Normal0, _Normal1, _Normal2, _Normal3;
struct APPDATA
{
float2 tc_Control: COLOR;
float4 vertex : POSITION;
float3 normal : NORMAL;
float2 uv_Splat0 : TEXCOORD0;
float2 uv_Splat1 : TEXCOORD1;
float2 uv_Splat2 : TEXCOORD2;
float2 uv_Splat3 : TEXCOORD3;
};
struct VS_CONTROL_POINT_OUTPUT
{
float4 position : SV_POSITION;
float3 normal : NORMAL;
float2 uv_Splat0 : TEXCOORD0;
float2 uv_Splat1 : TEXCOORD1;
float2 uv_Splat2 : TEXCOORD2;
float2 uv_Splat3 : TEXCOORD3;
float2 tc_Control : COLOR;
float4 _ShadowCoord : TEXCOORD4;
};
struct HS_CONSTANT_DATA_OUTPUT
{
float edge[3] : SV_TessFactor;
float inside : SV_InsideTessFactor;
};
float4 ComputeScreenPos (float4 p)
{
float4 o = p * 0.5;
o.xy = float2(o.x, o.y*_ProjectionParams.x) + o.w;
o.zw = p.zw;
return o;
}
VS_CONTROL_POINT_OUTPUT vertex_shader (APPDATA i)
{
VS_CONTROL_POINT_OUTPUT vs;
vs.position = i.vertex;
vs.normal = i.normal;
vs.uv_Splat0 = i.uv_Splat0;
vs.uv_Splat1 = i.uv_Splat1;
vs.uv_Splat2 = i.uv_Splat2;
vs.uv_Splat3 = i.uv_Splat3;
vs.tc_Control = i.tc_Control;
vs._ShadowCoord = ComputeScreenPos(vs.position);
return vs;
}
HS_CONSTANT_DATA_OUTPUT constantsHS (InputPatch<VS_CONTROL_POINT_OUTPUT,3> V)
{
HS_CONSTANT_DATA_OUTPUT output = (HS_CONSTANT_DATA_OUTPUT)0;
output.edge[0] = output.edge[1] = output.edge[2] = _TessellationFactor;
output.inside = _TessellationFactor;
return output;
}
[domain("tri")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[patchconstantfunc("constantsHS")]
[outputcontrolpoints(3)]
VS_CONTROL_POINT_OUTPUT hull_shader (InputPatch<VS_CONTROL_POINT_OUTPUT,3> V, uint ID : SV_OutputControlPointID)
{
return V[ID];
}
[domain("tri")]
VS_CONTROL_POINT_OUTPUT domain_shader (HS_CONSTANT_DATA_OUTPUT input, const OutputPatch<VS_CONTROL_POINT_OUTPUT,3> P, float3 K : SV_DomainLocation)
{
APPDATA ds;
ds.vertex = UnityObjectToClipPos(P[0].position*K.x + P[1].position*K.y + P[2].position*K.z);
ds.normal = (P[0].normal*K.x + P[1].normal*K.y + P[2].normal*K.z);
ds.uv_Splat0 = (P[0].uv_Splat0*K.x + P[1].uv_Splat0*K.y + P[2].uv_Splat0*K.z)*_Splat0_ST.xy+_Splat0_ST.zw;
ds.uv_Splat1 = (P[0].uv_Splat1*K.x + P[1].uv_Splat1*K.y + P[2].uv_Splat1*K.z)*_Splat1_ST.xy+_Splat1_ST.zw;
ds.uv_Splat2 = (P[0].uv_Splat2*K.x + P[1].uv_Splat2*K.y + P[2].uv_Splat2*K.z)*_Splat2_ST.xy+_Splat2_ST.zw;
ds.uv_Splat3 = (P[0].uv_Splat3*K.x + P[1].uv_Splat3*K.y + P[2].uv_Splat3*K.z)*_Splat3_ST.xy+_Splat3_ST.zw;
ds.tc_Control = (P[0].uv_Splat0*K.x + P[1].uv_Splat0*K.y + P[2].uv_Splat0*K.z)*_Control_ST.xy+_Control_ST.zw;
return vertex_shader(ds);
}
float4 pixel_shader (VS_CONTROL_POINT_OUTPUT ps) : SV_Target
{
float3 normal = normalize(mul((float3x3)unity_ObjectToWorld,ps.normal));
float4 tangent = float4 (cross(ps.normal, float3(0,0,1)),-1);
tangent.xyz = normalize(mul((float3x3)unity_ObjectToWorld,tangent.xyz));
float3 binormal = normalize(cross(normal,tangent)*tangent.w);
float4 splat_control = tex2D (_Control, ps.tc_Control);
float weight = dot(splat_control, half4(1,1,1,1));
clip(weight == 0.0f ? -1 : 1);
splat_control /= (weight + 1e-3f);
float3 color = splat_control.r * tex2D (_Splat0, ps.uv_Splat0).rgb;
color += splat_control.g * tex2D (_Splat1, ps.uv_Splat1).rgb;
color += splat_control.b * tex2D (_Splat2, ps.uv_Splat2).rgb;
color += splat_control.a * tex2D (_Splat3, ps.uv_Splat3).rgb;
float4 nrm = splat_control.r * tex2D(_Normal0, ps.uv_Splat0);
nrm += splat_control.g * tex2D(_Normal1, ps.uv_Splat1);
nrm += splat_control.b * tex2D(_Normal2, ps.uv_Splat2);
nrm += splat_control.a * tex2D(_Normal3, ps.uv_Splat3);
nrm.rgb = float3(2.0*nrm.ag-1.0, 0.0);
nrm.b = sqrt(1.0 - dot(nrm.rgb,nrm.rgb));
float3x3 tbn = float3x3(tangent.xyz,binormal,normal);
float attenuation = SHADOW_ATTENUATION(ps);
float3 AmbientLight = UNITY_LIGHTMODEL_AMBIENT;
float3 LightDirection = normalize(_WorldSpaceLightPos0.xyz);
float3 LightColor = _LightColor0.xyz*attenuation;
float3 NormalDirection = normalize(mul(nrm.rgb, tbn));
float3 diffuse = max(dot(LightDirection, NormalDirection),0.0) * LightColor + AmbientLight;
return float4(color*weight*diffuse,1.0);
}
ENDCG
}
}
FallBack "Diffuse"
}