vault backup: 2025-02-06 21:31:49
This commit is contained in:
parent
c21c070784
commit
8e9daf7717
@ -311,111 +311,167 @@ else
|
|||||||
```
|
```
|
||||||
|
|
||||||
```c++
|
```c++
|
||||||
|
|
||||||
FDirectLighting ToonBxDF(FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow)
|
FDirectLighting ToonBxDF(FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, float NoL, FAreaLight AreaLight, FShadowTerms Shadow)
|
||||||
{
|
{
|
||||||
FMooaToonContext Context = GBuffer.MooaToonContext;
|
FMooaToonContext MooaToonContext = GBuffer.MooaToonContext;
|
||||||
FMooaToonData MooaToonData = GBuffer.MooaToonContext.MooaToonData;
|
FToonGBufferData ToonGBuffer = GBuffer.MooaToonContext.ToonGBuffer;
|
||||||
FDirectLighting Lighting = (FDirectLighting)0;
|
FDirectLighting Lighting = (FDirectLighting)0;
|
||||||
Context.LightColor *= PI_INV; // default(EV100=0) light intensity == PI
|
float3 LightColorAndAttenuation = AreaLight.FalloffColor * MooaToonContext.LightColor * Falloff;
|
||||||
float3 LightColorAndAttenuation = AreaLight.FalloffColor * Context.LightColor * Falloff;
|
ColorSaturationPowerAndScale(LightColorAndAttenuation, View.MooaLightSaturationScale);
|
||||||
|
|
||||||
/* Tips:
|
/* Tips:
|
||||||
* SvPosition == PixelPos (0 ~ View.BufferSizeAndInvSize.xy) * SceneTextureUV == BufferUV == ScreenUV (0 ~ 1), used to GetScreenSpaceData() / GetGBufferData() * * ScreenPosition = ClipPosition.xy / ClipPosition.w
|
* SvPosition == PixelPos (0 ~ View.BufferSizeAndInvSize.xy)
|
||||||
* ViewportUV = ScreenPosition * float2(0.5, -0.5) + 0.5 * ViewportUV is the visible part of Buffer's UV (0 ~ 1) */ const float SpecularIntensity = Pow2(GBuffer.Specular * 2);
|
* SceneTextureUV == BufferUV == ScreenUV (0 ~ 1), used to GetScreenSpaceData() / GetGBufferData()
|
||||||
const float3 H = normalize(V + L);
|
*
|
||||||
const float NoH = saturate(dot(N, H));
|
* ScreenPosition = ClipPosition.xy / ClipPosition.w
|
||||||
const float halfNoL = dot(N, L) * 0.5f + 0.5f;
|
* ViewportUV = ScreenPosition * float2(0.5, -0.5) + 0.5
|
||||||
const float2 BufferUV = SvPositionToBufferUV(float4(Context.PixelPos, 0, 0));
|
* ViewportUV is the visible part of Buffer's UV (0 ~ 1)
|
||||||
const float3 L_ClipSpace = mul(L, (float3x3)View.TranslatedWorldToClip).xyz;
|
*/
|
||||||
const float2 L_ViewportSpace = normalize(L_ClipSpace.xy * float2(0.5, -0.5));
|
const float NoL_Full = dot(N, L);
|
||||||
const float3 N_ClipSpace = mul(N, (float3x3)View.TranslatedWorldToClip).xyz;
|
const float NoL_Half = NoL_Full * 0.5f + 0.5f;
|
||||||
const float2 N_ViewportSpace = normalize(N_ClipSpace.xy * float2(0.5, -0.5));
|
const float3 H = normalize(V + L);
|
||||||
const float WorldUnitLengthInBufferSizePixels = ComputeWorldUnitLengthInBufferSizePixels(GBuffer.Depth);
|
const float2 BufferUV = SvPositionToBufferUV(float4(MooaToonContext.PixelPos, 0, 0));
|
||||||
|
const float2 ViewportUV = BufferUVToViewportUV(BufferUV);
|
||||||
|
const float3 L_ClipSpace = mul(L, (float3x3)View.TranslatedWorldToClip).xyz;
|
||||||
|
const float2 L_ViewportSpace = (L_ClipSpace.xy * float2(0.5, -0.5));
|
||||||
|
const float3 N_ClipSpace = mul(N, (float3x3)View.TranslatedWorldToClip).xyz;
|
||||||
|
const float2 N_ViewportSpace = (N_ClipSpace.xy * float2(0.5, -0.5));
|
||||||
|
const float ViewportSpaceToWorldSpaceDir = rcp(GBuffer.Depth);
|
||||||
|
|
||||||
|
|
||||||
// Diffuse
|
// Diffuse
|
||||||
BRANCH if (Context.IsMainLight)
|
{
|
||||||
{ // Screen Space Depth Test Hair Shadow
|
float HairShadowOffset = 0;
|
||||||
float HairShadowValueOffset = 0;
|
float DiffuseColorRampUVOffset = (ToonGBuffer.DiffuseColorRampUVOffset * 2.0f - 1.0f) * View.MooaDiffuseColorRampUVOffsetMaxRange;
|
||||||
BRANCH if(MooaToonData.RayTracingShadowFlag == MOOA_RAY_TRACING_SHADOW_FLAG_FACE_SCREEN_SPACE_HAIR_SHADOW &&
|
float ShadowGradient = saturate(NoL_Half + DiffuseColorRampUVOffset);
|
||||||
MooaToonData.HairShadowWidth > 0 && MooaToonData.HairShadowIntensity > 0)
|
|
||||||
{ float2 UVOffset = L_ViewportSpace * WorldUnitLengthInBufferSizePixels * Pow2(MooaToonData.HairShadowWidth) * View.MooaHairShadowMaxScreenSpaceDistance;
|
|
||||||
FGBufferData HairGbuffer = GetGBufferData(BufferUV + UVOffset);
|
|
||||||
float DepthFade = 1 - saturate(max(0, HairGbuffer.Depth - GBuffer.Depth - View.MooaHairShadowDepthTestThreshold) / max(1e-5, View.MooaHairShadowDepthFadeDistance));
|
|
||||||
|
|
||||||
if (HairGbuffer.ShadingModelID == SHADINGMODELID_TOON &&
|
#if SHADING_PATH_DEFERRED && defined(MOOA_TOON_DEFERRED_LIGHTING) && !SUBSTRATE_ENABLED
|
||||||
HairGbuffer.MooaToonContext.MooaToonData.RayTracingShadowFlag == MOOA_RAY_TRACING_SHADOW_FLAG_HAIR)
|
{
|
||||||
{ HairShadowValueOffset = -1 * MooaToonData.HairShadowIntensity * DepthFade;
|
// Screen Space Depth Test Hair Shadow
|
||||||
} }
|
const float HairShadowWidth = 2.0f * View.MooaHairShadowWidth;
|
||||||
Shadow.SurfaceShadow = saturate(Shadow.SurfaceShadow + HairShadowValueOffset + MooaToonData.MainLightShadowValueOffset * 2.0f - 1.0f);
|
const float HairShadowIntensity = View.MooaHairShadowIntensity;
|
||||||
LightColorAndAttenuation *= Shadow.SurfaceShadow;
|
BRANCH if(ToonGBuffer.RayTracingShadowFlag == MOOA_RAY_TRACING_SHADOW_FLAG_FACE_SCREEN_SPACE_HAIR_SHADOW &&
|
||||||
Lighting.Diffuse = lerp(MooaToonData.MainLightShadowColor * lerp(1, Context.LightColor, MooaToonData.MainLightShadowApplyLightColor) * View.MooaIsGlobalIlluminationEnabled,
|
HairShadowWidth > 0 && HairShadowIntensity > 0)
|
||||||
GBuffer.DiffuseColor * Context.LightColor, Shadow.SurfaceShadow);
|
{
|
||||||
} else
|
float2 ViewportUVOffset = L_ViewportSpace * ViewportSpaceToWorldSpaceDir * HairShadowWidth;
|
||||||
{
|
float2 TargetBufferUV = ViewportUVToBufferUV(saturate(ViewportUV + ViewportUVOffset));
|
||||||
float OtherLightShadowValue = ToonStep(halfNoL, MooaToonData.OtherLightDiffuseFeather, MooaToonData.OtherLightDiffuseThreshold);
|
FGBufferData HairGbuffer = GetGBufferData(TargetBufferUV);
|
||||||
// Non-Directional light's SurfaceShadow contains distance attenuation, not just shadowmap
|
float DepthFade = saturate(max(0, GBuffer.Depth - HairGbuffer.Depth - View.MooaHairShadowDepthTestThreshold) / max(1e-5, View.MooaHairShadowDepthTestFadeDistance));
|
||||||
Shadow.SurfaceShadow *= OtherLightShadowValue;
|
|
||||||
LightColorAndAttenuation *= Shadow.SurfaceShadow;
|
if (HairGbuffer.ShadingModelID == SHADINGMODELID_TOON &&
|
||||||
Lighting.Diffuse = GBuffer.DiffuseColor * LightColorAndAttenuation;
|
HairGbuffer.MooaToonContext.ToonGBuffer.RayTracingShadowFlag == MOOA_RAY_TRACING_SHADOW_FLAG_HAIR)
|
||||||
}
|
{
|
||||||
// Anisotropy Context
|
HairShadowOffset = -1 * HairShadowIntensity * DepthFade;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
GetDistanceFieldFacialShadow(GBuffer, ToonGBuffer, L, DiffuseColorRampUVOffset,
|
||||||
|
ShadowGradient);
|
||||||
|
|
||||||
|
float DiffuseColorRampU = min3(saturate(Shadow.SurfaceShadow + HairShadowOffset), GBuffer.GBufferAO, ShadowGradient);
|
||||||
|
half4 DiffuseColorRamp = SampleGlobalRamp(View.MooaGlobalDiffuseColorRampAtlas, DiffuseColorRampU, ToonGBuffer.DiffuseColorRampIndex, View.MooaGlobalDiffuseColorRampAtlasHeight);
|
||||||
|
Shadow.SurfaceShadow = DiffuseColorRampU;
|
||||||
|
|
||||||
|
half3 ToonDiffuseColor = GBuffer.DiffuseColor;
|
||||||
|
half3 ToonShadowColor = ToonGBuffer.MainLightShadowColor * (1 - GBuffer.Metallic) * GetShadowColorIntensity(MooaToonContext);
|
||||||
|
#if USE_DEVELOPMENT_SHADERS
|
||||||
|
ToonShadowColor *= View.DiffuseOverrideParameter.w + View.DiffuseOverrideParameter.xyz;
|
||||||
|
#endif
|
||||||
|
ToonDiffuseColor = lerp(ToonShadowColor, ToonDiffuseColor, DiffuseColorRamp.a);
|
||||||
|
|
||||||
|
Lighting.Diffuse = Diffuse_Lambert(ToonDiffuseColor) * DiffuseColorRamp.rgb * LightColorAndAttenuation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Anisotropy Specular BxDF Context
|
||||||
|
bool bHasAnisotropy;
|
||||||
|
BxDFContext Context = (BxDFContext)0;
|
||||||
|
{
|
||||||
|
#if SUPPORTS_ANISOTROPIC_MATERIALS
|
||||||
|
bHasAnisotropy = true;// HasAnisotropy(GBuffer.SelectiveOutputMask);
|
||||||
|
#else
|
||||||
|
bHasAnisotropy = false;
|
||||||
|
#endif
|
||||||
|
if (ToonGBuffer.ShadingFeatureID == MOOA_SHADING_FEATURE_ID_DISTANCE_FIELD_FACIAL_SHADOW)
|
||||||
|
bHasAnisotropy = false;
|
||||||
|
|
||||||
|
BRANCH if (bHasAnisotropy)
|
||||||
|
{
|
||||||
|
half3 X = GBuffer.WorldTangent;
|
||||||
|
half3 Y = normalize(cross(N, X));
|
||||||
|
Init(Context, N, X, Y, V, L);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Init(Context, N, V, L);
|
||||||
|
GBuffer.Anisotropy = 0;
|
||||||
|
}
|
||||||
|
Context.NoV = saturate(abs( Context.NoV ) + 1e-5);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Specular
|
||||||
|
BRANCH if (ToonGBuffer.ShadingFeatureID == MOOA_SHADING_FEATURE_ID_PBR_SPECULAR)
|
||||||
|
{
|
||||||
#if SUPPORTS_ANISOTROPIC_MATERIALS
|
#if SUPPORTS_ANISOTROPIC_MATERIALS
|
||||||
bool bHasAnisotropy = HasAnisotropy(GBuffer.SelectiveOutputMask);
|
BRANCH if (bHasAnisotropy)
|
||||||
#else
|
{
|
||||||
bool bHasAnisotropy = false;
|
Lighting.Specular = LightColorAndAttenuation * Shadow.SurfaceShadow * NoL * SpecularGGX(GBuffer.Roughness, GBuffer.Anisotropy, GBuffer.SpecularColor, Context, NoL, AreaLight);
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
BxDFContext AnisotropyContext = (BxDFContext)0;
|
{
|
||||||
{ half3 X = GBuffer.WorldTangent;
|
BRANCH if( IsRectLight(AreaLight) )
|
||||||
half3 Y = normalize(cross(N, X));
|
{
|
||||||
Init(AnisotropyContext, N, X, Y, V, L);
|
Lighting.Specular = MooaToonContext.LightColor * Shadow.SurfaceShadow * RectGGXApproxLTC(GBuffer.Roughness, GBuffer.SpecularColor, N, V, AreaLight.Rect, AreaLight.Texture);
|
||||||
AnisotropyContext.NoV = saturate(abs( AnisotropyContext.NoV ) + 1e-5);
|
}
|
||||||
if (!bHasAnisotropy) GBuffer.Anisotropy = 0;
|
else
|
||||||
}
|
{
|
||||||
// Specular
|
Lighting.Specular = LightColorAndAttenuation * Shadow.SurfaceShadow * NoL * SpecularGGX(GBuffer.Roughness, GBuffer.SpecularColor, Context, NoL, AreaLight);
|
||||||
BRANCH if (MooaToonData.IsPBRSpecular)
|
}
|
||||||
{ Lighting.Specular = LightColorAndAttenuation * NoL *
|
}
|
||||||
max(0, SpecularGGX(GBuffer.Roughness, GBuffer.Anisotropy, GBuffer.SpecularColor, AnisotropyContext, NoL, AreaLight));
|
}
|
||||||
} else
|
else
|
||||||
{
|
{
|
||||||
// Anisotropy
|
float MaxSpecularValue;
|
||||||
float2 XY = normalize(float2(1.0f + GBuffer.Anisotropy, 1.0f - GBuffer.Anisotropy));
|
float SpecularColorRampU = GetSpecularColorRampUAndMaxSpecularValue(GBuffer, Context, N, H,
|
||||||
float AnisotropyGradient = length(float2(XY.y * AnisotropyContext.XoH, XY.x * AnisotropyContext.YoH));
|
MaxSpecularValue);
|
||||||
// Toon Specular: https://www.desmos.com/calculator/qecziyizl1
|
float SpecularColorRampUVOffset = (ToonGBuffer.SpecularColorRampUVOffset * 2.0f - 1.0f) * View.MooaSpecularColorRampUVOffsetMaxRange;
|
||||||
float SpecularGradient = 1.0f - AnisotropyGradient;
|
half3 SpecularColor = SampleGlobalRamp(View.MooaGlobalSpecularColorRampAtlas, SpecularColorRampU + SpecularColorRampUVOffset, ToonGBuffer.SpecularColorRampIndex, View.MooaGlobalSpecularColorRampAtlasHeight).rgb;
|
||||||
float SpecularThreshold = 1.0f - Pow2(MooaToonData.SpecularThreshold);
|
|
||||||
float SpecularFeather = Pow2(MooaToonData.SpecularFeather) * SpecularThreshold * 0.5f;
|
|
||||||
|
|
||||||
Lighting.Specular = saturate(ToonStep(SpecularGradient, SpecularFeather, SpecularThreshold + SpecularFeather, 1.0f, false, false))
|
Lighting.Specular = GBuffer.SpecularColor * ToonGBuffer.SpecularColor * MaxSpecularValue * SpecularColor * LightColorAndAttenuation * Shadow.SurfaceShadow;
|
||||||
* MooaToonData.SpecularColor * SpecularIntensity * LightColorAndAttenuation;
|
}
|
||||||
}
|
|
||||||
// Screen Space Depth Test Rim Light
|
|
||||||
// Recompute Normals to override DCC Normals on Face/Hair const float3 WorldNormalFromDepth = normalize(ReconstructNormalFromDepthBuffer_Copy(Context.PixelPos));
|
|
||||||
const float3 DepthToN_ClipSpace = mul(WorldNormalFromDepth, (float3x3)View.TranslatedWorldToClip).xyz;
|
|
||||||
const float2 DepthToN_ViewportSpace = DepthToN_ClipSpace.xy * float2(0.5, -0.5);
|
|
||||||
BRANCH if (MooaToonData.RimLightIntensity > 0 && MooaToonData.RimLightWidth > 0)
|
|
||||||
{ float NoL_ClipSpaceAngle01 = (dot(normalize(DepthToN_ClipSpace.xy), normalize(L_ClipSpace.xy)) * 0.5 + 0.5);
|
|
||||||
float WidthScaleByAngle = saturate(lerp(NoL_ClipSpaceAngle01, 1, MooaToonData.RimLightAngle));
|
|
||||||
const float MaxRimLightWidth = 0.0003 * View.MooaRimLightMaxWidth;
|
|
||||||
const float MaxDepthTestDistance = 100 * View.MooaRimLightMaxDepthTestDistance;
|
|
||||||
const float MaxDepthFadeDistance = 100 * View.MooaRimLightMaxDepthFadeDistance;
|
|
||||||
|
|
||||||
// TODO: AA
|
// Rimlight
|
||||||
float SubPixelFade = 1;
|
float3 RimLight = GetScreenSpaceDepthTestRimlightColor(GBuffer, ToonGBuffer, ViewportUV, L_ViewportSpace, ViewportSpaceToWorldSpaceDir) * LightColorAndAttenuation * Shadow.SurfaceShadow;
|
||||||
float2 UVOffset = L_ViewportSpace * WorldUnitLengthInBufferSizePixels * MaxRimLightWidth * WidthScaleByAngle * Pow2(MooaToonData.RimLightWidth);
|
ColorSaturationPowerAndScale(RimLight, View.MooaRimLightSaturationScale, View.MooaRimLightIntensity);
|
||||||
float2 TargetBufferUV = BufferUV + UVOffset;
|
Lighting.Specular += RimLight;
|
||||||
|
|
||||||
#if MATERIALBLENDING_TRANSLUCENT || MATERIALBLENDING_ADDITIVE || MATERIALBLENDING_MODULATE
|
return Lighting;
|
||||||
// TranslucentBasePass.SceneDepth include Translucent First Layer Depth
|
}
|
||||||
// see UseFrontLayerReflection() float SingleLayerDeviceZ = Texture2DSampleLevel( TranslucentBasePass.SceneDepth, GlobalPointClampedSampler, TargetBufferUV, 0).r;
|
|
||||||
float NewDepth = ConvertFromDeviceZ(SingleLayerDeviceZ);
|
```
|
||||||
#else
|
|
||||||
float NewDepth = GetGBufferData(TargetBufferUV).Depth;
|
# 实用函数
|
||||||
#endif
|
如果需要脸部SDF阴影,就覆盖ShadowGradient。
|
||||||
float DepthFade = saturate(max(0, NewDepth - GBuffer.Depth - MaxDepthTestDistance * Pow2(MooaToonData.RimLightDepthThreshold))
|
```c++
|
||||||
/ max(1e-5, MaxDepthFadeDistance * Pow2(MooaToonData.RimLightDepthThreshold)));
|
void GetDistanceFieldFacialShadow(FGBufferData GBuffer, FToonGBufferData ToonGBuffer, float3 L, float DiffuseColorRampUVOffset,
|
||||||
Lighting.Specular = max(Lighting.Specular, DepthFade * MooaToonData.RimLightIntensity * LightColorAndAttenuation);
|
inout float ShadowGradient)
|
||||||
}
|
{
|
||||||
return Lighting;
|
BRANCH if (ToonGBuffer.ShadingFeatureID == MOOA_SHADING_FEATURE_ID_DISTANCE_FIELD_FACIAL_SHADOW)
|
||||||
|
{
|
||||||
|
float3 FaceForwardDir = GBuffer.WorldTangent;
|
||||||
|
float LightAngle = RadianToDegree(FastACos(dot(FaceForwardDir, L)));
|
||||||
|
float RampUVOffsetByLightAngle = (1.0 - clamp(LightAngle / 180.0f, 1e-4, 1 - 1e-4)) - 0.5f;
|
||||||
|
bool bLightAtRight = cross(FaceForwardDir, L).z >= 0; // TODO: Fix the numerical accuracy issue of extreme angles
|
||||||
|
float shadowSdf = bLightAtRight ? ToonGBuffer.FacialShadowSdfRight : ToonGBuffer.FacialShadowSdfLeft;
|
||||||
|
|
||||||
|
ShadowGradient = saturate(RampUVOffsetByLightAngle + shadowSdf + DiffuseColorRampUVOffset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user