【UE】纹理绘制_数组转纹理_在材质中使用纹理实现数组的功能_纹理读取和导出_热力图的实现

本文介绍了如何将数据数组转换为不同精度的纹理,如B8G8R8A8和A32B32G32R32F格式,以及如何在材质中设置和操作纹理,包括导出、读取和编辑器中的设置。提到纹理精度、导出误差以及它们在游戏开发中的辅助用途。
摘要由CSDN通过智能技术生成

需求

数据/数组转成纹理,在材质中进行操作
纹理的导出、读取

纹理创建

最基础的模板

UTexture2D* U类名::方法名(int32 SizeX, int32 SizeY, const TArray<FColor>& Val)
{
	if (Val.Num() == 0)return nullptr;
	if (Val.Num() != SizeX * SizeY)return nullptr;
	UTexture2D* ResTexture2D = UTexture2D::CreateTransient(SizeX, SizeY, PF_B8G8R8A8);
	uint8* Pixels = new uint8[SizeX * SizeY * 4];
	for (int i = 0; i < SizeX * SizeY; i++)
	{
		Pixels[4 * i] = Val[i].B;
		Pixels[4 * i + 1] = Val[i].G;
		Pixels[4 * i + 2] = Val[i].R;
		Pixels[4 * i + 3] = Val[i].A;
	}
	void* TextureData = ResTexture2D->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
	FMemory::Memcpy(TextureData, Pixels, sizeof(uint8) * SizeX * SizeY * 4);
	ResTexture2D->GetPlatformData()->Mips[0].BulkData.Unlock();
	ResTexture2D->UpdateResource();
	return ResTexture2D;
}

返回一张BGRA8的纹理,可以设置成材质参数使用
在这里插入图片描述

提高精度

如果对数据精度要求较高,8位可能有较大误差,可以使用其他纹理格式。
需要注意纹理中数据的类型需要对应变化,我列出以下常用的几个
PF_B8G8R8A8使用uint8或FColor
PF_FloatRGBA使用FFloat16
PF_A32B32G32R32F使用FLinearColor
以下为创建一个PF_A32B32G32R32F纹理的代码

UTexture2D* U类名::方法名(int32 SizeX, int32 SizeY, const TArray<FLinearColor>& Val)
{
	if (Val.Num() == 0)return nullptr;
	if (Val.Num() != SizeX * SizeY)return nullptr;
	UTexture2D* ResTexture2D = UTexture2D::CreateTransient(SizeX, SizeY, PF_A32B32G32R32F);
	FLinearColor* Pixels = new FLinearColor[SizeX * SizeY];
	for (int i = 0; i < SizeX * SizeY; i++) Pixels[i] = Val[i];
	void* TextureData = ResTexture2D->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE);
	FMemory::Memcpy(TextureData, Pixels, sizeof(FLinearColor) * SizeX * SizeY);
	ResTexture2D->GetPlatformData()->Mips[0].BulkData.Unlock();
	ResTexture2D->UpdateResource();
	return ResTexture2D;
}

对纹理的设置

将创建的纹理暴露给外部,双击打开
需要注意的是以下参数
在这里插入图片描述
在这里插入图片描述
sRGB为色彩矫正,需要数据精确时应关闭,需要纹理导出或读取时应关闭
平铺法默认为包裹,纹理边缘UV0和1的地方会插值,建议设置成限制
过滤器设置为最近,类似像素化,适合作为纹理中的数组使用
在这里插入图片描述
过滤器设置为双线性,纹理会平滑插值,效果比顶点的三角插值好很多
在这里插入图片描述
其他参数为读取和导出相关参数
如果想要导出或读取纹理,需要以下设置
mip生成格式->无mip贴图
压缩设置->向量置换贴图
sRGB->Fasle
其中mip格式不能在Runtime设置,打包时会报错,需注意

所有设置可在纹理编辑器中更改,也可在代码中设置

	//样式相关
	ResTexture2D->AddressX = TextureAddress::TA_Clamp;
	ResTexture2D->AddressY = TextureAddress::TA_Clamp;
	ResTexture2D->Filter=TF_Bilinear;
	ResTexture2D->SRGB = false;
	//读取和导出相关
	ResTexture2D->CompressionSettings = TC_VectorDisplacementmap;
#if WITH_EDITOR
	//仅编辑器
	ResTexture2D->MipGenSettings = TMGS_NoMipmaps;
#endif

纹理读取

将纹理设置为可读取的格式,结束后修改回来
由于mip无法在打包后设置,且纹理由数组生成,直接读取数组中的值更便利
不建议使用,在编辑器作为测试函数即可

FColor U类名::方法名(UTexture2D* TextureToRead, int I, int J)
{
	FColor ResCol;
#if WITH_EDITOR
	//Only Read PF_B8G8R8A8
	if (TextureToRead->GetPixelFormat() != PF_B8G8R8A8) return ResCol;
	//Index Error
	if (I >= TextureToRead->GetSizeX() || J >= TextureToRead->GetSizeY())return ResCol;

	//Remember Some Settings Then Modify       To Prevent LockReadOnly() Return Null
	const TextureCompressionSettings OldCompressionSettings = TextureToRead->CompressionSettings;
	const TextureMipGenSettings OldMipGenSettings = TextureToRead->MipGenSettings;
	const bool OldSRGB = TextureToRead->SRGB;
	
	TextureToRead->CompressionSettings = TC_VectorDisplacementmap;
	TextureToRead->MipGenSettings = TMGS_NoMipmaps;
	TextureToRead->SRGB = false;
	TextureToRead->UpdateResource();

	//Get FColor
	const FColor* ImageData = (const FColor*)(TextureToRead->GetPlatformData()->Mips[0].BulkData.LockReadOnly());
	ResCol = ImageData[I * TextureToRead->GetSizeX() + J];

	//Reset Settings
	TextureToRead->GetPlatformData()->Mips[0].BulkData.Unlock();
	TextureToRead->CompressionSettings = OldCompressionSettings;
	TextureToRead->MipGenSettings = OldMipGenSettings;
	TextureToRead->SRGB = OldSRGB;
	TextureToRead->UpdateResource();
#endif

	//Return
	return ResCol;
}
}

纹理导出

数据导出为纹理
将颜色数组压缩成缓存,保存为文件
格式为RGBA8,导出时压缩一次,png导入纹理又压缩一次,有一定误差
建议作为预览/测试纹理,需要精度请直接存储数据,运行时用数据生成纹理

bool U类名::方法名(int32 SizeX, int32 SizeY, const TArray<FColor>& Val, const FString Path)
{
	//Quantity Mismatch
	if (Val.Num() != SizeX * SizeY)return false;

	//Compress To Bytes
	TArray<uint8> ResFileBytes;
	FImageUtils::CompressImageArray(SizeX, SizeY, Val, ResFileBytes);

	//Create
	return FFileHelper::SaveArrayToFile(ResFileBytes, *Path);
}

kismet中的纹理相关的函数,都对Texture2D->sourse中的参数进行了判断,CreateTransient出的纹理无法通过。
且纹理大小和奇偶有一定限制
暂时没有更好的导出方法

在材质中的使用

将实际数据、范围数组、对应颜色转为纹理
使用custom节点写个映射,制作成热力图
在这里插入图片描述
custom中的HLSL代码如下在这里插入图片描述

其他

如果需要精度,所有流程以数据驱动。
对纹理的导出、读取存在限制和误差,仅作为辅助工具使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值