But of course…My bad.
tempPos = cam.WorldToScreenPoint(cornerPoint); // Transform to screen pos
should be changed to
tempPos = cam.WorldToScreenPoint(tempPos); // Transform to screen pos
Now it works perfectly! Thank you! We are almost there…It works not so perfectly on objects with multiple meshrenderers. Let’s pretend I have a bed and it consists of multiple mesh renderers. For each mesh renderer I find the 8 points of the bounds. And then try to find min and max. It seems to be working kind of right. Except that there is a lot of free gap between the edges of the bounding box and the actual mesh.
Another video, which first demonstrates that the solution you’ve helped me achieve works with multiple point and directional lights (even combined together), on objects with a single mesh renderer. Then it demonstrates that things get messy as soon as an object consists of more than 1 mesh renderer:
https://www.youtube.com/watch?v=FtQqkY9WXc0
The changed code looks like this:
Code
[SerializeField] Camera cam;
[SerializeField] Transform planeTransform;
Vector3[] pts = new Vector3[8];
List<Light> lights = new List<Light>();
public GameObject _target;
private void Start()
{
foreach (Light l in FindObjectsOfType<Light>())
{
if (l.type == LightType.Point || l.type == LightType.Directional)
{
lights.Add(l);
}
}
}
void OnGUI() {
List<MeshRenderer> meshRenderers = _target.GetComponentsInChildren<MeshRenderer>().ToList();
if (meshRenderers.Count >= 1) {
pts = new Vector3[8 * meshRenderers.Count];
int counter = 0;
foreach (MeshRenderer mr in meshRenderers)
{
Bounds mrBounds = mr.bounds;
if (cam.WorldToScreenPoint(mrBounds.center).z < 0) { Debug.Log("returning"); }
pts[counter + 0] = new Vector3(mrBounds.center.x + mrBounds.extents.x, mrBounds.center.y + mrBounds.extents.y, mrBounds.center.z + mrBounds.extents.z);
pts[counter + 1] = new Vector3(mrBounds.center.x + mrBounds.extents.x, mrBounds.center.y + mrBounds.extents.y, mrBounds.center.z - mrBounds.extents.z);
pts[counter + 2] = new Vector3(mrBounds.center.x + mrBounds.extents.x, mrBounds.center.y - mrBounds.extents.y, mrBounds.center.z + mrBounds.extents.z);
pts[counter + 3] = new Vector3(mrBounds.center.x + mrBounds.extents.x, mrBounds.center.y - mrBounds.extents.y, mrBounds.center.z - mrBounds.extents.z);
pts[counter + 4] = new Vector3(mrBounds.center.x - mrBounds.extents.x, mrBounds.center.y + mrBounds.extents.y, mrBounds.center.z + mrBounds.extents.z);
pts[counter + 5] = new Vector3(mrBounds.center.x - mrBounds.extents.x, mrBounds.center.y + mrBounds.extents.y, mrBounds.center.z - mrBounds.extents.z);
pts[counter + 6] = new Vector3(mrBounds.center.x - mrBounds.extents.x, mrBounds.center.y - mrBounds.extents.y, mrBounds.center.z + mrBounds.extents.z);
pts[counter + 7] = new Vector3(mrBounds.center.x - mrBounds.extents.x, mrBounds.center.y - mrBounds.extents.y, mrBounds.center.z - mrBounds.extents.z);
counter += 8;
}
}
// 3. Project corners onto plane
float planeY = 0;
Vector3 minBounds = new Vector3(Mathf.Infinity, Mathf.Infinity, Mathf.Infinity);
Vector3 maxBounds = new Vector3(Mathf.NegativeInfinity, Mathf.NegativeInfinity, Mathf.NegativeInfinity);
Vector3 tempPos = Vector3.zero;
Vector3 cornerPoint = Vector3.zero;
Vector3 pointLightDir = Vector3.zero;
foreach (Light l in lights)
{
for (int i=0; i < pts.Length; i++)
{
cornerPoint = pts[i];
pointLightDir = l.type == LightType.Point ? (cornerPoint - l.transform.position).normalized : l.transform.forward;
planeY = planeTransform.position.y;
tempPos = cornerPoint + (- pointLightDir * ((cornerPoint.y - planeY) / pointLightDir.y)); // Project to plane
tempPos = cam.WorldToScreenPoint(tempPos); // Transform to screen pos
tempPos.y = Screen.height - tempPos.y; // Transform to GUI pos
minBounds = Vector3.Min(minBounds, tempPos);
maxBounds = Vector3.Max(maxBounds, tempPos);
}
}
// 6. Draw bounds
Rect r = Rect.MinMaxRect(minBounds.x, minBounds.y, maxBounds.x, maxBounds.y);
GUI.Box(r, "Shadow");
Any ideas how to remove the empty space?