Search Unity

Setting camera projection matrix breaks shadows and skybox

Discussion in 'Editor & General Support' started by BjornVTI, Sep 25, 2012.

  1. BjornVTI

    BjornVTI

    Joined:
    Sep 11, 2012
    Posts:
    7
  2. BjornVTI

    BjornVTI

    Joined:
    Sep 11, 2012
    Posts:
    7
    Well at least I have tracked down the shadow problem. If I use Forward rendering instead of deferred rendering, shadows work properly.

    If anyone else want to experience the problem, try using the following script on your camera and enable deferred rendering:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [ExecuteInEditMode]
    5.  
    6. public class AsymetricProjection : MonoBehaviour {
    7.     public bool enable = true;
    8.     Matrix4x4 default_matrix;
    9.  
    10.     void start() {
    11.         default_matrix = camera.projectionMatrix;
    12.     }
    13.  
    14.     void LateUpdate() {
    15.         Matrix4x4 m = new Matrix4x4();
    16.         m[0, 0] = 2.21687f;
    17.         m[0, 1] = -0.02983f;
    18.         m[0, 2] = -0.00969f;
    19.         m[0, 3] = 0.00000f;
    20.         m[1, 0] = 0.05348f;
    21.         m[1, 1] = 4.01233f;
    22.         m[1, 2] = -0.14524f;
    23.         m[1, 3] = 0.00000f;
    24.         m[2, 0] = -0.00154f;
    25.         m[2, 1] = -0.02675f;
    26.         m[2, 2] = -0.99984f;
    27.         m[2, 3] = -2.00020f;
    28.         m[3, 0] = -0.00154f;
    29.         m[3, 1] = -0.02675f;
    30.         m[3, 2] = -0.99964f;
    31.         m[3, 3] = 0.00000f;
    32.         if (enable) {
    33.             camera.projectionMatrix = m;
    34.         }
    35.         else {
    36.             camera.projectionMatrix = default_matrix;
    37.             camera.ResetProjectionMatrix();
    38.         }
    39.     }
    40. }
    When script is enabled shadows are jumping around depending on camera position.
     
  3. BjornVTI

    BjornVTI

    Joined:
    Sep 11, 2012
    Posts:
    7
  4. BjornVTI

    BjornVTI

    Joined:
    Sep 11, 2012
    Posts:
    7
    Well, I think I have solved this. You will need to recalculate the aspect ratio and the field of view for the asymmetric projection matrix.

    Lets use the example found here:
    http://docs.unity3d.com/Documentation/ScriptReference/Camera-projectionMatrix.html

    And extend it with code that calculates and sets the aspect and field of view:

    Code (csharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. [ExecuteInEditMode]
    5. public class OffProjection : MonoBehaviour {
    6.     public float left = -0.2F;
    7.     public float right = 0.2F;
    8.     public float top = 0.2F;
    9.     public float bottom = -0.2F;
    10.    
    11.     void LateUpdate() {
    12.         Camera cam = camera;
    13.         float width = (right - left);
    14.         float height = (top - bottom);
    15.         cam.aspect = width/height;
    16.         float fov = (Mathf.Atan(top/cam.nearClipPlane) - Mathf.Atan(bottom/cam.nearClipPlane)) * 57.2957795f;
    17.         cam.fieldOfView = fov;
    18.  
    19.         Matrix4x4 m = PerspectiveOffCenter(left, right, bottom, top, cam.nearClipPlane, cam.farClipPlane);
    20.         cam.projectionMatrix = m;
    21.     }
    22.    
    23.     static Matrix4x4 PerspectiveOffCenter(float left, float right, float bottom, float top, float near, float far) {
    24.         float x = 2.0F * near / (right - left);
    25.         float y = 2.0F * near / (top - bottom);
    26.         float a = (right + left) / (right - left);
    27.         float b = (top + bottom) / (top - bottom);
    28.         float c = -(far + near) / (far - near);
    29.         float d = -(2.0F * far * near) / (far - near);
    30.         float e = -1.0F;
    31.         Matrix4x4 m = new Matrix4x4();
    32.         m[0, 0] = x;
    33.         m[0, 1] = 0;
    34.         m[0, 2] = a;
    35.         m[0, 3] = 0;
    36.         m[1, 0] = 0;
    37.         m[1, 1] = y;
    38.         m[1, 2] = b;
    39.         m[1, 3] = 0;
    40.         m[2, 0] = 0;
    41.         m[2, 1] = 0;
    42.         m[2, 2] = c;
    43.         m[2, 3] = d;
    44.         m[3, 0] = 0;
    45.         m[3, 1] = 0;
    46.         m[3, 2] = e;
    47.         m[3, 3] = 0;
    48.         return m;
    49.     }
    50. }
     
  5. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    @BjornVTI, is this implementation for forward or deferred rending? I've tried both and my shadows still don't show up for deferred rendering.
     
  6. DaveTheVR

    DaveTheVR

    Joined:
    May 15, 2015
    Posts:
    2
    Hi, just wanted to ping this thread as I also need a solution for custom projection matrix rendering.
    The solution above is not working, was maybe done in an earlier version on Unity?

    If I understand correctly, there is a pass in which the projection matrix is used in a simpler form (probably to speed up rendering). If someone could give me a hint on how to modify the default shaders, I would like to take a deeper look.
     
  7. Ben-BearFish

    Ben-BearFish

    Joined:
    Sep 6, 2011
    Posts:
    1,204
    Last edited: May 18, 2015