Wednesday, July 29, 2015

Substance designer/painter PBR textures to mental ray

Hey there!

Substance designer and painter (SP) are awesome packages. If you're reading this, you probably agree. And, like me, you are probably also looking for a way to get those PBR textures to render nicely in mental ray (MR). Now I couldn't find any solution online, so instead I went to set out to see how I could reproduce SP rendering in MR. And I wouldn't be writing this if I didn't find something that seems to work ;)

If you just want the results, scroll down a bit to conclusion and you'll get the setup I ended up with.

First of all, let me mention I used the MR "mila_material". I started with a mia material, but mila is the future! And also much more convenient for our purposes. So; basic diffuse layer and a glossy reflect layer.

image 1

Step 1: Roughness

The first step is to just compare stuff. The mila_material has a fresnel based reflective specular with a roughness input. That already pretty much sounds like what a SP PBR shader consists of. So I threw a sphere in a SP and a Maya scene, gave them the same HDRI environment, and hit render. Then a moved the roughness sliders a bit and hit render again. I did that a couple of times and got this:

image 2: roughness comparison

So, at first glance, the 40% roughness in SP seems to correspond with about 75% roughness in mental ray. I figured I make a custom attribute on my sphere in maya, and patch it through a value remap node into the roughness on the mila_material, and see just remap the input values somewhat to have that custom value correspond properly with the SP roughness value.

What I got after some fiddling around is something that looked like this:
image 3: roughness remap curve
And I thought to myself, that looks a lot like a gamma curve... Let's ditch the value remap, and try a gamma correction node instead. So I played a bit with the values there, and ended up settling with a gamma value of 2.2...Haha.
For anyone who ever did anything with gamma correction, this value should sound familiar. Now I'm not entirely sure how SP was intended to work (and I am no expert on all this gamma stuff), but I've also noticed that in Marmoset, the gloss map needs to be flagged as 'sRGB space' to have the correct effect... also, a gloss map seems to be the inverse of roughness in sRGB space, while inversing it in linear space should give a totally different outcome... Whatever the case, a gamma correction of somewhere between 2.2 and 2.4 gives a good result (I prefer 2.4 myself, I want that roughness to really show)

Also, noticed how the higher roughness values leave the renders in MR much more shiny? It seems that in SP the specular values are toned down as roughness goes up. I went with a gut feeling and hooked up the inverse of the roughness through the same gamma correction and connected that the the specular tint. Again, left is SP, right is MR:
image 5: roughness affecting spec value
Not exactly the same results, but it looks pretty good to me. Personally, I like the rimlight a white spec creates on rough surfaces in MR, so I hooked this inverse roughness up through a very high gamma so only the very high values (say, 0.9 and over) start to eat away at that rim-light effect (mainly to prevent that weird velvet fresnel you see happening with the 100% roughness in image 2).

Step 2: Metallic. I mean, fresnel.

There is no Metallic slider on the mila_material. But thats ok; there is a fresnel IOR slider. The substance folks have some really nice documentation on PBR, including some information on what to do with IOR. Read it if you haven't already. Anyway, first step is to get that non-metallic look to be the same. Left side; SP with 0% metallic,  right side some mental ray renders.

image 6: iOR
1.2 was too dim, 1.5 too glossy; 1.4 seemed just about right to me.
Non-metalic nailed. Then metallic. Getting ahead a bit; to render SP maps in mental ray, you will need to output them as diffuse/specular maps, as intended for the specular workflow. That means that any diffuse values get transferred to the specular map for metals. So with this test I set diffuse to black, and set the otherwise white spec value to our nice rubber ball red. Then I amped up the IOR all the way to 20.

These are the christmas balls I got, left SP, right MR:
image 7

The metal turns out a bit darker in MR, but that is fine. Actually, it seems more accurate. Another difference actually is that blueish rim-light you see on top; that actually shouldn't be there. Not when working with a single fresnel pass anyway... Now I'm not sure if they should be there in the real world, but I like that bit of extra shine we get with the SP shader, so I thought I'd just reproduce it in MR.
Here is where those mila_materials work pretty nice; you can just add another glossy specular layer on the one that is handling your metal look. You'll get this:

image 8: setup for a metallic surface (The roughness on that extra layer should go down to 0.)

Step 3: texture testing!

So, time to start hooking up textures. It took some fiddeling and experimenting, but this is what I got initially:
image 9

Not bad. It seems that SP renders a lot crisper though (and I found the same between SP and Marmoset Toolbag). It helps to switch off filtering for the textures, which I did for all textures in the right image. MR doesn't need that filtering anyway, at least not for still renders. Also, MR is a lot more sensitive to rendering normal maps with edges that are baked a bit off, something that often happens with z-brush reprojections.

The results are not 100% identical, and I welcome any tips for a better approximation, but for now I'm pretty content. So, for those of you that are looking for the final setup:


This is the mila_material setup I use (with exception of the base layer; these layers are built top-down.. so the top layer is the first one I added):
image 10: basic setup
In the mila layers node/tab it looks like this:
image 11

Hooked up behind the scenes:
- Diffuse map to color in the Base layer
- Specular map to color in the 'reflect_dielectric' layer
- Normal map via a regular 2d bump node to the Bump slots for all layers (if you wonder why; mila_materials allow for nice effects like smooth coatings on a rough surface, by having a smooth normal map on the glossy reflect layer and a rough normal map in the diffuse underneath.)
- Roughness map* through a gamma correction node (value 2.2) to the roughness on all reflect layers.
- Metallic map* to the weight channels of 'reflect_metal' and 'reflect_metal_shine'(which is the channel for that extra bit of fresnel I mentioned earlier), and mapped through a reverse node to the weight of the 'reflect_dielectric' layer. Actually, I also ran this map through the gamma correct node. This map would mostly be black and white, but in transition area's it wouldn't be, and I just assumed this correction would also be required. Not sure if it is though, that requires a bit of testing.
- Opacity (not applied in the screenshots, but succesfully tested) via a reverse node to the weight channel of a new weighted layer set to "transparency", leaving its transparancy color to white.

*Note: You'll need to use their alpha-out channels. Don't forget to flag "Alpha Is Luminance" checkbox under the "file>color balance" tab for your textures.

image 12: basic graph

Some considerations; it would be possible to use just one layer for reflect_metal and reflect_dielectric, by mapping the Metallic map through a 'remap values' node for example, so that black reads as 1.4 and white as 20, and plug it in the Ior channel in the consolidated reflect layer. I for one prefer to work that way, because less layers is always better. But in this case not more manageable;
The problem is that you need to plug the specular map in the color for the layer that handles metal reflections. But for non-metals, SP outputs a very dark grey-ish specular value, while in MR want this value to be white be white.
... Or actually; a higher roughness value seems to lower the reflected value for nonmetals in SP compared to MR (see first image), so the relation is probably more complex. For accurate reproduction you might want to have the inverse of your (non-gamma-corrected) roughness map connected to your specular channel... probably run through a inverse gamma correction or something actually :D This would require further testing I suppose, but anyhow; it makes life easier to just have a separate layers for the metallic and nonmetallic reflections.

