There's an eastern european guy who works for Rockstar Games who is claiming that he's written a game engine which requires no Matrices, even in the Shaders. In fact, he's been published now, in GPU Pro 3.

This got me interested, because I've never seen actual evidence that a Projection transform can be imparted to the shader without using a matrix.

I tried to get my hands on more information, but after 12 hours of scouring the internet, I failed to do it (although I was able to get my hands on the sourcecode for the exercises in the book, via its editors personal blog, and sure enough, there's no source for that chapter).

So began my analysis of the Projection Transform, and here is posted some notes that I made, which explain what the Matrix is doing, and why. Knowing this, we can see clearly that we DON'T need a Matrix to do it.

This got me interested, because I've never seen actual evidence that a Projection transform can be imparted to the shader without using a matrix.

I tried to get my hands on more information, but after 12 hours of scouring the internet, I failed to do it (although I was able to get my hands on the sourcecode for the exercises in the book, via its editors personal blog, and sure enough, there's no source for that chapter).

So began my analysis of the Projection Transform, and here is posted some notes that I made, which explain what the Matrix is doing, and why. Knowing this, we can see clearly that we DON'T need a Matrix to do it.

Matrices are just a convenient way to handle a lot of multiplications and additions.

My 286 code doesn't use matrices either, because the maths are simplified and many parts of the matrix would remain 0 if I used a matrix.

So instead I just perform the required multiplications and additions directly, and then do a perspective divide, et voila.

No matrices... but hardly a spectacular conclusion.

My 286 code doesn't use matrices either, because the maths are simplified and many parts of the matrix would remain 0 if I used a matrix.

So instead I just perform the required multiplications and additions directly, and then do a perspective divide, et voila.

No matrices... but hardly a spectacular conclusion.

I think matrices are only convenient WHEN they are imparting lots of linear operations - if we are just doing something simple, they are wasteful, in every sense. I am not a fan of blindly using any tool, this is a great example of cracking a walnut with a sledgehammer in most cases.

Further, homogenous 4D stuff is not that hard to grasp, compared to matrices, its easy!

We should be teaching this from the start, not making it an adjunct, and making it seem hard when its trivial.

We should be teaching this from the start, not making it an adjunct, and making it seem hard when its trivial.

Further, homogenous 4D stuff is not that hard to grasp, compared to matrices, its easy!

We should be teaching this from the start, not making it an adjunct, and making it seem hard when its trivial.

That's how I learnt it anyway. Matrices came later.

Lucky you! Thats how it should be taught.

I learned 3D cartesian stuff, then matrices, then 4D vectors, and finally, tensors. Back and forth.

It makes sense to teach what it used most, first, and what it used least, last, but it made things a lot more confusing than they needed to be, I was left without a natural understanding of the forms which I had to figure out retrospectively, and without the benefit of understanding greek notation.

I learned 3D cartesian stuff, then matrices, then 4D vectors, and finally, tensors. Back and forth.

It makes sense to teach what it used most, first, and what it used least, last, but it made things a lot more confusing than they needed to be, I was left without a natural understanding of the forms which I had to figure out retrospectively, and without the benefit of understanding greek notation.

I bet Hamilton is rolling in his grave! :P

I think it depends on your definition of 'teaching'.

You can't really 'teach' matrices, they are just a notation for linear equations.

So regardless whether you teach how a perspective projection/homogenous coordinate system works via direct equations, or via matrix form...

If you understand matrices, you can write out the equations yourself, given a projection matrix. Or conversely, if you have some projection equations, you can construct a matrix.

If you cannot perform those operations, I would say you have not been taught properly, because you cannot perform these basic rewriting steps.

You can't really 'teach' matrices, they are just a notation for linear equations.

So regardless whether you teach how a perspective projection/homogenous coordinate system works via direct equations, or via matrix form...

If you understand matrices, you can write out the equations yourself, given a projection matrix. Or conversely, if you have some projection equations, you can construct a matrix.

If you cannot perform those operations, I would say you have not been taught properly, because you cannot perform these basic rewriting steps.

I've finally found a real honest to goodness example of a matrix-free shader.

It's not a particularly useful shader in the form presented, however, the rest of the document is quite thorough and worth reading.

This information should be more than enough for anyone who wishes to eliminate projection matrices (and all the others) from their video pipeline.

http://www.arcsynthesis.org/gltut/Positioning/Tut04%20Perspective%20Projection.html

@Scali, I agree with you that it's just a container representing a bunch of linear operations, however there's a lot to learn besides that, things we take for granted if we 'know' them, like, reciprocal inversion (relationship between matrices and their inverses with respect to order of multiplication), and lots of nifty tricks, like transposition of 3x3 matrices as a quick inverse, stuff we only learn by having it taught to us (even if that means we sought the information and 'taught ourselves').

A lot of that stuff simply isn't obvious, and especially to the novice (some people just seems to 'get it', I wasn't so lucky). It's also worth noting that matrices can be used for purposes other than relating linear operation sequences, they can represent numerical distributions, useful for predicting things like market trends, and also useful in physics, for representing things like mass distribution over orthogonal axes, solving general systems of simultaneous equations, and higher dimensional math that makes my brain hurt without a matrix to help me.

It's not a particularly useful shader in the form presented, however, the rest of the document is quite thorough and worth reading.

This information should be more than enough for anyone who wishes to eliminate projection matrices (and all the others) from their video pipeline.

http://www.arcsynthesis.org/gltut/Positioning/Tut04%20Perspective%20Projection.html

@Scali, I agree with you that it's just a container representing a bunch of linear operations, however there's a lot to learn besides that, things we take for granted if we 'know' them, like, reciprocal inversion (relationship between matrices and their inverses with respect to order of multiplication), and lots of nifty tricks, like transposition of 3x3 matrices as a quick inverse, stuff we only learn by having it taught to us (even if that means we sought the information and 'taught ourselves').

A lot of that stuff simply isn't obvious, and especially to the novice (some people just seems to 'get it', I wasn't so lucky). It's also worth noting that matrices can be used for purposes other than relating linear operation sequences, they can represent numerical distributions, useful for predicting things like market trends, and also useful in physics, for representing things like mass distribution over orthogonal axes, solving general systems of simultaneous equations, and higher dimensional math that makes my brain hurt without a matrix to help me.

