Add ChromaticAberration, HdrBloom, ColorCorrection post-processing tracks

Three new URP Volume Override tracks (Path A):

ChromaticAberration (73): power → intensity, isEnable toggles effect.
Per-channel redOffset/greenOffset/blueOffset not expressible in URP built-in CA.

HdrBloom (38): bloomIntensity → Bloom.intensity, threshold → Bloom.threshold.
Fields unconfirmed (no bundle data in 30-song scan).

ColorCorrection (61): saturation (game 1.0=neutral) → ColorAdjustments.saturation
(URP range -100..100). redCurve/greenCurve/blueCurve → ColorCurves via TextureCurve.
Depth curves and selective color have no URP equivalent.

Director.InitializeTimeline() acquires or creates a Volume on Camera.main and
adds the required overrides programmatically.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ritenseki
2026-05-07 14:17:41 +08:00
parent c0c7a5bfbe
commit fefcd96b07
10 changed files with 208 additions and 0 deletions
@@ -73,6 +73,9 @@ namespace Gallop.Live.Cutt
public event Action<LiveTimelineWashLightData, LiveTimelineKeyWashLightData> OnUpdateWashLight;
public event Action<LiveTimelineLaserData, LiveTimelineKeyLaserData> OnUpdateLaser;
public event Action<LiveTimelineBlinkLightData, LiveTimelineKeyBlinkLightData> OnUpdateBlinkLight;
public event Action<LiveTimelineChromaticAberrationData, LiveTimelineKeyChromaticAberrationData> OnUpdateChromaticAberration;
public event Action<LiveTimelineHdrBloomData, LiveTimelineKeyHdrBloomData> OnUpdateHdrBloom;
public event Action<LiveTimelineColorCorrectionData, LiveTimelineKeyColorCorrectionData> OnUpdateColorCorrection;
private static Func<LiveTimelineKeyCameraPositionData, LiveTimelineControl, FindTimelineConfig, Vector3> fnGetCameraPosValue = GetCameraPosValue;
@@ -364,6 +367,9 @@ namespace Gallop.Live.Cutt
AlterUpdate_SimpleListControl(workSheet.WashLightList, d => d.keys, OnUpdateWashLight, _currentFrame);
AlterUpdate_SimpleListControl(workSheet.laserList, d => d.keys, OnUpdateLaser, _currentFrame);
AlterUpdate_SimpleListControl(workSheet.blinkLightList, d => d.keys, OnUpdateBlinkLight, _currentFrame);
AlterUpdate_SimpleListControl(workSheet.chromaticAberrationList, d => d.keys, OnUpdateChromaticAberration, _currentFrame);
AlterUpdate_SimpleListControl(workSheet.hdrBloomKeys, d => d.keys, OnUpdateHdrBloom, _currentFrame);
AlterUpdate_SimpleListControl(workSheet.colorCorrectionDataLists, d => d.keys, OnUpdateColorCorrection, _currentFrame);
_isNowAlterUpdate = false;
@@ -0,0 +1,29 @@
using System;
using UnityEngine;
namespace Gallop.Live.Cutt
{
[Serializable]
public class LiveTimelineKeyChromaticAberrationData : LiveTimelineKeyWithInterpolate
{
public int isEnable;
public Vector2 redOffset;
public Vector2 greenOffset;
public Vector2 blueOffset;
public float power;
public float clip;
public int effectType;
}
[Serializable]
public class LiveTimelineKeyChromaticAberrationDataList : LiveTimelineKeyDataListTemplate<LiveTimelineKeyChromaticAberrationData>
{
}
[Serializable]
public class LiveTimelineChromaticAberrationData : ILiveTimelineGroupDataWithName
{
private const string default_name = "ChromaticAberration";
public LiveTimelineKeyChromaticAberrationDataList keys;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 577536d7b04577e4f97cd0c33c4c54d9
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,35 @@
using System;
using UnityEngine;
namespace Gallop.Live.Cutt
{
[Serializable]
public class LiveTimelineKeyColorCorrectionData : LiveTimelineKeyWithInterpolate
{
public int enable;
public float saturation; // 1.0 = neutral
public int mode;
public AnimationCurve redCurve;
public AnimationCurve greenCurve;
public AnimationCurve blueCurve;
public AnimationCurve depthRedCurve;
public AnimationCurve depthGreenCurve;
public AnimationCurve depthBlueCurve;
public AnimationCurve blendCurve;
public int selective;
public Color keyColor;
public Color targetColor;
}
[Serializable]
public class LiveTimelineKeyColorCorrectionDataList : LiveTimelineKeyDataListTemplate<LiveTimelineKeyColorCorrectionData>
{
}
[Serializable]
public class LiveTimelineColorCorrectionData : ILiveTimelineGroupDataWithName
{
private const string default_name = "ColorCorrection";
public LiveTimelineKeyColorCorrectionDataList keys;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3bbc9d423334b7e4fbce26081357344f
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,26 @@
using System;
using UnityEngine;
namespace Gallop.Live.Cutt
{
[Serializable]
public class LiveTimelineKeyHdrBloomData : LiveTimelineKeyWithInterpolate
{
// TODO: fields unconfirmed — no bundle data found in 30-song scan.
// Likely candidates based on URP Bloom: intensity, threshold.
public float bloomIntensity;
public float threshold;
}
[Serializable]
public class LiveTimelineKeyHdrBloomDataList : LiveTimelineKeyDataListTemplate<LiveTimelineKeyHdrBloomData>
{
}
[Serializable]
public class LiveTimelineHdrBloomData : ILiveTimelineGroupDataWithName
{
private const string default_name = "HdrBloom";
public LiveTimelineKeyHdrBloomDataList keys;
}
}
@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6de4d415603668a47807908ceac5e327
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -947,6 +947,9 @@ namespace Gallop.Live.Cutt
[SerializeField] public List<LiveTimelineWashLightData> WashLightList;
[SerializeField] public List<LiveTimelineLaserData> laserList;
[SerializeField] public List<LiveTimelineBlinkLightData> blinkLightList;
[SerializeField] public List<LiveTimelineChromaticAberrationData> chromaticAberrationList;
[SerializeField] public List<LiveTimelineHdrBloomData> hdrBloomKeys;
[SerializeField] public List<LiveTimelineColorCorrectionData> colorCorrectionDataLists;
/*
//���ڿ��Ե���AB���ˣ���Ȼ���淢��ûʲô��...˵����ʲôʱ�����õ�
@@ -4,6 +4,8 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.Universal;
namespace Gallop.Live
{
@@ -49,6 +51,8 @@ namespace Gallop.Live
private Dictionary<LiveTimelineEffectData, (int frame, GameObject instance)> _activeEffects
= new Dictionary<LiveTimelineEffectData, (int, GameObject)>();
private Volume _postProcessVolume;
public UmaViewerAudio.CuteAudioSource liveMusic = new UmaViewerAudio.CuteAudioSource();
public PartEntry partInfo;
@@ -307,6 +311,26 @@ namespace Gallop.Live
_liveTimelineControl.OnUpdateWashLight += OnWashLightUpdate;
_liveTimelineControl.OnUpdateLaser += OnLaserUpdate;
_liveTimelineControl.OnUpdateBlinkLight += OnBlinkLightUpdate;
_liveTimelineControl.OnUpdateChromaticAberration += OnChromaticAberrationUpdate;
_liveTimelineControl.OnUpdateHdrBloom += OnHdrBloomUpdate;
_liveTimelineControl.OnUpdateColorCorrection += OnColorCorrectionUpdate;
// 获取或创建摄像机上的 Volume 组件,供后处理 handler 使用
var mainCam = Camera.main;
if (mainCam != null)
{
_postProcessVolume = mainCam.GetComponent<Volume>();
if (_postProcessVolume == null)
_postProcessVolume = mainCam.gameObject.AddComponent<Volume>();
if (_postProcessVolume.profile == null)
_postProcessVolume.profile = ScriptableObject.CreateInstance<VolumeProfile>();
var profile = _postProcessVolume.profile;
if (!profile.Has<ChromaticAberration>()) profile.Add<ChromaticAberration>(true);
if (!profile.Has<Bloom>()) profile.Add<Bloom>(true);
if (!profile.Has<ColorAdjustments>()) profile.Add<ColorAdjustments>(true);
if (!profile.Has<ColorCurves>()) profile.Add<ColorCurves>(true);
}
}
private void OnEffectUpdate(LiveTimelineEffectData effectData, LiveTimelineKeyEffectData keyData)
@@ -430,6 +454,55 @@ namespace Gallop.Live
}
}
private void OnChromaticAberrationUpdate(LiveTimelineChromaticAberrationData data, LiveTimelineKeyChromaticAberrationData keyData)
{
if (keyData == null || _postProcessVolume == null) return;
if (!_postProcessVolume.profile.TryGet<ChromaticAberration>(out var fx)) return;
bool on = keyData.isEnable != 0;
fx.active = on;
if (on)
fx.intensity.Override(keyData.power);
// TODO: keyData.redOffset/greenOffset/blueOffset — per-channel displacement,
// not expressible in URP built-in ChromaticAberration. clip, effectType unused.
}
private void OnHdrBloomUpdate(LiveTimelineHdrBloomData data, LiveTimelineKeyHdrBloomData keyData)
{
if (keyData == null || _postProcessVolume == null) return;
if (!_postProcessVolume.profile.TryGet<Bloom>(out var fx)) return;
fx.intensity.Override(keyData.bloomIntensity);
fx.threshold.Override(keyData.threshold);
// TODO: field mapping unconfirmed — no bundle data found. Verify when data becomes available.
}
private void OnColorCorrectionUpdate(LiveTimelineColorCorrectionData data, LiveTimelineKeyColorCorrectionData keyData)
{
if (keyData == null || _postProcessVolume == null) return;
bool on = keyData.enable != 0;
if (_postProcessVolume.profile.TryGet<ColorAdjustments>(out var ca))
{
ca.active = on;
if (on)
// game: 1.0 = neutral; URP: 0 = neutral, range -100..100
ca.saturation.Override((keyData.saturation - 1f) * 100f);
}
if (_postProcessVolume.profile.TryGet<ColorCurves>(out var cc))
{
cc.active = on;
if (on && keyData.redCurve != null)
{
cc.red.Override(new TextureCurve(keyData.redCurve.keys, 0f, false, new Vector2(0f, 1f)));
cc.green.Override(new TextureCurve(keyData.greenCurve.keys, 0f, false, new Vector2(0f, 1f)));
cc.blue.Override(new TextureCurve(keyData.blueCurve.keys, 0f, false, new Vector2(0f, 1f)));
}
}
// TODO: depthRedCurve/depthGreenCurve/depthBlueCurve — depth-based curves, no URP equivalent.
// blendCurve, mode, selective, keyColor, targetColor unused.
}
private void OnBlinkLightUpdate(LiveTimelineBlinkLightData data, LiveTimelineKeyBlinkLightData keyData)
{
if (keyData == null || _stageController == null) return;
+3
View File
@@ -76,6 +76,9 @@ StageController.cs ← manages stage GameObjects, StageObjectMap
| LightShafts (50) | `LiveTimelineLightShaftsData` | data deserialized, no visual (component absent) |
| Particle (41) | `LiveTimelineParticleData` | sets ParticleSystem.emission.rateOverTime |
| ParticleGroup (42) | `LiveTimelineParticleGroupData` | sets FlickerLightRate |
| ChromaticAberration (73) | `LiveTimelineChromaticAberrationData` | URP `ChromaticAberration.intensity` ← `power`;per-channel offset 无法映射 |
| HdrBloom (38) | `LiveTimelineHdrBloomData` | URP `Bloom.intensity/threshold`;字段未经 bundle 确认 |
| ColorCorrection (61) | `LiveTimelineColorCorrectionData` | URP `ColorAdjustments.saturation` + `ColorCurves` RGB;depth/blend curve 无 URP 对应 |
| BlinkLight | `LiveTimelineBlinkLightData` | SetActive + child Light color/intensity from timeline data (56/58 songs) |
| WashLight | `LiveTimelineWashLightData` | SetActive only — RaycastDistance/CameraProjection fields unused (5/58 songs) |
| Laser | `LiveTimelineLaserData` | SetActive + position/rotation/scale — blink/raycast not implemented (6/58 songs) |