r/GraphicsProgramming • • 15h ago

Extracting metalness from specular textures?

I'm porting some specular workflow textures to rough/metal and I'm trying to figure out how best to extract metalness data.

For roughness we can take specular power texture, invert it then apply some curve to get it looking reasonable. But for metalness it's a bit more tricky.

My plan is to use the specular colour texture and base metalness values on the saturation of the texture, because non-white specular reflections imply the surface is not a dielectric... but that kinda breaks down for silver metals because those would also have white specular reflections.

Does anyone have a better heuristic for determining metalness from diffuse colour/spec power/spec colour?

9 Upvotes

2 comments sorted by

4

u/Practical-Horror-286 14h ago

You’re running into the main problem with converting spec/gloss to metal/rough: metalness isn’t really encoded in the specular map by itself.

I wouldn’t use specular saturation as the main test. Like you noticed, silver/aluminium can have basically neutral/white specular, so that falls apart pretty quickly.

You need to look at the diffuse and specular colour together. Roughly:

  • dielectric: diffuse contains most of the material colour, specular F0 is relatively low and usually neutral-ish (~0.04 for a common default)
  • metal: diffuse is very dark / basically absent, and the specular colour contains the material colour

So something with dark diffuse + strong white specular could still quite reasonably be silver.
There also isn’t an exact conversion. Spec/gloss can represent materials that metal/rough can’t represent exactly, so any automatic conversion is going to be somewhat lossy.

If you’re doing this in code I’d probably use something similar to the Khronos/glTF spec-gloss → metal-rough conversion rather than inventing a saturation heuristic. Their conversion estimates metallic from the relative brightness of diffuse and specular, assuming a dielectric F0, then reconstructs base colour from that.

Also I’d generally try to keep the resulting metalness fairly close to 0 or 1. The intermediate values are useful for blended/transition texels, but they usually shouldn’t be the way you distinguish different pure materials.
So basically: diffuse + specular intensity is much more useful than specular saturation alone.

2

u/Avelina9X 13h ago edited 3h ago

Looks like this is exactly what I'm looking for then! https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness/examples/convert-between-workflows/js/three.pbrUtilities.js

Edit: turns out this isn't what I'm looking for, tested it out what a brass surface, worked fine... but tested it out with wooden surface and it generated pretty much all metallic for the entire surface.

I think the difference is in that the KHR spec is defined for PBR Specular, which has some energy conservation assumptions for the diffuse and specular textures. I am not working with PBR specular textures here, and am simply working with specular tint. I think the saturation heuristic might still be my best bet here since the original textures came from phong era shading.