Well, while it is a good thing to understand how things like projection, rotation, scaling, translation etc work without matrices, I'm not sure why exactly one would want to get rid of them.

The hardware is designed for matrix/vector operations, and an entire 4x4 matrix*vector operation only takes 4 instructions. 4 instructions is not a lot of 'wiggle room' if you get what I mean.

The reason why 4x4 matrices are so popular is that a single matrix can encode any possible combination of transformations possible. So in the general case, only one matrix is required to take your vertices directly from object space to screen-space (the actual perspective-divide is 'free' as it is still performed in a fixed-function unit when the output of the vertex shaders is fed to the rasterizer).

So, all you have to do is concatenate all your matrices once, on the CPU side, then send it to your vertex shader, et voila. A single matrix*vector operation does the trick, in only 4 instructions. The tutorial you linked to, will not generate code that is as efficient as this. And that is just a very basic example.

The hardware is designed for matrix/vector operations, and an entire 4x4 matrix*vector operation only takes 4 instructions. 4 instructions is not a lot of 'wiggle room' if you get what I mean.

The reason why 4x4 matrices are so popular is that a single matrix can encode any possible combination of transformations possible. So in the general case, only one matrix is required to take your vertices directly from object space to screen-space (the actual perspective-divide is 'free' as it is still performed in a fixed-function unit when the output of the vertex shaders is fed to the rasterizer).

So, all you have to do is concatenate all your matrices once, on the CPU side, then send it to your vertex shader, et voila. A single matrix*vector operation does the trick, in only 4 instructions. The tutorial you linked to, will not generate code that is as efficient as this. And that is just a very basic example.

Reason is because, as you said, hardware is designed for vec4 operations (matrix4 is an extension of that).

We can fit all the data for all the major transforms into less space than one matrix4 requires, and do a few linear operations, less operations than matrices require, using the same optimized hardware pathways.

More FPS, 'for free'.

We can fit all the data for all the major transforms into less space than one matrix4 requires, and do a few linear operations, less operations than matrices require, using the same optimized hardware pathways.

More FPS, 'for free'.

As I say, there's only a very select subset of problems where this is the case.

On my 286 it's different, I don't have any vec4 hardware at all, so any operation that I can optimize because the matrix will always contain 0, 1 or -1 for a particular cell, saves calculations.

But on a machine with SSE, or on a GPU, as I say, it only takes 4 instructions to perform a matrix*vector operation. So you can only do 4 operations max. Which is not a whole lot.

