Skip to content

Commit d50ccb1

Browse files
Improved Area Light Config (#238)
1 parent bfaaab0 commit d50ccb1

7 files changed

Lines changed: 190 additions & 110 deletions

File tree

com.microsoft.mrtk.graphicstools.unity/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file.
44

55
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
66

7+
## [0.8.4] - 2025-04-03
8+
9+
### Changed
10+
11+
- Added more properties to the experimental AreaLight component.
12+
713
## [0.8.3] - 2025-03-26
814

915
### Changed

com.microsoft.mrtk.graphicstools.unity/Editor/Experimental/AreaLight/AreaLightInspector.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ private void OnSceneGUI()
4141
// Draw the area light's normal only if it will not overlap with the current tool.
4242
if (!((Tools.current == Tool.Move || Tools.current == Tool.Scale) && Tools.pivotRotation == PivotRotation.Local))
4343
{
44-
Handles.DrawLine(light.transform.position, light.transform.position + light.transform.forward);
44+
var normal = light.transform.forward * ((light.Facing == AreaLight.ForwardFacing.PositiveZ) ? 1.0f : -1.0f);
45+
Handles.DrawLine(light.transform.position, light.transform.position + normal);
4546
}
4647

4748
Handles.color = new Color(255.0f / 255.0f, 165.0f / 255.0f, 0.0f / 255.0f); // Orange.

com.microsoft.mrtk.graphicstools.unity/Runtime/Experimental/AreaLight/AreaLight.cs

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,20 +21,23 @@ public partial class AreaLight : BaseLight, IComparable<AreaLight>
2121
private static readonly float[,] offsets = new float[4, 2] { { 1, 1 }, { 1, -1 }, { -1, -1 }, { -1, 1 } };
2222
private const int lutResolution = 64;
2323
private const int lutMatrixDim = 3;
24+
private static readonly Matrix4x4 rotation180Up = Matrix4x4.Rotate(Quaternion.AngleAxis(180.0f, Vector3.up));
2425

2526
private static Texture2D transformInvTextureSpecular;
2627
private static Texture2D transformInvTextureDiffuse;
2728
private static Texture2D ampDiffAmpSpecFresnel;
2829

30+
private static int lastAreaLightUpdate = -1;
2931
private static List<AreaLight> activeAreaLights = new(maxAreaLights);
3032
private static List<AreaLight> activeAreaLightsSorted = new(maxAreaLights);
3133
private static Vector4[] areaLightData = new Vector4[areaLightDataSize * areaLightCount];
3234
private static Matrix4x4[] areaLightVerts = new Matrix4x4[areaLightCount];
3335
private static Texture[] areaLightCookies = new Texture[areaLightCount];
34-
private static int _AreaLightDataID;
35-
private static int _AreaLightVertsID;
36-
private static int[] _AreaLightCookiesIDs = new int[areaLightCount];
37-
private static int lastAreaLightUpdate = -1;
36+
private static int areaLightDataID;
37+
private static int areaLightVertsID;
38+
private static int[] areaLightCookiesIDs = new int[areaLightCount];
39+
private static int facingID;
40+
private static int uvStartsAtTopID;
3841
private static CullingGroup cullingGroup;
3942
private static BoundingSphere[] boundingSpheres = new BoundingSphere[maxAreaLights];
4043

@@ -89,6 +92,25 @@ public Vector2 Size
8992
set => size = value;
9093
}
9194

95+
public enum ForwardFacing
96+
{
97+
PositiveZ,
98+
NegativeZ,
99+
}
100+
101+
[Tooltip("The forward direction of the light.")]
102+
[SerializeField]
103+
private ForwardFacing facing = ForwardFacing.PositiveZ;
104+
105+
/// <summary>
106+
/// The forward direction of the light.
107+
/// </summary>
108+
public ForwardFacing Facing
109+
{
110+
get => facing;
111+
set => facing = value;
112+
}
113+
92114
[Tooltip("Optional texture to use instead of a solid color.")]
93115
[SerializeField]
94116
private Texture cookie;
@@ -102,6 +124,19 @@ public Texture Cookie
102124
set => cookie = value;
103125
}
104126

