Here's something that's been bothering me while learning graphics. We have two core concatenated matrix sets: "TRS" for transforms, and "MVP" for moving everything into the canonical view volume.

TRS is applied in this manner: T(R(S(p))), i.e. the scale is applied first, then the rotation, then the translation.

MVP is applied in this manner: P(V(M(p))), i.e. we apply the model matrix first, then the view matrix, and finally the projection matrix.

Why is the order in which we name these sets not consistent? I feel like I am getting something very obvious wrong, but I can't help but be confused by this.

  • $\begingroup$ MVP is actually not even consistent with itself - it encodes the transformation from model -> world -> view -> clip(projection) space. So to be consistent, it would be better to name it World-View-Projection. $\endgroup$ – russ Oct 15 '19 at 9:54

Because whether you use $MVP$ or $PVM$ actually depends on how you perform the multiplication: $vMVP$ versus $PVMv$, note that you have: $(PVMv)^T = v^TM^TV^TP^T=vM^TV^TP^T$, where the last identity does not hold in math, but holds in glsl since vectors can be reinterpreted as either row or column vectors for convenience.

The same holds for $TRS$ and $SRT$. In general CG code and applications have an issue with sticking to standard established conventions, so you get all kinds of funny conventions.

| improve this answer | |
  • $\begingroup$ I understand that it depends on whether you use column or row major matrix notation, which reverse the multiplication order. However, what I've seen often is that column major format is used (this appears to be the most common from the resources I see online, literature, and in gaming engines), but it's still called MVP and TRS within the same column major matrix context. For instance in Unity: docs.unity3d.com/ScriptReference/Matrix4x4.TRS.html docs.unity3d.com/Manual/SL-UnityShaderVariables.html $\endgroup$ – Thomas Oct 14 '19 at 19:21
  • $\begingroup$ @Thomas I don't understand the issue? In the link you provided they are doing $TRSv$ which is $TRS$. Column and row-major conventions are unrelated: en.wikipedia.org/wiki/Row-_and_column-major_order Their $MVP$ naming scheme seems to also be consistent with the description they have of it: "Current model * view * projection matrix." $\endgroup$ – lightxbulb Oct 14 '19 at 19:37
  • $\begingroup$ That's what the documentation says, but when I create 2 test shaders it appears to be the other way around, unless I am wholly confused about how mul() maps to MVP, which is absolutely possible. MVP: float4x4 mvp = mul(unity_ObjectToWorld, mul(UNITY_MATRIX_V, UNITY_MATRIX_P)); o.vertex = mul(mvp, v.vertex);, and this is the other way around: float4x4 pvm = mul(UNITY_MATRIX_P, mul(UNITY_MATRIX_V, unity_ObjectToWorld)); o.vertex = mul(pvm, v.vertex); If you run it in Unity, only the latter works as expected. $\endgroup$ – Thomas Oct 14 '19 at 20:03
  • $\begingroup$ You would obviously get wrong results if you do mvp * vector, as you did in the first case. You should have done: vector * mvp. $\endgroup$ – lightxbulb Oct 14 '19 at 20:17
  • $\begingroup$ Tried this now: float4x4 mvp = mul(unity_ObjectToWorld, mul(UNITY_MATRIX_V, UNITY_MATRIX_P)); o.vertex = mul(v.vertex, mvp); that still doesn't work though: imgur.com/a/t7vZpHy The green is with PVMv, the red is vMVP. Am I still doing something wrong? $\endgroup$ – Thomas Oct 14 '19 at 20:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.