6
\$\begingroup\$

I'd like to understand under what circumstances (if any) it is worth doing MVP matrix multiplication inside a vertex shader.

The vertex shader is run once per vertex, and a single mesh typically contains many vertices. All MVP inputs remain the same for each vertex in the vertex batch relating to a given draw call (model). Surely then, you're always better off keeping the multiplications in the client code, such that you pass in the whole MVP precalculated as a uniform? (avoiding redundant ops between individual vertices)

\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

If all you need to transform is the vertex positions, then I agree that there's no reason not to precompute the entire MVP matrix.

If you need to transform things like normal vectors and tangent vectors as well, you'll need more matrices. Probably your normals and tangents should end up in world space, or perhaps view space, so you'll want to transform them by just the local-to-world matrix, or the modelview matrix, but not the projection matrix.

Given this, it's possible to compute the positions in two ways - either by using one matrix multiply by a precomputed MVP matrix, or by doing two matrix multiplies, one going from local to world (the same matrix as for tangent vectors) and then from world to clip. If you use the MVP, you have to set two matrices per draw call, the MVP and the local-to-world matrix. If you use the second method, you only have to set the local-to-world matrix per draw call, since the world-to-clip matrix is constant for the whole frame. It's possible that setting one matrix vs two could make a difference in performance or memory usage in some cases. That's the only reason I can think of that using a precomputed MVP matrix might not be best.

All in all, I'd probably just use the precomputed MVP matrix unless you find a compelling reason to try it the other way.

\$\endgroup\$
3
  • \$\begingroup\$ Thanks. When you say, "Set the matrix", you are referring to setting it as a uniform, and thus transferring additional data over the bus, correct? Such that there's a small potential performance gain to be had there. \$\endgroup\$
    – Engineer
    Jul 6, 2012 at 20:56
  • 2
    \$\begingroup\$ @NickWiggill Yes, that's what I mean. The gain is one fewer matrices per draw call sent over the bus - but the cost is one more matrix-vector multiplication per vertex. So whether there's a performance gain at all really depends on whether bus bandwidth or vertex computation is the more precious resource at the moment. \$\endgroup\$ Jul 6, 2012 at 21:05
  • \$\begingroup\$ One point worth noting is that your shader compiler may be able to detect that you're doing a two-matrix multiply in your vertex shader and pull it out then perform it once-only on the CPU for you. Not sure about GL or ES (MS have a patent - yuck), but I do know that the D3D compiler can do this. Look up "preshaders" for more info. \$\endgroup\$ Jul 7, 2012 at 2:40

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .