引言
我最近在用vulkan来显示图片,需要用到这个库
初次尝试
通过git下载了std_image的库
我使用cmake来配置项目,不过这个库并没有使用cmake导入
首先把stb_image.h和stb_image.c放到项目里
然后在man文件的最上面
#define STB_IMAGE_IMPLEMENTATION
因为如果在其他cpp文件定义这个宏可能会导致重定义啥的错误
然后在需要的地方导入刚才拷贝的stb_image.h即可
注意要点
1、cmake需要刷新,然后obj文件也可以手动删一下(非必要)
2、出现重定义错误就按上面步骤说的做应该就好了
3、stb_image_write这个头文件我在我的cpp中引用会报错,在我的头文件中引用才行
资源中文路径
我们的图片是中文名,stbi_load默认使用的是fopen
所以我们查看stb_image.c可以看到其实这里是调用的stbi_load_from_file
fopen使用的是char*,而_wfopen使用的是wchar_t*
所以我们直接调用stbi_load_from_file然后使用_wfopen就可以加载中文路径了
其中注释部分是char*转换wchar_t*没测试过这样行不行,我是直接传了一个wchar_t*是可以的。
渲染文字
使用stb_truetype这个头文件
与之对应的初始化宏是
#define STB_TRUETYPE_IMPLEMENTATION
首先需要加载字体文件
stbtt_fontinfo* MTurbo::CreateStbFont(const wchar_t *ktxname) {
/* 加载字体(.ttf)文件 */
long int size = 0;
unsigned char *fontBuffer = NULL;
FILE *fontFile = _wfopen(ktxname, L"rb");
if (fontFile == NULL)
{
throw std::runtime_error("failed to load font!");
}
fseek(fontFile, 0, SEEK_END); /* 设置文件指针到文件尾,基于文件尾偏移0字节 */
size = ftell(fontFile); /* 获取文件大小(文件尾 - 文件头 单位:字节) */
fseek(fontFile, 0, SEEK_SET); /* 重新设置文件指针到文件头 */
fontBuffer = (unsigned char *)calloc(size, sizeof(unsigned char));
fread(fontBuffer, size, 1, fontFile);
fclose(fontFile);
/* 初始化字体 */
auto info = new stbtt_fontinfo;
if (!stbtt_InitFont(info, fontBuffer, 0))
{
throw std::runtime_error("failed to load font! Init");
}
//free(fontBuffer);
return info;
}
其中ktxname是字体的路径,使用wchar_t表示支持中文路径
然后就是使用字体对文字生成图片,这里补充一些小知识
补充:unicode编码
0x54表示一个字母“T”,0x开头表示16进制数,0开头表示8进制数,可以在网上找在线十六进制转十进制数进行观察。
每个数字表示一个符号,c++的char不支持中文,因为无法表示太大的数字,wchar_t可以支持中文是因为能支持大数字,所以字符本质上就是数字。
unicode编码支持很多字符,包括各种语言。这里可以在网上找在线unicode转换
可以看到转换出来的是类似
你好
\u4f60\u597d
\u就表示unicode,这里我们仅仅把4f60转换成十进制就是20320
补充:与vulkan对接
由于具体步骤太复杂,这里只说大概步骤
1、加载字体输出stbtt_fontinfo指针
2、使用字体指针和文字进行生成图片
3、创建buffer,把字体图片内存拷贝到缓冲区
4、销毁字体图片
5、通过width、height等数据创建Image
6、创建指令池command_pool,把文字图缓冲发给GPU
7、创建ImageView与Sampler采样器
这样shader就可以通过下面shader代码渲染文字了,跟渲染图片差不多
texture(sampler2D(myTexture, mySampler), inUV, 0)