以前、カメラの消失点を移動させる記事を書いたのですが、その後再利用しようとして、カメラのFoVが変わるたびに値を調整しなければならないことに気が付きました。これは面倒くさい…。
ということで、FoVを変えても消失点が変わらないように修正しました。以前は(-0.1,-0.1)-(0.1,0.1)という、これまた直感的ではない範囲でしたが、今回はこれを(-0.5,-0.5)-(0.5,0.5)にしてあります。
using UnityEngine;
using System.Collections;
namespace CameraUtils
{
[HelpURL("http://docs.unity3d.com/ScriptReference/Camera-projectionMatrix.html")]
[RequireComponent(typeof(Camera)), ExecuteAlways]
public class VanishingPointCtrl : MonoBehaviour
{
[SerializeField, Range(-0.5f, 0.5f)] private float offsetX = 0f;
[SerializeField, Range(-0.5f, 0.5f)] private float offsetY = 0f;
Camera m_camera;
void Start()
{
m_camera = gameObject.GetComponent<Camera>();
}
void LateUpdate()
{
if (m_camera == null)
{
m_camera = gameObject.GetComponent<Camera>();
}
SetVanishingPoint(new Vector2(offsetX,offsetY), m_camera);
}
static public Matrix4x4 PerspectiveOffCenter(float left, float right, float bottom, float top, float near, float far)
{
float x = (2f * near) / (right - left);
float y = (2f * near) / (top - bottom);
float a = (right + left) / (right - left);
float b = (top + bottom) / (top - bottom);
float c = -(far + near) / (far - near);
float d = -(2f * far * near) / (far - near);
float e = -1f;
Matrix4x4 m = new Matrix4x4();
m[0, 0] = x; m[0, 1] = 0f; m[0, 2] = a; m[0, 3] = 0f;
m[1, 0] = 0f; m[1, 1] = y; m[1, 2] = b; m[1, 3] = 0f;
m[2, 0] = 0f; m[2, 1] = 0f; m[2, 2] = c; m[2, 3] = d;
m[3, 0] = 0f; m[3, 1] = 0f; m[3, 2] = e; m[3, 3] = 0f;
return m;
}
static public void SetVanishingPoint(Vector2 perspectiveOffset, Camera cam)
{
cam.ResetProjectionMatrix();
Matrix4x4 m = cam.projectionMatrix;
float w = 2f * cam.nearClipPlane / m.m00;
float h = 2f * cam.nearClipPlane / m.m11;
float perspectiveOffsetX = perspectiveOffset.x * w;
float perspectiveOffsetY = perspectiveOffset.y * h;
float left = -w / 2f - perspectiveOffsetX;
float right = left + w;
float bottom = -h / 2f - perspectiveOffsetY;
float top = bottom + h;
cam.projectionMatrix = PerspectiveOffCenter(left, right, bottom, top, cam.nearClipPlane, cam.farClipPlane);
}
}
}
「これなら画面内に別カメラで小さい画面をいれてもいいのでは?」という話もあるのですが、今回は演出上HUDを取り外した状態も見せたかったのでこうなっております。

