diff --git a/02-Note/DAWA/福瑞格斗项目/开发计划.md b/02-Note/DAWA/福瑞格斗项目/开发计划.md
index b774ead..cb16449 100644
--- a/02-Note/DAWA/福瑞格斗项目/开发计划.md
+++ b/02-Note/DAWA/福瑞格斗项目/开发计划.md
@@ -16,8 +16,8 @@
 
 # GAShooter移植计划
 ## c++
-- [x] GSEngineSubsystem
-- [ ] UGSBlueprintFunctionLibrary
+- [x] GSEngineSubsystem.h
+- [ ] GSBlueprintFunctionLibrary.h
 - [x] ~~AI~~
 - [ ] Characters
 	- [ ] Abilities
diff --git a/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md b/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md
index d0a3d2e..ad5ad31 100644
--- a/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md
+++ b/03-UnrealEngine/Rendering/RenderingPipeline/Lighting/Lighting.md
@@ -642,5 +642,122 @@ $$Falloff = \frac{saturate(1-(distance/lightRadius)^4)^2}{distance^2 + 1}$$
 $$Falloff = (1 - saturate(length(WorldLightVector)))^ {FalloffExponent}$$
 ##### GetShadowTerms()
 ```c++
+void GetShadowTerms(float SceneDepth, half4 PrecomputedShadowFactors, uint ShadingModelID, float ContactShadowOpacity, FDeferredLightData LightData, float3 TranslatedWorldPosition, half3 L, half4 LightAttenuation, float Dither, inout FShadowTerms Shadow)
+{
+	float ContactShadowLength = 0.0f;
+	const float ContactShadowLengthScreenScale = GetTanHalfFieldOfView().y * SceneDepth;
 
+	BRANCH
+	if (LightData.ShadowedBits)
+	{
+		// Remapping the light attenuation buffer (see ShadowRendering.cpp)
+
+		// LightAttenuation: Light function + per-object shadows in z, per-object SSS shadowing in w, 
+		// Whole scene directional light shadows in x, whole scene directional light SSS shadows in y
+		// Get static shadowing from the appropriate GBuffer channel
+#if ALLOW_STATIC_LIGHTING
+		half UsesStaticShadowMap = dot(LightData.ShadowMapChannelMask, half4(1, 1, 1, 1));
+		half StaticShadowing = lerp(1, dot(PrecomputedShadowFactors, LightData.ShadowMapChannelMask), UsesStaticShadowMap);
+#else
+		half StaticShadowing = 1.0f;
+#endif
+
+		if (LightData.bRadialLight || SHADING_PATH_MOBILE)
+		{
+			// Remapping the light attenuation buffer (see ShadowRendering.cpp)
+
+			Shadow.SurfaceShadow = LightAttenuation.z * StaticShadowing;
+			// SSS uses a separate shadowing term that allows light to penetrate the surface
+			//@todo - how to do static shadowing of SSS correctly?
+			Shadow.TransmissionShadow = LightAttenuation.w * StaticShadowing;
+
+			Shadow.TransmissionThickness = LightAttenuation.w;
+		}
+		else
+		{
+			// Remapping the light attenuation buffer (see ShadowRendering.cpp)
+			// Also fix up the fade between dynamic and static shadows
+			// to work with plane splits rather than spheres.
+
+			float DynamicShadowFraction = DistanceFromCameraFade(SceneDepth, LightData);
+			// For a directional light, fade between static shadowing and the whole scene dynamic shadowing based on distance + per object shadows
+			Shadow.SurfaceShadow = lerp(LightAttenuation.x, StaticShadowing, DynamicShadowFraction);
+			// Fade between SSS dynamic shadowing and static shadowing based on distance
+			Shadow.TransmissionShadow = min(lerp(LightAttenuation.y, StaticShadowing, DynamicShadowFraction), LightAttenuation.w);
+
+			Shadow.SurfaceShadow *= LightAttenuation.z;
+			Shadow.TransmissionShadow *= LightAttenuation.z;
+
+			// Need this min or backscattering will leak when in shadow which cast by non perobject shadow(Only for directional light)
+			Shadow.TransmissionThickness = min(LightAttenuation.y, LightAttenuation.w);
+		}
+
+		FLATTEN
+		if (LightData.ShadowedBits > 1 && LightData.ContactShadowLength > 0)
+		{
+			ContactShadowLength = LightData.ContactShadowLength * (LightData.ContactShadowLengthInWS ? 1.0f : ContactShadowLengthScreenScale);
+		}
+	}
+
+#if SUPPORT_CONTACT_SHADOWS
+
+#if STRATA_ENABLED == 0
+	if (LightData.ShadowedBits < 2 && (ShadingModelID == SHADINGMODELID_HAIR))
+	{
+		ContactShadowLength = 0.2 * ContactShadowLengthScreenScale;
+	}
+	// World space distance to cover eyelids and eyelashes but not beyond
+	if (ShadingModelID == SHADINGMODELID_EYE)
+	{
+		ContactShadowLength = 0.5;
+		
+	}
+#endif
+
+	#if MATERIAL_CONTACT_SHADOWS
+		ContactShadowLength = 0.2 * ContactShadowLengthScreenScale;
+	#endif
+
+	BRANCH
+	if (ContactShadowLength > 0.0)
+	{
+		float StepOffset = Dither - 0.5;
+		bool bHitCastContactShadow = false;
+		bool bHairNoShadowLight = ShadingModelID == SHADINGMODELID_HAIR && !LightData.ShadowedBits;
+		float HitDistance = ShadowRayCast( TranslatedWorldPosition, L, ContactShadowLength, 8, StepOffset, bHairNoShadowLight, bHitCastContactShadow );
+				
+		if ( HitDistance > 0.0 )
+		{
+			float ContactShadowOcclusion = bHitCastContactShadow ? LightData.ContactShadowCastingIntensity : LightData.ContactShadowNonCastingIntensity;
+
+#if STRATA_ENABLED == 0
+			// Exponential attenuation is not applied on hair/eye/SSS-profile here, as the hit distance (shading-point to blocker) is different from the estimated 
+			// thickness (closest-point-from-light to shading-point), and this creates light leaks. Instead we consider first hit as a blocker (old behavior)
+			BRANCH
+			if (ContactShadowOcclusion > 0.0 && 
+				IsSubsurfaceModel(ShadingModelID) &&
+				ShadingModelID != SHADINGMODELID_HAIR &&
+				ShadingModelID != SHADINGMODELID_EYE &&
+				ShadingModelID != SHADINGMODELID_SUBSURFACE_PROFILE)
+			{
+				// Reduce the intensity of the shadow similar to the subsurface approximation used by the shadow maps path
+				// Note that this is imperfect as we don't really have the "nearest occluder to the light", but this should at least
+				// ensure that we don't darken-out the subsurface term with the contact shadows
+				float Density = SubsurfaceDensityFromOpacity(ContactShadowOpacity);
+				ContactShadowOcclusion *= 1.0 - saturate( exp( -Density * HitDistance ) );
+			}
+#endif
+
+			float ContactShadow = 1.0 - ContactShadowOcclusion;
+
+			Shadow.SurfaceShadow *= ContactShadow;
+			Shadow.TransmissionShadow *= ContactShadow;
+		}
+		
+	}
+#endif
+
+	Shadow.HairTransmittance = LightData.HairTransmittance;
+	Shadow.HairTransmittance.OpaqueVisibility = Shadow.SurfaceShadow;
+}
 ```
\ No newline at end of file