While experimenting with different ways to bake an AO map for fairly lowpoly objects with normal maps on them inside Blender I noticed that - for some reason - normal maps don't display correctly on edges and cylindrical shapes.
So, I made a simple test object and baked normals for it in Marmoset Toolbag:
Then I've set up a scene with just an HDRI map as a background, no lights, and disabled color management.
The object material is also as simple as it gets:
And here's how it looks in Cycles:
My first thought was to check if the normal map is in correct format - well, it is, flipping the green channel makes things even worse. The interesting part is, the exact same scene in Eevee looks completely fine, just as it should
Am I missing something important here? Can this be fixed or is it just the way Cycles does things?
Edit: whoops, forgot to add the file (and texture)
Replies
"Am I missing something important here?"
Yes - the upload of your file !
I have a sneaking suspicion that the AO node may be utilizing Cycles for its raytracing (I doubt that the folks who worked on it would decide to create a whole new raytracer just for this node), and as a consequence be using the same shading information as Cycles. If that turns out to be the case It would explain a lot of things, but still I wonder if I'd be able to work around that
As for the possible difference between both renderers : in the case of Blender they are definitely supposed to behave the same, as this has clearly been the goal ever since Eevee first came out. So at the very least this means that whatever issue you are running into should be of some interest to the devs.
Couldn't test in detail without the textures, but found a few things which might cause Cycles to render not as expected.
In Color Mangement set Display Device to srgb and don't use a fully white colour in the material.
As for color management - yeah I also tried that, the issue doesn't go away, just becomes less noticeable
You can expect differences from reflections and GI in Cycles too, but that shouldn't cause the faceting that we're seeing here.
And in Cycles:
The normal map seems to be doing its job, but there's still faceting on top of it
I checked in Toolbag and I'm seeing a similar issue, in both the raster (Eevee-like) and ray-traced renderer (Cycles-like).
In Toolbag this can be improved by adjusting the shadow offset. I think Blender has a similar setting but I forget what it's called.
That would be really unfortunate if it turns out to be a given with all raytracers. I know that at least 3DS Max's Scanline renderer doesn't have such issues with normal maps, but I'm not sure if that piece of ancient technology has anything in common with modern ray-tracing engines.
Modifying the geometry to support the normal map isn't really an option in my case, since I work with the kind of game assets where tris are limited and the normal map does the heavy lifting, so to speak, so guess I'll have to keep looking for ways to minimize these artifacts (or think about ditching raytracers from my workflow alltogether)
For best results, the normal map should be used to represent fine detail that doesn't affect the silhouette, while the primary forms should be represented in the low poly. Of course, you'll be triangle-limited depending on the project, target hardware, etc. But generally, if you can't afford to bevel a cube it's probably not a very important asset or something you would inspect up close. So I would think about presenting it more how you might view it in the game in these cases.
It's also worth noting that the vertex cost for adding a hard edge is roughly the same as beveling the edge. There's a small cost for the additional triangles, but it's really the vertex count that tends to matter for performance. In many cases, you'll be draw call limited as well, and there may not be any difference between a 300 triangle or 3000 triangle mesh on modern hardware, drawing it as a unique object is the expensive part.