关于静态材质(MIC)文件的创建及参数设置

1

主题

2

帖子

4

积分

新手上路

Rank: 1

积分
4
发表于 2023-1-18 13:43:43 | 显示全部楼层
前言

——本篇针对的是静态材质实例(MIC)的操作,动态材质实例(MID)可以看上一篇。
UE蓝图

——现成的蓝图节点里没有创建也没有Set参数,只有GetXXXParameterValue系列,就是下面这种同名但是写了“MIC”的。




——需要注意的是,Target输入接口的对象类型需要是MaterialInstanceConstant,即MIC,这也是它们与MID相关节点的唯一区别。
UE C++

——先保证你在.h中引了下面两个头文件
#include "Materials/MaterialInstanceConstant.h"
#include "AssetRegistry/AssetRegistryModule.h"
1、创建MIC文件

——其实资产操作相关的API有很多效果相似的,我现在也不是很清楚他们之间的区别,目前姑且先按下面套路来做,至少可以保证是有效的。不久之后的StaticMesh读写与创建也会用到相同的套路。
//路径拼装
FString Path = TEXT(文件保存路径);
FString OutName = TEXT(文件名);
FString PackageName = TEXT("/Game/") + Path + OutName;//"/Game/"效果等同于项目的Content目录,一般不要改

//拷贝输入的MIC相关数据到新的MIC中
UPackage* Package = CreatePackage(*PackageName);
UMaterialInstanceConstant* OutMIC = NewObject<UMaterialInstanceConstant>(Package, *OutName, RF_Public | RF_Standalone);
OutMIC->Parent = MI;//指定新创建的OutMIC的父材质,对应材质实例面板的Parent。可以是材质也可以是材质实例,即UMaterialInterface
//这里可以配置一些其他的参数设置

//创建文件
FAssetRegistryModule::AssetCreated(OutSM);

//保存更改
Package->SetDirtyFlag(true);//如果没有这行,虽然跑完上面的代码就可以看到生成的文件,但关掉再开UE后会发现文件消失
//U3D中也有一些类似的Dirty的概念和API
——如果要更保险一些,其实还需要加一些类型判断,路径检查之类的代码,这里只是提取了必要的步骤来做。
——除了Parent材质外,也可以代码配置一些其他的材质实例面板中的参数,用MIC->的代码提示猜一猜试一试即可,这里不再赘述。
2、参数读写

//以四维向量的配置为例
FLinearColor ColorOUT;
MIC->GetVectorParameterValue(TEXT("参数名"), ColorOUT);
MIC->SetVectorParameterValueEditorOnly(TEXT("参数名"), ColorOUT);
——看名字都知道,Set方法只能在Editor模式下用。而且如果你在运行时用这个方法,停止运行后,其对MIC做出的修改是不会重置的,这点和U3D不同。
3、案例

——这里临时补充一个知识点,就是UE中的PostEditChangeProperty方法。
void AActor::PostEditChangeProperty(FPropertyChangedEvent& e)
{
        Super::PostEditChangeProperty(e);
}
——它的作用相当于U3D里的OnValidate,即每当参数发生改变就会调用一次这个方法。UE里能起到相同效果的做法还有一个,就是在蓝图的构造函数(Construction Script)里去连一些节点。
——这种方法的好处就是能让美术,策划等在非运行模式下就能实时的看到调参带来的效果改变。
——然后我们这次利用PostEditChangeProperty方法来做一个给2Dfbm材质批量调参的功能,最终效果是下面这样。


https://www.zhihu.com/video/1594666183537655809
——因为我还不知道UE怎么给材质传数组(如果不用一些像是纹理存数组这种骚操作的话),所以这次姑且给定一个4阶的fbm。参数名匹配的方式也因此比较蠢,见谅- -
——材质大概是下面这样。


——这里图方便连了个自定义节点MF_FbmSampler去算UV和采样。


——然后代码都是在PostEditChangeProperty里的。因为参数名和循环上限是死的,所以代码仅针对本文案例。
——简单说一下案例结构:
1、ScaleVelocity参数中,R=混合权重、G=纹理缩放、BA=速度向量
2、下面的代码基本思路是,Step控制fbm阶数、RG通道按等比数列缩放、BA通道的向量长度和方向角按等差数列累加
//头文件的参数定义部分
UPROPERTY(EditAnywhere)
        UMaterialInstanceConstant* MIC;
UPROPERTY(EditAnywhere, meta = (ClampMin = 1, ClampMax = 4, UIMin = 1, UIMax = 4))
        int8 Step = 2;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0, ClampMax = 1, UIMin = 0, UIMax = 1))
        float AttenRatio = 0.5f;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0, ClampMax = 2, UIMin = 0, UIMax = 2))
        float ScaleRatio = 2;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0, ClampMax = 1, UIMin = 0, UIMax = 1))
        float VelocityDelta = 0.5f;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0, ClampMax = 10, UIMin = 0, UIMax = 10))
        float Scale0 = 1;
UPROPERTY(EditAnywhere, meta = (ClampMin = 0, ClampMax = 1, UIMin = 0, UIMax = 1))
        float Velocity0 = 1;

//cpp的PostEditChangeProperty
void AFbmManager::PostEditChangeProperty(FPropertyChangedEvent& e)
{
        Super::PostEditChangeProperty(e);

        if (MIC)
        {
                float Sigma = (1 - pow(AttenRatio, Step)) / (1 - AttenRatio);
                float DeltaAngle = 2 * PI / Step;
                for (int8 i = 0; i < 4; i++)
                {
                        FName CurrentName = FName(*FString::Printf(TEXT("ScaleVelocity_%d"), i));
                        if (i < Step)
                        {
                                FLinearColor CurrentCol = FLinearColor(
                                        pow(AttenRatio, i) / Sigma,
                                        Scale0 * pow(ScaleRatio, i),
                                        (Velocity0 + VelocityDelta * i) * cos(DeltaAngle * i),
                                        (Velocity0 + VelocityDelta * i) * sin(DeltaAngle * i)
                                );
                                MIC->SetVectorParameterValueEditorOnly(CurrentName, CurrentCol);
                        }
                        else
                        {
                                MIC->SetVectorParameterValueEditorOnly(CurrentName, FLinearColor::Transparent);
                        }
                }
        }
}
U3D

——U3D的静态动态材质的API没有区别,直接看上一篇即可。
——关于U3D的资产创建可以提一嘴,简单来说就是AssetDatabase.CreateAsset。
Material matDst = new Material(matSrc);
AssetDatabase.CreateAsset(matDst, "Assets/TEST.mat");//一般打头都是Assets,后面可以自己改
AssetDatabase.Refresh();
——CreateAsset的第一个参数是祖类Object类型,所以这个API不光能生成材质球,很多U3D类对象都可以用这个创建出资产文件。一般创建完了之后可以来一发AssetDatabase.Refresh来刷新一下Project目录,省的手动Ctrl+R才能在Project中看到生成的资产。
回复

举报 使用道具

您需要登录后才可以回帖 登录 | 立即注册
快速回复 返回顶部 返回列表