void UnFbx::FFbxImporter::CreateUnrealMaterial(FbxSurfaceMaterial* FbxMaterial, TArray<UMaterialInterface*>& OutMaterials, TArray<FString>& UVSets) { FString MaterialFullName = ANSI_TO_TCHAR(MakeName(FbxMaterial->GetName())); // check for a 'skinXX' suffix in the material name int32 MaterialNameLen = FCString::Strlen(*MaterialFullName) + 1; char* MaterialNameANSI = new char[MaterialNameLen]; FCStringAnsi::Strcpy(MaterialNameANSI, MaterialNameLen, TCHAR_TO_ANSI(*MaterialFullName)); if (FCStringAnsi::Strlen(MaterialNameANSI) > 6) { const char* SkinXX = MaterialNameANSI + FCStringAnsi::Strlen(MaterialNameANSI) - 6; if (FCharAnsi::ToUpper(*SkinXX) == 'S' && FCharAnsi::ToUpper(*(SkinXX+1)) == 'K' && FCharAnsi::ToUpper(*(SkinXX+2)) == 'I' && FCharAnsi::ToUpper(*(SkinXX+3)) == 'N') { if (FCharAnsi::IsDigit(*(SkinXX+4)) && FCharAnsi::IsDigit(*(SkinXX+5))) { // remove the 'skinXX' suffix from the material name MaterialFullName = MaterialFullName.Left(MaterialNameLen - 7); } } } MaterialFullName = ObjectTools::SanitizeObjectName(MaterialFullName); // Make sure we have a parent if ( !ensure(Parent) ) { return; } // set where to place the materials FString NewPackageName = FPackageName::GetLongPackagePath(Parent->GetOutermost()->GetName()) + TEXT("/") + MaterialFullName; NewPackageName = PackageTools::SanitizePackageName(NewPackageName); UPackage* Package = CreatePackage(NULL, *NewPackageName); UMaterialInterface* UnrealMaterialInterface = FindObject<UMaterialInterface>(Package,*MaterialFullName); // does not override existing materials if (UnrealMaterialInterface != NULL) { OutMaterials.Add(UnrealMaterialInterface); return; } // create an unreal material asset UMaterialFactoryNew* MaterialFactory = new UMaterialFactoryNew(FPostConstructInitializeProperties()); UMaterial* UnrealMaterial = (UMaterial*)MaterialFactory->FactoryCreateNew( UMaterial::StaticClass(), Package, *MaterialFullName, RF_Standalone|RF_Public, NULL, GWarn ); // TODO : need this ? UnrealMaterial->bUsedWithStaticLighting = true; if ( UnrealMaterial != NULL ) { // Notify the asset registry FAssetRegistryModule::AssetCreated(UnrealMaterial); // Set the dirty flag so this package will get saved later Package->SetDirtyFlag(true); } // textures and properties CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sDiffuse, UnrealMaterial->DiffuseColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sEmissive, UnrealMaterial->EmissiveColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sSpecular, UnrealMaterial->SpecularColor, false, UVSets); CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sSpecularFactor, UnrealMaterial->SpecularColor, false, UVSets); // SpecularFactor modulates the SpecularColor value if there's one //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sShininess, UnrealMaterial->SpecularPower, false, UVSets); if (!CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sNormalMap, UnrealMaterial->Normal, true, UVSets)) { CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, FbxSurfaceMaterial::sBump, UnrealMaterial->Normal, true, UVSets); // no bump in unreal, use as normal map } //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, KFbxSurfaceMaterial::sTransparentColor, UnrealMaterial->Opacity, false, UVSets); //CreateAndLinkExpressionForMaterialProperty( *FbxMaterial, UnrealMaterial, KFbxSurfaceMaterial::sTransparencyFactor, UnrealMaterial->OpacityMask, false, UVSets); FixupMaterial( *FbxMaterial, UnrealMaterial); // add random diffuse if none exists // compile shaders for PC (from UPrecompileShadersCommandlet::ProcessMaterial // and FMaterialEditor::UpdateOriginalMaterial) // make sure that any static meshes, etc using this material will stop using the FMaterialResource of the original // material, and will use the new FMaterialResource created when we make a new UMaterial in place FGlobalComponentReregisterContext RecreateComponents; // let the material update itself if necessary UnrealMaterial->PreEditChange(NULL); UnrealMaterial->PostEditChange(); OutMaterials.Add(UnrealMaterial); }
//! @brief Create an Unreal Material for the given graph-instance UMaterial* CreateMaterial(graph_inst_t* GraphInstance, const FString & MaterialName, UObject* Outer) { // create an unreal material asset UMaterialFactoryNew* MaterialFactory = NewObject<UMaterialFactoryNew>(); UMaterial* UnrealMaterial = (UMaterial*)MaterialFactory->FactoryCreateNew( UMaterial::StaticClass(), Substance::Helpers::CreateObjectPackage(Outer, MaterialName), *MaterialName, RF_Standalone|RF_Public, NULL, GWarn ); // textures and properties for (auto ItOut = GraphInstance->Outputs.itfront(); ItOut; ++ItOut) { output_inst_t* OutputInst = &(*ItOut); output_desc_t* OutputDesc = OutputInst->GetOutputDesc(); CreateMaterialExpression( OutputInst, UnrealMaterial); } // special case: emissive only materials TArray<FName> ParamNames; TArray<FGuid> ParamIds; UnrealMaterial->GetAllTextureParameterNames(ParamNames, ParamIds); if (ParamNames.Num() == 1) { if (ParamNames[0].ToString() == TEXT("emissive")) { UnrealMaterial->SetShadingModel(MSM_Unlit); } } // special case: no roughness but glossiness if (!UnrealMaterial->Roughness.IsConnected()) { for (auto ItOut = GraphInstance->Outputs.itfront(); ItOut; ++ItOut) { output_inst_t* OutputInst = &(*ItOut); output_desc_t* OutputDesc = OutputInst->GetOutputDesc(); UTexture* Texture = *OutputInst->Texture; if (OutputDesc->Channel == CHAN_Glossiness && Texture) { // and link it to the material UMaterialExpressionOneMinus* OneMinus = NewObject<UMaterialExpressionOneMinus>(UnrealMaterial); UMaterialExpressionTextureSampleParameter2D* UnrealTextureExpression = CreateSampler(UnrealMaterial, Texture, OutputDesc); UnrealTextureExpression->MaterialExpressionEditorX -= 200; OneMinus->MaterialExpressionEditorX = -200; OneMinus->MaterialExpressionEditorY = UnrealTextureExpression->MaterialExpressionEditorY; UnrealTextureExpression->ConnectExpression(OneMinus->GetInput(0), 0); UnrealMaterial->Roughness.Expression = OneMinus; UnrealMaterial->Expressions.Add(UnrealTextureExpression); UnrealMaterial->Expressions.Add(OneMinus); } } } // let the material update itself if necessary UnrealMaterial->PreEditChange(NULL); UnrealMaterial->PostEditChange(); return UnrealMaterial; }