From 72812a7b47f90f9460e54e8149ba9199a7841244 Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 2 Nov 2021 19:44:01 +0800 Subject: ! Text mesh done --- Runtime/GUI/Font.cpp | 4 +- Runtime/GUI/Font.h | 4 +- Runtime/GUI/TextMesh.cpp | 104 ++++++- Runtime/GUI/TextMesh.h | 3 +- Runtime/GUI/utf8.cpp | 415 ---------------------------- Runtime/GUI/utf8_decode.cpp | 415 ++++++++++++++++++++++++++++ Runtime/Graphics/Color.h | 14 + Runtime/Graphics/DynamicVertexBuffer.cpp | 10 +- Runtime/Graphics/DynamicVertexBuffer.h | 6 +- Runtime/Graphics/GPUDataBuffer.h | 6 +- Runtime/Graphics/GfxDevice.cpp | 3 +- Runtime/Graphics/OpenGL.h | 8 + Runtime/Graphics/Shader.cpp | 2 +- Runtime/Graphics/Texture.cpp | 4 + Runtime/Graphics/VertexBuffer.cpp | 107 ++++++- Runtime/Graphics/VertexBuffer.h | 14 +- Runtime/Lua/LuaBind/LuaBindUtility.h | 3 +- Runtime/Scripting/GUI/Font.bind.cpp | 10 + Runtime/Scripting/Rendering/Shader.bind.cpp | 4 +- 19 files changed, 683 insertions(+), 453 deletions(-) delete mode 100644 Runtime/GUI/utf8.cpp create mode 100644 Runtime/GUI/utf8_decode.cpp (limited to 'Runtime') diff --git a/Runtime/GUI/Font.cpp b/Runtime/GUI/Font.cpp index e5444f1..8cdfdf3 100644 --- a/Runtime/GUI/Font.cpp +++ b/Runtime/GUI/Font.cpp @@ -184,8 +184,8 @@ const GlyphAtals* Font::GetGlyphAtlas(int index) Internal::Rect Font::GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize) { - Internal::Rect rect; - Internal::Vector2 space; + Rect rect; + Vector2 space; space.x = atlas->width - atlas->cursor.x - m_AtlasMargin; space.y = atlas->height - atlas->cursor.y - m_AtlasMargin; if (space.x > preferSize.x && space.y > preferSize.y) diff --git a/Runtime/GUI/Font.h b/Runtime/GUI/Font.h index 9fea14e..e55e78f 100644 --- a/Runtime/GUI/Font.h +++ b/Runtime/GUI/Font.h @@ -16,7 +16,7 @@ struct Character { unsigned int atlas; // atlas索引 - Rect position; // 在altas里的位置 + Rect position; // 在altas里的位置,以左上角为原点的,和GL的Y镜像 Vector2 bearing; // 左上角相对于原点的偏移 unsigned int advance; // 总宽,算上了间隔 }; @@ -110,6 +110,8 @@ public: void RenderCharacters(character::Codepoint* codepoint, int n, int pixelSize); void RenderCharacters(std::vector& codepoint, int pixelSize); + GET(Vector2, AtlasSize, m_AtlasSize); + private: Texture* CreateAtlas(); GlyphAtals* RequestAtlas(int pixelSize, Vector2 preferSize); 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 #include +#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>(index, vector())); - list = s_TextInfos.find(index); - } - vector& v = list->second; + s_TextInfos.insert(std::pair>(atlasIndex, vector())); + + vector& 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& 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(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(); + } } diff --git a/Runtime/GUI/TextMesh.h b/Runtime/GUI/TextMesh.h index 8a29c92..c091a78 100644 --- a/Runtime/GUI/TextMesh.h +++ b/Runtime/GUI/TextMesh.h @@ -49,5 +49,4 @@ private: Font* m_Font; std::unordered_map m_VBOs; - -}; +}; \ No newline at end of file diff --git a/Runtime/GUI/utf8.cpp b/Runtime/GUI/utf8.cpp deleted file mode 100644 index 8a3a086..0000000 --- a/Runtime/GUI/utf8.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Description: UTF-8 瀛楃涓茬殑瑙g爜鍜岀紪鐮佸嚱鏁 - * unicode 瀛楃澶勭悊鍑芥暟 - * History: yang@haipo.me, 2013/05/29, create - * - * This code is in the public domain. - * You may use this code any way you wish, private, educational, - * or commercial. It's free. - */ - -# include -# include - -# include "utf8.h" - -namespace utf8 -{ - - ucs4_t getu8c(char **src, int *illegal) - { - static char umap[256] = { 0 }; - static int umap_init_flag = 0; - - if (umap_init_flag == 0) - { - int i; - - for (i = 0; i < 0x100; ++i) - { - if (i < 0x80) - { - umap[i] = 1; - } - else if (i >= 0xc0 && i < 0xe0) - { - umap[i] = 2; - } - else if (i >= 0xe0 && i < 0xf0) - { - umap[i] = 3; - } - else if (i >= 0xf0 && i < 0xf8) - { - umap[i] = 4; - } - else if (i >= 0xf8 && i < 0xfc) - { - umap[i] = 5; - } - else if (i >= 0xfc && i < 0xfe) - { - umap[i] = 6; - } - else - { - umap[i] = 0; - } - } - - umap_init_flag = 1; - } - - uint8_t *s = (uint8_t *)(*src); - int r_illegal = 0; - - while (umap[*s] == 0) - { - ++s; - ++r_illegal; - } - - uint8_t *t; - int byte_num; - uint32_t uc; - int i; - - repeat_label: - t = s; - byte_num = umap[*s]; - uc = *s++ & (0xff >> byte_num); - - for (i = 1; i < byte_num; ++i) - { - if (umap[*s]) - { - r_illegal += s - t; - goto repeat_label; - } - else - { - uc = (uc << 6) + (*s & 0x3f); - s += 1; - } - } - - *src = (char *)s; - if (illegal) - { - *illegal = r_illegal; - } - - return uc; - } - - size_t u8decode(char const *str, ucs4_t *des, size_t n, int *illegal) - { - if (n == 0) - return 0; - - char *s = (char *)str; - size_t i = 0; - ucs4_t uc = 0; - int r_illegal_all = 0, r_illegal; - - while ((uc = getu8c(&s, &r_illegal))) - { - if (i < (n - 1)) - { - des[i++] = uc; - r_illegal_all += r_illegal; - } - else - { - break; - } - } - - des[i] = 0; - if (illegal) - { - *illegal = r_illegal_all + r_illegal; - } - - return i; - } - -# define IF_CAN_HOLD(left, n) do { \ - size_t m = (size_t)(n); \ - if ((size_t)(left) < (m + 1)) return -2; \ - (left) -= m; \ -} while (0) - - int putu8c(ucs4_t uc, char **des, size_t *left) - { - if (uc < 0) - return -1; - - if (uc < (0x1 << 7)) - { - IF_CAN_HOLD(*left, 1); - - **des = (char)uc; - *des += 1; - **des = 0; - - return 1; - } - - int byte_num; - - if (uc < (0x1 << 11)) - { - byte_num = 2; - } - else if (uc < (0x1 << 16)) - { - byte_num = 3; - } - else if (uc < (0x1 << 21)) - { - byte_num = 4; - } - else if (uc < (0x1 << 26)) - { - byte_num = 5; - } - else - { - byte_num = 6; - } - - IF_CAN_HOLD(*left, byte_num); - - int i; - for (i = byte_num - 1; i > 0; --i) - { - *(uint8_t *)(*des + i) = (uc & 0x3f) | 0x80; - uc >>= 6; - } - - *(uint8_t *)(*des) = uc | (0xff << (8 - byte_num)); - - *des += byte_num; - **des = 0; - - return byte_num; - } - - size_t u8encode(ucs4_t *us, char *des, size_t n, int *illegal) - { - if (n == 0) - return 0; - - char *s = des; - size_t left = n; - size_t len = 0; - int r_illegal = 0; - - *s = 0; - while (*us) - { - int ret = putu8c(*us, &s, &left); - if (ret > 0) - { - len += ret; - } - else if (ret == -1) - { - r_illegal += 1; - } - else - { - break; - } - - ++us; - } - - if (illegal) - { - *illegal = r_illegal; - } - - return len; - } - - /* 鍏ㄨ瀛楃 */ - int isufullwidth(ucs4_t uc) - { - if (uc == 0x3000) - return 1; - - if (uc >= 0xff01 && uc <= 0xff5e) - return 1; - - return 0; - } - - /* 鍏ㄨ瀛楁瘝 */ - int isufullwidthalpha(ucs4_t uc) - { - if (uc >= 0xff21 && uc <= 0xff3a) - return 1; - - if (uc >= 0xff41 && uc <= 0xff5a) - return 2; - - return 0; - } - - /* 鍏ㄨ鏁板瓧 */ - int isufullwidthdigit(ucs4_t uc) - { - if (uc >= 0xff10 && uc <= 0xff19) - return 1; - - return 0; - } - - /* 鍏ㄨ杞崐瑙 */ - ucs4_t ufull2half(ucs4_t uc) - { - if (uc == 0x3000) - return ' '; - - if (uc >= 0xff01 && uc <= 0xff5e) - return uc - 0xfee0; - - return uc; - } - - /* 鍗婅杞叏瑙 */ - ucs4_t uhalf2full(ucs4_t uc) - { - if (uc == ' ') - return 0x3000; - - if (uc >= 0x21 && uc <= 0x7e) - return uc + 0xfee0; - - return uc; - } - - /* 涓棩闊╄秺缁熶竴琛ㄦ剰鏂囧瓧 */ - int isuchiness(ucs4_t uc) - { - /* 鏈鍒濇湡缁熶竴姹夊瓧 */ - if (uc >= 0x4e00 && uc <= 0x9fcc) - return 1; - - /* 鎵╁睍 A 鍖 */ - if (uc >= 0x3400 && uc <= 0x4db5) - return 2; - - /* 鎵╁睍 B 鍖 */ - if (uc >= 0x20000 && uc <= 0x2a6d6) - return 3; - - /* 鎵╁睍 C 鍖 */ - if (uc >= 0x2a700 && uc <= 0x2b734) - return 4; - - /* 鎵╁睍 D 鍖 */ - if (uc >= 0x2b740 && uc <= 0x2b81f) - return 5; - - /* 鎵╁睍 E 鍖 */ - if (uc >= 0x2b820 && uc <= 0x2f7ff) - return 6; - - /* 鍙版咕鍏煎姹夊瓧 */ - if (uc >= 0x2f800 && uc <= 0x2fa1d) - return 7; - - /* 鍖楁湞椴滃吋瀹规眽瀛 */ - if (uc >= 0xfa70 && uc <= 0xfad9) - return 8; - - /* 鍏煎姹夊瓧 */ - if (uc >= 0xf900 && uc <= 0xfa2d) - return 9; - - /* 鍏煎姹夊瓧 */ - if (uc >= 0xfa30 && uc <= 0xfa6d) - return 10; - - return 0; - } - - /* 涓枃鏍囩偣 */ - int isuzhpunct(ucs4_t uc) - { - if (uc >= 0x3001 && uc <= 0x3002) - return 1; - - if (uc >= 0x3008 && uc <= 0x300f) - return 1; - - if (uc >= 0xff01 && uc <= 0xff0f) - return 1; - - if (uc >= 0xff1a && uc <= 0xff20) - return 1; - - if (uc >= 0xff3b && uc <= 0xff40) - return 1; - - if (uc >= 0xff5b && uc <= 0xff5e) - return 1; - - if (uc >= 0x2012 && uc <= 0x201f) - return 1; - - if (uc >= 0xfe41 && uc <= 0xfe44) - return 1; - - if (uc >= 0xfe49 && uc <= 0xfe4f) - return 1; - - if (uc >= 0x3010 && uc <= 0x3017) - return 1; - - return 0; - } - - /* 鏃ユ枃骞冲亣鍚 */ - int isuhiragana(ucs4_t uc) - { - if (uc >= 0x3040 && uc <= 0x309f) - return 1; - - return 0; - } - - /* 鏃ユ枃鐗囧亣鍚 */ - int isukatakana(ucs4_t uc) - { - if (uc >= 0x30a0 && uc <= 0x30ff) - return 1; - - if (uc >= 0x31f0 && uc <= 0x31ff) - return 2; - - return 0; - } - - /* 闊╂枃 */ - int isukorean(ucs4_t uc) - { - /* 闊╂枃鎷奸煶 */ - if (uc >= 0xac00 && uc <= 0xd7af) - return 1; - - /* 闊╂枃瀛楁瘝 */ - if (uc >= 0x1100 && uc <= 0x11ff) - return 2; - - /* 闊╂枃鍏煎瀛楁瘝 */ - if (uc >= 0x3130 && uc <= 0x318f) - return 3; - - return 0; - } - -} diff --git a/Runtime/GUI/utf8_decode.cpp b/Runtime/GUI/utf8_decode.cpp new file mode 100644 index 0000000..8a3a086 --- /dev/null +++ b/Runtime/GUI/utf8_decode.cpp @@ -0,0 +1,415 @@ +/* + * Description: UTF-8 瀛楃涓茬殑瑙g爜鍜岀紪鐮佸嚱鏁 + * unicode 瀛楃澶勭悊鍑芥暟 + * History: yang@haipo.me, 2013/05/29, create + * + * This code is in the public domain. + * You may use this code any way you wish, private, educational, + * or commercial. It's free. + */ + +# include +# include + +# include "utf8.h" + +namespace utf8 +{ + + ucs4_t getu8c(char **src, int *illegal) + { + static char umap[256] = { 0 }; + static int umap_init_flag = 0; + + if (umap_init_flag == 0) + { + int i; + + for (i = 0; i < 0x100; ++i) + { + if (i < 0x80) + { + umap[i] = 1; + } + else if (i >= 0xc0 && i < 0xe0) + { + umap[i] = 2; + } + else if (i >= 0xe0 && i < 0xf0) + { + umap[i] = 3; + } + else if (i >= 0xf0 && i < 0xf8) + { + umap[i] = 4; + } + else if (i >= 0xf8 && i < 0xfc) + { + umap[i] = 5; + } + else if (i >= 0xfc && i < 0xfe) + { + umap[i] = 6; + } + else + { + umap[i] = 0; + } + } + + umap_init_flag = 1; + } + + uint8_t *s = (uint8_t *)(*src); + int r_illegal = 0; + + while (umap[*s] == 0) + { + ++s; + ++r_illegal; + } + + uint8_t *t; + int byte_num; + uint32_t uc; + int i; + + repeat_label: + t = s; + byte_num = umap[*s]; + uc = *s++ & (0xff >> byte_num); + + for (i = 1; i < byte_num; ++i) + { + if (umap[*s]) + { + r_illegal += s - t; + goto repeat_label; + } + else + { + uc = (uc << 6) + (*s & 0x3f); + s += 1; + } + } + + *src = (char *)s; + if (illegal) + { + *illegal = r_illegal; + } + + return uc; + } + + size_t u8decode(char const *str, ucs4_t *des, size_t n, int *illegal) + { + if (n == 0) + return 0; + + char *s = (char *)str; + size_t i = 0; + ucs4_t uc = 0; + int r_illegal_all = 0, r_illegal; + + while ((uc = getu8c(&s, &r_illegal))) + { + if (i < (n - 1)) + { + des[i++] = uc; + r_illegal_all += r_illegal; + } + else + { + break; + } + } + + des[i] = 0; + if (illegal) + { + *illegal = r_illegal_all + r_illegal; + } + + return i; + } + +# define IF_CAN_HOLD(left, n) do { \ + size_t m = (size_t)(n); \ + if ((size_t)(left) < (m + 1)) return -2; \ + (left) -= m; \ +} while (0) + + int putu8c(ucs4_t uc, char **des, size_t *left) + { + if (uc < 0) + return -1; + + if (uc < (0x1 << 7)) + { + IF_CAN_HOLD(*left, 1); + + **des = (char)uc; + *des += 1; + **des = 0; + + return 1; + } + + int byte_num; + + if (uc < (0x1 << 11)) + { + byte_num = 2; + } + else if (uc < (0x1 << 16)) + { + byte_num = 3; + } + else if (uc < (0x1 << 21)) + { + byte_num = 4; + } + else if (uc < (0x1 << 26)) + { + byte_num = 5; + } + else + { + byte_num = 6; + } + + IF_CAN_HOLD(*left, byte_num); + + int i; + for (i = byte_num - 1; i > 0; --i) + { + *(uint8_t *)(*des + i) = (uc & 0x3f) | 0x80; + uc >>= 6; + } + + *(uint8_t *)(*des) = uc | (0xff << (8 - byte_num)); + + *des += byte_num; + **des = 0; + + return byte_num; + } + + size_t u8encode(ucs4_t *us, char *des, size_t n, int *illegal) + { + if (n == 0) + return 0; + + char *s = des; + size_t left = n; + size_t len = 0; + int r_illegal = 0; + + *s = 0; + while (*us) + { + int ret = putu8c(*us, &s, &left); + if (ret > 0) + { + len += ret; + } + else if (ret == -1) + { + r_illegal += 1; + } + else + { + break; + } + + ++us; + } + + if (illegal) + { + *illegal = r_illegal; + } + + return len; + } + + /* 鍏ㄨ瀛楃 */ + int isufullwidth(ucs4_t uc) + { + if (uc == 0x3000) + return 1; + + if (uc >= 0xff01 && uc <= 0xff5e) + return 1; + + return 0; + } + + /* 鍏ㄨ瀛楁瘝 */ + int isufullwidthalpha(ucs4_t uc) + { + if (uc >= 0xff21 && uc <= 0xff3a) + return 1; + + if (uc >= 0xff41 && uc <= 0xff5a) + return 2; + + return 0; + } + + /* 鍏ㄨ鏁板瓧 */ + int isufullwidthdigit(ucs4_t uc) + { + if (uc >= 0xff10 && uc <= 0xff19) + return 1; + + return 0; + } + + /* 鍏ㄨ杞崐瑙 */ + ucs4_t ufull2half(ucs4_t uc) + { + if (uc == 0x3000) + return ' '; + + if (uc >= 0xff01 && uc <= 0xff5e) + return uc - 0xfee0; + + return uc; + } + + /* 鍗婅杞叏瑙 */ + ucs4_t uhalf2full(ucs4_t uc) + { + if (uc == ' ') + return 0x3000; + + if (uc >= 0x21 && uc <= 0x7e) + return uc + 0xfee0; + + return uc; + } + + /* 涓棩闊╄秺缁熶竴琛ㄦ剰鏂囧瓧 */ + int isuchiness(ucs4_t uc) + { + /* 鏈鍒濇湡缁熶竴姹夊瓧 */ + if (uc >= 0x4e00 && uc <= 0x9fcc) + return 1; + + /* 鎵╁睍 A 鍖 */ + if (uc >= 0x3400 && uc <= 0x4db5) + return 2; + + /* 鎵╁睍 B 鍖 */ + if (uc >= 0x20000 && uc <= 0x2a6d6) + return 3; + + /* 鎵╁睍 C 鍖 */ + if (uc >= 0x2a700 && uc <= 0x2b734) + return 4; + + /* 鎵╁睍 D 鍖 */ + if (uc >= 0x2b740 && uc <= 0x2b81f) + return 5; + + /* 鎵╁睍 E 鍖 */ + if (uc >= 0x2b820 && uc <= 0x2f7ff) + return 6; + + /* 鍙版咕鍏煎姹夊瓧 */ + if (uc >= 0x2f800 && uc <= 0x2fa1d) + return 7; + + /* 鍖楁湞椴滃吋瀹规眽瀛 */ + if (uc >= 0xfa70 && uc <= 0xfad9) + return 8; + + /* 鍏煎姹夊瓧 */ + if (uc >= 0xf900 && uc <= 0xfa2d) + return 9; + + /* 鍏煎姹夊瓧 */ + if (uc >= 0xfa30 && uc <= 0xfa6d) + return 10; + + return 0; + } + + /* 涓枃鏍囩偣 */ + int isuzhpunct(ucs4_t uc) + { + if (uc >= 0x3001 && uc <= 0x3002) + return 1; + + if (uc >= 0x3008 && uc <= 0x300f) + return 1; + + if (uc >= 0xff01 && uc <= 0xff0f) + return 1; + + if (uc >= 0xff1a && uc <= 0xff20) + return 1; + + if (uc >= 0xff3b && uc <= 0xff40) + return 1; + + if (uc >= 0xff5b && uc <= 0xff5e) + return 1; + + if (uc >= 0x2012 && uc <= 0x201f) + return 1; + + if (uc >= 0xfe41 && uc <= 0xfe44) + return 1; + + if (uc >= 0xfe49 && uc <= 0xfe4f) + return 1; + + if (uc >= 0x3010 && uc <= 0x3017) + return 1; + + return 0; + } + + /* 鏃ユ枃骞冲亣鍚 */ + int isuhiragana(ucs4_t uc) + { + if (uc >= 0x3040 && uc <= 0x309f) + return 1; + + return 0; + } + + /* 鏃ユ枃鐗囧亣鍚 */ + int isukatakana(ucs4_t uc) + { + if (uc >= 0x30a0 && uc <= 0x30ff) + return 1; + + if (uc >= 0x31f0 && uc <= 0x31ff) + return 2; + + return 0; + } + + /* 闊╂枃 */ + int isukorean(ucs4_t uc) + { + /* 闊╂枃鎷奸煶 */ + if (uc >= 0xac00 && uc <= 0xd7af) + return 1; + + /* 闊╂枃瀛楁瘝 */ + if (uc >= 0x1100 && uc <= 0x11ff) + return 2; + + /* 闊╂枃鍏煎瀛楁瘝 */ + if (uc >= 0x3130 && uc <= 0x318f) + return 3; + + return 0; + } + +} diff --git a/Runtime/Graphics/Color.h b/Runtime/Graphics/Color.h index af8d3ba..ebccafe 100644 --- a/Runtime/Graphics/Color.h +++ b/Runtime/Graphics/Color.h @@ -14,12 +14,26 @@ namespace Internal this->b = b; this->a = a; } + void Set(float r = 0, float g = 0, float b = 0, float a = 0) + { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + } float r, g, b, a; }; struct Color32 { Color32(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 0) + { + this->r = r; + this->g = g; + this->b = b; + this->a = a; + } + void Set(unsigned char r = 0, unsigned char g = 0, unsigned char b = 0, unsigned char a = 0) { this->r = r; this->g = g; diff --git a/Runtime/Graphics/DynamicVertexBuffer.cpp b/Runtime/Graphics/DynamicVertexBuffer.cpp index 203aa26..cb59a8b 100644 --- a/Runtime/Graphics/DynamicVertexBuffer.cpp +++ b/Runtime/Graphics/DynamicVertexBuffer.cpp @@ -1,4 +1,5 @@ #include "DynamicVertexBuffer.h" +#include "CustomVertexLayout.h" #include "../Profiling/FrameStats.h" DynamicVertexBuffer::DynamicVertexBuffer() @@ -109,11 +110,12 @@ void DynamicVertexBuffer::GetChunk(uint sizePerVert, uint sizePerIndex, int maxV { Assert(out_vb && out_ib); + m_CurStride = sizePerVert; uint vbufferSize = sizePerVert * maxVerts; uint ibufferSize = sizePerIndex * maxIndices; - const bool mapVertexBuffer = vbufferSize >= DataBufferThreshold; - const bool mapIndexBuffer = ibufferSize >= DataBufferThreshold; + const bool mapVertexBuffer = vbufferSize >= kDataBufferThreshold; + const bool mapIndexBuffer = ibufferSize >= kDataBufferThreshold; GLenum usage = GL_STREAM_DRAW; @@ -221,7 +223,7 @@ void DynamicVertexBuffer::ReleaseChunk(int actualVerts, int actualIndices) m_CurVB->FlushMapedRange(0, actualVBufferSize); m_CurVB->UnMap(); } - else if (actualVBufferSize >= DataBufferThreshold) + else if (actualVBufferSize >= kDataBufferThreshold) { m_CurVB = GPU::ClaimBuffer(actualVBufferSize, usage); m_CurVB->RestoreWithData(actualVBufferSize, usage, &m_CurVBData[0]); @@ -232,7 +234,7 @@ void DynamicVertexBuffer::ReleaseChunk(int actualVerts, int actualIndices) m_CurIB->FlushMapedRange(0, actualIBufferSize); m_CurIB->UnMap(); } - else if (actualIBufferSize >= DataBufferThreshold) + else if (actualIBufferSize >= kDataBufferThreshold) { m_CurIB = GPU::ClaimBuffer(0, usage); m_CurIB->RestoreWithData(0, usage, &m_CurIBData[0]); diff --git a/Runtime/Graphics/DynamicVertexBuffer.h b/Runtime/Graphics/DynamicVertexBuffer.h index 12aa48c..6f21010 100644 --- a/Runtime/Graphics/DynamicVertexBuffer.h +++ b/Runtime/Graphics/DynamicVertexBuffer.h @@ -35,8 +35,8 @@ private: void Clean(); - // 如果数据大小超过这个限制,用内存数据,而不是glBufferData - enum { DataBufferThreshold = 1024 }; + // 如果数据大小小于这个限制,用内存数据,而不是glBufferData + static const int kDataBufferThreshold = 1024; GPU::DataBuffer *m_CurVB; GPU::DataBuffer *m_CurIB; @@ -52,4 +52,4 @@ private: uint m_CurVertexCount; uint m_CurIndexCount; -}; +}; \ No newline at end of file diff --git a/Runtime/Graphics/GPUDataBuffer.h b/Runtime/Graphics/GPUDataBuffer.h index f66d951..3d24514 100644 --- a/Runtime/Graphics/GPUDataBuffer.h +++ b/Runtime/Graphics/GPUDataBuffer.h @@ -15,6 +15,9 @@ namespace GPU class DataBuffer { public: + DataBuffer(); + ~DataBuffer(); + void Upload(int offset, int size, const void* data); void* Map(uint32 access); void* MapRange(int offset, int size, uint32 access); // 性能最佳 @@ -34,9 +37,6 @@ namespace GPU private: friend class BufferPool; - DataBuffer(); - ~DataBuffer(); - GLuint m_Handle; int m_Size; GLenum m_Usage; diff --git a/Runtime/Graphics/GfxDevice.cpp b/Runtime/Graphics/GfxDevice.cpp index 9abea12..2c740ed 100644 --- a/Runtime/Graphics/GfxDevice.cpp +++ b/Runtime/Graphics/GfxDevice.cpp @@ -137,8 +137,7 @@ void GfxDevice::SetUniformTexture(const char* name, Texture* texture) int texUnit = s_TextureUnitBucket.back(); s_TextureUnitBucket.pop_back(); glActiveTexture(GL_TEXTURE0 + texUnit); - //glBindTexture(GL_TEXTURE_2D, texture->GetGpuID()); - glBindTexture(GL_TEXTURE_2D, 2); + glBindTexture(GL_TEXTURE_2D, texture->GetGpuID()); GLint loc = glGetUniformLocation(m_Shader.GetID(), name); glUniform1i(loc, texUnit); diff --git a/Runtime/Graphics/OpenGL.h b/Runtime/Graphics/OpenGL.h index b1b777e..d93fb5a 100644 --- a/Runtime/Graphics/OpenGL.h +++ b/Runtime/Graphics/OpenGL.h @@ -15,6 +15,14 @@ if(true){ \ } \ } +#define WipeGLError() \ +if(true){\ + GLenum error; \ + while ((error = glGetError()) != GL_NO_ERROR) { \ + throw GLException(error); \ + } \ +} + extern std::string g_sharedGLErrorMsg; class GLException : public std::exception diff --git a/Runtime/Graphics/Shader.cpp b/Runtime/Graphics/Shader.cpp index 60e165f..013b1ba 100644 --- a/Runtime/Graphics/Shader.cpp +++ b/Runtime/Graphics/Shader.cpp @@ -88,7 +88,7 @@ void Shader::CompileProgram(const char* vert, const char* frag, bool keepSrc) glAttachShader(m_ProgramID, m_VertID); glAttachShader(m_ProgramID, m_FragID); glLinkProgram(m_ProgramID); - checkCompileshaderErrorors(m_FragID, "PROGRAM"); + checkCompileshaderErrorors(m_ProgramID, "PROGRAM"); } Shader::~Shader() diff --git a/Runtime/Graphics/Texture.cpp b/Runtime/Graphics/Texture.cpp index eed0b90..a1f4181 100644 --- a/Runtime/Graphics/Texture.cpp +++ b/Runtime/Graphics/Texture.cpp @@ -106,6 +106,8 @@ Texture::Texture(TextureSetting setting, int w, int h) m_FilterMode = setting.filterMode; m_KeepPixelData = setting.keepImageData; + WipeGLError(); + glGenTextures(1, &m_GPUID); glBindTexture(GL_TEXTURE_2D, m_GPUID); @@ -170,6 +172,8 @@ Texture::Texture(TextureSetting setting, int w, int h) glBindTexture(GL_TEXTURE_2D, 0); throw TextureException(error); ); + + glBindTexture(GL_TEXTURE_2D, 0); } Texture::~Texture() diff --git a/Runtime/Graphics/VertexBuffer.cpp b/Runtime/Graphics/VertexBuffer.cpp index 5d136ee..16b29d5 100644 --- a/Runtime/Graphics/VertexBuffer.cpp +++ b/Runtime/Graphics/VertexBuffer.cpp @@ -3,8 +3,10 @@ VertexBuffer::VertexBuffer(int vbSize, int ibSize, VertexBufferType type) { - m_VB = GPU::ClaimBuffer(vbSize, GL_ARRAY_BUFFER); - m_IB = GPU::ClaimBuffer(ibSize, GL_ELEMENT_ARRAY_BUFFER); + m_VB = new GPU::DataBuffer(); + m_IB = new GPU::DataBuffer(); + //m_VB = GPU::ClaimBuffer(vbSize, GL_STATIC_DRAW); + //m_IB = GPU::ClaimBuffer(ibSize, GL_STATIC_DRAW); } VertexBuffer::~VertexBuffer() @@ -12,3 +14,104 @@ VertexBuffer::~VertexBuffer() GPU::ReleaseBuffer(m_VB); GPU::ReleaseBuffer(m_IB); } +// GetChunk +// +// FlushChunk +// DrawChunk +void VertexBuffer::GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib) +{ + m_SizePerVertex = sizePerVert; + + uint vbufferSize = sizePerVert * maxVerts; + uint ibufferSize = sizePerIndex * maxIndices; + + GLenum usage = GL_STATIC_DRAW; + m_VB->Restore(vbufferSize, usage); + m_IB->Restore(ibufferSize, usage); + + const GLenum access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT; + + *out_vb = m_VB->MapRange(0, vbufferSize, access); + *out_ib = m_IB->MapRange(0, ibufferSize, access); + + m_Primitive = primitive; + + WipeGLError(); +} + +void VertexBuffer::FlushChunk(int actualVerts, int actualIndices) +{ + int actualVBufferSize = m_SizePerVertex * actualVerts; + int actualIBufferSize = VertexLayout::GetDefaultIndexSize() * actualIndices; + + m_CurIndexCount = actualIndices; + + m_VB->FlushMapedRange(0, actualVBufferSize); + m_IB->FlushMapedRange(0, actualIBufferSize); + + // 一定要unmap + m_VB->UnMap(); + m_IB->UnMap(); + + WipeGLError(); +} + +void VertexBuffer::Draw(CustomVertexLayout& layout) +{ + const byte* basepointer = 0; + const GLuint buffer = m_VB->GetHandle(); + + FillCustomVertexLayout(layout); + + VertexLayout::SetupCustomVertexLayout(layout); + + layout.RestorePointer(); + + const void* indexPtr = 0; + + CheckGLError( + throw GLException(error); + ); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IB->GetHandle()); + + CheckGLError( + throw GLException(error); + ); + GLenum indexFormat = VertexLayout::GetDefaultIndexFormat(); + + switch (m_Primitive) + { + case Primitive_Triangle: + glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + g_FrameStats.AddTrianglesCount(m_CurIndexCount / 3); + break; + case Primitive_Line: + glDrawElements(GL_LINE, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + case Primitive_Point: + glDrawElements(GL_POINT, m_CurIndexCount, indexFormat, indexPtr); + g_FrameStats.AddDrawCall(); + break; + } + + CheckGLError( + throw GLException(error); + ); + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); +} + +void VertexBuffer::FillCustomVertexLayout(CustomVertexLayout& dst) +{ + const byte* basepointer = 0; + const GLuint buffer = m_VB->GetHandle(); + + dst.buffer = buffer; + + for (int i = 0; i < dst.attributes.size(); ++i) + { + int offset = dst.attributes[i].startOffset; + dst.attributes[i].pointer = basepointer + offset; + } +} \ No newline at end of file diff --git a/Runtime/Graphics/VertexBuffer.h b/Runtime/Graphics/VertexBuffer.h index c651bdb..2d3a9f5 100644 --- a/Runtime/Graphics/VertexBuffer.h +++ b/Runtime/Graphics/VertexBuffer.h @@ -26,16 +26,28 @@ public: VertexBuffer(int vbSize, int ibSize, VertexBufferType type); ~VertexBuffer(); + // 填充数据 + void GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib); + // 提交数据 + void FlushChunk(int actualVerts, int actualIndices); + GET(GPU::DataBuffer*, VB, m_VB); + GET(GPU::DataBuffer*, IB, m_IB); - void Draw(); + void Draw(CustomVertexLayout& layout); private: + void FillCustomVertexLayout(CustomVertexLayout& dst); + VertexBufferType m_Type; GPU::DataBuffer* m_VB; GPU::DataBuffer* m_IB; + int m_SizePerVertex; + + int m_CurIndexCount; + EPrimitive m_Primitive; }; diff --git a/Runtime/Lua/LuaBind/LuaBindUtility.h b/Runtime/Lua/LuaBind/LuaBindUtility.h index 6d04272..e88dd68 100644 --- a/Runtime/Lua/LuaBind/LuaBindUtility.h +++ b/Runtime/Lua/LuaBind/LuaBindUtility.h @@ -3,9 +3,8 @@ // 导出native接口 -// RegisterClass 注册类的方法和成员,比如枚举、常量等到class table GetNativeClassName 获得工厂的类名, +// RegisterNativeClass 注册类的方法和成员,比如枚举、常量等到class table GetNativeClassName 获得工厂的类名, // 同时用来避免注册时错误注册为了singleton,通过编译时报错避免 -// RegisterClass和win32的宏冲突,所以加个下划线 #define LUA_BIND_DECL_CLASS(type, ...) \ friend class LuaBind::State; \ friend class LuaBind::NativeClass; \ diff --git a/Runtime/Scripting/GUI/Font.bind.cpp b/Runtime/Scripting/GUI/Font.bind.cpp index 8259a60..733fcf1 100644 --- a/Runtime/Scripting/GUI/Font.bind.cpp +++ b/Runtime/Scripting/GUI/Font.bind.cpp @@ -5,6 +5,7 @@ #include "Runtime/Common/DataBuffer.h" #include "Runtime/GUI/utf8.h" #include "Runtime/Utilities/StaticInitiator.h" +#include "Runtime/GUI/TextMesh.h" static std::vector* s_Codepoints; @@ -127,6 +128,15 @@ LUA_BIND_IMPL_METHOD(Font, _GetCharacters) self->RenderCharacters(*s_Codepoints, size); + UnicodeString str; + str.str = s_Codepoints->data(); + str.length = s_Codepoints->size(); + + WipeGLError(); + + TextMesh* tm = new TextMesh(str, self, size, ETextAnchor::TextAnchor_MiddleLeft, ETextAlignment::TextAlignment_Left); + tm->Draw(); + return 0; } diff --git a/Runtime/Scripting/Rendering/Shader.bind.cpp b/Runtime/Scripting/Rendering/Shader.bind.cpp index 482efb9..08c96f9 100644 --- a/Runtime/Scripting/Rendering/Shader.bind.cpp +++ b/Runtime/Scripting/Rendering/Shader.bind.cpp @@ -63,7 +63,8 @@ LUA_BIND_IMPL_METHOD(Shader, _New) if (shader != NULL) shader->PushUserdata(state); else - state.PushNil(); + state.PushNil(); + return 1; } catch (ShaderCompileExecption e) @@ -72,6 +73,7 @@ LUA_BIND_IMPL_METHOD(Shader, _New) state.PushNil(); return 1; } + Assert(false); return 0; } -- cgit v1.1-26-g67d0