2dx支持几种格式的文字,如下:
enum class LabelType {
TTF,
BMFONT,
CHARMAP,
STRING_TEXTURE
};
今天看了TTF字体渲染的流程,总结如下:
1、对文本中的每个字符遍历,取得该字符的字符编码(unicode码);
2、通过该编码用取得文字对应的bitmap数据:
void renderCharAt(unsigned char *dest,int posX, int posY, unsigned char* bitmap,long bitmapWidth,long bitmapHeight); //对该字符的rect区域挨个像素的图设置内容,效率太低了吧,还能优化么?
3、通过这些bitmap数据,生成一个textrue2d对象(2dx纹理对象):
bool FontAtlas::prepareLetterDefinitions(const std::u16string& utf16Text)
{
if (_fontFreeType == nullptr)
{
return false;
}
std::unordered_map<unsigned short, unsigned short> codeMapOfNewChar;
findNewCharacters(utf16Text, codeMapOfNewChar);
if (codeMapOfNewChar.empty())
{
return false;
}
int adjustForDistanceMap = _letterPadding / 2;
int adjustForExtend = _letterEdgeExtend / 2;
long bitmapWidth;
long bitmapHeight;
Rect tempRect;
FontLetterDefinition tempDef;
auto scaleFactor = CC_CONTENT_SCALE_FACTOR();
auto pixelFormat = _fontFreeType->getOutlineSize() > 0 ? Texture2D::PixelFormat::AI88 : Texture2D::PixelFormat::A8;
float startY = _currentPageOrigY;
for (auto&& it : codeMapOfNewChar)
{
... //内容略,可以去2dx看源码
}
unsigned char *data = nullptr;
if (pixelFormat == Texture2D::PixelFormat::AI88)
{
data = _currentPageData + CacheTextureWidth * (int)startY * 2;
}
else
{
data = _currentPageData + CacheTextureWidth * (int)startY;
}
_atlasTextures[_currentPage]->updateWithData(data, 0, startY, CacheTextureWidth, _currentPageOrigY - startY + _lineHeight); //在这之前已经生成了一张大的空纹理对象,这个地方就用有效的数据去更新大纹理的内容
return true;
}
4、以上的步骤已经取得需要渲染的纹理了,2dx采用批量渲染的方式去渲染文字的:
void Label::onDraw(const Mat4& transform, bool transformUpdated)
{
...
for (auto&& batchNode : _batchNodes)
{
batchNode->getTextureAtlas()->drawQuads();
}
}
5、这样渲染的过程和图片等流程一样了,加到渲染队列,选择shader,提交纹理坐标,颜色。
疑问:
1、distance field(_useDistanceField控制开关)对边缘平滑处理是怎么做的??
2、描边是怎么实现的?
3、字体渲染怎么优化drawcall?