浏览代码

Fixed a lot of bugs on light intensity and emissive mesh updates

- Fix light intensity not updated when light type changes
- Fix light unit with emissive mesh conversion value (do not convert luminance anymore)
- Fix emissive mesh transform changes in timeline
- Fix light intensity not updated when undo/redo

And added color temperature for emissive mesh color
/main
Antoine Lelievre 6 年前
当前提交
21feec05
共有 2 个文件被更改,包括 155 次插入104 次删除
  1. 147
      com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs
  2. 112
      com.unity.render-pipelines.high-definition/HDRP/Lighting/Light/HDAdditionalLightData.cs

147
com.unity.render-pipelines.high-definition/HDRP/Editor/Lighting/HDLightEditor.cs


HDAdditionalLightData[] m_AdditionalLightDatas;
AdditionalShadowData[] m_AdditionalShadowDatas;
// Used to detect if the scale have been changed via the transform component
Vector3 m_OldAreaLightSize;
bool m_UpdateAreaLightEmissiveMesh;
bool m_UpdateAreaLightEmissiveMeshComponents = false;
protected override void OnEnable()
{

edgeToleranceNormal = o.Find(x => x.edgeToleranceNormal),
edgeTolerance = o.Find(x => x.edgeTolerance)
};
// Update emissive mesh and light intensity when undo/redo
Undo.undoRedoPerformed += () => {
foreach (var h in m_AdditionalLightDatas)
h.UpdateAreaLightEmissiveMesh();
};
}
public override void OnInspectorGUI()

CoreEditorUtils.DrawSplitter();
EditorGUILayout.Space();
UpdateAreaLightEmissiveMeshSize();
if (m_UpdateAreaLightEmissiveMesh)
UpdateAreaLightEmissiveMesh();
if (m_UpdateAreaLightEmissiveMeshComponents)
UpdateAreaLightEmissiveMeshComponents();
}
void DrawFoldout(SerializedProperty foldoutProperty, string title, Action func)

if (EditorGUI.EndChangeCheck())
{
UpdateLightIntensityUnit();
m_UpdateAreaLightEmissiveMesh = true;
UpdateLightScale();
m_UpdateAreaLightEmissiveMeshComponents = true;
((Light)target).SetLightDirty(); // Should be apply only to parameter that's affect GI, but make the code cleaner
}
}

m_AdditionalLightData.lightUnit.enumValueIndex = (int)LightUnit.Lumen;
}
bool IsAreaLightShape(LightShape shape)
// Refect light size changes on transform local scale
void UpdateLightScale()
return shape == LightShape.Rectangle || shape == LightShape.Line;
}
void UpdateAreaLightEmissiveMesh()
{
foreach (var lightData in m_AdditionalLightDatas)
foreach (var hdLightData in m_AdditionalLightDatas)
GameObject lightGameObject = lightData.gameObject;
MeshRenderer emissiveMeshRenderer = lightData.GetComponent<MeshRenderer>();
MeshFilter emissiveMeshFilter = lightData.GetComponent<MeshFilter>();
Light light = lightGameObject.GetComponent<Light>();
bool displayAreaLightEmissiveMesh = IsAreaLightShape(m_LightShape) && m_LightShape != LightShape.Line && m_AdditionalLightData.displayAreaLightEmissiveMesh.boolValue;
// Ensure that the emissive mesh components are here
if (displayAreaLightEmissiveMesh)
{
if (emissiveMeshRenderer == null)
emissiveMeshRenderer = lightGameObject.AddComponent<MeshRenderer>();
if (emissiveMeshFilter == null)
emissiveMeshFilter = lightGameObject.AddComponent<MeshFilter>();
}
else // Or remove them if the option is disabled
{
if (emissiveMeshRenderer != null)
DestroyImmediate(emissiveMeshRenderer);
if (emissiveMeshFilter != null)
DestroyImmediate(emissiveMeshFilter);
// Skip to the next light
continue;
}
float areaLightIntensity = 0.0f;
// Update Mesh emissive value
case LightShape.Line:
hdLightData.transform.localScale = new Vector3(m_AdditionalLightData.shapeWidth.floatValue, 0, 0);
break;
emissiveMeshFilter.mesh = HDEditorUtils.LoadAsset< Mesh >("RenderPipelineResources/Quad.FBX");
lightGameObject.transform.localScale = new Vector3(lightData.shapeWidth, lightData.shapeHeight, 0);
// Do the same conversion as for light intensity
areaLightIntensity = LightUtils.ConvertRectLightLumenToLuminance(
m_AdditionalLightData.intensity.floatValue,
lightData.shapeWidth,
lightData.shapeHeight);
hdLightData.transform.localScale = new Vector3(m_AdditionalLightData.shapeWidth.floatValue, m_AdditionalLightData.shapeHeight.floatValue, 0);
default:
case LightShape.Point:
case LightShape.Spot:
hdLightData.transform.localScale = Vector3.one * settings.range.floatValue;
if (emissiveMeshRenderer.sharedMaterial == null)
emissiveMeshRenderer.material = new Material(Shader.Find("HDRenderPipeline/Unlit"));
emissiveMeshRenderer.sharedMaterial.SetColor("_UnlitColor", Color.black);
// Note that we must use the light in linear RGB
emissiveMeshRenderer.sharedMaterial.SetColor("_EmissiveColor", light.color.linear * areaLightIntensity);
}
// This function updates the area light size when the local scale of the gameobject changes
void UpdateAreaLightEmissiveMeshSize()
{
// Early exit if the light type is not an area
if (!IsAreaLightShape(m_LightShape) || target == null || targets.Length > 1)
return ;
Vector3 lightSize = ((Light)target).transform.localScale;
lightSize = Vector3.Max(Vector3.one * k_MinAreaWidth, lightSize);
if (lightSize == m_OldAreaLightSize)
return ;
switch (m_LightShape)
{
case LightShape.Rectangle:
m_AdditionalLightData.shapeWidth.floatValue = lightSize.x;
m_AdditionalLightData.shapeHeight.floatValue = lightSize.y;
break;
default:
break;
}
m_UpdateAreaLightEmissiveMesh = true;
m_OldAreaLightSize = lightSize;
}
LightUnit LightIntensityUnitPopup(LightShape shape)