Another thing is that that gamma-correction applied to the roughness map is probably somehow manageable via color management. I didn't get proper results playing around with maya's color management though, and it seems that mental ray ignores any settings on the file node itself concerning the color profile. I just use a node for the correction


  1. Mind if I repost it on my blog for my own record?

  2. A general question for mila. I always get confused because all their layers name very similar and confusing. Anyways, when you add layers for this test. did you add it as a weighted layer or fresnel. And what are the differences. The attribute under the mila_layer node doesn't seem to have any differences at all tho.

    1. There is not really a difference, choosing either weighted or fresnel just turns the "use directional weight" checkbox off (weighted) or on (fresnel). When using fresnel, you use a combination of fresnel and a weight value to mix the layer over lower layers. With just weighted you use a straightforward blend.

    2. so just to be clear; the layer created is identical, with just that checkbox on or off. You can always change that in the 'mila layer' tab/node. The interface is a bit... oddly set up, because both the mila_material node/tab and the mila_layer node/tab list all layers, but they display different attributes (some the same, some not). The checkbox for using fresnel can only be found under mila_layer, but the fresnel value itself can be set under both.
      Weight can also be found on both tabs, but weight tint only under mila_layer. Then color can only be found under mila_material, but they have different effects. So all in all, not very straightforward ;)
      Other than the messy interface, the mila system is rather flexible though.
      I suggest just testing things in a minimal setup in a fashion to see what the different parameters do.

  3. About the gamma linear work flow Im very confuse in 2016. Maya 2016 has set linear render as default. But I m not sure what is their default image input as. And what SP spit out as. I was thinking SP would spits out sRGB maps thats more for game engines. So in maya either you preset all input as sRGB then mentalrey will degamma during render. From your case you are adding 2.2 to roughness map only. So did you preset the input as linear?

    1. Both roughness and metallic get that 2.2 gamma correction. About input, I left Maya at it's default settings. Changing things in the color management messed up all my other textures, and it seems that mental ray completely ignores what colorspace you specify on the texture file node.

      So if I'm not mistaken, maya provides all textures as sRGB to mental ray, and that 2.2 is to compensate for the translation to linear space that Mental Ray does, since the texture is already a linear space map.
      I believe you can use maya color management to have all textures with a certain name for example be passed to mental ray as linear, but I am yet to embrace that workflow :D
      So for now, I just use gamma correction.

  4. Hey Artificial,

    first thank you for this great Post. I helps me a lot.
    But i have a question. How is your setup for the map export in painter? I´m a little bit confused about that.

    1. I make a custom preset, and use the "create buttons to create the output map entries I need (so no specific preset used).

      For Diffuse, Specular and Normal I create "RGB", for metallic, opacity and roughness "Gray".

      On the RGB slot for Diffuse, Specular and Normal I drag the corrseponding maps from the "converted maps" column.
      For Roughness, Opacity and Metallic I use the corresponding greyscale maps from "input maps".

  5. Just wanted to say a huge thanks for the article as I'm new to Mila having used Mia presets pretty much exclusively. I wondered if you could spare any time helping create some arch viz presets with me as I feel this is something really lacking in maya... All the best

    1. Hey Yeo, great to hear this article has been of help! As for arch viz presets; I am quite swamped with work and social stuff, so I'm affraid I can't be of much help there..

  6. No worries, glad to hear work is keeping you busy! I was looking at the Marmoset PBR settings and trying to work out how to translate those to MILA, don't suppose you could offer a pointer or two?

    1. Alas; your guess would be as good as mine. The route I would take would be the same as described in the article; just some tests with different settings on a simple sphere, see how they match.

    2. Yeah I guess so, cheers anyway. If I can squeeze anything half decent out I'll share.

  7. Please, could you share a maya scene with a sample material?

  8. First thanks for the tutorial and the break down. I'm currently using your setup but in my render the material is looking flat and not like metal. I'm not sure hoe to fix it.

  9. Hi. I'm grateful for the info, however I use 3D Max and Lumion. Lumion allows only a diffuse/alpha and a normal map. So can I ask is it possible to see your template that you created in SP for the diffuse output please? As when I try to make the template it goes wrong (I'm new to materials as still learning them).

    Appreciate any support you can give.

  10. Hello, thank you very much for the guide. I got some problems, when I tried to connect the gamma correct node to either roughness or weight in the layer, it said it can't be connected. How did you connected those thing?

    1. Hey, sorry for the way late response, but have you tried connecting gammaCorrect1.outValueX to that roughness channel? Because I might have only connected a single channel there (not sure, and the pc I did this on is out of commission...)

  11. I'm trying to attach a gammaCorrect to the roughness attributes on the layers, but it won't let me. Tells me that gammaCorrect1.outValue' cannot be connected to 'reflect_dielectric.roughness'. This has become a barrier for me in trying to recreate your setup.

    Also I'm looking at your hypershade setup and your directions at the end of your tutorial and information contradicts one another. In your directions you say that you applied your spec map to your reflect_dielectric layer/node but looking at your chart you have the spec map plugged into your reflect_metal, any input on that?

    Thanks again, looking forward to finishing this experiment!

    1. Hey, sorry for the way late response, but have you tried connecting gammaCorrect1.outValueX to that roughness channel? Because I might have only connected a single channel there (not sure, and the pc I did this on is out of commission...)