HeavenStudioPlus/Assets/Plugins/UnityURPToonLitShaderExampl.../SimpleURPToonLitOutlineExam...

301 lines
16 KiB
Plaintext

// 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 "SimpleURPToonLitOutlineExample_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
// 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(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
#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
// ---------------------------------------------------------------------------------------------
// 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 "SimpleURPToonLitOutlineExample_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 "SimpleURPToonLitOutlineExample_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 "SimpleURPToonLitOutlineExample_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 "SimpleURPToonLitOutlineExample_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"
}