Corona material property names in MaxScript: Physical vs Legacy vs Max Physical

If you script materials in 3ds Max with Corona, the first thing to know is that the same slot has a different scripting name on each material class. Diffuse colour is baseColor on CoronaPhysicalMtl, diffuseColor on CoronaLegacyMtl and CoronaMtl, and base_color on Max's own PhysicalMaterial. A script written against one class will quietly do nothing on another, and that is behind most of the scripts in our notes that reported "Done" and changed nothing.
This guide is the reference we keep for those names, with the gotchas we hit and the ways a script can reach every material in a scene. The Physical names were confirmed with getPropNames on Corona 12 with 3ds Max 2025. We have not yet rechecked them on Corona 14, so run the dump below on your own build before relying on them.
It is the second guide in our 3ds Max series. The first, How to prompt AI to write 3ds Max scripts that actually work, covers the rules and template these names plug into.
Check the class first
Pick the column in the table below by the material's class, not by what the slot is called in the editor. This read only dump prints the class and every property the selected object's material actually has:
Use getPropNames rather than showProperties. On some Max 2025 builds showProperties prints to the editor window and the Listener just says OK.
The property reference
Confirmed on Corona 12 with Max 2025. Blank cells are slots we have no confirmed name for.
Slot | CoronaPhysicalMtl | CoronaLegacyMtl / CoronaMtl | Max PhysicalMaterial |
|---|---|---|---|
Diffuse colour |
|
|
|
Diffuse map |
|
|
|
Reflection |
|
|
|
Roughness map |
| ||
IOR |
|
| |
Bump map |
|
|
|
Bump amount |
|
|
|
Self illum level |
|
|
|
Self illum colour |
|
| |
Self illum map |
|
|
|
Opacity |
|
| |
Refraction |
| ||
Displacement |
| ||
Clearcoat |
| ||
Sheen |
| ||
Translucency |
|
The gotchas
Lowercase i.
selfillumMapAmounton Physical has a lowercase i in illum.Zero is not off. Zeroing the self illum level is not enough if a map is still plugged in. Set the map to
undefinedand the colour to black too. In our notes, "self illum still glowing at 0" came down to exactly this.Legacy names on Physical fail. Using
selfIllumMultiplieron a Physical material gives an unknown property error. The Physical name isselfIllumLevel.Roughness and glossiness run opposite ways. Physical scripts reflection as
baseRoughness, where 0 is sharp. Legacy usesreflectionGlossiness, where 1 is sharp. They are inverses: glossiness = 1 minus roughness. Our matte script gave PhysicalbaseRoughness = Rand LegacyreflectionGlossiness = 1 - R, so one value drove both classes.The UI may say Glossiness anyway. Physical shows "Glossiness" in the UI on some builds, but the only property we have found is
baseRoughness, and a glossiness script on one build left the field reading 0.9. This is still unresolved in our notes (see the last section).
Other Corona classes you will meet
CoronaLightMtl: real emitters. Leave these alone in any self illum clean up.CoronaSelectMtland theCoronaSelecttexmap. On the texmap, the switch is.selected, not.selectedMap, and it is 0 based, matching the Subtex number in the UI.CoronaScannedMtl: a NaN risk.CoronaColorCorrect: its input isinputTexmap, and it hasgamma.CoronaDecalMtlandCoronaMtlBlend.
Reaching every material
The right property name only helps if the script reaches the material. These are the patterns in our notes, from shallowest to deepest. The shallow ones are why scripts said "Done" and changed nothing.
Pattern | Reaches | Misses | Use when |
|---|---|---|---|
A: | Materials in editor slots | Anything only assigned to objects | Almost never |
B: | Top level material on each object | Anything nested | Flat imported assets |
C: B + | One level of Multi/Sub | CoronaSelect, Blend, nested Multi/Sub | Simple archviz scenes |
D: recursive | Everything, at any depth | Nothing | Default for all bulk edits |
E: D + | Texmaps too (CoronaSelect texmap, Composite, ColorCorrect) | Nothing | Finding a named map, NaN hunts |
F: | Every bitmap in the file | Context of which material owns it | Texture collect and relink |
Two rows from our notes show why this matters. sceneMaterials finds 0 materials when they are only assigned to objects and not sitting in the editor. And in one scene, a search for materials sharing a name prefix found only 2 of 13, because the rest were nested in Multi/Sub materials. A recursive walk found them all.
Pattern D, the deep walk
This is the version that worked. It follows every sub material at any depth, skips anything it has already seen, and branches on class so each one gets the right property names:
The counters are global on purpose: a counter a function changes stays at 0 otherwise.
Pattern E, finding a texmap by name
When the thing you need is a map rather than a material, walk texmaps as well as sub materials:
We used this to find a CoronaSelect texmap that sat in a Legacy material's diffuse slot, under two CoronaColorCorrect maps and a Composite layer. A screenshot of the Slate node tree is the fastest way to map a chain like that before scripting it.
How three of our scripts use these names
Triplanar consolidator. It reads every texture slot on a material by number with getNumSubTexmaps and getSubTexmap, skipping slots that already hold a CoronaTriplanar or an output helper. It plugs each map into one CoronaTriplanar, then wires a MultiOutputChannelTexmapToTexmap back into the original slot with setSubTexmap, one output channel per map. Working by slot number means it does not need to know the property names at all.
Scatter edge trimmer. It works on the selection and goes one level into Multi/Sub materials (pattern C). It only touches sub materials where hasProperty sub #opacityTexmap is true, the same name as the Physical opacity slot in the table. For each one it creates a unique ChaosScatterEdgeTrimming with createInstance, puts it in opacityTexmap first, then plugs the old map into the trimmer's defaultMap, and switches opacityTexmapOn on. It closes the Slate Material Editor while it runs, to stop the UI merging the new maps into one instance.
Kill accidental self illum. It looks only at CoronaPhysicalMtl, so CoronaLightMtl emitters stay lit. A material counts as emitting if selfIllumLevel is above 0, or if selfIllumTexmapOn is on with a map in selfIllumTexmap. It then sets selfIllumLevel to 0 and selfIllumTexmapOn to false, each inside try ( ) catch ( ), and prints every material it changed. It loops every object in the scene plus sceneMaterials, and goes one level into Multi/Sub.
Scripts like these are on our free 3ds Max scripts page, added one at a time.
What is still open
Two checks are still open in our notes, and both affect this table:
Glossiness on CoronaPhysicalMtl. Dump every property matching rough or gloss on one material, and note which property the UI field reads and which direction is matte.
Corona 14 names. Run the property dump on one Physical material in Corona 14 and compare it with the table.
Until then, treat the Physical column as confirmed on Corona 12 only, and dump before you script.
Need visuals built on a careful pipeline?
We use this reference on our own architectural and interior visualisation work. See our recent work, or get in touch to talk through your next project.