m_AdditionalLightData.intensity.floatValue = intensity;
}
void UpdateAreaLightEmissiveMeshComponents()
{
foreach (var hdLightData in m_AdditionalLightDatas)
{
hdLightData.UpdateAreaLightEmissiveMesh();
MeshRenderer emissiveMeshRenderer = hdLightData.GetComponent<MeshRenderer>();
MeshFilter emissiveMeshFilter = hdLightData.GetComponent<MeshFilter>();
// If the display emissive mesh is disabled, skip to the next selected light
if (emissiveMeshFilter == null || emissiveMeshRenderer == null)
continue ;
// We only load the mesh and it's material here, because we can't do that inside HDAdditionalLightData (Editor assembly)
// Every other properties of the mesh is updated in HDAdditionalLightData to support timeline and editor records
emissiveMeshFilter.mesh = UnityEditor.Experimental.Rendering.HDPipeline.HDEditorUtils.LoadAsset< Mesh >("RenderPipelineResources/Quad.FBX");
if (emissiveMeshRenderer.sharedMaterial == null)
emissiveMeshRenderer.material = new Material(Shader.Find("HDRenderPipeline/Unlit"));
}
m_UpdateAreaLightEmissiveMeshComponents = false;
}
EditorGUI.BeginChangeCheck();
if (EditorGUI.EndChangeCheck())
m_UpdateAreaLightEmissiveMesh = true;
EditorGUI.BeginChangeCheck();
EditorGUILayout.BeginHorizontal();
EditorGUILayout.PropertyField(m_AdditionalLightData.intensity, s_Styles.lightIntensity);

EditorGUILayout.PropertyField(m_AdditionalLightData.enableSpotReflector, s_Styles.enableSpotReflector);
}
if (EditorGUI.EndChangeCheck())
{
m_UpdateAreaLightEmissiveMesh = true;
}
settings.DrawBounceIntensity();
settings.DrawLightmapping();

// No cookie with area light (maybe in future textured area light ?)
if (!IsAreaLightShape(m_LightShape))
if (!HDAdditionalLightData.IsAreaLight(m_AdditionalLightData.lightTypeExtent))
{
settings.DrawCookie();

EditorGUILayout.PropertyField(m_AdditionalLightData.applyRangeAttenuation, s_Styles.applyRangeAttenuation);
// Emissive mesh for area light only
if (IsAreaLightShape(m_LightShape))
if (HDAdditionalLightData.IsAreaLight(m_AdditionalLightData.lightTypeExtent))
m_UpdateAreaLightEmissiveMesh = true;
m_UpdateAreaLightEmissiveMeshComponents = true;
}
EditorGUI.indentLevel--;

112
com.unity.render-pipelines.high-definition/HDRP/Lighting/Light/HDAdditionalLightData.cs


public bool featuresFoldout = true;
public bool showAdditionalSettings = false;
public float displayLightIntensity;
// Duplication of HDLightEditor.k_MinAreaWidth, maybe do something about that
const float k_MinAreaWidth = 0.01f; // Provide a small size of 1cm for line light
// We nee all those variables to make timeline and the animator record the intensity value
// We nee all those variables to make timeline and the animator record the intensity value and the emissive mesh changes
[System.NonSerialized]
float oldDisplayLightIntensity;
[System.NonSerialized]

