summaryrefslogtreecommitdiff
path: root/GameCode/SFLight.cs
diff options
context:
space:
mode:
authorchai <215380520@qq.com>2023-10-27 11:05:14 +0800
committerchai <215380520@qq.com>2023-10-27 11:05:14 +0800
commit766cdff5ffa72b65d7f106658d1603f47739b2ba (patch)
tree34d7799a94dfa9be182825577583c0fa6dc935f7 /GameCode/SFLight.cs
+ init
Diffstat (limited to 'GameCode/SFLight.cs')
-rw-r--r--GameCode/SFLight.cs350
1 files changed, 350 insertions, 0 deletions
diff --git a/GameCode/SFLight.cs b/GameCode/SFLight.cs
new file mode 100644
index 0000000..8ff6e38
--- /dev/null
+++ b/GameCode/SFLight.cs
@@ -0,0 +1,350 @@
+using System.Collections.Generic;
+using UnityEngine;
+
+[RequireComponent(typeof(RectTransform))]
+public class SFLight : MonoBehaviour
+{
+ private class VertexArray
+ {
+ public int capacity;
+
+ public int size;
+
+ public Vector3[] verts;
+
+ public Vector4[] tangents;
+
+ public Vector2[] uvs;
+
+ public int[] tris;
+
+ public VertexArray(int segments)
+ {
+ capacity = segments;
+ size = 0;
+ verts = new Vector3[segments * 4];
+ tangents = new Vector4[segments * 4];
+ uvs = new Vector2[segments * 4];
+ tris = new int[segments * 6];
+ }
+ }
+
+ [Tooltip("The radius of the light source. Larger lights cast softer shadows.")]
+ public float _radius = 0.5f;
+
+ [Tooltip("The brightness of the light. (Ignored when using non-linear light blending.) Allows for colors brighter than 1.0 in HDR lighting situations.")]
+ public float _intensity = 1f;
+
+ [Tooltip("The color of the light.")]
+ public Color _color = Color.white;
+
+ [Tooltip("The shape of the light.")]
+ public Texture2D _cookieTexture;
+
+ [Tooltip("Which layers cast shadows.")]
+ public LayerMask _shadowLayers = -1;
+
+ [Tooltip("Allows the light cookie to move off the light plane. Use gently as it can cause shadows to look weird.")]
+ public bool _parallaxLight;
+
+ private RectTransform _rt;
+
+ public static List<SFLight> _lights = new List<SFLight>();
+
+ private Rect _cullBounds;
+
+ private static int GROWTH_NUM = 4;
+
+ private static int GROWTH_DENOM = 3;
+
+ private static VertexArray[] vertexArrays = new VertexArray[40];
+
+ public float radius
+ {
+ get
+ {
+ return _radius;
+ }
+ set
+ {
+ _radius = value;
+ }
+ }
+
+ public float intensity
+ {
+ get
+ {
+ return _intensity;
+ }
+ set
+ {
+ _intensity = value;
+ }
+ }
+
+ public Color color
+ {
+ get
+ {
+ return _color;
+ }
+ set
+ {
+ _color = value;
+ }
+ }
+
+ public Texture2D cookieTexture
+ {
+ get
+ {
+ return _cookieTexture;
+ }
+ set
+ {
+ _cookieTexture = value;
+ }
+ }
+
+ public LayerMask shadowLayers
+ {
+ get
+ {
+ return _shadowLayers;
+ }
+ set
+ {
+ _shadowLayers = value;
+ }
+ }
+
+ public bool parallaxLight
+ {
+ get
+ {
+ return _parallaxLight;
+ }
+ set
+ {
+ _parallaxLight = value;
+ }
+ }
+
+ public Rect _bounds => _rt.rect;
+
+ public Rect _CullBounds => _cullBounds;
+
+ private void OnEnable()
+ {
+ _lights.Add(this);
+ }
+
+ private void OnDisable()
+ {
+ _lights.Remove(this);
+ }
+
+ public Matrix4x4 _ModelMatrix(bool forceProjection)
+ {
+ if (!_rt)
+ {
+ _rt = GetComponent<RectTransform>();
+ }
+ Matrix4x4 localToWorldMatrix = _rt.localToWorldMatrix;
+ if (!_parallaxLight || forceProjection)
+ {
+ localToWorldMatrix.SetRow(2, new Vector4(0f, 0f, 1f, 0f));
+ }
+ return localToWorldMatrix;
+ }
+
+ public Matrix4x4 _CookieMatrix()
+ {
+ if (!_rt)
+ {
+ _rt = GetComponent<RectTransform>();
+ }
+ Vector2 vector = _rt.sizeDelta / 2f;
+ Vector2 vector2 = Vector2.one - 2f * _rt.pivot;
+ Matrix4x4 identity = Matrix4x4.identity;
+ identity.SetRow(0, new Vector4(vector.x, 0f, 0f, vector2.x * vector.x));
+ identity.SetRow(1, new Vector4(0f, vector.y, 0f, vector2.y * vector.y));
+ return identity;
+ }
+
+ private static Rect Union(Rect r1, Rect r2)
+ {
+ return Rect.MinMaxRect(Mathf.Min(r1.xMin, r2.xMin), Mathf.Min(r1.yMin, r2.yMin), Mathf.Max(r1.xMax, r2.xMax), Mathf.Max(r1.yMax, r2.yMax));
+ }
+
+ private static Rect QuadrantCull(Rect cull, Matrix4x4 mvp, Rect r)
+ {
+ if (!SFRenderer._FastCull(mvp, r))
+ {
+ return cull;
+ }
+ return Union(cull, r);
+ }
+
+ public Rect _CalcCullBounds(Matrix4x4 vpMatrix)
+ {
+ Matrix4x4 matrix4x = _ModelMatrix(forceProjection: true);
+ Matrix4x4 mvp = vpMatrix * matrix4x;
+ Rect rect = new Rect(0f - _radius, 0f - _radius, 2f * _radius, 2f * _radius);
+ Rect rect2 = _rt.rect;
+ Rect cull = rect;
+ cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect2.xMin, rect2.yMin, rect.xMax, rect.yMax));
+ cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect.xMin, rect2.yMin, rect2.xMax, rect.yMax));
+ cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect2.xMin, rect.yMin, rect.xMax, rect2.yMax));
+ cull = QuadrantCull(cull, mvp, Rect.MinMaxRect(rect.xMin, rect.yMin, rect2.xMax, rect2.yMax));
+ return _cullBounds = SFRenderer._TransformRect(matrix4x, cull);
+ }
+
+ private VertexArray GetVertexArray(int segments)
+ {
+ int num = 0;
+ int num2 = 4;
+ while (segments > num2)
+ {
+ num2 = num2 * GROWTH_NUM / GROWTH_DENOM;
+ num++;
+ }
+ if (num >= vertexArrays.Length)
+ {
+ Debug.LogError("SFSS: Maximum vertexes per light exceeded. (" + num2 + ")");
+ return null;
+ }
+ if (vertexArrays[num] == null)
+ {
+ vertexArrays[num] = new VertexArray(num2);
+ }
+ return vertexArrays[num];
+ }
+
+ private void BatchPath(SFPolygon poly, int pathIndex, Matrix4x4 t, ref int j, bool flipped, Vector3 properties, Vector3[] verts, Vector4[] tangents, Vector2[] uvs, int[] tris)
+ {
+ Vector2[] path = poly.GetPath(pathIndex);
+ int num;
+ Vector2 vector;
+ if (poly.looped)
+ {
+ num = 0;
+ vector = Transform(t, path[^1]);
+ }
+ else
+ {
+ num = 1;
+ vector = Transform(t, path[0]);
+ }
+ for (int i = num; i < path.Length; i++)
+ {
+ Vector2 vector2 = Transform(t, path[i]);
+ Vector4 vector3 = (flipped ? new Vector4(vector2.x, vector2.y, vector.x, vector.y) : new Vector4(vector.x, vector.y, vector2.x, vector2.y));
+ verts[j * 4] = properties;
+ tangents[j * 4] = vector3;
+ uvs[j * 4] = new Vector2(0f, 0f);
+ verts[j * 4 + 1] = properties;
+ tangents[j * 4 + 1] = vector3;
+ uvs[j * 4 + 1] = new Vector2(1f, 0f);
+ verts[j * 4 + 2] = properties;
+ tangents[j * 4 + 2] = vector3;
+ uvs[j * 4 + 2] = new Vector2(0f, 1f);
+ verts[j * 4 + 3] = properties;
+ tangents[j * 4 + 3] = vector3;
+ uvs[j * 4 + 3] = new Vector2(1f, 1f);
+ tris[j * 6] = j * 4;
+ tris[j * 6 + 1] = j * 4 + 1;
+ tris[j * 6 + 2] = j * 4 + 2;
+ tris[j * 6 + 3] = j * 4 + 1;
+ tris[j * 6 + 4] = j * 4 + 3;
+ tris[j * 6 + 5] = j * 4 + 2;
+ j++;
+ vector = vector2;
+ }
+ }
+
+ public Mesh _BuildShadowMesh(Mesh mesh, List<SFPolygon> polys, float minLightPenetration)
+ {
+ int num = 0;
+ for (int i = 0; i < polys.Count; i++)
+ {
+ if (((int)polys[i].shadowLayers & (int)shadowLayers) == 0)
+ {
+ continue;
+ }
+ SFPolygon sFPolygon = polys[i];
+ int activePath = sFPolygon.activePath;
+ bool looped = sFPolygon.looped;
+ if (activePath >= 0)
+ {
+ num += sFPolygon.GetPath(activePath).Length - ((!looped) ? 1 : 0);
+ continue;
+ }
+ int pathCount = sFPolygon.pathCount;
+ for (int j = 0; j < pathCount; j++)
+ {
+ num += sFPolygon.GetPath(j).Length - ((!looped) ? 1 : 0);
+ }
+ }
+ VertexArray vertexArray = GetVertexArray(num);
+ Vector3[] verts = vertexArray.verts;
+ Vector4[] tangents = vertexArray.tangents;
+ Vector2[] uvs = vertexArray.uvs;
+ int[] tris = vertexArray.tris;
+ if (num == 0 || vertexArray.capacity == 0)
+ {
+ return null;
+ }
+ if (!_rt)
+ {
+ _rt = GetComponent<RectTransform>();
+ }
+ Matrix4x4 worldToLocalMatrix = _rt.worldToLocalMatrix;
+ int j2 = 0;
+ for (int k = 0; k < polys.Count; k++)
+ {
+ SFPolygon sFPolygon2 = polys[k];
+ if (((int)sFPolygon2.shadowLayers & (int)shadowLayers) == 0)
+ {
+ continue;
+ }
+ Matrix4x4 matrix4x = sFPolygon2._GetMatrix();
+ Matrix4x4 t = worldToLocalMatrix * matrix4x;
+ bool flipped = Det2x3(matrix4x) < 0f;
+ float y = Mathf.Max(sFPolygon2._lightPenetration, minLightPenetration);
+ Vector3 properties = new Vector3(_radius, y, sFPolygon2._opacity);
+ int activePath2 = sFPolygon2.activePath;
+ if (activePath2 >= 0)
+ {
+ BatchPath(sFPolygon2, activePath2, t, ref j2, flipped, properties, verts, tangents, uvs, tris);
+ continue;
+ }
+ int pathCount2 = sFPolygon2.pathCount;
+ for (int l = 0; l < pathCount2; l++)
+ {
+ BatchPath(sFPolygon2, l, t, ref j2, flipped, properties, verts, tangents, uvs, tris);
+ }
+ }
+ for (int m = 6 * num; m < 6 * vertexArray.size; m++)
+ {
+ vertexArray.tris[m] = 0;
+ }
+ mesh.vertices = verts;
+ mesh.tangents = tangents;
+ mesh.uv = uvs;
+ mesh.triangles = tris;
+ vertexArray.size = num;
+ return mesh;
+ }
+
+ private static float Det2x3(Matrix4x4 m)
+ {
+ return m[0] * m[5] - m[1] * m[4];
+ }
+
+ private static Vector2 Transform(Matrix4x4 m, Vector2 p)
+ {
+ return new Vector2(p.x * m[0] + p.y * m[4] + m[12], p.x * m[1] + p.y * m[5] + m[13]);
+ }
+}