UE4 如何将材质Material保存为本地图片Png
关于如何保存TextureRenderTarget2D,从虚幻4的回答中心中,一搜就搜到了这篇文章:
TextureRenderTarget2D saved to PNG is much darker
里面提供了一个保存TextureRenderTarget2D到本地PNG的方法,我把它写进了一个蓝图函数库里面:
BlueprintFunctionBPLibrary.h中:
#include "Runtime/Engine/Public/ImageUtils.h"
UCLASS()
class UBlueprintFunctionBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
//保存UTextureRenderTarget2D到本地文件
UFUNCTION(BlueprintCallable, meta = (DisplayName = "SaveRenderTargetToFile", Keywords = "SaveRenderTargetToFile"), Category = "SaveToFile")
static bool SaveRenderTargetToFile(UTextureRenderTarget2D* rt, const FString& fileDestination);
};
BlueprintFunctionBPLibrary.cpp中:
#include "BlueprintFunctionBPLibrary.h"
#include "BlueprintFunction.h"
bool UBlueprintFunctionBPLibrary::SaveRenderTargetToFile(UTextureRenderTarget2D* rt, const FString& fileDestination)
{
FTextureRenderTargetResource* rtResource = rt->GameThread_GetRenderTargetResource();
FReadSurfaceDataFlags readPixelFlags(RCM_UNorm);
TArray outBMP;
outBMP.AddUninitialized(rt->GetSurfaceWidth() * rt->GetSurfaceHeight());
rtResource->ReadPixels(outBMP, readPixelFlags);
FIntPoint destSize(rt->GetSurfaceWidth(), rt->GetSurfaceHeight());
TArray CompressedBitmap;
FImageUtils::CompressImageArray(destSize.X, destSize.Y, outBMP, CompressedBitmap);
bool imageSavedOk = FFileHelper::SaveArrayToFile(CompressedBitmap, *fileDestination);
return imageSavedOk;
}
可以看到引擎中效果图:
和保存的a.png图:
对比上面两张图,感觉明显不对。感觉透明通道有很大的问题
上面那篇文章也说了,保存的图颜色比引擎中看到的要淡很多,如下图:
*注意:上面这一步我理解错了,人家说的Darker,不是我遇到的这个问题,详见这里:UE4 如何将材质Material保存为本地图片Png
我这边的问题暴露的更严重,感觉透明通道都不正常了(很感谢暴露得很严重的问题)
如果,能有可以看到图像像素数据的工具就好了…
还别说,还真有,感谢我吧。
先做一个UE4的OpenCV的插件,可以参考我这篇博客:
UE4使用第三方库Ⅱ
https://blog.csdn.net/lunweiwangxi3/article/details/83187840
里面就是以做OpenCV插件为例的
OpenCV第三方库下载地址:
https://download.csdn.net/download/lunweiwangxi3/10960604
我设置不了免费,穷人可评论发邮箱,免费传
在OpenCV插件库制作完成后,
在需要用到该插件的地方,打开xx. .Build.cs文件
在UBlueprintFunctionBPLibrary.cpp文件中,添加头文件
//opencv
#include "opencv2/core.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/imgproc.hpp"
#include "opencv2/videoio.hpp"
把OpenCV的Bin目录下的文件,全部拷贝到项目> Binaries>Wn64目录下:
修改SaveRenderTargetToFile函数中的代码如下所示:
bool UBlueprintFunctionBPLibrary::SaveRenderTargetToFile(UTextureRenderTarget2D* rt, const FString& fileDestination)
{
FTextureRenderTargetResource* rtResource = rt->GameThread_GetRenderTargetResource();
FReadSurfaceDataFlags readPixelFlags(RCM_UNorm);
TArray outBMP;
outBMP.AddUninitialized(rt->GetSurfaceWidth() * rt->GetSurfaceHeight());
rtResource->ReadPixels(outBMP, readPixelFlags);
cv::Mat viewTmp = cv::Mat(rt->GetSurfaceHeight(), rt->GetSurfaceWidth(), CV_8UC4);
for (int y = 0; y < rt->GetSurfaceHeight(); y++)
{
for (int x = 0; x < rt->GetSurfaceWidth(); x++)
{
int i = x + (y * rt->GetSurfaceWidth());
viewTmp.at(y, x) = cv::Vec4b(outBMP[i].B, outBMP[i].G, outBMP[i].R, outBMP[i].A);
}
}
return true;
}
然后安装一个VS吊炸天的插件叫ImageWatch,操作如下
安装,期间要把VS软件关闭后才能继续。安装好,重新打开项目
在SaveRenderTargetToFile函数的最后一行( return true;)上下断点
运行VS,UE4项目,在运行SaveRenderTargetToFile时会暂停到断点处。
点击 视图>其他窗口>ImageWatch
RGBA四通道的值全都有!调试神器啊,仅限C++拥有。
注意:只能看到函数里的局部cv::Mat变量,只能在C++项目中有效,C#项目中显示不出。
结果显示Alpha值莫名奇妙的变成了0.罪魁祸首?我们猜想测试下
强制把Alpha通道设置成255试试呢,说干就干,
把这行代码:
viewTmp.at
改成:
viewTmp.at
老地方下断点,运行vs,ue4,运行SaveRenderTargetToFile函数,
然后将函数OpenCV调试图(左)和引擎效果图(右)作对比:
完美解决!
既然是改Alpha通道的值,那么,OpenCV作为我们的可视化调试工具的任务也圆满完成了,兔死狗烹,把OpenCV模块卸载掉,代码删掉。
在SaveRenderTargetToFile函数中添加代码:
for (FColor& color : outBMP)
color.A = 255;
最终如下图所示:
bool UBlueprintFunctionBPLibrary::SaveRenderTargetToFile(UTextureRenderTarget2D* rt, const FString& fileDestination)
{
FTextureRenderTargetResource* rtResource = rt->GameThread_GetRenderTargetResource();
FReadSurfaceDataFlags readPixelFlags(RCM_UNorm);
TArray outBMP;
outBMP.AddUninitialized(rt->GetSurfaceWidth() * rt->GetSurfaceHeight());
rtResource->ReadPixels(outBMP, readPixelFlags);
for (FColor& color : outBMP)
color.A = 255;
FIntPoint destSize(rt->GetSurfaceWidth(), rt->GetSurfaceHeight());
TArray CompressedBitmap;
FImageUtils::CompressImageArray(destSize.X, destSize.Y, outBMP, CompressedBitmap);
bool imageSavedOk = FFileHelper::SaveArrayToFile(CompressedBitmap, *fileDestination);
return imageSavedOk;
return true;
}
最后我们运行下保存图片,效果如下: