您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
218 行
8.6 KiB
218 行
8.6 KiB
#if UNITY_EDITOR
|
|
using UnityEditor;
|
|
using UnityEditor.Experimental.Rendering.HDPipeline;
|
|
#endif
|
|
using UnityEngine.Serialization;
|
|
|
|
namespace UnityEngine.Experimental.Rendering.HDPipeline
|
|
{
|
|
// This enum extent the original LightType enum with new light type from HD
|
|
public enum LightTypeExtent
|
|
{
|
|
Punctual, // Fallback on LightShape type
|
|
Rectangle,
|
|
Line,
|
|
// Sphere,
|
|
// Disc,
|
|
};
|
|
|
|
public enum SpotLightShape { Cone, Pyramid, Box };
|
|
|
|
//@TODO: We should continuously move these values
|
|
// into the engine when we can see them being generally useful
|
|
[RequireComponent(typeof(Light))]
|
|
public class HDAdditionalLightData : MonoBehaviour
|
|
{
|
|
#pragma warning disable 414 // CS0414 The private field '...' is assigned but its value is never used
|
|
// We can't rely on Unity for our additional data, we need to version it ourself.
|
|
[SerializeField]
|
|
float m_Version = 1.0f;
|
|
#pragma warning restore 414
|
|
|
|
// To be able to have correct default values for our lights and to also control the conversion of intensity from the light editor (so it is compatible with GI)
|
|
// we add intensity (for each type of light we want to manage).
|
|
public float directionalIntensity = Mathf.PI; // In Lux
|
|
public float punctualIntensity = 600.0f; // Light default to 600 lumen, i.e ~48 candela
|
|
public float areaIntensity = 200.0f; // Light default to 200 lumen to better match point light
|
|
|
|
[Range(0.0f, 100.0f)]
|
|
public float m_InnerSpotPercent = 0.0f; // To display this field in the UI this need to be public
|
|
|
|
public float GetInnerSpotPercent01()
|
|
{
|
|
return Mathf.Clamp(m_InnerSpotPercent, 0.0f, 100.0f) / 100.0f;
|
|
}
|
|
|
|
[Range(0.0f, 1.0f)]
|
|
public float lightDimmer = 1.0f;
|
|
|
|
// Not used for directional lights.
|
|
public float fadeDistance = 10000.0f;
|
|
|
|
public bool affectDiffuse = true;
|
|
public bool affectSpecular = true;
|
|
|
|
public LightTypeExtent lightTypeExtent = LightTypeExtent.Punctual;
|
|
|
|
// Only for Spotlight, should be hide for other light
|
|
public SpotLightShape spotLightShape = SpotLightShape.Cone;
|
|
|
|
// Only for Rectangle/Line/box projector lights
|
|
public float shapeWidth = 0.5f;
|
|
|
|
// Only for Rectangle/box projector lights
|
|
public float shapeHeight = 0.5f;
|
|
|
|
// Only for pyramid projector
|
|
public float aspectRatio = 1.0f;
|
|
|
|
// Only for Sphere/Disc
|
|
public float shapeRadius = 0.0f;
|
|
|
|
// Only for Spot/Point - use to cheaply fake specular spherical area light
|
|
[Range(0.0f, 1.0f)]
|
|
public float maxSmoothness = 1.0f;
|
|
|
|
// If true, we apply the smooth attenuation factor on the range attenuation to get 0 value, else the attenuation is just inverse square and never reach 0
|
|
public bool applyRangeAttenuation = true;
|
|
|
|
// This is specific for the LightEditor GUI and not use at runtime
|
|
public bool useOldInspector = false;
|
|
public bool featuresFoldout = true;
|
|
public bool showAdditionalSettings = false;
|
|
|
|
#if UNITY_EDITOR
|
|
|
|
private void DrawGizmos(bool selected)
|
|
{
|
|
var light = gameObject.GetComponent<Light>();
|
|
var gizmoColor = light.color;
|
|
gizmoColor.a = selected ? 1.0f : 0.3f; // Fade for the gizmo
|
|
Gizmos.color = Handles.color = gizmoColor;
|
|
|
|
if (lightTypeExtent == LightTypeExtent.Punctual)
|
|
{
|
|
switch (light.type)
|
|
{
|
|
case LightType.Directional:
|
|
HDLightEditorUtilities.DrawDirectionalLightGizmo(light);
|
|
break;
|
|
case LightType.Point:
|
|
HDLightEditorUtilities.DrawPointlightGizmo(light, selected);
|
|
break;
|
|
case LightType.Spot:
|
|
if (spotLightShape == SpotLightShape.Cone)
|
|
HDLightEditorUtilities.DrawSpotlightGizmo(light, selected);
|
|
else if (spotLightShape == SpotLightShape.Pyramid)
|
|
HDLightEditorUtilities.DrawFrustumlightGizmo(light);
|
|
else if (spotLightShape == SpotLightShape.Box)
|
|
HDLightEditorUtilities.DrawFrustumlightGizmo(light);
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (lightTypeExtent)
|
|
{
|
|
case LightTypeExtent.Rectangle:
|
|
HDLightEditorUtilities.DrawArealightGizmo(light);
|
|
break;
|
|
case LightTypeExtent.Line:
|
|
HDLightEditorUtilities.DrawArealightGizmo(light);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (selected)
|
|
{
|
|
DrawVerticalRay();
|
|
}
|
|
}
|
|
|
|
// Trace a ray down to better locate the light location
|
|
private void DrawVerticalRay()
|
|
{
|
|
Ray ray = new Ray(transform.position, Vector3.down);
|
|
RaycastHit hit;
|
|
if (Physics.Raycast(ray, out hit))
|
|
{
|
|
Handles.color = Color.green;
|
|
Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
|
|
Handles.DrawLine(transform.position, hit.point);
|
|
Handles.DrawWireDisc(hit.point, hit.normal, 0.5f);
|
|
|
|
Handles.color = Color.red;
|
|
Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
|
|
Handles.DrawLine(transform.position, hit.point);
|
|
Handles.DrawWireDisc(hit.point, hit.normal, 0.5f);
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
// DrawGizmos(false);
|
|
}
|
|
|
|
private void OnDrawGizmosSelected()
|
|
{
|
|
DrawGizmos(true);
|
|
}
|
|
#endif
|
|
|
|
// Caution: this function must match the one in HDLightEditor.UpdateLightIntensity - any change need to be replicated
|
|
public void ConvertPhysicalLightIntensityToLightIntensity()
|
|
{
|
|
var light = gameObject.GetComponent<Light>();
|
|
|
|
if (lightTypeExtent == LightTypeExtent.Punctual)
|
|
{
|
|
switch (light.type)
|
|
{
|
|
case LightType.Directional:
|
|
light.intensity = directionalIntensity;
|
|
break;
|
|
|
|
case LightType.Point:
|
|
light.intensity = LightUtils.ConvertPointLightIntensity(punctualIntensity);
|
|
break;
|
|
|
|
case LightType.Spot:
|
|
// Spot should used conversion which take into account the angle, and thus the intensity vary with angle.
|
|
// This is not easy to manipulate for lighter, so we simply consider any spot light as just occluded point light. So reuse the same code.
|
|
light.intensity = LightUtils.ConvertPointLightIntensity(punctualIntensity);
|
|
// TODO: What to do with box shape ?
|
|
// var spotLightShape = (SpotLightShape)m_AdditionalspotLightShape.enumValueIndex;
|
|
break;
|
|
|
|
}
|
|
}
|
|
else if (lightTypeExtent == LightTypeExtent.Rectangle)
|
|
{
|
|
light.intensity = LightUtils.ConvertRectLightIntensity(areaIntensity, shapeWidth, shapeHeight);
|
|
}
|
|
else if (lightTypeExtent == LightTypeExtent.Line)
|
|
{
|
|
light.intensity = LightUtils.CalculateLineLightIntensity(areaIntensity, shapeWidth);
|
|
}
|
|
}
|
|
|
|
// As we have our own default value, we need to initialize the light intensity correctly
|
|
public static void InitDefaultHDAdditionalLightData(HDAdditionalLightData lightData)
|
|
{
|
|
// At first init we need to initialize correctly the default value
|
|
lightData.ConvertPhysicalLightIntensityToLightIntensity();
|
|
|
|
// Special treatment for Unity builtin area light. Change it to our rectangle light
|
|
|
|
var light = lightData.gameObject.GetComponent<Light>();
|
|
|
|
// Sanity check: lightData.lightTypeExtent is init to LightTypeExtent.Punctual (in case for unknow reasons we recreate additional data on an existing line)
|
|
if (light.type == LightType.Area && lightData.lightTypeExtent == LightTypeExtent.Punctual)
|
|
{
|
|
lightData.lightTypeExtent = LightTypeExtent.Rectangle;
|
|
light.type = LightType.Point; // Same as in HDLightEditor
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|