Unityでサブカメラを用いる場合、どこにあるか、どの方向を向いているか確認できるようにしたい場面があると思います(レーシングの俯瞰とか、RenderTextureに映すカメラ位置とか)。
本記事では、カメラギズモ(視錘台)を可視化する実装を備忘録がてら紹介。
結論、コードは以下。
using UnityEngine;
public class CameraFrustumDrawer : MonoBehaviour
{
[SerializeField]
private Material lineMaterial; // 線を描画するためのマテリアル
private void OnRenderObject()
{
if (lineMaterial == null)
{
Debug.LogWarning("Line Materialが設定されていません。");
return;
}
Camera camera = GetComponent<Camera>();
if (camera == null)
{
Debug.LogWarning("カメラコンポーネントが見つかりません。");
return;
}
// 視錐台のコーナーポイントを計算
Vector3[] nearCorners = new Vector3[4];
Vector3[] farCorners = new Vector3[4];
camera.CalculateFrustumCorners(new Rect(0, 0, 1, 1), camera.nearClipPlane * 0.99f, Camera.MonoOrStereoscopicEye.Mono, nearCorners);
camera.CalculateFrustumCorners(new Rect(0, 0, 1, 1), camera.farClipPlane * 1.01f, Camera.MonoOrStereoscopicEye.Mono, farCorners);
for (int i = 0; i < 4; i++)
{
nearCorners[i] = camera.transform.TransformPoint(nearCorners[i]);
farCorners[i] = camera.transform.TransformPoint(farCorners[i]);
}
// 線の描画
GL.PushMatrix();
lineMaterial.SetPass(0);
GL.Begin(GL.LINES);
GL.Color(Color.green);
// 近クリップ面の四辺
DrawLine(nearCorners[0], nearCorners[1]);
DrawLine(nearCorners[1], nearCorners[2]);
DrawLine(nearCorners[2], nearCorners[3]);
DrawLine(nearCorners[3], nearCorners[0]);
// 遠クリップ面の四辺
DrawLine(farCorners[0], farCorners[1]);
DrawLine(farCorners[1], farCorners[2]);
DrawLine(farCorners[2], farCorners[3]);
DrawLine(farCorners[3], farCorners[0]);
// 近クリップ面と遠クリップ面を結ぶ四辺
for (int i = 0; i < 4; i++)
{
DrawLine(nearCorners[i], farCorners[i]);
}
GL.End();
GL.PopMatrix();
}
private void DrawLine(Vector3 start, Vector3 end)
{
GL.Vertex(start);
GL.Vertex(end);
}
}
ポイントは以下です。
- GLクラスでラインを描画
- OnRenderObjectを使用
- 視錘台のコーナーポイントを計算
1.GLクラスでラインを描画
GL.PushMatrix()
とGL.PopMatrix()
で行列を保存・復元。
GL.Begin(GL.LINES)
で線描画モードを開始し、GL.Vertex()
で線の始点・終点を指定。
2.OnRenderObject()を使用
OnRenderObject()は、カメラのレンダリング時に呼び出されます。これによってギズモをGameViewでも描画できます。
3.視錐台のコーナーポイント計算
Camera.CalculateFrustumCorners
を使用して、カメラの近クリップ面と遠クリップ面の四隅を取得しています。
描画範囲の各コーナーは、cameraのプロパティ、nearClipPlane
, farClipPlane
から取得。
ちなみに、本スクリプトをアタッチしたカメラ映像をRendererTextureに設定したい場合、Textureのふちと視錘台のラインがかぶります。
それを防ぐには以下に編集してください。
camera.CalculateFrustumCorners(new Rect(0, 0, 1, 1), camera.nearClipPlane * 0.99f, Camera.MonoOrStereoscopicEye.Mono, nearCorners);
camera.CalculateFrustumCorners(new Rect(0, 0, 1, 1), camera.farClipPlane * 1.01f, Camera.MonoOrStereoscopicEye.Mono, farCorners);
nearClipPlane
とfarClipPlane
に係数をかけて描画したいラインと実際の描画位置を微妙にずらしています。