public override bool CalculateShadow() { if (RingComponent == null) { RingCachedComponent.TryInit(this); } if (base.CalculateShadow() == true) { if (RingComponent == null) { return(false); } if (GetTexture() != null) { if (Helper.Enabled(RingComponent) == true) { InnerRadius = RingComponent.InnerRadius; OuterRadius = RingComponent.OuterRadius; } var direction = default(Vector3); var position = default(Vector3); var color = default(Color); Helper.CalculateLight(Light, transform.position, null, null, ref position, ref direction, ref color); var rotation = Quaternion.FromToRotation(direction, Vector3.back); var squash = Vector3.Dot(direction, transform.up); // Find how squashed the ellipse is based on light direction var width = transform.lossyScale.x * OuterRadius; var length = transform.lossyScale.z * OuterRadius; var axis = rotation * transform.up; // Find the transformed up axis var spin = Quaternion.LookRotation(Vector3.forward, new Vector2(-axis.x, axis.y)); // Orient the shadow ellipse var scale = Helper.Reciprocal3(new Vector3(width, length * Mathf.Abs(squash), 1.0f)); var skew = Mathf.Tan(Helper.Acos(-squash)); var shadowT = MatrixHelper.Translation(-transform.position); var shadowR = MatrixHelper.Rotation(spin * rotation); // Spin the shadow so lines up with its tilt var shadowS = MatrixHelper.Scaling(scale); // Scale the ring into an oval var shadowK = MatrixHelper.ShearingZ(new Vector2(0.0f, skew)); // Skew the shadow so it aligns with the ring plane Matrix = shadowS * shadowK * shadowR * shadowT; Ratio = Helper.Divide(OuterRadius, OuterRadius - InnerRadius); return(true); } } return(false); }