Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

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