Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Smoothly transition between Perspective and Orthographic camera matrix

Discussion in 'General Graphics' started by GravenFear, Jul 25, 2021.

  1. GravenFear

    GravenFear

    Joined:
    May 26, 2015
    Posts:
    12
    So I stumbled across this thread awhile ago and used their method for a bit but, as people discuss in that thread, using the Mathf.Lerp function is a bit 'instant'/really-fast at the start of orthographic->perspective and the end of perspective->orthographic. (Some of the methods in that thread I just couldn't understand or their way of writing code was so different/bizarre that I couldn't make sense of it)

    I've already tried applying many different types of easing to the two problem areas but it's still very noticeable that the transition isn't linear.

    Does anyone know of some way to make it so that the transition at every step of the lerp appears to be the same 'speed'?

    My Code:
    Code (CSharp):
    1. using System.Collections;
    2. using System.Collections.Generic;
    3. using UnityEngine;
    4.  
    5. [RequireComponent(typeof(Camera))]
    6. public class CameraProjectionTransition : MonoBehaviour
    7. {
    8.     private void Awake()
    9.     {
    10.         m_MatrixLerpEasing = EasingFunction.GetEasingFunction(LerpEasing);
    11.         int orthographicSize = Globals.instance.MapDraw.MapSize / 2;
    12.  
    13.         m_PerspectiveMatrix = Camera.projectionMatrix;
    14.  
    15.         float aspect = Screen.width / (float)Screen.height;
    16.         m_OrthographicMatrix = Matrix4x4.Ortho(-orthographicSize * aspect, orthographicSize * aspect, -orthographicSize, orthographicSize, Camera.nearClipPlane, Camera.farClipPlane);
    17.         m_Ortho = false;
    18.     }
    19.  
    20.     public static Matrix4x4 MatrixLerp(Matrix4x4 from, Matrix4x4 to, float time)
    21.     {
    22.         Matrix4x4 ret = new Matrix4x4();
    23.         for (int i = 0; i < 16; i++)
    24.             ret[i] = Mathf.Lerp(from[i], to[i], time);
    25.         return ret;
    26.     }
    27.  
    28.     private IEnumerator LerpFromTo_cr(Matrix4x4 src, Matrix4x4 dest, float duration)
    29.     {
    30.         float time = 0;
    31.         while (time < 1)
    32.         {
    33.             time = Mathf.Clamp01(time + Time.deltaTime / duration);
    34.             Camera.projectionMatrix = MatrixLerp(src, dest, time);
    35.             yield return null;
    36.         }
    37.         Camera.projectionMatrix = dest;
    38.     }
    39.  
    40.     private void BlendToMatrix(Matrix4x4 targetMatrix, float duration)
    41.     {
    42.         StopAllCoroutines();
    43.         StartCoroutine(LerpFromTo_cr(Camera.projectionMatrix, targetMatrix, duration));
    44.     }
    45.  
    46.     public void BeginTransition(bool toPerspective, float duration)
    47.     {
    48.         float d = Mathf.Max(0.0001f, duration);
    49.         if (toPerspective && m_Ortho)
    50.         {
    51.             m_Ortho = false;
    52.             BlendToMatrix(m_PerspectiveMatrix, d);
    53.         }
    54.         else if (!toPerspective && !m_Ortho)
    55.         {
    56.             m_Ortho = true;
    57.             BlendToMatrix(m_OrthographicMatrix, d);
    58.         }
    59.     }
    60.  
    61.     Camera Camera
    62.     {
    63.         get
    64.         {
    65.             if (m_Camera == null)
    66.                 m_Camera = GetComponent<Camera>();
    67.             return m_Camera;
    68.         }
    69.     }
    70.  
    71.     bool m_Ortho;
    72.     Camera m_Camera;
    73.     Matrix4x4 m_OrthographicMatrix;
    74.     Matrix4x4 m_PerspectiveMatrix;
    75.     EasingFunction.Function m_MatrixLerpEasing;
    76. }