Optimized text rendering
parent
aacc2d0596
commit
0d612b9928
|
@ -77,6 +77,7 @@ public:
|
|||
virtual void DrawPrimitive(PrimitiveType type, int count, const Vertex2D* vertices) = 0;
|
||||
|
||||
virtual Vertex2D* BeginPrimitive(PrimitiveType type, int count) = 0;
|
||||
virtual Vertex2D* BeginPrimitives(PrimitiveType type, int drawCount, const int* counts) = 0;
|
||||
virtual bool EndPrimitive() = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -136,26 +136,23 @@ public:
|
|||
renderer->SetTexture(Texture{ m_texID });
|
||||
renderer->SetTransparency(m_transparency);
|
||||
|
||||
assert(m_firsts.size() == m_counts.size());
|
||||
if (m_firsts.size() < m_quads.size())
|
||||
if (m_counts.size() < m_quads.size())
|
||||
{
|
||||
// m_firsts needs to look like { 0, 4, 8, 12, ... }
|
||||
// m_counts needs to look like { 4, 4, 4, 4, ... }
|
||||
// and both need to be the same length as m_quads
|
||||
m_counts.resize(m_quads.size(), 4);
|
||||
std::size_t begin = m_firsts.size();
|
||||
m_firsts.resize(m_quads.size());
|
||||
for (std::size_t i = begin; i < m_firsts.size(); ++i)
|
||||
{
|
||||
m_firsts[i] = static_cast<int>(4 * i);
|
||||
}
|
||||
}
|
||||
|
||||
auto vertices = renderer->BeginPrimitives(PrimitiveType::TRIANGLE_STRIP, m_quads.size(), m_counts.data());
|
||||
|
||||
size_t offset = 0;
|
||||
|
||||
for (const auto& quad : m_quads)
|
||||
{
|
||||
renderer->DrawPrimitive(PrimitiveType::TRIANGLE_STRIP, 4, quad.vertices);
|
||||
std::copy_n(quad.vertices, 4, vertices + offset);
|
||||
offset += 4;
|
||||
}
|
||||
|
||||
renderer->EndPrimitive();
|
||||
|
||||
m_engine.AddStatisticTriangle(static_cast<int>(m_quads.size() * 2));
|
||||
m_quads.clear();
|
||||
}
|
||||
|
@ -164,7 +161,6 @@ private:
|
|||
|
||||
struct Quad { Vertex2D vertices[4]; };
|
||||
std::vector<Quad> m_quads;
|
||||
std::vector<int> m_firsts;
|
||||
std::vector<int> m_counts;
|
||||
|
||||
Color m_color;
|
||||
|
@ -1050,18 +1046,14 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, glm::iv
|
|||
|
||||
Gfx::IntColor col = Gfx::ColorToIntColor(color);
|
||||
|
||||
auto renderer = m_device->GetUIRenderer();
|
||||
renderer->SetTransparency(TransparencyMode::WHITE);
|
||||
renderer->SetTexture(Texture{ texID });
|
||||
auto vertices = renderer->BeginPrimitive(PrimitiveType::TRIANGLE_STRIP, 4);
|
||||
Gfx::Vertex2D vertices[4];
|
||||
|
||||
vertices[0] = { { p1.x, p2.y }, { uv1.x, uv2.y }, col };
|
||||
vertices[1] = { { p1.x, p1.y }, { uv1.x, uv1.y }, col };
|
||||
vertices[2] = { { p2.x, p2.y }, { uv2.x, uv2.y }, col };
|
||||
vertices[3] = { { p2.x, p1.y }, { uv2.x, uv1.y }, col };
|
||||
|
||||
//m_quadBatch->Add(quad, texID, TransparencyMode::WHITE, color);
|
||||
renderer->EndPrimitive();
|
||||
m_quadBatch->Add(vertices, texID, TransparencyMode::WHITE, color);
|
||||
|
||||
pos.x += width;
|
||||
}
|
||||
|
@ -1092,18 +1084,14 @@ void CText::DrawCharAndAdjustPos(UTF8Char ch, FontType font, float size, glm::iv
|
|||
|
||||
Gfx::IntColor col = Gfx::ColorToIntColor(color);
|
||||
|
||||
auto renderer = m_device->GetUIRenderer();
|
||||
renderer->SetTransparency(TransparencyMode::ALPHA);
|
||||
renderer->SetTexture(Texture{ tex.id });
|
||||
auto vertices = renderer->BeginPrimitive(PrimitiveType::TRIANGLE_STRIP, 4);
|
||||
Gfx::Vertex2D vertices[4];
|
||||
|
||||
vertices[0] = { { p1.x, p2.y }, { texCoord1.x, texCoord2.y }, col };
|
||||
vertices[1] = { { p1.x, p1.y }, { texCoord1.x, texCoord1.y }, col };
|
||||
vertices[2] = { { p2.x, p2.y }, { texCoord2.x, texCoord2.y }, col };
|
||||
vertices[3] = { { p2.x, p1.y }, { texCoord2.x, texCoord1.y }, col };
|
||||
|
||||
//m_quadBatch->Add(quad, tex.id, TransparencyMode::ALPHA, color);
|
||||
renderer->EndPrimitive();
|
||||
m_quadBatch->Add(vertices, tex.id, TransparencyMode::ALPHA, color);
|
||||
|
||||
pos.x += tex.charSize.x * width;
|
||||
}
|
||||
|
|
|
@ -147,18 +147,30 @@ void CGL33UIRenderer::DrawPrimitive(PrimitiveType type, int count, const Vertex2
|
|||
}
|
||||
|
||||
Vertex2D* CGL33UIRenderer::BeginPrimitive(PrimitiveType type, int count)
|
||||
{
|
||||
return BeginPrimitives(type, 1, &count);
|
||||
}
|
||||
|
||||
Vertex2D* CGL33UIRenderer::BeginPrimitives(PrimitiveType type, int drawCount, const int* counts)
|
||||
{
|
||||
glBindVertexArray(m_bufferVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_bufferVBO);
|
||||
|
||||
GLuint total = m_offset + count;
|
||||
m_currentCount = 0;
|
||||
|
||||
for (size_t i = 0; i < drawCount; i++)
|
||||
{
|
||||
m_currentCount += counts[i];
|
||||
}
|
||||
|
||||
GLuint total = m_bufferOffset + m_currentCount;
|
||||
|
||||
// Buffer full, orphan
|
||||
if (total >= m_bufferCapacity)
|
||||
{
|
||||
glBufferData(GL_ARRAY_BUFFER, m_bufferCapacity * sizeof(Vertex2D), nullptr, GL_STREAM_DRAW);
|
||||
|
||||
m_offset = 0;
|
||||
m_bufferOffset = 0;
|
||||
|
||||
// Respecify vertex attributes
|
||||
glEnableVertexAttribArray(0);
|
||||
|
@ -174,20 +186,33 @@ Vertex2D* CGL33UIRenderer::BeginPrimitive(PrimitiveType type, int count)
|
|||
reinterpret_cast<void*>(offsetof(Vertex2D, color)));
|
||||
}
|
||||
|
||||
m_first.resize(drawCount);
|
||||
m_count.resize(drawCount);
|
||||
|
||||
GLsizei currentOffset = m_bufferOffset;
|
||||
|
||||
for (size_t i = 0; i < drawCount; i++)
|
||||
{
|
||||
m_first[i] = currentOffset;
|
||||
m_count[i] = counts[i];
|
||||
|
||||
currentOffset += counts[i];
|
||||
}
|
||||
|
||||
auto ptr = glMapBufferRange(GL_ARRAY_BUFFER,
|
||||
m_offset * sizeof(Vertex2D),
|
||||
count * sizeof(Vertex2D),
|
||||
m_bufferOffset * sizeof(Vertex2D),
|
||||
m_currentCount * sizeof(Vertex2D),
|
||||
GL_MAP_WRITE_BIT | GL_MAP_UNSYNCHRONIZED_BIT);
|
||||
|
||||
m_mapped = true;
|
||||
m_type = type;
|
||||
m_count = count;
|
||||
m_drawCount = drawCount;
|
||||
|
||||
// Mapping failed, use backup buffer
|
||||
if (ptr == nullptr)
|
||||
{
|
||||
m_backup = true;
|
||||
m_buffer.resize(count);
|
||||
m_buffer.resize(m_currentCount);
|
||||
|
||||
return m_buffer.data();
|
||||
}
|
||||
|
@ -203,7 +228,10 @@ bool CGL33UIRenderer::EndPrimitive()
|
|||
|
||||
if (m_backup)
|
||||
{
|
||||
glBufferSubData(GL_ARRAY_BUFFER, m_offset * sizeof(Vertex2D), m_count * sizeof(Vertex2D), m_buffer.data());
|
||||
glBufferSubData(GL_ARRAY_BUFFER,
|
||||
m_bufferOffset * sizeof(Vertex2D),
|
||||
m_currentCount * sizeof(Vertex2D),
|
||||
m_buffer.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -218,9 +246,12 @@ bool CGL33UIRenderer::EndPrimitive()
|
|||
|
||||
m_device->SetDepthTest(false);
|
||||
|
||||
glDrawArrays(TranslateGfxPrimitive(m_type), m_offset, m_count);
|
||||
if (m_drawCount == 1)
|
||||
glDrawArrays(TranslateGfxPrimitive(m_type), m_first.front(), m_count.front());
|
||||
else
|
||||
glMultiDrawArrays(TranslateGfxPrimitive(m_type), m_first.data(), m_count.data(), m_drawCount);
|
||||
|
||||
m_offset += m_count;
|
||||
m_bufferOffset += m_currentCount;
|
||||
|
||||
m_mapped = false;
|
||||
m_backup = false;
|
||||
|
|
|
@ -51,6 +51,7 @@ public:
|
|||
virtual void DrawPrimitive(PrimitiveType type, int count, const Vertex2D* vertices) override;
|
||||
|
||||
virtual Vertex2D* BeginPrimitive(PrimitiveType type, int count) override;
|
||||
virtual Vertex2D* BeginPrimitives(PrimitiveType type, int drawCount, const int* counts) override;
|
||||
virtual bool EndPrimitive() override;
|
||||
|
||||
private:
|
||||
|
@ -78,12 +79,22 @@ private:
|
|||
GLuint m_bufferVAO = 0;
|
||||
// VBO capacity
|
||||
GLsizei m_bufferCapacity = 128 * 1024;
|
||||
// Buffer offset
|
||||
GLsizei m_bufferOffset = 0;
|
||||
|
||||
// Buffer mapping state
|
||||
PrimitiveType m_type = {};
|
||||
GLuint m_offset = 0;
|
||||
GLuint m_count = 0;
|
||||
// Number of drawn primitives
|
||||
GLuint m_drawCount = 0;
|
||||
// Total count of drawn vertices
|
||||
GLuint m_currentCount = 0;
|
||||
// Starting offset for each drawn primitive
|
||||
std::vector<GLint> m_first;
|
||||
// Numbers of vertices for each drawn primitive
|
||||
std::vector<GLsizei> m_count;
|
||||
// True means currently drawing
|
||||
bool m_mapped = false;
|
||||
// True means mapping failed, using auxiliary buffer
|
||||
bool m_backup = false;
|
||||
|
||||
// Buffered vertex data
|
||||
|
|
Loading…
Reference in New Issue