Files
AR-Menu/Library/PackageCache/com.unity.cloud.gltfast@db5a82ec0b47/Runtime/Scripts/Export/KhrLightsPunctual.cs
2025-11-30 08:35:03 +02:00

233 lines
8.4 KiB
C#

// SPDX-FileCopyrightText: 2024 Unity Technologies and the glTFast authors
// SPDX-License-Identifier: Apache-2.0
using GLTFast.Schema;
using UnityEngine;
#if USING_HDRP
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
#endif
namespace GLTFast.Export
{
/// <summary>
/// Provides conversion from Unity light components to glTF lights.
/// </summary>
public static class KhrLightsPunctual
{
/// <summary>
/// Converts a Unity light component to a glTF light.
/// </summary>
/// <param name="uLight">Unity light component.</param>
/// <returns>glTF light.</returns>
public static LightPunctual ConvertToLight(Light uLight)
{
var light = new LightPunctual
{
name = uLight.name
};
var renderPipeline = RenderPipelineUtils.RenderPipeline;
var lightType = uLight.type;
#if USING_HDRP
HDAdditionalLightData lightHd = null;
if (renderPipeline == RenderPipeline.HighDefinition) {
lightHd = uLight.gameObject.GetComponent<HDAdditionalLightData>();
#if !UNITY_2023_2_OR_NEWER
lightType = lightHd != null ? lightHd.TryGetLightType() ?? lightType : lightType;
#endif
}
#endif
switch (lightType)
{
case LightType.Spot:
light.SetLightType(LightPunctual.Type.Spot);
light.spot = new SpotLight
{
outerConeAngle = uLight.spotAngle * Mathf.Deg2Rad * .5f,
};
#if USING_HDRP && !UNITY_6000_3_OR_NEWER
if (renderPipeline == RenderPipeline.HighDefinition)
{
// Up until Unity 6.2/HDRP 17.2 lightHd.innerSpotPercent was used
// instead of uLight.innerSpotAngle.
light.spot.innerConeAngle = lightHd != null
? uLight.spotAngle * Mathf.Deg2Rad * .5f * lightHd.innerSpotPercent01
: 0;
}
else
#endif
{
light.spot.innerConeAngle = uLight.innerSpotAngle * Mathf.Deg2Rad * .5f;
}
break;
case LightType.Directional:
light.SetLightType(LightPunctual.Type.Directional);
break;
case LightType.Point:
light.SetLightType(LightPunctual.Type.Point);
break;
case LightType.Rectangle:
case LightType.Disc:
default:
light.SetLightType(LightPunctual.Type.Spot);
light.spot = new SpotLight
{
outerConeAngle = 45 * Mathf.Deg2Rad * .5f,
innerConeAngle = 35 * Mathf.Deg2Rad * .5f
};
break;
}
light.LightColor = uLight.color.linear;
light.range = GetLightRange(uLight, lightType);
// Set Light intensity
switch (renderPipeline)
{
case RenderPipeline.BuiltIn:
light.intensity = uLight.intensity * Mathf.PI;
break;
case RenderPipeline.Universal:
light.intensity = uLight.intensity;
break;
#if USING_HDRP
case RenderPipeline.HighDefinition:
if (lightHd == null)
{
light.intensity = uLight.intensity;
}
else
{
#if UNITY_2023_2_OR_NEWER
switch (lightType)
{
case LightType.Spot:
case LightType.Point:
#if RENDER_PIPELINES_CORE_17_OR_NEWER
light.intensity = LightUnitUtils.ConvertIntensity(uLight, uLight.intensity, uLight.lightUnit, LightUnit.Candela);
#else
light.intensity = GetIntensity(LightUnit.Candela);
#endif
break;
case LightType.Directional:
#if RENDER_PIPELINES_CORE_17_OR_NEWER
light.intensity = LightUnitUtils.ConvertIntensity(uLight, uLight.intensity, uLight.lightUnit, LightUnit.Lux);
#else
light.intensity = GetIntensity(LightUnit.Lux);
#endif
break;
case LightType.Rectangle:
default:
light.intensity = uLight.intensity;
break;
}
#else
switch (lightHd.type) {
case HDLightType.Spot:
case HDLightType.Point:
light.intensity = GetIntensity(LightUnit.Candela);
break;
case HDLightType.Directional:
light.intensity = GetIntensity(LightUnit.Lux);
break;
case HDLightType.Area:
default:
light.intensity = uLight.intensity;
break;
}
#endif
}
break;
#if !RENDER_PIPELINES_CORE_17_OR_NEWER
float GetIntensity(LightUnit unit)
{
#if UNITY_2023_3_OR_NEWER
if (uLight.lightUnit == unit)
{
return uLight.intensity;
}
// Workaround to get intensity in candela
var oldUnit = uLight.lightUnit;
uLight.lightUnit = unit;
var result = uLight.intensity;
uLight.lightUnit = oldUnit;
return result;
#else
if (lightHd.lightUnit == unit)
{
return lightHd.intensity;
}
// Workaround to get intensity in candela
var oldUnit = lightHd.lightUnit;
lightHd.lightUnit = unit;
var result = lightHd.intensity;
lightHd.lightUnit = oldUnit;
return result;
#endif
}
#endif // !RENDER_PIPELINES_CORE_17_OR_NEWER
#endif // USING_HDRP
default:
light.intensity = uLight.intensity;
break;
}
return light;
}
/// <summary>
/// Retrieves the light's range.
/// In Unity 2023.1 and older `Light.range` would return what now is <see cref="Light.dilatedRange"/>, which is
/// the range extended by a certain area light size factor. This method removes that addition in that case to
/// get the original value that's shown in the inspector.
/// </summary>
/// <param name="light">Unity Light</param>
/// <param name="lightType">Actual light type (might differ from light.type in HDRP).</param>
/// <returns>The light's range.</returns>
static float GetLightRange(Light light, LightType lightType)
{
#if UNITY_2023_2_OR_NEWER
return light.range;
#else
var range = light.range;
switch (lightType)
{
#if !USING_HDRP // And, of course, it behaves correctly in the particular case HDRP+Rectangle.
case LightType.Rectangle:
#if UNITY_EDITOR
var longestSide = light.areaSize.magnitude;
#else
// At runtime, assume default magnitude(vec2(1,1))
var longestSide = 1.4142135624f;
#endif
range -= longestSide * .5f;
break;
#endif // !USING_HDRP
case LightType.Disc:
#if UNITY_EDITOR
var radius = light.areaSize.x;
#else
// At runtime, assume default
const float radius = 1f;
#endif
range -= radius * .5f;
break;
}
return range;
#endif
}
}
}