Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
2
Question by Zenggang · May 25, 2016 at 03:16 PM · projection-matrix

projection matrix in unity

can someone give me more info on the projection matrix used within unity?

Is it the same as that projection matrix from OpenGL?

 [ 2n/r-l     0      r+l/r-l        0
    0      2n/t-b    t+b/t-b        0
    0         0      -(f+n)/f-n  -2fn/f-n
    0         0        -1           0    ]

is also this matrix stored in column major?

 2n/r-l, 0, 0 ,0,  <- first column
 0, 2n/t-b, 0, 0, <- second column
 r+l/r-l, t+b/t-b,  -(f+n)/f-n, -1, <- third column
 0, 0, -2fn/f-n, 0                        <- last column

and one last question is around opengl probably: according to the opengl doc, v' = M * v and v is the un-transformed vertex and M is the transform matrix, according to this equation, what is the advantage using column major to store M instead of using row major?

Thanks

Comment
Add comment · Show 1
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image KazYamof · May 25, 2016 at 03:34 PM 0
Share

Not sure abour the rest, but if I remember, use column/row is just a convention. Doesn't affect anything use row or column (right/left hand).

1 Reply

· Add your reply
  • Sort: 
avatar image
11
Best Answer

Answer by Bunny83 · May 25, 2016 at 06:16 PM

Unity's Matrix4x4 struct uses the column-major format. The actual memory layout however is irrelevant. The struct has 16 float member variables:

 m00 m01 m02 m03
 m10 m11 m12 m13
 m20 m21 m22 m23
 m30 m31 m32 m33

They are stored in this order:

  m00; m10; m20; m30; m01; m11; m21; m31; m02; m12; m22; m32; m03; m13; m23; m33;
 |     column 0      |     column 1      |     column 2      |     column 3      |

As KazYarnof said in the comment there's no advantage / disadvantage using column / row major layout. However it does affect the way you have to treat the matrix of course. As you might know a matrix multiplication only works when the column count of the first matrix matches the row count of the second. A Vector4 can be treated either as 1x4 (row vector) or as 4x1(column vector).

 (1x4) * (4x4) --> (4x1)
 (4x4) * (4x1) --> (1x4)

    R = M * V  // V treated as column vector
    ( V.x   V.y   V.z   V.w )
       |     |     |     |
      \|/   \|/   \|/   \|/
      m00   m01   m02   m03 --> R.x
      m10   m11   m12   m13 --> R.y
      m20   m21   m22   m23 --> R.z
      m30   m31   m32   m33 --> R.w
 
 ----------------------------------------
 
     R = V * M // V treated as row vector.
     // this isn't defined in Unity. A vector is always treated as a column vector
     // this could be done in Unity by doing "M.transpose * V"
     V.x --> m00   m01   m02   m03
     V.y --> m10   m11   m12   m13
     V.z --> m20   m21   m22   m23
     V.w --> m30   m31   m32   m33
              |     |     |     |
             \|/   \|/   \|/   \|/
           ( R.x   R.y   R.z   R.w )

Don't get confused by those "drawings". I arranged the vectors in a way you can see how they are multiplied, not according to their actual layout (row / column).

The major difference between Unity and OpenGL is that Unity uses a left-handed coordinate system while OpenGL uses a right.handed system.

          X-axis          Y-axis         z-axis
 Unity    left-to-right   bottom-to-top  near-to-far
 OpenGL   left-to-right   bottom-to-top  far-to-near

So "forward" in OpenGL is "-z". In Unity forward is "+z". Most hand-rules you might know from math are inverted in Unity. For example the cross product usually uses the right hand rule c = a x b where a is thumb, b is index finger and c is the middle finger. In Unity you would use the same logic, but with the left hand.

However this does not affect the projection matrix as Unity uses the OpenGL convention for the projection matrix. The required z-flipping is done by the cameras worldToCameraMatrix. So the projection matrix should look the same as in OpenGL.

By using my ProjectionMatrixEditorWindow you can view (get) and edit (set) the projection matrix of the main camera inside the editor. This is an editor script so just place it in a folder called "editor". You can open the window via menu (Tools --> ProjectionMatrixEditor).

