forked from ColinLeung-NiloCat/UnityURPToonLitShaderExample
-
Notifications
You must be signed in to change notification settings - Fork 23
/
SimpleGenshinFacial.shader
305 lines (246 loc) · 16.1 KB
/
SimpleGenshinFacial.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
/*
This shader is a simple example showing you how to write your first URP custom lit shader with "minimum" shader code.
You can use this shader as a starting point, add/edit code to develop your own custom lit shader for URP10.3.2 or above.
*Usually, just by editing "SimpleGenshinFacial_LightingEquation.hlsl" alone can control most of the visual result.
This shader includes 5 passes:
0.ForwardLit pass (this pass will always render to the color buffer _CameraColorTexture)
1.Outline pass (this pass will always render to the color buffer _CameraColorTexture)
2.ShadowCaster pass (only for URP's shadow mapping, this pass won't render at all if your character don't cast shadow)
3.DepthOnly pass (only for URP's depth texture _CameraDepthTexture's rendering, this pass won't render at all if your project don't render URP's offscreen depth prepass)
4.DepthNormals pass (only for URP's normal texture _CameraNormalsTexture's rendering)
*Because most of the time, you use this toon lit shader for unique characters, so all lightmap & GPU instancing related code are removed for simplicity.
*For batching, we only rely on SRP batcher, which is the most practical batching method in URP for rendering lots of unique skinnedmesh characters
*In this shader, we choose static uniform branching over "shader_feature & multi_compile" for some of the togglable feature like "_UseEmission","_UseOcclusion"...,
because:
- we want to avoid this shader's build time takes too long (2^n)
- we want to avoid rendering spike when a new shader variant was seen by the camera first time (create GPU program)
- we want to avoid increasing ShaderVarientCollection's complexity
- we want to avoid shader size becomes too large easily (2^n)
- we want to avoid breaking SRP batcher's batching because SRP batcher is per shader variant batching, not per shader
- all modern GPU(include newer mobile devices) can handle static uniform branching with "almost" no performance cost
*/
Shader "SimpleURPToonLitExample(With Outline)"
{
Properties
{
[Header(High Level Setting)]
[ToggleUI]_IsFace("Is Face? (please turn on if this is a face material)", Float) = 0
[ToggleUI]_UseFaceShadowMap("_UseFaceShadowMap (please turn on this if using dynamic face shadow map)", Float) = 0
// all properties will try to follow URP Lit shader's naming convention
// so switching your URP lit material's shader to this toon lit shader will preserve most of the original properties if defined in this shader
// for URP Lit shader's naming convention, see URP's Lit.shader
[Header(Base Color)]
[MainTexture]_BaseMap("_BaseMap (Albedo)", 2D) = "white" {}
[HDR][MainColor]_BaseColor("_BaseColor", Color) = (1,1,1,1)
[Header(Alpha)]
[Toggle(_UseAlphaClipping)]_UseAlphaClipping("_UseAlphaClipping", Float) = 0
_Cutoff("_Cutoff (Alpha Cutoff)", Range(0.0, 1.0)) = 0.5
[Header(Emission)]
[Toggle]_UseEmission("_UseEmission (on/off Emission completely)", Float) = 0
[HDR] _EmissionColor("_EmissionColor", Color) = (0,0,0)
_EmissionMulByBaseColor("_EmissionMulByBaseColor", Range(0,1)) = 0
[NoScaleOffset]_EmissionMap("_EmissionMap", 2D) = "white" {}
_EmissionMapChannelMask("_EmissionMapChannelMask", Vector) = (1,1,1,0)
[Header(Occlusion)]
[Toggle]_UseOcclusion("_UseOcclusion (on/off Occlusion completely)", Float) = 0
_OcclusionStrength("_OcclusionStrength", Range(0.0, 1.0)) = 1.0
[NoScaleOffset]_OcclusionMap("_OcclusionMap", 2D) = "white" {}
_OcclusionMapChannelMask("_OcclusionMapChannelMask", Vector) = (1,0,0,0)
_OcclusionRemapStart("_OcclusionRemapStart", Range(0,1)) = 0
_OcclusionRemapEnd("_OcclusionRemapEnd", Range(0,1)) = 1
[Header(Lighting)]
_IndirectLightMinColor("_IndirectLightMinColor", Color) = (0.1,0.1,0.1,1) // can prevent completely black if lightprobe not baked
_IndirectLightMultiplier("_IndirectLightMultiplier", Range(0,1)) = 1
_DirectLightMultiplier("_DirectLightMultiplier", Range(0,1)) = 1
_CelShadeMidPoint("_CelShadeMidPoint", Range(-1,1)) = -0.5
_CelShadeSoftness("_CelShadeSoftness", Range(0,1)) = 0.05
_MainLightIgnoreCelShade("_MainLightIgnoreCelShade", Range(0,1)) = 0
_AdditionalLightIgnoreCelShade("_AdditionalLightIgnoreCelShade", Range(0,1)) = 0.9
[Header(Face Lighting)]
[NoScaleOffset]_FaceShadowMap("_FaceShadowMap", 2D) = "white" {}
_FaceDirectionOffset("_FaceDirectionOffset", Float) = 0
[ToggleUI]_FlipFaceDirection("_FlipFaceDirection", Float) = 0
[Header(Shadow mapping)]
_ReceiveShadowMappingAmount("_ReceiveShadowMappingAmount", Range(0,1)) = 0.65
_ReceiveShadowMappingPosOffset("_ReceiveShadowMappingPosOffset", Float) = 0
_ShadowMapColor("_ShadowMapColor", Color) = (1,0.825,0.78)
[Header(Outline)]
_OutlineWidth("_OutlineWidth (World Space)", Range(0,4)) = 1
_OutlineColor("_OutlineColor", Color) = (0.5,0.5,0.5,1)
_OutlineZOffset("_OutlineZOffset (View Space)", Range(0,1)) = 0.0001
[NoScaleOffset]_OutlineZOffsetMaskTex("_OutlineZOffsetMask (black is apply ZOffset)", 2D) = "black" {}
_OutlineZOffsetMaskRemapStart("_OutlineZOffsetMaskRemapStart", Range(0,1)) = 0
_OutlineZOffsetMaskRemapEnd("_OutlineZOffsetMaskRemapEnd", Range(0,1)) = 1
}
SubShader
{
Tags
{
// SRP introduced a new "RenderPipeline" tag in Subshader. This allows you to create shaders
// that can match multiple render pipelines. If a RenderPipeline tag is not set it will match
// any render pipeline. In case you want your subshader to only run in URP, set the tag to
// "UniversalPipeline"
// here "UniversalPipeline" tag is required, because we only want this shader to run in URP.
// If Universal render pipeline is not set in the graphics settings, this Subshader will fail.
// One can add a subshader below or fallback to Standard built-in to make this
// material work with both Universal Render Pipeline and Builtin Unity Pipeline
// the tag value is "UniversalPipeline", not "UniversalRenderPipeline", be careful!
// https://github.com/Unity-Technologies/Graphics/pull/1431/
"RenderPipeline" = "UniversalPipeline"
// explict SubShader tag to avoid confusion
"RenderType"="Opaque"
"UniversalMaterialType" = "Lit"
"Queue"="Geometry"
}
// We can extract duplicated hlsl code from all passes into this HLSLINCLUDE section. Less duplicated code = Less error
HLSLINCLUDE
// all Passes will need this keyword
#pragma shader_feature_local_fragment _UseAlphaClipping
ENDHLSL
// [#0 Pass - ForwardLit]
// Shades GI, all lights, emission and fog in a single pass.
// Compared to Builtin pipeline forward renderer, URP forward renderer will
// render a scene with multiple lights with less drawcalls and less overdraw.
Pass
{
Name "ForwardLit"
Tags
{
// "Lightmode" matches the "ShaderPassName" set in UniversalRenderPipeline.cs.
// SRPDefaultUnlit and passes with no LightMode tag are also rendered by Universal Render Pipeline
// "Lightmode" tag must be "UniversalForward" in order to render lit objects in URP.
"LightMode" = "UniversalForward"
}
// explict render state to avoid confusion
// you can expose these render state to material inspector if needed (see URP's Lit.shader)
Cull Back
ZTest LEqual
ZWrite On
Blend One Zero
HLSLPROGRAM
// ---------------------------------------------------------------------------------------------
// Universal Render Pipeline keywords (you can always copy this section from URP's Lit.shader)
// When doing custom shaders you most often want to copy and paste these #pragmas
// These multi_compile variants are stripped from the build depending on:
// 1) Settings in the URP Asset assigned in the GraphicsSettings at build time
// e.g If you disabled AdditionalLights in the asset then all _ADDITIONA_LIGHTS variants
// will be stripped from build
// 2) Invalid combinations are stripped. e.g variants with _MAIN_LIGHT_SHADOWS_CASCADE
// but not _MAIN_LIGHT_SHADOWS are invalid and therefore stripped.
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS _MAIN_LIGHT_SHADOWS_CASCADE _MAIN_LIGHT_SHADOWS_SCREEN
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile_fragment _ _SHADOWS_SOFT
// ---------------------------------------------------------------------------------------------
// Unity defined keywords
#pragma multi_compile_fog
// ---------------------------------------------------------------------------------------------
#pragma vertex VertexShaderWork
#pragma fragment ShadeFinalColor
// because this pass is just a ForwardLit pass, no need any special #define
// (no special #define)
// all shader logic written inside this .hlsl, remember to write all #define BEFORE writing #include
#include "SimpleGenshinFacial_Shared.hlsl"
ENDHLSL
}
// [#1 Pass - Outline]
// Same as the above "ForwardLit" pass, but
// -vertex position are pushed out a bit base on normal direction
// -also color is tinted
// -Cull Front instead of Cull Back because Cull Front is a must for all extra pass outline method
Pass
{
Name "Outline"
Tags
{
// IMPORTANT: don't write this line for any custom pass! else this outline pass will not be rendered by URP!
//"LightMode" = "UniversalForward"
// [Important CPU performance note]
// If you need to add a custom pass to your shader (outline pass, planar shadow pass, XRay pass when blocked....),
// (0) Add a new Pass{} to your shader
// (1) Write "LightMode" = "YourCustomPassTag" inside new Pass's Tags{}
// (2) Add a new custom RendererFeature(C#) to your renderer,
// (3) write cmd.DrawRenderers() with ShaderPassName = "YourCustomPassTag"
// (4) if done correctly, URP will render your new Pass{} for your shader, in a SRP-batcher friendly way (usually in 1 big SRP batch)
// For tutorial purpose, current everything is just shader files without any C#, so this Outline pass is actually NOT SRP-batcher friendly.
// If you are working on a project with lots of characters, make sure you use the above method to make Outline pass SRP-batcher friendly!
}
Cull Front // Cull Front is a must for extra pass outline method
HLSLPROGRAM
// Direct copy all keywords from "ForwardLit" pass
// ---------------------------------------------------------------------------------------------
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS
#pragma multi_compile _ _MAIN_LIGHT_SHADOWS_CASCADE
#pragma multi_compile _ _ADDITIONAL_LIGHTS_VERTEX _ADDITIONAL_LIGHTS
#pragma multi_compile_fragment _ _ADDITIONAL_LIGHT_SHADOWS
#pragma multi_compile_fragment _ _SHADOWS_SOFT
// ---------------------------------------------------------------------------------------------
#pragma multi_compile_fog
// ---------------------------------------------------------------------------------------------
#pragma vertex VertexShaderWork
#pragma fragment ShadeFinalColor
// because this is an Outline pass, define "ToonShaderIsOutline" to inject outline related code into both VertexShaderWork() and ShadeFinalColor()
#define ToonShaderIsOutline
// all shader logic written inside this .hlsl, remember to write all #define BEFORE writing #include
#include "SimpleGenshinFacial_Shared.hlsl"
ENDHLSL
}
// ShadowCaster pass. Used for rendering URP's shadowmaps
Pass
{
Name "ShadowCaster"
Tags{"LightMode" = "ShadowCaster"}
// more explict render state to avoid confusion
ZWrite On // the only goal of this pass is to write depth!
ZTest LEqual // early exit at Early-Z stage if possible
ColorMask 0 // we don't care about color, we just want to write depth, ColorMask 0 will save some write bandwidth
Cull Back // support Cull[_Cull] requires "flip vertex normal" using VFACE in fragment shader, which is maybe beyond the scope of a simple tutorial shader
HLSLPROGRAM
// the only keywords we need in this pass = _UseAlphaClipping, which is already defined inside the HLSLINCLUDE block
// (so no need to write any multi_compile or shader_feature in this pass)
#pragma vertex VertexShaderWork
#pragma fragment BaseColorAlphaClipTest // we only need to do Clip(), no need shading
// because it is a ShadowCaster pass, define "ToonShaderApplyShadowBiasFix" to inject "remove shadow mapping artifact" code into VertexShaderWork()
#define ToonShaderApplyShadowBiasFix
// all shader logic written inside this .hlsl, remember to write all #define BEFORE writing #include
#include "SimpleGenshinFacial_Shared.hlsl"
ENDHLSL
}
// DepthOnly pass. Used for rendering URP's offscreen depth prepass (you can search DepthOnlyPass.cs in URP package)
// For example, when depth texture is on, we need to perform this offscreen depth prepass for this toon shader.
Pass
{
Name "DepthOnly"
Tags{"LightMode" = "DepthOnly"}
// more explict render state to avoid confusion
ZWrite On // the only goal of this pass is to write depth!
ZTest LEqual // early exit at Early-Z stage if possible
ColorMask 0 // we don't care about color, we just want to write depth, ColorMask 0 will save some write bandwidth
Cull Back // support Cull[_Cull] requires "flip vertex normal" using VFACE in fragment shader, which is maybe beyond the scope of a simple tutorial shader
HLSLPROGRAM
// the only keywords we need in this pass = _UseAlphaClipping, which is already defined inside the HLSLINCLUDE block
// (so no need to write any multi_compile or shader_feature in this pass)
#pragma vertex VertexShaderWork
#pragma fragment BaseColorAlphaClipTest // we only need to do Clip(), no need color shading
// because Outline area should write to depth also, define "ToonShaderIsOutline" to inject outline related code into VertexShaderWork()
#define ToonShaderIsOutline
// all shader logic written inside this .hlsl, remember to write all #define BEFORE writing #include
#include "SimpleGenshinFacial_Shared.hlsl"
ENDHLSL
}
// Starting from version 10.0.x, URP can generate a normal texture called _CameraNormalsTexture.
// To render to this texture in your custom shader, add a Pass with the name DepthNormals.
// For example, see the implementation in Lit.shader.
// TODO: DepthNormals pass (see URP's Lit.shader)
/*
Pass
{
Name "DepthNormals"
Tags{"LightMode" = "DepthNormals"}
//...
}
*/
}
FallBack "Hidden/Universal Render Pipeline/FallbackError"
}