127+
[Tooltip("Should the texture UV coordinate convention for this cookie have Y starting at the top of the image.")]
128+
[SerializeField]
129+
private bool cookieUVStartsAtTop = true;
130+
131+
/// <summary>
132+
/// Should the texture UV coordinate convention for this cookie have Y starting at the top of the image.
133+
/// </summary>
134+
public bool CookieUVStartsAtTop
135+
{
136+
get => cookieUVStartsAtTop;
137+
set => cookieUVStartsAtTop = value;
138+
}
139+
105140
[Tooltip("Should the area light have a visualization?")]
106141
[SerializeField]
107142
private bool drawLightSource = true;
@@ -215,14 +250,17 @@ public Camera CullingGroupCamera
215250
/// <inheritdoc/>
216251
protected override void Initialize()
217252
{
218-
_AreaLightDataID = Shader.PropertyToID("_AreaLightData");
219-
_AreaLightVertsID = Shader.PropertyToID("_AreaLightVerts");
253+
areaLightDataID = Shader.PropertyToID("_AreaLightData");
254+
areaLightVertsID = Shader.PropertyToID("_AreaLightVerts");
220255

221-
for (int i = 0; i < _AreaLightCookiesIDs.Length; ++i)
256+
for (int i = 0; i < areaLightCookiesIDs.Length; ++i)
222257
{
223-
_AreaLightCookiesIDs[i] = Shader.PropertyToID($"_AreaLightCookie{i}");
258+
areaLightCookiesIDs[i] = Shader.PropertyToID($"_AreaLightCookie{i}");
224259
}
225260

261+
facingID = Shader.PropertyToID("_facing");
262+
uvStartsAtTopID = Shader.PropertyToID("_uvStartsAtTop");
263+
226264
CreateLUTs();
227265
UpdateLightSourceVisual();
228266

@@ -362,18 +400,23 @@ protected override void UpdateLights(bool forceUpdate = false)
362400

363401
if (light)
364402
{
365-
areaLightData[dataIndex] = light.Color;
403+
var color = light.Color;
404+
areaLightData[dataIndex] = new Vector4(color.r,
405+
color.g,
406+
color.b,
407+
light.cookieUVStartsAtTop ? 1.0f : 0.0f);
408+
409+
var lightVerts = new Matrix4x4();
410+
var localToWorld = light.transform.localToWorldMatrix;
366411

367-
// A little bit of bias to prevent the light from lighting itself.
368-
const float z = 0.01f;
412+
if (light.facing == ForwardFacing.NegativeZ)
413+
{
414+
localToWorld *= rotation180Up;
415+
}
369416

370-
Matrix4x4 lightVerts = new Matrix4x4();
371417
for (int v = 0; v < 4; ++v)
372418
{
373-
Vector3 vertex = new Vector3(light.size.x * offsets[v, 0],
374-
light.size.y * offsets[v, 1],
375-
z) * 0.5f;
376-
lightVerts.SetRow(v, light.transform.TransformPoint(vertex));
419+
lightVerts.SetRow(v, TransformVertex(v, light.size, localToWorld));
377420
}
378421

379422
areaLightVerts[i] = lightVerts;
@@ -397,13 +440,13 @@ protected override void UpdateLights(bool forceUpdate = false)
397440
}
398441
}
399442

400-
Shader.SetGlobalVectorArray(_AreaLightDataID, areaLightData);
401-
Shader.SetGlobalMatrixArray(_AreaLightVertsID, areaLightVerts);
443+
Shader.SetGlobalVectorArray(areaLightDataID, areaLightData);
444+
Shader.SetGlobalMatrixArray(areaLightVertsID, areaLightVerts);
402445

403446
// There is no SetGlobalTextureArray so pass in 1 by 1.
404447
for (int i = 0; i < areaLightCookies.Length; ++i)
405448
{
406-
Shader.SetGlobalTexture(_AreaLightCookiesIDs[i], areaLightCookies[i]);
449+
Shader.SetGlobalTexture(areaLightCookiesIDs[i], areaLightCookies[i]);
407450
}
408451

409452
lastAreaLightUpdate = Time.frameCount;
@@ -467,6 +510,18 @@ private void OnDrawGizmos()
467510
}
468511
#endif
469512

513+
private static Vector3 TransformVertex(int index, Vector2 size, Matrix4x4 localToWorld)
514+
{
515+
// A little bit of bias to prevent the light from lighting itself.
516+
const float z = 0.01f;
517+
518+
var vertex = new Vector3(size.x * offsets[index, 0],
519+
size.y * offsets[index, 1],
520+
z) * 0.5f;
521+
522+
return localToWorld.MultiplyPoint(vertex);
523+
}
524+
470525
private static void CreateLUTs()
471526
{
472527
if (transformInvTextureDiffuse == null)
@@ -506,6 +561,8 @@ private void UpdateLightSourceVisual()
506561

507562
lightSourceVisual.sharedMaterial.color = Color;
508563
lightSourceVisual.sharedMaterial.mainTexture = drawLightSourceCookie ? drawLightSourceCookie : cookie;
564+
lightSourceVisual.sharedMaterial.SetFloat(facingID, (float)facing);
565+
lightSourceVisual.sharedMaterial.SetFloat(uvStartsAtTopID, cookieUVStartsAtTop ? 0.0f : 1.0f);
509566
lightSourceVisual.transform.localScale = new Vector3(size.x, size.y, 1.0f);
510567
}
511568
else

com.microsoft.mrtk.graphicstools.unity/Runtime/Experimental/AreaLight/AreaLightCookieFilter.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public Material CookieFilterMaterial
5959

6060
[Tooltip("How many blur passes to perform during Dual blurring.")]
6161
[SerializeField]
62-
[Range(2, 7)]
62+
[Range(0, 7)]
6363
private int blurPasses = 3;
6464

6565
/// <summary>
@@ -68,7 +68,7 @@ public Material CookieFilterMaterial
6868
public int BlurPasses
6969
{
7070
get => blurPasses;
71-
set => blurPasses = Mathf.Clamp(value, 2, 7);
71+
set => blurPasses = Mathf.Clamp(value, 0, 7);
7272
}
7373

7474
/// <summary>

0 commit comments

Comments
 (0)