UE4 GetDynamicLighting

DeferredLightingCommon.ush

struct FDeferredLightData
{
	float3 Position;
	float  InvRadius;
	float3 Color;
	float  FalloffExponent;
	float3 Direction;
	float3 Tangent;
    float SoftSourceRadius;
	float2 SpotAngles;
	float SourceRadius;
	float SourceLength;
	float SpecularScale;
	float ContactShadowLength;
	/** Intensity of non-shadow-casting contact shadows */
	float ContactShadowNonShadowCastingIntensity;
	float2 DistanceFadeMAD;
	float4 ShadowMapChannelMask;
	/** Whether ContactShadowLength is in World Space or in Screen Space. */
	bool ContactShadowLengthInWS;
	/** Whether to use inverse squared falloff. */
	bool bInverseSquared;
	/** Whether this is a light with radial attenuation, aka point or spot light. */
	bool bRadialLight;
	/** Whether this light needs spotlight attenuation. */
	bool bSpotLight;
	bool bRectLight;
	/** Whether the light should apply shadowing. */
	uint ShadowedBits;
	float RectLightBarnCosAngle;
	float RectLightBarnLength;

	FHairTransmittanceData HairTransmittance;
};

/** Data about a single light to be shaded with the simple shading model, designed for speed and limited feature set. */
struct FSimpleDeferredLightData
{
	float3 Position;
	float  InvRadius;
	float3 Color;
	float  FalloffExponent;
	/** Whether to use inverse squared falloff. */
	bool bInverseSquared;
};


#define RECLIGHT_BARNDOOR 1
// Wrapper for FDeferredLightData for computing visible rect light (i.e., unoccluded by barn doors)
FRect GetRect(float3 ToLight, FDeferredLightData LightData)
{
	return GetRect(
		ToLight, 
		LightData.Direction, 
		LightData.Tangent, 
		LightData.SourceRadius, 
		LightData.SourceLength, 
		LightData.RectLightBarnCosAngle, 
		LightData.RectLightBarnLength,
		RECLIGHT_BARNDOOR);
}

FCapsuleLight GetCapsule( float3 ToLight, FDeferredLightData LightData )
{
	FCapsuleLight Capsule;
	Capsule.Length = LightData.SourceLength;
	Capsule.Radius = LightData.SourceRadius;
	Capsule.SoftRadius = LightData.SoftSourceRadius;
	Capsule.DistBiasSqr = 1;
	Capsule.LightPos[0] = ToLight - 0.5 * Capsule.Length * LightData.Tangent;
	Capsule.LightPos[1] = ToLight + 0.5 * Capsule.Length * LightData.Tangent;
	return Capsule;
}

/** Calculates lighting for a given position, normal, etc with a fully featured lighting model designed for quality. */
FDeferredLightingSplit GetDynamicLightingSplit(
	float3 WorldPosition, float3 CameraVector, FGBufferData GBuffer, float AmbientOcclusion, uint ShadingModelID, 
	FDeferredLightData LightData, float4 LightAttenuation, float Dither, uint2 SVPos, FRectTexture SourceTexture,
	inout float SurfaceShadow)
{
	FLightAccumulator LightAccumulator = (FLightAccumulator)0;

	float3 V = -CameraVector;
	float3 N = GBuffer.WorldNormal;
	BRANCH if( GBuffer.ShadingModelID == SHADINGMODELID_CLEAR_COAT && CLEAR_COAT_BOTTOM_NORMAL)
	{
		const float2 oct1 = ((float2(GBuffer.CustomData.a, GBuffer.CustomData.z) * 2) - (256.0/255.0)) + UnitVectorToOctahedron(GBuffer.WorldNormal);
		N = OctahedronToUnitVector(oct1);			
	}
	
	float3 L = LightData.Direction;	// Already normalized
	float3 ToLight = L;
	
	float LightMask = 1;
	if (LightData.bRadialLight)
	{
		LightMask = GetLocalLightAttenuation( WorldPosition, LightData, ToLight, L );
	}

	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;
		GetShadowTerms(GBuffer, LightData, WorldPosition, L, LightAttenuation, Dither, Shadow);
		SurfaceShadow = Shadow.SurfaceShadow;

		LightAccumulator.EstimatedCost += 0.3f;		// add the cost of getting the shadow terms

		BRANCH
		if( Shadow.SurfaceShadow + Shadow.TransmissionShadow > 0 )
		{
			const bool bNeedsSeparateSubsurfaceLightAccumulation = UseSubsurfaceProfile(GBuffer.ShadingModelID);
			float3 LightColor = LightData.Color;

		#if NON_DIRECTIONAL_DIRECT_LIGHTING
			float Lighting;

			if( LightData.bRectLight )
			{
				FRect Rect = GetRect( ToLight, LightData );

				Lighting = IntegrateLight( Rect, SourceTexture);
			}
			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, LightColor * LightMask * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation);
		#else
			FDirectLighting Lighting;

			if (LightData.bRectLight)
			{
				FRect Rect = GetRect( ToLight, 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
			}

			Lighting.Specular *= LightData.SpecularScale;
				
			LightAccumulator_AddSplit( LightAccumulator, Lighting.Diffuse, Lighting.Specular, Lighting.Diffuse, LightColor * LightMask * Shadow.SurfaceShadow, bNeedsSeparateSubsurfaceLightAccumulation );
			LightAccumulator_AddSplit( LightAccumulator, Lighting.Transmission, 0.0f, Lighting.Transmission, LightColor * LightMask * Shadow.TransmissionShadow, bNeedsSeparateSubsurfaceLightAccumulation );

			LightAccumulator.EstimatedCost += 0.4f;		// add the cost of the lighting computations (should sum up to 1 form one light)
		#endif
		}
	}

	return LightAccumulator_GetResultSplit(LightAccumulator);
}

float4 GetDynamicLighting(
	float3 WorldPosition, float3 CameraVector, FGBufferData GBuffer, float AmbientOcclusion, uint ShadingModelID, 
	FDeferredLightData LightData, float4 LightAttenuation, float Dither, uint2 SVPos, FRectTexture SourceTexture,
	inout float SurfaceShadow)
{
	FDeferredLightingSplit SplitLighting = GetDynamicLightingSplit(
		WorldPosition, CameraVector, GBuffer, AmbientOcclusion, ShadingModelID, 
		LightData, LightAttenuation, Dither, SVPos, SourceTexture,
		SurfaceShadow);

	return SplitLighting.SpecularLighting + SplitLighting.DiffuseLighting;
}


FCapsuleLight GetCapsule( float3 ToLight, FDeferredLightData LightData )
{
	FCapsuleLight Capsule;
	Capsule.Length = LightData.SourceLength;
	Capsule.Radius = LightData.SourceRadius;
	Capsule.SoftRadius = LightData.SoftSourceRadius;
	Capsule.DistBiasSqr = 1;
	Capsule.LightPos[0] = ToLight - 0.5 * Capsule.Length * LightData.Tangent;
	Capsule.LightPos[1] = ToLight + 0.5 * Capsule.Length * LightData.Tangent;
	return Capsule;
}

Guess you like

Origin blog.csdn.net/sh15285118586/article/details/121804477