如何在Unreal Engine中为材质添加网络传输的属性信息
Unreal Engine 动态创建PBR材质并填充纹理与属性
你当前的代码仅完成了材质的基础创建,未配置任何PBR相关属性与纹理。以下是完整的实现步骤,将MaterialMetha结构体中的参数映射到材质:
1. 辅助函数:加载纹理资源
首先实现一个工具函数,将纹理路径转换为Unreal的UTexture2D对象:
UTexture2D* LoadTextureFromPath(const FString& TexturePath) { if (TexturePath.IsEmpty()) return nullptr; return Cast<UTexture2D>(StaticLoadObject(UTexture2D::StaticClass(), nullptr, *TexturePath)); }
2. 完善GenerateMaterial函数
在原有的材质创建代码基础上,添加属性配置与节点连接逻辑:
bool AShapeGenerator::GenerateMaterial(FString id, MaterialMetha metha) { FString name = FString(TEXT("Material_")) + id; FString path = FString(TEXT("/Game/Material/Generated/")); FString packageName = path + name; UPackage* package = CreatePackage(*packageName); UMaterial* mat = NewObject<UMaterial>(package, FName(*name), RF_Public | RF_Standalone); mat->AddToRoot(); // -------------------------- // 1. 配置材质基础渲染属性 // -------------------------- mat->TwoSided = metha.side; if (metha.transparent) { mat->BlendMode = EBlendMode::BLEND_Translucent; mat->Opacity = metha.opacity; } else { mat->BlendMode = EBlendMode::BLEND_Opaque; } // -------------------------- // 2. 配置基础颜色(Base Color) // -------------------------- UMaterialExpressionConstant3Vector* BaseColorNode = NewObject<UMaterialExpressionConstant3Vector>(mat); BaseColorNode->Constant = FLinearColor(metha.color); BaseColorNode->Rename(TEXT("BaseColor")); mat->Expressions.Add(BaseColorNode); UTexture2D* BaseTex = LoadTextureFromPath(metha.map); if (BaseTex) { UMaterialExpressionTextureSample* BaseTexSample = NewObject<UMaterialExpressionTextureSample>(mat); BaseTexSample->Texture = BaseTex; BaseTexSample->Rename(TEXT("BaseTexture")); mat->Expressions.Add(BaseTexSample); UMaterialExpressionMultiply* BaseMultiply = NewObject<UMaterialExpressionMultiply>(mat); BaseMultiply->Rename(TEXT("BaseColorMultiply")); mat->Expressions.Add(BaseMultiply); BaseMultiply->InputA.Expression = BaseTexSample; BaseMultiply->InputB.Expression = BaseColorNode; mat->BaseColor.Expression = BaseMultiply; } else { mat->BaseColor.Expression = BaseColorNode; } // -------------------------- // 3. 配置粗糙度(Roughness) // -------------------------- UMaterialExpressionConstant* RoughnessNode = NewObject<UMaterialExpressionConstant>(mat); RoughnessNode->R = metha.roughness; RoughnessNode->Rename(TEXT("RoughnessValue")); mat->Expressions.Add(RoughnessNode); UTexture2D* RoughnessTex = LoadTextureFromPath(metha.roughnessMap); if (RoughnessTex) { UMaterialExpressionTextureSample* RoughnessTexSample = NewObject<UMaterialExpressionTextureSample>(mat); RoughnessTexSample->Texture = RoughnessTex; RoughnessTexSample->Rename(TEXT("RoughnessTexture")); RoughnessTexSample->SamplerType = EMaterialSamplerType::SAMPLERTYPE_LinearColor; mat->Expressions.Add(RoughnessTexSample); UMaterialExpressionMultiply* RoughnessMultiply = NewObject<UMaterialExpressionMultiply>(mat); RoughnessMultiply->Rename(TEXT("RoughnessMultiply")); mat->Expressions.Add(RoughnessMultiply); RoughnessMultiply->InputA.Expression = RoughnessTexSample; RoughnessMultiply->InputB.Expression = RoughnessNode; mat->Roughness.Expression = RoughnessMultiply; } else { mat->Roughness.Expression = RoughnessNode; } // -------------------------- // 4. 配置金属度(Metallic) // -------------------------- UMaterialExpressionConstant* MetalnessNode = NewObject<UMaterialExpressionConstant>(mat); MetalnessNode->R = metha.metalness; MetalnessNode->Rename(TEXT("MetalnessValue")); mat->Expressions.Add(MetalnessNode); UTexture2D* MetalnessTex = LoadTextureFromPath(metha.metalnessMap); if (MetalnessTex) { UMaterialExpressionTextureSample* MetalnessTexSample = NewObject<UMaterialExpressionTextureSample>(mat); MetalnessTexSample->Texture = MetalnessTex; MetalnessTexSample->Rename(TEXT("MetalnessTexture")); MetalnessTexSample->SamplerType = EMaterialSamplerType::SAMPLERTYPE_LinearColor; mat->Expressions.Add(MetalnessTexSample); UMaterialExpressionMultiply* MetalnessMultiply = NewObject<UMaterialExpressionMultiply>(mat); MetalnessMultiply->Rename(TEXT("MetalnessMultiply")); mat->Expressions.Add(MetalnessMultiply); MetalnessMultiply->InputA.Expression = MetalnessTexSample; MetalnessMultiply->InputB.Expression = MetalnessNode; mat->Metallic.Expression = MetalnessMultiply; } else { mat->Metallic.Expression = MetalnessNode; } // -------------------------- // 5. 配置法线贴图(Normal Map) // -------------------------- UTexture2D* NormalTex = LoadTextureFromPath(metha.normalMap); if (NormalTex) { UMaterialExpressionTextureSampleNormal* NormalTexSample = NewObject<UMaterialExpressionTextureSampleNormal>(mat); NormalTexSample->Texture = NormalTex; NormalTexSample->Rename(TEXT("NormalTexture")); mat->Expressions.Add(NormalTexSample); mat->Normal.Expression = NormalTexSample; } // -------------------------- // 6. 配置自发光(Emissive) // -------------------------- UMaterialExpressionConstant3Vector* EmissiveColorNode = NewObject<UMaterialExpressionConstant3Vector>(mat); EmissiveColorNode->Constant = FLinearColor(metha.emissive); EmissiveColorNode->Rename(TEXT("EmissiveColor")); mat->Expressions.Add(EmissiveColorNode); UMaterialExpressionConstant* EmissiveIntensityNode = NewObject<UMaterialExpressionConstant>(mat); EmissiveIntensityNode->R = metha.emissiveIntensity; EmissiveIntensityNode->Rename(TEXT("EmissiveIntensity")); mat->Expressions.Add(EmissiveIntensityNode); UTexture2D* EmissiveTex = LoadTextureFromPath(metha.emissiveMap); if (EmissiveTex) { UMaterialExpressionTextureSample* EmissiveTexSample = NewObject<UMaterialExpressionTextureSample>(mat); EmissiveTexSample->Texture = EmissiveTex; EmissiveTexSample->Rename(TEXT("EmissiveTexture")); mat->Expressions.Add(EmissiveTexSample); UMaterialExpressionMultiply* EmissiveColorMultiply = NewObject<UMaterialExpressionMultiply>(mat); EmissiveColorMultiply->Rename(TEXT("EmissiveColorMultiply")); mat->Expressions.Add(EmissiveColorMultiply); EmissiveColorMultiply->InputA.Expression = EmissiveTexSample; EmissiveColorMultiply->InputB.Expression = EmissiveColorNode; UMaterialExpressionMultiply* EmissiveFinal = NewObject<UMaterialExpressionMultiply>(mat); EmissiveFinal->Rename(TEXT("EmissiveFinal")); mat->Expressions.Add(EmissiveFinal); EmissiveFinal->InputA.Expression = EmissiveColorMultiply; EmissiveFinal->InputB.Expression = EmissiveIntensityNode; mat->EmissiveColor.Expression = EmissiveFinal; } else { UMaterialExpressionMultiply* EmissiveFinal = NewObject<UMaterialExpressionMultiply>(mat); EmissiveFinal->Rename(TEXT("EmissiveFinal")); mat->Expressions.Add(EmissiveFinal); EmissiveFinal->InputA.Expression = EmissiveColorNode; EmissiveFinal->InputB.Expression = EmissiveIntensityNode; mat->EmissiveColor.Expression = EmissiveFinal; } // -------------------------- // 7. 编译与保存材质 // -------------------------- #if WITH_EDITOR mat->PreEditChange(nullptr); mat->PostEditChange(); mat->MarkPackageDirty(); mat->Compile(); #endif FAssetRegistryModule::AssetCreated(mat); package->FullyLoad(); package->SetDirtyFlag(true); return true; }
关键注意事项
- 确保传入的纹理路径是Unreal项目内的合法资源路径,例如
/Game/Textures/MyRoughnessMap - 如果纹理是通过网络下载的,需要先将纹理导入到项目资源中,再获取其路径传入
- 默认创建的
UMaterial使用PBR模板,无需额外切换材质类型 - 所有创建的材质表达式节点必须添加到
mat->Expressions数组,否则不会被材质识别
内容的提问来源于stack exchange,提问作者lilington
相关产品推荐
相关产品推荐

