Correct Motion Blur for Fast Rotating Objects - aka - The Stupidest Motion Blur Technique Ever

Any reasonable person: WHAT??

Me: OK, lemme get right to the point:

The secret is... Simply, rendering multiple transparent meshes!!

** awkward pause **

Yes, that's it!

** awkward pause **

Any reasonable person: That is the stupidest thing I ever heard... That sounds so wrong!! Why would you do that?

Me: Ok here we go...

Lets start from the beginning...

Rendering fast moving rotating objects is a challenge, what we want to have is that nice smooth motion blur that we see for example in propeller aircraft or helicopters!

Poor solution #1: Blurred Texture Motion Blur

..But since the time I know about video games, the most common method of creating believable motion blurred rotating objects is to pre-render blurred rotors onto a texture. Then, in the game, we would switch between different 'blurs' at a certain speed (RPM), keeping the original 3D mesh only as the 'step 1' - for the non-blurred, 0 to very low RPM rotor.

Here is an example with the airplane from Unity's Standard Assets:


Here we can see alphas of, in this case 3 texture 'steps' that will be switched according to RPM

While this looks nice and is a very performant solution..


..the first obvious problem is that there is no 'depth' since the propeller is now a thin plane.

Comparing that to the base model at 0 rpm:


..we can see there is a considerable difference in depth. We can also see there will be a jarring switch, not only between the 'idle 3D' propeller, but also between 'blurs' themselves. Actually, the more blurred textures we have, the better. But we can't have an infinite amount of blurs so we need to pick a certain reasonable number.

An even bigger problem is that we need to pre-render these textures, so, takes away artists' time.

Any reasonable person: But man, these are all decade old methods! Now we have superawesome post processing motion blur!

Poor solution #2: Post Processing Motion Blur

Me: Yes post processing motion blur is superawesome, but..

First, the way that motion blur works is that it renders all motion into a 'motion vectors' map.


This is all nice if you have objects moving in a straight line but the problem is that the vectors are linear. The motion vectors map gives no information about rotation. As a result, any fast moving rotating object is going to look incorrect.


We can see on this propeller that the pixel has been blurred linearly instead of being blurred in an arc. Which is not what we would like.

While head on, it doesn't look so bad, at different angles it becomes worse and linearity more evident.


Now, if you think "well, that's not thaaaat bad", take a look at the example wheel:


Not only does it produce 'fringing' effect on the outside of the wheel, it also produces low quality smudges on the inside due to the thin nature of the spokes.

Instead of straight lines, we would really need arcs with a center at the rotation pivot:

Yellow: original, green: desired


Of course this is no small feat and would require reconstructing rotations n stuff (..that I don't really understand since I'm no hard core graphics programmer).. Maybe a future rendering method will be able to provide information about rotation (maybe there is already, I'm just not aware of it. If there is no, there's an idea for graphics programmers! :D )

Another consequence of post processing motion blur is that it is a screen-space effect. There is no information about anything that is not visible, hence the blur will be clipped on the edge of the screen, and there will be a lack of information if it is occluded by some other object. It also depends on the pixel density, so if it is far from the screen it will be much less precise.

Any reasonable person: Ok, so what's your deal?

Enter multiple mesh rendering technique

I can't believe how stupid this technique is, yes, you literally render meshes multiple times with reduced transparency, that's it!!!


First, what we get out of the box is depth! Or lets say... width, just not to confuse with 'z' depth. Since we literally render 3D meshes multiple times, the full shape is preserve, so it will look correct when we look at it from the side.


Second out of the box property is that it just works with any kind of mesh, not just relatively thin objects like propellers or stuff that can be seen from only one side like wheel rims. It can even be rotated around absolutely any axis! Like.. we can even switch axes during play and it will still look good!

Spinning rider character mesh from Trails of Ténéré

Another very cool thing is that the lighting is actually correct. Normals are preserved and likewise work in every viewing direction. There are no baking artifacts which you would get with a blurred texture technique.

mmmhm.. shiny

And should I just mention that there are no problems mentioned in the "why post processing motion blur sucks" section?!?

Now since we are rendering the SAME mesh, on modern graphics hardware we can use GPU instancing, so that we reduce the draw calls and relieve the CPU. Additionally, since we have rotation from the same point and along the same axis, that also means calculating all matrices for each instance is pretty simple.

Here is a WebGL demo! You can see it on a bike wheel from Trails of Ténéré or a propeller from a previous unpublished project.

Any reasonable person: If it's so awesome then why is it not more common?

Me: Well, you see, the reason is that it is not actually THAT awesome..

Ok, there are a few problems..

First, we need to render the mesh multiple times, and the more meshes we render, the better the effect is. This puts a big strain on rendering. Since transparent blending is already pretty expensive, especially the more pixels we can see.

If we render too few meshes, we will have obvious undersampling. This is especially problematic with high aspect ratio objects, i.e. "long and thin", like helicopter rotors. The higher the aspect ratio the more samples we need to render to produce a smooth result at the tips.

Too few meshes results in undersampling

Just the right amount of meshes for the blur to be practically continuous

A possible optimization we can make is decrease the number of rendering objects depending on the speed and on the screen size.

Another big problem is since we are rendering a transparent mesh, there will be some sorting issues. I've deduced experimentally that sorting between the blurring meshes themselves is not really an issue. Even if they might be changing order back an forth, as long as you have enough meshes to not create visible undersampling, it is not visible (since it's deduced experimentally I'm not sure if I was just lucky). A bigger problem is sorting with other objects in the scene..


Woops, as you can see, blurred wheels and particles don't like each other too much. In this case you will need to manually handle sorting order.

Another problem that comes from transparent blended meshes is that they are not written to the depth map. This means that no image effects that depend on depth will work, so no SSAO for example.

In case of an airplane propeller and SSAO, this is not really a big deal because they are 'out in the open' anyway. But, in case of a car wheel that is surrounded by a wheel well and the ground, you really want that sweet SSAO to work. So it's a thing to consider.

There could be issues with other image effects too that are being applied on the opaque objects in the background and isn't cleared by the transparent propeller meshes above.

However, if you don't have any depth-requiring image effects this is actually a pretty good solution for you!

Summary:

Pros

- Correct rendering from all sides with 'volume', unlike 'blurred flat plane' rendering.
- It works with any kind of mesh, and any axis of rotation, not just relatively flat or visible from only one side (like wheel rims)
- Correct normals and specular, especially evident if you have shiny bare-metal propellers
- Unlike post processing blur, it doesn't create linear smudges for fast rotating objects
- Also unlike post processing motion blur, it doesn't lack information that is outside of the screen
- No pre-processing required, unlike making blurred textures sheet in flat rendering

Cons

- Sorting. Since it relies on transparent blending, it must sort with itself and other stuff in the scene
- Rendering cost: since its rendering the same mesh multiple times. Partially mitigated (at least on CPU side) by GPU instancing
- Since it is transparent it will not be written to the depth map, so, any post processing effect that needs it like SSAO for example won't be rendered on it. There will probably also have shadow mapping problems too.

When to use it?

- If you have a single visible rotating object that is the main focus of the game. For example a first person view from the cockpit of a helicopter or a single-engine propeller aircraft. Since it will be visible pretty much all the time, you want the highest graphical fidelity for it.
- If you want the blurred mesh to reflect the changes in real time, if a propeller changes pitch or axis angle.
- If you have a no-shadows no-post-effects artstyle, it's actually perfect for you!

When not?

- If you have too many rotating objects, you probably DON'T want to use this method (or at least make some kind of LOD).
- If you rely on a lot of image effects that utilize a depth map, eg. SSAO.

Conclusion

As you can see from all the problems mentioned, it is not a universal solution. It is expensive, however if you need the highest fidelity spinning object motion blur you should strongly consider it. I know that I call it a hack, but it is actually a pretty good.. compromise.

Follow me on twitter for more hacks like this!
@nothke

Comments