UE4 如何将TextureRenderTarget2D保存为本地图片

7 篇文章 3 订阅

     


昨日不可追, 今日尤可为.勤奋,炽诚,不忘初心


 

           UE4 如何将TextureRenderTarget2D保存为本地图片

如果想要将材质保存为本地Png,请点这里:

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<FColor> outBMP;
	outBMP.AddUninitialized(rt->GetSurfaceWidth() * rt->GetSurfaceHeight());
	rtResource->ReadPixels(outBMP, readPixelFlags);

	FIntPoint destSize(rt->GetSurfaceWidth(), rt->GetSurfaceHeight());
	TArray<uint8> 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<FColor> 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<cv::Vec4b>(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<cv::Vec4b>(y, x) = cv::Vec4b(outBMP[i].B, outBMP[i].G, outBMP[i].R, outBMP[i].A);
改成:
viewTmp.at<cv::Vec4b>(y, x) = cv::Vec4b(outBMP[i].B, outBMP[i].G, outBMP[i].R, 255);
老地方下断点,运行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<FColor> 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<uint8> CompressedBitmap;
	FImageUtils::CompressImageArray(destSize.X, destSize.Y, outBMP, CompressedBitmap);
	bool imageSavedOk = FFileHelper::SaveArrayToFile(CompressedBitmap, *fileDestination);
	return imageSavedOk;

	return true;
}

最后我们运行下保存图片,效果如下:

Perfect!
不要将就,只愿完美。
 

 

 

 

 

 

  • 32
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 16
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值