This post is a quick follow up to my previous post on derivative maps. This time I’m going to compare the quality and performance of derivative maps with the currently accepted technique, normal maps.
I’ll be using the precomputed derivative maps for comparison since the ddx/ddy technique just isn’t acceptable in terms of quality.
Here’s the close up shot of the sphere with the moon texture again. This shows the derivative map implementation, and if you mouse over, you’ll see the normal map version.
There are some slight differences because the height of the derivative map doesn’t quite match the heights used to precompute the normal map, but overall I would say that they are remarkably similar. It looks to me that the normal map is preserving more of the detail though.
Here’s a high-contrast checkerboard, again with the normal map shown if you mouse over.
I’m no artist, but I would say the the derivative map results are close enough to the normal maps to call the technique viable from a quality standpoint.
EDIT: I had some issues with artifacts which I posted here. It turns out they were (embarrassingly) caused by my mipmap generation which was introducing a row of garbage at each level. Combined with FXAA and anisotropic filtering, this caused the weird vertical stripes I posted before.
I’ve removed the images since I don’t want to give the wrong impression of the quality of derivative maps.
I ran these tests on my Macbook Pro which has an AMD 6750M. The shader in question is a simple shader for filling out the gbuffer render targets. All shaders were compiled using shader model 5. I took the frame times from the Fraps frame counter and the other numbers came from Gpu Perf Studio.
For comparison, I’ve included an implementation with no normal perturbation at all.
|Perturbation||Frame||Pixels||Tex Inst||Tex Busy||ALU Inst||ALU Busy||ALU/Tex|
|None||1.08 ms||262144||3||27.5 %||14||32.1 %||4.667|
|Normal map||1.37 ms||262144||4||36.5 %||23||52.4 %||5.75|
|Derivative map||1.36 ms||262144||9||82.0 %||28||63.8 %||3.11|
Despite the extra shader instructions, the derivative map method is basically as fast as normal maps on my hardware. As Mikkelsen predicted, it seems like having one fewer vertex attribute interpolator offsets the cost of the extra ALU instructions.
Note that the derivative map shader has nine texture instructions compared to just four for the normal maps. The extra five instructions are the two sets of ddx/ddy instructions, and the instruction to get the texture dimensions. The pixel shader can issue one texture instruction and one ALU instruction on the same cycle, these are essentially free.
The only performance overhead which has any impact for derivative maps are the five extra ALU instructions.
As I mentioned in my previous post, derivative maps also have the tremendous benefit of not requiring tangent vectors. In my case, with a simple vertex containing position, normal, tangent and one set of texcoords, the tangent takes up 27% of the mesh space.
Given that most games these days have tens of megabytes of mesh data, this would turn into some pretty decent memory savings. There’s also a minor benefit on the tool-side to not having to spend time generating face tangents and merging them into the vertices.
Well, for me it’s pretty clear. On my setup, derivative maps have a similar quality with the same performance but less memory. This makes them a win in my book. Of course, these numbers will vary wildly based on the API and hardware, so this can’t be taken as a blanket ‘derivative maps are better than normal maps’ statement, but they look promising. Good job Morten Mikkelsen!
I would love to see a similar comparison for the current generation of console hardware (hint, hint!).
If you have DirectX 11, then you should be able to run the demo here.