You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 09:59:57