From 051abd04e4527095ef15412939450fbe504daebe Mon Sep 17 00:00:00 2001 From: chai Date: Tue, 26 Oct 2021 19:33:40 +0800 Subject: +texture & imagedata --- Runtime/Debug/Log.cpp | 8 +- Runtime/FileSystem/FileJobs.h | 3 +- Runtime/Graphics/Device.h | 12 +-- Runtime/Graphics/ImageData.h | 49 +++++++-- Runtime/Graphics/RenderTexture.h | 4 +- Runtime/Graphics/Texture.cpp | 69 ++++++++++++ Runtime/Graphics/Texture.h | 103 ++++++++++++------ Runtime/Lua/LuaHelper.cpp | 5 + Runtime/Lua/LuaHelper.h | 7 +- Runtime/Scripting/Rendering/ImageData.bind.cpp | 38 +++++++ Runtime/Scripting/Rendering/Rendering.bind.cpp | 32 ++++++ Runtime/Scripting/Rendering/Texture.bind.cpp | 143 +++++++++++++++++++++++++ 12 files changed, 413 insertions(+), 60 deletions(-) create mode 100644 Runtime/Scripting/Rendering/ImageData.bind.cpp create mode 100644 Runtime/Scripting/Rendering/Texture.bind.cpp (limited to 'Runtime') diff --git a/Runtime/Debug/Log.cpp b/Runtime/Debug/Log.cpp index 4d28502..c92bdc8 100644 --- a/Runtime/Debug/Log.cpp +++ b/Runtime/Debug/Log.cpp @@ -63,9 +63,9 @@ void log_warning(std::string log) s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); } SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY); - cout << currentDateTime() << " [Info] " << log << endl; + cout << currentDateTime() << " [Warning] " << log << endl; #else - cout << "\x1B[93m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl; + cout << "\x1B[93m" << currentDateTime() << " [Warning] " << log << "\x1B[0m" << endl; #endif } } @@ -78,9 +78,9 @@ void log_error(std::string log) s_ConsoleHandle = GetStdHandle(STD_OUTPUT_HANDLE); } SetConsoleTextAttribute(s_ConsoleHandle, FOREGROUND_RED | FOREGROUND_INTENSITY); - cout << currentDateTime() << " [Info] " << log << endl; + cout << currentDateTime() << " [Error] " << log << endl; #else - cout << "\x1B[91m" << currentDateTime() << " [Info] " << log << "\x1B[0m" << endl; + cout << "\x1B[91m" << currentDateTime() << " [Error] " << log << "\x1B[0m" << endl; #endif } } diff --git a/Runtime/FileSystem/FileJobs.h b/Runtime/FileSystem/FileJobs.h index 50e681d..1fe49f1 100644 --- a/Runtime/FileSystem/FileJobs.h +++ b/Runtime/FileSystem/FileJobs.h @@ -18,7 +18,8 @@ public: void Process() override; bool IsFinished() override; + int cur = 0; //当前处理的文件 std::vector files; // 文件路径 LuaBind::StrongRef callback; // 完成后的回调函数 -}; +}; \ No newline at end of file diff --git a/Runtime/Graphics/Device.h b/Runtime/Graphics/Device.h index e445efa..c7a059e 100644 --- a/Runtime/Graphics/Device.h +++ b/Runtime/Graphics/Device.h @@ -12,8 +12,8 @@ struct DeviceSetting { - TextureFilter texFilter; - TextureWrap texWrap; + ETextureFilterMode texFilter; + ETextureWrapMode texWrap; }; class Device : public NonCopyable @@ -46,8 +46,8 @@ public: GET_SET(Color, ClearColor, m_ClearColor); - GET_SET(TextureFilter, TextureFilter, m_TexFilter); - GET_SET(TextureWrap, TextureWrap, m_TexWrap); + GET_SET(ETextureFilterMode, TextureFilter, m_TexFilter); + GET_SET(ETextureWrapMode, TextureWrap, m_TexWrap); inline bool IsInsideFrame(); @@ -55,8 +55,8 @@ private: uint m_EnableFlag; // Global texture setting - TextureFilter m_TexFilter; - TextureWrap m_TexWrap; + ETextureFilterMode m_TexFilter; + ETextureWrapMode m_TexWrap; Color m_ClearColor; diff --git a/Runtime/Graphics/ImageData.h b/Runtime/Graphics/ImageData.h index af44f11..4663e0e 100644 --- a/Runtime/Graphics/ImageData.h +++ b/Runtime/Graphics/ImageData.h @@ -3,27 +3,54 @@ #include #include "Runtime/Threading/Job.h" +#include "Runtime/Lua/LuaHelper.h" // 图片像素数据 -class ImageData +class ImageData : public LuaBind::NativeClass { public: - enum ImageFormat + enum EPixelFormat { - ImageFormat_Rgba_Int, - ImageFormat_Rgba_Float, + RGBA, + RGB, + R, + RG, + BGR, + BGRA }; -private: - void* m_Data; + enum EPixelElementType + { + UNSIGNED_BYTE, + UNSIGNED_INT, + BYTE, + INT, + FLOAT, + }; + ImageData(LuaBind::VM* vm) + : LuaBind::NativeClass(vm) + { + } + + void* pixels; // 像素数据,格式和类型参考 http://docs.gl/gl3/glTexImage2D pixel data的format和type + EPixelFormat format; + EPixelElementType type; + int width, height; + +private: + LUA_BIND_DECL_CLASS(ImageData); + + LUA_BIND_DECL_METHOD(_GetWidth); + LUA_BIND_DECL_METHOD(_GetHeight); + LUA_BIND_DECL_METHOD(_GetSize); }; -enum ImageDataAsyncError +enum EImageDataAsyncError { - ImageDataAsyncError_NoFile = 1, - ImageDataAsyncError_ParseFailed = 2, - ImageDataAsyncError_InvalidFormat = 3, + NoFile = 1, + ParseFailed = 2, + InvalidFormat = 3, }; struct ImageDataRequest @@ -42,6 +69,8 @@ namespace ImageDataUtil ImageDataRequest* LoadAsync(std::vector paths); } +// 在工作线程最多只能走到读取->解码完,提交到GPU还得主线程做 + class ReadImageFilesJob : public Job { diff --git a/Runtime/Graphics/RenderTexture.h b/Runtime/Graphics/RenderTexture.h index 74c5602..a501f50 100644 --- a/Runtime/Graphics/RenderTexture.h +++ b/Runtime/Graphics/RenderTexture.h @@ -7,10 +7,10 @@ class RenderTexture : public Texture { public: - RenderTexture(TextureFormat format); + RenderTexture(ETextureFormat format); }; -RenderTexture* CreateRenderTexture(int width, int height, TextureFormat format); +RenderTexture* CreateRenderTexture(int width, int height, ETextureFormat format); #endif \ No newline at end of file diff --git a/Runtime/Graphics/Texture.cpp b/Runtime/Graphics/Texture.cpp index e69de29..ce09927 100644 --- a/Runtime/Graphics/Texture.cpp +++ b/Runtime/Graphics/Texture.cpp @@ -0,0 +1,69 @@ +#include "ImageData.h" +#include "Texture.h" + +using namespace LuaBind; + +Texture::Texture(LuaBind::VM* vm, TextureSetting setting, ImageData* imgData) + : NativeClass(vm) +{ + m_Width = imgData->width; + m_Height = imgData->height; + 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); + + 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; + } + + 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; + } + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, imgData->width, imgData->height, 0, GL_RGB, GL_UNSIGNED_BYTE, imgData->pixels); + + // keep image data ? + if (m_KeepPixelData) + { + LuaBind::State state = vm->GetCurThread(); + imgData->PushUserdata(state); + SetMemberRef(state, m_ImageData, -1); + state.Pop(1); + } +} + +Texture::~Texture() +{ + glDeleteTextures(1, &m_GPUID); +} \ No newline at end of file diff --git a/Runtime/Graphics/Texture.h b/Runtime/Graphics/Texture.h index d09429c..30cf303 100644 --- a/Runtime/Graphics/Texture.h +++ b/Runtime/Graphics/Texture.h @@ -1,61 +1,96 @@ -#ifndef TEXTURE_H -#define TEXTURE_H +#pragma once +#include #include "Runtime/Lua/LuaHelper.h" -#include "Runtime/Lua/LuaBind/LuaBind.h" #include "../Utilities/UtilMacros.h" #include "OpenGL.h" -#include "ImageData.h" -enum TextureFormat +class ImageData; + +enum ETextureType +{ + TEX_2D, + TEX_CUBE, +}; + +enum ETextureFormat +{ + RGBA32, + RGB24, + RGB16, + R8, + A8, +}; + +enum ETextureWrapMode +{ + Clamp, + Repeat, + Mirror, +}; + +enum ETextureFilterMode { - TextureFormat_DepthComponent, - TextureFormat_Red, - TextureFormat_Green, - TextureFormat_Blue, - TextureFormat_Alpha, - TextureFormat_Rgb, - TextureFormat_Rgba, + Nearest, + Linear, }; -enum TextureWrap +struct TextureSetting { - TextureWrap_Clamp, - TextureWrap_Repeat, + bool keepImageData; // 是否保存图片数据 + int type; // 图片类型 + int format; // 内部格式 + int wrapMode; // 包围 + int filterMode; // 滤波 }; -enum TextureFilter +class TextureException : public std::exception { - TextureFilter_Nearest, - TextureFilter_Bilinear, - TextureFilter_Trilinear, +public: + TextureException(const char* what) + : std::exception(what) + {} }; -class Texture +class Texture : public LuaBind::NativeClass { public: - Texture(); - Texture(ImageData* imgData, TextureFormat format); - Texture(ImageData* imgData, TextureFormat format, TextureWrap wrap, TextureFilter filter); + Texture(LuaBind::VM* vm, TextureSetting setting, ImageData* imgData)/*throw TextureException*/; ~Texture(); GET(int, Width, m_Width); GET(int, Height, m_Height); - GET(TextureFilter, Filter, m_Filter); - GET(TextureWrap, Wrap, m_Wrap); - - GET(GLint, Handle, m_Handle); + GET(GLuint, GpuID, m_GPUID); protected: - GLint m_Handle; + GLuint m_GPUID; + int m_Width, m_Height; - TextureFilter m_Filter; - TextureWrap m_Wrap; -}; + int m_Type; + int m_Format; + int m_FilterMode; + int m_WrapMode; + + bool m_KeepPixelData; // 是否保存图像像素数据,默认导入后不保存 + + LuaBind::MemberRef m_ImageData; //图片像素数据 + + LUA_BIND_DECL_CLASS(Texture); + + LUA_BIND_DECL_METHOD(_New); + + LUA_BIND_DECL_METHOD(_GetWidth); + LUA_BIND_DECL_METHOD(_GetHeight); + LUA_BIND_DECL_METHOD(_GetSize); + + LUA_BIND_DECL_METHOD(_GetType); + LUA_BIND_DECL_METHOD(_GetFormat); + LUA_BIND_DECL_METHOD(_GetWrapMode); + LUA_BIND_DECL_METHOD(_GetFilterMode); -Texture* CreateTexture(ImageData* imgData, TextureFormat format); -Texture* CreateTexture(ImageData* imgData, TextureFormat format, TextureWrap wrap, TextureFilter filter); + LUA_BIND_DECL_METHOD(_IsKeepImageData); + LUA_BIND_DECL_METHOD(_GetImageData); -#endif \ No newline at end of file +}; \ No newline at end of file diff --git a/Runtime/Lua/LuaHelper.cpp b/Runtime/Lua/LuaHelper.cpp index 2044ba2..9381b6c 100644 --- a/Runtime/Lua/LuaHelper.cpp +++ b/Runtime/Lua/LuaHelper.cpp @@ -59,4 +59,9 @@ bool LuaHelper::IsType(LuaBind::State& state, const char* typeName, int idx) bool bIsType = tname == typeName; state.SetTop(top); return bIsType; +} + +bool LuaHelper::InstantiateClass(LuaBind::State& state, const char* classFullName) +{ + return false; } \ No newline at end of file diff --git a/Runtime/Lua/LuaHelper.h b/Runtime/Lua/LuaHelper.h index 56dae54..c3cd70e 100644 --- a/Runtime/Lua/LuaHelper.h +++ b/Runtime/Lua/LuaHelper.h @@ -5,13 +5,14 @@ // lua 5.1 doc: https://www.lua.org/manual/5.1/ +// 针对GameLab做一些扩展 class LuaHelper { public: static int Call(const char* func, const char* params, ...); - static bool IsType(LuaBind::State& state, const char* typeName, int idx); - static void OnRegisterNativeClass(LuaBind::State& state, int cls, std::string clsName, std::string pkgName); - + // 创建lua类的实例并留在栈顶,如果失败返回false且不压栈 + static bool InstantiateClass(LuaBind::State& state, const char* classFullName); + }; \ No newline at end of file diff --git a/Runtime/Scripting/Rendering/ImageData.bind.cpp b/Runtime/Scripting/Rendering/ImageData.bind.cpp new file mode 100644 index 0000000..88412e5 --- /dev/null +++ b/Runtime/Scripting/Rendering/ImageData.bind.cpp @@ -0,0 +1,38 @@ +#include "Runtime/Graphics/ImageData.h" + +using namespace LuaBind; + +LUA_BIND_REGISTRY(ImageData) +{ + LUA_BIND_REGISTER_METHODS(state, + { "GetWidth", _GetWidth }, + { "GetHeight", _GetHeight }, + { "GetSize", _GetSize } + ); +} + +LUA_BIND_POSTPROCESS(ImageData) +{ +} + +LUA_BIND_IMPL_METHOD(ImageData, _GetWidth) +{ + LUA_BIND_PREPARE(L, ImageData); + state.Push(self->width); + return 1; +} + +LUA_BIND_IMPL_METHOD(ImageData, _GetHeight) +{ + LUA_BIND_PREPARE(L, ImageData); + state.Push(self->height); + return 1; +} + +LUA_BIND_IMPL_METHOD(ImageData, _GetSize) +{ + LUA_BIND_PREPARE(L, ImageData); + state.Push(self->width); + state.Push(self->height); + return 2; +} diff --git a/Runtime/Scripting/Rendering/Rendering.bind.cpp b/Runtime/Scripting/Rendering/Rendering.bind.cpp index 29fa421..40b3ac5 100644 --- a/Runtime/Scripting/Rendering/Rendering.bind.cpp +++ b/Runtime/Scripting/Rendering/Rendering.bind.cpp @@ -1,4 +1,32 @@ #include "Runtime/Graphics/Shader.h" +#include "Runtime/Graphics/Texture.h" +#include "Runtime/Graphics/ImageData.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "ThirdParty/stb/stb_image.h" + +// imgData = Rendering.LoadImage(path) +int LoadImage(lua_State* L) +{ + LUA_BIND_STATE(L); + + const char* path = state.GetValue(1, ""); + + stbi_set_flip_vertically_on_load(true); + 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->PushUserdata(state); + return 1; +} + +static luaL_Reg funcs[] = { + {"LoadImage", LoadImage}, + {0, 0} +}; int luaopen_GameLab_Engine_Rendering(lua_State* L) { @@ -11,7 +39,11 @@ int luaopen_GameLab_Engine_Rendering(lua_State* L) state.PushNamespace("Engine"); state.PushNamespace("Rendering"); + state.RegisterMethods(funcs); + state.RegisterNativeClass(); + state.RegisterNativeClass(); + state.RegisterNativeClass(); return 1; } \ No newline at end of file diff --git a/Runtime/Scripting/Rendering/Texture.bind.cpp b/Runtime/Scripting/Rendering/Texture.bind.cpp new file mode 100644 index 0000000..061a303 --- /dev/null +++ b/Runtime/Scripting/Rendering/Texture.bind.cpp @@ -0,0 +1,143 @@ +#include "Runtime/Graphics/Texture.h" + +using namespace LuaBind; + +LUA_BIND_REGISTRY(Texture) +{ + LUA_BIND_REGISTER_METHODS(state, + { "New", _New }, + { "GetWidth", _GetWidth }, + { "GetHeight", _GetHeight }, + { "GetSize", _GetSize }, + { "GetType", _GetType }, + { "GetFormat", _GetFormat }, + { "GetWrapMode", _GetWrapMode }, + { "GetImageData", _GetImageData }, + { "IsKeepImageData", _IsKeepImageData }, + { "GetFilterMode", _GetFilterMode } + ); +} + +LUA_BIND_POSTPROCESS(Texture) +{ + LUA_BIND_REGISTER_ENUM(state, "ETextureType", + { "TEX_2D", ETextureType::TEX_2D }, + { "TEX_CUBE", ETextureType::TEX_CUBE } + ); + LUA_BIND_REGISTER_ENUM(state, "ETextureFormat", + { "RGBA32", ETextureFormat::RGBA32 }, + { "RGB24", ETextureFormat::RGB24 }, + { "RGB16", ETextureFormat::RGB16 }, + { "R8", ETextureFormat::R8 }, + { "A8", ETextureFormat::A8 } + ); + LUA_BIND_REGISTER_ENUM(state, "ETextureWrapMode", + { "Clamp", ETextureWrapMode::Clamp }, + { "Repeat", ETextureWrapMode::Repeat }, + { "Mirror", ETextureWrapMode::Mirror } + ); + LUA_BIND_REGISTER_ENUM(state, "ETextureFilterMode", + { "Nearest", ETextureFilterMode::Nearest }, + { "Linear", ETextureFilterMode::Linear } + ); +} + +// Texture.New(imgData, keepImgData, type, format, wrapMode, filterMode) +LUA_BIND_IMPL_METHOD(Texture, _New) +{ + LUA_BIND_STATE(L); + LUA_BIND_CHECK(L, "U"); + + ImageData* imgData = state.GetUserdata(1); + + TextureSetting setting; + setting.keepImageData = state.GetValue(2, false); + setting.type = state.GetValue(3, (int)ETextureType::TEX_2D); + setting.format = state.GetValue(4, (int)ETextureFormat::RGBA32); + setting.wrapMode = state.GetValue(5, (int)ETextureWrapMode::Clamp); + setting.filterMode = state.GetValue(6, (int)ETextureFilterMode::Linear); + + try + { + Texture* tex = new Texture(state.GetVM(), setting, imgData); + tex->PushUserdata(state); + return 1; + } + catch (TextureException e) + { + luaL_error(L, "Failed to create texture."); + return 0; + } + return 0; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetWidth) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Width); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetHeight) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Height); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetSize) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Width); + state.Push(self->m_Height); + return 2; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetType) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Type); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetFormat) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_Format); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetWrapMode) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_WrapMode); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetFilterMode) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_FilterMode); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _IsKeepImageData) +{ + LUA_BIND_PREPARE(L, Texture); + state.Push(self->m_KeepPixelData); + return 1; +} + +LUA_BIND_IMPL_METHOD(Texture, _GetImageData) +{ + LUA_BIND_PREPARE(L, Texture); + if (self->m_KeepPixelData) + { + self->PushMemberRef(state, self->m_ImageData); + } + else + { + state.PushNil(); + } + return 1; +} -- cgit v1.1-26-g67d0