[System.NonSerialized]
Color oldLightColor;
[System.NonSerialized]
Vector3 oldLocalScale;
[System.NonSerialized]
bool oldDisplayAreaLightEmissiveMesh;
[System.NonSerialized]
LightTypeExtent oldLightTypeExtent;
[System.NonSerialized]
float oldLightColorTemperature;
// Runtime datas used to compute light intensity
Light _light;

DrawGizmos(true);
}
// TODO: There are a lot of old != current checks and assignation in this function, maybe think about using another system ?
if (oldDisplayLightIntensity != displayLightIntensity)
if (oldDisplayLightIntensity != displayLightIntensity
|| lightTypeExtent != oldLightTypeExtent
|| transform.localScale != oldLocalScale
|| m_Light.colorTemperature != oldLightColorTemperature)
UpdateAreaLightEmissiveMesh();
oldLocalScale = transform.localScale;
}
// Same check for light angle to update intensity using spot angle

oldSpotAngle = m_Light.spotAngle;
oldEnableSpotReflector = enableSpotReflector;
}
if (m_Light.color != oldLightColor
|| transform.localScale != oldLocalScale
|| displayAreaLightEmissiveMesh != oldDisplayAreaLightEmissiveMesh
|| lightTypeExtent != oldLightTypeExtent
|| m_Light.colorTemperature != oldLightColorTemperature)
{
UpdateAreaLightEmissiveMesh();
oldLightColor = m_Light.color;
oldLocalScale = transform.localScale;
oldDisplayAreaLightEmissiveMesh = displayAreaLightEmissiveMesh;
oldLightTypeExtent = lightTypeExtent;
oldLightColorTemperature = m_Light.colorTemperature;
}
public void RefreshLigthIntensity()
void RefreshLigthIntensity()
public static bool IsAreaLight(LightTypeExtent lightType)
{
return lightType != LightTypeExtent.Punctual;
}
public static bool IsAreaLight(SerializedProperty lightType)
{
return IsAreaLight((LightTypeExtent)lightType.enumValueIndex);
}
public void UpdateAreaLightEmissiveMesh()
{
MeshRenderer emissiveMeshRenderer = GetComponent<MeshRenderer>();
MeshFilter emissiveMeshFilter = GetComponent<MeshFilter>();
bool displayEmissiveMesh = IsAreaLight(lightTypeExtent) && lightTypeExtent != LightTypeExtent.Line && displayAreaLightEmissiveMesh;
// Ensure that the emissive mesh components are here
if (displayEmissiveMesh)
{
if (emissiveMeshRenderer == null)
emissiveMeshRenderer = gameObject.AddComponent<MeshRenderer>();
if (emissiveMeshFilter == null)
emissiveMeshFilter = gameObject.AddComponent<MeshFilter>();
}
else // Or remove them if the option is disabled
{
if (emissiveMeshRenderer != null)
DestroyImmediate(emissiveMeshRenderer);
if (emissiveMeshFilter != null)
DestroyImmediate(emissiveMeshFilter);
// We don't have anything to do left if the dislay emissive mesh option is disabled
return ;
}
// Update light area size from GameObject transform scale
Vector3 lightSize = m_Light.transform.localScale;
lightSize = Vector3.Max(Vector3.one * k_MinAreaWidth, lightSize);
m_Light.transform.localScale = lightSize;
float areaLightIntensity = intensity;
switch (lightTypeExtent)
{
case LightTypeExtent.Rectangle:
shapeWidth = lightSize.x;
shapeHeight = lightSize.y;
// If the light unit is in lumen, we need a convertion to get the good intensity value
if (lightUnit == LightUnit.Lumen)
{
areaLightIntensity = LightUtils.ConvertRectLightLumenToLuminance(
intensity,
shapeWidth,
shapeHeight);
}
break;
default:
break;
}
if (emissiveMeshRenderer.sharedMaterial == null)
emissiveMeshRenderer.material = new Material(Shader.Find("HDRenderPipeline/Unlit"));
// Update Mesh emissive properties
emissiveMeshRenderer.sharedMaterial.SetColor("_UnlitColor", Color.black);
// Note that we must use the light in linear RGB
emissiveMeshRenderer.sharedMaterial.SetColor("_EmissiveColor", m_Light.color.linear * areaLightIntensity * CorrelatedColorTemperatureToRGB(m_Light.colorTemperature));
}
#endif
// As we have our own default value, we need to initialize the light intensity correctly

// If we are deserializing an old version, convert the light intensity to the new system
if (version == 1.0f)
{
//TODO: convert dir, punc and area light intensities to intensity field
//TODO: test this
// Pragma to disable the warning got by using deprecated properties (areaIntensity, directionalIntensity, ...)
#pragma warning disable 0618

正在加载...
取消
保存