diff --git a/src/dependency/.ignore b/src/dependency/.ignore new file mode 100644 index 0000000..cf4a038 --- /dev/null +++ b/src/dependency/.ignore @@ -0,0 +1,4 @@ +SDL/* +# !SDL/src +# bgfx.cmake/* +tinygltf/* diff --git a/src/engine/Shared.h b/src/engine/Shared.h index 70ff357..bc2f9b9 100644 --- a/src/engine/Shared.h +++ b/src/engine/Shared.h @@ -6,7 +6,10 @@ struct SharedWindowData void* Handle = nullptr; int32_t WindowWidth = 1920; int32_t WindowHeight = 1080; - bool HeldScanCodes[512]{0}; + bool HeldScanCodes[512]{false}; + bool LastHeldScanCodes[512]{false}; + bool HeldMouseButtons[8]{false}; + bool LastHeldMouseButtons[8]{false}; float MouseDeltaX = 0.0f; float MouseDeltaY = 0.0f; }; @@ -29,6 +32,9 @@ struct GameData void* EntityStorage = nullptr; uint64_t EntityStorageSize = 0; + + void* TransientStorage = nullptr; + uint64_t TransientStorageSize = 0; }; struct SharedData diff --git a/src/engine/Window.cpp b/src/engine/Window.cpp index 70202b6..3f5933c 100644 --- a/src/engine/Window.cpp +++ b/src/engine/Window.cpp @@ -61,6 +61,16 @@ void EngineWindow::Update(SharedWindowData& shared) shared.MouseDeltaY += evt.motion.yrel; break; } + case SDL_EVENT_MOUSE_BUTTON_DOWN: + { + shared.HeldMouseButtons[evt.button.button] = true; + break; + } + case SDL_EVENT_MOUSE_BUTTON_UP: + { + shared.HeldMouseButtons[evt.button.button] = false; + break; + } default: break; } diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 77ae55c..f0da9df 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -4,19 +4,19 @@ #include #include #define WIN32_LEAN_AND_MEAN -#include +#include #undef min #undef max -#include -#include -#include #include +#include +#include +#include #include "Shared.h" #include "Window.h" -//#define VISUAL_STUDIO +// #define VISUAL_STUDIO #ifdef VISUAL_STUDIO constexpr const char* DLLPath = "PuzGame.dll"; @@ -28,285 +28,307 @@ constexpr const wchar_t* DLLWatch = L"libPuzGame2.dll"; namespace { - bx::AllocatorI* defaultAllocator = new bx::DefaultAllocator{}; + bx::AllocatorI* defaultAllocator = new bx::DefaultAllocator{}; } enum class FileChangeType { - DLL, - Shader, - CompiledShader, + DLL, + Shader, + CompiledShader, }; struct FileWatcherStartup { - char DirPath[512]{0}; - wchar_t CompName[512]{0}; - FileChangeType ChangeType = FileChangeType::Shader; - bool Shutdown = false; + char DirPath[512]{0}; + wchar_t CompName[512]{0}; + FileChangeType ChangeType = FileChangeType::Shader; + bool Shutdown = false; }; struct FileWatcherData { - FileWatcherStartup DLLWatcher; - FileWatcherStartup ShaderWatcher; - FileWatcherStartup CompiledShaderWatcher; - bx::MpScUnboundedQueueT ShaderQueue{defaultAllocator}; - bx::MpScUnboundedQueueT DLLQueue{defaultAllocator}; + FileWatcherStartup DLLWatcher; + FileWatcherStartup ShaderWatcher; + FileWatcherStartup CompiledShaderWatcher; + bx::MpScUnboundedQueueT ShaderQueue{defaultAllocator}; + bx::MpScUnboundedQueueT DLLQueue{defaultAllocator}; }; struct DevelopmentData { - HMODULE GameLib = NULL; - FileWatcherData FileWatcher; + HMODULE GameLib = NULL; + FileWatcherData FileWatcher; }; struct EngineData { - EngineWindow Window; + EngineWindow Window; }; namespace { - DevelopmentData DevData; - EngineData Engine; - SharedData Shared; - Startup StartupFunc; - Update UpdateFunc; - Shutdown ShutdownFunc; -} + DevelopmentData DevData; + EngineData Engine; + SharedData Shared; + Startup StartupFunc; + Update UpdateFunc; + Shutdown ShutdownFunc; +} // namespace void FileChangeCheck(HANDLE dirHandle, FileChangeType changeType, const wchar_t* compName = nullptr) { - if (dirHandle == NULL) return; + if (dirHandle == NULL) return; - uint8_t fileChangeBuffer[1024]{ 0 }; - bx::memSet(fileChangeBuffer, 0, sizeof(fileChangeBuffer)); - DWORD bytesReturned = 0; - if (ReadDirectoryChangesW(dirHandle, fileChangeBuffer, sizeof(fileChangeBuffer), true, FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, &bytesReturned, NULL, NULL)) - { - uint32_t offset = 0; - while (true) - { - FILE_NOTIFY_INFORMATION* notifyData = reinterpret_cast(&fileChangeBuffer[offset]); - if (notifyData->Action == FILE_ACTION_ADDED || notifyData->Action == FILE_ACTION_MODIFIED || notifyData->Action == FILE_ACTION_RENAMED_NEW_NAME) - { - if (compName == nullptr || compName[0] == 0 || wcscmp(notifyData->FileName, compName) == 0) - { - FileChangeNotification notif; - wcscpy(notif.FileName, notifyData->FileName); - if (changeType == FileChangeType::DLL) - { - DevData.FileWatcher.DLLQueue.push(¬if); - } - else if (changeType == FileChangeType::Shader) - { - std::system("shadercompile.bat"); - } - else if (changeType == FileChangeType::CompiledShader) - { - DevData.FileWatcher.ShaderQueue.push(¬if); - } - printf("detected file change of type %u!\n", changeType); - } - } + uint8_t fileChangeBuffer[1024]{0}; + bx::memSet(fileChangeBuffer, 0, sizeof(fileChangeBuffer)); + DWORD bytesReturned = 0; + if (ReadDirectoryChangesW(dirHandle, + fileChangeBuffer, + sizeof(fileChangeBuffer), + true, + FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE, + &bytesReturned, + NULL, + NULL)) + { + uint32_t offset = 0; + while (true) + { + FILE_NOTIFY_INFORMATION* notifyData = reinterpret_cast(&fileChangeBuffer[offset]); + if (notifyData->Action == FILE_ACTION_ADDED || notifyData->Action == FILE_ACTION_MODIFIED || + notifyData->Action == FILE_ACTION_RENAMED_NEW_NAME) + { + if (compName == nullptr || compName[0] == 0 || wcscmp(notifyData->FileName, compName) == 0) + { + FileChangeNotification notif; + wcscpy(notif.FileName, notifyData->FileName); + if (changeType == FileChangeType::DLL) + { + DevData.FileWatcher.DLLQueue.push(¬if); + } + else if (changeType == FileChangeType::Shader) + { + std::system("shadercompile.bat"); + } + else if (changeType == FileChangeType::CompiledShader) + { + DevData.FileWatcher.ShaderQueue.push(¬if); + } + printf("detected file change of type %u!\n", changeType); + } + } - if (notifyData->NextEntryOffset == 0) break; - offset += notifyData->NextEntryOffset; - } - } + if (notifyData->NextEntryOffset == 0) break; + offset += notifyData->NextEntryOffset; + } + } } HANDLE LoadDirHandle(const char* name) { - HANDLE h = CreateFileA(name, - FILE_LIST_DIRECTORY, - FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, - NULL); + HANDLE h = CreateFileA(name, + FILE_LIST_DIRECTORY, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OVERLAPPED, + NULL); - if (h == NULL) - { - printf("Failed to load dir handle for %s", name); - } - return h; + if (h == NULL) + { + printf("Failed to load dir handle for %s", name); + } + return h; } unsigned long FileWatcherThread(void* data) { - FileWatcherStartup* startupData = reinterpret_cast(data); - printf("Starting file watcher of type %u\n", startupData->ChangeType); - if (startupData->DirPath[0] == 0) - { - printf("Invalid file watcher path!\n"); - return 1; - } - HANDLE dirHandle = LoadDirHandle(startupData->DirPath); - if (dirHandle == NULL) - { - printf("Failed to load dir %s for file watcher!\n", startupData->DirPath); - return 1; - } - - while (!startupData->Shutdown) - { - FileChangeCheck(dirHandle, startupData->ChangeType, startupData->CompName); - } - printf("File watcher thread ended!\n"); - return 0; + FileWatcherStartup* startupData = reinterpret_cast(data); + printf("Starting file watcher of type %u\n", startupData->ChangeType); + if (startupData->DirPath[0] == 0) + { + printf("Invalid file watcher path!\n"); + return 1; + } + HANDLE dirHandle = LoadDirHandle(startupData->DirPath); + if (dirHandle == NULL) + { + printf("Failed to load dir %s for file watcher!\n", startupData->DirPath); + return 1; + } + + while (!startupData->Shutdown) + { + FileChangeCheck(dirHandle, startupData->ChangeType, startupData->CompName); + } + printf("File watcher thread ended!\n"); + return 0; } bool ReloadDLL() { - if (DevData.GameLib != NULL) - { - FreeLibrary(DevData.GameLib); - } + if (DevData.GameLib != NULL) + { + FreeLibrary(DevData.GameLib); + } #ifdef VISUAL_STUDIO - if (!CopyFile("PuzGame2.dll", "PuzGame.dll", false)) - { - printf("Failed to copy game DLL!\n"); - return false; - } + if (!CopyFile("PuzGame2.dll", "PuzGame.dll", false)) + { + printf("Failed to copy game DLL!\n"); + return false; + } #else - if (!CopyFile("cmake-build\\libPuzGame2.dll", "cmake-build\\libPuzGame.dll", false)) - { - printf("Failed to copy game DLL!\n"); - return false; - } + if (!CopyFile("cmake-build\\libPuzGame2.dll", "cmake-build\\libPuzGame.dll", false)) + { + printf("Failed to copy game DLL!\n"); + return false; + } #endif - HMODULE gameLibReloaded = LoadLibraryEx(DLLPath, NULL, 0); - if (gameLibReloaded == NULL) - { - printf("Failed to load game DLL from %s!\n", DLLPath); - return false; - } - DevData.GameLib = gameLibReloaded; + HMODULE gameLibReloaded = LoadLibraryEx(DLLPath, NULL, 0); + if (gameLibReloaded == NULL) + { + printf("Failed to load game DLL from %s!\n", DLLPath); + return false; + } + DevData.GameLib = gameLibReloaded; #ifdef VISUAL_STUDIO - Startup StartupReloaded = (Startup)GetProcAddress(DevData.GameLib, "?Setup@Game@@YAXPEAX@Z"); + Startup StartupReloaded = (Startup)GetProcAddress(DevData.GameLib, "?Setup@Game@@YAXPEAX@Z"); #else - Startup StartupReloaded = (Startup)GetProcAddress(DevData.GameLib, "_ZN4Game5SetupER10SharedData"); + Startup StartupReloaded = (Startup)GetProcAddress(DevData.GameLib, "_ZN4Game5SetupER10SharedData"); #endif - if (StartupReloaded == NULL) - { - printf("Failed to load startup function from game DLL!\n"); - return false; - } + if (StartupReloaded == NULL) + { + printf("Failed to load startup function from game DLL!\n"); + return false; + } #ifdef VISUAL_STUDIO - Update UpdateReloaded = (Update)GetProcAddress(DevData.GameLib, "?Update@Game@@YAXXZ"); + Update UpdateReloaded = (Update)GetProcAddress(DevData.GameLib, "?Update@Game@@YAXXZ"); #else - Update UpdateReloaded = (Update)GetProcAddress(DevData.GameLib, "_ZN4Game6UpdateEv"); + Update UpdateReloaded = (Update)GetProcAddress(DevData.GameLib, "_ZN4Game6UpdateEv"); #endif - if (UpdateReloaded == NULL) - { - printf("Failed to load update function from game DLL!\n"); - return false; - } + if (UpdateReloaded == NULL) + { + printf("Failed to load update function from game DLL!\n"); + return false; + } #ifdef VISUAL_STUDIO - Shutdown ShutdownReloaded = (Shutdown)GetProcAddress(DevData.GameLib, "?Shutdown@Game@@YAXXZ"); + Shutdown ShutdownReloaded = (Shutdown)GetProcAddress(DevData.GameLib, "?Shutdown@Game@@YAXXZ"); #else - Shutdown ShutdownReloaded = (Shutdown)GetProcAddress(DevData.GameLib, "_ZN4Game8ShutdownEv"); + Shutdown ShutdownReloaded = (Shutdown)GetProcAddress(DevData.GameLib, "_ZN4Game8ShutdownEv"); #endif - if (ShutdownReloaded == NULL) - { - printf("Failed to load shutdown function from game DLL\n"); - return false; - } + if (ShutdownReloaded == NULL) + { + printf("Failed to load shutdown function from game DLL\n"); + return false; + } - StartupFunc = StartupReloaded; - UpdateFunc = UpdateReloaded; - ShutdownFunc = ShutdownReloaded; + StartupFunc = StartupReloaded; + UpdateFunc = UpdateReloaded; + ShutdownFunc = ShutdownReloaded; - printf("Loaded Game DLL successfully!\n"); - return true; + printf("Loaded Game DLL successfully!\n"); + return true; } int main() { - char PathBuf[512]{ 0 }; - GetCurrentDirectory(sizeof(PathBuf), PathBuf); - printf("Current path: %s\n", PathBuf); + char PathBuf[512]{0}; + GetCurrentDirectory(sizeof(PathBuf), PathBuf); + printf("Current path: %s\n", PathBuf); - if (!ReloadDLL()) return 1; + if (!ReloadDLL()) return 1; - Engine.Window.Startup(Shared.Window); - if (Shared.Window.Handle == nullptr) - { - printf("Failed to set up window!\n"); - return 1; - } + Engine.Window.Startup(Shared.Window); + if (Shared.Window.Handle == nullptr) + { + printf("Failed to set up window!\n"); + return 1; + } - DevData.FileWatcher.DLLWatcher.ChangeType = FileChangeType::DLL; - DevData.FileWatcher.ShaderWatcher.ChangeType = FileChangeType::Shader; - DevData.FileWatcher.CompiledShaderWatcher.ChangeType = FileChangeType::CompiledShader; - - bx::strCopy(DevData.FileWatcher.DLLWatcher.DirPath, sizeof(DevData.FileWatcher.DLLWatcher.DirPath), "cmake-build"); - bx::strCopy(DevData.FileWatcher.ShaderWatcher.DirPath, sizeof(DevData.FileWatcher.ShaderWatcher.DirPath), "game/shaders"); - bx::strCopy(DevData.FileWatcher.CompiledShaderWatcher.DirPath, sizeof(DevData.FileWatcher.CompiledShaderWatcher.DirPath), "game/compiled-shaders/dx11"); + DevData.FileWatcher.DLLWatcher.ChangeType = FileChangeType::DLL; + DevData.FileWatcher.ShaderWatcher.ChangeType = FileChangeType::Shader; + DevData.FileWatcher.CompiledShaderWatcher.ChangeType = FileChangeType::CompiledShader; - wcscpy(DevData.FileWatcher.DLLWatcher.CompName, DLLWatch); - - DWORD fileWatcherThreadId = 0; - HANDLE dllThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.DLLWatcher, 0, &fileWatcherThreadId); - HANDLE shaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.ShaderWatcher, 0, &fileWatcherThreadId); - HANDLE compiledShaderThread = CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.CompiledShaderWatcher, 0, &fileWatcherThreadId); + bx::strCopy(DevData.FileWatcher.DLLWatcher.DirPath, sizeof(DevData.FileWatcher.DLLWatcher.DirPath), "cmake-build"); + bx::strCopy( + DevData.FileWatcher.ShaderWatcher.DirPath, sizeof(DevData.FileWatcher.ShaderWatcher.DirPath), "game/shaders"); + bx::strCopy(DevData.FileWatcher.CompiledShaderWatcher.DirPath, + sizeof(DevData.FileWatcher.CompiledShaderWatcher.DirPath), + "game/compiled-shaders/dx11"); - Shared.Game.PermanentStorageSize = 1024*1024; - Shared.Game.PermanentStorage = VirtualAllocEx(GetCurrentProcess(), NULL, Shared.Game.PermanentStorageSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - Shared.Game.EntityStorageSize = 1024*1024; - Shared.Game.EntityStorage = VirtualAllocEx(GetCurrentProcess(), NULL, Shared.Game.EntityStorageSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); - StartupFunc(Shared); - - bool isRunning = true; - while (isRunning) - { - Engine.Window.Update(Shared.Window); - if (Engine.Window.CloseRequested) - { - isRunning = false; - } - FileChangeNotification* DLLChange = nullptr; - if (DevData.FileWatcher.DLLQueue.pop()) - { - // Empty queue to avoid multiple reloads - while (DevData.FileWatcher.DLLQueue.pop()) {} - ShutdownFunc(); - ReloadDLL(); - StartupFunc(Shared); - } + wcscpy(DevData.FileWatcher.DLLWatcher.CompName, DLLWatch); - FileChangeNotification* CompiledShaderChange = nullptr; - while ((CompiledShaderChange = DevData.FileWatcher.ShaderQueue.pop())) - { - if (Shared.Dev.ChangedShaderCount < BX_COUNTOF(Shared.Dev.ChangedShaders)) - { - wcscpy(Shared.Dev.ChangedShaders[Shared.Dev.ChangedShaderCount].FileName, CompiledShaderChange->FileName); - ++Shared.Dev.ChangedShaderCount; - } - else - { - printf("Ran out of shader change buffer!\n"); - } - } + DWORD fileWatcherThreadId = 0; + HANDLE dllThread = + CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.DLLWatcher, 0, &fileWatcherThreadId); + HANDLE shaderThread = + CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.ShaderWatcher, 0, &fileWatcherThreadId); + HANDLE compiledShaderThread = + CreateThread(NULL, 0, FileWatcherThread, &DevData.FileWatcher.CompiledShaderWatcher, 0, &fileWatcherThreadId); - UpdateFunc(); - } - - ShutdownFunc(); - Engine.Window.Shutdown(); + Shared.Game.PermanentStorageSize = 1024 * 1024; + Shared.Game.PermanentStorage = VirtualAllocEx( + GetCurrentProcess(), NULL, Shared.Game.PermanentStorageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + Shared.Game.EntityStorageSize = 1024 * 1024; + Shared.Game.EntityStorage = VirtualAllocEx( + GetCurrentProcess(), NULL, Shared.Game.EntityStorageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + Shared.Game.TransientStorageSize = 1024 * 1024 * 100; + Shared.Game.TransientStorage = VirtualAllocEx( + GetCurrentProcess(), NULL, Shared.Game.TransientStorageSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); + StartupFunc(Shared); - DevData.FileWatcher.DLLWatcher.Shutdown = true; - DevData.FileWatcher.ShaderWatcher.Shutdown = true; - DevData.FileWatcher.CompiledShaderWatcher.Shutdown = true; - WaitForSingleObject(dllThread, 100); - WaitForSingleObject(shaderThread, 100); - WaitForSingleObject(compiledShaderThread, 100); - - return 0; + bool isRunning = true; + while (isRunning) + { + Engine.Window.Update(Shared.Window); + if (Engine.Window.CloseRequested) + { + isRunning = false; + } + FileChangeNotification* DLLChange = nullptr; + if (DevData.FileWatcher.DLLQueue.pop()) + { + // Empty queue to avoid multiple reloads + while (DevData.FileWatcher.DLLQueue.pop()) + { + } + ShutdownFunc(); + ReloadDLL(); + StartupFunc(Shared); + } + + FileChangeNotification* CompiledShaderChange = nullptr; + while ((CompiledShaderChange = DevData.FileWatcher.ShaderQueue.pop())) + { + if (Shared.Dev.ChangedShaderCount < BX_COUNTOF(Shared.Dev.ChangedShaders)) + { + wcscpy(Shared.Dev.ChangedShaders[Shared.Dev.ChangedShaderCount].FileName, + CompiledShaderChange->FileName); + ++Shared.Dev.ChangedShaderCount; + } + else + { + printf("Ran out of shader change buffer!\n"); + } + } + + UpdateFunc(); + } + + ShutdownFunc(); + Engine.Window.Shutdown(); + + DevData.FileWatcher.DLLWatcher.Shutdown = true; + DevData.FileWatcher.ShaderWatcher.Shutdown = true; + DevData.FileWatcher.CompiledShaderWatcher.Shutdown = true; + WaitForSingleObject(dllThread, 100); + WaitForSingleObject(shaderThread, 100); + WaitForSingleObject(compiledShaderThread, 100); + + return 0; } diff --git a/src/game/Global.cpp b/src/game/Global.cpp index 5db304d..4db822e 100644 --- a/src/game/Global.cpp +++ b/src/game/Global.cpp @@ -1,7 +1,10 @@ +#include "../engine/Shared.h" #include "Global.h" +#include "Instance.h" #include "bx/bx.h" #include "bx/math.h" #include +#include namespace { @@ -105,4 +108,15 @@ namespace Game { GameInst = &instance; } + + void* AllocateScratch(size_t byteCount, size_t align = 16) + { + size_t offset = GetInstance().UsedScratchAmount; + uint8_t* base = static_cast(GetShared().Game.TransientStorage); + uint8_t* current = base + offset; + uintptr_t ptrAligned = ((reinterpret_cast(current) + align - 1) / align) * align; + uintptr_t newOffset = ptrAligned - reinterpret_cast(base) + byteCount; + if (newOffset > GetShared().Game.TransientStorageSize) return nullptr; + return reinterpret_cast(ptrAligned); + } } // namespace Game diff --git a/src/game/Global.h b/src/game/Global.h index 1029a3e..6dbb8d8 100644 --- a/src/game/Global.h +++ b/src/game/Global.h @@ -2,26 +2,48 @@ #include "bx/math.h" +struct Vec2 +{ + float x = 0.0f; + float y = 0.0f; +}; + +struct Vec3 +{ + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; +}; + +struct Vec4 +{ + float x = 0.0f; + float y = 0.0f; + float z = 0.0f; + float w = 0.0f; +}; + +struct Mat3 +{ + // clang-format off + float M[9]{ + 1.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 1.0f, + }; + // clang-format on +}; + struct Mat4 { + // clang-format off float M[16]{ - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 1.0, + 1.0, 0.0, 0.0, 0.0, + 0.0, 1.0, 0.0, 0.0, + 0.0, 0.0, 1.0, 0.0, + 0.0, 0.0, 0.0, 1.0, }; + // clang-format on }; struct Transform @@ -54,4 +76,5 @@ namespace Game void SetShared(SharedData& instance); GameInstance& GetInstance(); void SetInstance(GameInstance& instance); + void* AllocateScratch(size_t byteCount); } // namespace Game diff --git a/src/game/Input.cpp b/src/game/Input.cpp index 9ec5e49..d77444d 100644 --- a/src/game/Input.cpp +++ b/src/game/Input.cpp @@ -8,4 +8,32 @@ namespace Game { return GetShared().Window.HeldScanCodes[(int32_t)key]; } + bool GetKeyPressedNow(ScanCode key) + { + auto& win = GetShared().Window; + return win.HeldScanCodes[(int32_t)key] && !win.LastHeldScanCodes[(int32_t)key]; + } + bool GetKeyReleasedNow(ScanCode key) + { + auto& win = GetShared().Window; + return !win.HeldScanCodes[(int32_t)key] && win.LastHeldScanCodes[(int32_t)key]; + } + bool GetMouseButton(MouseButton button) + { + return GetShared().Window.HeldMouseButtons[(int32_t)button]; + } + bool GetMouseButtonPressedNow(MouseButton button) + { + auto& win = GetShared().Window; + return win.HeldMouseButtons[(int32_t)button] && !win.LastHeldMouseButtons[(int32_t)button]; + } + bool GetMouseButtonReleasedNow(MouseButton button) + { + auto& win = GetShared().Window; + return !win.HeldMouseButtons[(int32_t)button] && win.LastHeldMouseButtons[(int32_t)button]; + } + Vec2 GetMouseMovement() + { + return {GetShared().Window.MouseDeltaX, GetShared().Window.MouseDeltaY}; + } } // namespace Game diff --git a/src/game/Input.h b/src/game/Input.h index f7a724b..70bf3d6 100644 --- a/src/game/Input.h +++ b/src/game/Input.h @@ -1,4 +1,14 @@ #pragma once +#include "Global.h" + +enum class MouseButton +{ + Left = 1, + Middle = 2, + Right = 3, + Four = 4, + Five = 5, +}; enum class ScanCode { @@ -60,50 +70,50 @@ enum class ScanCode LEFTBRACKET = 47, RIGHTBRACKET = 48, BACKSLASH = 49, /**< Located at the lower left of the return - * key on ISO keyboards and at the right end - * of the QWERTY row on ANSI keyboards. - * Produces REVERSE SOLIDUS (backslash) and - * VERTICAL LINE in a US layout, REVERSE - * SOLIDUS and VERTICAL LINE in a UK Mac - * layout, NUMBER SIGN and TILDE in a UK - * Windows layout, DOLLAR SIGN and POUND SIGN - * in a Swiss German layout, NUMBER SIGN and - * APOSTROPHE in a German layout, GRAVE - * ACCENT and POUND SIGN in a French Mac - * layout, and ASTERISK and MICRO SIGN in a - * French Windows layout. - */ + * key on ISO keyboards and at the right end + * of the QWERTY row on ANSI keyboards. + * Produces REVERSE SOLIDUS (backslash) and + * VERTICAL LINE in a US layout, REVERSE + * SOLIDUS and VERTICAL LINE in a UK Mac + * layout, NUMBER SIGN and TILDE in a UK + * Windows layout, DOLLAR SIGN and POUND SIGN + * in a Swiss German layout, NUMBER SIGN and + * APOSTROPHE in a German layout, GRAVE + * ACCENT and POUND SIGN in a French Mac + * layout, and ASTERISK and MICRO SIGN in a + * French Windows layout. + */ NONUSHASH = 50, /**< ISO USB keyboards actually use this code - * instead of 49 for the same key, but all - * OSes I've seen treat the two codes - * identically. So, as an implementor, unless - * your keyboard generates both of those - * codes and your OS treats them differently, - * you should generate BACKSLASH - * instead of this code. As a user, you - * should not rely on this code because SDL - * will never generate it with most (all?) - * keyboards. - */ + * instead of 49 for the same key, but all + * OSes I've seen treat the two codes + * identically. So, as an implementor, unless + * your keyboard generates both of those + * codes and your OS treats them differently, + * you should generate BACKSLASH + * instead of this code. As a user, you + * should not rely on this code because SDL + * will never generate it with most (all?) + * keyboards. + */ SEMICOLON = 51, APOSTROPHE = 52, GRAVE = 53, /**< Located in the top left corner (on both ANSI - * and ISO keyboards). Produces GRAVE ACCENT and - * TILDE in a US Windows layout and in US and UK - * Mac layouts on ANSI keyboards, GRAVE ACCENT - * and NOT SIGN in a UK Windows layout, SECTION - * SIGN and PLUS-MINUS SIGN in US and UK Mac - * layouts on ISO keyboards, SECTION SIGN and - * DEGREE SIGN in a Swiss German layout (Mac: - * only on ISO keyboards), CIRCUMFLEX ACCENT and - * DEGREE SIGN in a German layout (Mac: only on - * ISO keyboards), SUPERSCRIPT TWO and TILDE in a - * French Windows layout, COMMERCIAL AT and - * NUMBER SIGN in a French Mac layout on ISO - * keyboards, and LESS-THAN SIGN and GREATER-THAN - * SIGN in a Swiss German, German, or French Mac - * layout on ANSI keyboards. - */ + * and ISO keyboards). Produces GRAVE ACCENT and + * TILDE in a US Windows layout and in US and UK + * Mac layouts on ANSI keyboards, GRAVE ACCENT + * and NOT SIGN in a UK Windows layout, SECTION + * SIGN and PLUS-MINUS SIGN in US and UK Mac + * layouts on ISO keyboards, SECTION SIGN and + * DEGREE SIGN in a Swiss German layout (Mac: + * only on ISO keyboards), CIRCUMFLEX ACCENT and + * DEGREE SIGN in a German layout (Mac: only on + * ISO keyboards), SUPERSCRIPT TWO and TILDE in a + * French Windows layout, COMMERCIAL AT and + * NUMBER SIGN in a French Mac layout on ISO + * keyboards, and LESS-THAN SIGN and GREATER-THAN + * SIGN in a Swiss German, German, or French Mac + * layout on ANSI keyboards. + */ COMMA = 54, PERIOD = 55, SLASH = 56, @@ -139,7 +149,7 @@ enum class ScanCode UP = 82, NUMLOCKCLEAR = 83, /**< num lock on PC, clear on Mac keyboards - */ + */ KP_DIVIDE = 84, KP_MULTIPLY = 85, KP_MINUS = 86, @@ -158,19 +168,19 @@ enum class ScanCode KP_PERIOD = 99, NONUSBACKSLASH = 100, /**< This is the additional key that ISO - * keyboards have over ANSI ones, - * located between left shift and Y. - * Produces GRAVE ACCENT and TILDE in a - * US or UK Mac layout, REVERSE SOLIDUS - * (backslash) and VERTICAL LINE in a - * US or UK Windows layout, and - * LESS-THAN SIGN and GREATER-THAN SIGN - * in a Swiss German, German, or French - * layout. */ + * keyboards have over ANSI ones, + * located between left shift and Y. + * Produces GRAVE ACCENT and TILDE in a + * US or UK Mac layout, REVERSE SOLIDUS + * (backslash) and VERTICAL LINE in a + * US or UK Windows layout, and + * LESS-THAN SIGN and GREATER-THAN SIGN + * in a Swiss German, German, or French + * layout. */ APPLICATION = 101, /**< windows contextual menu, compose */ POWER = 102, /**< The USB document says this is a status flag, - * not a physical key - but some Mac keyboards - * do have a power key. */ + * not a physical key - but some Mac keyboards + * do have a power key. */ KP_EQUALS = 103, F13 = 104, F14 = 105, @@ -295,9 +305,9 @@ enum class ScanCode RGUI = 231, /**< windows, command (apple), meta */ MODE = 257, /**< I'm not sure if this is really not covered - * by any of the above, but since there's a - * special SDL_KMOD_MODE for it I'm adding it here - */ + * by any of the above, but since there's a + * special SDL_KMOD_MODE for it I'm adding it here + */ /* @} */ /* Usage page 0x07 */ @@ -378,4 +388,10 @@ enum class ScanCode namespace Game { bool GetKey(ScanCode key); -} + bool GetKeyPressedNow(ScanCode key); + bool GetKeyReleasedNow(ScanCode key); + bool GetMouseButton(MouseButton button); + bool GetMouseButtonPressedNow(MouseButton button); + bool GetMouseButtonReleasedNow(MouseButton button); + Vec2 GetMouseMovement(); +} // namespace Game diff --git a/src/game/Instance.h b/src/game/Instance.h index b0ebd17..ffdd77e 100644 --- a/src/game/Instance.h +++ b/src/game/Instance.h @@ -5,14 +5,37 @@ namespace Game { + enum class PlayerMode + { + Walk, + Freefly, + }; + + struct Time + { + double Now = 0.0; + double Delta = 0.0; + uint32_t FrameCounter = 0; + int64_t StartTime = 0; + }; + + struct PlayerData + { + Transform FreeflyCamTransform; + float FreeflyXRot = 0.0f; + float FreeflyYRot = 0.0f; + Transform PlayerTransform; + Transform PlayerCamTransform; + PlayerMode Mode = PlayerMode::Freefly; + }; + struct GameInstance { bool IsInitialized = false; uint64_t Size = sizeof(GameInstance); - uint32_t FrameCounter = 0; - int64_t StartTime = 0; - double Now = 0.0; - double Delta = 0.0; + uint8_t UsedScratchAmount = 0; + Time Time; + PlayerData Player; Level GameLevel; }; } // namespace Game diff --git a/src/game/Level.cpp b/src/game/Level.cpp index e19d85b..a719528 100644 --- a/src/game/Level.cpp +++ b/src/game/Level.cpp @@ -27,7 +27,8 @@ namespace Game bgfx::setState(currentMaterial.State); float TimeValues[4]{0.0f}; - TimeValues[0] = GetInstance().Now; + TimeValues[0] = GetInstance().Time.Now; + bgfx::setTexture(0, currentMaterial.Textures[0].SamplerHandle, currentMaterial.Textures[0].Handle); bgfx::setUniform(currentMaterial.Uniforms[Material::UTime], TimeValues); bgfx::setUniform(currentMaterial.Uniforms[Material::UDotColor], TestColor); @@ -66,13 +67,40 @@ namespace Game void Level::Update() { - if (GetKey(ScanCode::R)) + PlayerData& player = GetInstance().Player; + if (GetKeyPressedNow(ScanCode::R)) { Cubes.Count = 0; Tests.Count = 0; Setup(GetShared().Game); } + float delta = GetInstance().Time.Delta; + constexpr float moveSpeed = 10.0f; + constexpr float rotSpeed = 0.6f; + + float forwardInput = (GetKey(ScanCode::W) ? 1.0f : 0.0f) + (GetKey(ScanCode::S) ? -1.0f : 0.0f); + float rightInput = (GetKey(ScanCode::D) ? 1.0f : 0.0f) + (GetKey(ScanCode::A) ? -1.0f : 0.0f); + bx::Vec3 moveInput = bx::Vec3{rightInput, forwardInput, 0.0f}; + moveInput = bx::normalize(moveInput); + bx::Vec3 inputVec = {moveInput.x * delta * moveSpeed, 0.0f, moveInput.y * delta * moveSpeed}; + + bx::Vec3 camForward = player.FreeflyCamTransform.Forward(); + bx::Vec3 camRight = player.FreeflyCamTransform.Right(); + + if (GetMouseButton(MouseButton::Left)) + { + Vec2 mouseMovement = GetMouseMovement(); + bx::Vec3 rotInput = {mouseMovement.y * delta * rotSpeed, mouseMovement.x * delta * rotSpeed, 0.0f}; + player.FreeflyXRot += rotInput.x; + player.FreeflyYRot += rotInput.y; + bx::mtxRotateY(player.FreeflyCamTransform.Rotation.M, player.FreeflyYRot); + player.FreeflyCamTransform.RotateLocal({player.FreeflyXRot, 0.0f, 0.0f}); + } + + player.FreeflyCamTransform.TranslateLocal({0.0f, 0.0f, -inputVec.z}); + player.FreeflyCamTransform.TranslateLocal({-inputVec.x, 0.0f, 0.0f}); + Cubes.Update(); Tests.Update(); } @@ -87,7 +115,7 @@ namespace Game { if (TestX >= 0 && TestY >= 0) { - double globalTime = GetInstance().Now; + double globalTime = GetInstance().Time.Now; double time = TestY <= 5 ? globalTime * 1.0f : 0.0f; float scale = 1.0f + TestX * 0.4f; EData.Transform.Position = bx::Vec3{TestX * 2.0f, TestY * 2.0f, 0.0f}; diff --git a/src/game/Setup.cpp b/src/game/Setup.cpp index 5cf6e24..b943118 100644 --- a/src/game/Setup.cpp +++ b/src/game/Setup.cpp @@ -2,6 +2,7 @@ #include "Instance.h" #include "Log.h" #include "Setup.h" +#include "bx/bx.h" #include "bx/timer.h" #include "rendering/Rendering.h" @@ -52,13 +53,18 @@ namespace Game void Update() { - ++GetInstance().FrameCounter; - double newNow = (bx::getHPCounter() - GetInstance().StartTime) / (double)(bx::getHPFrequency()); - GetInstance().Delta = newNow - GetInstance().Now; - GetInstance().Now = newNow; + ++GetInstance().Time.FrameCounter; + double newNow = (bx::getHPCounter() - GetInstance().Time.StartTime) / (double)(bx::getHPFrequency()); + GetInstance().Time.Delta = newNow - GetInstance().Time.Now; + GetInstance().Time.Now = newNow; + SetupInstance.Rendering.Update(); - GetShared().Window.MouseDeltaX = 0.0f; - GetShared().Window.MouseDeltaY = 0.0f; + + auto& win = GetShared().Window; + win.MouseDeltaX = 0.0f; + win.MouseDeltaY = 0.0f; + bx::memCopy(win.LastHeldScanCodes, win.HeldScanCodes, sizeof(win.HeldScanCodes)); + bx::memCopy(win.LastHeldMouseButtons, win.HeldMouseButtons, sizeof(win.HeldMouseButtons)); } void Shutdown() diff --git a/src/game/compiled-shaders/dx11/frag.bin b/src/game/compiled-shaders/dx11/frag.bin index 8fb21c4..b01d079 100644 Binary files a/src/game/compiled-shaders/dx11/frag.bin and b/src/game/compiled-shaders/dx11/frag.bin differ diff --git a/src/game/compiled-shaders/glsl/frag.bin b/src/game/compiled-shaders/glsl/frag.bin index 4c7502c..14e802b 100644 Binary files a/src/game/compiled-shaders/glsl/frag.bin and b/src/game/compiled-shaders/glsl/frag.bin differ diff --git a/src/game/compiled-shaders/spirv/frag.bin b/src/game/compiled-shaders/spirv/frag.bin index f8ee115..ef58272 100644 Binary files a/src/game/compiled-shaders/spirv/frag.bin and b/src/game/compiled-shaders/spirv/frag.bin differ diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index 82c8c4d..b7b7776 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -1,15 +1,18 @@ #include "../../engine/Shared.h" #include "../Global.h" -#include "../Input.h" #include "../Instance.h" #include "../Log.h" #include "../Mesh.h" #include "Rendering.h" + #include "bgfx/defines.h" +#include "bx/filepath.h" #include "bx/math.h" #include "bx/timer.h" #include +#include #include +#include #include using namespace std::chrono_literals; @@ -18,20 +21,34 @@ namespace Game { namespace { - static const bgfx::Memory* loadMem(bx::FileReaderI* _reader, const bx::FilePath& _filePath) + const bgfx::Memory* loadFile(const char* path, bool appendZero = false, int32_t retryCount = 1) { - if (bx::open(_reader, _filePath)) + FILE* file; + for (int32_t i = 0; i < retryCount; ++i) { - uint32_t size = (uint32_t)bx::getSize(_reader); - const bgfx::Memory* mem = bgfx::alloc(size + 1); - bx::read(_reader, mem->data, size, bx::ErrorAssert{}); - bx::close(_reader); - mem->data[mem->size - 1] = '\0'; + file = fopen(path, "rb"); + if (file == nullptr && i < retryCount - 1) + { + std::this_thread::sleep_for(100ms); + break; + } + + fseek(file, 0, SEEK_END); + long fileSize = ftell(file); + fseek(file, 0, SEEK_SET); + + const bgfx::Memory* mem = bgfx::alloc(fileSize + 1); + fread(mem->data, 1, fileSize, file); + if (appendZero) + { + mem->data[mem->size - 1] = '\0'; + } + fclose(file); + return mem; } - Log("Failed to load %s.", _filePath.getCPtr()); - return NULL; + return nullptr; } bgfx::ShaderHandle loadShader(const char* FILENAME) @@ -72,31 +89,98 @@ namespace Game bx::strCat(buffer, sizeof(buffer), ".bin"); Log("Loading shader at %s", buffer); + const bgfx::Memory* mem = loadFile(buffer, true, 3); - FILE* file; - for (int32_t i = 0; i < 3; ++i) + if (mem == nullptr) { - file = fopen(buffer, "rb"); - if (file == nullptr) - { - std::this_thread::sleep_for(100ms); - break; - } + Log("Failed to load shader %s", FILENAME); + return {}; + } + return bgfx::createShader(mem); + } - fseek(file, 0, SEEK_END); - long fileSize = ftell(file); - fseek(file, 0, SEEK_SET); + bgfx::TextureHandle loadTexture(const bx::FilePath& _filePath, + uint64_t _flags, + uint8_t _skip, + bgfx::TextureInfo* _info, + bimg::Orientation::Enum* _orientation) + { + BX_UNUSED(_skip); + bgfx::TextureHandle handle = BGFX_INVALID_HANDLE; + bx::Error err; - const bgfx::Memory* mem = bgfx::alloc(fileSize + 1); - fread(mem->data, 1, fileSize, file); - mem->data[mem->size - 1] = '\0'; - fclose(file); - - return bgfx::createShader(mem); + const bgfx::Memory* data = loadFile(_filePath.getCPtr()); + if (data == nullptr) + { + Log("Failed to find image %s", _filePath.getCPtr()); + return handle; + } + bimg::ImageContainer imageContainer; + if (!bimg::imageParse(imageContainer, data->data, data->size, &err)) + { + Log("Failed to load image %s", _filePath.getCPtr()); + return handle; + } + if (NULL != _orientation) + { + *_orientation = imageContainer.m_orientation; } - Log("Failed to load shader %s", FILENAME); - return {}; + const bgfx::Memory* mem = bgfx::makeRef(imageContainer.m_data, imageContainer.m_size); + + if (NULL != _info) + { + bgfx::calcTextureSize(*_info, + uint16_t(imageContainer.m_width), + uint16_t(imageContainer.m_height), + uint16_t(imageContainer.m_depth), + imageContainer.m_cubeMap, + 1 < imageContainer.m_numMips, + imageContainer.m_numLayers, + bgfx::TextureFormat::Enum(imageContainer.m_format)); + } + + if (imageContainer.m_cubeMap) + { + handle = bgfx::createTextureCube(uint16_t(imageContainer.m_width), + 1 < imageContainer.m_numMips, + imageContainer.m_numLayers, + bgfx::TextureFormat::Enum(imageContainer.m_format), + _flags, + mem); + } + else if (1 < imageContainer.m_depth) + { + handle = bgfx::createTexture3D(uint16_t(imageContainer.m_width), + uint16_t(imageContainer.m_height), + uint16_t(imageContainer.m_depth), + 1 < imageContainer.m_numMips, + bgfx::TextureFormat::Enum(imageContainer.m_format), + _flags, + mem); + } + else if (bgfx::isTextureValid(0, + false, + imageContainer.m_numLayers, + bgfx::TextureFormat::Enum(imageContainer.m_format), + _flags)) + { + handle = bgfx::createTexture2D(uint16_t(imageContainer.m_width), + uint16_t(imageContainer.m_height), + 1 < imageContainer.m_numMips, + imageContainer.m_numLayers, + bgfx::TextureFormat::Enum(imageContainer.m_format), + _flags, + mem); + } + + if (bgfx::isValid(handle)) + { + const bx::StringView name(_filePath); + bgfx::setName(handle, name.getPtr(), name.getLength()); + } + + return handle; } } // namespace @@ -108,7 +192,6 @@ namespace Game bgfx::Init init; init.type = bgfx::RendererType::Direct3D12; init.debug = true; - init.callback = &Callback; init.platformData.nwh = shared.Window.Handle; init.platformData.ndt = nullptr; init.platformData.type = bgfx::NativeWindowHandleType::Default; @@ -129,14 +212,18 @@ namespace Game bgfx::setDebug(BGFX_DEBUG_TEXT); bgfx::setViewClear(0, BGFX_CLEAR_COLOR | BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0); + DefaultSampler = bgfx::createUniform("s_texColor", bgfx::UniformType::Sampler); + Textures[0].Handle = + loadTexture(bx::FilePath{"models/body.dds"}, BGFX_TEXTURE_NONE | BGFX_SAMPLER_NONE, 0, nullptr, nullptr); + Textures[0].SamplerHandle = DefaultSampler; LoadMesh(Models[0], "models/cube.gltf"); LoadMesh(Models[1], "models/zurg.gltf"); - Materials[0] = Material::LoadFromShader("vert", "frag"); + Materials[0] = Material::LoadFromShader("vert", "frag", Textures[0].Handle, Textures[0].SamplerHandle); if (!GetInstance().IsInitialized) { - GetInstance().StartTime = bx::getHPCounter(); + GetInstance().Time.StartTime = bx::getHPCounter(); } } @@ -170,30 +257,6 @@ namespace Game { GetInstance().GameLevel.Update(); - - float delta = GetInstance().Delta; - constexpr float moveSpeed = 10.0f; - constexpr float rotSpeed = 0.6f; - - float forwardInput = (GetKey(ScanCode::W) ? 1.0f : 0.0f) + (GetKey(ScanCode::S) ? -1.0f : 0.0f); - float rightInput = (GetKey(ScanCode::D) ? 1.0f : 0.0f) + (GetKey(ScanCode::A) ? -1.0f : 0.0f); - bx::Vec3 moveInput = bx::Vec3{rightInput, forwardInput, 0.0f}; - moveInput = bx::normalize(moveInput); - bx::Vec3 inputVec = {moveInput.x * delta * moveSpeed, 0.0f, moveInput.y * delta * moveSpeed}; - - bx::Vec3 camForward = Cam.Transform.Forward(); - bx::Vec3 camRight = Cam.Transform.Right(); - - bx::Vec3 rotInput = { - shared.Window.MouseDeltaY * delta * rotSpeed, shared.Window.MouseDeltaX * delta * rotSpeed, 0.0f}; - Cam.FreelookXRot += rotInput.x; - Cam.FreelookYRot += rotInput.y; - bx::mtxRotateY(Cam.Transform.Rotation.M, Cam.FreelookYRot); - Cam.Transform.RotateLocal({Cam.FreelookXRot, 0.0f, 0.0f}); - - Cam.Transform.TranslateLocal({0.0f, 0.0f, -inputVec.z}); - Cam.Transform.TranslateLocal({-inputVec.x, 0.0f, 0.0f}); - bgfx::dbgTextPrintf(1, 4, 0x0f, "Cam forward: %.2f %.2f %.2f", camForward.x, camForward.y, camForward.z); } // Set view and projection matrix for view 0. @@ -205,8 +268,17 @@ namespace Game 0.1f, 1000.0f, bgfx::getCaps()->homogeneousDepth); - Cam.Transform.UpdateMatrix(); - bgfx::setViewTransform(0, Cam.Transform.M.M, proj); + + auto& player = GetInstance().Player; + if (player.Mode == PlayerMode::Freefly) + { + player.FreeflyCamTransform.UpdateMatrix(); + bgfx::setViewTransform(0, player.FreeflyCamTransform.M.M, proj); + } + else + { + // TODO + } // Set view 0 default viewport. bgfx::setViewRect(0, 0, 0, shared.Window.WindowWidth, shared.Window.WindowHeight); @@ -215,9 +287,10 @@ namespace Game GetInstance().GameLevel.Cubes.Render(Models, Materials); GetInstance().GameLevel.Tests.Render(Models, Materials); - bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1f", GetInstance().Now); - bgfx::dbgTextPrintf(1, 2, 0x0F, "Frame: %u", GetInstance().FrameCounter); - bgfx::dbgTextPrintf(1, 3, 0x0F, "Delta: %.3fms / %.0ffps", GetInstance().Delta, 1.0 / GetInstance().Delta); + bgfx::dbgTextPrintf(1, 1, 0x0F, "Time: %.1f", GetInstance().Time.Now); + bgfx::dbgTextPrintf(1, 2, 0x0F, "Frame: %u", GetInstance().Time.FrameCounter); + bgfx::dbgTextPrintf( + 1, 3, 0x0F, "Delta: %.3fms / %.0ffps", GetInstance().Time.Delta, 1.0 / GetInstance().Time.Delta); bgfx::frame(); } @@ -227,10 +300,14 @@ namespace Game bgfx::shutdown(); } - Material Material::LoadFromShader(const char* vertPath, const char* fragPath) + Material Material::LoadFromShader(const char* vertPath, + const char* fragPath, + bgfx::TextureHandle tex, + bgfx::UniformHandle sampler) { - bgfx::ShaderHandle vertexShader = loadShader("vert"); - bgfx::ShaderHandle fragmentShader = loadShader("frag"); + BX_ASSERT(vertPath != nullptr && fragPath != nullptr, "Invalid shader path!"); + bgfx::ShaderHandle vertexShader = loadShader(vertPath); + bgfx::ShaderHandle fragmentShader = loadShader(fragPath); Material mat; mat.Shader = bgfx::createProgram(vertexShader, fragmentShader, true); @@ -238,6 +315,8 @@ namespace Game BGFX_STATE_CULL_CCW | BGFX_STATE_MSAA; mat.Uniforms[Material::UTime] = bgfx::createUniform("u_time", bgfx::UniformType::Vec4); mat.Uniforms[Material::UDotColor] = bgfx::createUniform("u_testColor", bgfx::UniformType::Vec4); + mat.Textures[0].Handle = tex; + mat.Textures[0].SamplerHandle = sampler; return mat; } } // namespace Game diff --git a/src/game/rendering/Rendering.h b/src/game/rendering/Rendering.h index faf3e48..e0988a0 100644 --- a/src/game/rendering/Rendering.h +++ b/src/game/rendering/Rendering.h @@ -1,8 +1,7 @@ #pragma once -#include "../Global.h" #include #include -#include +#include namespace Game { @@ -19,84 +18,10 @@ namespace Game float uv_y; }; - struct BgfxCallback : public bgfx::CallbackI + struct Texture { - virtual ~BgfxCallback() - { - } - - virtual void fatal(const char* _filePath, uint16_t _line, bgfx::Fatal::Enum _code, const char* _str) override - { - // Something unexpected happened, inform user and bail out. - printf("Fatal error: 0x%08x: %s", _code, _str); - - // Must terminate, continuing will cause crash anyway. - abort(); - } - - virtual void traceVargs(const char* _filePath, uint16_t _line, const char* _format, va_list _argList) override - { - printf("%s (%d): ", _filePath, _line); - vprintf(_format, _argList); - } - - virtual void profilerBegin(const char* /*_name*/, - uint32_t /*_abgr*/, - const char* /*_filePath*/, - uint16_t /*_line*/) override - { - } - - virtual void profilerBeginLiteral(const char* /*_name*/, - uint32_t /*_abgr*/, - const char* /*_filePath*/, - uint16_t /*_line*/) override - { - } - - virtual void profilerEnd() override - { - } - - virtual uint32_t cacheReadSize(uint64_t _id) override - { - return 0; - } - - virtual bool cacheRead(uint64_t _id, void* _data, uint32_t _size) override - { - return false; - } - - virtual void cacheWrite(uint64_t _id, const void* _data, uint32_t _size) override - { - } - - virtual void screenShot(const char* _filePath, - uint32_t _width, - uint32_t _height, - uint32_t _pitch, - const void* _data, - uint32_t /*_size*/, - bool _yflip) override - { - } - - virtual void captureBegin(uint32_t _width, - uint32_t _height, - uint32_t /*_pitch*/, - bgfx::TextureFormat::Enum /*_format*/, - bool _yflip) override - { - } - - virtual void captureEnd() override - { - } - - virtual void captureFrame(const void* _data, uint32_t /*_size*/) override - { - } + bgfx::UniformHandle SamplerHandle; + bgfx::TextureHandle Handle; }; struct Model @@ -116,24 +41,21 @@ namespace Game bgfx::ProgramHandle Shader; bgfx::UniformHandle Uniforms[8]; + Texture Textures[4]; uint64_t State = 0; - static Material LoadFromShader(const char* vertPath, const char* fragPath); - }; - - struct Camera - { - float FreelookXRot = 0.0f; - float FreelookYRot = 0.0f; - Transform Transform; + static Material LoadFromShader(const char* vertPath, + const char* fragPath, + bgfx::TextureHandle = BGFX_INVALID_HANDLE, + bgfx::UniformHandle sampler = BGFX_INVALID_HANDLE); }; class GameRendering { private: + bgfx::UniformHandle DefaultSampler; + Texture Textures[8]; Material Materials[8]; Model Models[8]; - BgfxCallback Callback; - Camera Cam; public: void Setup(); diff --git a/src/game/shaders/frag.sc b/src/game/shaders/frag.sc index 17823e8..0526edf 100644 --- a/src/game/shaders/frag.sc +++ b/src/game/shaders/frag.sc @@ -3,11 +3,12 @@ $input v_normal $input v_uv0 $input v_wpos +#include "common.sh" + +SAMPLER2D(s_texColor, 0); uniform vec4 u_time; uniform vec4 u_testColor; -#include "common.sh" - float circle(vec2 uv, float radius) { float distSq = uv.x * uv.x + uv.y * uv.y; @@ -86,4 +87,5 @@ void main() // gl_FragColor = brightness; // gl_FragColor = dither; // gl_FragColor = u_testColor; + gl_FragColor = texture2D(s_texColor, v_uv0); } diff --git a/src/game/shaders/vert.sc b/src/game/shaders/vert.sc index 746d180..acb1f28 100644 --- a/src/game/shaders/vert.sc +++ b/src/game/shaders/vert.sc @@ -10,5 +10,5 @@ void main() v_uv0 = a_texcoord0; v_wpos = mul(u_model[0], vec4(a_position, 1.0)).xyz; - v_normal = normalize(mul((mat3)u_model[0], a_normal)); + v_normal = normalize(mul(mat3(u_model[0]), a_normal)); } diff --git a/src/setup-release.bat b/src/setup-release.bat new file mode 100644 index 0000000..b0eeec6 --- /dev/null +++ b/src/setup-release.bat @@ -0,0 +1,4 @@ +cd dependency/bgfx.cmake +cmake -G "Ninja" -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DBGFX_BUILD_TOOLS=OFF -DBGFX_BUILD_EXAMPLES=OFF +cd ..\.. +cmake -G "Ninja" -S . -B cmake-build-release -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER="clang.exe" -DCMAKE_CXX_COMPILER="clang++.exe" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON