Added HairBlending shader pass;

Added HairBlendingSetting in UTSRenderPassSetting;
Added MaterialType to UTS;
Added MaterialFeature scope to UTS material editor;

Merged HairBlendingPass and HairShadowPass into UTSPass;

Fixed the bug that character box light can not update rotation correctly according to bound light source;
This commit is contained in:
Misaki
2025-01-09 07:58:06 +09:00
parent 9290223624
commit d47641e5e2
18 changed files with 627 additions and 368 deletions

View File

@@ -22,6 +22,9 @@ Shader "HDRP/Toon"
_BaseColorMap("BaseColorMap", 2D) = "white" {}
[HideInInspector] _BaseColorMap_MipInfo("_BaseColorMap_MipInfo", Vector) = (0, 0, 0, 0)
_HairBlendingMap("HairBlendingMap", 2D) = "black" {}
[KeywordEnum(OFF, FrontHair, Face, Eye)] _Material_Type("Material Type", Float) = 0
[KeywordEnum(OFF, ST, ANISO, KK, TOON)] _PBR_Mode("PBR MODE", Float) = 0
_Metallic("_Metallic", Range(0.0, 1.0)) = 0
_Smoothness("Smoothness", Range(0.0, 1.0)) = 0.5
@@ -330,8 +333,8 @@ Shader "HDRP/Toon"
_EyeParallaxAmount("EyeParallaxAmount", Float) = 0.1
// Eyebrow Seethrough
[Togle(_)] _Is_EyebrowSeethrough("_Is_EyebrowSeethrough", Float) = 0
_EyeBrowBlendingFactor("EyeBrowBlendingFactor", Float) = 0.5
[Togle(_)] _Is_HairBlendingTarget("_Is_HairBlendingTarget", Float) = 0
_HairBlendingFactor("EyeBrowBlendingFactor", Float) = 0.5
//v.2.0.6
_BaseColor_Step("BaseColor_Step", Range(0, 1)) = 0.5
@@ -516,8 +519,6 @@ Shader "HDRP/Toon"
// Variant
//-------------------------------------------------------------------------------------
#pragma shader_feature _HAIR_SHADOWS
#pragma shader_feature_local _ALPHATEST_ON
#pragma shader_feature_local _DEPTHOFFSET_ON
#pragma shader_feature_local _DOUBLESIDED_ON
@@ -530,15 +531,6 @@ Shader "HDRP/Toon"
#pragma shader_feature_local _NORMALMAP_TANGENT_SPACE
#pragma shader_feature_local _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _DISABLE_DECALS
#pragma shader_feature_local _DISABLE_SSR
#pragma shader_feature_local _MASKMAP
#pragma shader_feature_local _ANISOTROPYMAP
#pragma shader_feature_local _SDFShadow
#pragma shader_feature_local _SPECULARCOLORMAP
#pragma shader_feature_local_fragment _ENABLE_FOG_ON_TRANSPARENT
#pragma shader_feature_local _TRANSPARENT_WRITES_MOTION_VEC
@@ -963,7 +955,7 @@ Shader "HDRP/Toon"
HLSLPROGRAM
// #pragma multi_compile _ UTS_DEBUG_SHADOWMAP_BINALIZATION
//#pragma multi_compile _ UTS_DEBUG_SHADOWMAP_BINALIZATION
#pragma multi_compile _ DEBUG_DISPLAY
#pragma multi_compile _ LIGHTMAP_ON
#pragma multi_compile _ DIRLIGHTMAP_COMBINED
@@ -974,9 +966,10 @@ Shader "HDRP/Toon"
#pragma multi_compile SCREEN_SPACE_SHADOWS_OFF SCREEN_SPACE_SHADOWS_ON
// Supported shadow modes per light type
#pragma multi_compile SHADOW_LOW SHADOW_MEDIUM SHADOW_HIGH
#pragma multi_compile MATERIAL_TYPE_STANDARD MATERIAL_TYPE_FRONT_HAIR MATERIAL_TYPE_FACE MATERIAL_TYPE_EYE
#pragma multi_compile _PBR_Mode_OFF _PBR_Mode_ST _PBR_Mode_ANISO _PBR_Mode_KK _PBR_Mode_TOON
#define LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
// #pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
//#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#define AREA_SHADOW_LOW
#define SHADERPASS SHADERPASS_FORWARD
// In case of opaque we don't want to perform the alpha test, it is done in depth prepass and we use depth equal for ztest (setup from UI)
@@ -998,23 +991,27 @@ Shader "HDRP/Toon"
//Probe volume
#pragma multi_compile PROBE_VOLUMES_OFF PROBE_VOLUMES_L1 PROBE_VOLUMES_L2
// Sample Face Shadow
#pragma shader_feature ENABLE_UTS_HAIR_SHAOW
#pragma shader_feature ENABLE_UTS_HAIR_BLENDING
#pragma shader_feature_local _MASKMAP
#pragma shader_feature_local _NORMALMAP
#pragma shader_feature_local _ANISOTROPYMAP
#pragma shader_feature_local _SPECULARCOLORMAP
#pragma shader_feature_local _SDFShadow
#pragma shader_feature_local _RECEIVE_HAIR_SHADOW
// Eye parallax
#pragma shader_feature_local _EYE_PARALLAX
// Eyebrow Blending with hair
#pragma shader_feature_local _EYEBROW_SEETHROUGH
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/Lighting.hlsl"
#ifdef DEBUG_DISPLAY
# if (SHADER_LIBRARY_VERSION_MAJOR >= 10)
#include "DebugDisplay.hlsl"
# else
#include "DebugDisplayHDRP7.hlsl"
# endif
#endif
#ifdef DEBUG_DISPLAY
# if (SHADER_LIBRARY_VERSION_MAJOR >= 10)
#include "DebugDisplay.hlsl"
# else
#include "DebugDisplayHDRP7.hlsl"
# endif
#endif
// The light loop (or lighting architecture) is in charge to:
// - Define light list
@@ -1032,16 +1029,16 @@ Shader "HDRP/Toon"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Lighting/LightLoop/LightLoop.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/ShaderPass/LitSharePass.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitData.hlsl"
#ifdef DEBUG_DISPLAY
# if (SHADER_LIBRARY_VERSION_MAJOR >= 10)
#include "ShaderPassForward.hlsl"
# else
#include "ShaderPassForwardHDRP7.hlsl"
# endif
#else
#include "UtsLightLoop.hlsl"
#include "ShaderPassForwardUTS.hlsl"
#endif
#ifdef DEBUG_DISPLAY
# if (SHADER_LIBRARY_VERSION_MAJOR >= 10)
#include "ShaderPassForward.hlsl"
# else
#include "ShaderPassForwardHDRP7.hlsl"
# endif
#else
#include "UtsLightLoop.hlsl"
#include "ShaderPassForwardUTS.hlsl"
#endif
#pragma vertex Vert
#pragma fragment Frag
@@ -1110,7 +1107,6 @@ Shader "HDRP/Toon"
Cull Front
Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
@@ -1185,6 +1181,39 @@ Shader "HDRP/Toon"
ENDHLSL
}
Pass
{
Name "HairBlendingTarget"
Tags{ "LightMode" = "HairBlendingTarget" }
Cull[_CullMode]
ZClip [_ZClip]
ZWrite On
ZTest LEqual
HLSLPROGRAM
#define SHADERPASS SHADERPASS_FORWARD
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Material.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/Lit.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/ShaderPass/LitSharePass.hlsl"
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Material/Lit/LitData.hlsl"
#ifdef DEBUG_DISPLAY
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/Debug/DebugDisplay.hlsl"
#endif
#include "HDRPToonHead.hlsl"
#include "HDRPToonHairBlending.hlsl"
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
}
}
SubShader

