UE4學習筆記(4)——材質學習
UE4材質相關的東西很多,要學起來比較複雜,今天通過一個讓物體從透明逐漸顯現出實體的例項,來初步瞭解一下UE4的材質、材質例項的一些基本知識。
1. 我們的目標是讓物體從透明逐漸顯現,那麼先整理一下實現思路,如果開發過遊戲或者對模型有一些基本的瞭解,一般都會想到,通過調節材質的Alpha通道,使其從0調節到1的過程,物體的透明度就會從純透明變化到實體。如果是U3D,直接獲取材質的Alpha通道進行調節即可,實現起來非常簡單,下面我們來看一下UE4的實現方法。
2. UE4的材質分為5種類型,Opaque,Masked,Translucent,Additive,Modulate,其中Opaque是預設型別,為不透明材質。 Translucent為可透明材質。顯而易見我們這裡選用Translucent型別。 在Opaque模式下,材質的Opacity屬性是灰的,不可調節。 換成Translucent模式,該屬性點亮,但是很多其他屬性例如金屬性等都變灰,會損失很多的材質資訊,這個我們後面進行分析和處理。
3. 我們把材質的Blend mode改為Translucent,並且為材質新增一個Scalar Parameter,(在材質編輯器的右邊Palette中找到Scalar Parameter並拖拽到編輯器中),並把它與Opacity相連。相當於為材質的透明度關聯了一個引數,我們只需要在遊戲中調節該引數就可以控制該材質的透明度了。
4. 在UE4中,材質有點類似於類,在真正的應用中,我們一般會使用材質例項,材質例項相當於材質的例項化,所以為了實現該功能,可以先參考官方文件https://docs.unrealengine.com/latest/INT/Engine/Rendering/Materials/MaterialInstances/index.html
5. 我們在編輯好的材質上點右鍵,可以看到Create Material Instance的選項,點選就可以生成該材質的例項,點開材質例項可以看到左邊Parameter Group中,我們新增的Scalar Parameter已經在裡面了,改變他的值可以在預覽視窗中看到材質例項的變化。
6. 到此為止我們要實現功能的材質例項已經搞定啦,下面我們來實現其邏輯,首先我們建立一個類,起名叫ATransparatableActor,繼承Actor類, 為其建立兩個UMaterialInstance屬性,以及一個UStaticMeshComponent的列表,用來儲存Actor中所有的靜態模型(因為預先不知道Actor中會有多少個模型,所以為了實現透明漸變,必須為所有的模型都換上可透明材質)
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ChangeTransparentalbe")
UMaterial* M_TransparentalbeMaterial;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ChangeTransparentalbe")
UMaterial* M_OpaqueMaterial;
TArray<UStaticMeshComponent*> Components;
其中M_TransparentalbeMaterial為可透明材質,M_OpaqueMaterial為不可透明材質,Components為模型列表。
7. 之後新增一個timeline用來調節Alpha的值,來產生透明變換,Timeline是UE4的一個空間,具體可以參考UE4的文件,後續會介紹其功能
UPROPERTY()
UTimelineComponent* Timeline;
FOnTimelineFloat InterpFunction{};
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "ChangeTransparentalbe")
UCurveFloat* fCurve;
其中InterpFunction是Timeline繫結的函式,fCurve是Timeline的曲線引數。
8. 最後實現邏輯部分程式碼,邏輯就是在透明變換之前,為Actor所有的靜態模型換上可透明材質,之後通過把timeline的值付給Scalar Parameter調節材質例項的Opacity引數,實現漸變過程,在Opacity引數達到1後,也就是變為純不透明物體時,把材質換位不可透明材質。
//建構函式,初始化timeline
AATransparentableActor::AATransparentableActor(const FObjectInitializer& ObjectInitializer)
:Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = true;
// Initiate the timeline
Timeline = ObjectInitializer.CreateDefaultSubobject<UTimelineComponent>(this, TEXT("Timeline"));
//Bind the Callbackfuntion for the float return value
InterpFunction.BindUFunction(this, FName{ TEXT("TimelineFloatReturn") });
}
// Called when the game starts or when spawned
void AATransparentableActor::BeginPlay()
{
Super::BeginPlay();
if (fCurve)
{
Timeline->AddInterpFloat(fCurve, InterpFunction, FName{ TEXT("Alpha") });
}
}
bool AATransparentableActor::IsTransforming()
{
if (Timeline->IsPlaying())
{
return true;
}
else
{
return false;
}
}
// Called every frame
void AATransparentableActor::Tick( float DeltaTime )
{
Super::Tick( DeltaTime );
if (IsTransforming()) {
TransformByAlpha();
}
}
void AATransparentableActor::SetTransparentable()
{
//TArray<UStaticMeshComponent*> Components;
this->GetComponents<UStaticMeshComponent>(Components);
if (M_TransparentalbeMaterial) {
for (int32 Index = 0; Index != Components.Num(); ++Index)
{
UStaticMeshComponent* targetComp = Components[Index];
targetComp->SetMaterial(0, M_TransparentalbeMaterial);
}
}
}
void AATransparentableActor::SetOpaque()
{
//TArray<UStaticMeshComponent*> Components;
this->GetComponents<UStaticMeshComponent>(Components);
if (M_OpaqueMaterial) {
for (int32 Index = 0; Index != Components.Num(); ++Index)
{
UStaticMeshComponent* targetComp = Components[Index];
targetComp->SetMaterial(0, M_OpaqueMaterial);
}
}
}
void AATransparentableActor::StartTransform()
{
Timeline->Play();
}
void AATransparentableActor::TransformByAlpha()
{
//TArray<UStaticMeshComponent*> Components;
this->GetComponents<UStaticMeshComponent>(Components);
float AlphaFloat = 0.0f;
if (fCurve)
{
AlphaFloat = fCurve->GetFloatValue(Timeline->GetPlaybackPosition());
}
for (int32 Index = 0; Index != Components.Num(); ++Index)
{
UStaticMeshComponent* targetComp = Components[Index];
targetComp->SetScalarParameterValueOnMaterials("alpha", AlphaFloat);
}
}
9. 我們 要注意的是,如果材質為可透明材質,那麼即便Opacity引數為1,該物體也是透明的,如果多個透明物體疊加會出現嚴重的效率瓶問題,要儘量避免該情況發生。