Skip to main content
1 of 2
Chuck
  • 249
  • 3
  • 12

Following @DMGregory's excellent feedback, I wrote the following class to test:

public class MaterialTextureTest : MonoBehaviour
{
    public Material material = null;
    public List<string> textureNames = new List<string>();
    public List<Texture2D> textures = new List<Texture2D>();
    // Start is called before the first frame update
    void Start()
    {
        if(material!=null)
        {
            string[] names = material.GetTexturePropertyNames();
            foreach(string name in names)
            {
                textureNames.Add(name);
                textures.Add((Texture2D)material.GetTexture(name));
            }
        }
    }
}

This showed the material has the following texture property names:

_MainTex
_AlphaTex
_BumpMap
_NormalMap
_DetailNormalMap
_BaseMap
_MetallicGlossMap
_ParallaxMap
_OcclusionMap
_EmissionMap
_DetailMask
_DetailAlbedoMap
_SpecGlossMap
_MaskTex

I'm using the Universal Render Pipeline and my test material is using the "Simple Lit" shader. I've got a texture put into the "Normal Map" section of the "Surface Inputs" portion of the material, but I actually drew a grayscale image to use for the normal map, with the intention of using it as a true bump map.

I believe this is handled on the texture, because there's a checkbox on the texture properties that says "Create from Grayscale" that I ticked.

I used the grayscale/bump map texture as the input to the "Normal Map" setting for my material, so the elements in my textures List from the test class above are:

Element 0    <My image texture>
Element 1    None (Texture 2D)
Element 2    <My bump map texture!>
Element 3    None (Texture 2D)
Element 4    None (Texture 2D)
Element 5    <My image texture>
Element 6    None (Texture 2D)
Element 7    None (Texture 2D)
Element 8    None (Texture 2D)
Element 9    None (Texture 2D)
Element 10   None (Texture 2D)
Element 11   None (Texture 2D)
Element 12   None (Texture 2D)
Element 13   None (Texture 2D)

So now I can see that I can access my bump map by calling:

Texture2D bumpMap = (Texture2D)material.GetTexture("_BumpMap");

Then finally I just use this line instead of the:

Texture2D texture2D = renderer.material.mainTexture as Texture2D;

line in the snippet from my question to access the bump map, just like DMGregory said. Now the "color" (grayscale) I get back from the .GetPixel() line returns the grayscale value I wrote.

I think a super noteworthy point here is that most "bump" maps are actually normal maps, which are the blue/purple looking maps like CrazyBump or similar would generate. I'm trying to encode a height offset on the objects to use for modifying the Raycast results, so there's this double benefit for me in that the grayscale bump maps seem to actually correlate better to a height than the surface normals, but also that the actual grayscale bump maps are rarely used, so it's like this hidden channel included in all materials.

For my test material, with a grayscale bump map, the _NormalMap entry in the material is null! I am expecting the opposite to be true for most standard materials - the _BumpMap entry will probably be null because most modern materials will be using an actual normal map.

All that is to say I can try to get the _BumpMap texture and check if it's null. If it's null it's probably not a material I've made, which means I skip the raycast modification and use the actual results. If it's not null, then I can get the color as described above and use that to modify the results.

Chuck
  • 249
  • 3
  • 12