IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 游戏开发 -> 游戏引擎Flax Engine源码分析(九)渲染 -> 正文阅读

[游戏开发]游戏引擎Flax Engine源码分析(九)渲染

?2021SC@SDUSC


一、概述

? ? ? ? 这篇文章我们主要分析一下文本渲染,也就是DrawText()函数及其几个重载。仍然是2D渲染的部分、

二、分析

? ? ? ? DrawText有一下几个重载:

static void DrawText(Font* font, const StringView& text, const Color& color, const Vector2& location, MaterialBase* customMaterial = nullptr);
static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, const Vector2& location, MaterialBase* customMaterial = nullptr);
static void DrawText(Font* font, const StringView& text, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);
static void DrawText(Font* font, const StringView& text, API_PARAM(Ref) const TextRange& textRange, const Color& color, API_PARAM(Ref) const TextLayoutOptions& layout, MaterialBase* customMaterial = nullptr);

? ? ? ? 第三第四个重载用于绘制带格式的文本。

? ? ? ? 我们简单分析一下函数的几个参数:

font: 使用的字体

text: 被渲染的文本

color: 使用的颜色

location: 二维向量,表示文本的位置

customMaterial:用于字体字符呈现的自定义材质。它必须包含用于取样字体纹理的名为Font的纹理参数

textRange:?输入文本范围(输入文本参数的子字符串范围)

layout:文本布局属性

? ? ? ? ?下面来看具体的函数实现:


?????????第一个重载(没有参数textRange和layout):

????????检车是否需要进行渲染操作

if (font == nullptr ||
        text.IsEmpty() ||
        (customMaterial && (!customMaterial->IsReady() || !customMaterial->IsGUI())))
        return;

? ? ? ? 临时数据:

    uint32 fontAtlasIndex = 0;
    FontTextureAtlas* fontAtlas = nullptr;
    Vector2 invAtlasSize = Vector2::One;
    FontCharacterEntry previous;
    int32 kerning;
    float scale = 1.0f / FontManager::FontScale;

? ? ? ? 接下来渲染所有字符:

? ? ? ? 首先判断了自定义材质(customMaterial)是否为空,根据情况进行不同的2D渲染调用。(2D渲染调用的类型在之前的博客中已提及)

    FontCharacterEntry entry;
    Render2DDrawCall drawCall;
    if (customMaterial)
    {
        drawCall.Type = DrawCallType::DrawCharMaterial;
        drawCall.AsChar.Mat = customMaterial;
    }
    else
    {
        drawCall.Type = DrawCallType::DrawChar;
        drawCall.AsChar.Mat = nullptr;
    }
    Vector2 pointer = location;

? ? ? ? 然后对每一个字符进行渲染:

for (int32 currentIndex = 0; currentIndex <= text.Length(); currentIndex++)

????????缓存当前字符

const Char currentChar = text[currentIndex];

? ? ? ? 检查是否是换行符,若不是:

  • ????????获取字符条目
  • ????????检查是否需要选择/更改字体图集(因为相同字体的字符可能位于不同的地图集中),获取包含当前字符的纹理图谱。
  • ????????检查字符是否是空格,调整字距,省略空格字符,计算字符大小和地图坐标,添加绘图调用。
  • ? ? ? ? 移动。

? ? ? ? 若是换行符:

? ? ? ? 仅执行移动操作。

if (currentChar != '\n')
        {
            font->GetCharacter(currentChar, entry);

            if (fontAtlas == nullptr || entry.TextureIndex != fontAtlasIndex)
            {
          
                fontAtlasIndex = entry.TextureIndex;
                fontAtlas = FontManager::GetAtlas(fontAtlasIndex);
                if (fontAtlas)
                {
                    fontAtlas->EnsureTextureCreated();
                    drawCall.AsChar.Tex = fontAtlas->GetTexture();
                    invAtlasSize = 1.0f / fontAtlas->GetSize();
                }
                else
                {
                    drawCall.AsChar.Tex = nullptr;
                    invAtlasSize = 1.0f;
                }
            }

            const bool isWhitespace = StringUtils::IsWhitespace(currentChar);

            if (!isWhitespace && previous.IsValid)
            {
                kerning = font->GetKerning(previous.Character, entry.Character);
            }
            else
            {
                kerning = 0;
            }
            pointer.X += kerning * scale;
            previous = entry;

            
            if (!isWhitespace)
            {
                
                const float x = pointer.X + entry.OffsetX * scale;
                const float y = pointer.Y + (font->GetHeight() + font->GetDescender() - entry.OffsetY) * scale;

                Rectangle charRect(x, y, entry.UVSize.X * scale, entry.UVSize.Y * scale);

                Vector2 upperLeftUV = entry.UV * invAtlasSize;
                Vector2 rightBottomUV = (entry.UV + entry.UVSize) * invAtlasSize;

             
                drawCall.StartIB = IBIndex;
                drawCall.CountIB = 6;
                DrawCalls.Add(drawCall);
                WriteRect(charRect, color, upperLeftUV, rightBottomUV);
            }

           
            pointer.X += entry.AdvanceX * scale;
        }

? ? ? ? 第二个重载(带有参数textRange):

 DrawText(font, StringView(text.Get() + textRange.StartIndex, textRange.Length()), color, location, customMaterial);

? ? ? ? StringView类型将静态文本视图表示为 utf-16字符序列。?可见此处仅是将text和textRange重新组装后再次调用之前的文本渲染函数。


? ? ? ? 第三个重载(带有参数layout):

? ? ? ? 大体上与第一个重载一样,这里仅分析不同之处:

? ? ? ? 首先是在准备阶段,除了判断是否需要进行渲染和声明临时数据外,对文本进行处理以获取行:

    Lines.Clear();
    font->ProcessText(text, Lines, layout);

? ? ? ? 注意后面对每个字符渲染的部分在这里做了一些改变,变成了两层循环,及将之前的获取每个字符的for语句改成如下结构:

for (int32 lineIndex = 0; lineIndex < Lines.Count(); lineIndex++)
    {
        const FontLineCache& line = Lines[lineIndex];
        Vector2 pointer = line.Location;
        for (int32 charIndex = line.FirstCharIndex; charIndex <= line.LastCharIndex; charIndex++)

? ? ? ? 即首先对上面获取的行进行一次位置的处理,在对每一行的每一个字符进行渲染,以这样的方式完成布局。?


? ? ? ? 第四个重载(带有layout和textRange):?

? ? ? ? 这里就不再赘述,textRange与text参数组合后调用第三个重载方法即可。


? ? ? ? 本次的分析就到这里,感谢。?

  游戏开发 最新文章
6、英飞凌-AURIX-TC3XX: PWM实验之使用 GT
泛型自动装箱
CubeMax添加Rtthread操作系统 组件STM32F10
python多线程编程:如何优雅地关闭线程
数据类型隐式转换导致的阻塞
WebAPi实现多文件上传,并附带参数
from origin ‘null‘ has been blocked by
UE4 蓝图调用C++函数(附带项目工程)
Unity学习笔记(一)结构体的简单理解与应用
【Memory As a Programming Concept in C a
上一篇文章      下一篇文章      查看所有文章
加:2021-11-23 12:41:48  更:2021-11-23 12:41:56 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/27 22:32:30-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码