K.Wagrez Posted June 12, 2025 Posted June 12, 2025 Hello everyone, Newcomer here, trying to wrap my head around Unigine. I'm coming from an Unity background, so a lot of the questions I ask myself are related to the changes I can expect moving from Unity to Unigine. My question of today is related to the materials. I have a pointer to the object "OBJ", one of many similar objects (same mesh, same material). These objects were not created manually by code, they are in the .world, and they are used as node references. If in the C++ code I call the method pOBJ->setMaterialParameter and change anything other than a texture (like changing the intensity of emission for example), will it implicitly create a material instance specific to this object OR will it modify the general material parameters ? OR does it use a "material property block" style approach which avoids breaking batching (one can always dream) ? And does this behavior changes if I modify a texture ? (Unity does allow some leeway for GPU instancing with non-texture parameters, that's why I make the distinction) Maybe the answer is in the forum/documentation, I haven't yet found it. Thanks in advance
bmyagkov Posted June 16, 2025 Posted June 16, 2025 Hello! @K.WagrezThe setMaterialParameter/Texture function uses getMaterialInherit which inherits the material if it has not been inherited yet. Batching breaks if the inherited material contains any overrides. However, if it is simply an inherited child without any modifications batching will work correctly. Please let us know if you need any further assistance with this matter. Thanks!
K.Wagrez Posted June 16, 2025 Author Posted June 16, 2025 Okay, so If I understand what's an inherited material, it means that every time I use setMaterialParameter on an object whose material is not inherited yet, it will create a new material which inherits the base one, thus breaking batching, since I override a parameter by calling setMaterialParameter. Is there a way to reset a material's overrides relative to the parent it is inheriting from ?
bmyagkov Posted June 16, 2025 Posted June 16, 2025 14 minutes ago, K.Wagrez said: Okay, so If I understand what's an inherited material, it means that every time I use setMaterialParameter on an object whose material is not inherited yet, it will create a new material which inherits the base one, thus breaking batching, since I override a parameter by calling setMaterialParameter. Is there a way to reset a material's overrides relative to the parent it is inheriting from ? Yes, calling setMaterialParameter will cause the object to inherit a material and apply the parameter to the inherited instance which can break batching. To avoid this, you can call clearMaterialInherit on the object which removes the inherited material—leaving only the original (parent) material. Alternatively, if you're working directly with materials, you can use resetParameter to restore the parameter to its default value and help maintain batching. Thanks! 1
Gmarquez Posted June 30, 2025 Posted June 30, 2025 (edited) Hi there, I'm gonna bump up this thread. As far as I read, I'm understanding that direct modification of a material parameter of a node added in code behind or previously included in the .world, wioll create a cchild material so any modification of this child material will not affect the properties of the material from others objects using the same material (same parent I guess). I'm asking because changing the properties of a material, all the objects using this material are changing at the same time. The objects are being included in the scene in code behind using basically this code node = util::UnigineUtils::handleNullprt(Unigine::World::loadNode(mNodePath.c_str(), 0), B_RED("NodePath not found. Node ")); node->setEnabled(true); node->updateEnabled(); node->setLifetime(Unigine::Node::LIFETIME_WORLD); node->setWorldPosition(Unigine::Math::Vec3(static_cast<double>(mIntelligentEntityType->getStartingX()), static_cast<double>(mIntelligentEntityType->getStartingY()), And the material parameter modification is being do with this one for (int j = 0; j < child->getNumSurfaces(); j++) { if (child->getMaterial(j) != nullptr) { child->getMaterial(j)->setParameterFloat4( child->getMaterial(j)->findParameter(util::UnigineUtils::ALBEDO_COLOR.c_str()), Unigine::Math::vec4(mDeltaColor, mDeltaColor, mDeltaColor, 1.0)); child->getMaterial(j)->setParameterFloat4( child->getMaterial(j)->findParameter(util::UnigineUtils::DIFFUSE_COLOR.c_str()), Unigine::Math::vec4(mDeltaColor, mDeltaColor, mDeltaColor, 1.0)); child->getMaterial(j)->setParameterFloat4( child->getMaterial(j)->findParameter(util::UnigineUtils::AUXILIARY_COLOR.c_str()), Unigine::Math::vec4(mDeltaIR, mDeltaIR, mDeltaIR, 1.0)); } } We are just fading the color of the object to black. And all objects using this material are fading to black at the same time. I have tryied to clone the material and asing it the suface to isolate the modification to another material not related with the original one for (int j = 0; j < object->getNumSurfaces(); j++) { if (object->getMaterial(j) != nullptr) { std::string name = object->getMaterial(j)->getManualName(); if (name.empty() != 0) { name.append(std::to_string(node->getID())); Unigine::MaterialPtr mat = object->getMaterial(j)->clone(); object->setMaterial(mat, j); } } } But the documentation sais that "Clones the material. The cloned material will be empty" which Eexactly I dont undestand what imply, but looks like it's not what I'm looking for. Also I have tried to manually inherit the material, but the result is the same for (int j = 0; j < object->getNumSurfaces(); j++) { if (object->getMaterial(j) != nullptr) { std::string name = object->getMaterial(j)->getManualName(); Unigine::MaterialPtr mat = Unigine::Materials::findManualMaterial(name.c_str()); if (mat != nullptr) { name.append(std::to_string(node->getID())); Unigine::MaterialPtr inheritMateiral = mat->inherit(); object->setMaterial(inheritMateiral, j); } } } Any advice or clarification on how to tackle this? Edited June 30, 2025 by Gmarquez
K.Wagrez Posted June 30, 2025 Author Posted June 30, 2025 The difference with what I have done in my first post, is that I was calling directly the SetMaterialParameter, while you are getting the material first. The behavior you obtain in your first code seem intuitively like the correct behavior. What are you trying to achieve ? you want to make an inherited material for each object ? Have you tried the getMaterialInherit (Unigine::Object Class - Documentation - Unigine Developer) ?
Gmarquez Posted June 30, 2025 Posted June 30, 2025 I think that in some point I have tried the getInheritMaterial method, with the same result. I'm going try the direct material parameter modification without get first the material. Lets see if this change something as you are usign this way and looks it's working fine. What I'm trying to achieve is just "burn" a destroyed vehicle in a lapse of time, fading the albedo color to a blackish color. but all unit of the same type in my world are fading to black, so the material modified is the parant used by all the units. If I need to create an inherited material for aech unit, it's ok, but in my actual tries all the units are being affected by the modification. The code maybe looks somethig messy because it's coming from a port of the 2.4.1 version which have a lot less functionality and you need to do some workarounds to get the things working.
Gmarquez Posted June 30, 2025 Posted June 30, 2025 Using getMaterialInherit solve the problem of modify the parent material when you want to midify a child one. Thanks for the hint @K.Wagrez 1
Recommended Posts