summaryrefslogtreecommitdiff
path: root/Runtime/GUI/TextMesh.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Runtime/GUI/TextMesh.cpp')
-rw-r--r--Runtime/GUI/TextMesh.cpp104
1 files changed, 90 insertions, 14 deletions
diff --git a/Runtime/GUI/TextMesh.cpp b/Runtime/GUI/TextMesh.cpp
index 6f3b3d6..de9a195 100644
--- a/Runtime/GUI/TextMesh.cpp
+++ b/Runtime/GUI/TextMesh.cpp
@@ -3,8 +3,11 @@
#include "../Math/Math.h"
#include "../Graphics/Color.h"
#include "TextMesh.h"
+#include "../Graphics/DefaultVertexLayout.h"
+#include "Runtime/Debug/Log.h"
#include <vector>
#include <unordered_map>
+#include "Runtime/Graphics/GfxDevice.h"
using namespace std;
@@ -20,6 +23,7 @@ static CustomVertexLayout s_TextMeshVBOLayout;
static unsigned int s_VertexPerText;
static unsigned int s_SizePerVertex;
static unsigned int s_SizePerText;
+static unsigned int s_SizePerIndex;
static unsigned int s_IndicesPerText;
struct TextInfo {
@@ -39,33 +43,36 @@ InitializeStaticVariables([]() {
s_VertexPerText = 4;
s_SizePerVertex = sizeof(TextMeshVBOLayout);
+
+ s_IndicesPerText = 6;
+ s_SizePerIndex = VertexLayout::GetDefaultIndexSize();
+
s_SizePerText = sizeof(TextMeshVBOLayout) * 4;
- s_IndicesPerText = 6;
});
TextMesh::TextMesh(const UnicodeString& str, Font* font,int pixelSize, ETextAnchor anchor, ETextAlignment alignment)
{
m_Font = font;
s_TextInfos.clear();
+ const Vector2 atlasSize = font->GetAtlasSize();
+ // 按照不同的atlas分类到s_TextInfos
float offset = 0;
for (int i = 0; i < str.length; ++i)
{
character::Codepoint c = str.str[i];
const Character* ch = font->GetCharacter(c, pixelSize);
- unsigned int index = ch->atlas;
+ unsigned int atlasIndex = ch->atlas;
TextInfo info;
info.ch = ch;
info.offset = offset;
- auto list = s_TextInfos.find(index);
+ auto list = s_TextInfos.find(atlasIndex);
if (list == s_TextInfos.end())
- {
- s_TextInfos.insert(std::pair<unsigned int, vector<TextInfo>>(index, vector<TextInfo>()));
- list = s_TextInfos.find(index);
- }
- vector<TextInfo>& v = list->second;
+ s_TextInfos.insert(std::pair<unsigned int, vector<TextInfo>>(atlasIndex, vector<TextInfo>()));
+
+ vector<TextInfo>& v = s_TextInfos[atlasIndex];
v.push_back(info);
offset += ch->advance;
@@ -74,17 +81,86 @@ TextMesh::TextMesh(const UnicodeString& str, Font* font,int pixelSize, ETextAnch
if (s_TextInfos.size() == 0)
return;
+ // 填充VBO和IBO
for (auto iter : s_TextInfos) {
- unsigned int index = iter.first;
+ unsigned int atlasIndex = iter.first; // atlas atlasIndex
vector<TextInfo>& texts = iter.second;
- int count = texts.size();
-
- VertexBuffer* vb = new VertexBuffer(count * s_SizePerText, count * s_IndicesPerText, VertexBuffer::VertexBufferType_Static);
-
+ int textCount = texts.size();
+
+ VertexBuffer* vb = new VertexBuffer(textCount * s_SizePerText, textCount * s_IndicesPerText * s_SizePerIndex, VertexBuffer::VertexBufferType_Static);
+ void* pVB;
+ uint16* pIB;
+
+ vb->GetChunk(s_SizePerVertex, s_SizePerIndex, s_VertexPerText * textCount, s_IndicesPerText * textCount, EPrimitive::Primitive_Triangle, &pVB,(void**) &pIB);
+
+ TextMeshVBOLayout* dst = (TextMeshVBOLayout*)pVB;
+ for (int i = 0; i < textCount; ++i)
+ {
+ TextInfo& text = texts[i];
+
+ int vOff = i * s_VertexPerText;
+ float pos[] = {
+ text.offset + text.ch->bearing.x, text.ch->bearing.y - text.ch->position.height, // bottom-left
+ text.offset + text.ch->bearing.x + text.ch->position.width, text.ch->bearing.y - text.ch->position.height, // bottom-right
+ text.offset + text.ch->bearing.x + text.ch->position.width, text.ch->bearing.y, // top-right
+ text.offset + text.ch->bearing.x, text.ch->bearing.y, // top-left
+ };
+ // 左上角为UV原点,所以在shader里采样的时候要镜像y
+ Vector4 uvQuad = Vector4(text.ch->position.x / atlasSize.x, text.ch->position.y / atlasSize.y, text.ch->position.width / atlasSize.x, text.ch->position.height / atlasSize.y);
+ float uv[] = {
+ uvQuad.x, uvQuad.y + uvQuad.w,
+ uvQuad.x + uvQuad.z, uvQuad.y + uvQuad.w,
+ uvQuad.x + uvQuad.z, uvQuad.y,
+ uvQuad.x, uvQuad.y,
+ };
+ for (int j = 0; j < s_VertexPerText; ++j)
+ {
+ dst[vOff + j].position.Set(pos[2 * j], pos[2 * j + 1]);
+ dst[vOff + j].uv.Set(uv[2 * j], uv[2 * j + 1]);
+ dst[vOff + j].color.Set(255 , 255, 255, 255);
+ }
+
+ int iOff = i * s_IndicesPerText;
+ int indices[] = {
+ 0, 1, 3, // right-top
+ 1, 2, 3, // left-bottom
+ };
+ for (int j = 0; j < s_IndicesPerText; ++j)
+ pIB[iOff + j] = vOff + indices[j];
+ }
+
+ vb->FlushChunk(s_VertexPerText * textCount, s_IndicesPerText * textCount);
+
+ m_VBOs.insert(std::pair<int, VertexBuffer*>(atlasIndex, vb));
}
+
+ WipeGLError();
}
void TextMesh::Draw()
{
-
+ for (auto subText : m_VBOs)
+ {
+ int atlasIndex = subText.first; // atlasIndex of atlas
+ VertexBuffer* vbo = subText.second;
+
+ const GlyphAtals* atlas = m_Font->GetGlyphAtlas(atlasIndex);
+ if (atlas == NULL)
+ {
+ log_error("Render text failed, no glyph atlas.");
+ continue;
+ }
+
+ g_GfxDevice.SetUniformTexture("gamelab_main_tex", atlas->altas);
+
+ CheckGLError(
+ throw GLException(error);
+ );
+ vbo->Draw(s_TextMeshVBOLayout);
+
+ CheckGLError(
+ throw GLException(error);
+ );
+ g_GfxDevice.ResetUniformsState();
+ }
}