Unreal Engine 4 —— 使用IPlatformFile进行Shader文件在开发团队间的共享

这篇博客介绍了如何使用IPlatformFile来实现Shaders文件在开发团队间的共享。

这篇博客所涉及的代码来自Temaran的UE4ShaderPluginDemo里面的ShaderCopyHelper插件。


背景

虽然UE4的材质编辑器已经足够强大并且可以支持大部分的需求了,但是有时候我们还是需要自定义自己的Shader。

但是由于UE4的着色器必须位于Engine/Shaders/文件夹下,这样一来针对那些不进行定制化UE4的开发团队来说,对Shaders文件夹进行代码管理就不太方便了。

解决方案

对于开发团队来说,最好的解决方案便是在项目文件夹下维护一个Shaders文件夹。由于Shaders文件夹位于项目文件夹下,因此对其进行代码管理就是一件非常容易的事。

那么我们要做的便是在引擎打开时,将项目下的Shaders下的文件复制到Engine/Shaders/文件夹中,并且在引擎关闭时,将这些文件删除。

使用插件uplugin

由于UE4的插件可以将StartupModule()ShutdownModule()直接暴露出来,并且可以指定其只在编辑器(Developer)下启用,因此无疑成为了这个功能实现的最好平台。

"Modules" :
[
    {
        "Name" : "ShaderCopyHelper",
        "Type" : "Developer",
        "LoadingPhase" : "PostConfigInit"
    }
]

代码实现

了解原理后,具体的实现就很简单了。先遍历项目文件夹下的Shaders文件夹并获得所有的Shader文件名:

bool FShaderFileVisitor::Visit(const TCHAR* FilenameOrDirectory, bool bIsDirectory)
{
    if (!bIsDirectory)
    {
        ShaderFilePaths.Add(FPaths::GetCleanFilename(FilenameOrDirectory));
    }

    return true;
}

在整个模块startup时,使用IPlatformFile::CopyFile(const TCHAR* To, const TCHAR* From)函数进行文件的拷贝:

void FShaderCopyHelperModule::StartupModule()
{
    UE_LOG(ShaderCopyHelper, Log, TEXT("Shader Copy Helper Plugin loaded!"));

    FString GameShadersDirectory = FPaths::Combine(*FPaths::GameDir(), TEXT("Shaders"));
    FString EngineShadersDirectory = FPaths::Combine(*FPaths::EngineDir(), TEXT("Shaders"));

    ShaderFiles = new FShaderFileVisitor();
    IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
    PlatformFile.IterateDirectoryRecursively(*GameShadersDirectory, *ShaderFiles);

    UE_LOG(ShaderCopyHelper, Log, TEXT("Copying project shader files to Engine/Shaders/"));
    for (int32 ShaderFileIndex = 0; ShaderFileIndex < ShaderFiles->ShaderFilePaths.Num(); ShaderFileIndex++)
    {
        FString CurrentShaderFile = ShaderFiles->ShaderFilePaths[ShaderFileIndex];
        FString GameShaderFullPath = FPaths::Combine(*GameShadersDirectory, *CurrentShaderFile);
        FString EngineShaderFullPath = FPaths::Combine(*EngineShadersDirectory, *CurrentShaderFile);

        if (PlatformFile.CopyFile(*EngineShaderFullPath, *GameShaderFullPath))
        {
            UE_LOG(ShaderCopyHelper, Log, TEXT("Shader file %s copied to %s."), *GameShaderFullPath, *EngineShaderFullPath);
        }
        else
        {
            UE_LOG(ShaderCopyHelper, Warning, TEXT("Could not copy %s to %s!"), *GameShaderFullPath, *EngineShaderFullPath);
        }
    }
}

同样的,在模块退出时,将这些文件删除:

void FShaderCopyHelperModule::ShutdownModule()
{
    FString EngineShadersDirectory = FPaths::Combine(*FPaths::EngineDir(), TEXT("Shaders"));
    IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();

    UE_LOG(ShaderCopyHelper, Log, TEXT("Deleting project shaders from Engine/Shaders/"));
    for (int32 ShaderFileIndex = 0; ShaderFileIndex < ShaderFiles->ShaderFilePaths.Num(); ShaderFileIndex++)
    {
        FString EngineShaderFullPath = FPaths::Combine(*EngineShadersDirectory, *ShaderFiles->ShaderFilePaths[ShaderFileIndex]);

        if (PlatformFile.DeleteFile(*EngineShaderFullPath))
        {
            UE_LOG(ShaderCopyHelper, Log, TEXT("Shader file %s deleted."), *EngineShaderFullPath);
        }
        else
        {
            UE_LOG(ShaderCopyHelper, Warning, TEXT("Could not delete %s!"), *EngineShaderFullPath);
        }
    }

    delete ShaderFiles;

    UE_LOG(ShaderCopyHelper, Log, TEXT("Shader Copy Helper Plugin unloaded!"));
}

这样一来,团队中的成员只需要启用这个插件,然后维护Shaders文件夹就可以了。

<全文完>

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值