← 返回项目技术总览

三处独立的"昼夜亮度控制"原本走不同曲线,夜景氛围调暗时角色/技能自发光还保持几百倍的白天乘数导致过曝。统一为一条共享曲线 GetDaylightFactor,三处消费方各取所需。

— V61 统一曲线的来源

一、三个独立问题 → 一个统一方案

问题根因修复手段
夜景整体太亮,没有夜晚氛围场景 PPV 没做夜间压暗AutoExposureBias 负向偏移
角色发光纹路夜晚过曝材质 Emissive 末尾乘数固定几百倍,昼夜不变材质 × EffectBrightness 标量(Lerp 夜晚 0.03 / 白天 1.0)
技能特效夜晚像白天一样亮部分 Niagara 材质没接 MPC EmissiveScale52 个发光材质批量补 Multiply × CollectionParameter(EmissiveScale)

二、V61 唯一权威曲线(三处共用)

静态函数 ATimeOfDayManager::GetDaylightFactor(float Hours) 返回 0(夜晚全暗)到 1(白天满亮)的因子。曝光/技能/角色三处消费方各取"1 − factor"或"直接用 factor"。

时段DaylightFactor曝光 DimFactor (=1−factor)技能 EmissiveScale角色 EffectBrightness
09:00–18:151(满亮)0(不动)1.01.0
18:15–19:301→0.7620→0.2381→0.7621→0.762
19:30–21:300.762→00.238→10.762→00.762→0
21:30–06:150(全暗)1(最大)0.0000240.03
06:15–08:000→0.5381→0.4620.000024→0.5380.03→0.538
08:00–09:000.538→10.462→00.538→10.538→1

曲线参数(可调杠杆)

constexpr float NightDimMaxEV   = 4.0f;   // 夜晚最多压暗的 EV(±1 EV ≈ 亮度 ×2 或 ÷2)
constexpr float DawnStartH      = 6.25f;  // 06:15 开始恢复
constexpr float DawnAccelEndH   = 8.0f;   // 08:00 加速段起点
constexpr float DawnRestoreEndH = 9.0f;   // 09:00 完全恢复
constexpr float DuskStartH      = 18.25f; // 18:15 开始压暗
constexpr float DuskAccelEndH   = 19.5f;  // 19:30 加速段起点
constexpr float DuskEndH        = 21.5f;  // 21:30 全暗
constexpr float NightEndH       = 6.25f;  // 06:15 结束
constexpr float NightEffBright  = 0.03f;  // 角色发光夜晚值(角色材质 Multiply)
constexpr float NightEmissive   = 0.000024f; // 技能特效 MPC 夜晚值

三、曝光压暗实现(AutoExposureBias)

铁律:UE 的 AutoExposureBias 符号——正值 = 变亮,负值 = 变暗(每 ±1 EV 亮度约 ×2 或 ÷2)。初版 V48 注释错误写成"正=更暗",按注释写导致夜晚越加曝光越亮。

// TimeOfDayManager.cpp · ApplySunMoonIntensity() V61 块
// 缓存 PPV 的原始 EV 基值(避免每帧把上次写入值当基值导致漂移)
float CachedBaseBias = PPVCache.Get(PPV);  // 首次读取 PPV->Settings.AutoExposureBias

const float DimFactor = 1.0f - GetDaylightFactor(CurrentHours);
const float Offset = NightDimMaxEV * DimFactor;
PPV->Settings.AutoExposureBias = CachedBaseBias - Offset;  // 负方向 = 变暗 ✓

四、角色材质 EffectBrightness 接入

6 个发光母材质(M_Nyx_Emissive / M_Nyx_Body / M_Nyx_Clothes / M_Nyx_Fur / M_Nyx_Hair / M_Nyx_Ribbon)各在 EmissiveColor 输出前新增 Multiply 节点串联新标量参数 EffectBrightness(默认=1)。

// TransformCharacter.cpp · UpdateEffectBrightness()
// 白天=1(保持原大乘数不变),夜晚=0.03(压暗到接近默认)
const float Target = FMath::Lerp(NightEffBright, 1.0f,
    ATimeOfDayManager::GetDaylightFactor(GetCurrentGameHours()));

// 对每个骨骼/静态网格材质槽创建 MID 并设 EffectBrightness
for (auto& Slot : MeshComponent->GetMaterials()) {
    UMaterialInstanceDynamic* MID = MeshComponent->CreateAndSetMaterialInstanceDynamicFromMaterial(i, Slot);
    MID->SetScalarParameterValue(TEXT("EffectBrightness"), Target);
}

五、技能特效 MPC EmissiveScale 接入

52 个技能发光材质,母材质链末端新增 Multiply × CollectionParameter(EmissiveScale),MPC 引用 /Game/TimeOfDay/MPC_GlobalEffectBrightness。TimeOfDayManager 每帧写入 MPC,三个昼夜曲线统一驱动。

六、复用要点(后续调亮调暗)