#include "bitmap_font.h" #include #include #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); }