编辑器界面:
代码流程:
FLinearColor ULightComponent::GetColoredLightBrightness() const
{
// Brightness in Lumens
float LightBrightness = ComputeLightBrightness();
FLinearColor Energy = FLinearColor(LightColor) * LightBrightness;
if (bUseTemperature)
{
Energy *= FLinearColor::MakeFromColorTemperature(Temperature);
}
return Energy;
}
/**
* Filter color of the light.
* Note that this can change the light's effective intensity.
*/
UPROPERTY(BlueprintReadOnly, interp, Category=Light, meta=(HideAlphaChannel, ShouldShowInViewport = true))
FColor LightColor;
FORCEINLINE FLinearColor::FLinearColor(const FColor& Color)
{
R = sRGBToLinearTable[Color.R];
G = sRGBToLinearTable[Color.G];
B = sRGBToLinearTable[Color.B];
A = float(Color.A) * (1.0f / 255.0f);
}
float ULightComponent::ComputeLightBrightness() const
{
float LightBrightness = Intensity;
if(IESTexture)
{
if(bUseIESBrightness)
{
LightBrightness = IESTexture->Brightness * IESBrightnessScale;
}
LightBrightness *= IESTexture->TextureMultiplier;
}
return LightBrightness;
}
FLinearColor FLinearColor::MakeFromColorTemperature( float Temp )
{
Temp = FMath::Clamp( Temp, 1000.0f, 15000.0f );
// Approximate Planckian locus in CIE 1960 UCS
float u = ( 0.860117757f + 1.54118254e-4f * Temp + 1.28641212e-7f * Temp*Temp ) / ( 1.0f + 8.42420235e-4f * Temp + 7.08145163e-7f * Temp*Temp );
float v = ( 0.317398726f + 4.22806245e-5f * Temp + 4.20481691e-8f * Temp*Temp ) / ( 1.0f - 2.89741816e-5f * Temp + 1.61456053e-7f * Temp*Temp );
float x = 3.0f * u / ( 2.0f * u - 8.0f * v + 4.0f );
float y = 2.0f * v / ( 2.0f * u - 8.0f * v + 4.0f );
float z = 1.0f - x - y;
float Y = 1.0f;
float X = Y/y * x;
float Z = Y/y * z;
// XYZ to RGB with BT.709 primaries
float R = 3.2404542f * X + -1.5371385f * Y + -0.4985314f * Z;
float G = -0.9692660f * X + 1.8760108f * Y + 0.0415560f * Z;
float B = 0.0556434f * X + -0.2040259f * Y + 1.0572252f * Z;
return FLinearColor(R,G,B);
}
void FLightRenderParameters::MakeShaderParameters(const FViewMatrices& ViewMatrices, float Exposure, FLightShaderParameters& OutShaderParameters) const
{
OutShaderParameters.TranslatedWorldPosition = FVector3f(ViewMatrices.GetPreViewTranslation() + WorldPosition);
OutShaderParameters.InvRadius = InvRadius;
OutShaderParameters.Color = FVector3f(Color) * GetLightExposureScale(Exposure);
OutShaderParameters.FalloffExponent = FalloffExponent;
OutShaderParameters.Direction = Direction;
OutShaderParameters.SpecularScale = SpecularScale;
OutShaderParameters.Tangent = Tangent;
OutShaderParameters.SourceRadius = SourceRadius;
OutShaderParameters.SpotAngles = SpotAngles;
OutShaderParameters.SoftSourceRadius = SoftSourceRadius;
OutShaderParameters.SourceLength = SourceLength;
OutShaderParameters.RectLightBarnCosAngle = RectLightBarnCosAngle;
OutShaderParameters.RectLightBarnLength = RectLightBarnLength;
OutShaderParameters.RectLightAtlasUVOffset = RectLightAtlasUVOffset;
OutShaderParameters.RectLightAtlasUVScale = RectLightAtlasUVScale;
OutShaderParameters.RectLightAtlasMaxLevel = RectLightAtlasMaxLevel;
}
FLightSceneProxy::FLightSceneProxy(const ULightComponent* InLightComponent)
: LightComponent(InLightComponent)
, SceneInterface(InLightComponent->GetScene())
, IndirectLightingScale(InLightComponent->IndirectLightingIntensity)
, VolumetricScatteringIntensity(FMath::Max(InLightComponent->VolumetricScatteringIntensity, 0.0f))
, ShadowResolutionScale(InLightComponent->ShadowResolutionScale)
, ShadowBias(InLightComponent->ShadowBias)
, ShadowSlopeBias(InLightComponent->ShadowSlopeBias)
, ShadowSharpen(InLightComponent->ShadowSharpen)
, ContactShadowLength(InLightComponent->ContactShadowLength)
, SpecularScale(InLightComponent->SpecularScale)
, LightGuid(InLightComponent->LightGuid)
, RayStartOffsetDepthScale(InLightComponent->RayStartOffsetDepthScale)
, IESTexture(0)
, bContactShadowLengthInWS(InLightComponent->ContactShadowLengthInWS ? true : false)
, bMovable(InLightComponent->IsMovable())
, bStaticLighting(InLightComponent->HasStaticLighting())
, bStaticShadowing(InLightComponent->HasStaticShadowing())
, bCastDynamicShadow(InLightComponent->CastShadows && InLightComponent->CastDynamicShadows)
, bCastStaticShadow(InLightComponent->CastShadows && InLightComponent->CastStaticShadows)
, bCastTranslucentShadows(InLightComponent->CastTranslucentShadows)
, bTransmission(InLightComponent->bTransmission && bCastDynamicShadow && !bStaticShadowing)
, bCastVolumetricShadow(InLightComponent->bCastVolumetricShadow)
, bCastHairStrandsDeepShadow(InLightComponent->bCastDeepShadow)
, bCastShadowsFromCinematicObjectsOnly(InLightComponent->bCastShadowsFromCinematicObjectsOnly)
, bForceCachedShadowsForMovablePrimitives(InLightComponent->bForceCachedShadowsForMovablePrimitives)
, CastRaytracedShadow(InLightComponent->CastShadows == 0? (TEnumAsByte) ECastRayTracedShadow::Disabled : InLightComponent->CastRaytracedShadow)
, bAffectReflection(InLightComponent->bAffectReflection)
, bAffectGlobalIllumination(InLightComponent->bAffectGlobalIllumination)
, bAffectTranslucentLighting(InLightComponent->bAffectTranslucentLighting)
, bUsedAsAtmosphereSunLight(InLightComponent->IsUsedAsAtmosphereSunLight())
, bAffectDynamicIndirectLighting(InLightComponent->bAffectDynamicIndirectLighting)
, bUseRayTracedDistanceFieldShadows(InLightComponent->bUseRayTracedDistanceFieldShadows)
, bUseVirtualShadowMaps(false) // See below
, bCastModulatedShadows(false)
, bUseWholeSceneCSMForMovableObjects(false)
, AtmosphereSunLightIndex(InLightComponent->GetAtmosphereSunLightIndex())
, AtmosphereSunDiskColorScale(InLightComponent->GetAtmosphereSunDiskColorScale())
, LightType(InLightComponent->GetLightType())
, LightingChannelMask(GetLightingChannelMaskForStruct(InLightComponent->LightingChannels))
, StatId(InLightComponent->GetStatID(true))
, ComponentName(InLightComponent->GetFName())
, LevelName(InLightComponent->GetOwner() ? InLightComponent->GetOwner()->GetLevel()->GetOutermost()->GetFName() : NAME_None)
, FarShadowDistance(0)
, FarShadowCascadeCount(0)
, ShadowAmount(1.0f)
, SamplesPerPixel(1)
, DeepShadowLayerDistribution(InLightComponent->DeepShadowLayerDistribution)
#if ACTOR_HAS_LABELS
, OwnerNameOrLabel(InLightComponent->GetOwner() ? InLightComponent->GetOwner()->GetActorNameOrLabel() : InLightComponent->GetName())
#endif
{
check(SceneInterface);
// Currently we use virtual shadows maps for all lights when the global setting is enabled
bUseVirtualShadowMaps = ::UseVirtualShadowMaps(SceneInterface->GetShaderPlatform(), SceneInterface->GetFeatureLevel());
// Treat stationary lights as movable when non-nanite VSMs are enabled
const bool bNonNaniteVirtualShadowMaps = UseNonNaniteVirtualShadowMaps(SceneInterface->GetShaderPlatform(), SceneInterface->GetFeatureLevel());
if (bNonNaniteVirtualShadowMaps)
{
bStaticShadowing = bStaticLighting;
}
const FLightComponentMapBuildData* MapBuildData = InLightComponent->GetLightComponentMapBuildData();
if (MapBuildData && bStaticShadowing && !bStaticLighting)
{
ShadowMapChannel = MapBuildData->ShadowMapChannel;
}
else
{
ShadowMapChannel = INDEX_NONE;
}
// Use the preview channel if valid, otherwise fallback to the lighting build channel
PreviewShadowMapChannel = InLightComponent->PreviewShadowMapChannel != INDEX_NONE ? InLightComponent->PreviewShadowMapChannel : ShadowMapChannel;
StaticShadowDepthMap = &LightComponent->StaticShadowDepthMap;
if(LightComponent->IESTexture)
{
IESTexture = LightComponent->IESTexture;
}
Color = LightComponent->GetColoredLightBrightness();
}
FDeferredLightUniformStruct GetDeferredLightParameters(const FSceneView& View, const FLightSceneInfo& LightSceneInfo)
{
FDeferredLightUniformStruct Out;
FLightRenderParameters LightParameters;
LightSceneInfo.Proxy->GetLightShaderParameters(LightParameters);
LightParameters.MakeShaderParameters(View.ViewMatrices, View.GetLastEyeAdaptationExposure(), Out.LightParameters);
}
struct FLightRenderParameters
{
ENGINE_API void MakeShaderParameters(const FViewMatrices& ViewMatrices, float Exposure, FLightShaderParameters& OutShaderParameters) const;
ENGINE_API float GetLightExposureScale(float Exposure) const;
static ENGINE_API float GetLightExposureScale(float Exposure, float InverseExposureBlend);
// Position of the light in world space.
FVector WorldPosition;
// 1 / light's falloff radius from Position.
float InvRadius;
// Color of the light.
FLinearColor Color;
// The exponent for the falloff of the light intensity from the distance.
float FalloffExponent;
// Direction of the light if applies.
FVector3f Direction;
// Factor to applies on the specular.
float SpecularScale;
// One tangent of the light if applies.
// Note: BiTangent is on purpose not stored for memory optimisation purposes.
FVector3f Tangent;
// Radius of the point light.
float SourceRadius;
// Dimensions of the light, for spot light, but also
FVector2f SpotAngles;
// Radius of the soft source.
float SoftSourceRadius;
// Other dimensions of the light source for rect light specifically.
float SourceLength;
// Barn door angle for rect light
float RectLightBarnCosAngle;
// Barn door length for rect light
float RectLightBarnLength;
// Rect. light atlas transformation
FVector2f RectLightAtlasUVOffset;
FVector2f RectLightAtlasUVScale;
float RectLightAtlasMaxLevel;
float InverseExposureBlend;
// Return Invalid rect light atlas MIP level
static float GetRectLightAtlasInvalidMIPLevel() { return 32.f; }
};
Shader对应代码:
FDeferredLightData SetupLightDataForStandardDeferred()
{
FDeferredLightData LightData;
LightData.TranslatedWorldPosition = GetDeferredLightTranslatedWorldPosition();
LightData.InvRadius = DeferredLightUniforms_InvRadius;
LightData.Color = DeferredLightUniforms_Color;
LightData.FalloffExponent = DeferredLightUniforms_FalloffExponent;
LightData.Direction = DeferredLightUniforms_Direction;
LightData.Tangent = DeferredLightUniforms_Tangent;
LightData.SpotAngles = DeferredLightUniforms_SpotAngles;
LightData.SourceRadius = DeferredLightUniforms_SourceRadius;
LightData.SourceLength = 1 > 0 ? DeferredLightUniforms_SourceLength : 0;
LightData.SoftSourceRadius = DeferredLightUniforms_SoftSourceRadius;
LightData.SpecularScale = DeferredLightUniforms_SpecularScale;
LightData.ContactShadowLength = abs(DeferredLightUniforms_ContactShadowLength);
LightData.ContactShadowLengthInWS = DeferredLightUniforms_ContactShadowLength < 0.0f;
LightData.ContactShadowNonShadowCastingIntensity = DeferredLightUniforms_ContactShadowNonShadowCastingIntensity;
LightData.DistanceFadeMAD = DeferredLightUniforms_DistanceFadeMAD;
LightData.ShadowMapChannelMask = DeferredLightUniforms_ShadowMapChannelMask;
LightData.ShadowedBits = DeferredLightUniforms_ShadowedBits;
LightData.bInverseSquared = 1 > 0 && DeferredLightUniforms_FalloffExponent == 0;
LightData.bRadialLight = 1 > 0;
LightData.bSpotLight = 1 > 0;
LightData.bRectLight = 1 == 2;
LightData.RectLightBarnCosAngle = DeferredLightUniforms_RectLightBarnCosAngle;
LightData.RectLightBarnLength = DeferredLightUniforms_RectLightBarnLength;
LightData.RectLightAtlasMaxLevel = DeferredLightUniforms_RectLightAtlasMaxLevel;
LightData.RectLightAtlasUVOffset = DeferredLightUniforms_RectLightAtlasUVOffset;
LightData.RectLightAtlasUVScale = DeferredLightUniforms_RectLightAtlasUVScale;
LightData.HairTransmittance = InitHairTransmittanceData();
return LightData;
}