Skip to content

Commit 24ec1bc

Browse files
svc-reach-platform-supportEvergreen
authored andcommitted
[Port] [6000.4] [SRP] [UUM-87566] Change SS UI within SRP in HDR output to share a texture resource across all cameras.
1 parent fb2e68c commit 24ec1bc

26 files changed

+700
-77
lines changed

Packages/com.unity.render-pipelines.core/Runtime/Utilities/CoreUtils.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,37 @@ public static DepthBits GetDefaultDepthBufferBits()
19471947
#endif
19481948
}
19491949

1950+
/// <summary>
1951+
/// Indicates whether the combined camera viewports fully cover the screen area.
1952+
/// </summary>
1953+
/// <param name="cameras">List of cameras to render.</param>
1954+
/// <returns>True if the combined camera viewports fully cover the screen area.</returns>
1955+
public static bool IsScreenFullyCoveredByCameras(List<Camera> cameras)
1956+
{
1957+
if (cameras == null || cameras.Count == 0)
1958+
return false;
1959+
1960+
bool isScreenFullyCovered = false;
1961+
using (ListPool<Rect>.Get(out var cameraRects))
1962+
{
1963+
// We don't need to exclude stacked cameras for the input camera list because the overlay camera have the same viewport with its base camera.
1964+
foreach (var camera in cameras)
1965+
{
1966+
if (camera.targetTexture != null || camera.cameraType != CameraType.Game)
1967+
continue;
1968+
1969+
// Skip test if any viewport is full-screen
1970+
if (Mathf.Approximately(camera.rect.xMin, 0f) && Mathf.Approximately(camera.rect.yMin, 0f) && camera.rect.width >= Screen.width && camera.rect.height >= Screen.height)
1971+
return true;
1972+
1973+
cameraRects.Add(camera.rect);
1974+
}
1975+
isScreenFullyCovered = Mathf.Approximately(SweepLineRectUtils.CalculateRectUnionArea(cameraRects), 1f);
1976+
}
1977+
1978+
return isScreenFullyCovered;
1979+
}
1980+
19501981
#if UNITY_EDITOR
19511982
/// <summary>
19521983
/// Populates null fields or collection elements in a target object from a source object of the same type.
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
using System.Buffers;
2+
using System.Collections.Generic;
3+
using Unity.Collections;
4+
5+
namespace UnityEngine.Rendering
6+
{
7+
/// <summary>
8+
/// Utility class that computes the total rect area via a sweep-line.
9+
/// </summary>
10+
public static class SweepLineRectUtils
11+
{
12+
struct EventComparer : IComparer<Vector4>
13+
{
14+
public int Compare(Vector4 a, Vector4 b)
15+
{
16+
int cx = a.x.CompareTo(b.x);
17+
if (cx != 0) return cx;
18+
// tie on x: larger y first (+1 before -1)
19+
return b.y.CompareTo(a.y);
20+
}
21+
}
22+
struct ActiveComparer : IComparer<Vector2>
23+
{
24+
public int Compare(Vector2 a, Vector2 b)
25+
{
26+
return a.x.CompareTo(b.x);
27+
}
28+
}
29+
30+
/// <summary>
31+
/// Computes the total covered area (union) of a set of axis-aligned rectangles, counting overlaps only once.
32+
/// </summary>
33+
/// <param name="rects">List of rects to compute.</param>
34+
/// <returns>The normalized union area in [0,1], with overlaps counted once.</returns>
35+
public static float CalculateRectUnionArea(List<Rect> rects)
36+
{
37+
int rectsCount = rects.Count;
38+
var eventsBuffer = ArrayPool<Vector4>.Shared.Rent(rectsCount * 2);
39+
var activeBuffer = ArrayPool<Vector2>.Shared.Rent(rectsCount);
40+
41+
int eventCount = 0;
42+
foreach (var rect in rects)
43+
InsertEvents(rect, eventsBuffer, ref eventCount);
44+
45+
float area = CalculateRectUnionArea(eventsBuffer, activeBuffer, eventCount);
46+
ArrayPool<Vector4>.Shared.Return(eventsBuffer);
47+
ArrayPool<Vector2>.Shared.Return(activeBuffer);
48+
49+
return area;
50+
}
51+
52+
// Merge overlapping intervals and return total covered Y length
53+
static float MergeLengthY(Vector2[] activeBuffer, int count)
54+
{
55+
if (count <= 0)
56+
return 0f;
57+
58+
// ActiveBuffer stores (yMin, yMax)
59+
float total = 0f;
60+
float cy0 = activeBuffer[0].x;
61+
float cy1 = activeBuffer[0].y;
62+
63+
for (int i = 1; i < count; i++)
64+
{
65+
float y0 = activeBuffer[i].x;
66+
float y1 = activeBuffer[i].y;
67+
if (y0 <= cy1)
68+
{
69+
if (y1 > cy1) cy1 = y1;
70+
}
71+
else
72+
{
73+
total += (cy1 - cy0);
74+
cy0 = y0; cy1 = y1;
75+
}
76+
}
77+
total += (cy1 - cy0);
78+
return Mathf.Clamp01(total);
79+
}
80+
81+
/// <summary>
82+
/// Computes the total covered area (union) of a set of axis-aligned rectangles using a sweep-line.
83+
/// </summary>
84+
static unsafe float CalculateRectUnionArea(Vector4[] eventsBuffer, Vector2[] activeBuffer, int eventCount)
85+
{
86+
if (eventCount == 0)
87+
return 0f;
88+
89+
// Sort events by (x asc, enter first)
90+
fixed (Vector4* ptr = eventsBuffer)
91+
{
92+
NativeSortExtension.Sort(ptr, eventCount, new EventComparer());
93+
}
94+
95+
int activeCount = 0;
96+
float area = 0f;
97+
float lastX = eventsBuffer[0].x;
98+
bool needLastXUpdate = false;
99+
int i = 0;
100+
101+
while (i < eventCount)
102+
{
103+
float x = eventsBuffer[i].x;
104+
105+
if (needLastXUpdate)
106+
{
107+
lastX = x;
108+
needLastXUpdate = false;
109+
}
110+
111+
// Accumulate area over [lastX, x)
112+
float dx = x - lastX;
113+
if (dx > 0f && activeCount > 0)
114+
{
115+
fixed (Vector2* ptr = activeBuffer)
116+
{
117+
NativeSortExtension.Sort(ptr, activeCount, new ActiveComparer());
118+
}
119+
area += MergeLengthY(activeBuffer, activeCount) * dx;
120+
lastX = x;
121+
}
122+
123+
// Consume all events at this x (group approx-equal x's)
124+
do
125+
{
126+
Vector4 ev = eventsBuffer[i];
127+
float y0 = ev.z;
128+
float y1 = ev.w;
129+
130+
if (ev.y > 0f) // Enter
131+
{
132+
activeBuffer[activeCount++] = new Vector2(y0, y1);
133+
}
134+
else // Leave
135+
{
136+
// Remove once (swap with last)
137+
for (int k = 0; k < activeCount; k++)
138+
{
139+
Vector2 v = activeBuffer[k];
140+
if (Mathf.Approximately(v.x, y0) && Mathf.Approximately(v.y, y1))
141+
{
142+
int last = activeCount - 1;
143+
activeBuffer[k] = activeBuffer[last];
144+
activeCount = last;
145+
break;
146+
}
147+
}
148+
149+
if (activeCount == 0)
150+
needLastXUpdate = true;
151+
}
152+
153+
i++;
154+
}
155+
while (i < eventCount && Mathf.Approximately(eventsBuffer[i].x, x));
156+
}
157+
158+
return area;
159+
}
160+
161+
// Insert events with clamped rects
162+
static void InsertEvents(in Rect rect, Vector4[] eventsBuffer, ref int eventCount)
163+
{
164+
if (rect.width > 0f && rect.height > 0f)
165+
{
166+
var y0 = Mathf.Clamp01(rect.yMin);
167+
var y1 = Mathf.Clamp01(rect.yMax);
168+
eventsBuffer[eventCount++] = new Vector4(Mathf.Clamp01(rect.xMin), +1f, y0, y1); // enter
169+
eventsBuffer[eventCount++] = new Vector4(Mathf.Clamp01(rect.xMax), -1f, y0, y1); // leave
170+
}
171+
}
172+
}
173+
}

Packages/com.unity.render-pipelines.core/Runtime/Utilities/SweepLineRectUtils.cs.meta

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)