mirror of
https://github.com/doitsujin/dxvk.git
synced 2024-12-05 01:24:14 +01:00
[hud] Greatly simplify text rendering in the HUD
This commit is contained in:
parent
8ce83cabca
commit
0709c5f5c7
@ -15,11 +15,15 @@ namespace dxvk::hud {
|
||||
m_device (device),
|
||||
m_textShaders (createTextShaders()),
|
||||
m_lineShaders (createLineShaders()),
|
||||
m_dataBuffer (createDataBuffer()),
|
||||
m_dataView (createDataView()),
|
||||
m_dataOffset (0ull),
|
||||
m_fontBuffer (createFontBuffer()),
|
||||
m_fontImage (createFontImage()),
|
||||
m_fontView (createFontView()),
|
||||
m_fontSampler (createFontSampler()),
|
||||
m_vertexBuffer (createVertexBuffer()) {
|
||||
this->initCharMap();
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -32,9 +36,6 @@ namespace dxvk::hud {
|
||||
if (!m_initialized)
|
||||
this->initFontTexture(context);
|
||||
|
||||
context->bindResourceSampler(0, m_fontSampler);
|
||||
context->bindResourceView (0, m_fontView, nullptr);
|
||||
|
||||
m_mode = Mode::RenderNone;
|
||||
m_scale = scale;
|
||||
m_surfaceSize = surfaceSize;
|
||||
@ -49,66 +50,32 @@ namespace dxvk::hud {
|
||||
HudPos pos,
|
||||
HudColor color,
|
||||
const std::string& text) {
|
||||
if (text.empty())
|
||||
return;
|
||||
|
||||
beginTextRendering();
|
||||
|
||||
const float xscale = m_scale / std::max(float(m_surfaceSize.width), 1.0f);
|
||||
const float yscale = m_scale / std::max(float(m_surfaceSize.height), 1.0f);
|
||||
// Copy string into string buffer, but extend it to cover a full cache
|
||||
// line to avoid potential CPU performance issues with the upload.
|
||||
std::string textCopy = text;
|
||||
textCopy.resize(align(text.size(), CACHE_LINE_SIZE), ' ');
|
||||
|
||||
uint32_t vertexCount = 6 * text.size();
|
||||
VkDeviceSize offset = allocDataBuffer(textCopy.size());
|
||||
std::memcpy(m_dataBuffer->mapPtr(offset), textCopy.data(), textCopy.size());
|
||||
|
||||
if (m_currTextVertex + vertexCount > MaxTextVertexCount
|
||||
|| m_currTextInstance + 1 > MaxTextInstanceCount)
|
||||
allocVertexBufferSlice();
|
||||
// Fill in push constants for the next draw
|
||||
HudTextPushConstants pushData;
|
||||
pushData.color = color;
|
||||
pushData.pos = pos;
|
||||
pushData.offset = offset;
|
||||
pushData.size = size;
|
||||
pushData.scale.x = m_scale / std::max(float(m_surfaceSize.width), 1.0f);
|
||||
pushData.scale.y = m_scale / std::max(float(m_surfaceSize.height), 1.0f);
|
||||
|
||||
m_context->draw(vertexCount, 1, m_currTextVertex, m_currTextInstance);
|
||||
m_context->pushConstants(0, sizeof(pushData), &pushData);
|
||||
|
||||
const float sizeFactor = size / float(g_hudFont.size);
|
||||
|
||||
for (size_t i = 0; i < text.size(); i++) {
|
||||
const HudGlyph& glyph = g_hudFont.glyphs[
|
||||
m_charMap[uint8_t(text[i])]];
|
||||
|
||||
HudPos size = {
|
||||
sizeFactor * float(glyph.w),
|
||||
sizeFactor * float(glyph.h) };
|
||||
|
||||
HudPos origin = {
|
||||
pos.x - sizeFactor * float(glyph.originX),
|
||||
pos.y - sizeFactor * float(glyph.originY) };
|
||||
|
||||
HudPos posTl = { xscale * (origin.x), yscale * (origin.y) };
|
||||
HudPos posBr = { xscale * (origin.x + size.x), yscale * (origin.y + size.y) };
|
||||
|
||||
HudTexCoord texTl = { uint32_t(glyph.x), uint32_t(glyph.y) };
|
||||
HudTexCoord texBr = { uint32_t(glyph.x + glyph.w), uint32_t(glyph.y + glyph.h) };
|
||||
|
||||
uint32_t idx = 6 * i + m_currTextVertex;
|
||||
|
||||
m_vertexData->textVertices[idx + 0].position = { posTl.x, posTl.y };
|
||||
m_vertexData->textVertices[idx + 0].texcoord = { texTl.u, texTl.v };
|
||||
|
||||
m_vertexData->textVertices[idx + 1].position = { posBr.x, posTl.y };
|
||||
m_vertexData->textVertices[idx + 1].texcoord = { texBr.u, texTl.v };
|
||||
|
||||
m_vertexData->textVertices[idx + 2].position = { posTl.x, posBr.y };
|
||||
m_vertexData->textVertices[idx + 2].texcoord = { texTl.u, texBr.v };
|
||||
|
||||
m_vertexData->textVertices[idx + 3].position = { posBr.x, posBr.y };
|
||||
m_vertexData->textVertices[idx + 3].texcoord = { texBr.u, texBr.v };
|
||||
|
||||
m_vertexData->textVertices[idx + 4].position = { posTl.x, posBr.y };
|
||||
m_vertexData->textVertices[idx + 4].texcoord = { texTl.u, texBr.v };
|
||||
|
||||
m_vertexData->textVertices[idx + 5].position = { posBr.x, posTl.y };
|
||||
m_vertexData->textVertices[idx + 5].texcoord = { texBr.u, texTl.v };
|
||||
|
||||
pos.x += sizeFactor * static_cast<float>(g_hudFont.advance);
|
||||
}
|
||||
|
||||
m_vertexData->textColors[m_currTextInstance] = color;
|
||||
|
||||
m_currTextVertex += vertexCount;
|
||||
m_currTextInstance += 1;
|
||||
// Draw with orignal vertex count
|
||||
m_context->draw(6 * text.size(), 1, 0, 0);
|
||||
}
|
||||
|
||||
|
||||
@ -142,8 +109,6 @@ namespace dxvk::hud {
|
||||
auto vertexSlice = m_vertexBuffer->allocSlice();
|
||||
m_context->invalidateBuffer(m_vertexBuffer, vertexSlice);
|
||||
|
||||
m_currTextVertex = 0;
|
||||
m_currTextInstance = 0;
|
||||
m_currLineVertex = 0;
|
||||
|
||||
m_vertexData = reinterpret_cast<VertexBufferData*>(vertexSlice.mapPtr);
|
||||
@ -154,33 +119,20 @@ namespace dxvk::hud {
|
||||
if (m_mode != Mode::RenderText) {
|
||||
m_mode = Mode::RenderText;
|
||||
|
||||
m_context->bindVertexBuffer(0, DxvkBufferSlice(m_vertexBuffer, offsetof(VertexBufferData, textVertices), sizeof(HudTextVertex) * MaxTextVertexCount), sizeof(HudTextVertex));
|
||||
m_context->bindVertexBuffer(1, DxvkBufferSlice(m_vertexBuffer, offsetof(VertexBufferData, textColors), sizeof(HudColor) * MaxTextInstanceCount), sizeof(HudColor));
|
||||
|
||||
m_context->bindShader(VK_SHADER_STAGE_VERTEX_BIT, m_textShaders.vert);
|
||||
m_context->bindShader(VK_SHADER_STAGE_FRAGMENT_BIT, m_textShaders.frag);
|
||||
|
||||
m_context->bindResourceBuffer (0, DxvkBufferSlice(m_fontBuffer));
|
||||
m_context->bindResourceView (1, nullptr, m_dataView);
|
||||
m_context->bindResourceSampler(2, m_fontSampler);
|
||||
m_context->bindResourceView (2, m_fontView, nullptr);
|
||||
|
||||
static const DxvkInputAssemblyState iaState = {
|
||||
VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
|
||||
VK_FALSE, 0 };
|
||||
|
||||
static const std::array<DxvkVertexAttribute, 3> ilAttributes = {{
|
||||
{ 0, 0, VK_FORMAT_R32G32_SFLOAT, offsetof(HudTextVertex, position) },
|
||||
{ 1, 0, VK_FORMAT_R32G32_UINT, offsetof(HudTextVertex, texcoord) },
|
||||
{ 2, 1, VK_FORMAT_R32G32B32A32_SFLOAT, 0 },
|
||||
}};
|
||||
|
||||
static const std::array<DxvkVertexBinding, 2> ilBindings = {{
|
||||
{ 0, 0, VK_VERTEX_INPUT_RATE_VERTEX },
|
||||
{ 1, 1, VK_VERTEX_INPUT_RATE_INSTANCE },
|
||||
}};
|
||||
|
||||
m_context->setInputAssemblyState(iaState);
|
||||
m_context->setInputLayout(
|
||||
ilAttributes.size(),
|
||||
ilAttributes.data(),
|
||||
ilBindings.size(),
|
||||
ilBindings.data());
|
||||
m_context->setInputLayout(0, nullptr, 0, nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
@ -215,6 +167,18 @@ namespace dxvk::hud {
|
||||
ilBindings.data());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
VkDeviceSize HudRenderer::allocDataBuffer(VkDeviceSize size) {
|
||||
if (m_dataOffset + size > m_dataBuffer->info().size) {
|
||||
m_context->invalidateBuffer(m_dataBuffer, m_dataBuffer->allocSlice());
|
||||
m_dataOffset = 0;
|
||||
}
|
||||
|
||||
VkDeviceSize offset = m_dataOffset;
|
||||
m_dataOffset = align(offset + size, 64);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
HudRenderer::ShaderPair HudRenderer::createTextShaders() {
|
||||
@ -223,14 +187,21 @@ namespace dxvk::hud {
|
||||
const SpirvCodeBuffer vsCode(hud_text_vert);
|
||||
const SpirvCodeBuffer fsCode(hud_text_frag);
|
||||
|
||||
// Two shader resources: Font texture and sampler
|
||||
const std::array<DxvkResourceSlot, 3> vsResources = {{
|
||||
{ 0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
||||
{ 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, VK_IMAGE_VIEW_TYPE_MAX_ENUM },
|
||||
}};
|
||||
|
||||
const std::array<DxvkResourceSlot, 1> fsResources = {{
|
||||
{ 0, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D },
|
||||
{ 2, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_IMAGE_VIEW_TYPE_2D },
|
||||
}};
|
||||
|
||||
result.vert = m_device->createShader(
|
||||
VK_SHADER_STAGE_VERTEX_BIT,
|
||||
0, nullptr, { 0x7, 0x3 }, vsCode);
|
||||
vsResources.size(),
|
||||
vsResources.data(),
|
||||
{ 0x0, 0x3, 0, sizeof(HudTextPushConstants) },
|
||||
vsCode);
|
||||
|
||||
result.frag = m_device->createShader(
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT,
|
||||
@ -261,6 +232,46 @@ namespace dxvk::hud {
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkBuffer> HudRenderer::createDataBuffer() {
|
||||
DxvkBufferCreateInfo info;
|
||||
info.size = DataBufferSize;
|
||||
info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
|
||||
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||
info.access = VK_ACCESS_SHADER_READ_BIT;
|
||||
|
||||
return m_device->createBuffer(info,
|
||||
VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
|
||||
VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkBufferView> HudRenderer::createDataView() {
|
||||
DxvkBufferViewCreateInfo info;
|
||||
info.format = VK_FORMAT_R8_UINT;
|
||||
info.rangeOffset = 0;
|
||||
info.rangeLength = m_dataBuffer->info().size;
|
||||
|
||||
return m_device->createBufferView(m_dataBuffer, info);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkBuffer> HudRenderer::createFontBuffer() {
|
||||
DxvkBufferCreateInfo info;
|
||||
info.size = sizeof(HudFontGpuData);
|
||||
info.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
|
||||
| VK_BUFFER_USAGE_TRANSFER_DST_BIT;
|
||||
info.stages = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
|
||||
| VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
info.access = VK_ACCESS_SHADER_READ_BIT
|
||||
| VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||
|
||||
return m_device->createBuffer(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
|
||||
}
|
||||
|
||||
|
||||
Rc<DxvkImage> HudRenderer::createFontImage() {
|
||||
DxvkImageCreateInfo info;
|
||||
info.type = VK_IMAGE_TYPE_2D;
|
||||
@ -336,31 +347,29 @@ namespace dxvk::hud {
|
||||
|
||||
void HudRenderer::initFontTexture(
|
||||
const Rc<DxvkContext>& context) {
|
||||
DxvkBufferCreateInfo bufferInfo;
|
||||
bufferInfo.size = g_hudFont.width * g_hudFont.height;
|
||||
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
|
||||
bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
bufferInfo.access = VK_ACCESS_TRANSFER_READ_BIT;
|
||||
HudFontGpuData gpuData = { };
|
||||
gpuData.size = float(g_hudFont.size);
|
||||
gpuData.advance = float(g_hudFont.advance);
|
||||
|
||||
auto stagingBuffer = m_device->createBuffer(bufferInfo,
|
||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||
std::memcpy(stagingBuffer->mapPtr(0), g_hudFont.texture, bufferInfo.size);
|
||||
for (uint32_t i = 0; i < g_hudFont.charCount; i++) {
|
||||
auto src = &g_hudFont.glyphs[i];
|
||||
auto dst = &gpuData.glyphs[src->codePoint];
|
||||
|
||||
context->copyBufferToImage(m_fontImage,
|
||||
dst->x = src->x;
|
||||
dst->y = src->y;
|
||||
dst->w = src->w;
|
||||
dst->h = src->h;
|
||||
dst->originX = src->originX;
|
||||
dst->originY = src->originY;
|
||||
}
|
||||
|
||||
context->uploadBuffer(m_fontBuffer, &gpuData);
|
||||
|
||||
context->uploadImage(m_fontImage,
|
||||
VkImageSubresourceLayers { VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1 },
|
||||
VkOffset3D { 0, 0, 0 },
|
||||
VkExtent3D { g_hudFont.width, g_hudFont.height, 1 },
|
||||
stagingBuffer, 0, 0, 0);
|
||||
g_hudFont.texture, g_hudFont.width, g_hudFont.width * g_hudFont.height);
|
||||
|
||||
m_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
void HudRenderer::initCharMap() {
|
||||
std::fill(m_charMap.begin(), m_charMap.end(), 0);
|
||||
|
||||
for (uint32_t i = 0; i < g_hudFont.charCount; i++)
|
||||
m_charMap.at(g_hudFont.glyphs[i].codePoint) = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -17,17 +17,6 @@ namespace dxvk::hud {
|
||||
float y;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Texture coordinates
|
||||
*
|
||||
* Absolute texture coordinates that are used
|
||||
* to pick letters in the font texture.
|
||||
*/
|
||||
struct HudTexCoord {
|
||||
uint32_t u;
|
||||
uint32_t v;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Color
|
||||
*
|
||||
@ -52,14 +41,6 @@ namespace dxvk::hud {
|
||||
uint8_t a;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Text vertex and texture coordinates
|
||||
*/
|
||||
struct HudTextVertex {
|
||||
HudPos position;
|
||||
HudTexCoord texcoord;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Line vertex and color
|
||||
*/
|
||||
@ -67,7 +48,37 @@ namespace dxvk::hud {
|
||||
HudPos position;
|
||||
HudNormColor color;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \brief HUD push constant data
|
||||
*/
|
||||
struct HudTextPushConstants {
|
||||
HudColor color;
|
||||
HudPos pos;
|
||||
uint32_t offset;
|
||||
float size;
|
||||
HudPos scale;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Glyph data
|
||||
*/
|
||||
struct HudGlyphGpuData {
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t w;
|
||||
int16_t h;
|
||||
int16_t originX;
|
||||
int16_t originY;
|
||||
};
|
||||
|
||||
struct HudFontGpuData {
|
||||
float size;
|
||||
float advance;
|
||||
uint32_t padding[2];
|
||||
HudGlyphGpuData glyphs[256];
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief Text renderer for the HUD
|
||||
*
|
||||
@ -75,14 +86,11 @@ namespace dxvk::hud {
|
||||
* display performance and driver information.
|
||||
*/
|
||||
class HudRenderer {
|
||||
constexpr static uint32_t MaxTextVertexCount = 512 * 6;
|
||||
constexpr static uint32_t MaxTextInstanceCount = 64;
|
||||
constexpr static VkDeviceSize DataBufferSize = 16384;
|
||||
constexpr static uint32_t MaxLineVertexCount = 1024;
|
||||
|
||||
struct VertexBufferData {
|
||||
HudColor textColors[MaxTextInstanceCount];
|
||||
HudTextVertex textVertices[MaxTextVertexCount];
|
||||
HudLineVertex lineVertices[MaxLineVertexCount];
|
||||
HudLineVertex lineVertices[MaxLineVertexCount];
|
||||
};
|
||||
public:
|
||||
|
||||
@ -127,8 +135,6 @@ namespace dxvk::hud {
|
||||
Rc<DxvkShader> frag;
|
||||
};
|
||||
|
||||
std::array<uint8_t, 256> m_charMap;
|
||||
|
||||
Mode m_mode;
|
||||
float m_scale;
|
||||
VkExtent2D m_surfaceSize;
|
||||
@ -139,6 +145,11 @@ namespace dxvk::hud {
|
||||
ShaderPair m_textShaders;
|
||||
ShaderPair m_lineShaders;
|
||||
|
||||
Rc<DxvkBuffer> m_dataBuffer;
|
||||
Rc<DxvkBufferView> m_dataView;
|
||||
VkDeviceSize m_dataOffset;
|
||||
|
||||
Rc<DxvkBuffer> m_fontBuffer;
|
||||
Rc<DxvkImage> m_fontImage;
|
||||
Rc<DxvkImageView> m_fontView;
|
||||
Rc<DxvkSampler> m_fontSampler;
|
||||
@ -146,8 +157,6 @@ namespace dxvk::hud {
|
||||
Rc<DxvkBuffer> m_vertexBuffer;
|
||||
VertexBufferData* m_vertexData = nullptr;
|
||||
|
||||
uint32_t m_currTextVertex = 0;
|
||||
uint32_t m_currTextInstance = 0;
|
||||
uint32_t m_currLineVertex = 0;
|
||||
|
||||
bool m_initialized = false;
|
||||
@ -157,21 +166,25 @@ namespace dxvk::hud {
|
||||
void beginTextRendering();
|
||||
|
||||
void beginLineRendering();
|
||||
|
||||
|
||||
VkDeviceSize allocDataBuffer(VkDeviceSize size);
|
||||
|
||||
ShaderPair createTextShaders();
|
||||
ShaderPair createLineShaders();
|
||||
|
||||
Rc<DxvkBuffer> createDataBuffer();
|
||||
Rc<DxvkBufferView> createDataView();
|
||||
|
||||
Rc<DxvkBuffer> createFontBuffer();
|
||||
Rc<DxvkImage> createFontImage();
|
||||
Rc<DxvkImageView> createFontView();
|
||||
|
||||
Rc<DxvkSampler> createFontSampler();
|
||||
|
||||
Rc<DxvkBuffer> createVertexBuffer();
|
||||
|
||||
void initFontTexture(
|
||||
const Rc<DxvkContext>& context);
|
||||
|
||||
void initCharMap();
|
||||
|
||||
};
|
||||
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
layout(constant_id = 1225) const bool srgbSwapchain = false;
|
||||
|
||||
layout(set = 0, binding = 0) uniform sampler2D s_font;
|
||||
layout(binding = 2) uniform sampler2D s_font;
|
||||
|
||||
layout(location = 0) in vec2 v_texcoord;
|
||||
layout(location = 1) in vec4 v_color;
|
||||
|
@ -1,16 +1,75 @@
|
||||
#version 450
|
||||
|
||||
layout(location = 0) in vec2 v_position;
|
||||
layout(location = 1) in uvec2 v_texcoord;
|
||||
layout(location = 2) in vec4 v_color;
|
||||
struct font_info_t {
|
||||
float size;
|
||||
float advance;
|
||||
uvec2 padding;
|
||||
};
|
||||
|
||||
struct glyph_info_t {
|
||||
uint packed_xy;
|
||||
uint packed_wh;
|
||||
uint packed_origin;
|
||||
};
|
||||
|
||||
layout(binding = 0, std430)
|
||||
readonly buffer font_buffer_t {
|
||||
font_info_t font_data;
|
||||
glyph_info_t glyph_data[];
|
||||
};
|
||||
|
||||
layout(binding = 1) uniform usamplerBuffer text_buffer;
|
||||
|
||||
layout(push_constant)
|
||||
uniform push_data_t {
|
||||
vec4 text_color;
|
||||
vec2 text_pos;
|
||||
uint text_offset;
|
||||
float text_size;
|
||||
vec2 hud_scale;
|
||||
};
|
||||
|
||||
layout(location = 0) out vec2 o_texcoord;
|
||||
layout(location = 1) out vec4 o_color;
|
||||
|
||||
const uvec2 coord_mask = uvec2(0x2a, 0x1c);
|
||||
|
||||
vec2 unpack_u16(uint v) {
|
||||
// Inputs may be signed
|
||||
int hi = int(v);
|
||||
int lo = int(v << 16);
|
||||
return vec2(float(lo >> 16), float(hi >> 16));
|
||||
}
|
||||
|
||||
void main() {
|
||||
o_texcoord = vec2(v_texcoord);
|
||||
o_color = v_color;
|
||||
|
||||
vec2 pos = 2.0f * v_position - 1.0f;
|
||||
gl_Position = vec4(pos, 0.0f, 1.0f);
|
||||
}
|
||||
o_color = text_color;
|
||||
|
||||
// Compute character index and vertex index for the current
|
||||
// character. We'll render two triangles per character.
|
||||
uint chr_idx = gl_VertexIndex / 6;
|
||||
uint vtx_idx = gl_VertexIndex - 6 * chr_idx;
|
||||
|
||||
// Load glyph info based on vertex index
|
||||
uint glyph_idx = texelFetch(text_buffer, int(text_offset + chr_idx)).x;
|
||||
glyph_info_t glyph_info = glyph_data[glyph_idx];
|
||||
|
||||
// Compute texture coordinate from glyph data
|
||||
vec2 coord = vec2((coord_mask >> vtx_idx) & 0x1);
|
||||
|
||||
vec2 tex_xy = unpack_u16(glyph_info.packed_xy);
|
||||
vec2 tex_wh = unpack_u16(glyph_info.packed_wh);
|
||||
|
||||
o_texcoord = tex_xy + coord * tex_wh;
|
||||
|
||||
// Compute vertex position. We can easily do this here since our
|
||||
// font is a monospace font, otherwise we'd need to preprocess
|
||||
// the strings to render in a compute shader.
|
||||
float size_factor = text_size / font_data.size;
|
||||
|
||||
vec2 local_pos = tex_wh * coord - unpack_u16(glyph_info.packed_origin)
|
||||
+ vec2(font_data.advance * float(chr_idx), 0.0f);
|
||||
vec2 pixel_pos = text_pos + size_factor * local_pos;
|
||||
vec2 scaled_pos = 2.0f * hud_scale * pixel_pos - 1.0f;
|
||||
|
||||
gl_Position = vec4(scaled_pos, 0.0f, 1.0f);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user