# Why do we call it TRS and MVP, instead of SRT and MVP or TRS and PVM?

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.

• 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. – 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.
• @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." – lightxbulb Oct 14 '19 at 19:37
• 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. – Thomas Oct 14 '19 at 20:03
• You would obviously get wrong results if you do mvp * vector, as you did in the first case. You should have done: vector * mvp. – lightxbulb Oct 14 '19 at 20:17
• 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? – Thomas Oct 14 '19 at 20:45