From fc67ff62be57a9abb830e7c6b2773b76bea69800 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Till=20W=C3=BCbbers?= Date: Sat, 29 Mar 2025 05:10:13 +0100 Subject: [PATCH] cleanup --- src/CMakeLists.txt | 1 + src/engine/main.cpp | 7 +- src/game/Tools.cpp | 286 +++++++++++++++++++++- src/game/Tools.h | 2 + src/game/rendering/Dither.cpp | 120 ++++++++++ src/game/rendering/Dither.h | 26 ++ src/game/rendering/Rendering.cpp | 399 +------------------------------ src/game/rendering/Rendering.h | 24 +- 8 files changed, 443 insertions(+), 422 deletions(-) create mode 100644 src/game/rendering/Dither.cpp create mode 100644 src/game/rendering/Dither.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index af3f866..8009357 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.10) project(PuzGameProj) if (MSVC) +add_definitions(-D_CRT_SECURE_NO_WARNINGS) else() add_compile_options(-g -gcodeview) add_link_options(-fuse-ld=lld -g -Wl,--pdb=) diff --git a/src/engine/main.cpp b/src/engine/main.cpp index 7bc1060..1a3bfbd 100644 --- a/src/engine/main.cpp +++ b/src/engine/main.cpp @@ -279,7 +279,12 @@ int main() 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"); + char exePath[1024]; + GetModuleFileName(nullptr, exePath, BX_COUNTOF(exePath)); + bx::FilePath exeFilePath{exePath}; + bx::FilePath exeDir{exeFilePath.getPath()}; + bx::strCopy( + DevData.FileWatcher.DLLWatcher.DirPath, sizeof(DevData.FileWatcher.DLLWatcher.DirPath), exeDir.getCPtr()); bx::strCopy( DevData.FileWatcher.ShaderWatcher.DirPath, sizeof(DevData.FileWatcher.ShaderWatcher.DirPath), "game/shaders"); bx::strCopy(DevData.FileWatcher.CompiledShaderWatcher.DirPath, diff --git a/src/game/Tools.cpp b/src/game/Tools.cpp index 8a8f8ee..919a2a8 100644 --- a/src/game/Tools.cpp +++ b/src/game/Tools.cpp @@ -1,9 +1,9 @@ -#include "Global.h" #include "Instance.h" +#include "Mesh.h" #include "Tools.h" -#include "rendering/Rendering.h" #include +#include namespace Tools { @@ -61,4 +61,286 @@ namespace Tools ImGui::EndCombo(); } } + void RenderDebugUI(Game::GameRendering& rendering) + { + auto& time = Game::GetInstance().Time; + if (rendering.UIVisible == Game::UIVisibilityState::Debug) + { + ZoneScopedN("DebugUI"); + + auto& shared = Game::GetShared(); + auto& debug = Game::GetInstance().DebugData; + auto& level = Game::GetInstance().GameLevel; + + if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) + { + debug.DebugCardRotation++; + if (debug.DebugCardRotation >= 4) debug.DebugCardRotation = 0; + } + if (ImGui::Begin("Log")) + { + ImGui::Checkbox("Shorten File Names", &debug.ShortenLogFileNames); + ImGui::BeginTable( + "tbl", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_SizingFixedFit); + ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_NoResize); + ImGui::TableSetupColumn("Log"); + ImGui::TableSetupColumn("Line", ImGuiTableColumnFlags_NoResize); + ImGui::TableSetupColumn("File", ImGuiTableColumnFlags_NoResize); + ImGui::TableHeadersRow(); + for (int32_t i = 0; i < bx::min(100, LogInternal::LogHistorySize); ++i) + { + int32_t idx = GetLogHistory().WriteIdx - i - 1; + if (idx < 0) idx += LogInternal::LogHistorySize; + const char* line = &GetLogHistory().LogBuffer[idx * LogInternal::MaxLineSize]; + if (line[0] != 0) + { + int64_t timeOffset = GetLogHistory().WriteTime[idx] - time.StartTime; + double writeTime = (double)timeOffset / bx::getHPFrequency(); + uint32_t fileLine = GetLogHistory().LineBuffer[idx]; + const char* filePath = &GetLogHistory().FileBuffer[idx * LogInternal::MaxLineSize]; + const char* filePathRes = + debug.ShortenLogFileNames ? bx::FilePath{filePath}.getFileName().getPtr() : filePath; + + ImGui::TableNextRow(); + ImGui::TableNextColumn(); + ImGui::Text("%.01f", writeTime); + + ImGui::TableNextColumn(); + ImGui::Text("%s", line); + ImGui::SetItemTooltip("%f\n%s%s:%u", writeTime, line, filePath, fileLine); + + ImGui::TableNextColumn(); + ImGui::Text("%u", fileLine); + + ImGui::TableNextColumn(); + ImGui::Text("%s", filePathRes); + } + } + ImGui::EndTable(); + } + ImGui::End(); + if (ImGui::Begin("Rendering")) + { + if (rendering.LastShaderLoadTime >= 0.0f) + { + ImGui::TextColored({0.2f, 0.9f, 0.2f, 1.0f}, + "Shader loaded %.0f seconds ago", + time.Now - rendering.LastShaderLoadTime); + } + else + { + ImGui::TextColored({0.9f, 0.2f, 0.2f, 1.0f}, "Shader load Failiure!"); + } + if (ImGui::Button("Reload Meshes")) + { + LoadModels(rendering.Models, rendering.ModelCount); + } + ImGui::SameLine(); + if (ImGui::Button("Reload Level")) + { + level = {}; + level.Setup(shared.Game); + } + ImGui::Checkbox("Show ImGui Demo", &debug.ShowImguiDemo); + if (debug.ShowImguiDemo) ImGui::ShowDemoWindow(&debug.ShowImguiDemo); + ImGui::Separator(); + + ImGui::Checkbox("Cubes", &level.Cubes.IsEnabled); + ImGui::Checkbox("Tests", &level.Tests.IsEnabled); + ImGui::Checkbox("PuzzleTiles", &level.PuzzleTiles.IsEnabled); + ImGui::Checkbox("UIQuads", &level.UIQuads.IsEnabled); + + if (ImGui::Button("Dithergen")) + { + DitherGen(rendering.DitherTextures, rendering.DitherRecursion); + } + ImGui::SameLine(); + ImGui::SliderInt("Recursion", &rendering.DitherRecursion, 1, 4); + ImGui::Text("%ux%ux%u", + rendering.DitherTextures.DitherTexWH, + rendering.DitherTextures.DitherTexWH, + rendering.DitherTextures.DitherTexDepth); + if (!isValid(rendering.DitherTextures.PreviewTex)) + { + ImGui::Text("Invalid Texture"); + } + else + { + ImGui::Image( + rendering.DitherTextures.PreviewTex.idx, + {(float)rendering.DitherTextures.DitherTexWH, + (float)rendering.DitherTextures.DitherTexWH * rendering.DitherTextures.DitherTexDepth}); + } + if (isValid(rendering.DitherTextures.RampTex)) + { + ImGui::Image(rendering.DitherTextures.RampTex.idx, + {BX_COUNTOF(rendering.DitherTextures.BrightnessRamp), 8}); + } + Vec3 quadPos = level.UIQuads.Get({0}).EData.Transform.GetPosition(); + ImGui::Text("%f %f %f", quadPos.x, quadPos.y, quadPos.z); + + if (ImGui::ColorEdit3("Base Color", &rendering.DefaultBaseColor.x)) + { + auto& tiles = level.PuzzleTiles; + for (int32_t i = 0; i < tiles.Count; ++i) + { + tiles.Data[i].EData.BaseColor = rendering.DefaultBaseColor; + } + } + if (ImGui::ColorEdit3("Dot Color", &rendering.DefaultTileColor.x)) + { + auto& tiles = level.PuzzleTiles; + for (int32_t i = 0; i < tiles.Count; ++i) + { + tiles.Data[i].EData.TestColor = rendering.DefaultTileColor; + } + } + + ImGui::Text("Shader log:"); + ImGui::TextWrapped("%s", Game::GetShared().Dev.ShaderLog); + } + ImGui::End(); + if (ImGui::Begin("Textures")) + { + if (ImGui::Button("Reload")) + { + rendering.LoadTextures(); + } + for (int32_t i = 0; i < rendering.MaxTextures; ++i) + { + if (!isValid(rendering.Textures[i].RenderHandle)) continue; + ImGui::Text("%i", i); + float width = bx::min(ImGui::GetContentRegionAvail().x, rendering.Textures[i].Info.width); + float height = bx::min(ImGui::GetContentRegionAvail().x, rendering.Textures[i].Info.height); + ImGui::Image(rendering.Textures[i].RenderHandle.idx, {width, height}); + } + } + ImGui::End(); + if (ImGui::Begin("Puzzles")) + { + if (ImGui::Button("Add")) + { + bool found = false; + for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) + { + auto& puz = level.Puzzles[i].Data; + if (puz.ID == UINT16_MAX) + { + bx::strCopy(puz.PuzzleName, sizeof(puz.PuzzleName), "Unnamed Puzzle"); + puz.ID = i; + found = true; + break; + } + } + if (!found) + { + LOG_ERROR("Too many puzzles!"); + } + } + ImGui::Separator(); + for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) + { + auto& puzzleData = level.Puzzles[i].Data; + if (puzzleData.ID == UINT16_MAX) continue; + + bool isSelected = debug.SelectedDebugLevel == i; + ImGui::PushID("selectable"); + if (ImGui::Selectable(puzzleData.PuzzleName, isSelected)) + { + debug.SelectedDebugLevel = isSelected ? UINT16_MAX : i; + } + ImGui::PopID(); + } + } + ImGui::End(); + if (debug.SelectedDebugLevel < BX_COUNTOF(level.Puzzles)) + { + if (!Puzzle::RenderDebugUI(level.Puzzles[debug.SelectedDebugLevel].Data)) + { + debug.SelectedDebugLevel = UINT16_MAX; + } + } + if (ImGui::Begin("Cards")) + { + Generated::StaticPuzzleData& staticData = Puzzle::GetStaticPuzzleData(); + if (ImGui::Button("Save")) + { + Puzzle::SaveStaticPuzzleData(); + } + ImGui::SameLine(); + if (ImGui::Button("Reload")) + { + Puzzle::LoadStaticPuzzleData(); + } + + for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i) + { + ImGui::Separator(); + + Generated::StaticPuzzleCard& card = staticData.Cards[i]; + ImGui::PushID(i); + char cardName[64]{0}; + bx::snprintf(cardName, sizeof(cardName), "%i", i); + ImGui::Selectable(cardName); + if (ImGui::BeginDragDropSource()) + { + Puzzle::DrawCard(card, debug.DebugCardRotation, ImGui::GetCursorScreenPos()); + ImGui::SetDragDropPayload("cardtype", &i, sizeof(i)); + ImGui::EndDragDropSource(); + } + + Tools::ModelDropdown(card.ModelHandle); + Tools::TextureDropdown(card.BoardTextureHandle); + for (int8_t y = 0; y < Puzzle::Config::CardSize; ++y) + { + ImGui::PushID(y); + for (int8_t x = 0; x < Puzzle::Config::CardSize; ++x) + { + if (x > 0) ImGui::SameLine(); + ImGui::PushID(x); + auto& node = Puzzle::EditCardNodeAt(card, 0, x, y); + if (ImGui::Button(Generated::PuzzleElementType::ShortName[node], {26, 24})) + { + int32_t newVal = int32_t(node) + 1; + if (newVal >= Generated::PuzzleElementType::EntryCount) + { + newVal = 0; + } + node = Generated::PuzzleElementType::Enum(newVal); + } + ImGui::PopID(); + } + ImGui::PopID(); + } + ImGui::PopID(); + } + } + ImGui::End(); + } + ImGui::SetNextWindowPos({0, 0}); + if (ImGui::Begin("Stats", + nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs | + ImGuiWindowFlags_AlwaysAutoResize)) + { + if (Game::GetInstance().Player.CameraM == Game::CameraMode::Freefly) + { + ImGui::PushStyleColor(ImGuiCol_Text, {0.8f, 0.1f, 0.1f, 1.0f}); + ImGui::Text("NOCLIP"); + ImGui::PopStyleColor(); + } + ImGui::Text("Delta: %.01fms", time.Delta * 1000); + ImGui::Text("FPS: %.0f", 1.0 / time.Delta); + + constexpr ImVec2 FpsPlotSize{200, 60}; + if (ImGui::BeginChild("FpsPlot", FpsPlotSize)) + { + auto& drawList = *ImGui::GetWindowDrawList(); + ImVec2 pos = ImGui::GetWindowPos(); + drawList.AddRectFilled(pos, {pos.x + FpsPlotSize.x, pos.y + FpsPlotSize.y}, 0xFFFFFF33); + } + ImGui::EndChild(); + } + ImGui::End(); + } } // namespace Tools diff --git a/src/game/Tools.h b/src/game/Tools.h index a694051..87f1e44 100644 --- a/src/game/Tools.h +++ b/src/game/Tools.h @@ -1,8 +1,10 @@ #pragma once #include "Gen.h" +#include "rendering/Rendering.h" namespace Tools { void ModelDropdown(Generated::ModelHandle& modelHandle); void TextureDropdown(Generated::TextureHandle& texHandle); + void RenderDebugUI(Game::GameRendering& rendering); } // namespace Tools diff --git a/src/game/rendering/Dither.cpp b/src/game/rendering/Dither.cpp new file mode 100644 index 0000000..b44fb7f --- /dev/null +++ b/src/game/rendering/Dither.cpp @@ -0,0 +1,120 @@ +#include "../Log.h" +#include "Dither.h" + +void DitherGen(DitherData& data, int32_t recursion) +{ + data.Points[0] = {0.0f, 0.0f}; + data.Points[1] = {0.5f, 0.5f}; + data.Points[2] = {0.5f, 0.0f}; + data.Points[3] = {0.0f, 0.5f}; + data.PointCount = 4; + for (int32_t i = 0; i < data.BrightnessBucketCount; ++i) + data.BrightnessBuckets[i] = 0; + + for (int32_t recursionLevel = 0; recursionLevel < recursion; ++recursionLevel) + { + int32_t startCount = data.PointCount; + float offset = bx::pow(0.5f, recursionLevel + 1); + for (int32_t i = 0; i < 4; ++i) + { + for (int32_t j = 0; j < startCount; ++j) + { + data.Points[data.PointCount] = data.Points[j] + data.Points[i] * offset; + data.PointCount++; + } + } + } + + uint64_t dotsPerSide = bx::round(bx::pow(2, recursion)); + data.DitherTexDepth = dotsPerSide * dotsPerSide; + data.DitherTexWH = 16 * dotsPerSide; + uint64_t texPixelCount = data.DitherTexWH * data.DitherTexWH * data.DitherTexDepth; + + if (BX_COUNTOF(DitherData::DitherTex) < texPixelCount) + { + LOG_ERROR("Too many pixels: %llu", texPixelCount); + return; + } + + float invRes = 1.0f / data.DitherTexWH; + for (int32_t z = 0; z < data.DitherTexDepth; ++z) + { + int32_t dotCount = z + 1; + float dotArea = 0.5f / dotCount; + float dotRadius = bx::sqrt(dotArea / bx::kPi); + + int zOffset = z * data.DitherTexWH * data.DitherTexWH; + for (int32_t y = 0; y < data.DitherTexWH; ++y) + { + int32_t yOffset = y * data.DitherTexWH; + for (int32_t x = 0; x < data.DitherTexWH; ++x) + { + Vec2 point{(x + 0.5f) * invRes, (y + 0.5f) * invRes}; + float dist = bx::kFloatInfinity; + for (int32_t i = 0; i < dotCount; ++i) + { + Vec2 vec = point - data.Points[i]; + Vec2 wrappedVec{bx::mod(vec.x + 0.5f, 1.0f) - 0.5f, bx::mod(vec.y + 0.5f, 1.0f) - 0.5f}; + float curDist = wrappedVec.Magnitude(); + dist = bx::min(dist, curDist); + } + + dist = dist / (dotRadius * 2.4f); + float val = bx::clamp(1.0f - dist, 0.0f, 1.0f); + data.DitherTex[x + yOffset + zOffset] = Vec4{val, val, val, 1.0f}; + // data.DitherTex[x + yOffset + zOffset] = Vec4{1.0, 0.0f, 0.0f, 1.0f}; + int32_t bucket = bx::clamp( + uint32_t(val * DitherData::BrightnessBucketCount), 0, DitherData::BrightnessBucketCount - 1); + data.BrightnessBuckets[bucket] += 1; + } + } + } + + // Brightness ramp + int32_t sum = 0; + for (int32_t i = 0; i < data.BrightnessBucketCount; ++i) + { + sum += data.BrightnessBuckets[data.BrightnessBucketCount - 1 - i]; + data.BrightnessRamp[i + 1] = sum / (float)texPixelCount; + } + + // Upload textures + if (isValid(data.PreviewTex)) + { + bgfx::destroy(data.PreviewTex); + data.PreviewTex = BGFX_INVALID_HANDLE; + } + if (isValid(data.FinalTex)) + { + bgfx::destroy(data.FinalTex); + data.FinalTex = BGFX_INVALID_HANDLE; + } + if (isValid(data.RampTex)) + { + bgfx::destroy(data.RampTex); + data.RampTex = BGFX_INVALID_HANDLE; + } + const bgfx::Memory* memPreview = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4)); + const bgfx::Memory* memFinal = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4)); + const bgfx::Memory* memRamp = bgfx::makeRef(data.BrightnessRamp, sizeof(data.BrightnessRamp)); + data.PreviewTex = bgfx::createTexture2D(data.DitherTexWH, + data.DitherTexWH * data.DitherTexDepth, + false, + false, + bgfx::TextureFormat::RGBA32F, + 0, + memPreview); + data.FinalTex = bgfx::createTexture3D( + data.DitherTexWH, data.DitherTexWH, data.DitherTexDepth, false, bgfx::TextureFormat::RGBA32F, 0, memFinal); + data.RampTex = + bgfx::createTexture2D(BX_COUNTOF(data.BrightnessRamp), 1, false, 1, bgfx::TextureFormat::R32F, 0, memRamp); + + if (!isValid(data.DitherSampler)) + { + data.DitherSampler = bgfx::createUniform("s_ditherSampler", bgfx::UniformType::Sampler); + } + if (!isValid(data.RampSampler)) + { + data.RampSampler = bgfx::createUniform("s_rampSampler", bgfx::UniformType::Sampler); + } +} diff --git a/src/game/rendering/Dither.h b/src/game/rendering/Dither.h new file mode 100644 index 0000000..c52cbb3 --- /dev/null +++ b/src/game/rendering/Dither.h @@ -0,0 +1,26 @@ +#pragma once +#include "../Global.h" + +#include +#include + +struct DitherData +{ + static constexpr uint32_t BrightnessBucketCount = 256; + Vec2 Points[4096]; + uint32_t PointCount = 0; + Vec4 DitherTex[256 * 256 * 64]; + uint32_t DitherTexWH = 0; + uint32_t DitherTexDepth = 0; + int32_t BrightnessBuckets[BrightnessBucketCount]; + float BrightnessRamp[BrightnessBucketCount + 1]; + bgfx::TextureHandle PreviewTex = BGFX_INVALID_HANDLE; + bgfx::TextureHandle FinalTex = BGFX_INVALID_HANDLE; + bgfx::TextureHandle RampTex = BGFX_INVALID_HANDLE; + + bgfx::UniformHandle DitherSampler = BGFX_INVALID_HANDLE; + bgfx::UniformHandle RampSampler = BGFX_INVALID_HANDLE; + ImTextureID PreviewID = 0; +}; + +void DitherGen(DitherData& data, int32_t recursion); diff --git a/src/game/rendering/Rendering.cpp b/src/game/rendering/Rendering.cpp index cb7e314..5a046a5 100644 --- a/src/game/rendering/Rendering.cpp +++ b/src/game/rendering/Rendering.cpp @@ -206,130 +206,6 @@ namespace Game return handle; } - void DitherGen(DitherData& data, int32_t recursion) - { - data.Points[0] = {0.0f, 0.0f}; - data.Points[1] = {0.5f, 0.5f}; - data.Points[2] = {0.5f, 0.0f}; - data.Points[3] = {0.0f, 0.5f}; - data.PointCount = 4; - for (int32_t i = 0; i < data.BrightnessBucketCount; ++i) - data.BrightnessBuckets[i] = 0; - - for (int32_t recursionLevel = 0; recursionLevel < recursion; ++recursionLevel) - { - int32_t startCount = data.PointCount; - float offset = bx::pow(0.5f, recursionLevel + 1); - for (int32_t i = 0; i < 4; ++i) - { - for (int32_t j = 0; j < startCount; ++j) - { - data.Points[data.PointCount] = data.Points[j] + data.Points[i] * offset; - data.PointCount++; - } - } - } - - uint64_t dotsPerSide = bx::round(bx::pow(2, recursion)); - data.DitherTexDepth = dotsPerSide * dotsPerSide; - data.DitherTexWH = 16 * dotsPerSide; - uint64_t texPixelCount = data.DitherTexWH * data.DitherTexWH * data.DitherTexDepth; - - if (BX_COUNTOF(DitherData::DitherTex) < texPixelCount) - { - LOG_ERROR("Too many pixels: %llu", texPixelCount); - return; - } - - float invRes = 1.0f / data.DitherTexWH; - for (int32_t z = 0; z < data.DitherTexDepth; ++z) - { - int32_t dotCount = z + 1; - float dotArea = 0.5f / dotCount; - float dotRadius = bx::sqrt(dotArea / bx::kPi); - - int zOffset = z * data.DitherTexWH * data.DitherTexWH; - for (int32_t y = 0; y < data.DitherTexWH; ++y) - { - int32_t yOffset = y * data.DitherTexWH; - for (int32_t x = 0; x < data.DitherTexWH; ++x) - { - Vec2 point{(x + 0.5f) * invRes, (y + 0.5f) * invRes}; - float dist = bx::kFloatInfinity; - for (int32_t i = 0; i < dotCount; ++i) - { - Vec2 vec = point - data.Points[i]; - Vec2 wrappedVec{bx::mod(vec.x + 0.5f, 1.0f) - 0.5f, bx::mod(vec.y + 0.5f, 1.0f) - 0.5f}; - float curDist = wrappedVec.Magnitude(); - dist = bx::min(dist, curDist); - } - - dist = dist / (dotRadius * 2.4f); - float val = bx::clamp(1.0f - dist, 0.0f, 1.0f); - data.DitherTex[x + yOffset + zOffset] = Vec4{val, val, val, 1.0f}; - // data.DitherTex[x + yOffset + zOffset] = Vec4{1.0, 0.0f, 0.0f, 1.0f}; - int32_t bucket = bx::clamp(uint32_t(val * DitherData::BrightnessBucketCount), - 0, - DitherData::BrightnessBucketCount - 1); - data.BrightnessBuckets[bucket] += 1; - } - } - } - - // Brightness ramp - int32_t sum = 0; - for (int32_t i = 0; i < data.BrightnessBucketCount; ++i) - { - sum += data.BrightnessBuckets[data.BrightnessBucketCount - 1 - i]; - data.BrightnessRamp[i + 1] = sum / (float)texPixelCount; - } - - // Upload textures - if (isValid(data.PreviewTex)) - { - bgfx::destroy(data.PreviewTex); - data.PreviewTex = BGFX_INVALID_HANDLE; - } - if (isValid(data.FinalTex)) - { - bgfx::destroy(data.FinalTex); - data.FinalTex = BGFX_INVALID_HANDLE; - } - if (isValid(data.RampTex)) - { - bgfx::destroy(data.RampTex); - data.RampTex = BGFX_INVALID_HANDLE; - } - const bgfx::Memory* memPreview = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4)); - const bgfx::Memory* memFinal = bgfx::makeRef(data.DitherTex, texPixelCount * sizeof(Vec4)); - const bgfx::Memory* memRamp = bgfx::makeRef(data.BrightnessRamp, sizeof(data.BrightnessRamp)); - data.PreviewTex = bgfx::createTexture2D(data.DitherTexWH, - data.DitherTexWH * data.DitherTexDepth, - false, - false, - bgfx::TextureFormat::RGBA32F, - 0, - memPreview); - data.FinalTex = bgfx::createTexture3D(data.DitherTexWH, - data.DitherTexWH, - data.DitherTexDepth, - false, - bgfx::TextureFormat::RGBA32F, - 0, - memFinal); - data.RampTex = bgfx::createTexture2D( - BX_COUNTOF(data.BrightnessRamp), 1, false, 1, bgfx::TextureFormat::R32F, 0, memRamp); - - if (!isValid(data.DitherSampler)) - { - data.DitherSampler = bgfx::createUniform("s_ditherSampler", bgfx::UniformType::Sampler); - } - if (!isValid(data.RampSampler)) - { - data.RampSampler = bgfx::createUniform("s_rampSampler", bgfx::UniformType::Sampler); - } - } - GameRendering* Instance = nullptr; } // namespace @@ -351,7 +227,7 @@ namespace Game bgfx::Init init; init.type = bgfx::RendererType::Direct3D12; #ifdef _DEBUG - init.debug = true; + // init.debug = true; #endif init.platformData.nwh = shared.Window.Handle; init.platformData.ndt = nullptr; @@ -455,258 +331,6 @@ namespace Game } } - void GameRendering::RenderDebugUI() - { - ZoneScopedN("DebugUI"); - - auto& shared = GetShared(); - auto& debug = GetInstance().DebugData; - auto& level = GetInstance().GameLevel; - auto& time = GetInstance().Time; - - if (ImGui::IsMouseClicked(ImGuiMouseButton_Right)) - { - debug.DebugCardRotation++; - if (debug.DebugCardRotation >= 4) debug.DebugCardRotation = 0; - } - if (ImGui::Begin("Log")) - { - ImGui::Checkbox("Shorten File Names", &GetInstance().DebugData.ShortenLogFileNames); - ImGui::BeginTable( - "tbl", 4, ImGuiTableFlags_Resizable | ImGuiTableFlags_Hideable | ImGuiTableFlags_SizingFixedFit); - ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_NoResize); - ImGui::TableSetupColumn("Log"); - ImGui::TableSetupColumn("Line", ImGuiTableColumnFlags_NoResize); - ImGui::TableSetupColumn("File", ImGuiTableColumnFlags_NoResize); - ImGui::TableHeadersRow(); - for (int32_t i = 0; i < bx::min(100, LogInternal::LogHistorySize); ++i) - { - int32_t idx = GetLogHistory().WriteIdx - i - 1; - if (idx < 0) idx += LogInternal::LogHistorySize; - const char* line = &GetLogHistory().LogBuffer[idx * LogInternal::MaxLineSize]; - if (line[0] != 0) - { - int64_t timeOffset = GetLogHistory().WriteTime[idx] - GetInstance().Time.StartTime; - double writeTime = (double)timeOffset / bx::getHPFrequency(); - uint32_t fileLine = GetLogHistory().LineBuffer[idx]; - const char* filePath = &GetLogHistory().FileBuffer[idx * LogInternal::MaxLineSize]; - const char* filePathRes = GetInstance().DebugData.ShortenLogFileNames - ? bx::FilePath{filePath}.getFileName().getPtr() - : filePath; - - ImGui::TableNextRow(); - ImGui::TableNextColumn(); - ImGui::Text("%.01f", writeTime); - - ImGui::TableNextColumn(); - ImGui::Text("%s", line); - ImGui::SetItemTooltip("%f\n%s%s:%u", writeTime, line, filePath, fileLine); - - ImGui::TableNextColumn(); - ImGui::Text("%u", fileLine); - - ImGui::TableNextColumn(); - ImGui::Text("%s", filePathRes); - } - } - ImGui::EndTable(); - } - ImGui::End(); - if (ImGui::Begin("Rendering")) - { - if (LastShaderLoadTime >= 0.0f) - { - ImGui::TextColored({0.2f, 0.9f, 0.2f, 1.0f}, - "Shader loaded %.0f seconds ago", - GetInstance().Time.Now - LastShaderLoadTime); - } - else - { - ImGui::TextColored({0.9f, 0.2f, 0.2f, 1.0f}, "Shader load Failiure!"); - } - if (ImGui::Button("Reload Meshes")) - { - LoadModels(Models, ModelCount); - } - ImGui::SameLine(); - if (ImGui::Button("Reload Level")) - { - level = {}; - level.Setup(shared.Game); - } - ImGui::Checkbox("Show ImGui Demo", &debug.ShowImguiDemo); - if (debug.ShowImguiDemo) ImGui::ShowDemoWindow(&debug.ShowImguiDemo); - ImGui::Separator(); - - ImGui::Checkbox("Cubes", &level.Cubes.IsEnabled); - ImGui::Checkbox("Tests", &level.Tests.IsEnabled); - ImGui::Checkbox("PuzzleTiles", &level.PuzzleTiles.IsEnabled); - ImGui::Checkbox("UIQuads", &level.UIQuads.IsEnabled); - - if (ImGui::Button("Dithergen")) - { - DitherGen(DitherTextures, DitherRecursion); - } - ImGui::SameLine(); - ImGui::SliderInt("Recursion", &DitherRecursion, 1, 4); - ImGui::Text( - "%ux%ux%u", DitherTextures.DitherTexWH, DitherTextures.DitherTexWH, DitherTextures.DitherTexDepth); - if (!isValid(DitherTextures.PreviewTex)) - { - ImGui::Text("Invalid Texture"); - } - else - { - ImGui::Image(DitherTextures.PreviewTex.idx, - {(float)DitherTextures.DitherTexWH, - (float)DitherTextures.DitherTexWH * DitherTextures.DitherTexDepth}); - } - if (isValid(DitherTextures.RampTex)) - { - ImGui::Image(DitherTextures.RampTex.idx, {BX_COUNTOF(DitherTextures.BrightnessRamp), 8}); - } - Vec3 quadPos = level.UIQuads.Get({0}).EData.Transform.GetPosition(); - ImGui::Text("%f %f %f", quadPos.x, quadPos.y, quadPos.z); - - if (ImGui::ColorEdit3("Base Color", &DefaultBaseColor.x)) - { - auto& tiles = GetInstance().GameLevel.PuzzleTiles; - for (int32_t i = 0; i < tiles.Count; ++i) - { - tiles.Data[i].EData.BaseColor = DefaultBaseColor; - } - } - if (ImGui::ColorEdit3("Dot Color", &DefaultTileColor.x)) - { - auto& tiles = GetInstance().GameLevel.PuzzleTiles; - for (int32_t i = 0; i < tiles.Count; ++i) - { - tiles.Data[i].EData.TestColor = DefaultTileColor; - } - } - - ImGui::Text("Shader log:"); - ImGui::TextWrapped("%s", GetShared().Dev.ShaderLog); - } - ImGui::End(); - if (ImGui::Begin("Textures")) - { - if (ImGui::Button("Reload")) - { - LoadTextures(); - } - for (int32_t i = 0; i < MaxTextures; ++i) - { - if (!isValid(Textures[i].RenderHandle)) continue; - ImGui::Text("%i", i); - float width = bx::min(ImGui::GetContentRegionAvail().x, Textures[i].Info.width); - float height = bx::min(ImGui::GetContentRegionAvail().x, Textures[i].Info.height); - ImGui::Image(Textures[i].RenderHandle.idx, {width, height}); - } - } - ImGui::End(); - if (ImGui::Begin("Puzzles")) - { - if (ImGui::Button("Add")) - { - bool found = false; - for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) - { - auto& puz = level.Puzzles[i].Data; - if (puz.ID == UINT16_MAX) - { - bx::strCopy(puz.PuzzleName, sizeof(puz.PuzzleName), "Unnamed Puzzle"); - puz.ID = i; - found = true; - break; - } - } - if (!found) - { - LOG_ERROR("Too many puzzles!"); - } - } - ImGui::Separator(); - for (int32_t i = 0; i < BX_COUNTOF(level.Puzzles); ++i) - { - auto& puzzleData = level.Puzzles[i].Data; - if (puzzleData.ID == UINT16_MAX) continue; - - bool isSelected = debug.SelectedDebugLevel == i; - ImGui::PushID("selectable"); - if (ImGui::Selectable(puzzleData.PuzzleName, isSelected)) - { - debug.SelectedDebugLevel = isSelected ? UINT16_MAX : i; - } - ImGui::PopID(); - } - } - ImGui::End(); - if (debug.SelectedDebugLevel < BX_COUNTOF(level.Puzzles)) - { - if (!Puzzle::RenderDebugUI(level.Puzzles[debug.SelectedDebugLevel].Data)) - { - debug.SelectedDebugLevel = UINT16_MAX; - } - } - if (ImGui::Begin("Cards")) - { - Generated::StaticPuzzleData& staticData = Puzzle::GetStaticPuzzleData(); - if (ImGui::Button("Save")) - { - Puzzle::SaveStaticPuzzleData(); - } - ImGui::SameLine(); - if (ImGui::Button("Reload")) - { - Puzzle::LoadStaticPuzzleData(); - } - - for (int32_t i = 0; i < BX_COUNTOF(staticData.Cards); ++i) - { - ImGui::Separator(); - - Generated::StaticPuzzleCard& card = staticData.Cards[i]; - ImGui::PushID(i); - char cardName[64]{0}; - bx::snprintf(cardName, sizeof(cardName), "%i", i); - ImGui::Selectable(cardName); - if (ImGui::BeginDragDropSource()) - { - Puzzle::DrawCard(card, debug.DebugCardRotation, ImGui::GetCursorScreenPos()); - ImGui::SetDragDropPayload("cardtype", &i, sizeof(i)); - ImGui::EndDragDropSource(); - } - - Tools::ModelDropdown(card.ModelHandle); - Tools::TextureDropdown(card.BoardTextureHandle); - for (int8_t y = 0; y < Puzzle::Config::CardSize; ++y) - { - ImGui::PushID(y); - for (int8_t x = 0; x < Puzzle::Config::CardSize; ++x) - { - if (x > 0) ImGui::SameLine(); - ImGui::PushID(x); - auto& node = Puzzle::EditCardNodeAt(card, 0, x, y); - if (ImGui::Button(Generated::PuzzleElementType::ShortName[node], {26, 24})) - { - int32_t newVal = int32_t(node) + 1; - if (newVal >= Generated::PuzzleElementType::EntryCount) - { - newVal = 0; - } - node = Generated::PuzzleElementType::Enum(newVal); - } - ImGui::PopID(); - } - ImGui::PopID(); - } - ImGui::PopID(); - } - } - ImGui::End(); - } - void GameRendering::LoadTextures() { for (int32_t i = 0; i < MaxTextures; ++i) @@ -791,26 +415,7 @@ namespace Game ImGui::DockSpaceOverViewport(0, 0, ImGuiDockNodeFlags_PassthruCentralNode); } - if (UIVisible == UIVisibilityState::Debug) - { - RenderDebugUI(); - } - ImGui::SetNextWindowPos({0, 0}); - if (ImGui::Begin("Stats", - nullptr, - ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoBackground | ImGuiWindowFlags_NoInputs | - ImGuiWindowFlags_AlwaysAutoResize)) - { - if (GetInstance().Player.CameraM == CameraMode::Freefly) - { - ImGui::PushStyleColor(ImGuiCol_Text, {0.8f, 0.1f, 0.1f, 1.0f}); - ImGui::Text("NOCLIP"); - ImGui::PopStyleColor(); - } - ImGui::Text("Delta: %.01fms", time.Delta * 1000); - ImGui::Text("FPS: %.0f", 1.0 / time.Delta); - } - ImGui::End(); + Tools::RenderDebugUI(*this); GetInstance().GameLevel.Update(); GetInstance().GameLevel.Render(MainViewID, Models, Materials, Textures); diff --git a/src/game/rendering/Rendering.h b/src/game/rendering/Rendering.h index 5e5c46c..1f39ec4 100644 --- a/src/game/rendering/Rendering.h +++ b/src/game/rendering/Rendering.h @@ -1,12 +1,12 @@ #pragma once #include "bgfx/defines.h" -#include "imgui.h" #include #include #include #include "../Gen.h" #include "../Global.h" +#include "Dither.h" union SDL_Event; @@ -65,25 +65,6 @@ namespace Game Debug, }; - struct DitherData - { - static constexpr uint32_t BrightnessBucketCount = 256; - Vec2 Points[4096]; - uint32_t PointCount = 0; - Vec4 DitherTex[256 * 256 * 64]; - uint32_t DitherTexWH = 0; - uint32_t DitherTexDepth = 0; - int32_t BrightnessBuckets[BrightnessBucketCount]; - float BrightnessRamp[BrightnessBucketCount + 1]; - bgfx::TextureHandle PreviewTex = BGFX_INVALID_HANDLE; - bgfx::TextureHandle FinalTex = BGFX_INVALID_HANDLE; - bgfx::TextureHandle RampTex = BGFX_INVALID_HANDLE; - - bgfx::UniformHandle DitherSampler = BGFX_INVALID_HANDLE; - bgfx::UniformHandle RampSampler = BGFX_INVALID_HANDLE; - ImTextureID PreviewID = 0; - }; - enum class EMaterial : uint16_t { Default = 0, @@ -110,7 +91,7 @@ namespace Game Model Models[MaxModels]; int32_t LastWidth = 0; int32_t LastHeight = 0; - uint32_t ResetFlags = BGFX_RESET_NONE; + uint32_t ResetFlags = BGFX_RESET_VSYNC; uint16_t MainViewID = 10; float LastShaderLoadTime = 0.0f; int32_t DitherRecursion = 1; @@ -121,7 +102,6 @@ namespace Game void Setup(); void Update(); void HandleEvents(); - void RenderDebugUI(); void LoadTextures(); void ReloadShaders(); void Shutdown();