[Day 24] 字形渲染(Text Rendering) - 渲染文字

今日目标

  • 在视窗内渲染出"Hello, world!"

DrawText

void DrawText(const char* text, V2f pos, float sz, Color c)

这是渲染文字API的宣告,要渲染的每个字母都可以视为一小个矩形,与DrawRectangle不同的是不处理旋转的部分(会很麻烦...再加上2D Platformer大多不会需要旋转),第二个不同是**暂且(因为时间紧迫,想快点完成,直接用raylib的作法了)**这些文字的原点会是在左上角,然後因为正投影(Projection Matrix)我是反过来的,原点在左上角,所以找出一个字母的四个顶点座标也是反的

// 以下座标事实上划出都会翻转Y轴180
V2f p = { 
	pos.x + text_xoff + (CONTEXT.RenderState.default_font.chars[index].xoffset * sz),
	pos.y + (float)text_yoff + (CONTEXT.RenderState.default_font.chars[index].yoffset * sz),
};
// 右上角
V2f top_right = { p.x + CONTEXT.RenderState.default_font.chars[index].rec.w * sz, p.y + CONTEXT.RenderState.default_font.chars[index].rec.h * sz };
// 左上角
V2f top_left = { .x = p.x, .y = p.y + CONTEXT.RenderState.default_font.chars[index].rec.h * sz};
// 右下角
V2f bottom_right = { .x = p.x + CONTEXT.RenderState.default_font.chars[index].rec.w * sz, .y = p.y };
// 左下角
V2f bottom_left = { .x = p.x, .y = p.y };

再访2D批次渲染

昨天我把ASCII Code画在一张图片上,作为图集(Font Atlas)。

接着,需要对之前写的批次渲染器做一些改造,之前主要是对不同的顶点座标做处理,这次需要加入对不同贴图的处理,之後也会用到不同的图集,也是用这种方法。

首先看一下改造过後的DrawCall结构

typedef struct DrawCall {
    size_t vertices_count;
    unsigned int texture_id;
} DrawCall;

多了用贴图的ID作为依据,在每次要把顶点塞入Buffer的时候,检查当前的texture id是不是不同的,如果是不同的,依情况利用新一个Draw Call专门处理这些顶点。

...
    // check texture id from current draw call and vertex buffer
    if (CONTEXT.RenderState.draw_calls[CONTEXT.RenderState.draw_calls_count - 1].texture_id != texture->id) {

        // check is there any shapes are waiting to draw
        if (CONTEXT.RenderState.draw_calls[CONTEXT.RenderState.draw_calls_count - 1].vertices_count > 0) {
            CONTEXT.RenderState.draw_calls_count += 1;
        }

        if (CONTEXT.RenderState.draw_calls_count >= MAX_DRAW_CALL_PER_FRAME) {
            RenderCurrentBatch();
        }

        CONTEXT.RenderState.draw_calls[CONTEXT.RenderState.draw_calls_count - 1].texture_id = texture->id;
        CONTEXT.RenderState.draw_calls[CONTEXT.RenderState.draw_calls_count - 1].vertices_count = 0;
    }
...

会先去检查当前的Draw Call纪录是不是已有顶点记录在内,若有则会确定用另一个Drall Call纪录要画的顶点。

再来,PushVertexData多了一个Rect的参数给贴图,根据Rect求出要渲染出的字母是在图片中的哪一块区域,会有四个贴图座标,然後会每个座标分量会是范围(0, 1),因为贴图在座标是在[0, 1]之间。

参考

最後,今天的成果也上传到github罗,虽然没人会点进去看就是了O_>O


<<:  # Day 25 Heterogeneous Memory Management (HMM) (Summary)

>>:  Day19 不使用JSX开发React的方式

最短路径问题 (7)

10.9 Chan’s APSP 演算法 我们今天来介绍一个 O(n^3 / log n) 时间复杂...

Azure 管理资源方式比较差异

Azure 管理资源方式比较差异 首先对 Azure 管理资源的方式有个概念,好方便之後介绍 Azu...

Day 20 Flask Session

上一篇讲完了 Cookie,那 Session 又是什麽? Session Session 就像是麦...

从零开始学游戏开发:建立得分条 Part1.开始

这是 Roblox 从零开始系列,使用者介面章节的第一个单元,你将开始学习如何设计出一个精美的得分条...

Windows 10 环境 MINGW64 找不到 PGP Keys 的问题 (Gpg4win)

How to reproduction 在 Windows 10 环境安装 Gpg4win 使用 K...