As you can see the resulting matrix looks similar to the one you've posted. However in Unity L and R (as well as T and B) are always of equal size so the (R+L) term (as well as the (T+B) term) result in "0".

Unity has an example script in the docs how to setup a custom off center perspective matrix.

edit
I forgot to mention that since Unity can run on different platforms using different APIs (DirectX / OpenGL) the actual projection matrix representation inside the GPU might be different from the representation you use in Unity. However you don't have to worry about that since Unity handles this automatically. The only case where it does matter when you directly pass a matrix from your code to a shader. In that case Unity offers the method GL.GetGPUProjectionMatrix which converts the given projection matrix into the right format used by the GPU.

So to sum up how the MVP matrix is composed:

  • M = transform.localToWorld of the object

  • V = camera.worldToCameraMatrix

  • P = GL.GetGPUProjectionMatrix(camera.projectionMatrix)

  • MVP = P V M

ps: If i messed something up, feel free to leave a comment. ^^

Comment
Add comment · Show 6 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Zenggang · May 27, 2016 at 11:04 AM 0
Share

Thanks for this info

avatar image yishixqg · Mar 20, 2018 at 01:52 AM 0
Share

Hi @Bunny83 , thanks for your explanation, it's great. But I still have several questions. I learned about projection matrix from this link. I know Projection matrix = NDC matrix * Perspective matrix. I also attach 3 figures to help me explain myself.

You said in Unity, R and L (T and B) are alwasy of equal size. So (R-L) and (T-B) will be 0 in those deno$$anonymous$$ators part, which makes no sense. So I think those entries should be 0 (the first 2 rows in the projection matrix). Right? Also the F and N are the far and near clipping plane in Unity. Right? Thanks in advance.

![projection matrix][4]

proj.png (41.0 kB)
avatar image Bunny83 yishixqg · Mar 20, 2018 at 03:19 AM 0
Share

They are of equal size but don't have the same sign. If you read my sentence again the term (R+L) is equal to 0. Therefore (R-L) can't be 0 if R and L are not both 0 as well. "R" is usually positive since it's on the right side and L is negative since it's on the left. If R = 1 and L = -1 the term (R-L) would be "2". That's why when you look at the ortho example of the page you've linked you have a term like 2 / (R - L) which would be just "1".


The values of R, L, T, B actually specify what value you will have at the right, left, top and bottom edge of the screen. So if you would have R = 5 and L = -5 the x range would be "10". So an inco$$anonymous$$g coordinate in camera space can reach from -5 (left edge of the screen) to +5 (right edge of the screen). The projection matrix simply turns the coordinates into clipspace so the values goes from -1 to 1. 2/(R-L) would become 2/10 == 1/5. So an inco$$anonymous$$g coordinage is basically divided by 5 which gives you your desired range of -1 to 1 for inco$$anonymous$$g coordinates of -5 to 5. If you have an off-center projection where R and L are not of equal size you would also have an offset term in the 4th column.

avatar image Bunny83 yishixqg · Mar 20, 2018 at 04:17 AM 0
Share

The person who made the page you linked used some terms in a wrong way. NDC (normalized device coordinates) are the coordinates after the perspective divide which is performed by the GPU. The Projection matrix actually outputs homogenous clipspace coordinates which are similar to NDC but before the normalization.


I'm not sure why he actually splits the "projection" into two parts. What he calls the "NDC matrix" is actually an orthographic projection matrix. However when doing a perspective projection any orthographic relation becomes quite pointless. The scaling of the coordinates depends on the frustum angles. Perspective projection does not have a left / right / top / bottom value. Each projection matrix will produce clipspace coordinates.

avatar image yishixqg Bunny83 · Mar 20, 2018 at 06:08 PM 0
Share

Thanks so so much. You are so kind. Now, I understand R = -L. I will try it out. Thanks again :)

Show more comments

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Can you serialize custom camera projection matrices? 1 Answer

WorldToViewportPoint and ViewportToWorldPoint math 2 Answers

Possible to use an oblique frustum camera and still be able to change the fov? 1 Answer

Custom camera projection matrix of orthographic camera 1 Answer

Generating rays from cameras with custom projection matrices 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges