Files
lity3d/Engine/Editor/bitmap_font.c
T
shuiyu1123 2d56cb3bc9 MiMoEngine ASM: x86-64 MASM汇编+C混合架构游戏引擎
核心热路径(数学/内存/字符串/性能分析)用MASM汇编(SSE/AVX2)
外围系统(窗口/渲染/ECS/音频/UI/脚本)用C语言
含自研编辑器、VisualScript积木编程、中文渲染(glyph_atlas)
2026-07-10 19:20:40 +08:00

304 lines
16 KiB
C

#include "bitmap_font.h"
#include <stdlib.h>
#include <string.h>
#include "../Core/logger.h"
static const uint8_t FONT_DATA[FONT_NUM_CHARS][FONT_CHAR_H] = {
{0},{0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00},
{0x00,0x66,0x66,0x66,0x24,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x6C,0x6C,0xFE,0x6C,0x6C,0xFE,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00},
{0x18,0x18,0x7C,0xC6,0xC2,0xC0,0x7C,0x06,0x06,0x86,0xC6,0x7C,0x18,0x18,0x00,0x00},
{0x00,0x00,0x00,0x00,0xC2,0xC6,0x0C,0x18,0x30,0x60,0xC6,0x86,0x00,0x00,0x00,0x00},
{0x00,0x00,0x38,0x6C,0x6C,0x38,0x76,0xDC,0xCC,0xCC,0xCC,0x76,0x00,0x00,0x00,0x00},
{0x00,0x30,0x30,0x30,0x70,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x0C,0x18,0x30,0x30,0x30,0x30,0x30,0x30,0x18,0x0C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x30,0x18,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x18,0x30,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x7E,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x02,0x06,0x0C,0x18,0x30,0x60,0xC0,0x80,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xDE,0xF6,0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00},
{0},{0},{0},
{0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x00,0x00,0x00,0x00},
{0},{0},
{0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00},
{0},{0},{0},{0},{0},{0},{0},{0},{0},
{0x00,0x00,0x7C,0xC6,0xC6,0xCE,0xDE,0xF6,0xE6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x18,0x38,0x78,0x18,0x18,0x18,0x18,0x18,0x18,0x7E,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0x06,0x0C,0x18,0x30,0x60,0xC0,0xC6,0xFE,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0x06,0x06,0x3C,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x0C,0x1C,0x3C,0x6C,0xCC,0xFE,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0xC0,0xC0,0xC0,0xFC,0x06,0x06,0x06,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x38,0x60,0xC0,0xC0,0xFC,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0xC6,0x06,0x06,0x0C,0x18,0x30,0x30,0x30,0x30,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7C,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xC6,0x7E,0x06,0x06,0x06,0x0C,0x78,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x30,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x0C,0x18,0x30,0x60,0xC0,0x60,0x30,0x18,0x0C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0x0C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x7C,0xC6,0xC6,0xDE,0xDE,0xDE,0xDC,0xC0,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x10,0x38,0x6C,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x66,0x66,0x66,0x66,0xFC,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xC0,0xC0,0xC2,0x66,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xF8,0x6C,0x66,0x66,0x66,0x66,0x66,0x66,0x6C,0xF8,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0x66,0x62,0x68,0x78,0x68,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3C,0x66,0xC2,0xC0,0xC0,0xDE,0xC6,0xC6,0x66,0x3A,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xFE,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x1E,0x0C,0x0C,0x0C,0x0C,0x0C,0xCC,0xCC,0xCC,0x78,0x00,0x00,0x00,0x00},
{0x00,0x00,0xE6,0x66,0x66,0x6C,0x78,0x78,0x6C,0x66,0x66,0xE6,0x00,0x00,0x00,0x00},
{0x00,0x00,0xF0,0x60,0x60,0x60,0x60,0x60,0x60,0x62,0x66,0xFE,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xD6,0xC6,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xE6,0xF6,0xFE,0xDE,0xCE,0xC6,0xC6,0xC6,0xC6,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x60,0x60,0x60,0x60,0xF0,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xD6,0xDE,0x7C,0x0C,0x0E,0x00,0x00},
{0x00,0x00,0xFC,0x66,0x66,0x66,0x7C,0x6C,0x66,0x66,0x66,0xE6,0x00,0x00,0x00,0x00},
{0x00,0x00,0x7C,0xC6,0xC6,0x60,0x38,0x0C,0x06,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x7C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0xC6,0x6C,0x38,0x10,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xC6,0xC6,0xC6,0xD6,0xD6,0xD6,0xFE,0xEE,0x6C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xC6,0x6C,0x7C,0x38,0x38,0x7C,0x6C,0xC6,0xC6,0x00,0x00,0x00,0x00},
{0x00,0x00,0xC6,0xC6,0xC6,0x6C,0x38,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0xFE,0xC6,0x86,0x0C,0x18,0x30,0x60,0xC2,0xC6,0xFE,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x06,0x02,0x00,0x00,0x00,0x00},
{0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00},
{0x10,0x38,0x6C,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00},
};
static Shader* g_font_shader = NULL;
static ID3D11Buffer* g_font_vb = NULL;
static ID3D11Buffer* g_font_ib = NULL;
static FontVert g_font_verts[FONT_MAX_QUADS * 4];
static uint32_t g_font_indices[FONT_MAX_QUADS * 6];
static int g_font_vi = 0;
static int g_font_ii = 0;
static void make_ortho(float* m, float sw, float sh) {
memset(m, 0, 64);
m[0] = 2.0f / sw;
m[5] = -2.0f / sh;
m[10] = 1.0f;
m[12] = -1.0f;
m[13] = 1.0f;
m[15] = 1.0f;
}
static void make_atlas(uint8_t* pixels, int w, int h) {
memset(pixels, 0, (size_t)w * h * 4);
int cols = w / FONT_CHAR_W;
for (int i = 0; i < FONT_NUM_CHARS; i++) {
int cx = (i % cols) * FONT_CHAR_W;
int cy = (i / cols) * FONT_CHAR_H;
for (int row = 0; row < FONT_CHAR_H; row++) {
uint8_t bits = FONT_DATA[i][row];
for (int col = 0; col < 8; col++) {
if (bits & (0x80 >> col)) {
int px = cx + col, py = cy + row;
int idx = (py * w + px) * 4;
pixels[idx] = 255; pixels[idx+1] = 255; pixels[idx+2] = 255; pixels[idx+3] = 255;
}
}
}
}
}
int bitmap_font_init(BitmapFont* f, ID3D11Device* dev) {
memset(f, 0, sizeof(*f));
int cols = 16;
f->atlas_w = cols * FONT_CHAR_W;
f->atlas_h = ((FONT_NUM_CHARS + cols - 1) / cols) * FONT_CHAR_H;
uint8_t* pixels = (uint8_t*)malloc((size_t)f->atlas_w * f->atlas_h * 4);
make_atlas(pixels, f->atlas_w, f->atlas_h);
D3D11_TEXTURE2D_DESC td = {0};
td.Width = (UINT)f->atlas_w; td.Height = (UINT)f->atlas_h;
td.MipLevels = 1; td.ArraySize = 1;
td.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
td.SampleDesc.Count = 1;
td.Usage = D3D11_USAGE_DEFAULT;
td.BindFlags = D3D11_BIND_SHADER_RESOURCE;
D3D11_SUBRESOURCE_DATA sd = {0};
sd.pSysMem = pixels; sd.SysMemPitch = (UINT)(f->atlas_w * 4);
HRESULT hr = dev->lpVtbl->CreateTexture2D(dev, &td, &sd, &f->texture);
free(pixels);
if (FAILED(hr)) return 0;
dev->lpVtbl->CreateShaderResourceView(dev, (ID3D11Resource*)f->texture, NULL, &f->srv);
f->shader = shader_create();
if (!shader_compile(f->shader, dev, NULL, NULL, 0, 0)) return 0;
g_font_shader = f->shader;
D3D11_BUFFER_DESC bd = {0};
bd.ByteWidth = FONT_MAX_QUADS * 4 * sizeof(FontVert);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
memset(g_font_verts, 0, sizeof(g_font_verts));
sd.pSysMem = g_font_verts;
dev->lpVtbl->CreateBuffer(dev, &bd, &sd, &g_font_vb);
bd.ByteWidth = FONT_MAX_QUADS * 6 * sizeof(uint32_t);
bd.Usage = D3D11_USAGE_DEFAULT;
bd.BindFlags = D3D11_BIND_INDEX_BUFFER;
memset(g_font_indices, 0, sizeof(g_font_indices));
sd.pSysMem = g_font_indices;
dev->lpVtbl->CreateBuffer(dev, &bd, &sd, &g_font_ib);
bd.ByteWidth = 256; bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
dev->lpVtbl->CreateBuffer(dev, &bd, NULL, &f->cb);
D3D11_BLEND_DESC bdesc = {0};
bdesc.RenderTarget[0].BlendEnable = TRUE;
bdesc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA;
bdesc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA;
bdesc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD;
bdesc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE;
bdesc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO;
bdesc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD;
dev->lpVtbl->CreateBlendState(dev, &bdesc, &f->blend);
D3D11_SAMPLER_DESC sdesc = {0};
sdesc.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT;
sdesc.AddressU = sdesc.AddressV = sdesc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP;
dev->lpVtbl->CreateSamplerState(dev, &sdesc, &f->sampler);
D3D11_DEPTH_STENCIL_DESC dsdesc = {0};
dsdesc.DepthEnable = FALSE;
dsdesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO;
dev->lpVtbl->CreateDepthStencilState(dev, &dsdesc, &f->ds_no_depth);
LOG_INFO("bitmap_font: initialized (%dx%d atlas)", f->atlas_w, f->atlas_h);
return 1;
}
void bitmap_font_destroy(BitmapFont* f) {
if (!f) return;
if (f->ds_no_depth) f->ds_no_depth->lpVtbl->Release(f->ds_no_depth);
if (f->sampler) f->sampler->lpVtbl->Release(f->sampler);
if (f->blend) f->blend->lpVtbl->Release(f->blend);
if (f->cb) f->cb->lpVtbl->Release(f->cb);
if (g_font_ib) { g_font_ib->lpVtbl->Release(g_font_ib); g_font_ib = NULL; }
if (g_font_vb) { g_font_vb->lpVtbl->Release(g_font_vb); g_font_vb = NULL; }
if (f->shader) { shader_destroy(f->shader); g_font_shader = NULL; }
if (f->srv) f->srv->lpVtbl->Release(f->srv);
if (f->texture) f->texture->lpVtbl->Release(f->texture);
memset(f, 0, sizeof(*f));
}
static void font_flush(ID3D11DeviceContext* ctx,
float screen_w, float screen_h, int num_idx) {
if (num_idx == 0) return;
float wvp[64];
make_ortho(wvp, screen_w, screen_h);
ID3D11Device* dev = NULL;
ctx->lpVtbl->GetDevice(ctx, &dev);
D3D11_RASTERIZER_DESC rdesc = {0};
rdesc.FillMode = D3D11_FILL_SOLID;
rdesc.CullMode = D3D11_CULL_NONE;
rdesc.ScissorEnable = FALSE;
ID3D11RasterizerState* rstate = NULL;
HRESULT hr = dev->lpVtbl->CreateRasterizerState(dev, &rdesc, &rstate);
if (rstate) {
ctx->lpVtbl->RSSetState(ctx, rstate);
rstate->lpVtbl->Release(rstate);
}
dev->lpVtbl->Release(dev);
shader_bind(g_font_shader, ctx);
shader_set_matrix(g_font_shader, ctx, wvp);
UINT stride = sizeof(FontVert), offset = 0;
ctx->lpVtbl->IASetVertexBuffers(ctx, 0, 1, &g_font_vb, &stride, &offset);
ctx->lpVtbl->IASetIndexBuffer(ctx, g_font_ib, DXGI_FORMAT_R32_UINT, 0);
ctx->lpVtbl->IASetPrimitiveTopology(ctx, D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
ctx->lpVtbl->DrawIndexed(ctx, (UINT)num_idx, 0, 0);
}
static void font_begin(void) { g_font_vi = 0; g_font_ii = 0; }
static void font_add_quad(BitmapFont* f, float x, float y, float w, float h,
float r, float g, float b, float a) {
if (g_font_vi + 4 > FONT_MAX_QUADS * 4) return;
float u0 = 0.19f, v0 = 0.01f, u1 = 0.24f, v1 = 0.15f;
int vi = g_font_vi;
g_font_verts[vi] = (FontVert){{x, y, 0},{0,0,-1},{u0,v0},{r,g,b,a}};
g_font_verts[vi+1] = (FontVert){{x+w, y, 0},{0,0,-1},{u1,v0},{r,g,b,a}};
g_font_verts[vi+2] = (FontVert){{x+w, y+h, 0},{0,0,-1},{u1,v1},{r,g,b,a}};
g_font_verts[vi+3] = (FontVert){{x, y+h, 0},{0,0,-1},{u0,v1},{r,g,b,a}};
uint32_t base = (uint32_t)vi;
g_font_indices[g_font_ii++] = base; g_font_indices[g_font_ii++] = base+1; g_font_indices[g_font_ii++] = base+2;
g_font_indices[g_font_ii++] = base; g_font_indices[g_font_ii++] = base+2; g_font_indices[g_font_ii++] = base+3;
g_font_vi += 4;
}
void bitmap_font_draw(BitmapFont* f, ID3D11DeviceContext* ctx,
const char* text, int x, int y,
float r, float g, float b, float a,
float screen_w, float screen_h) {
if (!text || !*text || !f->shader) return;
int len = (int)strlen(text);
if (len > FONT_MAX_QUADS) len = FONT_MAX_QUADS;
int cols = f->atlas_w / FONT_CHAR_W;
font_begin();
int cx = x;
for (int i = 0; i < len; i++) {
int ch = (unsigned char)text[i] - FONT_FIRST_CHAR;
if (ch < 0 || ch >= FONT_NUM_CHARS) ch = 0;
int col_idx = ch % cols;
int row_idx = ch / cols;
float u0 = (float)(col_idx * FONT_CHAR_W) / (float)f->atlas_w;
float v0 = (float)(row_idx * FONT_CHAR_H) / (float)f->atlas_h;
float u1 = (float)((col_idx + 1) * FONT_CHAR_W) / (float)f->atlas_w;
float v1 = (float)((row_idx + 1) * FONT_CHAR_H) / (float)f->atlas_h;
int vi = g_font_vi;
g_font_verts[vi] = (FontVert){{(float)cx,(float)y,0},{0,0,-1},{u0,v0},{r,g,b,a}};
g_font_verts[vi+1] = (FontVert){{(float)cx+FONT_CHAR_W,(float)y,0},{0,0,-1},{u1,v0},{r,g,b,a}};
g_font_verts[vi+2] = (FontVert){{(float)cx+FONT_CHAR_W,(float)y+FONT_CHAR_H,0},{0,0,-1},{u1,v1},{r,g,b,a}};
g_font_verts[vi+3] = (FontVert){{(float)cx,(float)y+FONT_CHAR_H,0},{0,0,-1},{u0,v1},{r,g,b,a}};
uint32_t base = (uint32_t)vi;
g_font_indices[g_font_ii++] = base; g_font_indices[g_font_ii++] = base+1; g_font_indices[g_font_ii++] = base+2;
g_font_indices[g_font_ii++] = base; g_font_indices[g_font_ii++] = base+2; g_font_indices[g_font_ii++] = base+3;
g_font_vi += 4;
cx += FONT_CHAR_W;
}
ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)g_font_vb, 0, NULL, g_font_verts, 0, 0);
ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)g_font_ib, 0, NULL, g_font_indices, 0, 0);
font_flush(ctx, screen_w, screen_h, g_font_ii);
}
void bitmap_font_rect(BitmapFont* f, ID3D11DeviceContext* ctx,
float x, float y, float w, float h,
float r, float g, float b, float a,
float screen_w, float screen_h) {
if (!f->shader) return;
font_begin();
font_add_quad(f, x, y, w, h, r, g, b, a);
ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)g_font_vb, 0, NULL, g_font_verts, 0, 0);
ctx->lpVtbl->UpdateSubresource(ctx, (ID3D11Resource*)g_font_ib, 0, NULL, g_font_indices, 0, 0);
font_flush(ctx, screen_w, screen_h, g_font_ii);
}