当前位置:首页 > 动态 > UE4开发入门   > UE4学习笔记——材质学习
内容详情
UE4学习笔记——材质学习
来源:      发布时间:2018-05-08 17:35      浏览:1507     字体:    
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材质实例部分,来了解一下UE4材质的强大功能。 在UE4中,材质实例分为两种类型:静态(Constant)  和 动态(Dynamic Instance),其中静态的材质实例,只能在运行前进行一次计算,在游戏中不会发生变化。动态材质实例在运行过程中是可以进行计算的。所以我们要用的就是动态材质实例。 其实动态与静态实例是不需要 手动设置的,根据材质本身的不同,UE4会自动判断。

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);
    }
}
途联微信号