From 32001bcf8cdb70ed7f79e9cba3625f695ce6e1ee Mon Sep 17 00:00:00 2001 From: BlueRose <378100977@qq.com> Date: Thu, 20 Jun 2024 19:05:41 +0800 Subject: [PATCH] vault backup: 2024-06-20 19:05:41 --- 02-Note/DAWA/ASoul/渲染方案/Shader修改部分.md | 403 +++++++++++++++++- 1 file changed, 397 insertions(+), 6 deletions(-) diff --git a/02-Note/DAWA/ASoul/渲染方案/Shader修改部分.md b/02-Note/DAWA/ASoul/渲染方案/Shader修改部分.md index 23c5544..81b75e2 100644 --- a/02-Note/DAWA/ASoul/渲染方案/Shader修改部分.md +++ b/02-Note/DAWA/ASoul/渲染方案/Shader修改部分.md @@ -1,3 +1,7 @@ +# TODO +- [ ] [[#BasePass]] +- [ ] [[#DeferredShadingCommon.ush]] + # Common ## Common.ush 添加结构体,主要用在材质的CustomNode里。 @@ -29,18 +33,377 @@ struct FToonShadingPerMaterialCustomData static FToonShadingPerMaterialCustomData ToonShadingPerMaterialCustomData; ``` + ## DeferredShadingCommon.ush +# BasePass +BasePassPixelShader.usf + # Lighting ## ShadingModels ### ShadingCommon.ush -1. 添加ShadingModelID宏: -- SHADINGMODELID_TOON_BASE 13 -- +**添加ShadingModelID宏**: +- SHADINGMODELID_TOON_BASE 13 +- SHADINGMODELID_TOON_PBR 14 +- SHADINGMODELID_TOON_SKIN 15 +- SHADINGMODELID_NUM 16 + +判断是否是IsToonShadingModel: +```c++ +bool IsToonShadingModel(uint ShadingModel) +{ + uint4 ToonShadingModels = uint4(SHADINGMODELID_TOON_BASE, SHADINGMODELID_TOON_PBR, SHADINGMODELID_TOON_SKIN, 0xFF); + return any(ShadingModel.xxxx == ToonShadingModels); +} +``` +## DeferredLightingCommon.ush +修改了AccumulateDynamicLighting()的逻辑。 +```c++ +FLightAccumulator AccumulateDynamicLighting( + float3 TranslatedWorldPosition, half3 CameraVector, FGBufferData GBuffer, half AmbientOcclusion, uint ShadingModelID, + FDeferredLightData LightData, half4 LightAttenuation, float Dither, uint2 SVPos, + inout float SurfaceShadow) +{ + FLightAccumulator LightAccumulator = (FLightAccumulator)0; + + half3 V = -CameraVector; + half3 N = GBuffer.WorldNormal; + BRANCH if( GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT && CLEAR_COAT_BOTTOM_NORMAL) + { + const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 4) - (512.0/255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal); + N = OctahedronToUnitVector(oct1); + } + + float3 L = LightData.Direction; // Already normalized + float3 ToLight = L; + float3 MaskedLightColor = LightData.Color; + float LightMask = 1; + if (LightData.bRadialLight) + { + LightMask = GetLocalLightAttenuation( TranslatedWorldPosition, LightData, ToLight, L ); + MaskedLightColor *= LightMask; + } + + LightAccumulator.EstimatedCost += 0.3f; // running the PixelShader at all has a cost + + BRANCH + if( LightMask > 0 ) + { + FShadowTerms Shadow; + Shadow.SurfaceShadow = AmbientOcclusion; + Shadow.TransmissionShadow = 1; + Shadow.TransmissionThickness = 1; + Shadow.HairTransmittance.OpaqueVisibility = 1; + const float ContactShadowOpacity = GBuffer.CustomData.a; + GetShadowTerms(GBuffer.Depth, GBuffer.PrecomputedShadowFactors, GBuffer.ShadingModelID, ContactShadowOpacity, + LightData, TranslatedWorldPosition, L, LightAttenuation, Dither, Shadow); + SurfaceShadow = Shadow.SurfaceShadow; + + LightAccumulator.EstimatedCost += 0.3f; // add the cost of getting the shadow terms + +#if SHADING_PATH_MOBILE + const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID); + + FDirectLighting Lighting = (FDirectLighting)0; + + half NoL = max(0, dot(GBuffer.WorldNormal, L)); + #if TRANSLUCENCY_NON_DIRECTIONAL + NoL = 1.0f; + #endif + Lighting = EvaluateBxDF(GBuffer, N, V, L, NoL, Shadow); + + Lighting.Specular *= LightData.SpecularScale; + + LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, MaskedLightColor * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation ); + LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, MaskedLightColor * Shadow.TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation ); +#else // SHADING_PATH_MOBILE + //修改了这里 + bool UseToonShadow = IsToonShadingModel(GBuffer.ShadingModelID); + BRANCH + if( Shadow.SurfaceShadow + Shadow.TransmissionShadow > 0 || UseToonShadow)//修改结束 + { + const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID); + //修改了这里 + BRANCH + if(UseToonShadow) + { + float NoL = dot(N, L); + float ToonNoL = min(NoL, GBuffer.ToonForceShadow); + //合并SurfaceShadow以及Transmision Shadow + Shadow.SurfaceShadow = min(Shadow.SurfaceShadow, Shadow.TransmissionShadow); + + //根据ToonShadowSmoothness、ToonShadowLocation、NoL计算阴影亮度,最后计算主阴影颜色。 + float RangeHalf = GBuffer.ToonShadowSmoothness * 0.5; + float RangeMin = max(0.0, GBuffer.ToonShadowLocation - RangeHalf); + float RangeMax = min(1.0, GBuffer.ToonShadowLocation + RangeHalf); + float ShadowIntensity = Shadow.SurfaceShadow * smoothstep(RangeMin, RangeMax, ToonNoL); + GBuffer.ToonCalcShadowColor = lerp(GBuffer.ToonShadowColor * LightData.SpecularScale, (1.0).xxx, ShadowIntensity); + + //计算次级阴影颜色,并最终合成。 + RangeHalf = GBuffer.ToonSecondaryShadowSmoothness * 0.5; + RangeMin = max(0.0, GBuffer.ToonSecondaryShadowLocation - RangeHalf); + RangeMax = min(1.0, GBuffer.ToonSecondaryShadowLocation + RangeHalf); + ShadowIntensity = Shadow.SurfaceShadow * smoothstep(RangeMin, RangeMax, ToonNoL); + GBuffer.ToonCalcShadowColor = lerp(GBuffer.ToonSecondaryShadowColor * LightData.SpecularScale, GBuffer.ToonCalcShadowColor, ShadowIntensity); + } + //修改结束 + + #if NON_DIRECTIONAL_DIRECT_LIGHTING + float Lighting; + + if( LightData.bRectLight ) + { + FRect Rect = GetRect( ToLight, LightData ); + + Lighting = IntegrateLight( Rect ); + } + else + { + FCapsuleLight Capsule = GetCapsule( ToLight, LightData ); + + Lighting = IntegrateLight( Capsule, LightData.bInverseSquared ); + } + + float3 LightingDiffuse = Diffuse_Lambert( GBuffer.DiffuseColor ) * Lighting; + LightAccumulator_AddSplit(LightAccumulator, LightingDiffuse, 0.0f, 0, MaskedLightColor * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation); + #else + FDirectLighting Lighting; + + if (LightData.bRectLight) + { + FRect Rect = GetRect( ToLight, LightData ); + const FRectTexture SourceTexture = ConvertToRectTexture(LightData); + + #if REFERENCE_QUALITY + Lighting = IntegrateBxDF( GBuffer, N, V, Rect, Shadow, SourceTexture, SVPos ); + #else + Lighting = IntegrateBxDF( GBuffer, N, V, Rect, Shadow, SourceTexture); + #endif + } + else + { + FCapsuleLight Capsule = GetCapsule( ToLight, LightData ); + + #if REFERENCE_QUALITY + Lighting = IntegrateBxDF( GBuffer, N, V, Capsule, Shadow, SVPos ); + #else + Lighting = IntegrateBxDF( GBuffer, N, V, Capsule, Shadow, LightData.bInverseSquared ); + #endif + } + //修改了这里 + float SurfaceShadow = UseToonShadow ? 1.0 : Shadow.SurfaceShadow; + float TransmissionShadow = UseToonShadow ? 1.0 : Shadow.TransmissionShadow; + Lighting.Specular *= UseToonShadow ? GBuffer.ToonSpecularColor : LightData.SpecularScale; + + LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, MaskedLightColor * SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation ); + LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, MaskedLightColor * TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation ); + //修改结束 + LightAccumulator.EstimatedCost += 0.4f; // add the cost of the lighting computations (should sum up to 1 form one light) + #endif + } +#endif // SHADING_PATH_MOBILE + } + return LightAccumulator; +} +``` + +## ShadingModels.ush +```c++ +float3 ToonSpecular(float ToonSpecularLocation, float ToonSpecularSmoothness, float3 ToonSpecularColor, float NoL) +{ + float ToonSpecularRangeHalf = ToonSpecularSmoothness * 0.5; + float ToonSpecularRangeMin = ToonSpecularLocation - ToonSpecularRangeHalf; + float ToonSpecularRangeMax = ToonSpecularLocation + ToonSpecularRangeHalf; + return smoothstep(ToonSpecularRangeMin, ToonSpecularRangeMax, NoL) * ToonSpecularColor; +} +``` + +创建了ToonCustomBxDF(**SHADINGMODELID_TOON_BASE**)与ToonLitBxDF(**SHADINGMODELID_TOON_PBR**、**SHADINGMODELID_TOON_SKIN**)2个ShadingModel函数。 + +### ToonCustomBxDF的修改 +Diffuse里面乘以之前在DeferredShadingCommon.ush中计算好的ShadowColor(已经计算了NoL) +`Lighting.Diffuse *= AreaLight.FalloffColor * (Falloff * NoL);` +=> +`Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor;` + +Speuclar直接归零,具体是在BasePass阶段进行计算了。 +`Lighting.Specular = 0;` +### ToonLitBxDF的修改 +Diffuse里面乘以之前在DeferredShadingCommon.ush中计算好的ShadowColor(已经计算了NoL) +`Lighting.Diffuse *= AreaLight.FalloffColor * (Falloff * NoL);` +=> +`Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor;` + +Speuclar最后乘以了**Shadow.SurfaceShadow** +`Lighting.Specular *= Shadow.SurfaceShadow;` + +```c++ + +FDirectLighting ToonLitBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow ) +{ + BxDFContext Context; + FDirectLighting Lighting; + +#if SUPPORTS_ANISOTROPIC_MATERIALS + bool bHasAnisotropy = HasAnisotropy(GBuffer.SelectiveOutputMask); +#else + bool bHasAnisotropy = false; +#endif + + float NoV, VoH, NoH; + BRANCH + if (bHasAnisotropy) + { + half3 X = GBuffer.WorldTangent; + half3 Y = normalize(cross(N, X)); + Init(Context, N, X, Y, V, L); + + NoV = Context.NoV; + VoH = Context.VoH; + NoH = Context.NoH; + } + else + { +#if SHADING_PATH_MOBILE + InitMobile(Context, N, V, L, NoL); +#else + Init(Context, N, V, L); +#endif + + NoV = Context.NoV; + VoH = Context.VoH; + NoH = Context.NoH; + + SphereMaxNoH(Context, AreaLight.SphereSinAlpha, true); + } + + Context.NoV = saturate(abs( Context.NoV ) + 1e-5); + +#if MATERIAL_ROUGHDIFFUSE + // Chan diffuse model with roughness == specular roughness. This is not necessarily a good modelisation of reality because when the mean free path is super small, the diffuse can in fact looks rougher. But this is a start. + // Also we cannot use the morphed context maximising NoH as this is causing visual artefact when interpolating rough/smooth diffuse response. + Lighting.Diffuse = Diffuse_Chan(GBuffer.DiffuseColor, Pow4(GBuffer.Roughness), NoV, NoL, VoH, NoH, GetAreaLightDiffuseMicroReflWeight(AreaLight)); +#else + Lighting.Diffuse = Diffuse_Lambert(GBuffer.DiffuseColor); +#endif + // Toon Diffuse + Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor; + + BRANCH + if (bHasAnisotropy) + { + //Lighting.Specular = GBuffer.WorldTangent * .5f + .5f; + Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.Anisotropy, GBuffer.SpecularColor, Context, NoL, AreaLight); + } + else + { + if( IsRectLight(AreaLight) ) + { + Lighting.Specular = RectGGXApproxLTC(GBuffer.Roughness, GBuffer.SpecularColor, N, V, AreaLight.Rect, AreaLight.Texture); + } + else + { + // Toon specular + Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * SpecularGGX(GBuffer.Roughness, GBuffer.SpecularColor, Context, NoL, AreaLight); + } + } + Lighting.Specular *= Shadow.SurfaceShadow; + + FBxDFEnergyTerms EnergyTerms = ComputeGGXSpecEnergyTerms(GBuffer.Roughness, Context.NoV, GBuffer.SpecularColor); + + // Add energy presevation (i.e. attenuation of the specular layer onto the diffuse component + Lighting.Diffuse *= ComputeEnergyPreservation(EnergyTerms); + + // Add specular microfacet multiple scattering term (energy-conservation) + Lighting.Specular *= ComputeEnergyConservation(EnergyTerms); + + Lighting.Transmission = 0; + return Lighting; +} + +FDirectLighting ToonCustomBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow ) +{ + BxDFContext Context; + FDirectLighting Lighting; + + float NoV, VoH, NoH; +#if SHADING_PATH_MOBILE + InitMobile(Context, N, V, L, NoL); +#else + Init(Context, N, V, L); +#endif + NoV = Context.NoV; + VoH = Context.VoH; + NoH = Context.NoH; + + SphereMaxNoH(Context, AreaLight.SphereSinAlpha, true); + + Context.NoV = saturate(abs( Context.NoV ) + 1e-5); + +#if MATERIAL_ROUGHDIFFUSE + // Chan diffuse model with roughness == specular roughness. This is not necessarily a good modelisation of reality because when the mean free path is super small, the diffuse can in fact looks rougher. But this is a start. + // Also we cannot use the morphed context maximising NoH as this is causing visual artefact when interpolating rough/smooth diffuse response. + Lighting.Diffuse = Diffuse_Chan(GBuffer.DiffuseColor, Pow4(GBuffer.Roughness), NoV, NoL, VoH, NoH, GetAreaLightDiffuseMicroReflWeight(AreaLight)); +#else + Lighting.Diffuse = Diffuse_Lambert(GBuffer.DiffuseColor); +#endif + // Toon Diffuse + Lighting.Diffuse *= AreaLight.FalloffColor * Falloff * GBuffer.ToonCalcShadowColor; + + // Toon specular + // Lighting.Specular = AreaLight.FalloffColor * (Falloff * NoL) * ToonSpecular(GBuffer.ToonSpecularLocation, GBuffer.ToonSpecularSmoothness, GBuffer.ToonSpecularColor, NoL); + // Lighting.Specular *= Shadow.SurfaceShadow; + + // FBxDFEnergyTerms EnergyTerms = ComputeGGXSpecEnergyTerms(GBuffer.Roughness, Context.NoV, GBuffer.SpecularColor); + + // Add energy presevation (i.e. attenuation of the specular layer onto the diffuse component + // Lighting.Diffuse *= ComputeEnergyPreservation(EnergyTerms); + + Lighting.Specular = 0; + Lighting.Transmission = 0; + return Lighting; +} + +FDirectLighting IntegrateBxDF( FGBufferData GBuffer, half3 N, half3 V, half3 L, float Falloff, half NoL, FAreaLight AreaLight, FShadowTerms Shadow ) +{ + switch( GBuffer.ShadingModelID ) + { + case SHADINGMODELID_DEFAULT_LIT: + case SHADINGMODELID_SINGLELAYERWATER: + case SHADINGMODELID_THIN_TRANSLUCENT: + return DefaultLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_SUBSURFACE: + return SubsurfaceBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_PREINTEGRATED_SKIN: + return PreintegratedSkinBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_CLEAR_COAT: + return ClearCoatBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_SUBSURFACE_PROFILE: + return SubsurfaceProfileBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_TWOSIDED_FOLIAGE: + return TwoSidedBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_HAIR: + return HairBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_CLOTH: + return ClothBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_EYE: + return EyeBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_TOON_BASE: + return ToonCustomBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + case SHADINGMODELID_TOON_PBR: + case SHADINGMODELID_TOON_SKIN: + return ToonLitBxDF( GBuffer, N, V, L, Falloff, NoL, AreaLight, Shadow ); + default: + return (FDirectLighting)0; + } +} +``` + +## DeferredLightPixelShaders.usf # PostProcess ## ToneMapping c++部分主要修改了: @@ -51,8 +414,6 @@ c++部分主要修改了: ***实现向ToneMaper Shader传递 `TRDGUniformBufferRef`的功能*** 之后再PostProcessTonemap.usf中,对**CustomStencil**进行判断,如果为true,则直接返回之前渲染结果。实际上BufferVisualization里根本看不出来。 - - ```c++ #include "DeferredShadingCommon.ush" @@ -86,4 +447,34 @@ void MainPS( } ``` -## Lut \ No newline at end of file +## PostProcessCombineLUT.usf +主要移植了UE4版本的LUT,以此保证效果统一。 + +# 其他 +## GpuSkinCacheComputeShader.usf +注释2行代码,用处不明。 +```c++ +#if GPUSKIN_MORPH_BLEND + { + Intermediates.UnpackedPosition += Unpacked.DeltaPosition; + // calc new normal by offseting it with the delta + LocalTangentZ = normalize( LocalTangentZ + Unpacked.DeltaTangentZ); + // derive the new tangent by orthonormalizing the new normal against + // the base tangent vector (assuming these are normalized) + LocalTangentX = normalize( LocalTangentX - (dot(LocalTangentX, LocalTangentZ) * LocalTangentZ) ); + }#else +#if GPUSKIN_APEX_CLOTH +``` +=> +```c++ +#if GPUSKIN_MORPH_BLEND + { + Intermediates.UnpackedPosition += Unpacked.DeltaPosition; + // calc new normal by offseting it with the delta + //LocalTangentZ = normalize( LocalTangentZ + Unpacked.DeltaTangentZ); + // derive the new tangent by orthonormalizing the new normal against + // the base tangent vector (assuming these are normalized) + //LocalTangentX = normalize( LocalTangentX - (dot(LocalTangentX, LocalTangentZ) * LocalTangentZ) ); + }#else +#if GPUSKIN_APEX_CLOTH +```