Added hair blending support.

This commit is contained in:
2025-05-06 23:39:49 +09:00
parent 10331b93ff
commit 961db806e9
12 changed files with 161 additions and 115 deletions

View File

@@ -45,21 +45,21 @@ DirectLighting UtsEvaluateBSDF_Directional(LightLoopContext lightLoopContext, Po
{
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 L = -lightData.forward;
SHADOW_TYPE shadow = 1.0;
#if _RECEIVE_LIGHT_SHADOW_ON
shadow = EvaluateShadow_Directional(lightLoopContext, posInput, lightData, builtinData, bsdfData.geomNormalWS);
#endif
if (lightData.lightDimmer > 0.0)
{
// TODO: Colored shadow will overwrite the first and second shading diffuse color
//float3 shadowColor = ComputeShadowColor(shadow, lightData.shadowTint, lightData.penumbraTint);
float4 lightColor = EvaluateLight_Directional(lightLoopContext, posInput, lightData);
lightColor.rgb = GetLimitedLightColor(lightColor.rgb * lightColor.a * _LightIntensityMultiplier);
UtsClampRoughness(preLightData, bsdfData, lightData.minRoughness);
lighting = UtsShadeSurface(posInput, bsdfData, preLightData, shadow, lightColor.rgb, V, L, uv0, lightData.diffuseDimmer, lightData.specularDimmer);
@@ -72,28 +72,28 @@ DirectLighting UtsEvaluateBSDF_Punctual(LightLoopContext lightLoopContext, Posit
{
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 L;
float4 distances; // {d, d^2, 1/d, d_proj}
GetPunctualLightVectors(posInput.positionWS, lightData, L, distances);
SHADOW_TYPE shadow = 1.0;
#if _RECEIVE_LIGHT_SHADOW_ON
shadow = UtsEvaluateShadow_Punctual(lightLoopContext, posInput, lightData, builtinData, UtsGetShadowNormal(bsdfData), L, distances);
#endif
if (lightData.lightDimmer > 0.0)
{
// TODO: Colored shadow will overwrite the first and second shading diffuse color
//float3 shadowColor = ComputeShadowColor(shadow, lightData.shadowTint, lightData.penumbraTint);
float4 lightColor = EvaluateLight_Punctual(lightLoopContext, posInput, lightData, L, distances);
lightColor.rgb = GetLimitedLightColor(lightColor.rgb * lightColor.a * _LightIntensityMultiplier);
UtsClampRoughness(preLightData, bsdfData, lightData.minRoughness);
lighting = UtsShadeSurface(posInput, bsdfData, preLightData, shadow, lightColor.rgb, V, L, uv0, lightData.diffuseDimmer, lightData.specularDimmer);
}
return lighting;
}
@@ -124,17 +124,17 @@ void UtsEvaluateBSDF_BakeDiffuse(PositionInputs posInput, PreLightData preLightD
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
lightInReflDir = float3(-1, -1, -1); // This variable is used with APV for reflection probe normalization - see code for LIGHTFEATUREFLAGS_ENV
#endif
#if defined(_PBR_MODE_OFF) || defined(_PBR_MODE_TOON)
float3 normalWS = float3(0.0, 0.0, 1.0);
#else
float3 normalWS = bsdfData.normalWS;
#endif
float3 backNormalWS = -normalWS;
// Reflect normal to get lighting for reflection probe tinting
float3 R = reflect(-V, normalWS);
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
if (_EnableProbeVolumes)
{
@@ -150,7 +150,7 @@ void UtsEvaluateBSDF_BakeDiffuse(PositionInputs posInput, PreLightData preLightD
builtinData.backBakeDiffuseLighting = EvaluateAmbientProbe(backNormalWS);
}
#endif
#if !defined(_SURFACE_TYPE_TRANSPARENT) && !defined(SCREEN_SPACE_INDIRECT_DIFFUSE_DISABLED)
if (_IndirectDiffuseMode != INDIRECTDIFFUSEMODE_OFF)
{
@@ -178,7 +178,7 @@ IndirectLighting UtsEvaluateBSDF_MatCapSpecular(float3 positionWS, UtsBSDFData b
{
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
float3 positionVS = mul(UNITY_MATRIX_V, float4(positionWS, 1.0)).xyz;
float3 normalVS = mul(UNITY_MATRIX_V, float4(bsdfData.normalWS, 1.0)).xyz;
float3 pcrossN = cross(normalize(positionVS), normalVS);
@@ -190,7 +190,7 @@ IndirectLighting UtsEvaluateBSDF_MatCapSpecular(float3 positionWS, UtsBSDFData b
float lod = clamp(PerceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness) + _IndirectSpecularMatCapLod, 0.0, 10.0);
lighting.specularReflected = SAMPLE_TEXTURE2D_LOD(_IndirectSpecularMatCapMap, s_trilinear_clamp_sampler, uv, lod).rgb;
lighting.specularReflected *= preLightData.specularFGD * GetInverseCurrentExposureMultiplier();
return lighting;
}
@@ -204,7 +204,7 @@ IndirectLighting UtsEvaluateBSDF_Env(LightLoopContext lightLoopContext, Position
{
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
float3 envLighting;
float3 positionWS = posInput.positionWS;
float weight = 1.0;
@@ -268,13 +268,13 @@ void UtsPostEvaluateBSDF(PositionInputs posInput, PreLightData preLightData, Uts
ApplyAmbientOcclusion(aoFactor, builtinData, lighting);
#endif
AdjustIndirectLighting(preLightData, bsdfData, builtinData, lighting);
// In regular pbr, we need to multiple diffuse color here with direct diffuse lighting. However, in UTS, we have already multiplied it when evaluating the direct diffuse since we need to apply the shading color.
lightLoopOutput.diffuseLighting = lighting.direct.diffuse + builtinData.bakeDiffuseLighting + builtinData.emissiveColor;
lightLoopOutput.specularLighting = lighting.direct.specular + lighting.indirect.specularReflected;
// Rescale the GGX to account for the multiple scattering.
lightLoopOutput.specularLighting *= 1.0 + bsdfData.fresnel0 * preLightData.energyCompensation;
ApplyExposureAdjustment(lightLoopOutput.diffuseLighting);
ApplyExposureAdjustment(lightLoopOutput.specularLighting);
}

View File

@@ -30,27 +30,28 @@ float3 SampleSDFTexture(float3 L, float2 uv, out float angle)
float GetHairShadow(PositionInputs posInput, float3 L)
{
float shadow = 1.0;
// 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)));
if (hairShadowOpacity > 0.0)
{
float3 viewLightDir = TransformWorldToViewDir(L);
float shadowLengthY = _HairShadowDistance * 5.0 * max(0.5, posInput.linearDepth * _HairShadowDistanceScaleFactor) / posInput.linearDepth;
float2 shadowLength = float2(shadowLengthY * 2.0f, shadowLengthY);
float3 cameraDirOS = normalize(TransformWorldToObject(GetCameraPositionWS()));
float cameraDirFactor = 1 - smoothstep(0.1, 0.9, cameraDirOS.y);
shadowLength.y *= cameraDirFactor;
// TODO: sample point is still shifting when fov change.
float2 samplingPoint = (posInput.positionSS + 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.
float2 scaledUVs = samplingPoint * _HairShadowRTHandleScale.xy; // We have to including the scaling factor for our shadow map since we are not going to allocate new texture if the rendering resolution changed.
float2 scaledUVs = samplingPoint * _RTHandleScale.xy; // We have to including the scaling factor for our shadow map since we are not going to allocate new texture if the rendering resolution changed.
float hairShadow = SAMPLE_TEXTURE2D_SHADOW(_HairShadowTex, s_linear_clamp_compare_sampler, float3(scaledUVs, posInput.deviceDepth + _HairShadowDepthBias)).r;
shadow = lerp(1.0 - hairShadowOpacity, 1.0, hairShadow);
}
return shadow;
}
@@ -118,4 +119,4 @@ SHADOW_TYPE UtsEvaluateShadow_Punctual(LightLoopContext lightLoopContext, Positi
#endif
}
#endif
#endif