View File

@@ -0,0 +1,127 @@
#undef unity_ObjectToWorld
#undef unity_WorldToObject
#ifdef _WRITE_TRANSPARENT_MOTION_VECTOR
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/MotionVectorVertexShaderCommon.hlsl"
// PackedVaryingsType
// https://github.com/Unity-Technologies/Graphics/blob/e4117c07b479adafed38237f3407a363eefb4590/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl#L120
PackedVaryingsType Vert(AttributesMesh inputMesh, AttributesPass inputPass)
{
// VaryingsType
// https://github.com/Unity-Technologies/Graphics/blob/e4117c07b479adafed38237f3407a363eefb4590/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl#L118
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return MotionVectorVS(varyingsType, inputMesh, inputPass);
}
#else // _WRITE_TRANSPARENT_MOTION_VECTOR
#include "Packages/com.unity.render-pipelines.high-definition/Runtime/RenderPipeline/ShaderPass/VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#endif // _WRITE_TRANSPARENT_MOTION_VECTOR
#ifdef UNITY_VIRTUAL_TEXTURING
#define VT_BUFFER_TARGET SV_Target1
#define EXTRA_BUFFER_TARGET SV_Target2
#else
#define EXTRA_BUFFER_TARGET SV_Target1
#endif
void Frag(PackedVaryingsToPS packedInput,
#ifdef OUTPUT_SPLIT_LIGHTING
out float4 outColor : SV_Target0, // outSpecularLighting
#ifdef UNITY_VIRTUAL_TEXTURING
out float4 outVTFeedback : VT_BUFFER_TARGET,
#endif
out float4 outDiffuseLighting : EXTRA_BUFFER_TARGET,
OUTPUT_SSSBUFFER(outSSSBuffer)
#else
out float4 outColor : SV_Target0
#ifdef UNITY_VIRTUAL_TEXTURING
, out float4 outVTFeedback : VT_BUFFER_TARGET
#endif
#ifdef _WRITE_TRANSPARENT_MOTION_VECTOR
, out float4 outMotionVec : EXTRA_BUFFER_TARGET
#endif // _WRITE_TRANSPARENT_MOTION_VECTOR
#endif // OUTPUT_SPLIT_LIGHTING
#ifdef _DEPTHOFFSET_ON
, out float outputDepth : SV_Depth
#endif
)
{
UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(packedInput);
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
#ifdef _IS_CLIPPING_MASK
if (_ClippingMaskMode != 0)
{
discard;
}
#endif
#ifdef _IS_CLIPPING_MATTE
if (_ClippingMatteMode != 0)
{
discard;
}
#endif // _IS_CLIPPING_MATTE
#if defined(UTS_DEBUG_SHADOWMAP_NO_OUTLINE)
discard;
#endif
//v.2.0.5
if (_ZOverDrawMode > 0.99f)
{
#ifdef _DEPTHOFFSET_ON
outputDepth = posInput.deviceDepth;
#endif
#ifdef UNITY_VIRTUAL_TEXTURING
outVTFeedback = builtinData.vtPackedFeedback;
#endif
outColor = float4(1.0f, 1.0f, 1.0f, 1.0f); // but nothing should be drawn except Z value as colormask is set to 0
return;
}
_Color = _BaseColor;
float4 objPos = mul(unity_ObjectToWorld, float4(0, 0, 0, 1));
float4 Set_UV0 = input.texCoord0;
// The following temporary definition of unity_AmbientEquator is for HDRP only.
//float4 unity_AmbientEquator = float4(0.05, 0.05, 0.05, 1.0); //Todo.
//v.2.0.9
//float3 envLightSource_GradientEquator = unity_AmbientEquator.rgb > 0.05 ? unity_AmbientEquator.rgb : half3(0.05, 0.05, 0.05);
float3 envLightSource_GradientEquator = ShadeSH9(float4(0, 1, 0, 0));
float3 envLightSource_SkyboxIntensity = max(
SampleBakedGI_UTS_OutLine(objPos.xyz, float3(0.0, 0.0, 0.0), input.texCoord1.xy, input.texCoord2.xy),
SampleBakedGI_UTS_OutLine(objPos.xyz, float3(0.0, -1.0, 0.0), input.texCoord1.xy, input.texCoord2.xy)
).rgb;
float3 ambientSkyColor = envLightSource_SkyboxIntensity.rgb > 0.0 ? envLightSource_SkyboxIntensity : envLightSource_GradientEquator;
ambientSkyColor *= GetCurrentExposureMultiplier();
float4 _BlendingTex_var = SAMPLE_TEXTURE2D(_HairBlendingMap, sampler_HairBlendingMap, TRANSFORM_TEX(Set_UV0, _MainTex));
outColor = float4(_BlendingTex_var.rgb * ambientSkyColor, _BlendingTex_var.a);
#ifdef _DEPTHOFFSET_ON
outputDepth = posInput.deviceDepth;
#endif
#ifdef UNITY_VIRTUAL_TEXTURING
outVTFeedback = builtinData.vtPackedFeedback;
#endif
}
// End of File

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: a528382509a1bca4b9da190eb68e40d4
ShaderIncludeImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -194,7 +194,7 @@ void Frag(PackedVaryingsToPS packedInput,
#ifdef VARYINGS_NEED_POSITION_WS
float3 V = GetWorldSpaceNormalizeViewDir(input.positionRWS);
#ifdef _EYE_PARALLAX
#ifdef MATERIAL_TYPE_EYE
// Must have view Dir to work
float2 viewT = TransformObjectToTangent(V, input.tangentToWorld);
float2 parallaxOffset = viewT;
@@ -878,7 +878,7 @@ void Frag(PackedVaryingsToPS packedInput,
// We directly calculate custome main light during the light loop in upper code to avoid extra calculation
//customMainLight = GetCustomMainLightData(builtinData, mainPunctualLight);
#if _SDFShadow || _RECEIVE_HAIR_SHADOW
#if _SDFShadow || (_RECEIVE_HAIR_SHADOW && ENABLE_UTS_HAIR_SHAOW)
float3 defaultLightDirection = normalize(UNITY_MATRIX_V[2].xyz + UNITY_MATRIX_V[1].xyz);
float3 defaultLightColor = saturate(max(float3(0.05, 0.05, 0.05) * _Unlit_Intensity, max(ShadeSH9(float4(0.0, 0.0, 0.0, 1.0)), ShadeSH9(float4(0.0, -1.0, 0.0, 1.0)).rgb) * _Unlit_Intensity));
@@ -910,7 +910,7 @@ void Frag(PackedVaryingsToPS packedInput,
utsAggregateLighting.directSpecular += _SDFNoseHighlightCoef * SDFNoseHighlight(angle, sdfRes.g, rightside, SDF_UV) * lightColor;
#endif
#ifdef _RECEIVE_HAIR_SHADOW
#if _RECEIVE_HAIR_SHADOW && ENABLE_UTS_HAIR_SHAOW
// Push the face fragment view space position towards the light for a little bit
float hairShadowOpacity = saturate(Remap(length(posInput.positionWS), float2(_HairShadowFadeOutDistance, _HairShadowFadeInDistance), float2(0, 1)));
@@ -921,6 +921,10 @@ void Frag(PackedVaryingsToPS packedInput,
float shadowLengthY = _HairShadowDistance * 5.0 * max(0.5, posInput.linearDepth * _HairShadowDistanceScaleFactor) / posInput.linearDepth;
float2 shadowLength = float2(shadowLengthY * 2.0f, shadowLengthY);
float3 camDirOS = normalize(TransformWorldToObject(GetCameraPositionWS()));
float camDirFactor = 1 - smoothstep(0.1, 0.9, camDirOS.y);
shadowLength.y *= camDirFactor;
float2 samplingPoint = (input.positionSS.xy + shadowLength * viewLightDir.xy * (_ScreenSize.xy / float2 (1920.0f, 1080.0f))) * _ScreenSize.zw; // Use 1080p as the reference resolution to achieve consistent shadow lengths across various screen resolutions.
// Then sample the hair buffer, to see if the fragment lands in shadow.
@@ -958,29 +962,13 @@ void Frag(PackedVaryingsToPS packedInput,
outColor = float4(outColor.rgb, Set_Opacity * ApplyChannelAlpha(channelAlpha));
#endif
#ifdef _EYEBROW_SEETHROUGH
// By Suomi, 20230915
// The eyebrow should use transparent pass and utilize the hair depth texture we have from HairShadowPass
float2 samplingPoint = posInput.positionNDC;
float cDepth = SampleCameraDepth(samplingPoint); // Camera Depth. At transparent queue we should have all the opaque object by now
float mDepth = posInput.deviceDepth; // Depth of this fragment
float3 hDepth = SAMPLE_TEXTURE2D(_HairShadowTex, s_trilinear_clamp_sampler, samplingPoint); // r: Depth of hair g: Depth of Eyebrow
float hairPixel = step(0.001, hDepth.r);
float magic = 0.075;
mDepth = hairPixel > 0.1 ? max(hDepth.r, mDepth) + magic : mDepth; // Move this part of eyebrow in front of the hair
// Added a max here to prevent sampling of hair in the back
if(cDepth - mDepth > 0.02) // Manual Depth Test
{
discard;
}
outColor.a = _EyeBrowBlendingFactor;
outColor.a = hairPixel > 0.01 ? outColor.a : 1 ;
#if MATERIAL_TYPE_FRONT_HAIR && ENABLE_UTS_HAIR_BLENDING
float2 screenUV = posInput.positionNDC * _HairBlendingRTHandleScale.xy;
float4 hairBlendingMap = SAMPLE_TEXTURE2D(_HairBlendingTex, s_trilinear_clamp_sampler, screenUV);
outColor.rgb = lerp(outColor.rgb, hairBlendingMap.rgb, hairBlendingMap.a * _HairBlendingFactor);
#endif
#if defined(UTS_DEBUG_SHADOWMAP) || defined(UTS_DEBUG_SELFSHADOW)
#if UTS_DEBUG_SHADOWMAP || UTS_DEBUG_SELFSHADOW
outColor.rgb = 1;
#ifdef UTS_DEBUG_SELFSHADOW
outColor.rgb = min(finalColor, outColor.rgb);

View File

@@ -30,6 +30,9 @@ SAMPLER(sampler_DiffuseLightingMap);
TEXTURE2D(_BaseColorMap);
SAMPLER(sampler_BaseColorMap);
TEXTURE2D(_HairBlendingMap);
SAMPLER(sampler_HairBlendingMap);
TEXTURE2D(_MaskMap);
SAMPLER(sampler_MaskMap);
TEXTURE2D(_BentNormalMap); // Reuse sampler from normal map
@@ -81,7 +84,7 @@ TEXTURE2D(_SDFShadowTex);
SAMPLER(sampler_SDFShadowTex);
TEXTURE2D(_HairShadowTex);
//SAMPLER(sampler_HairShadowTex); //registered number of this sampler is more than 16, so we can't use this sampler, use s_trilinear_clamp_sampler instead
TEXTURE2D(_HairBlendingTex);
#else
@@ -350,4 +353,6 @@ float _HairShadowDistance;
float _HairShadowDistanceScaleFactor;
float _HairShadowDepthBias;
float _HairShadowFadeInDistance;
float _HairShadowFadeOutDistance;
float _HairShadowFadeOutDistance;
float4 _HairBlendingRTHandleScale;

View File

@@ -23,7 +23,7 @@ float _SDFNoseHighlightCoef;
float _SDFNoseHighlightSmoothRange;
float _EyeParallaxAmount;
float _EyeBrowBlendingFactor;
float _HairBlendingFactor;
float _BaseColor_Step;
float _BaseShade_Feather;