Changeset View
Changeset View
Standalone View
Standalone View
ps/trunk/source/graphics/TextRenderer.cpp
Show First 20 Lines • Show All 197 Lines • ▼ Show 20 Lines | if (a.font != b.font) | ||||
return a.font < b.font; | return a.font < b.font; | ||||
// TODO: is it worth sorting by color/translate too? | // TODO: is it worth sorting by color/translate too? | ||||
return false; | return false; | ||||
} | } | ||||
}; | }; | ||||
void CTextRenderer::Render( | void CTextRenderer::Render( | ||||
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, | Renderer::Backend::IDeviceCommandContext* deviceCommandContext, | ||||
Renderer::Backend::IShaderProgram* shader, const CMatrix3D& transform) | Renderer::Backend::IShaderProgram* shader, | ||||
const CVector2D& transformScale, const CVector2D& translation) | |||||
{ | { | ||||
std::vector<u16> indexes; | std::vector<u16> indexes; | ||||
std::vector<t2f_v2i> vertexes; | std::vector<t2f_v2i> vertexes; | ||||
// Try to merge non-consecutive batches that share the same font/color/translate: | // Try to merge non-consecutive batches that share the same font/color/translate: | ||||
// sort the batch list by font, then merge the runs of adjacent compatible batches | // sort the batch list by font, then merge the runs of adjacent compatible batches | ||||
m_Batches.sort(SBatchCompare()); | m_Batches.sort(SBatchCompare()); | ||||
for (std::list<SBatch>::iterator it = m_Batches.begin(); it != m_Batches.end(); ) | for (std::list<SBatch>::iterator it = m_Batches.begin(); it != m_Batches.end(); ) | ||||
{ | { | ||||
std::list<SBatch>::iterator next = std::next(it); | std::list<SBatch>::iterator next = std::next(it); | ||||
if (next != m_Batches.end() && it->chars + next->chars <= MAX_CHAR_COUNT_PER_BATCH && it->font == next->font && it->color == next->color && it->translate == next->translate) | if (next != m_Batches.end() && it->chars + next->chars <= MAX_CHAR_COUNT_PER_BATCH && it->font == next->font && it->color == next->color && it->translate == next->translate) | ||||
{ | { | ||||
it->chars += next->chars; | it->chars += next->chars; | ||||
it->runs.splice(it->runs.end(), next->runs); | it->runs.splice(it->runs.end(), next->runs); | ||||
m_Batches.erase(next); | m_Batches.erase(next); | ||||
} | } | ||||
else | else | ||||
++it; | ++it; | ||||
} | } | ||||
const int32_t texBindingSlot = shader->GetBindingSlot(str_tex); | const int32_t texBindingSlot = shader->GetBindingSlot(str_tex); | ||||
const int32_t transformBindingSlot = shader->GetBindingSlot(str_transform); | const int32_t translationBindingSlot = shader->GetBindingSlot(str_translation); | ||||
const int32_t colorAddBindingSlot = shader->GetBindingSlot(str_colorAdd); | const int32_t colorAddBindingSlot = shader->GetBindingSlot(str_colorAdd); | ||||
const int32_t colorMulBindingSlot = shader->GetBindingSlot(str_colorMul); | const int32_t colorMulBindingSlot = shader->GetBindingSlot(str_colorMul); | ||||
bool transformChanged = false; | bool translationChanged = false; | ||||
CTexture* lastTexture = nullptr; | CTexture* lastTexture = nullptr; | ||||
for (std::list<SBatch>::iterator it = m_Batches.begin(); it != m_Batches.end(); ++it) | for (std::list<SBatch>::iterator it = m_Batches.begin(); it != m_Batches.end(); ++it) | ||||
{ | { | ||||
SBatch& batch = *it; | SBatch& batch = *it; | ||||
const CFont::GlyphMap& glyphs = batch.font->GetGlyphs(); | const CFont::GlyphMap& glyphs = batch.font->GetGlyphs(); | ||||
if (lastTexture != batch.font->GetTexture().get()) | if (lastTexture != batch.font->GetTexture().get()) | ||||
{ | { | ||||
lastTexture = batch.font->GetTexture().get(); | lastTexture = batch.font->GetTexture().get(); | ||||
lastTexture->UploadBackendTextureIfNeeded(deviceCommandContext); | lastTexture->UploadBackendTextureIfNeeded(deviceCommandContext); | ||||
deviceCommandContext->SetTexture(texBindingSlot, lastTexture->GetBackendTexture()); | deviceCommandContext->SetTexture(texBindingSlot, lastTexture->GetBackendTexture()); | ||||
} | } | ||||
if (batch.translate.X != 0.0f || batch.translate.Y != 0.0f) | if (batch.translate.X != 0.0f || batch.translate.Y != 0.0f) | ||||
{ | { | ||||
CMatrix3D localTransform; | const CVector2D localTranslation = | ||||
localTransform.SetTranslation(batch.translate.X, batch.translate.Y, 0.0f); | translation + CVector2D(batch.translate.X * transformScale.X, batch.translate.Y * transformScale.Y); | ||||
localTransform = transform * localTransform; | deviceCommandContext->SetUniform(translationBindingSlot, localTranslation.AsFloatArray()); | ||||
deviceCommandContext->SetUniform(transformBindingSlot, localTransform.AsFloatArray()); | translationChanged = true; | ||||
transformChanged = true; | |||||
} | } | ||||
// ALPHA-only textures will have .rgb sampled as 0, so we need to | // ALPHA-only textures will have .rgb sampled as 0, so we need to | ||||
// replace it with white (but not affect RGBA textures) | // replace it with white (but not affect RGBA textures) | ||||
if (batch.font->HasRGB()) | if (batch.font->HasRGB()) | ||||
deviceCommandContext->SetUniform(colorAddBindingSlot, 0.0f, 0.0f, 0.0f, 0.0f); | deviceCommandContext->SetUniform(colorAddBindingSlot, 0.0f, 0.0f, 0.0f, 0.0f); | ||||
else | else | ||||
deviceCommandContext->SetUniform(colorAddBindingSlot, batch.color.r, batch.color.g, batch.color.b, 0.0f); | deviceCommandContext->SetUniform(colorAddBindingSlot, batch.color.r, batch.color.g, batch.color.b, 0.0f); | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | for (std::list<SBatchRun>::iterator runit = batch.runs.begin(); runit != batch.runs.end(); ++runit) | ||||
} | } | ||||
} | } | ||||
flush(); | flush(); | ||||
} | } | ||||
m_Batches.clear(); | m_Batches.clear(); | ||||
if (transformChanged) | if (translationChanged) | ||||
deviceCommandContext->SetUniform(transformBindingSlot, transform.AsFloatArray()); | deviceCommandContext->SetUniform(translationBindingSlot, translation.AsFloatArray()); | ||||
} | } |
Wildfire Games · Phabricator