From 58e351eb106e17e21dc0d2f28ebb77eec376b197 Mon Sep 17 00:00:00 2001 From: nekoffski Date: Tue, 12 Mar 2024 19:32:16 +0100 Subject: [PATCH] Support configurable polygon modes for shaders --- assets/shaders/Builtin.Shader.Material.json | 1 + editor/Application.cpp | 26 ++++--- editor/Application.h | 3 +- editor/ui/Core.h | 5 ++ editor/ui/EntityInspectorPanel.cpp | 11 --- editor/ui/ScenePanel.cpp | 78 +++++++++---------- editor/ui/ScenePanel.h | 3 + engine/src/starlight/renderer/PolygonMode.cpp | 29 +++++++ engine/src/starlight/renderer/PolygonMode.h | 12 +++ engine/src/starlight/renderer/gpu/Shader.cpp | 4 +- engine/src/starlight/renderer/gpu/Shader.h | 3 + .../renderer/gpu/vulkan/VKPipeline.h | 5 +- .../renderer/gpu/vulkan/VKShader.cpp | 8 +- .../resource/configs/ShaderConfig.cpp | 3 +- engine/src/starlight/ui/Utils.cpp | 6 +- engine/src/starlight/ui/Utils.h | 5 ++ 16 files changed, 130 insertions(+), 72 deletions(-) create mode 100644 engine/src/starlight/renderer/PolygonMode.cpp create mode 100644 engine/src/starlight/renderer/PolygonMode.h diff --git a/assets/shaders/Builtin.Shader.Material.json b/assets/shaders/Builtin.Shader.Material.json index 206cdb98..275e80db 100644 --- a/assets/shaders/Builtin.Shader.Material.json +++ b/assets/shaders/Builtin.Shader.Material.json @@ -2,6 +2,7 @@ "version": 1.0, "name": "Builtin.Shader.Material", "cullMode": "back", + "polygonMode": "fill", "stages": [ { "stage": "vertex", "file": "Builtin.Shader.Material.vert.spv" }, { "stage": "fragment", "file": "Builtin.Shader.Material.frag.spv" } diff --git a/editor/Application.cpp b/editor/Application.cpp index 7932f3d8..97b8244a 100644 --- a/editor/Application.cpp +++ b/editor/Application.cpp @@ -49,8 +49,12 @@ Application::Application(int argc, char** argv) : .viewportWidth = w, .viewportHeight = h, }); - m_activeCamera = m_eulerCamera.get(); - m_ui.getState()->camera = m_activeCamera; + m_activeCamera = m_eulerCamera.get(); + + calculateViewport(); + + m_ui.getState()->camera = m_activeCamera; + m_ui.getState()->viewport = &m_viewport; } int Application::run() { @@ -83,8 +87,8 @@ int Application::run() { sl::SkyboxRenderView skyboxView{ m_activeCamera, skyboxShader, skybox }; m_views.push_back(&skyboxView); - m_views.push_back(&uiView); m_views.push_back(&worldView); + m_views.push_back(&uiView); LOG_INFO("Starlight Editor starting"); @@ -97,7 +101,7 @@ int Application::run() { LOG_VAR(m_activeCamera->getPosition()); auto renderPacket = m_scene.getRenderPacket(); - renderPacket.viewport = calculateViewport(); + renderPacket.viewport = m_viewport; m_renderer.renderFrame(deltaTime, renderPacket); @@ -148,6 +152,8 @@ void Application::setupEventHandlers() { m_renderer.onViewportResize(w, h); m_eulerCamera->onViewportResize(w, h); m_firstPersonCamera->onViewportResize(w, h); + + calculateViewport(); }; const auto onSceneLoaded = [&](SceneLoaded* event) { @@ -169,13 +175,11 @@ void Application::setupEventHandlers() { .on(onSceneSaved); } -sl::Viewport Application::calculateViewport() const { +void Application::calculateViewport() { const auto [w, h] = m_window->getSize(); - return sl::Viewport{ - .x = panelWidthFactor * w, - .y = 0.25f * h, - .width = (1.0f - 2.0f * panelWidthFactor) * w, - .height = (0.75f) * h - }; + m_viewport.x = panelWidthFactor * w; + m_viewport.y = 0.25f * h; + m_viewport.width = (1.0f - 2.0f * panelWidthFactor) * w; + m_viewport.height = (0.75f) * h; } diff --git a/editor/Application.h b/editor/Application.h index 566684f1..ee6ae8e3 100644 --- a/editor/Application.h +++ b/editor/Application.h @@ -29,8 +29,9 @@ class Application { private: void setupEventHandlers(); + void calculateViewport(); - sl::Viewport calculateViewport() const; + sl::Viewport m_viewport; bool m_isRunning; bool m_update; diff --git a/editor/ui/Core.h b/editor/ui/Core.h index ccabb8dc..5632f19a 100644 --- a/editor/ui/Core.h +++ b/editor/ui/Core.h @@ -5,6 +5,7 @@ #include "starlight/core/Core.h" #include "starlight/core/math/Glm.h" #include "starlight/renderer/camera/Camera.h" +#include "starlight/renderer/Viewport.h" #include "starlight/ui/UI.h" enum class ResourceType { mesh = 0, texture, shader, material }; @@ -18,6 +19,10 @@ struct UIState { std::unordered_map> imageHandles; sl::Camera* camera; + sl::Viewport* viewport; + + bool showGrid = true; + float gridSize = 25.0f; sl::ui::ImageHandle* getOrCreateImageHandle(sl::Texture* texture); }; diff --git a/editor/ui/EntityInspectorPanel.cpp b/editor/ui/EntityInspectorPanel.cpp index ce007c0a..54bfccde 100644 --- a/editor/ui/EntityInspectorPanel.cpp +++ b/editor/ui/EntityInspectorPanel.cpp @@ -28,17 +28,6 @@ void EntityInspectorPanel::renderEntityUI(sl::u64 entityId) { auto entity = m_scene->getEntity(entityId); auto& data = m_entitiesData[entity->getId()]; - auto view = m_state->camera->getViewMatrix(); - auto projection = m_state->camera->getProjectionMatrix(); - - ImGuiIO& io = ImGui::GetIO(); - ImGuizmo::SetRect(0, 0, io.DisplaySize.x, io.DisplaySize.y); - - ImGuizmo::DrawGrid( - glm::value_ptr(view), glm::value_ptr(projection), - glm::value_ptr(sl::identityMatrix), 100.f - ); - sl::ui::namedScope(fmt::format("Entity_{}", entity->getId()), [&]() { sl::ui::text("Entity: {}/{}", entity->getId(), entity->getName()); sl::ui::separator(); diff --git a/editor/ui/ScenePanel.cpp b/editor/ui/ScenePanel.cpp index f07698ac..bc44f0de 100644 --- a/editor/ui/ScenePanel.cpp +++ b/editor/ui/ScenePanel.cpp @@ -5,46 +5,44 @@ ScenePanel::ScenePanel(sl::Scene* scene, UIState* state, Logger* logger) : m_scene(scene), m_state(state), m_logger(logger), m_tabs("scene-tabs") { - m_tabs - .addTab( - ICON_FA_SITEMAP " Scene graph", - [&]() { - if (sl::ui::button("Add Entity")) { - m_logger->debug("Adding new entity"); - m_scene->addEntity(); - } - sl::ui::separator(); - sl::ui::treeNode( - ICON_FA_CUBE " Root", - [&]([[maybe_unused]] bool clicked) { - m_scene->forEachEntity( - [&](const std::string& name, sl::Entity* entity) -> void { - auto& selectedEntityId = m_state->selectedEntityId; - - const auto entityId = entity->getId(); - const auto color = - selectedEntityId && *selectedEntityId == entityId - ? selectedColor - : defaultColor; - - sl::ui::withColor(color, [&]() { - const auto title = - fmt::format("\t{} {}", ICON_FA_CUBE, name); - - if (sl::ui::text(title)) { - m_logger->debug( - "Selected entity with id={}", entityId - ); - selectedEntityId = entityId; - } - }); - } - ); - } - ); - } - ) - .addTab(ICON_FA_CLOUD " Skybox", [&]() {}); + m_tabs.addTab( + ICON_FA_SITEMAP " Scene graph", [&]() { renderSceneGraph(); } + ).addTab(ICON_FA_WRENCH " Scene Settings", [&]() { renderSceneSettings(); }); } void ScenePanel::render() { m_tabs.render(); } + +void ScenePanel::renderSceneGraph() { + if (sl::ui::button("Add Entity")) { + m_logger->debug("Adding new entity"); + m_scene->addEntity(); + } + sl::ui::separator(); + sl::ui::treeNode(ICON_FA_CUBE " Root", [&]([[maybe_unused]] bool clicked) { + m_scene->forEachEntity( + [&](const std::string& name, sl::Entity* entity) -> void { + auto& selectedEntityId = m_state->selectedEntityId; + + const auto entityId = entity->getId(); + const auto color = + selectedEntityId && *selectedEntityId == entityId + ? selectedColor + : defaultColor; + + sl::ui::withColor(color, [&]() { + const auto title = fmt::format("\t{} {}", ICON_FA_CUBE, name); + + if (sl::ui::text(title)) { + m_logger->debug("Selected entity with id={}", entityId); + selectedEntityId = entityId; + } + }); + } + ); + }); +} + +void ScenePanel::renderSceneSettings() { + sl::ui::checkbox("Show grid", m_state->showGrid); + sl::ui::separator(); +} diff --git a/editor/ui/ScenePanel.h b/editor/ui/ScenePanel.h index c9e281c5..5fa9f27e 100644 --- a/editor/ui/ScenePanel.h +++ b/editor/ui/ScenePanel.h @@ -15,6 +15,9 @@ class ScenePanel { void render(); private: + void renderSceneGraph(); + void renderSceneSettings(); + sl::Scene* m_scene; UIState* m_state; Logger* m_logger; diff --git a/engine/src/starlight/renderer/PolygonMode.cpp b/engine/src/starlight/renderer/PolygonMode.cpp new file mode 100644 index 00000000..581db7f3 --- /dev/null +++ b/engine/src/starlight/renderer/PolygonMode.cpp @@ -0,0 +1,29 @@ +#include "PolygonMode.h" + +#include "starlight/core/utils/Log.h" + +namespace sl { + +std::string polygonModeToString(PolygonMode polygonMode) { + switch (polygonMode) { + case PolygonMode::fill: + return "fill"; + case PolygonMode::line: + return "line"; + case PolygonMode::point: + return "point"; + } + __builtin_unreachable(); +} + +PolygonMode polygonModeFromString(const std::string& polygonName) { + if (polygonName == "line") + return PolygonMode::line; + else if (polygonName == "fill") + return PolygonMode::fill; + else if (polygonName == "point") + return PolygonMode::point; + FATAL_ERROR("Could not parse polygon mode: {}", polygonName); +} + +} // namespace sl \ No newline at end of file diff --git a/engine/src/starlight/renderer/PolygonMode.h b/engine/src/starlight/renderer/PolygonMode.h new file mode 100644 index 00000000..d24872be --- /dev/null +++ b/engine/src/starlight/renderer/PolygonMode.h @@ -0,0 +1,12 @@ +#pragma once + +#include "starlight/core/Core.h" + +namespace sl { + +enum class PolygonMode : u8 { fill, line, point }; + +std::string polygonModeToString(PolygonMode polygonMode); +PolygonMode polygonModeFromString(const std::string& polygonName); + +} // namespace sl diff --git a/engine/src/starlight/renderer/gpu/Shader.cpp b/engine/src/starlight/renderer/gpu/Shader.cpp index 726c3348..574aee10 100644 --- a/engine/src/starlight/renderer/gpu/Shader.cpp +++ b/engine/src/starlight/renderer/gpu/Shader.cpp @@ -194,8 +194,8 @@ const std::string& Shader::getName() const { return m_name; } Shader::Shader(const Properties& props, u32 id) : m_name(props.name), m_id(id), m_useInstances(props.useInstances), - m_useLocals(props.useLocals), m_uniformProxy(*this), m_cullMode(props.cullMode) { -} + m_useLocals(props.useLocals), m_uniformProxy(*this), m_cullMode(props.cullMode), + m_polygonMode(props.polygonMode) {} void Shader::UniformProxy::set(const std::string& uniform, const Texture* value) { m_shader.setSampler(uniform, value); diff --git a/engine/src/starlight/renderer/gpu/Shader.h b/engine/src/starlight/renderer/gpu/Shader.h index f44e93e3..76de82f0 100644 --- a/engine/src/starlight/renderer/gpu/Shader.h +++ b/engine/src/starlight/renderer/gpu/Shader.h @@ -14,6 +14,7 @@ #include "starlight/core/Core.h" #include "starlight/core/utils/Log.h" #include "starlight/renderer/CullMode.h" +#include "starlight/renderer/PolygonMode.h" #include "fwd.h" #include "Texture.h" @@ -106,6 +107,7 @@ class Shader { Texture* defaultTexture; CullMode cullMode; + PolygonMode polygonMode; }; class UniformProxy { @@ -163,6 +165,7 @@ class Shader { UniformProxy m_uniformProxy; CullMode m_cullMode; + PolygonMode m_polygonMode; private: virtual void bindGlobals() = 0; diff --git a/engine/src/starlight/renderer/gpu/vulkan/VKPipeline.h b/engine/src/starlight/renderer/gpu/vulkan/VKPipeline.h index 90a95e40..46be87ed 100644 --- a/engine/src/starlight/renderer/gpu/vulkan/VKPipeline.h +++ b/engine/src/starlight/renderer/gpu/vulkan/VKPipeline.h @@ -135,8 +135,9 @@ class VKPipeline { // Dynamic state const uint32_t dynamic_state_count = 3; VkDynamicState dynamic_states[dynamic_state_count] = { - VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, - VK_DYNAMIC_STATE_LINE_WIDTH + VK_DYNAMIC_STATE_VIEWPORT, + VK_DYNAMIC_STATE_SCISSOR, + VK_DYNAMIC_STATE_LINE_WIDTH, }; VkPipelineDynamicStateCreateInfo dynamic_state_create_info = { diff --git a/engine/src/starlight/renderer/gpu/vulkan/VKShader.cpp b/engine/src/starlight/renderer/gpu/vulkan/VKShader.cpp index 82b0a400..9dd66d1b 100644 --- a/engine/src/starlight/renderer/gpu/vulkan/VKShader.cpp +++ b/engine/src/starlight/renderer/gpu/vulkan/VKShader.cpp @@ -656,6 +656,12 @@ void VKShader::createDescriptorSetLayouts() { } } +static std::unordered_map vkPolygonModes = { + {PolygonMode::fill, VK_POLYGON_MODE_FILL }, + { PolygonMode::line, VK_POLYGON_MODE_LINE }, + { PolygonMode::point, VK_POLYGON_MODE_POINT}, +}; + void VKShader::createPipeline(RenderPass* renderPass) { // viewport & scissor const auto [w, h] = WindowManager::get().getSize(); @@ -685,7 +691,7 @@ void VKShader::createPipeline(RenderPass* renderPass) { pipelineProps.stages = stageCreateInfos; pipelineProps.viewport = viewport; pipelineProps.scissor = scissor; - pipelineProps.polygonMode = VK_POLYGON_MODE_FILL; + pipelineProps.polygonMode = vkPolygonModes.at(m_polygonMode); pipelineProps.depthTestEnabled = true; pipelineProps.cullMode = m_cullMode; diff --git a/engine/src/starlight/resource/configs/ShaderConfig.cpp b/engine/src/starlight/resource/configs/ShaderConfig.cpp index 48cfceab..f4ad0100 100644 --- a/engine/src/starlight/resource/configs/ShaderConfig.cpp +++ b/engine/src/starlight/resource/configs/ShaderConfig.cpp @@ -111,7 +111,8 @@ std::optional ShaderConfig::load( .stages = processStages(getArray(root, "stages"), shadersPath, fs), .uniformProperties = processUniforms(getArray(root, "uniforms")), .defaultTexture = defaultTexture, - .cullMode = cullModeFromString(getFieldOr(root, "cullMode", "back")) + .cullMode = cullModeFromString(getFieldOr(root, "cullMode", "back")), + .polygonMode = polygonModeFromString(getFieldOr(root, "polygonMode", "fill")) } }; // clang-format on diff --git a/engine/src/starlight/ui/Utils.cpp b/engine/src/starlight/ui/Utils.cpp index 2bcdd4d2..d0db4610 100644 --- a/engine/src/starlight/ui/Utils.cpp +++ b/engine/src/starlight/ui/Utils.cpp @@ -7,9 +7,9 @@ namespace sl::ui { -// auto foo() { -// ImGui::PushTex -// } +void checkbox(const std::string& label, bool& value) { + ImGui::Checkbox(label.c_str(), &value); +} void pushFont(Font* font) { ImGui::PushFont(font->handle); } void popFont() { ImGui::PopFont(); } diff --git a/engine/src/starlight/ui/Utils.h b/engine/src/starlight/ui/Utils.h index 8b231248..30065977 100644 --- a/engine/src/starlight/ui/Utils.h +++ b/engine/src/starlight/ui/Utils.h @@ -5,6 +5,9 @@ #include #include +#include "starlight/renderer/Viewport.h" +#include "starlight/renderer/camera/Camera.h" + #include "starlight/core/math/Glm.h" #include "starlight/renderer/gpu/UIRenderer.h" @@ -13,6 +16,8 @@ namespace sl::ui { using Callback = std::function; // TODO: measure if it causes bottlenecks -> // if yes implement lightweight wrapper +void checkbox(const std::string& label, bool& value); + void pushFont(Font*); void popFont();