[Bug] TitanEditor EditMaterial::fixOldReflect makes old materials metallic → dark
I noticed when I would change any parameter of the "Path" material in the Tutorials in Titan Editor the material would immediately become darker.
AI solved it, I'm not sure if this is because of some other change I made in the engine or not but here was the solution..
[Bug] TitanEditor EditMaterial::fixOldReflect makes old materials metallic → renders dark (esp. on terrain)
Summary
When an old material (one saved with a single reflect value, before the reflect_min/reflect_max model) is loaded into TitanEditor, EditMaterial::fixOldReflect() can wrongly set reflect_max = 1, turning a dielectric material into a metallic one. On terrain (multi-material rendering) this makes the material render much darker than its texture, because the high reflectivity reads the packed metal channel and metals have ~no diffuse albedo.
Affected code
Editor/.../Shared/Elements/Material.cpp — EditMaterial::fixOldReflect(flt reflect):
void EditMaterial::fixOldReflect(flt reflect)
{
if(metal_map.is())
{
reflect_min=MATERIAL_REFLECT;
reflect_max=reflect;
}else
{
reflect_min=reflect;
reflect_max=1; // <-- bug
}
}
Introduced in commit 60929bf7708b2ff18e92032411928947bf4b74ca (2022-02-21), when the reflect_min/reflect_max model was added — so it's long-standing, not platform-specific.
Root cause
An old single-reflect material had constant reflectivity (it predates per-texture metalness). The no-metal-map branch sets reflect_max = 1, and on publish Material::reflect(min, max) computes:
reflect_add = min; reflect_mul = (1 - min) * max;
So reflect(0.04, 1.0) → reflect_mul ≈ 0.96. The intent appears to be "harmless when there's no metal map," but the multi-material / terrain shader samples the metal channel of the packed base_2 (Ext) texture regardless of whether a separate metal_map was assigned. With reflect_mul ≈ 0.96, reflectivity becomes 0.04 + 0.96 × base_2.metal, i.e. metallic wherever that channel is bright → the surface renders dark. The engine's own old-material Material::loadData conversion, by contrast, uses reflect_mul = 0 (pure dielectric), so the editor was inconsistent with the engine.
Observed effects / how it presents (very confusing!)
- A material's tile preview looks correct/light (single-material path doesn't sample that metal channel), which masks the problem.
- Painted onto terrain it renders dark, and it's per-material (paint the dark material anywhere → dark; the light one → light).
- A raw copy of an old material stays correct (still the old single-reflect format, dielectric). Editing it (tweaking any slider) republishes it through fixOldReflect → it becomes metallic → goes dark and stays dark, even though the color (1,1,1,1) and all visible sliders look normal. The only tell is ReflectivityMax = 1.000 in the material editor.
Reproduction
1. Take an old-format material that has packed base textures and no separate metal_map, with low/constant reflectivity.
2. Assign it to terrain — looks fine.
3. Edit any slider (forces a republish through fixOldReflect).
4. It renders noticeably darker on terrain; the tile preview still looks light.
Fix
Make the no-metal-map branch dielectric (matching the engine and how a normal dielectric material loads, where reflectMax() == 0):
}else
{
reflect_min=reflect;
reflect_max=0; // dielectric: old single-'reflect' materials have constant reflectivity; 0 => reflect_mul=0 (matches Material::loadData)
}
|