Lets talk Physically Based Shading for Vray & Corona. I wrote this short guide as I found lots of information online about how to author textures for 3D Shaders, and there’s different methods (which kind of defies standards but anywho lets cut to the chase).
Lets start with my desired outcome - I want to create textures that will work in Vray and also Corona (easily pressing the convert to corona button or visa versa). In this case we will use the Physically Based (Specular/Glossiness) workflow (Metallic isn’t supported in Corona as of yet so this makes the choice easy as well as some other things we will discuss below). I also want to have a simple material setup, without the need for multi layered/blend materials.
Lets do this with something that seems reasonably simple: A Metal Copper Sphere (Conductor) with some light glossiness and some chunks removed to reveal the surface below (A basic rust Dialectic). Normally rust would be on top but I have carved it into the surface for an experiment on masks and fresnel, more explained later.
Substance Designer Preview
I wont go into the details of how the Shader was made in Substance Designer as it was just a quick few generated maps - the import part is how we export them and bring them into 3dsmax. So lets move on.
Start a New Substance Graph Template
We will go with an empty template for now, as we will create our own outputs.
Setup your 3D Viewport Display
Now lets setup the material we will see in the 3D view, create a Base Material Node and change the Instance Parameters from Metal - Roughness to Specular - Glossiness. This will be the node we output our texture maps from to use in 3dsmax.
Lets expose the parameters on the left you will need (as shown above) in the User-Defined Maps section within the Base Material (you may use Height and Ambient occlusion but in this instance we wont need it). Right click and drag the Base Material into your 3D Viewport and you will see your material, it should be black at this stage. Now go ahead and plug in your maps to these inputs (without inputs these will default to black and you will get Shader issues - this is not an introduction to Substance Designer so I recommend you follow some basic tutorials at this point if you are unsure, this is just workflow based so you can output your textures correctly). This is a good one based on Specular/Glossiness.
However if you want just a shiny metal ball to begin with I have provided quick setup below to get you going. Its just a flat normal node, a white greyscale node for the glossiness and a white color node for the specular. If you are used to this workflow in 3dsmax you will know that the diffuse should be black and specular should be white to show 100% reflection as the image below.
Basic Substance Designer Setup
Once you have your maps setup and ready to go lets output this. Right click on your Base Material, Create, Output Nodes. Make sure you press No for hidden connections. I have deleted the last 2 nodes Ambient Occlusion and Height as I don’t need these. Lets see how the material output looks for my current setup with our Copper/Rusted sphere.
A quick note, I have changed the output of the Specular to the word Reflection (as this is more usual for me). You are probably wondering what is the additional Reflection Mask at the bottom? Well this will be more apparent once we are in 3dsmax, so hang tight - but just so you know its a black and white version of the reflection before it was colored. Ok so go ahead and output these using the little wrench icon at the top.
Lets open 3dsmax and load up Corona to start with. If you are unfamiliar with PBR shading for Corona please watch this video as it quickly explains how to make shaders for conductors and dialectics and will make the next part of this much easier to understand.
Lets start with our basic input of texture maps and see the result. Only Diffuse & Reflection will have the Input Gamma as Automatic and the rest of your maps will require you to Override the Input to 1.0 as shown below. Ensure you set the Fresnel IOR to 999 (disabled) as our base is metal.
Corona Specular - Glossiness Render
Now you are probably wondering where is our Reflection Mask we output from Substance Designer? We now implement that to add the fresnel effect as below (notice grazing angle has more reflection).
Corona Specular - Glossiness Render + Complex Fresnel
Now because we have disabled the fresnel we are controlling it through the reflection map. We have a Mix Map and we can use our Reflection Mask to define the dialectic and conductor. For the conductor I am using a ComplexFresnel from Siger Shaders with the Copper Preset set to gamma 2.2. For the dialectic I am simply using the Reflection Map (You can do further adjustments to the intensity of this to match the desired IOR levels to match the exact dialectic value but I am happy with it for this example). If you wanted to share this file with someone else they will need the Siger plugin or you could just copy the curve profile and use that instead of the Complex Fresnel.
Corona Render with Complex Fresnel
Vray Render with Complex Fresnel
As you can see it easily converts over and looks very much the same. There’s some slight differences due to vrays GGX model and the differences between lighting in corona/vray (but not much).
I wanted to also discover a little more about how Substance Designer handles it different outputs, specifically:
Base Material: PBR Workflow Metal - Roughness
For this experiment we will stay in Vray.
This method takes an existing Metal - Rougness workflow and outputs maps to use in Specular - Glossiness workflow and gives you an 1/IOR Map to use in the Fresnel Map. You will notice the reflection map looks different as now we are controlling the fresnel by mapping the IOR to 0-1 range (Vray does the inverse conversion for you, more explained below for those who want to know the math).
Vray Render using 1/IOR Map
Base Material: PBR Workflow Metal - Roughness
In this case we use the Metal - Roughness workflow which Vray can handle and is a similar approach to how real time engines use the maps (with some slight differences). We end up with less maps (and less control over the fresnel) but is a more simplistic approach (and saves texture memory by using some greyscale maps instead of rgb). Just be aware the glossiness maps are basically inverted to become roughness maps, we also need to change Vrays BRDF to Use roughness. We also don’t need a reflection map and set it to pure white (1.0) as the Metallic Map handles this for us.
Vray Metallic Render
A couple of things I found interesting. Left (Metallic/Roughness Converter) the fresnel need additional work, also there seems to be an issue with the normals on the lower half of the sphere (could be my fault with the conversion). Center (Spec/Gloss) is basically the closest to the original Substance Designer I setup). The right (Metal - Rougness) has a higher overall reflection (and Vlado himself said that this is a more accurate representation) but I’m losing some colour in the rusted areas (this can be remedied using a Vray Blend Material to separate the conductors/dialectics but I wanted a built in texture approach - but useful to know).
You could also just use the Substance to 3dsmax plugin to save yourself doing the gamma work on import, just be aware that anyone you share your files with needs to have the Substance Files and plugin for it to work correctly too. I myself have had some issues with the plugin as it doesn’t auto wire them correctly for this setup, but I will continue to experiment with it.
Fresnel & 1/IOR Map
For Substance Painter you dont have control over the fresnel - all dialectics are basically set to 1.5 and the metals have fresnel disabled. In Substance Designer you have the ability to control the 1/IOR output range. The basic idea is that most dialectics have a Reflectance Value of 0.04 to 0.08 and 0.001 for metallics.
example from above:
As an example if you had a fresnel value of 1.52
To get the RGB value you would do 1 / 1.52 = 0.658 (rounded up)
You can then plug this color/value into the fresnel slot and Vray/Corona will do the conversion for you back to 1.52.
1/0.0001 = 10000.0 fresnel value
(same as turning fresnel off in Vray or setting Corona fresnel to 999). If you want 4 decimal places you can enable this in your Customize, Preferences to get the 0.0001 for Color Correction node or just round up to 0.001 - I’m not so concerned as I will just use the bitmap to map the values instead as shown at the bottom below in the IOR bitmap (which is closer to 0.001 anyway).
In 3dsmax bitmap parameters if you view image and right click in the preview window you can see this reflected in the IOR texture itself.
1/0.6666 = 1.5 fresnel value
1/0.0009 = 1111.0 fresnel value (or disabled)
You can find these values on the refractive index website. It may seem a little overwhelming at first if you are not used to it however this should simplify the process for you.
Lets use Plastic as an example:
This would be the IOR value you would place into the fresnel usually to get the correct looking falloff on your reflection. If you scroll down the page you can also find the f0 (reflectance value at 0 degrees).
Following the formula above:
1/((2.0/(sqrt(0.037619)+1.0))-1.0) = 1.4813 fresnel value
1 / 1.4813 = 0.675 RGB Value
If you use python you can use this little script I made which will give you conversions for both the RGB Value & Fresnel by inputting the Reflectance Value. Copy the below text and place into a .py file and run as needed, remember to change the REFLECTANCE variable to your requirements.
# Start of script.
James Vella 2019
This python script maps the Reflectance value to a 1/IOR.
Go to https://refractiveindex.info and find the Reflectance (at 1.052 µm) value
replace REFLECTANCE variable with this number.
PMMA - Poly(methyl methacrylate)
Reflectance (at 1.052 µm): R = 0.037619
from math import sqrt
REFLECTANCE = 0.037619 # Replace this with the Reflectance (at 1.052 µm)
RGB = ((2.0/(sqrt(REFLECTANCE)+1.0))-1.0) # Formula for converting Reflectance to 1/IOR.
IOR = 1/RGB # Calculate IOR value back to Fresnel value.
RGB3D = RGB*100 # Usable Color Value for Fresnel Color Swatch in 3D.
print("The RGB Value Color Swatch value is: ", round(RGB3D, 1))
print("The rounded IOR value is: ", round(IOR, 3))
print("The exact IOR value is: ", IOR)
# End of script.
This will print:
The RGB Value Color Swatch value is: 67.5
The rounded IOR value is: 1.481
The exact IOR value is: 1.4812546810841039