181 lines
7.5 KiB
HLSL
181 lines
7.5 KiB
HLSL
// SPDX-License-Identifier: (Not available for this version, you are only allowed to use this software if you have express permission from the copyright holder and agreed to the latest NiloToonURP EULA)
|
|
// Copyright (c) 2021 Kuroneko ShaderLab Limited
|
|
|
|
// For more information, visit -> https://github.com/ColinLeung-NiloCat/UnityURPToonLitShaderExample
|
|
|
|
// #pragma once is a safeguard best practice in almost every .hlsl,
|
|
// doing this can make sure your .hlsl's user can include this .hlsl anywhere anytime without producing any multi include conflict
|
|
#pragma once
|
|
|
|
// Required by all Universal Render Pipeline shaders.
|
|
// It will include Unity built-in shader variables (except the lighting variables)
|
|
// (https://docs.unity3d.com/Manual/SL-UnityShaderVariables.html
|
|
// It will also include many utilitary functions.
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
|
|
|
|
// Include this if you are doing a lit shader. This includes lighting shader variables,
|
|
// lighting and shadow functions
|
|
#include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
|
|
|
|
// include a few small utility .hlsl files to help us
|
|
#include "/../ShaderLibrary/NiloUtilityHLSL/NiloAllUtilIncludes.hlsl"
|
|
|
|
sampler2D _BaseMap;
|
|
sampler2D _OverrideAlphaMap;
|
|
|
|
#if _NILOTOON_DISSOLVE
|
|
sampler2D _DissolveThresholdMap;
|
|
#endif
|
|
|
|
struct Attributes
|
|
{
|
|
float4 positionOS : POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
|
|
// to support GPU instancing and Single Pass Stereo rendering(VR), add the following section
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID // in non OpenGL / non PSSL, will turn into -> uint instanceID : SV_InstanceID;
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
};
|
|
|
|
struct Varyings
|
|
{
|
|
float4 positionHCS : SV_POSITION;
|
|
float2 uv : TEXCOORD0;
|
|
half fogFactor : TEXCOORD1;
|
|
|
|
// to support GPU instancing and Single Pass Stereo rendering(VR), add the following section
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
UNITY_VERTEX_INPUT_INSTANCE_ID // will turn into this in non OpenGL / non PSSL -> uint instanceID : SV_InstanceID;
|
|
UNITY_VERTEX_OUTPUT_STEREO // will turn into this in non OpenGL / non PSSL -> uint stereoTargetEyeIndexAsRTArrayIdx : SV_RenderTargetArrayIndex;
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
};
|
|
|
|
CBUFFER_START(UnityPerMaterial)
|
|
float4 _BaseMap_ST;
|
|
half4 _BaseColor;
|
|
|
|
// perspective removal
|
|
float _PerspectiveRemovalAmount; // total amount
|
|
|
|
// perspective removal(sphere)
|
|
float _PerspectiveRemovalRadius;
|
|
//float3 _HeadBonePositionWS; // Converted to global array
|
|
|
|
// perspective removal(world height)
|
|
float _PerspectiveRemovalStartHeight; // usually is world space pos.y 0
|
|
float _PerspectiveRemovalEndHeight;
|
|
|
|
float _DitherFadeoutAmount;
|
|
float _PerCharZOffset;
|
|
float _ZOffset;
|
|
|
|
// _NILOTOON_DISSOLVE
|
|
float _DissolveAmount;
|
|
|
|
half _FadeoutByBaseMapAlpha;
|
|
|
|
// Character ID for read global 1D array or load 1D texture
|
|
uint _CharacterID;
|
|
CBUFFER_END
|
|
|
|
half3 _GlobalVolumeMulColor;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
// Global Arrays
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
#define MAX_CHARACTER_COUNT 128
|
|
float3 _NiloToonGlobalPerCharHeadBonePosWSArray[MAX_CHARACTER_COUNT];
|
|
|
|
Varyings vert(Attributes IN)
|
|
{
|
|
Varyings OUT;
|
|
|
|
// disable rendering sticker if minimum shader debug is on
|
|
#if _NILOTOON_FORCE_MINIMUM_SHADER
|
|
return (Varyings)0;
|
|
#endif
|
|
|
|
// to support GPU instancing and Single Pass Stereo rendering(VR), add the following section
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
UNITY_SETUP_INSTANCE_ID(IN); // will turn into this in non OpenGL / non PSSL -> UnitySetupInstanceID(input.instanceID);
|
|
UNITY_TRANSFER_INSTANCE_ID(IN, OUT); // will turn into this in non OpenGL / non PSSL -> output.instanceID = input.instanceID;
|
|
UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(OUT); // will turn into this in non OpenGL / non PSSL -> output.stereoTargetEyeIndexAsRTArrayIdx = unity_StereoEyeIndex;
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
|
|
|
|
// fog, do it before any positionHCS.z's edit
|
|
OUT.fogFactor = ComputeFogFactor(OUT.positionHCS.z);
|
|
|
|
// zoffset
|
|
OUT.positionHCS = NiloGetNewClipPosWithZOffsetVS(OUT.positionHCS, -(_ZOffset+_PerCharZOffset));
|
|
|
|
// perspective removal
|
|
float3 positionWS = mul(UNITY_MATRIX_M, float4(IN.positionOS.xyz,1)).xyz;
|
|
OUT.positionHCS = NiloDoPerspectiveRemoval(OUT.positionHCS,positionWS,_NiloToonGlobalPerCharHeadBonePosWSArray[_CharacterID],_PerspectiveRemovalRadius,_PerspectiveRemovalAmount, _PerspectiveRemovalStartHeight, _PerspectiveRemovalEndHeight);
|
|
|
|
OUT.uv = TRANSFORM_TEX(IN.uv,_BaseMap);
|
|
|
|
return OUT;
|
|
}
|
|
|
|
half FogAsAlpha(real fogFactor)
|
|
{
|
|
#if defined(FOG_LINEAR) || defined(FOG_EXP) || defined(FOG_EXP2)
|
|
return ComputeFogIntensity(fogFactor);
|
|
#else
|
|
return 1; // if fog is off, return constant 1 so it will not affect any multiplication (compiler will remove * 1)
|
|
#endif
|
|
}
|
|
|
|
half4 frag(Varyings IN) : SV_Target
|
|
{
|
|
// to support GPU instancing and Single Pass Stereo rendering(VR), add the following section
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
UNITY_SETUP_INSTANCE_ID(IN); // in non OpenGL / non PSSL, MACRO will turn into -> UnitySetupInstanceID(input.instanceID);
|
|
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(IN); // in non OpenGL / non PSSL, MACRO will turn into -> unity_StereoEyeIndex = input.stereoTargetEyeIndexAsRTArrayIdx;
|
|
//------------------------------------------------------------------------------------------------------------------------------
|
|
|
|
// dither
|
|
#if _NILOTOON_DITHER_FADEOUT
|
|
NiloDoDitherFadeoutClip(IN.positionHCS.xy, 1-_DitherFadeoutAmount);
|
|
#endif
|
|
|
|
// dissolve (copied from nilotoon character shader's ApplyDissolve())
|
|
#if _NILOTOON_DISSOLVE
|
|
// read black and white map
|
|
half dissolveMapThresholdMapValue = tex2D(_DissolveThresholdMap, IN.uv).g;
|
|
|
|
half dissolve = dissolveMapThresholdMapValue - _DissolveAmount;
|
|
|
|
// clip threshold
|
|
clip(dissolve);
|
|
|
|
// no need to edit color, we only need clip()
|
|
//...
|
|
#endif
|
|
|
|
half4 customColor = tex2D(_BaseMap, IN.uv);
|
|
|
|
#if OVERRIDE_ALPHA
|
|
customColor.a = tex2D(_OverrideAlphaMap, IN.uv).r; // TODO: accept r,g,b,a option
|
|
#endif
|
|
|
|
customColor *= _BaseColor;
|
|
|
|
half fogAsAlpha = FogAsAlpha(IN.fogFactor);
|
|
half opacity = customColor.a * fogAsAlpha;
|
|
|
|
#if NiloToonStickerMultiply
|
|
customColor.rgb = lerp(1,customColor.rgb, opacity);
|
|
#endif
|
|
#if NiloToonStickerAdditive
|
|
customColor.rgb *= opacity;
|
|
customColor.rgb *= _GlobalVolumeMulColor;
|
|
#endif
|
|
|
|
// return const 1 alpha, since ColorMask is RGB, the return value of alpha doesn't matter
|
|
return half4(customColor.rgb, 1);
|
|
}
|