Skip to content
On this page

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:

TypeUI nameMaterial sectionProperty nameTexture slot(Default) Simplygon channelMapping through nameNote
intMaterial ModePresetsmaterial_modeNot required (changes the view mode of the material)
floatBase WeightBase Colorbase_weightbase_weightColorNode
Point4*Base ColorBase Colorbase_colorbase_colorColorNode
floatReflectivityReflectionsreflectivityreflectivityColorNode
floatRoughnessReflectionsroughnessroughnessColorNode
boolRoughness, GlossinessReflectionsroughness_invroughnessUsed internally when no override
Inverts roughness input
floatMetalnessReflectionsmetalnessmetalnessColorNode
Point4*Reflection ColorReflectionsrefl_colorrefl_colorColorNode
floatDiffuse RoughnessReflectionsdiff_roughnessdiff_roughnessColorNode
boolBy IOR, Custom CurveAdvanced reflection Parametersbrdf_modeNo appropriate mapping
floatFacingAdvanced reflection Parametersbrdf_lowColorNodeOnly through color node
floatEdgeAdvanced reflection Parametersbrdf_highColorNodeOnly through color node
floatSlopeAdvanced reflection Parametersbrdf_curveColorNodeOnly through color node
floatAnisotropyAnisotropyanisotropyColorNodeOnly through color node
floatAnisotropy RotationAnisotropyanisoangleColorNodeOnly through color node
intAuto, Map ChannelAnisotropyaniso_modeNo appropriate mapping
intMap ChannelAnisotropyaniso_channelNo appropriate mapping
floatTransparency WeightTransparencytransparencytransparencyColorNode
Point4*Transparency ColorTransparencytrans_colortrans_colorColorNode
floatTransparency DepthTransparencytrans_depthtrans_depthColorNode
floatTransparency RoughnessTransparencytrans_roughnesstrans_roughnessColorNode
boolTransparency Roughness, Transparency GlossinessTransparencytrans_roughness_invtrans_roughnessUsed internally when no override
Inverts roughness input
boolTransparency Roughness LockTransparencytrans_roughness_locktrans_roughnessUsed internally when no override
true -> use roughness map
false -> use trans_roughness
floatIORTransparencytrans_iortrans_iorstored as value / 50.f (0.0f - 1.0f)
boolThin-walledTransparencythin_walledNo appropriate mapping
floatScattering WeightSub-Surface ScatteringscatteringscatteringColorNode
Point4*Scattering ColorSub-Surface Scatteringsss_colorsss_colorColorNode
floatScattering DepthSub-Surface Scatteringsss_depthsss_scaleColorNodeStored in sss_scale
floatScattering ScaleSub-Surface Scatteringsss_scalesss_scaleColorNode(sss_depth / 1000.f) * sss_scale
Point4*Scatter ColorSub-Surface Scatteringsss_scatter_colorsss_scatter_colorColorNodeNo automatic back mapping as there is no texture slot in Physical Material
floatEmission WeightEmissionemissionemissionColorNode
Point4*Emission ColorEmissionemit_coloremit_colorColorNode
floatEmission LuminanceEmissionemit_luminanceemit_luminanceColorNodeStored as emit_luminance / 1000.f (0.0f - 1.0f)
floatEmission KelvinEmissionemit_kelvinemit_kelvinColorNodeStored as Color::FromKelvinTemperature(fKelvin) / 1.78516805f (0.0f - 1.0f)
floatSheen WeightSheensheensheenColorNode
floatSheen RoughnessSheensheen_roughnesssheen_roughnessColorNode
floatThin Film WeightThin Filmthin_filmthin_filmColorNode
floatThin Film ThicknessThin Filmthin_film_thicknessNo appropriate mapping
floatThin Film IORThin Filmthin_film_iorthin_film_iorColorNode
floatCoating WeightClearcoatcoatingcoatingColorNode
Point4*Coating ColorClearcoatcoat_colorcoat_colorColorNode
floatCoating RoughnessClearcoatcoat_roughnesscoat_roughnessColorNode
boolCoating Roughness, Coating GlossinessClearcoatcoat_roughness_invcoat_roughness_inv
floatCoat Affect ColorClearcoatcoat_affect_colorcoat_affect_colorColorNode
floatCoat Affect RoughnessClearcoatcoat_affect_roughnesscoat_affect_roughnessColorNode
floatCoating IORClearcoatcoat_iorcoat_iorStored as coat_ior / 5.f (0.0f - 1.0f)
Texmap*Base WeightBase Color, Generic Mapsbase_weight_map0base_weightTextureNode
Texmap*Base ColorBase Color, Generic Mapsbase_color_map1base_colorTextureNode
Texmap*Reflection WeightReflections, Generic Mapsreflectivity_map2reflectivityTextureNode
Texmap*Reflection ColorReflections, Generic Mapsrefl_color_map3refl_colorTextureNode
Texmap*RoughnessReflections, Generic Mapsroughness_map4roughnessTextureNode
Texmap*MetalnessReflections, Generic Mapsmetalness_map5metalnessTextureNode
Texmap*Diffuse RoughnessBase Color, Generic Mapsdiff_rough_map6diff_roughTextureNode
Texmap*AnisotropyAnisotropy, Generic Mapsanisotropy_map7TextureNode
Texmap*Anisotropy AngleAnisotropy, Generic Mapsaniso_angle_map8TextureNode
Texmap*Transparency WeightTransparency, Generic Mapstransparency_map9transparencyTextureNode
Texmap*Transparency ColorTransparency, Generic Mapstrans_color_map10trans_colorTextureNode
Texmap*Transparency RoughnessTransparency, Generic Mapstrans_rough_map11trans_roughTextureNode
Texmap*IORTransparency, Generic Mapstrans_ior_map12trans_iorTextureNode
Texmap*Scattering WeightSub-Surface Scattering, Generic Mapsscattering_map13scatteringTextureNode
Texmap*Scattering ColorSub-Surface Scattering, Generic Mapssss_color_map14sss_colorTextureNode
Texmap*Scattering ScaleSub-Surface Scattering, Generic Mapssss_scale_map15sss_scaleTextureNode
Texmap*Emission WeightEmission, Generic Mapsemission_map16emissionTextureNode
Texmap*Emission ColorEmission, Generic Mapsemit_color_map17emit_colorTextureNode
Texmap*Coating WeightClearcoat, Generic Mapscoat_map18coatTextureNode
Texmap*Coating ColorClearcoat, Generic Mapscoat_color_map19coat_colorTextureNode
Texmap*Coating RoughnessClearcoat, Generic Mapscoat_rough_map20coat_roughTextureNode
Texmap*Coating AnisotropyClearcoat, Generic Mapscoat_anistropy_map21coat_anistropyNo appropriate mapping
Texmap*Coating Aniso. AngleClearcoat, Generic Mapscoat_anisoangle_map22coat_anisoangleNo appropriate mapping
Texmap*Sheen WeightSheen, Generic Mapssheen_map23sheenTextureNode
Texmap*Sheen ColorSheen, Generic Mapssheen_color_map24sheen_colorTextureNode
Texmap*Sheen RoughnessSheen, Generic Mapssheen_roughness_map25sheen_roughnessTextureNode
Texmap*Thin Film WeightThin Film, Generic Mapsthin_film_map26thin_filmTextureNode
Texmap*Thin Film IORThin Film, Generic Mapsthin_film_ior_map27thin_film_iorNo appropriate mapping
Texmap*Bump MapSpecial Mapsbump_map30bumpTextureNode
Texmap*Coating Bump MapSpecial Mapscoat_bump_map31coat_bumpTextureNode
Texmap*DisplacementSpecial Mapsdisplacement_map32displacementTextureNode
Texmap*Cutout (opacity)Special Mapscutout_map33cutoutTextureNode
boolBase WeightBase Color, Generic Mapsbase_weight_map_onUsed internally when no override
boolBase ColorBase Color, Generic Mapsbase_color_map_onUsed internally when no override
boolReflection WeightReflections, Generic Mapsreflectivity_map_onUsed internally when no override
boolReflection ColorReflections, Generic Mapsrefl_color_map_onUsed internally when no override
boolRoughnessReflections, Generic Mapsroughness_map_onUsed internally when no override
boolMetalnessReflections, Generic Mapsmetalness_map_onUsed internally when no override
boolDiffuse RoughnessBase Color, Generic Mapsdiff_rough_map_onUsed internally when no override
boolAnisotropyAnisotropy, Generic Mapsanisotropy_map_on
boolAnisotropy AngleAnisotropy, Generic Mapsaniso_angle_map_on
boolTransparency WeightTransparency, Generic Mapstransparency_map_onUsed internally when no override
boolTransparency ColorTransparency, Generic Mapstrans_color_map_onUsed internally when no override
boolTransparency RoughnessTransparency, Generic Mapstrans_rough_map_onUsed internally when no override
boolIORTransparency, Generic Mapstrans_ior_map_onUsed internally when no override
boolScattering WeightSub-Surface Scattering, Generic Mapsscattering_map_onUsed internally when no override
boolScattering ColorSub-Surface Scattering, Generic Mapssss_color_map_onUsed internally when no override
boolScattering ScaleSub-Surface Scattering, Generic Mapssss_scale_map_onUsed internally when no override
boolEmission WeightEmission, Generic Mapsemission_map_onUsed internally when no override
boolEmission ColorEmission, Generic Mapsemit_color_map_onUsed internally when no override
boolSheen WeightSheen, Generic Mapssheen_map_onUsed internally when no override
boolSheen ColorSheen, Generic Mapssheen_color_map_onUsed internally when no override
boolSheen RoughnessSheen, Generic Mapssheen_rough_map_onUsed internally when no override
boolThin Film WeightThin Film, Generic Mapsthin_film_map_onUsed internally when no override
boolThin Film IORThin Film, Generic Mapsthin_film_ior_map_onUsed internally when no override
boolCoating WeightClearcoat, Generic Mapscoat_map_onUsed internally when no override
boolCoating ColorClearcoat, Generic Mapscoat_color_map_onUsed internally when no override
boolCoating RoughnessClearcoat, Generic Mapscoat_rough_map_onUsed internally when no override
boolBump MapSpecial Mapsbump_map_onUsed internally when no override
boolCoating Bump MapSpecial Mapscoat_bump_map_onUsed internally when no override
boolDisplacementSpecial Mapsdisplacement_map_onUsed internally when no override
boolCutout (opacity)Special Mapscutout_map_onUsed internally when no override
floatBump Map AmountSpecial Mapsbump_map_amtColorNode
floatClearcoat Bump Map AmountSpecial Mapsclearcoat_bump_map_amtColorNode
floatDisplacement Map AmountSpecial Mapsdisplacement_map_amtColorNode

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.

MaxScript
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.

MaxScript
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.

MaxScript
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.

MaxScript
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.

MaxScript
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.

MaxScript
sgsdk_SetTextureOutputDirectory "D:\\CubeExample\\OutputTextures\\"
sgsdk_RunPipelineOnSelection reductionPipelineWithMaterialBaking

The final export script:

MaxScript
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.

MaxScript
-- 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: Physical Material - properties

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.

MaxScript
...
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: