-
Notifications
You must be signed in to change notification settings - Fork 41
/
Copy pathDistantLight.cs
130 lines (110 loc) · 5.1 KB
/
DistantLight.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections.Generic;
using UnityEngine;
namespace Microsoft.MixedReality.GraphicsTools
{
/// <summary>
/// Utility component to animate and visualize a light that can be used with the GraphicsTools/Standard and
/// GraphicsTools/Standard Canvas shaders that have the "_DISTANT_LIGHT" keyword enabled.
///
/// A DistantLight can be used as a replacement for a Unity DirectionalLight. The main purpose of DistantLights is to recreate
/// important light sources for environments, i.e. the sun or moon.
///
/// By default The Graphics Tools/Standard and Graphics Tools/Standard Canvas shaders use the first Unity DirectionalLight
/// added to a scene. But, there are some cases where you need a light that is decoupled from the environment (such as
/// in user interfaces). Unity normally performs this decoupling with light masks. But, light masks can be expensive on some platforms.
/// </summary>
[ExecuteInEditMode]
[AddComponentMenu("Scripts/GraphicsTools/DistantLight")]
public class DistantLight : BaseLight
{
// The Graphics Tools/Standard and Graphics Tools/Standard Canvas shaders supports up to one (1) distant lights.
private const int distantLightCount = 1;
private const int distantLightDataSize = 2;
private static readonly Vector4 invalidLightDirection = new Vector4(0.0f, 0.0f, 1.0f, 0.0f);
private static List<DistantLight> activeDistantLights = new List<DistantLight>(distantLightCount);
private static Vector4[] distantLightData = new Vector4[distantLightDataSize * distantLightCount];
private static int _DistantLightDataID;
private static int lastDistantLightUpdate = -1;
[Tooltip("Specifies the light color.")]
[SerializeField]
private Color color = new Color(255.0f / 255.0f, 244.0f / 255.0f, 214.0f / 255.0f, 1.0f);
/// <summary>
/// Specifies the light color.
/// </summary>
public Color Color
{
get => color;
set => color = value;
}
[Tooltip("Scales the brightness of the light.")]
[SerializeField, Min(0.0f)]
private float intensity = 1.0f;
/// <summary>
/// Scales the brightness of the light.
/// </summary>
public float Intensity
{
get => intensity;
set => intensity = Mathf.Max(0.0f, value);
}
#region BaseLight Implementation
/// <inheritdoc/>
protected override void Initialize()
{
_DistantLightDataID = Shader.PropertyToID("_DistantLightData");
}
/// <inheritdoc/>
protected override void AddLight()
{
if (activeDistantLights.Count == distantLightCount)
{
Debug.LogWarningFormat("Max distant light count {0} exceeded. {1} will not be considered by the Graphics Tools/Standard shader until other lights are removed.", distantLightCount, gameObject.name);
}
activeDistantLights.Add(this);
}
/// <inheritdoc/>
protected override void RemoveLight()
{
activeDistantLights.Remove(this);
}
/// <inheritdoc/>
protected override void UpdateLights(bool forceUpdate = false)
{
if (lastDistantLightUpdate == -1)
{
Initialize();
}
if (!forceUpdate && (Time.frameCount == lastDistantLightUpdate))
{
return;
}
for (int i = 0; i < distantLightCount; ++i)
{
DistantLight light = (i >= activeDistantLights.Count) ? null : activeDistantLights[i];
int dataIndex = i * distantLightDataSize;
if (light)
{
Vector4 direction = -light.transform.forward;
distantLightData[dataIndex] = new Vector4(direction.x,
direction.y,
direction.z,
1.0f);
distantLightData[dataIndex + 1] = new Vector4(light.Color.r * intensity,
light.Color.g * intensity,
light.Color.b * intensity,
1.0f);
}
else
{
distantLightData[dataIndex] = invalidLightDirection;
distantLightData[dataIndex + 1] = Vector4.zero;
}
}
Shader.SetGlobalVectorArray(_DistantLightDataID, distantLightData);
lastDistantLightUpdate = Time.frameCount;
}
#endregion BaseLight Implementation
}
}