#include "client/rendering/FontRenderer.h" const u64 FontRenderer::BUFFER_LENGTH = 8 * 1024 * 1024; static void setVertexAttribute(uint index, uint length, uint offset) { glVertexAttribPointer(index, length, GL_FLOAT, false, sizeof (float) * 7, static_cast (0) + offset); glEnableVertexAttribArray(index); } FontRenderer::FontRenderer() : tex("resources/font8x8.png"), offset(BUFFER_LENGTH), vertexArray(0), vertexBuffer(0) { glGenVertexArrays(1, &vertexArray); glBindVertexArray(vertexArray); glGenBuffers(1, &vertexBuffer); glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); setVertexAttribute(0, 2, 0); setVertexAttribute(1, 2, 2); setVertexAttribute(2, 3, 4); } FontRenderer::~FontRenderer() { glDeleteBuffers(1, &vertexBuffer); glDeleteVertexArrays(1, &vertexArray); } void FontRenderer::drawString(float x, float y, const char* text) { glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer); const u64 maxIndex = 256; const u64 maxLength = maxIndex * 4 * sizeof (float) * 7; if(offset + maxLength >= BUFFER_LENGTH) { offset = 0; glBufferData(GL_ARRAY_BUFFER, BUFFER_LENGTH, nullptr, GL_STREAM_DRAW); } float* buffer = static_cast (glMapBufferRange(GL_ARRAY_BUFFER, offset, maxLength, GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT)); if(buffer == nullptr) { return; } u64 index = 0; u64 i = 0; float r = 1.0f; float g = 1.0f; float b = 1.0f; while(text[index] != '\0' && index < maxIndex) { char c = text[index]; if(c == '&') { if(text[index + 1] == '\0' || text[index + 2] == '\0' || text[index + 3] == '\0') { break; } r = (text[index + 1] - '0') * (1.0f / 9.0f); g = (text[index + 2] - '0') * (1.0f / 9.0f); b = (text[index + 3] - '0') * (1.0f / 9.0f); index += 4; continue; } float minX = (c & 0xF) * (1.0f / 16.0f) + 1.0f / 128.0f; float minY = (c >> 4) * (1.0f / 16.0f); float maxX = minX + (1.0f / 16.0f) - 2.0f / 128.0f; float maxY = minY + (1.0f / 16.0f); buffer[i++] = x; buffer[i++] = y; buffer[i++] = minX; buffer[i++] = minY; buffer[i++] = r; buffer[i++] = g; buffer[i++] = b; buffer[i++] = x; buffer[i++] = y + 8; buffer[i++] = minX; buffer[i++] = maxY; buffer[i++] = r; buffer[i++] = g; buffer[i++] = b; buffer[i++] = x + 6; buffer[i++] = y; buffer[i++] = maxX; buffer[i++] = minY; buffer[i++] = r; buffer[i++] = g; buffer[i++] = b; buffer[i++] = x + 6; buffer[i++] = y + 8; buffer[i++] = maxX; buffer[i++] = maxY; buffer[i++] = r; buffer[i++] = g; buffer[i++] = b; x += 6; index++; } glUnmapBuffer(GL_ARRAY_BUFFER); glBindVertexArray(vertexArray); tex.bind(0); glDrawArrays(GL_TRIANGLE_STRIP, offset / (sizeof (float) * 7), i / 7); offset += maxLength; }