And the great disadvantage of that would be that it would only work for the select subset of problems. You'd have to rewrite your code if you happen to want to use a slightly different transform (which may negate any savings you had in the first place). Matrices can encode any possible transform in homogenous 4d space, so the same code will work, no matter what kind of animation, camera, projection etc you want to apply.

In other words: not a good place to try and save a few cycles. The phrase "More trouble than it's worth" comes to mind.

I think the easiest way to try and save some cycles/space is to use 3x4 matrices if you can. Most transforms will only use the 3x3 portion for rotation and scaling, and one row (or column, depending on your orientation) for a translation. Which means that you always have one column (or row) that is (0,0,0,1).

But again, you're limiting yourself in terms of transforms. The projection matrix is one of the exceptions where you would be using more than just the 3x4 portion of the matrix.

On my 286 it's different, I don't have any vec4 hardware at all, so any operation that I can optimize because the matrix will always contain 0, 1 or -1 for a particular cell, saves calculations.

But on a machine with SSE, or on a GPU, as I say, it only takes 4 instructions to perform a matrix*vector operation. So you can only do 4 operations max. Which is not a whole lot.

And the great disadvantage of that would be that it would only work for the select subset of problems. You'd have to rewrite your code if you happen to want to use a slightly different transform (which may negate any savings you had in the first place). Matrices can encode any possible transform in homogenous 4d space, so the same code will work, no matter what kind of animation, camera, projection etc you want to apply.

In other words: not a good place to try and save a few cycles. The phrase "More trouble than it's worth" comes to mind.

I think the easiest way to try and save some cycles/space is to use 3x4 matrices if you can. Most transforms will only use the 3x3 portion for rotation and scaling, and one row (or column, depending on your orientation) for a translation. Which means that you always have one column (or row) that is (0,0,0,1).

But again, you're limiting yourself in terms of transforms. The projection matrix is one of the exceptions where you would be using more than just the 3x4 portion of the matrix.

As noted, turns out that the traditional projection transform can be simplified, without altering the mapping, that is a game changer. That's what I got interested, and with a single dual quaternion for mapping the other two major matrices, it becomes clear that we can indeed win, for a given projection, world and view.

As long as we already baked scale out of the picture, we can win easily.

If we need to scale model space, its messier.

If we need to scale model space, its messier.

As noted, turns out that the traditional projection transform can be simplified, without altering the mapping, that is a game changer.

How exactly?

You have 4 instructions to work with.

You'd need 3 instructions to perform rotation, scaling and translation. Which I'd say would be the minimal for any regular transform from object space to screen space.

That gives you exactly one extra instruction to set up the projection.

So how is it better at all? Let alone a 'game changer'?

That's what I got interested, and with a single dual quaternion for mapping the other two major matrices, it becomes clear that we can indeed win, for a given projection, world and view.

Okay, work out the math and post it here, then we'll see how many instructions it takes. I'd be surprised if you can come up with a solution with less than 4 instructions.

Seriously, u CANT just pass in a PVM matrix , u NEED to pass TWO at least, you know this, right?

I won't argue you know this means, at least, a 4x4 matrix mul in the shader, and thats NOT 4 operations. And we didn't even process a vertex yet.

I won't argue you know this means, at least, a 4x4 matrix mul in the shader, and thats NOT 4 operations. And we didn't even process a vertex yet.

I mean, unless we are drawing one object, only, we need to calculate PVM somewhere, true?

Seriously, u CANT just pass in a PVM matrix , u NEED to pass TWO at least, you know this, right?

Uhhh, what? Why would you need two?

I mean, unless we are drawing one object, only, we need to calculate PVM somewhere, true?

Not in the vertex shader (where you'd be doing it per-vertex, rather than per-object).

So why would you need more than one matrix in the vertex shader?

You cannot show more than one object with 'four instructions'. So it wont work for anything other than a very simple demo drawing one model space. Don't try to talk s***. You need a unique modelspace transform for every instance of a geometry. You know that you can't just send one WorldViewProj for everything. Let alone we talk about things like lighting and shadowing, which you obviously think are all best done in viewspace. Seriously man, you can't just send one matrix and call it a day. Jeez.

And thats using ONE shader! If we have more than one shader, there's no guarantee that uniforms will be stateful, we need to re-transmit them when shaders switch!

And thats using ONE shader! If we have more than one shader, there's no guarantee that uniforms will be stateful, we need to re-transmit them when shaders switch!