summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchai <chaifix@163.com>2021-10-30 22:59:42 +0800
committerchai <chaifix@163.com>2021-10-30 22:59:42 +0800
commit26f05c6e3dcac9995345fb5a2b031be7e3ea79e9 (patch)
treefc32c3e9d235817df0be331a6100b7f8263facab
parentc3e259f4d29e9bdcb73617ad8e4d71f117b4d289 (diff)
*TextGenerator
-rw-r--r--Data/Editor.exebin0 -> 2385408 bytes
-rw-r--r--Data/Resources/Font/Deng.ttfbin0 -> 16093132 bytes
-rw-r--r--Data/Scripts/Editor/AssetBrowser.lua9
-rw-r--r--Data/Scripts/EditorApplication.lua2
-rw-r--r--Editor/EditorMain.cpp28
-rw-r--r--Editor/GUI/ContainerWindow.cpp19
-rw-r--r--Editor/GUI/EditorWindows.h4
-rw-r--r--Editor/GUI/GUIWindow.cpp18
-rw-r--r--Editor/Graphics/Graphics.cpp2
-rw-r--r--Editor/Graphics/Graphics.h2
-rw-r--r--Runtime/Common/DataBuffer.h2
-rw-r--r--Runtime/FileSystem/ImageJobs.cpp4
-rw-r--r--Runtime/GUI/TextGenerator.cpp205
-rw-r--r--Runtime/GUI/TextGenerator.h89
-rw-r--r--Runtime/Graphics/GfxDevice.cpp6
-rw-r--r--Runtime/Graphics/ImageData.h38
-rw-r--r--Runtime/Graphics/Texture.cpp118
-rw-r--r--Runtime/Graphics/Texture.h3
-rw-r--r--Runtime/Math/Math.h4
-rw-r--r--Runtime/Math/Rect.h2
-rw-r--r--Runtime/Scripting/Resource/Resource.bind.cpp4
21 files changed, 481 insertions, 78 deletions
diff --git a/Data/Editor.exe b/Data/Editor.exe
new file mode 100644
index 0000000..e59406e
--- /dev/null
+++ b/Data/Editor.exe
Binary files differ
diff --git a/Data/Resources/Font/Deng.ttf b/Data/Resources/Font/Deng.ttf
new file mode 100644
index 0000000..7438a2a
--- /dev/null
+++ b/Data/Resources/Font/Deng.ttf
Binary files differ
diff --git a/Data/Scripts/Editor/AssetBrowser.lua b/Data/Scripts/Editor/AssetBrowser.lua
index a36cda2..68f0483 100644
--- a/Data/Scripts/Editor/AssetBrowser.lua
+++ b/Data/Scripts/Editor/AssetBrowser.lua
@@ -42,7 +42,11 @@ out vec4 FragColor;
void main()
{
- FragColor = texture(uiTex, uv);
+ vec4 sampled = vec4(texture(uiTex, uv).r, 0, 0, 1.0);
+ FragColor = sampled;
+// FragColor = texture(uiTex, uv);
+// FragColor.rgb = vec3(1,0,0);
+// FragColor.a = 1;
}
FSH_END
@@ -52,6 +56,7 @@ local tex
AssetBrowser.OnGUI = function(self)
+
if tex == nil then
tex = Engine.Resource.LoadTexture("./Resources/Images/brickwall.jpg")
end
@@ -76,7 +81,7 @@ AssetBrowser.OnGUI = function(self)
Engine.Rendering.UseShader(shader)
Engine.Rendering.SetMatrix44("mvp", ortho)
- Engine.Rendering.SetTexture("tex", tex)
+ Engine.Rendering.SetTexture("uiTex", tex)
Engine.Rendering.DrawUIQuad({10, 30, 300, 300})
Engine.Rendering.ResetUniformState()
diff --git a/Data/Scripts/EditorApplication.lua b/Data/Scripts/EditorApplication.lua
index 75749df..e9dbc32 100644
--- a/Data/Scripts/EditorApplication.lua
+++ b/Data/Scripts/EditorApplication.lua
@@ -111,6 +111,8 @@ local fsh = [[
}
]]
+BeforeMainLoop()
+
while true do
app:OnStep()
diff --git a/Editor/EditorMain.cpp b/Editor/EditorMain.cpp
index 69c1c1a..e31da28 100644
--- a/Editor/EditorMain.cpp
+++ b/Editor/EditorMain.cpp
@@ -9,6 +9,8 @@
#include "Editor/Win/Win.h"
#include "Runtime/Threading/Thread.h"
+#include "Runtime/GUI/TextGenerator.h"
+
using namespace LuaBind;
void ErrorHandle(cc8* msg)
@@ -16,6 +18,27 @@ void ErrorHandle(cc8* msg)
log_error(std::string("[Lua] ") + msg);
}
+void TestFont()
+{
+ TextGeneratingSettings setting;
+ setting.margin = 5;
+ setting.padding = 3;
+ setting.atlasSize = Internal::Vector2(256, 256);
+ TextGenerator::Instance()->Setup(setting);
+ TextGenerator::Instance()->RenderCharacter(L'好', 14);
+ TextGenerator::Instance()->RenderCharacter(L'大', 14);
+ TextGenerator::Instance()->RenderCharacter(L'家', 14);
+ TextGenerator::Instance()->RenderCharacter(L'晚', 14);
+ TextGenerator::Instance()->RenderCharacter(L'上', 14);
+ TextGenerator::Instance()->RenderCharacter(L'快', 14);
+}
+
+int BeforeMainLoop(lua_State* L)
+{
+ TestFont();
+ return 0;
+}
+
void InitLuaState(LuaBind::VM& vm)
{
vm.Setup();
@@ -35,6 +58,9 @@ void InitLuaState(LuaBind::VM& vm)
Win::SetDllSearchDirectory(workingDir);
LuaBind::State state = vm.GetMainState();
+ state.PushGlobalNamespace();
+ state.RegisterMethod("BeforeMainLoop", BeforeMainLoop);
+
state.DoFile("./boot.lua");
}
@@ -50,4 +76,4 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw)
InitLuaState(vm);
return 0;
-} \ No newline at end of file
+}
diff --git a/Editor/GUI/ContainerWindow.cpp b/Editor/GUI/ContainerWindow.cpp
index 62c6cb7..01bb1e9 100644
--- a/Editor/GUI/ContainerWindow.cpp
+++ b/Editor/GUI/ContainerWindow.cpp
@@ -196,8 +196,8 @@ void ContainerWindow::DoPaint()
void ContainerWindow::SetAsRenderContext()
{
Assert(m_DC != NULL);
- Assert(m_RC != NULL);
- Assert(wglMakeCurrent(m_DC, m_RC));
+ Assert(g_GLRC != NULL);
+ Assert(wglMakeCurrent(m_DC, g_GLRC));
RECT rect;
GetWindowRect(m_Window, &rect);
glViewport(0, 0, rect.right - rect.left, rect.bottom - rect.top);
@@ -256,16 +256,15 @@ bool ContainerWindow::SetRenderContext()
int pf = 0;
DescribePixelFormat(m_DC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- if (!(m_RC = wglCreateContext(m_DC))) // Are We Able To Get A Rendering Context?
- {
- MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
- return FALSE; // Return FALSE
- }
-
- if (m_RC && !g_IsGLInitialized)
+ if (g_GLRC == NULL || !g_IsGLInitialized)
{
+ if (!(g_GLRC = wglCreateContext(m_DC))) // Are We Able To Get A Rendering Context?
+ {
+ MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
+ return FALSE; // Return FALSE
+ }
log_info("Initialize OpenGL");
- wglMakeCurrent(m_DC, m_RC);
+ wglMakeCurrent(m_DC, g_GLRC);
if (!gladLoadGL()) {
log_error("初始化GL错误");
}
diff --git a/Editor/GUI/EditorWindows.h b/Editor/GUI/EditorWindows.h
index 79e047c..e1ad89a 100644
--- a/Editor/GUI/EditorWindows.h
+++ b/Editor/GUI/EditorWindows.h
@@ -67,7 +67,6 @@ public:
GET(HWND, WindowHandle, m_Window);
GET(HDC, DC, m_DC);
- GET(HGLRC, RC, m_RC);
void OnRectChanged();
void OnActivateApplication(bool active);
@@ -79,7 +78,6 @@ private:
HWND m_Window;
HDC m_DC;
- HGLRC m_RC;
POINT m_Size;
ShowMode m_ShowMode; // 窗口类型
bool m_IsClosing;
@@ -149,7 +147,6 @@ public:
GET_SET(std::string, Name, m_Name);
GET(HDC, DC, m_DC);
- GET(HGLRC, RC, m_RC);
private:
void ProcessEventMessages(UINT message, WPARAM wParam, LPARAM lParam);
@@ -160,7 +157,6 @@ private:
ContainerWindow* m_ContainerWindow;
HWND m_Handle;
HDC m_DC;
- HGLRC m_RC;
std::vector<LuaBind::MemberRef> m_EditorWindows;
diff --git a/Editor/GUI/GUIWindow.cpp b/Editor/GUI/GUIWindow.cpp
index fddc68d..eb44647 100644
--- a/Editor/GUI/GUIWindow.cpp
+++ b/Editor/GUI/GUIWindow.cpp
@@ -293,21 +293,6 @@ bool GUIWindow::SetRenderContext()
int pf = 0;
DescribePixelFormat(m_DC, pf, sizeof(PIXELFORMATDESCRIPTOR), &pfd);
- if (!(m_RC = wglCreateContext(m_DC))) // Are We Able To Get A Rendering Context?
- {
- MessageBox(NULL, "Can't Create A GL Rendering Context.", "ERROR", MB_OK | MB_ICONEXCLAMATION);
- return FALSE; // Return FALSE
- }
-
- if (m_RC && !g_IsGLInitialized)
- {
- log_info("Initialize OpenGL");
- wglMakeCurrent(m_DC, m_RC);
- if (!gladLoadGL()) {
- log_error("初始化GL错误");
- }
- g_IsGLInitialized = true;
- }
return true;
}
@@ -345,8 +330,7 @@ void GUIWindow::SetPosition(Internal::Rect position)
void GUIWindow::SetAsRenderContext()
{
Assert(m_DC != NULL);
- Assert(m_RC != NULL);
- Assert(wglMakeCurrent(m_DC, m_RC));
+ Assert(wglMakeCurrent(m_DC, g_GLRC));
RECT rect;
GetWindowRect(m_Handle, &rect);
glViewport(0, 0, rect.right - rect.left, rect.bottom - rect.top);
diff --git a/Editor/Graphics/Graphics.cpp b/Editor/Graphics/Graphics.cpp
index af48d75..4c9465f 100644
--- a/Editor/Graphics/Graphics.cpp
+++ b/Editor/Graphics/Graphics.cpp
@@ -1,3 +1,5 @@
#include "Graphics.h"
bool g_IsGLInitialized = false;
+
+HGLRC g_GLRC = NULL; \ No newline at end of file
diff --git a/Editor/Graphics/Graphics.h b/Editor/Graphics/Graphics.h
index ad27ede..f32246a 100644
--- a/Editor/Graphics/Graphics.h
+++ b/Editor/Graphics/Graphics.h
@@ -1,3 +1,5 @@
#pragma once
+#include <windows.h>
extern bool g_IsGLInitialized;
+extern HGLRC g_GLRC; \ No newline at end of file
diff --git a/Runtime/Common/DataBuffer.h b/Runtime/Common/DataBuffer.h
index 74d2b02..7004937 100644
--- a/Runtime/Common/DataBuffer.h
+++ b/Runtime/Common/DataBuffer.h
@@ -17,7 +17,7 @@ public:
delete data;
}
- char* data;
+ unsigned char* data;
int length;
private:
diff --git a/Runtime/FileSystem/ImageJobs.cpp b/Runtime/FileSystem/ImageJobs.cpp
index 84e4ff3..1d836d2 100644
--- a/Runtime/FileSystem/ImageJobs.cpp
+++ b/Runtime/FileSystem/ImageJobs.cpp
@@ -41,8 +41,8 @@ void ReadImageFileJob::Dispacth(void* param)
bridge.pixels = NULL;
imgData->width = bridge.width;
imgData->height = bridge.height;
- imgData->format = ImageData::EPixelFormat::RGB;
- imgData->type = ImageData::EPixelElementType::UNSIGNED_BYTE;
+ imgData->format = EPixelFormat::PixelFormat_RGB;
+ imgData->type = EPixelElementType::PixelType_UNSIGNED_BYTE;
callback.PushRef(state);
imgData->PushUserdata(state);
diff --git a/Runtime/GUI/TextGenerator.cpp b/Runtime/GUI/TextGenerator.cpp
index 6841c4e..a518772 100644
--- a/Runtime/GUI/TextGenerator.cpp
+++ b/Runtime/GUI/TextGenerator.cpp
@@ -1,19 +1,206 @@
#include "freetype.h"
#include "TextGenerator.h"
#include "../Math/Math.h"
+#include "Runtime/Debug/Log.h"
+#include "Runtime/Utilities/Assert.h"
+#include "Runtime/Graphics/ImageData.h"
using namespace character;
+//https://unicode-table.com/en/#cjk-unified-ideographs-extension-a
//https://learnopengl.com/In-Practice/Text-Rendering
+//https://www.zhihu.com/question/294660079
+//https://baike.baidu.com/item/%E5%9F%BA%E6%9C%AC%E5%A4%9A%E6%96%87%E7%A7%8D%E5%B9%B3%E9%9D%A2/10788078
+//https://stackoverflow.com/questions/27331819/whats-the-difference-between-a-character-a-code-point-a-glyph-and-a-grapheme
-struct Character {
- unsigned int textureID; // ID handle of the glyph texture
- Internal::Vector2 size; // Size of glyph
- Internal::Vector2 bearing; // Offset from baseline to left/top of glyph
- unsigned int advance; // Offset to advance to next glyph
-};
+void TextGenerator::Setup(TextGeneratingSettings settings)
+{
+ m_AtlasMargin = settings.margin;
+ m_GlyphPadding = settings.padding;
+ m_AtlasSize = settings.atlasSize;
+
+ if (FT_Init_FreeType(&m_FTLibrary))
+ {
+ return;
+ }
+
+ if (FT_New_Face(m_FTLibrary, "Resources/Font/Deng.ttf", 0, &m_FTFace))
+ {
+ return;
+ }
+}
+
+character::Hash TextGenerator::GetHash(Codepoint codepoint, int pixelSize)
+{
+ character::Hash hash;
+ hash.codepoint = codepoint;
+ hash.size = pixelSize;
+ return hash;
+}
+
+Character TextGenerator::GetCharacter(character::Codepoint codepoint, int pixelSize)
+{
+ character::Hash hash = GetHash(codepoint, pixelSize);
+ auto iter = m_Characters.find(hash);
+ if (iter == m_Characters.end())
+ {
+ RenderCharacter(codepoint, pixelSize);
+ iter = m_Characters.find(hash);
+ }
+ Assert(iter != m_Characters.end());
+ return iter->second;
+}
+
+void TextGenerator::RenderCharacter(character::Codepoint codepoint, int pixelSize)
+{
+ character::Hash hash = GetHash(codepoint, pixelSize);
+// if (m_Characters.count(hash) != 0)
+// return;
+ FT_Set_Pixel_Sizes(m_FTFace, 0, pixelSize);
+ if (FT_Load_Char(m_FTFace, codepoint, FT_LOAD_RENDER))
+ {
+ return;
+ }
+
+ int w = m_FTFace->glyph->bitmap.width;
+ int h = m_FTFace->glyph->bitmap.rows;
+
+ TextHelper::print_glyph(m_FTFace->glyph->bitmap.buffer, w, h);
+
+ GlyphAtals* atlas = RequestAtlas(pixelSize, Internal::Vector2(w, h));
+ Assert(atlas);
+
+ Internal::Rect rect = GetRenderChartAndMove(atlas, Internal::Vector2(w, h));
+
+ try
+ {
+ atlas->altas->UpdateSubImage(rect, EPixelFormat::PixelFormat_R, EPixelElementType::PixelType_UNSIGNED_BYTE, m_FTFace->glyph->bitmap.buffer);
+ }
+ catch (TextureException& e)
+ {
+ std::string error = e.what();
+ error = "Render Character Error: " + error;
+ log_error(e.what());
+ return;
+ }
+
+ Character character;
+ character.atlas = atlas->index;
+ character.position = rect;
+ character.bearing = Internal::Vector2(m_FTFace->glyph->bitmap_left, m_FTFace->glyph->bitmap_top);
+ character.advance = m_FTFace->glyph->advance.x;
+
+ m_Characters.insert(std::pair<character::Hash, Character>(hash, character));
+}
+
+GlyphAtals* TextGenerator::GetGlyphAtlas(int index)
+{
+ if (index >= m_Atlases.size())
+ return NULL;
+ return &m_Atlases[index];
+}
+
+Internal::Rect TextGenerator::GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize)
+{
+ Internal::Rect rect;
+ Internal::Vector2 space;
+ space.x = atlas->width - m_AtlasMargin * 2 - m_GlyphPadding - atlas->cursor.x;
+ space.y = atlas->height - m_AtlasMargin * 2 - m_GlyphPadding - atlas->cursor.y;
+ if (space.x > preferSize.x && space.y > preferSize.y)
+ {
+ rect.x = atlas->cursor.x;
+ rect.y = atlas->cursor.y;
+ rect.width = preferSize.x;
+ rect.height = preferSize.y;
+ atlas->cursor.x += rect.width;
+ atlas->rowHeight = max(atlas->rowHeight, preferSize.y);
+ }
+ else if (space.y - atlas->rowHeight > preferSize.y)
+ {
+ rect.x = m_AtlasMargin;
+ rect.y = atlas->cursor.y + m_GlyphPadding + atlas->rowHeight;
+ rect.width = preferSize.x;
+ rect.height = preferSize.y;
+ atlas->cursor.x = m_AtlasMargin;
+ atlas->cursor.y += atlas->rowHeight;
+ atlas->rowHeight = rect.height;
+ }
+ else
+ {
+ Assert(false);
+ }
+ return rect;
+}
+
+GlyphAtals* TextGenerator::RequestAtlas(int pixelSize, Internal::Vector2 preferSize)
+{
+ GlyphAtals* atlas = NULL;
+ auto iter = m_AtlasCache.find(pixelSize);
+ if (iter == m_AtlasCache.end() || !HasEnoughSpace(iter->second, preferSize))
+ {
+ Texture* tex = CreateAtlas();
+ GlyphAtals newAtlas = GlyphAtals();
+ newAtlas.altas = tex;
+ newAtlas.width = m_AtlasSize.x;
+ newAtlas.height = m_AtlasSize.y;
+ newAtlas.index = m_Atlases.size();
+ newAtlas.cursor = Internal::Vector2(m_AtlasMargin, m_AtlasMargin);
+
+ m_Atlases.push_back(newAtlas);
+ atlas = &m_Atlases[m_Atlases.size() - 1];
+
+ if (iter != m_AtlasCache.end())
+ m_AtlasCache.erase(pixelSize);
+ m_AtlasCache.insert(std::pair<int, GlyphAtals*>(pixelSize, atlas));
+ }
+ else
+ {
+ atlas = iter->second;
+ }
+ Assert(atlas);
+ return atlas;
+}
+
+Texture* TextGenerator::CreateAtlas()
+{
+ TextureSetting setting;
+ setting.filterMode = ETextureFilterMode::Linear;
+ setting.wrapMode = ETextureWrapMode::Clamp;
+ setting.format = ETextureFormat::R8;
+ setting.type = ETextureType::TEX_2D;
+ setting.keepImageData = false;
+ Texture* tex = new Texture(setting, m_AtlasSize.x, m_AtlasSize.y);
+ return tex;
+}
+
+bool TextGenerator::HasEnoughSpace(GlyphAtals* atlas, Internal::Vector2 preferSize)
+{
+ if (atlas == NULL)
+ return false;
+ Internal::Vector2 space;
+ space.x = atlas->width - m_AtlasMargin * 2 - m_GlyphPadding - atlas->cursor.x;
+ space.y = atlas->height - m_AtlasMargin * 2 - m_GlyphPadding - atlas->cursor.y;
+ if (space.x > preferSize.x && space.y > preferSize.y)
+ return true;
+ if (space.y - atlas->rowHeight > preferSize.y)
+ return true;
+ return false;
+}
+
+Character GetCharacter(character::Codepoint Codepoint, int pixelSize)
+{
+ return Character();
+}
-hash TextGenerator::GetCharacterHash(unicode unicode, int pixelSize)
+void TextHelper::print_glyph(unsigned char* glyph, int width, int height)
{
-
-} \ No newline at end of file
+ for (int r = 0; r < height; ++r)
+ {
+ for (int c = 0; c < width; ++c)
+ {
+ unsigned char ch = glyph[c + r * width];
+ printf("%c", ch == 0 ? ' ' : '+');
+ }
+ printf("\n");
+ }
+}
diff --git a/Runtime/GUI/TextGenerator.h b/Runtime/GUI/TextGenerator.h
index eacc99c..1065acf 100644
--- a/Runtime/GUI/TextGenerator.h
+++ b/Runtime/GUI/TextGenerator.h
@@ -1,32 +1,105 @@
#pragma once
#include "Runtime/Utilities/Singleton.h"
+#include "Runtime/Graphics/Texture.h"
+#include "freetype.h"
+
#include <string>
#include <unordered_map>
+#include <vector>
//https://learnopengl.com/In-Practice/Text-Rendering
struct Character {
- unsigned int textureID; // ID handle of the glyph texture
- Internal::Vector2 size; // Size of glyph
- Internal::Vector2 bearing; // Offset from baseline to left/top of glyph
- unsigned int advance; // Offset to advance to next glyph
+ unsigned int atlas; // atlas索引
+ Internal::Rect position; // 在altas里的位置
+ Internal::Vector2 bearing; // 左上角相对于原点的偏移
+ unsigned int advance; // 总宽,算上了间隔
};
namespace character
{
- typedef wchar_t unicode;
- typedef unsigned int hash;
+ typedef unsigned short Codepoint; // unicode Codepoint(BMP,U+0000至U+FFFF)
+
+ union Hash {
+ unsigned int hashCode;
+ struct {
+ Codepoint codepoint;
+ unsigned short size;//字体大小
+ };
+ bool operator==(const Hash &other) const
+ {
+ return codepoint == other.codepoint && size == other.size;
+ }
+ };
+}
+
+namespace std
+{
+ template <>
+ struct hash<character::Hash>
+ {
+ std::size_t operator()(const character::Hash& k) const
+ {
+ return k.hashCode;
+ }
+ };
}
+struct GlyphAtals
+{
+ int index;
+ Texture* altas; // 贴图
+ int width, height; // 尺寸
+ Internal::Vector2 cursor; // 游标,从左上角(0,0)开始
+ int rowHeight; // 当前行的高度
+};
+
+struct TextGeneratingSettings
+{
+ Internal::Vector2 atlasSize; // atlas的尺寸
+ int margin; // atlas的边界
+ int padding; // glyph相互之间的间距,防止采样的时候越界
+};
+
class TextGenerator : public Singleton<TextGenerator>
{
public:
+ void Setup(TextGeneratingSettings settings);
+ Character GetCharacter(character::Codepoint codepoint, int pixelSize);
+ void RenderCharacter(character::Codepoint codepoint, int pixelSize);
+ GlyphAtals* GetGlyphAtlas(int index);
private:
- std::unordered_map<character::hash, Character> m_Characters;
- character::hash GetCharacterHash(character::unicode unicode, int pixelSize);
+ Texture* CreateAtlas();
+ GlyphAtals* RequestAtlas(int pixelSize, Internal::Vector2 preferSize);
+
+ Internal::Rect GetRenderChartAndMove(GlyphAtals* atlas, Internal::Vector2 preferSize);
+ bool HasEnoughSpace(GlyphAtals* atlas, Internal::Vector2 preferSize);
+
+ std::unordered_map<character::Hash, Character> m_Characters; // 渲染完的文字
+
+ std::vector<GlyphAtals> m_Atlases; // 当前所有的atlas
+ std::unordered_map<int, GlyphAtals*> m_AtlasCache; // 快速找到可用的atlas
+
+ int m_AtlasMargin;
+ int m_GlyphPadding;
+ Internal::Vector2 m_AtlasSize;
+
+ FT_Library m_FTLibrary;
+ FT_Face m_FTFace;
+
+ character::Hash GetHash(character::Codepoint Codepoint, int pixelSize);
};
+
+#define g_TextGenerator (*TextGenerator::Instance())
+
+namespace TextHelper
+{
+
+ void print_glyph(unsigned char* glyph, int width, int height);
+
+}
diff --git a/Runtime/Graphics/GfxDevice.cpp b/Runtime/Graphics/GfxDevice.cpp
index d30a60a..f318487 100644
--- a/Runtime/Graphics/GfxDevice.cpp
+++ b/Runtime/Graphics/GfxDevice.cpp
@@ -80,6 +80,9 @@ void GfxDevice::UseShader(LuaBind::State& state, Shader* shader, int idx)
m_Shader.shader = shader;
m_Shader.ref.SetRef(state, idx);
+
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
void GfxDevice::UnuseShader()
@@ -135,7 +138,8 @@ 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, texture->GetGpuID());
+ glBindTexture(GL_TEXTURE_2D, 2);
GLint loc = glGetUniformLocation(m_Shader.GetID(), name);
glUniform1i(loc, texUnit);
diff --git a/Runtime/Graphics/ImageData.h b/Runtime/Graphics/ImageData.h
index 7bf0335..fe26776 100644
--- a/Runtime/Graphics/ImageData.h
+++ b/Runtime/Graphics/ImageData.h
@@ -5,29 +5,29 @@
#include "Runtime/Threading/Job.h"
#include "Runtime/Lua/LuaHelper.h"
+enum EPixelFormat
+{
+ PixelFormat_RGBA,
+ PixelFormat_RGB,
+ PixelFormat_R,
+ PixelFormat_RG,
+ PixelFormat_BGR,
+ PixelFormat_BGRA
+};
+
+enum EPixelElementType
+{
+ PixelType_UNSIGNED_BYTE,
+ PixelType_UNSIGNED_INT,
+ PixelType_BYTE,
+ PixelType_INT,
+ PixelType_FLOAT,
+};
+
// 图片像素数据
class ImageData : public LuaBind::NativeClass<ImageData>
{
public:
- enum EPixelFormat
- {
- RGBA,
- RGB,
- R,
- RG,
- BGR,
- BGRA
- };
-
- enum EPixelElementType
- {
- UNSIGNED_BYTE,
- UNSIGNED_INT,
- BYTE,
- INT,
- FLOAT,
- };
-
ImageData(LuaBind::VM* vm)
: LuaBind::NativeClass<ImageData>(vm)
{
diff --git a/Runtime/Graphics/Texture.cpp b/Runtime/Graphics/Texture.cpp
index 6b682e9..f92c094 100644
--- a/Runtime/Graphics/Texture.cpp
+++ b/Runtime/Graphics/Texture.cpp
@@ -3,7 +3,6 @@
using namespace LuaBind;
-
Texture::Texture(TextureSetting setting, ImageData* imgData)
: NativeClass<Texture>()
{
@@ -94,7 +93,124 @@ void Texture::Init(TextureSetting setting, ImageData* imgData)
);
}
+Texture::Texture(TextureSetting setting, int w, int h)
+ : NativeClass<Texture>()
+{
+ m_KeepPixelData = false;
+
+ m_Width = w;
+ m_Height = h;
+ m_Type = setting.type;
+ m_Format = setting.format;
+ m_WrapMode = setting.wrapMode;
+ m_FilterMode = setting.filterMode;
+ m_KeepPixelData = setting.keepImageData;
+
+ glGenTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, m_GPUID);
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ switch (m_WrapMode) {
+ case ETextureWrapMode::Clamp:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ break;
+ case ETextureWrapMode::Repeat:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+ break;
+ case ETextureWrapMode::Mirror:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+ break;
+ default:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
+ break;
+ }
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ switch (m_FilterMode) {
+ case ETextureFilterMode::Linear:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ case ETextureFilterMode::Nearest:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ break;
+ default:
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ break;
+ }
+ GLenum internalFormat = GL_RGB;
+ if (m_Format == ETextureFormat::R8)
+ {
+ internalFormat = GL_RED;
+ }
+
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+
+ glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, w, h, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);
+
+ CheckGLError(
+ glDeleteTextures(1, &m_GPUID);
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+}
+
Texture::~Texture()
{
glDeleteTextures(1, &m_GPUID);
+}
+
+void Texture::UpdateSubImage(Internal::Rect rect, int format, int type, const void* data)
+{
+ glBindTexture(GL_TEXTURE_2D, m_GPUID);
+
+ CheckGLError(
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ GLenum fmt = GL_RED;
+ switch (format)
+ {
+ case EPixelFormat::PixelFormat_BGR: fmt = GL_BGR; break;
+ case EPixelFormat::PixelFormat_BGRA:fmt = GL_BGRA; break;
+ case EPixelFormat::PixelFormat_R: fmt = GL_RED; break;
+ case EPixelFormat::PixelFormat_RG: fmt = GL_RG; break;
+ case EPixelFormat::PixelFormat_RGB: fmt = GL_RGB; break;
+ case EPixelFormat::PixelFormat_RGBA: fmt = GL_RGBA; break;
+ }
+ GLenum t = GL_UNSIGNED_BYTE;
+ switch (type)
+ {
+ case EPixelElementType::PixelType_UNSIGNED_BYTE: t = GL_UNSIGNED_BYTE; break;
+ case EPixelElementType::PixelType_UNSIGNED_INT: t = GL_UNSIGNED_INT; break;
+ case EPixelElementType::PixelType_BYTE: t = GL_BYTE; break;
+ case EPixelElementType::PixelType_INT: t = GL_INT; break;
+ case EPixelElementType::PixelType_FLOAT: t = GL_FLOAT; break;
+ }
+
+ glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x, rect.y, rect.width, rect.height, fmt, t, data);
+
+ CheckGLError(
+ glBindTexture(GL_TEXTURE_2D, 0);
+ throw TextureException(error);
+ );
+
+ glBindTexture(GL_TEXTURE_2D, 0);
} \ No newline at end of file
diff --git a/Runtime/Graphics/Texture.h b/Runtime/Graphics/Texture.h
index d02634c..6ead2fb 100644
--- a/Runtime/Graphics/Texture.h
+++ b/Runtime/Graphics/Texture.h
@@ -61,10 +61,13 @@ public:
class Texture : public LuaBind::NativeClass<Texture>
{
public:
+ Texture(TextureSetting setting, int width, int height)/*throw TextureException*/; // 空贴图
Texture(TextureSetting setting, ImageData* imgData)/*throw TextureException*/;
Texture(LuaBind::VM* vm, TextureSetting setting, ImageData* imgData)/*throw TextureException*/;
~Texture();
+ void UpdateSubImage(Internal::Rect rect, int format, int type, const void* data);
+
GET(int, Width, m_Width);
GET(int, Height, m_Height);
diff --git a/Runtime/Math/Math.h b/Runtime/Math/Math.h
index 370b91c..7f61544 100644
--- a/Runtime/Math/Math.h
+++ b/Runtime/Math/Math.h
@@ -5,3 +5,7 @@
#include "Vector4.h"
#include "Matrix44.h"
#include "FloatConversion.h"
+#include "Rect.h"
+
+#define max(a, b)\
+(a)>(b)?(a):(b)
diff --git a/Runtime/Math/Rect.h b/Runtime/Math/Rect.h
index 80170d6..8e7dae6 100644
--- a/Runtime/Math/Rect.h
+++ b/Runtime/Math/Rect.h
@@ -4,6 +4,6 @@ namespace Internal
{
struct Rect
{
- int x, y, width, height;
+ float x, y, width, height;
};
} \ No newline at end of file
diff --git a/Runtime/Scripting/Resource/Resource.bind.cpp b/Runtime/Scripting/Resource/Resource.bind.cpp
index 6f9c0bb..379d88d 100644
--- a/Runtime/Scripting/Resource/Resource.bind.cpp
+++ b/Runtime/Scripting/Resource/Resource.bind.cpp
@@ -32,8 +32,8 @@ int LoadImageData(lua_State* L)
ImageData* data = new ImageData(state.GetVM());
int channels;
data->pixels = stbi_load(path, &data->width, &data->height, &channels, 0);
- data->format = ImageData::EPixelFormat::RGB;
- data->type = ImageData::EPixelElementType::UNSIGNED_BYTE;
+ data->format = EPixelFormat::PixelFormat_RGB;
+ data->type = EPixelElementType::PixelType_UNSIGNED_BYTE;
data->PushUserdata(state);
return 1;