制作游戏UI的时候经常会有界面上的自定义样式的文本需求,在2d引擎中我们都会以
这样的图片资源来进行动态数字文本的显示,而固定的属性名称等内容则使用指定贴图代替,现在我们就在ue4中实现这样的渲染
注意:
1.本实例只实现了横向文本渲染,没有多行文本处理,如有需要可以在uv采样上添加Y轴的起始及偏移自行扩展
2.理论上采样贴图size设置的够大能支持无限字符长度采样,但是受限于引擎或者性能影响,建议还是根据需求合理扩展使用
8-22更新:
将4个通道都用起来,兼容更多的字符节约开销
1.修改uv存储贴图的数据写入逻辑,将起始uv分别写入4个通道(如果是做多行的情况,这里就需要修改为分别写入两个通道,每个像素填入两个字符)
UFUNCTION(BlueprintCallable, Category = "AceImageText")
static void UpdateDynImage(UTexture2DDynamic* tex, TArray<float> values) {
if (!tex) {
return;
}
FTexture2DDynamicResource* dynRes = static_cast<FTexture2DDynamicResource*>(tex->Resource);
TArray<FColor> src;
src.Init(FColor(0, 0, 0), tex->SizeX);
if (values.Num() > 0) {
int len = values.Num() / 4;
if (values.Num() - len * 4 > 0) {
len = len + 1;
}
for (size_t i = 0; i < len; i++)
{
if (i >= src.Num())break;
int index = i * 4;
float r, g, b, a;
r = values[index];
if (index + 1 < values.Num()) {
g = values[index + 1];
}
if (index + 2 < values.Num()) {
b = values[index + 2];
}
if (index + 3 < values.Num()) {
a = values[index + 3];
}
FLinearColor c(r, g, b, a);
src[i] = (c.ToFColor(false));
}
}
/*
更新实现参照
UTexture2D::UpdateTextureRegions();
*/
ENQUEUE_RENDER_COMMAND(FWriteRawDataToDyn)(
[dynRes, src](FRHICommandListImmediate& FRHICommandList) {
check(IsInRenderingThread());
if (dynRes) {
FRHITexture2D* rhi = dynRes->GetTexture2DRHI();
uint32 d = 0;
FColor* data = reinterpret_cast<FColor*>(RHILockTexture2D(rhi, 0, RLM_WriteOnly, d, false));
FMemory::Memcpy(data, src.GetData(), sizeof(FColor) * src.Num());
RHIUnlockTexture2D(rhi, 0, false);
}
}
);
}
2.修改材质采样部分,使用4个通道数据
3.修改组件蓝图兼容的最大字符数计算
材质
材质中包含动态赋予属性:
fontTexSampleScale 文字贴图的每个字符所占的uv宽度 ,我们采样的时候根据这个数据来计算出采样uv插值
NumSize 在实际渲染中每个字符在渲染网格或Image上所占用的uv宽度
uvOffsetSampleSize 每个字符的起始uv数据在动态uv偏移贴图上所对应的uv宽度
FontSampleTex 根据当前文本数据动态刷新的uv偏移贴图,采样获取每个文本单元的起始uv
NumTex 需要渲染的文本字符集贴图,因制作的时候是出于需要动态掉血数值绘制,所以取名NumTex
UV偏移贴图
创建
贴图高度永远为1,因为我们只考虑横向采样
参数width:贴图的宽度,代表了可以采样的最大文本长度
UFUNCTION(BlueprintCallable, Category = "AceImageText")
static UTexture2DDynamic* CreateDynImage(int width) {
UTexture2DDynamic* tex= UTexture2DDynamic::Create(width, 1);
tex->SRGB = false;
tex->SamplerAddressMode = AM_Clamp;
tex->CompressionSettings = TC_HDR;
tex->Filter = TF_Nearest;
tex->MipGenSettings = TMGS_NoMipmaps;
tex->UpdateResource();
TArray<FColor> src;
src.Init(FColor(0, 0, 0), width);
for (size_t i = 0; i < width; i++)
{
auto v = (i % 2)*255;
FColor c(v, v, v);
src[i] = c;
}
FTexture2DDynamicResource* dynRes= static_cast<FTexture2DDynamicResource*>(tex->Resource);
ENQUEUE_RENDER_COMMAND(FWriteRawDataToDyn)(
[dynRes, src](FRHICommandListImmediate& FRHICommandList) {
check(IsInRenderingThread());
FRHITexture2D* rhi= dynRes->GetTexture2DRHI();
uint32 d = 0;
FColor* data= reinterpret_cast<FColor*>( RHILockTexture2D(rhi, 0, RLM_WriteOnly, d,false));
FMemory::Memcpy(data, src.GetData(), sizeof(FColor) * src.Num());
RHIUnlockTexture2D(rhi, 0, false);
}
);
return tex;
}
更新
参数 tex:uv偏移的动态贴图对象,有上面的创建方法创建后用户进行存档,更新时传入
参数values:字符串的uv偏移值数组,长度为字符串的长度
UFUNCTION(BlueprintCallable, Category = "AceImageText")
static void UpdateDynImage(UTexture2DDynamic* tex, TArray<float> values) {
if (!tex) {
return;
}
FTexture2DDynamicResource* dynRes = static_cast<FTexture2DDynamicResource*>(tex->Resource);
TArray<FColor> src;
src.Init(FColor(0, 0, 0), tex->SizeX);
for (size_t i = 0; i < values.Num(); i++)
{
if (i >= src.Num())break;
FLinearColor c(values[i], values[i], values[i]);
src[i]=(c.ToFColor(false));
}
/*
更新实现参照
UTexture2D::UpdateTextureRegions();
*/
ENQUEUE_RENDER_COMMAND(FWriteRawDataToDyn)(
[dynRes, src](FRHICommandListImmediate& FRHICommandList) {
check(IsInRenderingThread());
FRHITexture2D* rhi = dynRes->GetTexture2DRHI();
uint32 d = 0;
FColor* data = reinterpret_cast<FColor*>(RHILockTexture2D(rhi, 0, RLM_WriteOnly, d, false));
FMemory::Memcpy(data, src.GetData(), sizeof(FColor) * src.Num());
RHIUnlockTexture2D(rhi, 0, false);
}
);
}
对齐方式枚举
组件蓝图
变量
dynFontMat 动态渲染材质
uvmap 字符集的起始uv偏移映射表
fontSize 渲染的字符大小,起始就是image对象的单元大小,每个字符这里实现都是正方形
text 当前渲染的文本
dynFontUVTex 动态uv偏移贴图的缓存
maxLength 最大字符长度,超出长度的字符不会做渲染
align 横向对齐方式,参照对齐方式枚举,纵向始终居中
fontImage UMG组件,用于最终文本的渲染
构造
初始化布局
初始化渲染
设置文本渲染