Physical material to Simplygon material
The Physical Material is the new standard material in Max 2021 and later, and although we have a basic implementation for mapping most properties there might be a need for customizing material channels. This section goes through how to map Physical material properties to Simplygon and back through scripting and shading networks. It is recommended to read Shading network concepts and Simplygon Shading Network functions before proceeding.
Scripting
To translate a Physical material to a Simplygon material you would most likely want to extract certain properties from your material. To map a specific material property to Simplygon we need to identify the name of the Physical Material we want to override, as well as the material properties we are interested in, here's a list of "Physical Material" properties that we've gathered so far:
Type | UI name | Material section | Property name | Texture slot | (Default) Simplygon channel | Mapping through name | Note |
---|---|---|---|---|---|---|---|
int | Material Mode | Presets | material_mode | Not required (changes the view mode of the material) | |||
float | Base Weight | Base Color | base_weight | base_weight | ColorNode | ||
Point4* | Base Color | Base Color | base_color | base_color | ColorNode | ||
float | Reflectivity | Reflections | reflectivity | reflectivity | ColorNode | ||
float | Roughness | Reflections | roughness | roughness | ColorNode | ||
bool | Roughness, Glossiness | Reflections | roughness_inv | roughness | Used internally when no override Inverts roughness input | ||
float | Metalness | Reflections | metalness | metalness | ColorNode | ||
Point4* | Reflection Color | Reflections | refl_color | refl_color | ColorNode | ||
float | Diffuse Roughness | Reflections | diff_roughness | diff_roughness | ColorNode | ||
bool | By IOR, Custom Curve | Advanced reflection Parameters | brdf_mode | No appropriate mapping | |||
float | Facing | Advanced reflection Parameters | brdf_low | ColorNode | Only through color node | ||
float | Edge | Advanced reflection Parameters | brdf_high | ColorNode | Only through color node | ||
float | Slope | Advanced reflection Parameters | brdf_curve | ColorNode | Only through color node | ||
float | Anisotropy | Anisotropy | anisotropy | ColorNode | Only through color node | ||
float | Anisotropy Rotation | Anisotropy | anisoangle | ColorNode | Only through color node | ||
int | Auto, Map Channel | Anisotropy | aniso_mode | No appropriate mapping | |||
int | Map Channel | Anisotropy | aniso_channel | No appropriate mapping | |||
float | Transparency Weight | Transparency | transparency | transparency | ColorNode | ||
Point4* | Transparency Color | Transparency | trans_color | trans_color | ColorNode | ||
float | Transparency Depth | Transparency | trans_depth | trans_depth | ColorNode | ||
float | Transparency Roughness | Transparency | trans_roughness | trans_roughness | ColorNode | ||
bool | Transparency Roughness, Transparency Glossiness | Transparency | trans_roughness_inv | trans_roughness | Used internally when no override Inverts roughness input | ||
bool | Transparency Roughness Lock | Transparency | trans_roughness_lock | trans_roughness | Used internally when no override true -> use roughness map false -> use trans_roughness | ||
float | IOR | Transparency | trans_ior | trans_ior | stored as value / 50.f (0.0f - 1.0f) | ||
bool | Thin-walled | Transparency | thin_walled | No appropriate mapping | |||
float | Scattering Weight | Sub-Surface Scattering | scattering | scattering | ColorNode | ||
Point4* | Scattering Color | Sub-Surface Scattering | sss_color | sss_color | ColorNode | ||
float | Scattering Depth | Sub-Surface Scattering | sss_depth | sss_scale | ColorNode | Stored in sss_scale | |
float | Scattering Scale | Sub-Surface Scattering | sss_scale | sss_scale | ColorNode | (sss_depth / 1000.f) * sss_scale | |
Point4* | Scatter Color | Sub-Surface Scattering | sss_scatter_color | sss_scatter_color | ColorNode | No automatic back mapping as there is no texture slot in Physical Material | |
float | Emission Weight | Emission | emission | emission | ColorNode | ||
Point4* | Emission Color | Emission | emit_color | emit_color | ColorNode | ||
float | Emission Luminance | Emission | emit_luminance | emit_luminance | ColorNode | Stored as emit_luminance / 1000.f (0.0f - 1.0f) | |
float | Emission Kelvin | Emission | emit_kelvin | emit_kelvin | ColorNode | Stored as Color::FromKelvinTemperature(fKelvin) / 1.78516805f (0.0f - 1.0f) | |
float | Sheen Weight | Sheen | sheen | sheen | ColorNode | ||
float | Sheen Roughness | Sheen | sheen_roughness | sheen_roughness | ColorNode | ||
float | Thin Film Weight | Thin Film | thin_film | thin_film | ColorNode | ||
float | Thin Film Thickness | Thin Film | thin_film_thickness | No appropriate mapping | |||
float | Thin Film IOR | Thin Film | thin_film_ior | thin_film_ior | ColorNode | ||
float | Coating Weight | Clearcoat | coating | coating | ColorNode | ||
Point4* | Coating Color | Clearcoat | coat_color | coat_color | ColorNode | ||
float | Coating Roughness | Clearcoat | coat_roughness | coat_roughness | ColorNode | ||
bool | Coating Roughness, Coating Glossiness | Clearcoat | coat_roughness_inv | coat_roughness_inv | |||
float | Coat Affect Color | Clearcoat | coat_affect_color | coat_affect_color | ColorNode | ||
float | Coat Affect Roughness | Clearcoat | coat_affect_roughness | coat_affect_roughness | ColorNode | ||
float | Coating IOR | Clearcoat | coat_ior | coat_ior | Stored as coat_ior / 5.f (0.0f - 1.0f) | ||
Texmap* | Base Weight | Base Color, Generic Maps | base_weight_map | 0 | base_weight | TextureNode | |
Texmap* | Base Color | Base Color, Generic Maps | base_color_map | 1 | base_color | TextureNode | |
Texmap* | Reflection Weight | Reflections, Generic Maps | reflectivity_map | 2 | reflectivity | TextureNode | |
Texmap* | Reflection Color | Reflections, Generic Maps | refl_color_map | 3 | refl_color | TextureNode | |
Texmap* | Roughness | Reflections, Generic Maps | roughness_map | 4 | roughness | TextureNode | |
Texmap* | Metalness | Reflections, Generic Maps | metalness_map | 5 | metalness | TextureNode | |
Texmap* | Diffuse Roughness | Base Color, Generic Maps | diff_rough_map | 6 | diff_rough | TextureNode | |
Texmap* | Anisotropy | Anisotropy, Generic Maps | anisotropy_map | 7 | TextureNode | ||
Texmap* | Anisotropy Angle | Anisotropy, Generic Maps | aniso_angle_map | 8 | TextureNode | ||
Texmap* | Transparency Weight | Transparency, Generic Maps | transparency_map | 9 | transparency | TextureNode | |
Texmap* | Transparency Color | Transparency, Generic Maps | trans_color_map | 10 | trans_color | TextureNode | |
Texmap* | Transparency Roughness | Transparency, Generic Maps | trans_rough_map | 11 | trans_rough | TextureNode | |
Texmap* | IOR | Transparency, Generic Maps | trans_ior_map | 12 | trans_ior | TextureNode | |
Texmap* | Scattering Weight | Sub-Surface Scattering, Generic Maps | scattering_map | 13 | scattering | TextureNode | |
Texmap* | Scattering Color | Sub-Surface Scattering, Generic Maps | sss_color_map | 14 | sss_color | TextureNode | |
Texmap* | Scattering Scale | Sub-Surface Scattering, Generic Maps | sss_scale_map | 15 | sss_scale | TextureNode | |
Texmap* | Emission Weight | Emission, Generic Maps | emission_map | 16 | emission | TextureNode | |
Texmap* | Emission Color | Emission, Generic Maps | emit_color_map | 17 | emit_color | TextureNode | |
Texmap* | Coating Weight | Clearcoat, Generic Maps | coat_map | 18 | coat | TextureNode | |
Texmap* | Coating Color | Clearcoat, Generic Maps | coat_color_map | 19 | coat_color | TextureNode | |
Texmap* | Coating Roughness | Clearcoat, Generic Maps | coat_rough_map | 20 | coat_rough | TextureNode | |
Texmap* | Coating Anisotropy | Clearcoat, Generic Maps | coat_anistropy_map | 21 | coat_anistropy | No appropriate mapping | |
Texmap* | Coating Aniso. Angle | Clearcoat, Generic Maps | coat_anisoangle_map | 22 | coat_anisoangle | No appropriate mapping | |
Texmap* | Sheen Weight | Sheen, Generic Maps | sheen_map | 23 | sheen | TextureNode | |
Texmap* | Sheen Color | Sheen, Generic Maps | sheen_color_map | 24 | sheen_color | TextureNode | |
Texmap* | Sheen Roughness | Sheen, Generic Maps | sheen_roughness_map | 25 | sheen_roughness | TextureNode | |
Texmap* | Thin Film Weight | Thin Film, Generic Maps | thin_film_map | 26 | thin_film | TextureNode | |
Texmap* | Thin Film IOR | Thin Film, Generic Maps | thin_film_ior_map | 27 | thin_film_ior | No appropriate mapping | |
Texmap* | Bump Map | Special Maps | bump_map | 30 | bump | TextureNode | |
Texmap* | Coating Bump Map | Special Maps | coat_bump_map | 31 | coat_bump | TextureNode | |
Texmap* | Displacement | Special Maps | displacement_map | 32 | displacement | TextureNode | |
Texmap* | Cutout (opacity) | Special Maps | cutout_map | 33 | cutout | TextureNode | |
bool | Base Weight | Base Color, Generic Maps | base_weight_map_on | Used internally when no override | |||
bool | Base Color | Base Color, Generic Maps | base_color_map_on | Used internally when no override | |||
bool | Reflection Weight | Reflections, Generic Maps | reflectivity_map_on | Used internally when no override | |||
bool | Reflection Color | Reflections, Generic Maps | refl_color_map_on | Used internally when no override | |||
bool | Roughness | Reflections, Generic Maps | roughness_map_on | Used internally when no override | |||
bool | Metalness | Reflections, Generic Maps | metalness_map_on | Used internally when no override | |||
bool | Diffuse Roughness | Base Color, Generic Maps | diff_rough_map_on | Used internally when no override | |||
bool | Anisotropy | Anisotropy, Generic Maps | anisotropy_map_on | ||||
bool | Anisotropy Angle | Anisotropy, Generic Maps | aniso_angle_map_on | ||||
bool | Transparency Weight | Transparency, Generic Maps | transparency_map_on | Used internally when no override | |||
bool | Transparency Color | Transparency, Generic Maps | trans_color_map_on | Used internally when no override | |||
bool | Transparency Roughness | Transparency, Generic Maps | trans_rough_map_on | Used internally when no override | |||
bool | IOR | Transparency, Generic Maps | trans_ior_map_on | Used internally when no override | |||
bool | Scattering Weight | Sub-Surface Scattering, Generic Maps | scattering_map_on | Used internally when no override | |||
bool | Scattering Color | Sub-Surface Scattering, Generic Maps | sss_color_map_on | Used internally when no override | |||
bool | Scattering Scale | Sub-Surface Scattering, Generic Maps | sss_scale_map_on | Used internally when no override | |||
bool | Emission Weight | Emission, Generic Maps | emission_map_on | Used internally when no override | |||
bool | Emission Color | Emission, Generic Maps | emit_color_map_on | Used internally when no override | |||
bool | Sheen Weight | Sheen, Generic Maps | sheen_map_on | Used internally when no override | |||
bool | Sheen Color | Sheen, Generic Maps | sheen_color_map_on | Used internally when no override | |||
bool | Sheen Roughness | Sheen, Generic Maps | sheen_rough_map_on | Used internally when no override | |||
bool | Thin Film Weight | Thin Film, Generic Maps | thin_film_map_on | Used internally when no override | |||
bool | Thin Film IOR | Thin Film, Generic Maps | thin_film_ior_map_on | Used internally when no override | |||
bool | Coating Weight | Clearcoat, Generic Maps | coat_map_on | Used internally when no override | |||
bool | Coating Color | Clearcoat, Generic Maps | coat_color_map_on | Used internally when no override | |||
bool | Coating Roughness | Clearcoat, Generic Maps | coat_rough_map_on | Used internally when no override | |||
bool | Bump Map | Special Maps | bump_map_on | Used internally when no override | |||
bool | Coating Bump Map | Special Maps | coat_bump_map_on | Used internally when no override | |||
bool | Displacement | Special Maps | displacement_map_on | Used internally when no override | |||
bool | Cutout (opacity) | Special Maps | cutout_map_on | Used internally when no override | |||
float | Bump Map Amount | Special Maps | bump_map_amt | ColorNode | |||
float | Clearcoat Bump Map Amount | Special Maps | clearcoat_bump_map_amt | ColorNode | |||
float | Displacement Map Amount | Special Maps | displacement_map_amt | ColorNode |
Now that we have all available material properties, let's head over to the export section and do some prototyping!
Export
The first thing we need to do to create a shading network is to specify the material name we want to override. The line below tells the Simplygon plug-in that there's a shading network available for the specific material.MaterialName in this case is the name of the Physical Material in the 3ds Max material browser/editor, usually something like '01 - default' for new materials.
MyPhysicalMaterial = sgsdk_CreateMaterialMetadata MaterialName
Simplygon's texture nodes maps directly to the Physical material's texture property via name, let's use base_color_map
(Texmap*) from the table above for this tutorial.
MyBaseColorTexture = sgsdk_CreateShadingTextureNode "base_color_map"
Color nodes work pretty much in the same way, let's use base_color
(Point4*). This line is just an illustration, we'll not use it in our shading network.
MyBaseColor = sgsdk_CreateShadingColorNode "base_color"
To connect the shading network to a material channel we will add another line to our script. A material channel can be named anything, but keep in mind that it directly maps to the channel name of the material caster in the settings, if you intend to cast the material channel to a texture that is.
sgsdk_ConnectNodeToChannel MyBaseColorTexture MyPhysicalMaterial "base_color"
Let's add the bump_map
texture to the bump material channel, this should be fairly easy from what we have learned.
MyBumpTexture = sgsdk_CreateShadingTextureNode "bump_map"
sgsdk_ConnectNodeToChannel MyBumpTexture MyPhysicalMaterial "bump"
Before calling the Simplygon function there are some optional settings that can be set, for example texture output directory which can make life easier when importing / handling textures. Remember to select the asset before running the Simplygon command, otherwise the command will be ignored.
sgsdk_SetTextureOutputDirectory "D:\\CubeExample\\OutputTextures\\"
sgsdk_RunPipelineOnSelection reductionPipelineWithMaterialBaking
The final export script:
MyPhysicalMaterial = sgsdk_CreateMaterialMetadata "MyPhysicalMaterial"
MyBaseColorTexture = sgsdk_CreateShadingTextureNode "base_color_map"
MyBumpTexture = sgsdk_CreateShadingTextureNode "bump_map"
sgsdk_ConnectNodeToChannel MyBaseColorTexture MyPhysicalMaterial "base_color"
sgsdk_ConnectNodeToChannel MyBumpTexture MyPhysicalMaterial "bump"
sgsdk_SetTextureOutputDirectory "D:\\CubeExample\\OutputTextures\\"
sgsdk_RunPipelineOnSelection reductionPipelineWithMaterialBaking
For properties that are not automatically mapped, such as int, bool and float properties, these are accessible through the Physical Material via MaxScript / Python. We recommend setting up a material loop where the Physical Material type is identified and then translated using Simplygon Shading Nodes. Keep in mind that "empty" texture nodes are not allowed, make sure that a valid texture is and that the checkbox is enabled, otherwise it is recommended to ignore creating the node or replace it with a color node.
Here's a snippet that will loop through available scene materials and list all material properties.
-- loop all scene materials
for mat in scenematerials do
(
print ("Material name: " + mat.name)
-- get all material properties
props = getPropNames mat
for i = 1 to props.count do
(
prop = getProperty mat props[i]
print ("\t\t\t." + props[i] + ": " + prop as string + "")
)
print ("\n")
-- loop through all sub-materials
subMatCount = getNumSubMtls mat
print ("\tNum sub-materials: " + subMatCount as string)
for i = 1 to subMatCount do
(
subMat = getSubMtl mat i
print ("\t\tSub-material name: " + subMat.name)
-- get all sub-material properties
props = getPropNames subMat
for i = 1 to props.count do
(
prop = getProperty subMat props[i]
print ("\t\t\t." + props[i] + ": " + prop as string + "")
)
print ("\n")
)
)
Which should give the following output:
This is a short tutorial on how to use shading networks to translate a Physical Material to Simplygon material.
Import
The Simplygon Max plug-in stores some material information from the last run which can be accessed via script. We will start by asking the plug-in for the material name of a mesh, material channels followed by textures.
...
sgsdk_RunPipelineOnSelection reductionPipelineWithMaterialBaking
processedMeshes = sgsdk_GetProcessedMeshes()
for mesh in processedMeshes do
(
print ("\tMesh: " + mesh)
materials = sgsdk_GetMaterialsForMesh mesh
for material in materials do
(
print ("\n\t\tMaterial: " + material)
reusingMaterials = sgsdk_GetMeshReusesMaterials mesh
for reuseMaterial in reusingMaterials do
(
print ("\t\tReusing: " + reuseMaterial)
)
channels = sgsdk_GetChannelsForMaterial material
for channel in channels do
(
print ("\t\t\tChannel: " + channel)
texture = sgsdk_GetTexturePathForChannel material channel
print ("\t\t\t\tTexture: " + texture)
mappingChannel = sgsdk_GetMappingChannelForChannel material channel
print ("\t\t\t\tMappingChannel: " + mappingChannel as string)
)
-- sub-materials
materials = sgsdk_GetSubMaterials material
for submaterial in materials do
(
print ("\n\t\t\tSubMaterial: " + submaterial)
reusingMaterial = sgsdk_GetMaterialReusesSubMaterial material submaterial
print ("\t\t\tReusing: " + reusingMaterial)
channels = sgsdk_GetChannelsForMaterial submaterial
for channel in channels do
(
print ("\t\t\tChannel: " + channel)
texture = sgsdk_GetTexturePathForChannel submaterial channel
print ("\t\t\t\tTexture: " + texture)
mappingChannel = sgsdk_GetMappingChannelForChannel submaterial channel
print ("\t\t\t\tMappingChannel: " + mappingChannel as string)
)
materialIndex = sgsdk_GetSubMaterialIndex material submaterial
print ("\t\t\tIndex: " + materialIndex as string)
)
)
)
Simplygon's "Physical Material" implementation is based on a collection of material channels, if these material channels are identified at import then Simplygon will hook in the result automatically. If custom channels are used, then they have to be handled manually by querying the plug-in and create the target material(s) manually and map back the information that was fetched from sgsdk_GetMaterialsForMesh
, sgsdk_GetChannelsForMaterial
, sgsdk_GetTexturePathForChannel
and sgsdk_GetMappingChannelForChannel
. We've excluded the material creation part from this tutorial as there usually are many lines of code and special conditions that does not really contribute that much. See the Physical Material example for a more detailed example.
References
Get to know how to work with Shading Networks: