A game about forced loneliness, made by TACStudios
1#ifndef UNITY_AREA_MRP_INCLUDED
2#define UNITY_AREA_MRP_INCLUDED
3
4// Ref: Moving Frostbite to PBR (Listing 11).
5// Returns the solid angle of a rectangle at the point.
6float SolidAngleRectangle(float3 positionWS, float4x3 lightVerts)
7{
8 float3 v0 = lightVerts[0] - positionWS;
9 float3 v1 = lightVerts[1] - positionWS;
10 float3 v2 = lightVerts[2] - positionWS;
11 float3 v3 = lightVerts[3] - positionWS;
12
13 float3 n0 = normalize(cross(v0, v1));
14 float3 n1 = normalize(cross(v1, v2));
15 float3 n2 = normalize(cross(v2, v3));
16 float3 n3 = normalize(cross(v3, v0));
17
18 float g0 = FastACos(dot(-n0, n1));
19 float g1 = FastACos(dot(-n1, n2));
20 float g2 = FastACos(dot(-n2, n3));
21 float g3 = FastACos(dot(-n3, n0));
22
23 return g0 + g1 + g2 + g3 - TWO_PI;
24}
25
26// Optimized (and approximate) solid angle routine. Doesn't handle the horizon.
27float SolidAngleRightPyramid(float positionWS, float lightPositionWS, float halfWidth, float halfHeight)
28{
29 const float a = halfWidth;
30 const float b = halfHeight;
31 const float h = length(positionWS - lightPositionWS);
32
33 return 4.0 * FastASin(a * b / sqrt (( a * a + h * h) * (b * b + h * h) ));
34}
35
36float FlatAngleSegment(float3 positionWS, float3 lightP1, float3 lightP2)
37{
38 float3 v0 = normalize(lightP1 - positionWS);
39 float3 v1 = normalize(lightP2 - positionWS);
40
41 return FastACos(dot(v0,v1));
42}
43
44// Ref: Moving Frostbite to PBR (Appendix E, Listing E.2)
45// Returns the closest point to a rectangular shape defined by right and up (and the rect extents).
46float3 ClosestPointRectangle(float3 positionWS, float3 planeOrigin, float3 left, float3 up, float halfWidth, float halfHeight)
47{
48 float3 dir = positionWS - planeOrigin;
49
50 // Project into the 2D light plane.
51 float2 dist2D = float2(dot(dir, left), dot(dir, up));
52
53 // Clamp within the rectangle.
54 const float2 halfSize = float2(halfWidth, halfHeight);
55 dist2D = clamp(dist2D, -halfSize, halfSize);
56
57 // Compute the new world position.
58 return planeOrigin + dist2D.x * left + dist2D.y * up;
59}
60
61// Ref: Moving Frostbite to PBR (Listing 13)
62float3 ClosestPointLine(float3 a, float3 b, float3 c)
63{
64 float3 ab = b - a;
65 float t = dot(c - a, ab) / dot(ab, ab);
66 return a + t * ab;
67}
68
69float3 ClosestPointSegment(float3 a, float3 b, float3 c)
70{
71 float3 ab = b - a;
72 float t = dot(c - a, ab) / dot(ab, ab);
73 return a + saturate(t) * ab;
74}
75
76#endif // UNITY_AREA_MRP_INCLUDED