- Home /
Capture Bounds with an orthographic camera -- runtime world map
I have bounds for a group of objects (calculated with Bounds.Encapsulate on the group). How can I capture an image of the objects to a texture?
For example, the objects are my level and I want to take an overhead capture of them to use as an in-game map. I want to precisely capture the bounds to make it easy to map a position within the bounds to a position within the map.
Answer by idbrii · Apr 27, 2021 at 10:09 PM
Setup an orthographic camera where the size is set to the z of the bounds and render to a render texture with the same aspect ratio as the bounds.
Here's my solution:
public RawImage _MapImage;
// AspectRatioFitter ensures the resulting image matches the
// bounds dimensions and allows converting between the
// normalized position within the bounds to the position
// within the map (for drawing positions on the map).
public AspectRatioFitter _AspectFitter;
public Bounds _WorldBounds;
void CaptureMapImage() {
var aspect_ratio = _WorldBounds.extents.x / _WorldBounds.extents.z;
var t = _MapImage.transform as RectTransform;
var height = Mathf.RoundToInt(t.rect.size.y);
var width = Mathf.RoundToInt(height * aspect_ratio);
_AspectFitter.aspectRatio = aspect_ratio;
// To make the map a live view of the world, allocate and
// store RenderTexture instead of temporary and don't
// destroy the camera.
var render_target = RenderTexture.GetTemporary(width, height, 16);
var cam = new GameObject("overhead map camera").AddComponent<Camera>();
cam.targetTexture = render_target;
cam.renderingPath = RenderingPath.Forward;
// Clear solid color so empty areas are transparent
cam.clearFlags = CameraClearFlags.SolidColor;
cam.backgroundColor = Color.clear;
// You may need to play with offset. I wanted it close to
// my main ground plane so ceilings are not visible. You
// may want it at _WorldBounds.extent.y height.
cam.orthographic = true;
var offset = Vector3.up;
cam.transform.SetPositionAndRotation(_WorldBounds.center + offset, Quaternion.LookRotation(Vector3.down));
cam.orthographicSize = _WorldBounds.extents.z;
cam.Render();
Util.DestroyGameObject(cam.gameObject);
var tex = new Texture2D(render_target.width, render_target.height);
var rect = new Rect(0, 0, tex.width, tex.height);
var old_rt = RenderTexture.active;
RenderTexture.active = render_target;
tex.ReadPixels(rect, 0, 0);
tex.Apply();
RenderTexture.active = old_rt;
RenderTexture.ReleaseTemporary(render_target);
_MapImage.texture = tex;
}
// Use this to position world objects on the map.
void PlaceOnMap(Transform world_obj, RectTransform map_obj) {
var pos = OverheadToMap(world_obj.position);
map_obj.anchoredPosition = pos;
var yaw = world_obj.rotation.eulerAngles.y;
map_obj.rotation = Quaternion.Euler(0f, 0f, -yaw);
}
//
// Helper math functions.
//
Vector2 OverheadToMap(Vector3 v) {
var pos = OverheadTo2D(v - _WorldBounds.center);
var world_size = OverheadTo2D(_WorldBounds);
var pos_normalized = Vector2.Scale(pos, Inverse(world_size));
var t = _MapImage.transform as RectTransform;
var map_size = t.rect.size;
return Vector2.Scale(pos_normalized, map_size);
}
Vector2 OverheadTo2D(Vector3 v) {
return new Vector2(v.x, v.z);
}
Vector2 Inverse(Vector2 v) {
return new Vector2(1f / v.x, 1f / v.y);
}
Your answer
Follow this Question
Related Questions
Main Camera Stops working or just freezes? 0 Answers
Camera stack mask 0 Answers
Render object with different shader depending on the camera 2 Answers
Why am I getting rendering issues, with fog on VR? 0 Answers
Improve render quality? 0 Answers