Fixed the engergy conservation problem when pbr mode is toon.

This commit is contained in:
2025-05-13 21:35:52 +09:00
parent 961db806e9
commit d19322b768
11 changed files with 72 additions and 53 deletions

View File

@@ -25,12 +25,12 @@
struct UTSSurfaceData
{
uint surfaceFeatures;
real3 baseColor;
real3 firstShadingColor;
real3 secondShadingColor;
real alpha;
float3 normalWS;
real perceptualSmoothness;
real metallic;
@@ -40,35 +40,35 @@ struct UTSSurfaceData
float3 geomNormalWS;
float3 tangentWS;
real4 subsurfaceColor;
real anisotropy;
};
struct UtsBSDFData
{
uint surfaceFeatures;
real3 diffuseColor;
real3 firstShadingDiffuseColor;
real3 secondShadingDiffuseColor;
real3 fresnel0;
real fresnel90;
real reflectivity;
real ambientOcclusion;
real specularOcclusion;
real perceptualRoughness;
real3 subsurfaceColor;
float3 geomNormalWS;
float3 normalWS;
float3 tangentWS;
float3 bitangentWS;
real anisotropy;
real roughnessT;
real roughnessB;
@@ -103,7 +103,7 @@ UTSSurfaceData GetUTSSurfaceData(FragInputs input, float3 V)
UTSSurfaceData output;
output.surfaceFeatures = _SurfaceFeatures;
float4 mainTexture = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, TRANSFORM_TEX(input.texCoord0, _BaseColorMap));
output.baseColor = mainTexture.rgb * _BaseColor.rgb;
output.alpha = mainTexture.a;
@@ -173,20 +173,22 @@ UTSSurfaceData GetUTSSurfaceData(FragInputs input, float3 V)
smoothness *=_BSDFContribution;
#endif
#ifdef _PBR_Mode_TOON
// TODO: Specular color is not handle correctly.
#ifdef _PBR_MODE_TOON
metallic = 0.0;
specularColor = _SpecularColor;
#ifdef _SPECULARCOLORMAP
specularColor = SAMPLE_TEXTURE2D(_SpecularColorMap, sampler_SpecularColorMap, TRANSFORM_TEX(input.texCoord0, _BaseColorMap)).rgb * _SpecularColor;
specularColor *= SAMPLE_TEXTURE2D(_SpecularColorMap, sampler_SpecularColorMap, TRANSFORM_TEX(input.texCoord0, _BaseColorMap)).rgb;
#endif
specularColor = GetSpecularColor(output.baseColor, metallic);
#endif
output.metallic = metallic;
output.ambientOcclusion = ao;
output.specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(dot(normalWS, V), ao, PerceptualRoughnessToRoughness(1 - smoothness));
output.perceptualSmoothness = smoothness;
output.normalWS = normalWS;
output.specularColor = specularColor;
output.geomNormalWS = input.tangentToWorld[2];
output.tangentWS = Orthonormalize(input.tangentToWorld[0].rgb, normalWS);
@@ -194,7 +196,7 @@ UTSSurfaceData GetUTSSurfaceData(FragInputs input, float3 V)
output.subsurfaceColor = 0.0;
output.anisotropy = anisotropy;
return output;
}
@@ -203,13 +205,20 @@ UtsBSDFData ConvertUTSSurfaceDataToUTSBSDFData(UTSSurfaceData surfaceData)
UtsBSDFData output;
output.surfaceFeatures = surfaceData.surfaceFeatures;
output.diffuseColor = UtsComputeDiffuseColor(surfaceData.baseColor, surfaceData.metallic, 0.05);
output.firstShadingDiffuseColor = UtsComputeDiffuseColor(surfaceData.firstShadingColor, surfaceData.metallic, 0.05);
output.secondShadingDiffuseColor = UtsComputeDiffuseColor(surfaceData.secondShadingColor, surfaceData.metallic, 0.05);
#if _PBR_MODE_TOON
float m = Max3(surfaceData.specularColor.r, surfaceData.specularColor.g, surfaceData.specularColor.b);
#else
float m = surfaceData.metallic;
#endif
output.diffuseColor = UtsComputeDiffuseColor(surfaceData.baseColor, m, _Minimal_Diffuse_Contribution);
output.firstShadingDiffuseColor = UtsComputeDiffuseColor(surfaceData.firstShadingColor, m, _Minimal_Diffuse_Contribution);
output.secondShadingDiffuseColor = UtsComputeDiffuseColor(surfaceData.secondShadingColor, m, _Minimal_Diffuse_Contribution);
#if _PBR_MODE_OFF
output.fresnel0 = surfaceData.baseColor;
output.fresnel0 = 0.22;
#elif _PBR_MODE_TOON
output.fresnel0 = surfaceData.specularColor;
#else
output.fresnel0 = ComputeFresnel0(surfaceData.baseColor, surfaceData.metallic, 0.22);
#endif
@@ -229,7 +238,7 @@ UtsBSDFData ConvertUTSSurfaceDataToUTSBSDFData(UTSSurfaceData surfaceData)
output.anisotropy = surfaceData.anisotropy;
ConvertAnisotropyToRoughness(output.perceptualRoughness, surfaceData.anisotropy, output.roughnessT, output.roughnessB);
return output;
}
@@ -243,7 +252,7 @@ PreLightData GetPreLightData_UTS(float3 V, PositionInputs posInput, inout UtsBSD
preLightData.iblPerceptualRoughness = bsdfData.perceptualRoughness;
float clampedNdotV = ClampNdotV(preLightData.NdotV);
// Handle IBL + area light + multiscattering.
// Note: use the not modified by anisotropy iblPerceptualRoughness here.
float specularReflectivity = 1.0;

View File

@@ -66,7 +66,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
// Initialize the contactShadow and contactShadowFade fields
InitContactShadow(posInput, context);
#if _RECEIVE_LIGHT_SHADOW_ON
// First of all we compute the shadow value of the directional light to reduce the VGPR pressure
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
@@ -97,12 +97,12 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
}
}
#endif
PreLightData preLightData = GetPreLightData_UTS(V, posInput, bsdfData);
AggregateLighting aggregateLighting;
ZERO_INITIALIZE(AggregateLighting, aggregateLighting);
// Evaluate the punctual lights.
if (featureFlags & LIGHTFEATUREFLAGS_PUNCTUAL)
{
@@ -172,7 +172,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
}
}
}
// Evaluate the directional lights.
if (featureFlags & LIGHTFEATUREFLAGS_DIRECTIONAL)
{
@@ -232,7 +232,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
replaceBakeDiffuseLighting = true;
}
#endif
#if defined(PROBE_VOLUMES_L1) || defined(PROBE_VOLUMES_L2)
if (!builtinData.isLightmap)
{
@@ -243,7 +243,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
#if defined(LIGHT_EVALUATION_SKIP_INDIRECT_DIFFUSE)
replaceBakeDiffuseLighting = false;
#endif
if (replaceBakeDiffuseLighting)
{
UtsEvaluateBSDF_BakeDiffuse(posInput, preLightData, bsdfData, V, builtinData, lightInReflDir);
@@ -257,7 +257,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
if (featureFlags & LIGHTFEATUREFLAGS_ENV)
{
#if _INDIRECT_SPECULAR_MODE_OFF
#elif _INDIRECT_SPECULAR_MODE_IBL
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
@@ -317,7 +317,6 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
AccumulateIndirectLighting(lighting, aggregateLighting);
}
}
}
}
#elif _INDIRECT_SPECULAR_MODE_MATCAP
@@ -345,7 +344,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
}
#endif
}
#ifndef _LIGHT_BASE_RIM_LIGHT_ON
if (HasFlag(bsdfData.surfaceFeatures, SURFACEFEATURE_RIM_LIGHT))
{
@@ -353,7 +352,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
AccumulateDirectLighting(lighting, aggregateLighting);
}
#endif
if (HasFlag(bsdfData.surfaceFeatures, SURFACEFEATURE_ANGEL_RING))
{
DirectLighting lighting = UtsEvaluateLighting_AngelRing(fragInputs, bsdfData.normalWS, V);
@@ -368,7 +367,7 @@ void UtsLightLoop(FragInputs fragInputs, PositionInputs posInput, UtsBSDFData bs
// UTSLightData mainPunctualLight;
// uint lightCount, lightStart;
// #ifndef LIGHTLOOP_DISABLE_TILE_AND_CLUSTER
// GetCountAndStart(posInput, LIGHTCATEGORY_PUNCTUAL, lightStart, lightCount);
// #else // LIGHTLOOP_DISABLE_TILE_AND_CLUSTER

View File

@@ -39,10 +39,10 @@ float3 ComputeSpecularTerm(UtsBSDFData bsdfData, PreLightData preLightData, floa
#elif _PBR_MODE_ANISOTROPY
float TdotV = dot(bsdfData.tangentWS, V);
float BdotV = dot(bsdfData.bitangentWS, V);
ConvertAnisotropyToRoughness(bsdfData.perceptualRoughness, bsdfData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, clampedNdotV, bsdfData.roughnessT, bsdfData.roughnessB);
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float TdotL = dot(bsdfData.tangentWS, L);
@@ -63,11 +63,9 @@ float3 ComputeSpecularTerm(UtsBSDFData bsdfData, PreLightData preLightData, floa
float specularExponent = RoughnessToBlinnPhongSpecularExponent(PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness));
DV = pow(NdotH, 5.0 * specularExponent);
DV = StepFeatherToon(DV, _ToonSpecularStep, _ToonSpecularFeather);
//specTerm = pow(NdotH, 5.0 * specularExponent);
//specTerm = StepFeatherToon(specTerm, _ToonSpecularStep, _ToonSpecularFeather);
//return specTerm * ColorSpaceDielectricSpec.rgb * clampedNdotL;
#endif
// We use specularFGD here to approximate F.
specTerm = DV * preLightData.specularFGD * clampedNdotL;
return specTerm;
#endif

View File

@@ -119,6 +119,7 @@ float _HairBlendingFactor;
// Advance
half _ClampLightColor;
float _LightIntensityMultiplier;
float _Minimal_Diffuse_Contribution;
// Light Loop
float3 _ObjectCenterPositionWS;