How are Normal Maps created? How does one go about taking a single photograph, like a picture of a rock wall, and getting a decent normal map out of it?

If you can, I'd like to learn about the mechanics behind it, and not a piece of software like CrazyBump that does it for me.
"decent" is quite subjective and if you are restricting the capture to certain types of surfaces and controlled lighting conditions. For example normals and other SVBRDF parameters for shiny metallic surfaces are very difficult to capture compared to non-metallic, matte and bright surfaces without texture.

There are tools proposed in comments (CrazyBump, AwesomeBump) that try to do what you ask for and may generate normal maps sufficient to your requirements, but you could argue how "decent" the results are and how robust these tools are in capturing different types of surfaces. I don't know about the algorithms these tools use, but I believe they use more of an "artistic" than robust/accurate methods in generating the results.

There is some recent work to estimate normal map and other SVBRDF parameters using two images or from a single image (using neural networks), which is probably your best bet. However these algorithms assume a level of repeating pattern in the input images, but this might be ok for you since you mention rock wall as an example. There are likely other constraints as well such as requiring the captured surface to be dielectric hard surface material.

For more robust SVBRDF capturing you can check paper on frequency domain capture, but this is more complex capturing setup and far from a single image capture.


To my knowledge there's no known generic algorithm to accurately extract SVBRDF parameters from a single image of a non-repeating surface because of the fundamental issue that a single image can't unambiguously represent SVBRDF parameters. E.g. two different normal &amp; albedo combinations of a Lambertian surface may result in same pixel color in a single image.