C++ ときどき ごはん、わりとてぃーぶれいく☆

USAGI.NETWORKのなかのひとのブログ。主にC++。

UE4/C++: メッシュのマテリアルやテクスチャーをC++コードで制御する方法

要点を整理しようと思ったらソースの例示しかない記事になりました(ノω・)テヘ

// マテリアルをロードしてメッシュへ設定する
// mesh: UPrimitive またはその派生型( UStaticMeshComponent, UProceduralMeshComponent など)のポインターオブジェクト
// element_index: メッシュ内の要素番号。1つしか無ければ 0 のみ。
mesh->SetMaterial
( element_index
, Cast< UMaterial >
  ( StaticLoadObject
    ( UMaterial::StaticClass()
    , nullptr
    , TEXT( "/Game/MyMaterial" ) // Game/MyMaterial は UE4Editor で作り込んでおく
    )
  )
);
// マテリアルをロードしてマテリアルインスタンスを作成した上でメッシュへ設定する
// material_instance は UMaterialInstanceDynamic* 型。クラスメンバー変数として保持して使う事が多いと思う。
auto material_instance =
  mesh->CreateAndSetMaterialInstanceDynamicFromMaterial
  ( element_index
  , Cast< UMaterial >
    ( StaticLoadObject
      ( UMaterial::StaticClass()
      , nullptr
      , TEXT( "/Game/MyMaterial" )
      )
    )
  );

// マテリアルインスタンスへスカラーパラメーターを設定する。与える値の型は float
material_instance ->SetScalarParameterValue( "scalar_parameter_name", 1.23f );
// マテリアルインスタンスへベクターパラメーターを設定する。与える値の型は FLinearColor
material_instance ->SetVectorParameterValue( "vector_parameter_name", { 1.0f, 1.0f, 1.0f, 1.0f } );
// テクスチャーを作成する。
// my_generated_texture は UTexture2D* 型
constexpr int32 width  = 2;
constexpr int32 height = 2;
auto my_generated_texture = UTexture2D::CreateTransient( width, height, PF_R8G8B8A8 );
struct r8g8b8a8 { uint8 r = 255, g = 255, b = 255, a = 255; };
std::array< r8g8b8a8, width * height > my_data{};
auto locked_bulk_data = my_generated_texture->PlatformData->Mips[ 0 ].BulkData.Lock( LOCK_READ_WRITE );
FMemory::Memcpy( locked_bulk_data, my_data.data(), sizeof( r8g8b8a8 ) * my_data.size() );
my_generated_texture->PlatformData->Mips[ 0 ].BulkData.Unlock();
my_generated_texture->UpdateResource();

// マテリアルインスタンスへテクスチャーパラメーターを設定する。与える値の型は UTexture2D*
material->SetTextureParameterValue( "texture_parameter_name", my_generated_texture );
// 作成した my_generated_texture を破棄する(ことにする)。
my_generated_texture->ConditionalBeginDestroy();
my_generated_texture = nullptr;

// 作成した material_instance を破棄する(ことにする)。
material_instance->ConditionalBeginDestroy();
material_instance = nullptr;
// おまけ: アクターのメンバー関数内などで、UE4のCGが破棄する事になっているオブジェクトをに強制的に破棄させる
// GetWorld は AActor のメンバー関数
GetWorld()->ForceGarbageCollection(true);

参考

  1. UMeshComponent::SetMaterial | Unreal Engine API Reference
  2. UPrimitiveComponent::CreateAndSetMaterialInstanceDynamicFromMaterial | Unreal Engine API Reference
  3. UMaterialInstanceDynamic | Unreal Engine API Reference
  4. EPixelFormat | Unreal Engine API Reference
  5. UTexture2D | Unreal Engine API Reference
  6. Unreal Engine | インスタンス化マテリアル
  7. Is it possible to load bitmap or JPG files at runtime and use them on assets as textures? - UE4 AnswerHub
  8. How to set a texture parameter in C++? - UE4 AnswerHub