226 lines
8.7 KiB
C#
226 lines
8.7 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UnityEngine.Rendering.HighDefinition
|
|
{
|
|
/// <summary>
|
|
/// Class controlling which sky is used for static and baked lighting.
|
|
/// </summary>
|
|
[HelpURL(Documentation.baseURL + Documentation.version + Documentation.subURL + "Static-Lighting-Sky" + Documentation.endURL)]
|
|
[ExecuteAlways]
|
|
[AddComponentMenu("")] // Hide this object from the Add Component menu
|
|
public class StaticLightingSky : MonoBehaviour
|
|
{
|
|
[SerializeField]
|
|
VolumeProfile m_Profile;
|
|
[SerializeField, FormerlySerializedAs("m_BakingSkyUniqueID")]
|
|
int m_StaticLightingSkyUniqueID = 0;
|
|
int m_LastComputedHash;
|
|
bool m_NeedUpdateStaticLightingSky;
|
|
|
|
SkySettings m_SkySettings; // This one contain only property values from overridden properties in the original profile component
|
|
SkySettings m_SkySettingsFromProfile;
|
|
|
|
internal SkySettings skySettings
|
|
{
|
|
get
|
|
{
|
|
GetSkyFromIDAndVolume(m_StaticLightingSkyUniqueID, m_Profile, out var skyFromProfile, out var skyType);
|
|
if (skyFromProfile != null)
|
|
{
|
|
int newHash = skyFromProfile.GetHashCode();
|
|
if (m_LastComputedHash != newHash)
|
|
UpdateCurrentStaticLightingSky();
|
|
}
|
|
else
|
|
{
|
|
ResetSky();
|
|
}
|
|
return m_SkySettings;
|
|
}
|
|
}
|
|
|
|
List<SkySettings> m_VolumeSkyList = new List<SkySettings>();
|
|
|
|
|
|
/// <summary>
|
|
/// Volume profile where the sky settings used for static lighting will be fetched.
|
|
/// </summary>
|
|
public VolumeProfile profile
|
|
{
|
|
get
|
|
{
|
|
return m_Profile;
|
|
}
|
|
set
|
|
{
|
|
if (value != m_Profile)
|
|
{
|
|
// Changing the volume is considered a destructive operation => reset the static lighting sky.
|
|
m_StaticLightingSkyUniqueID = 0;
|
|
|
|
//Registration is also done when we go from null to not null
|
|
if (m_Profile == null)
|
|
SkyManager.RegisterStaticLightingSky(this);
|
|
|
|
//Unregistration is also done when we go from not null to null
|
|
if (value == null)
|
|
SkyManager.UnRegisterStaticLightingSky(this);
|
|
}
|
|
|
|
m_Profile = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Unique ID of the sky used for static lighting.
|
|
/// The unique ID should be for a sky that is present in the profile. See SkySettings.GetUniqueID to get the ID per sky type.
|
|
/// </summary>
|
|
public int staticLightingSkyUniqueID
|
|
{
|
|
get
|
|
{
|
|
return m_StaticLightingSkyUniqueID;
|
|
}
|
|
set
|
|
{
|
|
m_StaticLightingSkyUniqueID = value;
|
|
UpdateCurrentStaticLightingSky();
|
|
}
|
|
}
|
|
|
|
void GetSkyFromIDAndVolume(int skyUniqueID, VolumeProfile profile, out SkySettings skySetting, out System.Type skyType)
|
|
{
|
|
skySetting = null;
|
|
skyType = typeof(SkySettings);
|
|
if (profile != null && skyUniqueID != 0)
|
|
{
|
|
m_VolumeSkyList.Clear();
|
|
if (profile.TryGetAllSubclassOf<SkySettings>(typeof(SkySettings), m_VolumeSkyList))
|
|
{
|
|
foreach (var sky in m_VolumeSkyList)
|
|
{
|
|
if (skyUniqueID == SkySettings.GetUniqueID(sky.GetType()) && sky.active)
|
|
{
|
|
skyType = sky.GetType();
|
|
skySetting = sky;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void UpdateCurrentStaticLightingSky()
|
|
{
|
|
// First, grab the sky settings of the right type in the profile.
|
|
CoreUtils.Destroy(m_SkySettings);
|
|
m_SkySettings = null;
|
|
m_LastComputedHash = 0;
|
|
GetSkyFromIDAndVolume(m_StaticLightingSkyUniqueID, m_Profile, out m_SkySettingsFromProfile, out var skyType);
|
|
|
|
if (m_SkySettingsFromProfile != null)
|
|
{
|
|
// The static lighting sky is a Volume Component that lives outside of the volume system (we just grab a component from a profile)
|
|
// As such, it may contain values that are not actually overridden
|
|
// For example, user overrides a value, change it, and disable overrides. In this case the volume still contains the old overridden value
|
|
// In this case, we want to use values only if they are still overridden, so we create a volume component with default values and then copy the overridden values from the profile.
|
|
// Also, a default profile might be set in the HDRP project settings, this volume is applied by default to all the scene so it should also be taken into account here.
|
|
|
|
// Create an instance with default values
|
|
m_SkySettings = (SkySettings)ScriptableObject.CreateInstance(skyType);
|
|
var newSkyParameters = m_SkySettings.parameters;
|
|
var profileSkyParameters = m_SkySettingsFromProfile.parameters;
|
|
|
|
var defaultVolume = HDRenderPipeline.GetOrCreateDefaultVolume();
|
|
SkySettings defaultSky = null;
|
|
if (defaultVolume.sharedProfile != null) // This can happen with old projects.
|
|
defaultVolume.sharedProfile.TryGet(skyType, out defaultSky);
|
|
var defaultSkyParameters = defaultSky != null ? defaultSky.parameters : null; // Can be null if the profile does not contain the component.
|
|
|
|
// Seems to inexplicably happen sometimes on domain reload.
|
|
if (profileSkyParameters == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int parameterCount = m_SkySettings.parameters.Count;
|
|
// Copy overridden parameters.
|
|
for (int i = 0; i < parameterCount; ++i)
|
|
{
|
|
if (profileSkyParameters[i].overrideState == true)
|
|
{
|
|
newSkyParameters[i].SetValue(profileSkyParameters[i]);
|
|
}
|
|
// Fallback to the default profile if values are overridden in there.
|
|
else if (defaultSkyParameters != null && defaultSkyParameters[i].overrideState == true)
|
|
{
|
|
newSkyParameters[i].SetValue(defaultSkyParameters[i]);
|
|
}
|
|
}
|
|
|
|
m_LastComputedHash = m_SkySettingsFromProfile.GetHashCode();
|
|
}
|
|
}
|
|
|
|
// All actions done in this method are because Editor won't go through setters so we need to manually check consistency of our data.
|
|
void OnValidate()
|
|
{
|
|
if (!isActiveAndEnabled)
|
|
return;
|
|
|
|
// If we detect that the profile has been removed we need to reset the static lighting sky.
|
|
if (m_Profile == null)
|
|
{
|
|
m_StaticLightingSkyUniqueID = 0;
|
|
}
|
|
|
|
// If we detect that the profile has changed, we need to reset the static lighting sky.
|
|
// We have to do that manually because PropertyField won't go through setters.
|
|
if (profile != null && m_SkySettingsFromProfile != null)
|
|
{
|
|
if (!profile.components.Find(x => x == m_SkySettingsFromProfile))
|
|
{
|
|
m_StaticLightingSkyUniqueID = 0;
|
|
}
|
|
}
|
|
|
|
// We can't call UpdateCurrentStaticLightingSky in OnValidate because we may destroy an object there and it's forbidden.
|
|
// So we delay the update.
|
|
m_NeedUpdateStaticLightingSky = true;
|
|
}
|
|
|
|
void OnEnable()
|
|
{
|
|
UpdateCurrentStaticLightingSky();
|
|
if (m_Profile != null)
|
|
SkyManager.RegisterStaticLightingSky(this);
|
|
}
|
|
|
|
void OnDisable()
|
|
{
|
|
if (m_Profile != null)
|
|
SkyManager.UnRegisterStaticLightingSky(this);
|
|
|
|
ResetSky();
|
|
}
|
|
|
|
void Update()
|
|
{
|
|
if (m_NeedUpdateStaticLightingSky)
|
|
{
|
|
UpdateCurrentStaticLightingSky();
|
|
m_NeedUpdateStaticLightingSky = false;
|
|
}
|
|
}
|
|
|
|
void ResetSky()
|
|
{
|
|
CoreUtils.Destroy(m_SkySettings);
|
|
m_SkySettings = null;
|
|
m_SkySettingsFromProfile = null;
|
|
m_LastComputedHash = 0;
|
|
}
|
|
}
|
|
}
|