// SPDX-FileCopyrightText: 2023 Unity Technologies and the glTFast authors // SPDX-License-Identifier: Apache-2.0 using System; using UnityEngine; #if USING_HDRP using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; #endif namespace GLTFast { using Schema; /// /// Extension methods for /// public static class LightPunctualExtension { /// /// Initialize a UnityEngine.Light from a LightsPunctual /// /// light to get data from /// light to initialize /// light intensity conversion factor public static void ToUnityLight(this LightPunctual lightSource, Light lightDestination, float lightIntensityFactor) { switch (lightSource.GetLightType()) { case LightPunctual.Type.Unknown: break; case LightPunctual.Type.Spot: lightDestination.type = LightType.Spot; break; case LightPunctual.Type.Directional: lightDestination.type = LightType.Directional; break; case LightPunctual.Type.Point: lightDestination.type = LightType.Point; break; default: throw new ArgumentOutOfRangeException(); } lightDestination.useColorTemperature = false; lightDestination.color = lightSource.LightColor.gamma; LightAssignIntensity(lightDestination, lightSource, lightIntensityFactor); lightDestination.range = lightSource.range > 0 ? lightSource.range : 100_000; // glTF 2.0 spec says infinite, but float.MaxValue // breaks spot lights in URP. if (lightSource.GetLightType() == LightPunctual.Type.Spot) { lightDestination.spotAngle = lightSource.spot.outerConeAngle * Mathf.Rad2Deg * 2f; lightDestination.innerSpotAngle = lightSource.spot.innerConeAngle * Mathf.Rad2Deg * 2f; #if USING_HDRP && !UNITY_6000_3_OR_NEWER var lightHd = lightDestination.gameObject.GetComponent(); lightHd.SetSpotAngle( lightSource.spot.outerConeAngle * Mathf.Rad2Deg * 2f, 100 * lightSource.spot.innerConeAngle / lightSource.spot.outerConeAngle ); #endif } } /// /// Initialize a LightPunctual from a UnityEngine.Light /// /// light to initialize /// light to get data from /// light intensity conversion factor public static void ToLightPunctual(this Light lightSource, LightPunctual lightDestination, float lightIntensityFactor) { switch (lightSource.type) { case LightType.Spot: lightDestination.SetLightType(LightPunctual.Type.Spot); break; case LightType.Directional: lightDestination.SetLightType(LightPunctual.Type.Directional); break; case LightType.Point: lightDestination.SetLightType(LightPunctual.Type.Point); break; default: throw new ArgumentOutOfRangeException(); } lightDestination.LightColor = lightSource.color; LightAssignIntensity(lightDestination, lightSource, lightIntensityFactor); lightDestination.range = lightSource.range > 0 ? lightSource.range : 100_000; // glTF 2.0 spec says infinite, but float.MaxValue // breaks spot lights in URP. if (lightSource.type == LightType.Spot) { lightDestination.spot = lightDestination.spot ?? new SpotLight(); lightDestination.spot.outerConeAngle = lightSource.spotAngle / Mathf.Rad2Deg * 0.5f; lightDestination.spot.innerConeAngle = lightSource.innerSpotAngle / Mathf.Rad2Deg * 0.5f; } } static void LightAssignIntensity(Light lightDestination, LightPunctual lightSource, float lightIntensityFactor) { var intensity = lightSource.intensity * lightIntensityFactor; var renderPipeline = RenderPipelineUtils.RenderPipeline; switch (renderPipeline) { case RenderPipeline.BuiltIn: lightDestination.intensity = intensity / Mathf.PI; break; case RenderPipeline.Universal: lightDestination.intensity = intensity; break; #if USING_HDRP case RenderPipeline.HighDefinition: var lightUnit = lightSource.GetLightType() == LightPunctual.Type.Directional ? LightUnit.Lux : LightUnit.Candela; #if USING_HDRP_17_OR_NEWER lightDestination.gameObject.AddComponent(); lightDestination.lightUnit = lightUnit; lightDestination.intensity = lightSource.intensity; #else var lightHd = lightDestination.gameObject.AddComponent(); lightHd.lightUnit = lightUnit; lightHd.intensity = lightSource.intensity; #endif break; #endif default: lightDestination.intensity = intensity; break; } } static void LightAssignIntensity(LightPunctual lightDestination, Light lightSource, float lightIntensityFactor) { var intensity = lightSource.intensity / lightIntensityFactor; var renderPipeline = RenderPipelineUtils.RenderPipeline; switch (renderPipeline) { case RenderPipeline.BuiltIn: lightDestination.intensity = intensity * Mathf.PI; break; case RenderPipeline.Universal: lightDestination.intensity = intensity; break; #if USING_HDRP case RenderPipeline.HighDefinition: #if USING_HDRP_17_OR_NEWER lightDestination.intensity = lightSource.intensity; #else if (lightSource.gameObject.TryGetComponent(out HDAdditionalLightData lightHd)) lightDestination.intensity = lightHd.intensity; else lightDestination.intensity = 1; #endif break; #endif default: lightDestination.intensity = intensity; break; } } } }