From d20248792a697f36e052a35938b0b17439b22985 Mon Sep 17 00:00:00 2001 From: Egor Orachev Date: Sat, 28 Oct 2023 01:48:27 +0300 Subject: [PATCH] gh-44: rework canvas drawing - impl new canvas class (batch textures, cmds, use new gfx vector) - use new canvas for debug console rendering - fix ecs ent deletion - move visibility cull to sep stage - move cameras fill to set stage - store visibility items along with render objects in gpu scene - remove unnecessary sync in vis system --- engine/CMakeLists.txt | 6 +- engine/core/engine.cpp | 7 +- engine/core/engine.hpp | 6 +- engine/debug/console.cpp | 33 +- engine/debug/console.hpp | 18 +- engine/debug/debug_layer.cpp | 17 +- engine/ecs/ecs_memory.cpp | 4 +- engine/ecs/ecs_memory.hpp | 2 +- engine/ecs/ecs_system.hpp | 4 + engine/ecs/ecs_world.cpp | 11 +- engine/ecs/ecs_world.hpp | 3 +- engine/engine.hpp | 2 +- engine/gfx/gfx_ctx.hpp | 4 +- engine/gfx/gfx_defs.hpp | 6 + engine/gfx/gfx_driver.hpp | 36 +- engine/gfx/gfx_pipeline_cache.cpp | 21 +- engine/gfx/gfx_pipeline_cache.hpp | 7 +- engine/gfx/gfx_texture.hpp | 2 + engine/gfx/gfx_vector.hpp | 9 + engine/gfx/gfx_vert_format_cache.cpp | 21 +- engine/gfx/gfx_vert_format_cache.hpp | 7 +- engine/gfx/threaded/gfx_ctx_wrapper.cpp | 2 +- engine/gfx/threaded/gfx_ctx_wrapper.hpp | 2 +- engine/gfx/threaded/gfx_driver_wrapper.cpp | 19 +- engine/gfx/threaded/gfx_driver_wrapper.hpp | 2 +- engine/gfx/vulkan/vk_ctx.cpp | 14 +- engine/gfx/vulkan/vk_ctx.hpp | 2 +- engine/gfx/vulkan/vk_driver.cpp | 8 +- engine/gfx/vulkan/vk_driver.hpp | 2 +- engine/gfx/vulkan/vk_texture.cpp | 20 +- engine/gfx/vulkan/vk_texture.hpp | 2 +- engine/gfx/vulkan/vk_window.cpp | 2 +- engine/hgfx/hgfx_pass_base.cpp | 4 +- engine/hgfx/hgfx_pass_text.cpp | 4 +- engine/main/main.cpp | 13 +- engine/main/main.hpp | 3 +- engine/mesh/mesh_processors.cpp | 2 +- engine/render/aux_draw_canvas.cpp | 420 ------------- engine/render/aux_draw_canvas.hpp | 143 ----- engine/render/aux_draw_manager.cpp | 24 +- engine/render/canvas.cpp | 587 ++++++++++++++++++ engine/render/canvas.hpp | 198 ++++++ engine/render/render_camera.cpp | 21 +- engine/render/render_camera.hpp | 1 + engine/render/render_engine.cpp | 31 +- engine/render/render_engine.hpp | 6 +- engine/render/render_scene.cpp | 6 +- engine/render/render_scene.hpp | 7 +- engine/render/shader_manager.cpp | 4 +- engine/render/texture_manager.cpp | 30 + engine/render/texture_manager.hpp | 21 +- engine/render/vertex_factory.cpp | 2 +- engine/render/visibility.cpp | 36 +- engine/render/visibility.hpp | 29 +- engine/resource/font.cpp | 2 +- engine/resource/texture.cpp | 7 +- engine/resource/texture.hpp | 7 +- engine/scene/scene.cpp | 7 +- engine/scene/scene_camera.cpp | 10 + engine/scene/scene_camera.hpp | 1 + engine/scene/scene_components.hpp | 2 +- engine/scene/scene_manager.cpp | 79 ++- engine/scene/scene_manager.hpp | 2 + engine/shaders/aux_draw_canvas.frag | 27 - engine/shaders/aux_draw_canvas.vert | 23 - engine/shaders/base.frag | 2 - engine/shaders/base.vert | 2 - engine/shaders/canvas.frag | 62 ++ engine/shaders/canvas.vert | 38 ++ .../auto_aux_draw_canvas_gl410_frag.hpp | 110 ---- .../auto_aux_draw_canvas_gl410_vert.hpp | 107 ---- .../auto_aux_draw_canvas_vk450_frag.hpp | 110 ---- .../auto_aux_draw_canvas_vk450_vert.hpp | 107 ---- .../generated/auto_base_gl410_frag.hpp | 4 +- .../generated/auto_base_gl410_vert.hpp | 4 +- engine/shaders/generated/auto_base_pass.hpp | 2 +- .../generated/auto_base_reflection.hpp | 2 +- .../generated/auto_base_vk450_frag.hpp | 4 +- .../generated/auto_base_vk450_vert.hpp | 4 +- .../generated/auto_canvas_gl410_frag.hpp | 309 +++++++++ .../generated/auto_canvas_gl410_vert.hpp | 370 +++++++++++ ...w_canvas_pass.hpp => auto_canvas_pass.hpp} | 78 ++- ...lection.hpp => auto_canvas_reflection.hpp} | 69 +- .../generated/auto_canvas_vk450_frag.hpp | 309 +++++++++ .../generated/auto_canvas_vk450_vert.hpp | 370 +++++++++++ .../generated/auto_material_gl410_frag.hpp | 6 +- .../generated/auto_material_gl410_vert.hpp | 6 +- .../shaders/generated/auto_material_pass.hpp | 2 +- .../generated/auto_material_reflection.hpp | 4 +- .../generated/auto_material_vk450_frag.hpp | 6 +- .../generated/auto_material_vk450_vert.hpp | 6 +- .../generated/auto_text_gl410_frag.hpp | 2 +- .../generated/auto_text_gl410_vert.hpp | 2 +- engine/shaders/generated/auto_text_pass.hpp | 2 +- .../generated/auto_text_reflection.hpp | 2 +- .../generated/auto_text_vk450_frag.hpp | 2 +- .../generated/auto_text_vk450_vert.hpp | 2 +- engine/shaders/scene_data.glsl | 2 - engine/shaders/scripts/aux_draw_canvas.py | 24 - engine/shaders/scripts/canvas.py | 54 ++ engine/shaders/scripts/material.py | 4 +- engine/shaders/scripts/shaders.py | 4 +- engine/systems/system_render.hpp | 2 - 103 files changed, 2839 insertions(+), 1416 deletions(-) delete mode 100644 engine/render/aux_draw_canvas.cpp delete mode 100644 engine/render/aux_draw_canvas.hpp create mode 100644 engine/render/canvas.cpp create mode 100644 engine/render/canvas.hpp delete mode 100644 engine/shaders/aux_draw_canvas.frag delete mode 100644 engine/shaders/aux_draw_canvas.vert create mode 100644 engine/shaders/canvas.frag create mode 100644 engine/shaders/canvas.vert delete mode 100644 engine/shaders/generated/auto_aux_draw_canvas_gl410_frag.hpp delete mode 100644 engine/shaders/generated/auto_aux_draw_canvas_gl410_vert.hpp delete mode 100644 engine/shaders/generated/auto_aux_draw_canvas_vk450_frag.hpp delete mode 100644 engine/shaders/generated/auto_aux_draw_canvas_vk450_vert.hpp create mode 100644 engine/shaders/generated/auto_canvas_gl410_frag.hpp create mode 100644 engine/shaders/generated/auto_canvas_gl410_vert.hpp rename engine/shaders/generated/{auto_aux_draw_canvas_pass.hpp => auto_canvas_pass.hpp} (56%) rename engine/shaders/generated/{auto_aux_draw_canvas_reflection.hpp => auto_canvas_reflection.hpp} (53%) create mode 100644 engine/shaders/generated/auto_canvas_vk450_frag.hpp create mode 100644 engine/shaders/generated/auto_canvas_vk450_vert.hpp delete mode 100644 engine/shaders/scripts/aux_draw_canvas.py create mode 100644 engine/shaders/scripts/canvas.py diff --git a/engine/CMakeLists.txt b/engine/CMakeLists.txt index 9b5dffca9..3b73476d6 100644 --- a/engine/CMakeLists.txt +++ b/engine/CMakeLists.txt @@ -261,8 +261,10 @@ add_library(wmoge STATIC platform/glfw/glfw_window_manager.hpp render/aux_draw_manager.cpp render/aux_draw_manager.hpp - render/aux_draw_canvas.cpp - render/aux_draw_canvas.hpp + render/canvas.cpp + render/canvas.hpp + render/graphics_pipeline.cpp + render/graphics_pipeline.hpp render/render_camera.cpp render/render_camera.hpp render/render_engine.cpp diff --git a/engine/core/engine.cpp b/engine/core/engine.cpp index 9bf178ce3..292ee8fac 100644 --- a/engine/core/engine.cpp +++ b/engine/core/engine.cpp @@ -83,6 +83,9 @@ namespace wmoge { ShaderManager* Engine::shader_manager() { return m_shader_manager; } + TextureManager* Engine::texture_manager() { + return m_texture_manager; + } AuxDrawManager* Engine::aux_draw_manager() { return m_aux_draw_manager; } @@ -101,8 +104,8 @@ namespace wmoge { Console* Engine::console() { return m_console; } - AuxDrawCanvas* Engine::canvas_2d_debug() { - return m_canvas_2d_debug; + Canvas* Engine::canvas_debug() { + return m_canvas_debug; } ScriptSystem* Engine::script_system() { return m_script_system; diff --git a/engine/core/engine.hpp b/engine/core/engine.hpp index 58df0af70..ff9e0f175 100644 --- a/engine/core/engine.hpp +++ b/engine/core/engine.hpp @@ -64,13 +64,14 @@ namespace wmoge { class GfxDriver* gfx_driver(); class GfxCtx* gfx_ctx(); class ShaderManager* shader_manager(); + class TextureManager* texture_manager(); class AuxDrawManager* aux_draw_manager(); class SceneManager* scene_manager(); class ActionManager* action_manager(); class GameTokenManager* game_token_manager(); class Profiler* profiler(); class Console* console(); - class AuxDrawCanvas* canvas_2d_debug(); + class Canvas* canvas_debug(); class ScriptSystem* script_system(); class AudioEngine* audio_engine(); class RenderEngine* render_engine(); @@ -112,13 +113,14 @@ namespace wmoge { class GfxDriver* m_gfx_driver = nullptr; class GfxCtx* m_gfx_ctx = nullptr; class ShaderManager* m_shader_manager = nullptr; + class TextureManager* m_texture_manager = nullptr; class AuxDrawManager* m_aux_draw_manager = nullptr; class SceneManager* m_scene_manager = nullptr; class ActionManager* m_action_manager = nullptr; class GameTokenManager* m_game_token_manager = nullptr; class Profiler* m_profiler = nullptr; class Console* m_console = nullptr; - class AuxDrawCanvas* m_canvas_2d_debug = nullptr; + class Canvas* m_canvas_debug = nullptr; class ScriptSystem* m_script_system = nullptr; class AudioEngine* m_audio_engine = nullptr; class RenderEngine* m_render_engine = nullptr; diff --git a/engine/debug/console.cpp b/engine/debug/console.cpp index ca91d1b6b..6a2db0dce 100644 --- a/engine/debug/console.cpp +++ b/engine/debug/console.cpp @@ -39,7 +39,7 @@ #include "math/math_utils.hpp" #include "platform/window.hpp" #include "platform/window_manager.hpp" -#include "render/aux_draw_canvas.hpp" +#include "render/canvas.hpp" #include "resource/config_file.hpp" #include "resource/resource_manager.hpp" @@ -262,42 +262,35 @@ namespace wmoge { if (m_state == ConsoleState::Closed) return; - auto screen = m_canvas->get_screen_size(); + auto screen = Vec2f(1280.0f, 720.0f); float height = m_size * m_state_open * screen.y(); float width = screen.x(); - m_canvas->push(Vec2f(0.0f, screen.y() - height), 0.0f); - m_canvas->set_font(m_console_font); + m_canvas->push_transform(Vec2f(0.0f, screen.y() - height), 0.0f); - m_canvas->set_fill_color(m_color_back); - m_canvas->draw_filled_rect(Vec2f(0, 0), Vec2f(width, height)); - - m_canvas->set_fill_color(m_color_line); - m_canvas->draw_filled_rect(Vec2f(0, 0), Vec2f(width, m_line_size)); - - m_canvas->set_font_color(m_color_text); - m_canvas->draw_text(">", Vec2f(m_margin, m_text_line), m_text_size); + m_canvas->add_rect_filled(Vec2f(0, 0), Vec2f(width, height), m_color_back); + m_canvas->add_rect_filled(Vec2f(0, 0), Vec2f(width, m_line_size), m_color_line); + m_canvas->add_text(">", m_console_font, m_text_size, Vec2f(m_margin, m_text_line), m_color_text); if (!m_line.empty()) { - m_canvas->set_font_color(m_color_text); - m_canvas->draw_text(m_line, Vec2f(m_margin_line, m_text_line), m_text_size); + m_canvas->add_text(m_line, m_console_font, m_text_size, Vec2f(m_margin_line, m_text_line), m_color_text); } if (m_state_blink > m_blink_threshold) { - m_canvas->set_fill_color(m_color_cursor); - m_canvas->draw_filled_rect(Vec2f(m_margin_line + m_cursor_offset, m_margin), Vec2f(m_cursor_width, m_cursor_height)); + const auto p_min = Vec2f(m_margin_line + m_cursor_offset, m_margin); + const auto p_max = p_min + Vec2f(m_cursor_width, m_cursor_height); + m_canvas->add_rect_filled(p_min, p_max, m_color_cursor); } float text_pos = m_line_size + m_margin; for (int i = static_cast(m_messages.size()) - m_scroll_messages - 1; i >= 0; --i) { if (text_pos > height) break; - m_canvas->set_font_color(m_messages[i].color); - m_canvas->draw_text(m_messages[i].text, Vec2f(m_margin, text_pos), m_text_size); + m_canvas->add_text(m_messages[i].text, m_console_font, m_text_size, Vec2f(m_margin, text_pos), m_messages[i].color); text_pos += m_text_size; } m_max_to_display = static_cast((height - m_line_size - m_margin) / m_text_size); - m_canvas->pop(); + m_canvas->pop_transform(); } void Console::register_commands() { @@ -409,7 +402,7 @@ namespace wmoge { auto res_man = engine->resource_manager(); auto config = engine->config(); - m_canvas = engine->canvas_2d_debug(); + m_canvas = engine->canvas_debug(); m_console_font = res_man->load(SID(config->get_string(SID("debug.console.font"), "res://fonts/anonymous_pro"))).cast(); m_margin_line = m_margin + m_console_font->get_string_size("> ", m_text_size).x(); diff --git a/engine/debug/console.hpp b/engine/debug/console.hpp index 221eecd5d..74f4a7bc2 100644 --- a/engine/debug/console.hpp +++ b/engine/debug/console.hpp @@ -202,15 +202,15 @@ namespace wmoge { float m_margin = 3.0f; float m_margin_line = 14.0f; - class AuxDrawCanvas* m_canvas = nullptr; - std::string m_line; - ConsoleState m_state = ConsoleState::Closed; - float m_state_open = 0.0f; - float m_state_blink = 0.0f; - float m_current_speed = 0.0f; - float m_cursor_offset = 0.0f; - int m_scroll_messages = 0; - int m_max_to_display = 0; + class Canvas* m_canvas = nullptr; + std::string m_line; + ConsoleState m_state = ConsoleState::Closed; + float m_state_open = 0.0f; + float m_state_blink = 0.0f; + float m_current_speed = 0.0f; + float m_cursor_offset = 0.0f; + int m_scroll_messages = 0; + int m_max_to_display = 0; }; }// namespace wmoge diff --git a/engine/debug/debug_layer.cpp b/engine/debug/debug_layer.cpp index 90fba792c..771ec1b86 100644 --- a/engine/debug/debug_layer.cpp +++ b/engine/debug/debug_layer.cpp @@ -32,7 +32,6 @@ #include "debug/profiler.hpp" #include "platform/window.hpp" #include "platform/window_manager.hpp" -#include "render/aux_draw_canvas.hpp" #include "render/aux_draw_manager.hpp" #include "render/render_engine.hpp" @@ -43,30 +42,28 @@ namespace wmoge { auto engine = Engine::instance(); auto window = engine->window_manager()->primary_window(); - auto canvas_debug = engine->canvas_2d_debug(); + auto canvas_debug = engine->canvas_debug(); auto aux_draw_manager = engine->aux_draw_manager(); - - canvas_debug->set_window(window); - canvas_debug->set_viewport(Rect2i{0, 0, window->fbo_width(), window->fbo_height()}); - canvas_debug->set_screen_size(Vec2f(1280, 720)); } void DebugLayer::on_debug_draw() { WG_AUTO_PROFILE_DEBUG("DebugLayer::on_debug_draw"); auto engine = Engine::instance(); auto render_engine = engine->render_engine(); - auto canvas_debug = engine->canvas_2d_debug(); + auto canvas_debug = engine->canvas_debug(); auto aux_draw_manager = engine->aux_draw_manager(); auto console = engine->console(); console->update(); - - canvas_debug->set_fill_color(Color::BLACK4f); - canvas_debug->draw_filled_rect({0, 0}, {1280, 720}); console->render(); aux_draw_manager->flush(engine->get_delta_time_game()); render_engine->render_aux_geom(*aux_draw_manager); + + canvas_debug->compile(true); + render_engine->render_canvas(*canvas_debug, Vec4f(0.0f, 0.0f, 1280.0f, 720.0f)); + + canvas_debug->clear(false); } }// namespace wmoge diff --git a/engine/ecs/ecs_memory.cpp b/engine/ecs/ecs_memory.cpp index e86d72e2f..d8bb015fc 100644 --- a/engine/ecs/ecs_memory.cpp +++ b/engine/ecs/ecs_memory.cpp @@ -98,7 +98,7 @@ namespace wmoge { out_entity_idx = entity_idx; m_size += 1; } - void EcsArchStorage::destroy_entity(const std::uint32_t& in_entity_idx) { + void EcsArchStorage::destroy_entity(const std::uint32_t& in_entity_idx, bool& was_swapped) { WG_AUTO_PROFILE_ECS("EcsArchStorage::destroy_entity"); assert(int(in_entity_idx) < m_size); @@ -120,6 +120,8 @@ namespace wmoge { m_components_info[component_idx]->swap(component_pool.get_element_raw(entity_idx), component_pool.get_element_raw(last_entity)); }); + + was_swapped = true; } m_arch.for_each_component([&](int component_idx) { diff --git a/engine/ecs/ecs_memory.hpp b/engine/ecs/ecs_memory.hpp index 91107c647..11aeca1e2 100644 --- a/engine/ecs/ecs_memory.hpp +++ b/engine/ecs/ecs_memory.hpp @@ -77,7 +77,7 @@ namespace wmoge { ~EcsArchStorage(); void make_entity(const EcsEntity& entity, std::uint32_t& entity_idx); - void destroy_entity(const std::uint32_t& entity_idx); + void destroy_entity(const std::uint32_t& entity_idx, bool& was_swapped); void clear(); template diff --git a/engine/ecs/ecs_system.hpp b/engine/ecs/ecs_system.hpp index e7e6448c7..def08530f 100644 --- a/engine/ecs/ecs_system.hpp +++ b/engine/ecs/ecs_system.hpp @@ -136,6 +136,10 @@ namespace wmoge { const int entity_idx = start_entity + i; const EcsEntity entity = storage.get_entity(entity_idx); + if (entity.is_invalid()) { + continue; + } + #define WG_ECS_ACCESS_COMPONENT(at) \ using TypeComponent##at = typename std::remove_reference>::type>::type; \ TypeComponent##at* ptr##at = storage.template get_component(entity_idx); diff --git a/engine/ecs/ecs_world.cpp b/engine/ecs/ecs_world.cpp index 37ee0e0fa..18db30094 100644 --- a/engine/ecs/ecs_world.cpp +++ b/engine/ecs/ecs_world.cpp @@ -97,11 +97,18 @@ namespace wmoge { assert(entity.is_valid()); assert(entity.idx < m_entity_info.size()); + bool need_swap = false; + EcsEntityInfo& entity_info = m_entity_info[entity.idx]; + m_arch_storage[entity_info.arch]->destroy_entity(entity_info.storage, need_swap); - m_arch_storage[entity_info.arch]->destroy_entity(entity_info.storage); - m_entity_pool.emplace_back(entity.idx, (entity.gen + 1) % EcsLimits::MAX_GENERATIONS_PER_ARC); + if (need_swap) { + const EcsEntity entity_to_swap = m_arch_storage[entity_info.arch]->get_entity(entity_info.storage); + assert(m_entity_info[entity_to_swap.idx].arch == entity_info.arch); + m_entity_info[entity_to_swap.idx].storage = entity_info.storage; + } + m_entity_pool.emplace_back(entity.idx, (entity.gen + 1) % EcsLimits::MAX_GENERATIONS_PER_ARC); entity_info = EcsEntityInfo{}; } diff --git a/engine/ecs/ecs_world.hpp b/engine/ecs/ecs_world.hpp index 2acd87e97..4b4a45282 100644 --- a/engine/ecs/ecs_world.hpp +++ b/engine/ecs/ecs_world.hpp @@ -30,6 +30,7 @@ #include "core/callback_queue.hpp" #include "core/fast_map.hpp" +#include "core/synchronization.hpp" #include "core/task_manager.hpp" #include "ecs/ecs_component.hpp" #include "ecs/ecs_core.hpp" @@ -128,7 +129,7 @@ namespace wmoge { CallbackQueue m_queue; // queue for async world operations, flushed on sync TaskManager* m_task_manager;// manager for parallel system update - mutable std::mutex m_mutex; + SpinMutex m_mutex; }; template diff --git a/engine/engine.hpp b/engine/engine.hpp index 14b2fc326..62d370dc6 100644 --- a/engine/engine.hpp +++ b/engine/engine.hpp @@ -151,8 +151,8 @@ #include "platform/window.hpp" #include "platform/window_manager.hpp" -#include "render/aux_draw_canvas.hpp" #include "render/aux_draw_manager.hpp" +#include "render/canvas.hpp" #include "render/render_camera.hpp" #include "render/render_engine.hpp" #include "render/render_mesh_skinned.hpp" diff --git a/engine/gfx/gfx_ctx.hpp b/engine/gfx/gfx_ctx.hpp index f8b694ef7..68927453d 100644 --- a/engine/gfx/gfx_ctx.hpp +++ b/engine/gfx/gfx_ctx.hpp @@ -95,8 +95,8 @@ namespace wmoge { virtual void draw_indexed(int index_count, int base_vertex, int instance_count) = 0; virtual void end_render_pass() = 0; - virtual void execute(const std::function& functor) = 0; - virtual void shutdown() = 0; + virtual void execute(const std::function& functor) = 0; + virtual void shutdown() = 0; virtual void begin_frame() = 0; virtual void end_frame() = 0; diff --git a/engine/gfx/gfx_defs.hpp b/engine/gfx/gfx_defs.hpp index 5330c0abb..fbef1c1ac 100644 --- a/engine/gfx/gfx_defs.hpp +++ b/engine/gfx/gfx_defs.hpp @@ -132,6 +132,12 @@ namespace wmoge { NegativeZ = 5, }; + /** @brief Tex view channels swizzling */ + enum class GfxTexSwizz : int { + None = 0, + RRRRtoRGBA = 1 + }; + /** @brief Formats used to specify internal storage format */ enum class GfxFormat : int { Unknown, diff --git a/engine/gfx/gfx_driver.hpp b/engine/gfx/gfx_driver.hpp index 20732dcdf..91c1836a6 100644 --- a/engine/gfx/gfx_driver.hpp +++ b/engine/gfx/gfx_driver.hpp @@ -69,24 +69,24 @@ namespace wmoge { virtual ~GfxDriver() = default; - virtual Ref make_vert_format(const GfxVertElements& elements, const StringId& name = StringId()) = 0; - virtual Ref make_vert_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; - virtual Ref make_index_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; - virtual Ref make_uniform_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; - virtual Ref make_storage_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; - virtual Ref make_shader(std::string vertex, std::string fragment, const GfxDescSetLayouts& layouts, const StringId& name = StringId()) = 0; - virtual Ref make_shader(Ref code, const StringId& name = StringId()) = 0; - virtual Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name = StringId()) = 0; - virtual Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name = StringId()) = 0; - virtual Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name = StringId()) = 0; - virtual Ref make_sampler(const GfxSamplerDesc& desc, const StringId& name = StringId()) = 0; - virtual Ref make_pipeline(const GfxPipelineState& state, const StringId& name = StringId()) = 0; - virtual Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const StringId& name = StringId()) = 0; - virtual Ref make_dyn_vert_buffer(int chunk_size, const StringId& name = StringId()) = 0; - virtual Ref make_dyn_index_buffer(int chunk_size, const StringId& name = StringId()) = 0; - virtual Ref make_dyn_uniform_buffer(int chunk_size, const StringId& name = StringId()) = 0; - virtual Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const StringId& name = StringId()) = 0; - virtual Ref make_desc_set(const GfxDescSetResources& resources, const StringId& name = StringId()) = 0; + virtual Ref make_vert_format(const GfxVertElements& elements, const StringId& name = StringId()) = 0; + virtual Ref make_vert_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; + virtual Ref make_index_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; + virtual Ref make_uniform_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; + virtual Ref make_storage_buffer(int size, GfxMemUsage usage, const StringId& name = StringId()) = 0; + virtual Ref make_shader(std::string vertex, std::string fragment, const GfxDescSetLayouts& layouts, const StringId& name = StringId()) = 0; + virtual Ref make_shader(Ref code, const StringId& name = StringId()) = 0; + virtual Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name = StringId()) = 0; + virtual Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name = StringId()) = 0; + virtual Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name = StringId()) = 0; + virtual Ref make_sampler(const GfxSamplerDesc& desc, const StringId& name = StringId()) = 0; + virtual Ref make_pipeline(const GfxPipelineState& state, const StringId& name = StringId()) = 0; + virtual Ref make_render_pass(const GfxRenderPassDesc& pass_desc, const StringId& name = StringId()) = 0; + virtual Ref make_dyn_vert_buffer(int chunk_size, const StringId& name = StringId()) = 0; + virtual Ref make_dyn_index_buffer(int chunk_size, const StringId& name = StringId()) = 0; + virtual Ref make_dyn_uniform_buffer(int chunk_size, const StringId& name = StringId()) = 0; + virtual Ref make_desc_layout(const GfxDescSetLayoutDesc& desc, const StringId& name = StringId()) = 0; + virtual Ref make_desc_set(const GfxDescSetResources& resources, const StringId& name = StringId()) = 0; virtual void shutdown() = 0; diff --git a/engine/gfx/gfx_pipeline_cache.cpp b/engine/gfx/gfx_pipeline_cache.cpp index 9365a3824..643b2644a 100644 --- a/engine/gfx/gfx_pipeline_cache.cpp +++ b/engine/gfx/gfx_pipeline_cache.cpp @@ -27,27 +27,22 @@ #include "gfx_pipeline_cache.hpp" -#include "core/log.hpp" -#include "gfx/gfx_driver.hpp" - #include namespace wmoge { - Ref GfxPipelineCache::get_or_create(const GfxPipelineState& state, const StringId& name) { + std::optional> GfxPipelineCache::get(const GfxPipelineState& state) { std::lock_guard guard(m_mutex); - - auto& pipeline = m_cache[state]; - if (!pipeline) { - pipeline = m_driver->make_pipeline(state, name); - WG_LOG_INFO("cache new pso " << name); + auto it = m_cache.find(state); + if (it != m_cache.end()) { + return it->second; } - - return pipeline; + return std::nullopt; } - void GfxPipelineCache::set_driver(GfxDriver* driver) { - m_driver = driver; + void GfxPipelineCache::add(const GfxPipelineState& state, const Ref& pipeline) { + std::lock_guard guard(m_mutex); + m_cache[state] = pipeline; } }// namespace wmoge \ No newline at end of file diff --git a/engine/gfx/gfx_pipeline_cache.hpp b/engine/gfx/gfx_pipeline_cache.hpp index a51820a8f..d55ae6a64 100644 --- a/engine/gfx/gfx_pipeline_cache.hpp +++ b/engine/gfx/gfx_pipeline_cache.hpp @@ -33,6 +33,8 @@ #include "core/synchronization.hpp" #include "gfx/gfx_pipeline.hpp" +#include + namespace wmoge { /** @@ -46,12 +48,11 @@ namespace wmoge { GfxPipelineCache(GfxPipelineCache&&) = delete; ~GfxPipelineCache() = default; - Ref get_or_create(const GfxPipelineState& state, const StringId& name = StringId()); - void set_driver(class GfxDriver* driver); + std::optional> get(const GfxPipelineState& state); + void add(const GfxPipelineState& state, const Ref& pipeline); private: fast_map> m_cache; - class GfxDriver* m_driver; SpinMutex m_mutex; }; diff --git a/engine/gfx/gfx_texture.hpp b/engine/gfx/gfx_texture.hpp index 79025f380..279e3054f 100644 --- a/engine/gfx/gfx_texture.hpp +++ b/engine/gfx/gfx_texture.hpp @@ -46,6 +46,7 @@ namespace wmoge { [[nodiscard]] int mips_count() const { return m_mips_count; } [[nodiscard]] int array_slices() const { return m_array_slices; } [[nodiscard]] GfxTex tex_type() const { return m_tex_type; } + [[nodiscard]] GfxTexSwizz tex_swizz() const { return m_swizz; } [[nodiscard]] GfxFormat format() const { return m_format; } [[nodiscard]] GfxMemUsage mem_usage() const { return m_mem_usage; } [[nodiscard]] GfxTexUsages usages() const { return m_usages; } @@ -57,6 +58,7 @@ namespace wmoge { int m_mips_count = 1; int m_array_slices = 1; GfxTex m_tex_type = GfxTex::Tex2d; + GfxTexSwizz m_swizz = GfxTexSwizz::None; GfxFormat m_format = GfxFormat::RGBA8; GfxMemUsage m_mem_usage = GfxMemUsage::GpuLocal; GfxTexUsages m_usages; diff --git a/engine/gfx/gfx_vector.hpp b/engine/gfx/gfx_vector.hpp index 326c28de9..a1aa12cca 100644 --- a/engine/gfx/gfx_vector.hpp +++ b/engine/gfx/gfx_vector.hpp @@ -101,6 +101,9 @@ namespace wmoge { if constexpr (std::is_same_v) { ptr = gfx_ctx->map_vert_buffer(m_buffer); } + if constexpr (std::is_same_v) { + ptr = gfx_ctx->map_index_buffer(m_buffer); + } if constexpr (std::is_same_v) { ptr = gfx_ctx->map_storage_buffer(m_buffer); } @@ -112,6 +115,9 @@ namespace wmoge { if constexpr (std::is_same_v) { gfx_ctx->unmap_vert_buffer(m_buffer); } + if constexpr (std::is_same_v) { + gfx_ctx->unmap_index_buffer(m_buffer); + } if constexpr (std::is_same_v) { gfx_ctx->unmap_storage_buffer(m_buffer); } @@ -152,6 +158,9 @@ namespace wmoge { if constexpr (std::is_same_v) { m_buffer = Engine::instance()->gfx_driver()->make_vert_buffer(new_size, GfxMemUsage::GpuLocal, buffer_name); } + if constexpr (std::is_same_v) { + m_buffer = Engine::instance()->gfx_driver()->make_index_buffer(new_size, GfxMemUsage::GpuLocal, buffer_name); + } if constexpr (std::is_same_v) { m_buffer = Engine::instance()->gfx_driver()->make_storage_buffer(new_size, GfxMemUsage::GpuLocal, buffer_name); } diff --git a/engine/gfx/gfx_vert_format_cache.cpp b/engine/gfx/gfx_vert_format_cache.cpp index f92f91037..ea10ccc63 100644 --- a/engine/gfx/gfx_vert_format_cache.cpp +++ b/engine/gfx/gfx_vert_format_cache.cpp @@ -27,27 +27,22 @@ #include "gfx_vert_format_cache.hpp" -#include "core/log.hpp" -#include "gfx/gfx_driver.hpp" - #include namespace wmoge { - Ref GfxVertFormatCache::get_or_create(const GfxVertElements& elements, const StringId& name) { + std::optional> GfxVertFormatCache::get(const GfxVertElements& elements) { std::lock_guard guard(m_mutex); - - auto& format = m_cache[elements]; - if (!format) { - format = m_driver->make_vert_format(elements, name); - WG_LOG_INFO("cache new format " << name); + auto it = m_cache.find(elements); + if (it != m_cache.end()) { + return it->second; } - - return format; + return std::nullopt; } - void GfxVertFormatCache::set_driver(GfxDriver* driver) { - m_driver = driver; + void GfxVertFormatCache::add(const GfxVertElements& elements, const Ref& format) { + std::lock_guard guard(m_mutex); + m_cache[elements] = format; } }// namespace wmoge \ No newline at end of file diff --git a/engine/gfx/gfx_vert_format_cache.hpp b/engine/gfx/gfx_vert_format_cache.hpp index 982daf39f..a9dba35c4 100644 --- a/engine/gfx/gfx_vert_format_cache.hpp +++ b/engine/gfx/gfx_vert_format_cache.hpp @@ -33,6 +33,8 @@ #include "core/synchronization.hpp" #include "gfx/gfx_vert_format.hpp" +#include + namespace wmoge { /** @@ -46,12 +48,11 @@ namespace wmoge { GfxVertFormatCache(GfxVertFormatCache&&) = delete; ~GfxVertFormatCache() = default; - Ref get_or_create(const GfxVertElements& elements, const StringId& name = StringId()); - void set_driver(class GfxDriver* driver); + std::optional> get(const GfxVertElements& elements); + void add(const GfxVertElements& elements, const Ref& format); private: fast_map> m_cache; - class GfxDriver* m_driver = nullptr; SpinMutex m_mutex; }; diff --git a/engine/gfx/threaded/gfx_ctx_wrapper.cpp b/engine/gfx/threaded/gfx_ctx_wrapper.cpp index f3195911b..6cb30164a 100644 --- a/engine/gfx/threaded/gfx_ctx_wrapper.cpp +++ b/engine/gfx/threaded/gfx_ctx_wrapper.cpp @@ -207,7 +207,7 @@ namespace wmoge { m_stream->push([=]() { m_ctx->end_render_pass(); }); } - void GfxCtxWrapper::execute(const std::function& functor) { + void GfxCtxWrapper::execute(const std::function& functor) { WG_AUTO_PROFILE_GFX("GfxCtxWrapper::execute"); m_stream->push_and_wait([&]() { m_ctx->execute(functor); }); diff --git a/engine/gfx/threaded/gfx_ctx_wrapper.hpp b/engine/gfx/threaded/gfx_ctx_wrapper.hpp index 41a745cee..19b4b7bb4 100644 --- a/engine/gfx/threaded/gfx_ctx_wrapper.hpp +++ b/engine/gfx/threaded/gfx_ctx_wrapper.hpp @@ -86,7 +86,7 @@ namespace wmoge { void draw_indexed(int index_count, int base_vertex, int instance_count) override; void end_render_pass() override; - void execute(const std::function& functor) override; + void execute(const std::function& functor) override; void shutdown() override; void begin_frame() override; diff --git a/engine/gfx/threaded/gfx_driver_wrapper.cpp b/engine/gfx/threaded/gfx_driver_wrapper.cpp index 411505b8f..bed9e7f88 100644 --- a/engine/gfx/threaded/gfx_driver_wrapper.cpp +++ b/engine/gfx/threaded/gfx_driver_wrapper.cpp @@ -27,6 +27,7 @@ #include "gfx_driver_wrapper.hpp" +#include "core/log.hpp" #include "debug/profiler.hpp" #include @@ -60,8 +61,15 @@ namespace wmoge { Ref GfxDriverWrapper::make_vert_format(const GfxVertElements& elements, const StringId& name) { WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_vert_format"); + auto cached = m_vert_fmt_cache->get(elements); + if (cached.has_value()) { + return cached.value(); + } + Ref vert_format; m_stream->push_and_wait([&]() { vert_format = m_driver->make_vert_format(elements, name); }); + m_vert_fmt_cache->add(elements, vert_format); + WG_LOG_INFO("cache new vf " << name); return vert_format; } Ref GfxDriverWrapper::make_vert_buffer(int size, GfxMemUsage usage, const StringId& name) { @@ -106,11 +114,11 @@ namespace wmoge { m_stream->push_and_wait([&]() { shader = m_driver->make_shader(std::move(code), name); }); return shader; } - Ref GfxDriverWrapper::make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) { + Ref GfxDriverWrapper::make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name) { WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_texture_2d"); Ref texture; - m_stream->push_and_wait([&]() { texture = m_driver->make_texture_2d(width, height, mips, format, usages, mem_usage, name); }); + m_stream->push_and_wait([&]() { texture = m_driver->make_texture_2d(width, height, mips, format, usages, mem_usage, swizz, name); }); return texture; } Ref GfxDriverWrapper::make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) { @@ -137,8 +145,15 @@ namespace wmoge { Ref GfxDriverWrapper::make_pipeline(const GfxPipelineState& state, const StringId& name) { WG_AUTO_PROFILE_GFX("GfxDriverWrapper::make_pipeline"); + auto cached = m_pso_cache->get(state); + if (cached.has_value()) { + return cached.value(); + } + Ref pipeline; m_stream->push_and_wait([&]() { pipeline = m_driver->make_pipeline(state, name); }); + m_pso_cache->add(state, pipeline); + WG_LOG_INFO("cache new pso " << name); return pipeline; } Ref GfxDriverWrapper::make_render_pass(const GfxRenderPassDesc& pass_desc, const StringId& name) { diff --git a/engine/gfx/threaded/gfx_driver_wrapper.hpp b/engine/gfx/threaded/gfx_driver_wrapper.hpp index 3cb908879..b1ea5558f 100644 --- a/engine/gfx/threaded/gfx_driver_wrapper.hpp +++ b/engine/gfx/threaded/gfx_driver_wrapper.hpp @@ -59,7 +59,7 @@ namespace wmoge { Ref make_storage_buffer(int size, GfxMemUsage usage, const StringId& name) override; Ref make_shader(std::string vertex, std::string fragment, const GfxDescSetLayouts& layouts, const StringId& name) override; Ref make_shader(Ref code, const StringId& name) override; - Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) override; + Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name) override; Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) override; Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) override; Ref make_sampler(const GfxSamplerDesc& desc, const StringId& name) override; diff --git a/engine/gfx/vulkan/vk_ctx.cpp b/engine/gfx/vulkan/vk_ctx.cpp index 08d49dd3e..40393f1e7 100644 --- a/engine/gfx/vulkan/vk_ctx.cpp +++ b/engine/gfx/vulkan/vk_ctx.cpp @@ -365,11 +365,15 @@ namespace wmoge { assert(check_thread_valid()); assert(m_in_render_pass); - if (m_render_pass_started) { - WG_VK_END_LABEL(cmd_current()); - vkCmdEndRenderPass(cmd_current()); + if (!m_render_pass_started) { + prepare_render_pass(); } + assert(m_render_pass_started); + + WG_VK_END_LABEL(cmd_current()); + vkCmdEndRenderPass(cmd_current()); + m_render_pass_binder->finish(); m_current_pass.reset(); m_current_pipeline.reset(); @@ -388,10 +392,10 @@ namespace wmoge { m_target_bound = false; } - void VKCtx::execute(const std::function& functor) { + void VKCtx::execute(const std::function& functor) { WG_AUTO_PROFILE_VULKAN("VKCtx::execute"); - functor(); + functor(this); } void VKCtx::shutdown() { WG_AUTO_PROFILE_VULKAN("VKCtx::shutdown"); diff --git a/engine/gfx/vulkan/vk_ctx.hpp b/engine/gfx/vulkan/vk_ctx.hpp index d3eefde3d..2ae79b4c1 100644 --- a/engine/gfx/vulkan/vk_ctx.hpp +++ b/engine/gfx/vulkan/vk_ctx.hpp @@ -94,7 +94,7 @@ namespace wmoge { void draw_indexed(int index_count, int base_vertex, int instance_count) override; void end_render_pass() override; - void execute(const std::function& functor) override; + void execute(const std::function& functor) override; void shutdown() override; void begin_frame() override; diff --git a/engine/gfx/vulkan/vk_driver.cpp b/engine/gfx/vulkan/vk_driver.cpp index 12c090d45..86da83d7b 100644 --- a/engine/gfx/vulkan/vk_driver.cpp +++ b/engine/gfx/vulkan/vk_driver.cpp @@ -155,10 +155,6 @@ namespace wmoge { // finally init wrapper for ctx immediate m_ctx_immediate_wrapper = std::make_unique(m_ctx_immediate.get()); - // Provide ptr to wrapper - m_pso_cache->set_driver(m_driver_wrapper.get()); - m_vert_fmt_cache->set_driver(m_driver_wrapper.get()); - WG_LOG_INFO("init vulkan gfx driver"); } VKDriver::~VKDriver() { @@ -243,13 +239,13 @@ namespace wmoge { return shader; } - Ref VKDriver::make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) { + Ref VKDriver::make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name) { WG_AUTO_PROFILE_VULKAN("VKDriver::make_texture_2d"); assert(on_gfx_thread()); auto texture = make_ref(*this); - texture->create_2d(m_ctx_immediate->cmd_current(), width, height, mips, format, usages, mem_usage, name); + texture->create_2d(m_ctx_immediate->cmd_current(), width, height, mips, format, usages, mem_usage, swizz, name); return texture; } Ref VKDriver::make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) { diff --git a/engine/gfx/vulkan/vk_driver.hpp b/engine/gfx/vulkan/vk_driver.hpp index ff3bd3e44..24a8a971f 100644 --- a/engine/gfx/vulkan/vk_driver.hpp +++ b/engine/gfx/vulkan/vk_driver.hpp @@ -71,7 +71,7 @@ namespace wmoge { Ref make_storage_buffer(int size, GfxMemUsage usage, const StringId& name) override; Ref make_shader(std::string vertex, std::string fragment, const GfxDescSetLayouts& layouts, const StringId& name) override; Ref make_shader(Ref code, const StringId& name) override; - Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) override; + Ref make_texture_2d(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name) override; Ref make_texture_2d_array(int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) override; Ref make_texture_cube(int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) override; Ref make_sampler(const GfxSamplerDesc& desc, const StringId& name) override; diff --git a/engine/gfx/vulkan/vk_texture.cpp b/engine/gfx/vulkan/vk_texture.cpp index 87fece23d..2210485fb 100644 --- a/engine/gfx/vulkan/vk_texture.cpp +++ b/engine/gfx/vulkan/vk_texture.cpp @@ -76,7 +76,7 @@ namespace wmoge { init_view(); init_layout(cmd); } - void VKTexture::create_2d(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name) { + void VKTexture::create_2d(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name) { WG_AUTO_PROFILE_VULKAN("VKTexture::create_2d"); m_tex_type = GfxTex::Tex2d; @@ -86,6 +86,7 @@ namespace wmoge { m_array_slices = 1; m_mips_count = mips; m_format = format; + m_swizz = swizz; m_usages = usages; m_name = name; m_mem_usage = mem_usage; @@ -310,10 +311,19 @@ namespace wmoge { view_info.subresourceRange.levelCount = m_mips_count; view_info.subresourceRange.baseArrayLayer = 0; view_info.subresourceRange.layerCount = m_array_slices; - view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; - view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; - view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; - view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + + if (m_swizz == GfxTexSwizz::None) { + view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.g = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.b = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.a = VK_COMPONENT_SWIZZLE_IDENTITY; + } + if (m_swizz == GfxTexSwizz::RRRRtoRGBA) { + view_info.components.r = VK_COMPONENT_SWIZZLE_IDENTITY; + view_info.components.g = VK_COMPONENT_SWIZZLE_R; + view_info.components.b = VK_COMPONENT_SWIZZLE_R; + view_info.components.a = VK_COMPONENT_SWIZZLE_R; + } WG_VK_CHECK(vkCreateImageView(m_driver.device(), &view_info, nullptr, &m_view)); WG_VK_NAME(m_driver.device(), m_view, VK_OBJECT_TYPE_IMAGE_VIEW, "image_view " + name().str()); diff --git a/engine/gfx/vulkan/vk_texture.hpp b/engine/gfx/vulkan/vk_texture.hpp index a9adbe9dd..ff0220c5d 100644 --- a/engine/gfx/vulkan/vk_texture.hpp +++ b/engine/gfx/vulkan/vk_texture.hpp @@ -45,7 +45,7 @@ namespace wmoge { ~VKTexture() override; void create_2d(VkCommandBuffer cmd, int width, int height, VkImage image, VkFormat format, const StringId& name); - void create_2d(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name); + void create_2d(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, GfxTexSwizz swizz, const StringId& name); void create_2d_array(VkCommandBuffer cmd, int width, int height, int mips, int slices, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name); void create_cube(VkCommandBuffer cmd, int width, int height, int mips, GfxFormat format, GfxTexUsages usages, GfxMemUsage mem_usage, const StringId& name); diff --git a/engine/gfx/vulkan/vk_window.cpp b/engine/gfx/vulkan/vk_window.cpp index e74ab7319..c33ef7278 100644 --- a/engine/gfx/vulkan/vk_window.cpp +++ b/engine/gfx/vulkan/vk_window.cpp @@ -217,7 +217,7 @@ namespace wmoge { GfxTexUsages depth_stencil_usages; depth_stencil_usages.set(GfxTexUsageFlag::DepthStencilTarget); m_depth_stencil_target = make_ref(m_driver); - m_depth_stencil_target->create_2d(m_driver.vk_ctx()->cmd_current(), width(), height(), 1, GfxFormat::DEPTH24_STENCIL8, depth_stencil_usages, GfxMemUsage::GpuLocal, m_window->id()); + m_depth_stencil_target->create_2d(m_driver.vk_ctx()->cmd_current(), width(), height(), 1, GfxFormat::DEPTH24_STENCIL8, depth_stencil_usages, GfxMemUsage::GpuLocal, GfxTexSwizz::None, m_window->id()); m_requested_extent = m_extent; m_version += 1; diff --git a/engine/hgfx/hgfx_pass_base.cpp b/engine/hgfx/hgfx_pass_base.cpp index 4393ee2ea..8ecdf4dfa 100644 --- a/engine/hgfx/hgfx_pass_base.cpp +++ b/engine/hgfx/hgfx_pass_base.cpp @@ -54,7 +54,7 @@ namespace wmoge { GfxPipelineState pipeline_state{}; pipeline_state.shader = shader_manager->get_shader(SID("base"), attribs_req, defines); - pipeline_state.vert_format = gfx_driver->vert_fmt_cache()->get_or_create(elements, name); + pipeline_state.vert_format = gfx_driver->make_vert_format(elements, name); pipeline_state.prim_type = prim_type; pipeline_state.poly_mode = poly_mode; pipeline_state.cull_mode = cull_mode; @@ -64,7 +64,7 @@ namespace wmoge { pipeline_state.depth_func = depth_func; pipeline_state.blending = !no_alpha; - m_pipeline = gfx_driver->pso_cache()->get_or_create(pipeline_state, name); + m_pipeline = gfx_driver->make_pipeline(pipeline_state, name); ShaderBase::Params params; params.mat_clip_proj_view = (gfx_driver->clip_matrix() * mat_proj_view).transpose(); diff --git a/engine/hgfx/hgfx_pass_text.cpp b/engine/hgfx/hgfx_pass_text.cpp index 8d541de5a..4af8f45e4 100644 --- a/engine/hgfx/hgfx_pass_text.cpp +++ b/engine/hgfx/hgfx_pass_text.cpp @@ -53,10 +53,10 @@ namespace wmoge { GfxPipelineState pipeline_state{}; pipeline_state.shader = shader_manager->get_shader(SID("text"), attribs, defines); - pipeline_state.vert_format = gfx_driver->vert_fmt_cache()->get_or_create(elements, name); + pipeline_state.vert_format = gfx_driver->make_vert_format(elements, name); pipeline_state.blending = true; - m_pipeline = gfx_driver->pso_cache()->get_or_create(pipeline_state, name); + m_pipeline = gfx_driver->make_pipeline(pipeline_state, name); ShaderText::Params params; params.mat_clip_proj_screen = (gfx_driver->clip_matrix() * Math3d::orthographic(0.0f, screen_size.x(), 0, screen_size.y(), -1000.0f, 1000.0f)).transpose(); diff --git a/engine/main/main.cpp b/engine/main/main.cpp index 8d67a9111..950fe6af8 100644 --- a/engine/main/main.cpp +++ b/engine/main/main.cpp @@ -50,10 +50,11 @@ #include "platform/glfw/glfw_window_manager.hpp" #include "platform/input.hpp" #include "platform/window_manager.hpp" -#include "render/aux_draw_canvas.hpp" #include "render/aux_draw_manager.hpp" +#include "render/canvas.hpp" #include "render/render_engine.hpp" #include "render/shader_manager.hpp" +#include "render/texture_manager.hpp" #include "resource/config_file.hpp" #include "resource/resource_manager.hpp" #include "scene/scene_manager.hpp" @@ -158,6 +159,9 @@ namespace wmoge { m_shader_manager = std::make_unique(); engine->m_shader_manager = m_shader_manager.get(); + m_texture_manager = std::make_unique(); + engine->m_texture_manager = m_texture_manager.get(); + m_render_engine = std::make_unique(); engine->m_render_engine = m_render_engine.get(); @@ -179,8 +183,8 @@ namespace wmoge { m_game_token_manager = std::make_unique(); engine->m_game_token_manager = m_game_token_manager.get(); - m_canvas_2d_debug = std::make_unique(); - engine->m_canvas_2d_debug = m_canvas_2d_debug.get(); + m_canvas_debug = std::make_unique(); + engine->m_canvas_debug = m_canvas_debug.get(); m_console->init(); WG_LOG_INFO("init high level systems"); @@ -272,9 +276,10 @@ namespace wmoge { m_game_token_manager.reset(); m_action_manager.reset(); m_aux_draw_manager.reset(); - m_canvas_2d_debug.reset(); + m_canvas_debug.reset(); m_ecs_registry.reset(); m_render_engine.reset(); + m_texture_manager.reset(); m_shader_manager.reset(); m_al_engine.reset(); m_vk_driver.reset(); diff --git a/engine/main/main.hpp b/engine/main/main.hpp index 35db5d2a8..aa32b53b0 100644 --- a/engine/main/main.hpp +++ b/engine/main/main.hpp @@ -77,8 +77,9 @@ namespace wmoge { std::unique_ptr m_game_token_manager; std::unique_ptr m_profiler; std::unique_ptr m_console; - std::unique_ptr m_canvas_2d_debug; + std::unique_ptr m_canvas_debug; std::unique_ptr m_shader_manager; + std::unique_ptr m_texture_manager; std::unique_ptr m_render_engine; std::unique_ptr m_ecs_registry; std::unique_ptr m_glfw_window_manager; diff --git a/engine/mesh/mesh_processors.cpp b/engine/mesh/mesh_processors.cpp index 047fc03e5..32f7c71f6 100644 --- a/engine/mesh/mesh_processors.cpp +++ b/engine/mesh/mesh_processors.cpp @@ -70,7 +70,7 @@ namespace wmoge { gfx_pso_state.depth_func = pipeline_state.depth_func; gfx_pso_state.blending = false; - out_pipeline = m_gfx_driver->pso_cache()->get_or_create(gfx_pso_state); + out_pipeline = m_gfx_driver->make_pipeline(gfx_pso_state); return StatusCode::Ok; } diff --git a/engine/render/aux_draw_canvas.cpp b/engine/render/aux_draw_canvas.cpp deleted file mode 100644 index f2f33d061..000000000 --- a/engine/render/aux_draw_canvas.cpp +++ /dev/null @@ -1,420 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#include "aux_draw_canvas.hpp" - -#include "core/engine.hpp" -#include "core/log.hpp" -#include "debug/profiler.hpp" -#include "gfx/gfx_driver.hpp" -#include "math/math_utils2d.hpp" -#include "math/math_utils3d.hpp" -#include "render/render_engine.hpp" -#include "render/shader_manager.hpp" -#include "resource/config_file.hpp" -#include "shaders/generated/auto_aux_draw_canvas_reflection.hpp" - -#include - -namespace wmoge { - - AuxDrawCanvas::AuxDrawCanvas() { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::AuxDrawCanvas"); - - auto engine = Engine::instance(); - auto gfx_driver = engine->gfx_driver(); - auto gfx_ctx = engine->gfx_ctx(); - - m_transform_stack.push_back(Math2d::translate_rotate_z(Vec2f(), 0.0f)); - - m_default_sampler = gfx_driver->make_sampler(GfxSamplerDesc{}, SID("default")); - m_default_texture = gfx_driver->make_texture_2d(1, 1, 1, GfxFormat::RGBA8, {GfxTexUsageFlag::Sampling}, GfxMemUsage::GpuLocal, SID("default_white")); - - unsigned char white[] = {0xff, 0xff, 0xff, 0xff}; - gfx_ctx->update_texture_2d(m_default_texture, 0, Rect2i(0, 0, 1, 1), make_ref(white, sizeof(white))); - - // b0_Pos2Uv2Col4; - { - GfxVertElements elements; - elements.add_element(SID("pos"), GfxFormat::RG32F, 0, offsetof(GfxVF_Pos2Uv2Col4, pos), sizeof(GfxVF_Pos2Uv2Col4)); - elements.add_element(SID("uv"), GfxFormat::RG32F, 0, offsetof(GfxVF_Pos2Uv2Col4, uv), sizeof(GfxVF_Pos2Uv2Col4)); - elements.add_element(SID("col"), GfxFormat::RGBA32F, 0, offsetof(GfxVF_Pos2Uv2Col4, col), sizeof(GfxVF_Pos2Uv2Col4)); - m_b0_Pos2Uv2Col4 = gfx_driver->make_vert_format(elements, SID("b0_Pos2Uv2Col4")); - } - } - - void AuxDrawCanvas::push(const Vec2f& translate, float rotate_rad, const Vec2f& scale) { - push(Math2d::translate_rotate_z(translate, rotate_rad) * Math2d::scale(scale)); - } - void AuxDrawCanvas::push(const Vec2f& translate, float rotate_rad) { - push(Math2d::translate_rotate_z(translate, rotate_rad)); - } - void AuxDrawCanvas::push(const Transform2d& transform) { - push(transform.get_transform()); - } - void AuxDrawCanvas::push(const Mat3x3f& matr) { - assert(m_transform_stack.size() > 0); - auto new_transform = m_transform_stack.back() * matr; - m_transform_stack.push_back(new_transform); - } - void AuxDrawCanvas::pop() { - assert(m_transform_stack.size() > 1); - m_transform_stack.pop_back(); - } - const Mat3x3f& AuxDrawCanvas::peek() { - assert(m_transform_stack.size() >= 1); - return m_transform_stack.back(); - } - void AuxDrawCanvas::set_line_color(const Color4f& color) { - m_color_line = color; - } - void AuxDrawCanvas::set_fill_color(const Color4f& color) { - m_color_fill = color; - } - void AuxDrawCanvas::set_font_color(const Color4f& color) { - m_color_font = color; - } - void AuxDrawCanvas::set_tint_color(const Color4f& color) { - m_color_tint = color; - } - void AuxDrawCanvas::set_font(Ref font) { - m_font = std::move(font); - } - - void AuxDrawCanvas::draw_line(const Vec2f& from, const Vec2f& to, float width) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_line"); - - float x = to.x() - from.x(); - float y = to.y() - from.y(); - - float angle = Math::atan2(y, x); - float half_width = width * 0.5f; - - push(from, angle); - add_rect(Vec2f(0, -half_width), Vec2f(Vec2f(x, y).length(), width), m_color_line); - pop(); - } - void AuxDrawCanvas::draw_triangle(const Vec2f& p0, const Vec2f& p1, const Vec2f& p2, float border) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_triangle"); - - draw_line(p0, p1, border); - draw_line(p1, p2, border); - draw_line(p2, p0, border); - } - void AuxDrawCanvas::draw_rect(const Vec2f& pos, const Vec2f& size, float border) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_rect"); - - const Vec2f p0(pos.x(), pos.y() + size.y()); - const Vec2f p1(pos.x(), pos.y()); - const Vec2f p2(pos.x() + size.x(), pos.y()); - const Vec2f p3(pos.x() + size.x(), pos.y() + size.y()); - - draw_line(p0, p1, border); - draw_line(p1, p2, border); - draw_line(p2, p3, border); - draw_line(p3, p0, border); - } - void AuxDrawCanvas::draw_filled_triangle(const Vec2f& p0, const Vec2f& p1, const Vec2f& p2) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_filled_triangle"); - - add_triangle(p0, p1, p2, m_color_fill); - } - void AuxDrawCanvas::draw_filled_rect(const Vec2f& pos, const Vec2f& size) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_filled_rect"); - - const Vec2f p0(pos.x(), pos.y() + size.y()); - const Vec2f p1(pos.x(), pos.y()); - const Vec2f p2(pos.x() + size.x(), pos.y()); - const Vec2f p3(pos.x() + size.x(), pos.y() + size.y()); - - draw_filled_triangle(p0, p1, p2); - draw_filled_triangle(p2, p3, p0); - } - void AuxDrawCanvas::draw_texture(const Ref& texture, const Vec2f& pos, const Vec2f& size, const Vec2f& uv_base, const Vec2f& uv_size) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_texture"); - - assert(texture); - - const auto& mat = m_transform_stack.back(); - const auto& gfx_texture = texture->get_texture(); - const auto& gfx_sampler = texture->get_sampler(); - - Vec2f p[4]; - Vec2f t[4]; - - p[0] = Math2d::transform(mat, Vec2f(pos.x(), pos.y() + size.y())); - p[1] = Math2d::transform(mat, Vec2f(pos.x(), pos.y())); - p[2] = Math2d::transform(mat, Vec2f(pos.x() + size.x(), pos.y())); - p[3] = Math2d::transform(mat, Vec2f(pos.x() + size.x(), pos.y() + size.y())); - - t[0] = Vec2f(uv_base.x(), uv_base.y() + uv_size.y()); - t[1] = Vec2f(uv_base.x(), uv_base.y()); - t[2] = Vec2f(uv_base.x() + uv_size.x(), uv_base.y()); - t[3] = Vec2f(uv_base.x() + uv_size.x(), uv_base.y() + uv_size.y()); - - auto& t1 = m_triangles.emplace_back(); - t1.p[0] = p[0]; - t1.p[1] = p[1]; - t1.p[2] = p[2]; - t1.t[0] = t[0]; - t1.t[1] = t[1]; - t1.t[2] = t[2]; - t1.color = m_color_tint; - t1.texture = gfx_texture; - t1.sampler = gfx_sampler; - t1.is_text = false; - - auto& t2 = m_triangles.emplace_back(); - t2.p[0] = p[2]; - t2.p[1] = p[3]; - t2.p[2] = p[0]; - t2.t[0] = t[2]; - t2.t[1] = t[3]; - t2.t[2] = t[0]; - t2.color = m_color_tint; - t2.texture = gfx_texture; - t2.sampler = gfx_sampler; - t2.is_text = false; - } - void AuxDrawCanvas::draw_text(const std::string& text, const Vec2f& pos, float size) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::draw_text"); - - const int n = int(text.size()); - - if (!n) { - WG_LOG_WARNING("passed empty string to draw"); - return; - } - - const auto& mat = m_transform_stack.back(); - const float scale = size > 0 ? size / float(m_font->get_height()) : 1.0f; - const auto& bitmap = m_font->get_bitmap(); - const auto& sampler = m_font->get_sampler(); - const auto& glyphs = m_font->get_glyphs(); - const auto null_glyph = glyphs.find(0)->second; - - float advance_x = 0.0f; - - for (int i = 0; i < n; ++i) { - auto c = text[i]; - auto query = glyphs.find(int(c)); - - FontGlyph font_glyph = null_glyph; - if (query != glyphs.end()) font_glyph = query->second; - - float left = advance_x + scale * float(font_glyph.bearing.x()); - float top = scale * float(font_glyph.bearing.y()); - float right = left + scale * float(font_glyph.size.x()); - float bottom = top - scale * float(font_glyph.size.y()); - - Vec2f p[4]; - Vec2f t[4]; - - p[0] = Math2d::transform(mat, pos + Vec2f(left, top)); - p[1] = Math2d::transform(mat, pos + Vec2f(left, bottom)); - p[2] = Math2d::transform(mat, pos + Vec2f(right, bottom)); - p[3] = Math2d::transform(mat, pos + Vec2f(right, top)); - - t[0] = font_glyph.bitmap_uv0; - t[1] = Vec2f(font_glyph.bitmap_uv0.x(), font_glyph.bitmap_uv1.y()); - t[2] = font_glyph.bitmap_uv1; - t[3] = Vec2f(font_glyph.bitmap_uv1.x(), font_glyph.bitmap_uv0.y()); - - auto& t1 = m_triangles.emplace_back(); - t1.p[0] = p[0]; - t1.p[1] = p[1]; - t1.p[2] = p[2]; - t1.t[0] = t[0]; - t1.t[1] = t[1]; - t1.t[2] = t[2]; - t1.color = m_color_font; - t1.texture = bitmap; - t1.sampler = sampler; - t1.is_text = true; - - auto& t2 = m_triangles.emplace_back(); - t2.p[0] = p[2]; - t2.p[1] = p[3]; - t2.p[2] = p[0]; - t2.t[0] = t[2]; - t2.t[1] = t[3]; - t2.t[2] = t[0]; - t2.color = m_color_font; - t2.texture = bitmap; - t2.sampler = sampler; - t2.is_text = true; - - advance_x += scale * float(font_glyph.advance.x()); - } - } - - void AuxDrawCanvas::add_triangle(const Vec2f& p0, const Vec2f& p1, const Vec2f& p2, const Color4f& color) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::add_triangle"); - - const auto& mat = m_transform_stack.back(); - auto& triangle = m_triangles.emplace_back(); - triangle.p[0] = Math2d::transform(mat, p0); - triangle.p[1] = Math2d::transform(mat, p1); - triangle.p[2] = Math2d::transform(mat, p2); - triangle.t[0] = Vec2f(0, 0); - triangle.t[1] = Vec2f(1, 0); - triangle.t[2] = Vec2f(1, 1); - triangle.color = color; - triangle.texture = m_default_texture; - triangle.sampler = m_default_sampler; - } - void AuxDrawCanvas::add_rect(const Vec2f& pos, const Vec2f& size, const Color4f& color) { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::add_rect"); - - const Vec2f p0(pos.x(), pos.y() + size.y()); - const Vec2f p1(pos.x(), pos.y()); - const Vec2f p2(pos.x() + size.x(), pos.y()); - const Vec2f p3(pos.x() + size.x(), pos.y() + size.y()); - - add_triangle(p0, p1, p2, color); - add_triangle(p2, p3, p0, color); - } - - void AuxDrawCanvas::set_window(const Ref& window) { - m_window = window; - } - void AuxDrawCanvas::set_viewport(const Rect2i& viewport) { - m_viewport = viewport; - } - void AuxDrawCanvas::set_screen_size(const Vec2f& size) { - m_screen_size = size; - } - - void AuxDrawCanvas::render() { - WG_AUTO_PROFILE_RENDER("AuxDrawCanvas::render"); - - return; - - auto engine = Engine::instance(); - auto gfx_driver = engine->gfx_driver(); - auto gfx_ctx = engine->gfx_ctx(); - auto shader_manager = engine->shader_manager(); - auto gfx_dyn_vert = gfx_driver->dyn_vert_buffer(); - - int num_of_verts_triangles = 3 * static_cast(m_triangles.size()); - - if (!num_of_verts_triangles) return; - - auto triangles = gfx_dyn_vert->allocate_n(num_of_verts_triangles); - - if (num_of_verts_triangles > 0) { - for (const auto& entry : m_triangles) { - triangles.ptr->pos = entry.p[0]; - triangles.ptr->uv = entry.t[0]; - triangles.ptr->col = entry.color; - triangles.ptr++; - triangles.ptr->pos = entry.p[1]; - triangles.ptr->uv = entry.t[1]; - triangles.ptr->col = entry.color; - triangles.ptr++; - triangles.ptr->pos = entry.p[2]; - triangles.ptr->uv = entry.t[2]; - triangles.ptr->col = entry.color; - triangles.ptr++; - } - } - - gfx_dyn_vert->flush(); - - ShaderAuxDrawCanvas::Params params; - params.clip_proj_screen = (gfx_ctx->clip_matrix() * Math3d::orthographic(0.0f, m_screen_size.x(), 0, m_screen_size.y(), -1000.0f, 1000.0f)).transpose(); - params.gamma = 2.2f; - params.inverse_gamma = 1.0f / 2.2f; - auto params_setup = gfx_driver->uniform_pool()->allocate(params); - - gfx_ctx->begin_render_pass(GfxRenderPassDesc{}, SID("aux_draw_canvas")); - gfx_ctx->bind_target(m_window); - gfx_ctx->viewport(m_viewport); - - GfxPipeline* prev_bound = nullptr; - - GfxPipelineState pipeline_state; - pipeline_state.cull_mode = GfxPolyCullMode::Disabled; - pipeline_state.front_face = GfxPolyFrontFace::CounterClockwise; - pipeline_state.poly_mode = GfxPolyMode::Fill; - pipeline_state.depth_enable = false; - pipeline_state.depth_write = false; - pipeline_state.prim_type = GfxPrimType::Triangles; - pipeline_state.vert_format = m_b0_Pos2Uv2Col4; - pipeline_state.blending = true; - - pipeline_state.shader = shader_manager->get_shader(SID("aux_draw_canvas")); - auto pipeline_triangle = gfx_driver->make_pipeline(pipeline_state, SID("canvas_triangle")); - - pipeline_state.shader = shader_manager->get_shader(SID("aux_draw_canvas"), {"CANVAS_FONT_BITMAP"}); - auto pipeline_text = gfx_driver->make_pipeline(pipeline_state, SID("canvas_text")); - - if (num_of_verts_triangles > 0) { - int current_triangle_id = 0; - while (current_triangle_id < m_triangles.size()) { - const auto& current_triangle = m_triangles[current_triangle_id]; - int next_triangle_id = current_triangle_id + 1; - - while (next_triangle_id < m_triangles.size()) { - const auto& next_triangle = m_triangles[next_triangle_id]; - - if (current_triangle.texture != next_triangle.texture || - current_triangle.sampler != next_triangle.sampler || - current_triangle.is_text != next_triangle.is_text) { - break; - } - - next_triangle_id += 1; - } - - int batch_size = next_triangle_id - current_triangle_id; - int start_vertex = 3 * current_triangle_id; - int vertex_count = batch_size * 3; - - bool is_text = current_triangle.is_text; - Ref& to_bind = is_text ? pipeline_text : pipeline_triangle; - - if (to_bind.get() == prev_bound || gfx_ctx->bind_pipeline(to_bind)) { - gfx_ctx->bind_vert_buffer(Ref(triangles.buffer), 0, triangles.offset); - // gfx_ctx->bind_uniform_buffer(ShaderAuxDrawCanvas::PARAMS_LOC, params_setup.offset, params_setup.range, Ref(params_setup.buffer)); - // gfx_ctx->bind_texture(ShaderAuxDrawCanvas::TEXTURE_LOC, 0, current_triangle.texture, current_triangle.sampler); - gfx_ctx->draw(vertex_count, start_vertex, 1); - prev_bound = to_bind.get(); - } - - current_triangle_id = next_triangle_id; - } - } - - gfx_ctx->end_render_pass(); - - m_triangles.clear(); - - gfx_dyn_vert->recycle(); - } - -}// namespace wmoge diff --git a/engine/render/aux_draw_canvas.hpp b/engine/render/aux_draw_canvas.hpp deleted file mode 100644 index cb688c1ce..000000000 --- a/engine/render/aux_draw_canvas.hpp +++ /dev/null @@ -1,143 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -#ifndef WMOGE_AUX_DRAW_CANVAS_HPP -#define WMOGE_AUX_DRAW_CANVAS_HPP - -#include "core/fast_vector.hpp" - -#include "gfx/gfx_buffers.hpp" -#include "gfx/gfx_pipeline.hpp" -#include "gfx/gfx_sampler.hpp" -#include "gfx/gfx_texture.hpp" - -#include "platform/window.hpp" -#include "resource/font.hpp" -#include "resource/shader.hpp" -#include "resource/texture.hpp" - -#include "math/color.hpp" -#include "math/mat.hpp" -#include "math/quat.hpp" -#include "math/transform.hpp" -#include "math/vec.hpp" - -#include -#include - -namespace wmoge { - - /** - * @class AuxDrawCanvas - * @brief 2d drawing canvas for a vector graphics, text and image rendering - * - * Canvas allows to paint a virtual surface from a back to front using - * standard primitives, such as lines, curves, rectangles, text and - * textures for image drawing. - * - * @note Canvas supports transformation stack (in a old OpenCL 1.0 fashion). - * It allows to stack transformations and graw primitives without - * 2d math complexity. - * - * @note Canvas supports alpha blending automatically. User can draw any - * primitives. They automatically overlay one on top of the another - * following the order of the drawing. - * - * @note The rendering of the elements is optimized using batching. Consecutive - * elements with the same type and texture are rendered at once as a - * group. Thy to avoid mixing of primitives in your code in order to - * get maximum performance of the rendering. - */ - class AuxDrawCanvas final { - public: - AuxDrawCanvas(); - - void push(const Vec2f& translate, float rotate_rad, const Vec2f& scale); - void push(const Vec2f& translate, float rotate_rad); - void push(const Transform2d& transform); - void push(const Mat3x3f& matr); - void pop(); - const Mat3x3f& peek(); - - void set_line_color(const Color4f& color); - void set_fill_color(const Color4f& color); - void set_font_color(const Color4f& color); - void set_tint_color(const Color4f& color); - void set_font(Ref font); - - void draw_line(const Vec2f& from, const Vec2f& to, float width); - void draw_triangle(const Vec2f& p0, const Vec2f& p1, const Vec2f& p2, float border); - void draw_rect(const Vec2f& pos, const Vec2f& size, float border); - void draw_filled_triangle(const Vec2f& p0, const Vec2f& p1, const Vec2f& p2); - void draw_filled_rect(const Vec2f& pos, const Vec2f& size); - void draw_texture(const Ref& texture, const Vec2f& pos, const Vec2f& size, const Vec2f& uv_base, const Vec2f& uv_size); - void draw_text(const std::string& text, const Vec2f& pos, float size); - - void set_window(const Ref& window); - void set_viewport(const Rect2i& viewport); - void set_screen_size(const Vec2f& size); - - Rect2i get_viewport() { return m_viewport; } - Vec2f get_screen_size() { return m_screen_size; } - - void render(); - - private: - struct CanvasTriangle { - Vec2f p[3]; - Vec2f t[3]; - Color4f color; - Ref texture; - Ref sampler; - bool is_text = false; - }; - - void add_triangle(const Vec2f& p0, const Vec2f& p1, const Vec2f& p2, const Color4f& color); - void add_rect(const Vec2f& pos, const Vec2f& size, const Color4f& color); - - private: - fast_vector m_transform_stack; - Color4f m_color_line; - Color4f m_color_fill; - Color4f m_color_font; - Color4f m_color_tint; - Ref m_font; - - std::vector m_triangles; - - Ref m_b0_Pos2Uv2Col4; - Ref m_default_texture; - Ref m_default_sampler; - - Ref m_window; - Rect2i m_viewport; - Vec2f m_screen_size; - }; - -}// namespace wmoge - -#endif//WMOGE_AUX_DRAW_CANVAS_HPP diff --git a/engine/render/aux_draw_manager.cpp b/engine/render/aux_draw_manager.cpp index 1ebf7066d..637795646 100644 --- a/engine/render/aux_draw_manager.cpp +++ b/engine/render/aux_draw_manager.cpp @@ -689,21 +689,23 @@ namespace wmoge { m_tria_wired.flush(gfx_ctx); m_text.flush(gfx_ctx); - gfx_ctx->begin_render_pass({}, SID("AuxDrawManager::render")); - gfx_ctx->bind_target(window); - gfx_ctx->viewport(viewport); - HgfxPass* passes[num_types] = {&pass_lines, &pass_triangles_solid, &pass_triangles_wire, &pass_text}; - for (int i = 0; i < num_types; i++) { - // if it has primitives and configured pass - do draw - if (num_elements[i] > 0 && passes[i] && passes[i]->configure(gfx_ctx)) { - gfx_ctx->bind_vert_buffer(*vert_buffers[i], 0, 0); - gfx_ctx->draw(num_vertices[i], 0, 1); + gfx_ctx->execute([&](GfxCtx* thread_ctx) { + thread_ctx->begin_render_pass({}, SID("AuxDrawManager::render")); + thread_ctx->bind_target(window); + thread_ctx->viewport(viewport); + + for (int i = 0; i < num_types; i++) { + // if it has primitives and configured pass - do draw + if (num_elements[i] > 0 && passes[i] && passes[i]->configure(thread_ctx)) { + thread_ctx->bind_vert_buffer(*vert_buffers[i], 0, 0); + thread_ctx->draw(num_vertices[i], 0, 1); + } } - } - gfx_ctx->end_render_pass(); + thread_ctx->end_render_pass(); + }); } void AuxDrawManager::flush(float delta_time) { WG_AUTO_PROFILE_RENDER("AuxDrawManager::flush"); diff --git a/engine/render/canvas.cpp b/engine/render/canvas.cpp new file mode 100644 index 000000000..0e1274661 --- /dev/null +++ b/engine/render/canvas.cpp @@ -0,0 +1,587 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +#include "canvas.hpp" + +#include "core/engine.hpp" +#include "core/string_utils.hpp" +#include "debug/profiler.hpp" +#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_driver.hpp" +#include "render/shader_manager.hpp" +#include "render/texture_manager.hpp" + +#include + +namespace wmoge { + + CanvasSharedData::CanvasSharedData() { + Engine* engine = Engine::instance(); + GfxDriver* driver = engine->gfx_driver(); + ShaderManager* shader_manager = engine->shader_manager(); + + GfxVertAttribs attribs_vert = {GfxVertAttrib::Pos2f, GfxVertAttrib::Col04f, GfxVertAttrib::Uv02f}; + GfxVertAttribs attribs_inst = {GfxVertAttrib::PrimitiveIdi}; + GfxVertAttribs attribs_full = attribs_vert | attribs_inst; + + GfxVertElements elements; + elements.add_vert_attribs(attribs_vert, 0, false); + elements.add_vert_attribs(attribs_inst, 1, true); + + GfxPipelineState pso_state{}; + pso_state.vert_format = driver->make_vert_format(elements, SID("[pos2, col0, uv0, primitiveId]")); + pso_state.depth_enable = false; + pso_state.depth_write = false; + pso_state.blending = true; + + pso_state.shader = shader_manager->get_shader(SID("canvas"), attribs_full, {"OUT_SRGB"}); + pipeline_srgb = driver->make_pipeline(pso_state, SID("canvas_srgb")); + + pso_state.shader = shader_manager->get_shader(SID("canvas"), attribs_full, {}); + pipeline_linear = driver->make_pipeline(pso_state, SID("canvas_linear")); + } + + void CanvasSharedData::compile() { + WG_AUTO_PROFILE_RENDER("CanvasSharedData::compile"); + + Engine* engine = Engine::instance(); + GfxDriver* gfx_drvier = engine->gfx_driver(); + TextureManager* tex_manager = engine->texture_manager(); + + // Expecting to fit all textures in single set (mathces most use cases) + const int textures_count = int(tex_buffer.size()); + const int textures_count_aligned = int(Math::align(textures_count, MAX_CANVAS_IMAGES)); + const int texture_gpoups = textures_count_aligned / MAX_CANVAS_IMAGES; + + tex_sets.resize(texture_gpoups); + + for (int i = 0; i < texture_gpoups; i++) { + GfxDescSetResources resources; + + for (int j = 0; j < MAX_CANVAS_IMAGES; j++) { + const int textureIdx = i * MAX_CANVAS_IMAGES + j; + + auto& r = resources.emplace_back(); + auto& point = r.first; + auto& value = r.second; + + point.type = GfxBindingType::SampledTexture; + point.binding = j; + point.array_element = 0; + + if (textureIdx < tex_buffer.size()) { + const Ref texture = tex_buffer[textureIdx]; + value.resource = texture->get_texture().as(); + value.sampler = texture->get_sampler(); + } else { + value.resource = tex_manager->get_gfx_default_texture_white().as(); + value.sampler = tex_manager->get_gfx_default_sampler(); + } + } + + const std::string name = "canvas idx=" + StringUtils::from_int(i); + tex_sets[i] = gfx_drvier->make_desc_set(resources, SID(name)); + } + } + + void CanvasSharedData::clear() { + tex_sets.clear(); + tex_buffer.clear(); + } + + Canvas::Canvas() : Canvas(std::make_shared()) { + } + + Canvas::Canvas(std::shared_ptr shared) { + assert(shared); + + m_shared = std::move(shared); + m_vtx_buffer.set_name(SID("canvas_vtx")); + m_idx_buffer.set_name(SID("canvas_idx")); + m_prx_buffer.set_name(SID("canvas_primitives")); + m_gpu_cmd_buffer.set_name(SID("canvas_cmds")); + + Engine* engine = Engine::instance(); + GfxDriver* driver = engine->gfx_driver(); + ShaderManager* shader_manager = engine->shader_manager(); + + m_params = driver->make_uniform_buffer(int(sizeof(ShaderCanvas::Params)), GfxMemUsage::GpuLocal, SID("canvas_params")); + + clear(); + } + + void Canvas::push_clip_rect(const Vec4f& clip_rect) { + m_clip_rect_stack.push_back(clip_rect); + + commit_draw_cmd(); + } + void Canvas::pop_clip_rect() { + m_clip_rect_stack.pop_back(); + + commit_draw_cmd(); + } + const Vec4f& Canvas::peek_clip_rect() { + return m_clip_rect_stack.back(); + } + + void Canvas::push_transform(const Vec2f& translate, float rotate_rad, const Vec2f& scale) { + push_transform(Math2d::translate_rotate_z(translate, rotate_rad) * Math2d::scale(scale)); + } + void Canvas::push_transform(const Vec2f& translate, float rotate_rad) { + push_transform(Math2d::translate_rotate_z(translate, rotate_rad)); + } + void Canvas::push_transform(const Transform2d& transform) { + push_transform(transform.get_transform()); + } + void Canvas::push_transform(const Mat3x3f& matr) { + const Mat3x3f prev = m_transform_stack.back(); + const Mat3x3f top = prev * matr; + m_transform_stack.push_back(top); + + commit_draw_cmd(); + } + void Canvas::pop_transform() { + m_transform_stack.pop_back(); + + commit_draw_cmd(); + } + const Mat3x3f& Canvas::peek_transform() { + return m_transform_stack.back(); + } + + void Canvas::add_line(const Vec2f& p1, const Vec2f& p2, const Color4f& color, float thickness) { + Vec2f points[] = {p1, p2}; + add_polyline(ArrayView(points, 2), color, thickness); + } + void Canvas::add_rect(const Vec2f& p_min, const Vec2f& p_max, const Color4f& color, float rounding, CanvasFlags flags, float thickness) { + if (!need_rounding(rounding, flags)) { + path_line_to(Vec2f(p_min.x(), p_min.y())); + path_line_to(Vec2f(p_min.x(), p_max.y())); + path_line_to(Vec2f(p_max.x(), p_max.y())); + path_line_to(Vec2f(p_max.x(), p_min.y())); + path_line_to(Vec2f(p_min.x(), p_min.y())); + path_stroke(color, thickness); + } else { + const bool rounding_all = flags.get(CanvasFlag::Rounded); + const float rounding_lu = rounding_all || flags.get(CanvasFlag::RoundedCornerLU) ? rounding : 0.0f; + const float rounding_ru = rounding_all || flags.get(CanvasFlag::RoundedCornerRU) ? rounding : 0.0f; + const float rounding_lb = rounding_all || flags.get(CanvasFlag::RoundedCornerLB) ? rounding : 0.0f; + const float rounding_rb = rounding_all || flags.get(CanvasFlag::RoundedCornerRB) ? rounding : 0.0f; + + path_arc_to(Vec2f(p_min.x() + rounding_lu, p_max.y() - rounding_lu), rounding_lu, Math::PIf, Math::HALF_PIf); + path_arc_to(Vec2f(p_max.x() - rounding_ru, p_max.y() - rounding_ru), rounding_ru, Math::HALF_PIf, 0); + path_arc_to(Vec2f(p_max.x() - rounding_lb, p_min.y() + rounding_lb), rounding_lb, 0, -Math::HALF_PIf); + path_arc_to(Vec2f(p_min.x() + rounding_rb, p_min.y() + rounding_rb), rounding_rb, -Math::HALF_PIf, Math::PIf); + path_stroke(color, thickness); + } + } + void Canvas::add_rect_filled(const Vec2f& p_min, const Vec2f& p_max, const Color4f& color, float rounding, CanvasFlags flags) { + if (!need_rounding(rounding, flags)) { + path_line_to(Vec2f(p_min.x(), p_min.y())); + path_line_to(Vec2f(p_min.x(), p_max.y())); + path_line_to(Vec2f(p_max.x(), p_max.y())); + path_line_to(Vec2f(p_max.x(), p_min.y())); + path_stroke_filled(color); + } else { + const bool rounding_all = flags.get(CanvasFlag::Rounded); + const float rounding_lu = rounding_all || flags.get(CanvasFlag::RoundedCornerLU) ? rounding : 0.0f; + const float rounding_ru = rounding_all || flags.get(CanvasFlag::RoundedCornerRU) ? rounding : 0.0f; + const float rounding_lb = rounding_all || flags.get(CanvasFlag::RoundedCornerLB) ? rounding : 0.0f; + const float rounding_rb = rounding_all || flags.get(CanvasFlag::RoundedCornerRB) ? rounding : 0.0f; + + path_arc_to(Vec2f(p_min.x() + rounding_lu, p_max.y() - rounding_lu), rounding_lu, Math::PIf, Math::HALF_PIf); + path_arc_to(Vec2f(p_max.x() - rounding_ru, p_max.y() - rounding_ru), rounding_ru, Math::HALF_PIf, 0); + path_arc_to(Vec2f(p_max.x() - rounding_lb, p_min.y() + rounding_lb), rounding_lb, 0, -Math::HALF_PIf); + path_arc_to(Vec2f(p_min.x() + rounding_rb, p_min.y() + rounding_rb), rounding_rb, -Math::HALF_PIf, Math::PIf); + path_stroke_filled(color); + } + } + void Canvas::add_triangle(const Vec2f& p1, const Vec2f& p2, const Vec2f& p3, const Color4f& color, float thickness) { + } + void Canvas::add_triangle_filled(const Vec2f& p1, const Vec2f& p2, const Vec2f& p3, const Color4f& color) { + } + void Canvas::add_polyline(const ArrayView& points, const Color4f& color, float thickness) { + set_texture(); + + assert(points.size() > 1); + const int n_lines = int(points.size()) - 1; + + reserve(n_lines * 4, n_lines * 2 * 3); + + for (int i = 0; i < n_lines; i++) { + const Vec2f& from = points[i]; + const Vec2f& to = points[i + 1]; + + const Vec2f dir = to - from; + const float angle = Math::atan2(dir.y(), dir.x()); + const float half_width = thickness * 0.5f; + + const Vec2f h = Vec2f(-Math::cos(angle), Math::sin(angle)); + + const int start = m_vxt_current; + + write_vtx(from + h * half_width, Vec2f(0, 0), color); + write_vtx(from + h * (-half_width), Vec2f(0, 0), color); + write_vtx(to + h * half_width, Vec2f(0, 0), color); + write_vtx(to + h * (-half_width), Vec2f(0, 0), color); + + write_idx(start + 0, start + 1, start + 3); + write_idx(start + 3, start + 2, start + 0); + } + } + void Canvas::add_polygone(const ArrayView& points, const Color4f& color) { + set_texture(); + + assert(points.size() >= 3); + + const Vec2f& pivot = points[0]; + const int n_vtx = int(points.size()); + const int n_tri = n_vtx - 2; + + reserve(n_vtx, n_tri * 3); + + const int start = m_vxt_current; + + for (int i = 0; i < n_vtx; i++) { + write_vtx(points[i], Vec2f(0, 0), color); + } + + for (int i = 0; i < n_tri; i++) { + write_idx(start + 0, start + i + 1, start + i + 2); + } + } + void Canvas::add_text(const std::string& text, const Ref& font, float font_size, const Vec2f& p, const Color4f& color) { + assert(font); + + if (text.empty()) { return; } + + set_texture(font->get_texture()); + + const int n = int(text.size()); + const float scale = font_size > 0 ? font_size / float(font->get_height()) : 1.0f; + const auto& glyphs = font->get_glyphs(); + const auto null_glyph = glyphs.find(0)->second; + + float advance_x = 0.0f; + + for (int i = 0; i < n; ++i) { + auto c = text[i]; + auto query = glyphs.find(int(c)); + + FontGlyph font_glyph = null_glyph; + if (query != glyphs.end()) font_glyph = query->second; + + float left = advance_x + scale * float(font_glyph.bearing.x()); + float top = scale * float(font_glyph.bearing.y()); + float right = left + scale * float(font_glyph.size.x()); + float bottom = top - scale * float(font_glyph.size.y()); + + reserve(4, 6); + + const int start = m_vxt_current; + + write_vtx(p + Vec2f(left, top), font_glyph.bitmap_uv0, color); + write_vtx(p + Vec2f(left, bottom), Vec2f(font_glyph.bitmap_uv0.x(), font_glyph.bitmap_uv1.y()), color); + write_vtx(p + Vec2f(right, bottom), font_glyph.bitmap_uv1, color); + write_vtx(p + Vec2f(right, top), Vec2f(font_glyph.bitmap_uv1.x(), font_glyph.bitmap_uv0.y()), color); + + write_idx(start + 0, start + 1, start + 2); + write_idx(start + 2, start + 3, start + 0); + + advance_x += scale * float(font_glyph.advance.x()); + } + } + void Canvas::add_image(const Ref& image, const Vec2f& p_min, const Vec2f& p_max, const Vec2f& uv_min, const Vec2f& uv_max, const Color4f& color) { + set_texture(image); + + Vec2f points[4]; + points[0] = Vec2f(p_min.x(), p_min.y()); + points[1] = Vec2f(p_min.x(), p_max.y()); + points[2] = Vec2f(p_max.x(), p_max.y()); + points[3] = Vec2f(p_max.x(), p_min.y()); + + Vec2f uvs[4]; + uvs[0] = Vec2f(uv_min.x(), uv_min.y()); + uvs[1] = Vec2f(uv_min.x(), uv_max.y()); + uvs[2] = Vec2f(uv_max.x(), uv_max.y()); + uvs[3] = Vec2f(uv_max.x(), uv_min.y()); + + reserve(4, 6); + + const int start = m_idx_current; + + for (int i = 0; i < 4; i++) { + write_vtx(points[i], uvs[i], color); + } + + write_idx(start + 0, start + 1, start + 2); + write_idx(start + 2, start + 3, start + 0); + } + + void Canvas::path_line_to(const Vec2f& p) { + m_path.push_back(p); + } + void Canvas::path_arc_to(const Vec2f& p, float r, float start_rad, float end_rad, int num_segments) { + assert(num_segments >= 0); + + if (r == 0.0f) { + path_line_to(p); + return; + } + + const float angle = end_rad - start_rad; + const int n_seg = tessellate(angle, num_segments); + const int n_vtx = n_seg + 1; + + const float angle_diff = angle / float(n_seg); + float angle_curr = start_rad; + + for (int i = 1; i < n_vtx; i++) { + path_line_to(Vec2f(p.x() + r * Math::cos(angle_curr), p.y() + r * Math::sin(angle_curr))); + angle_curr += angle_diff; + } + } + void Canvas::path_stroke(const Color4f& color, float thickness) { + add_polyline(ArrayView(m_path.data(), int(m_path.size())), color, thickness); + path_clear(); + } + void Canvas::path_stroke_filled(const Color4f& color) { + add_polygone(ArrayView(m_path.data(), int(m_path.size())), color); + path_clear(); + } + void Canvas::path_clear() { + m_path.clear(); + } + + void Canvas::clear(bool clear_shared_data) { + if (clear_shared_data) { + m_shared->clear(); + } + + m_cmd_buffer.clear(); + m_vtx_buffer.clear(); + m_idx_buffer.clear(); + m_prx_buffer.clear(); + m_clip_rect_stack.clear(); + m_transform_stack.clear(); + + m_vxt_current = 0; + m_idx_current = 0; + + m_path.clear(); + m_clip_rect_stack.push_back(Vec4f(-20000.0f, -20000.0f, 20000.0f, 20000.0f)); + m_transform_stack.push_back(Math2d::identity3x3()); + + commit_draw_cmd(); + } + + void Canvas::compile(bool compile_shared_data) { + WG_AUTO_PROFILE_RENDER("Canvas::compile"); + + Engine* engine = Engine::instance(); + GfxCtx* gfx_ctx = engine->gfx_ctx(); + GfxDriver* gfx_drvier = engine->gfx_driver(); + + m_gpu_cmd_buffer.resize(m_cmd_buffer.size()); + + for (int i = 0; i < int(m_cmd_buffer.size()); i++) { + const CanvasDrawCmd& src_cmd = m_cmd_buffer[i]; + GPUCanvasDrawCmd& dst_cmd = m_gpu_cmd_buffer[i]; + + const Mat3x3f& t = src_cmd.transform; + + dst_cmd.ClipRect = src_cmd.clip_rect; + dst_cmd.TextureIdx = src_cmd.texture_idx; + dst_cmd.Transform0 = Vec4f(t.col(0), 0.0f); + dst_cmd.Transform1 = Vec4f(t.col(1), 0.0f); + dst_cmd.Transform2 = Vec4f(t.col(2), 0.0f); + } + + m_gpu_cmd_buffer.flush(gfx_ctx); + m_vtx_buffer.flush(gfx_ctx); + m_idx_buffer.flush(gfx_ctx); + m_prx_buffer.flush(gfx_ctx); + + GfxDescSetResources resources; + { + { + auto& resource = resources.emplace_back(); + auto& point = resource.first; + point.type = GfxBindingType::UniformBuffer; + point.binding = ShaderCanvas::PARAMS_SLOT; + auto& value = resource.second; + value.resource = m_params.as(); + value.offset = 0; + value.range = m_params->size(); + } + { + auto& resource = resources.emplace_back(); + auto& point = resource.first; + point.type = GfxBindingType::StorageBuffer; + point.binding = ShaderCanvas::DRAWCMDSDATA_SLOT; + auto& value = resource.second; + value.resource = m_gpu_cmd_buffer.get_buffer().as(); + value.offset = 0; + value.range = m_gpu_cmd_buffer.get_buffer()->size(); + } + } + m_params_set = gfx_drvier->make_desc_set(resources, SID("canvas_params")); + + if (compile_shared_data) { + m_shared->compile(); + } + } + + void Canvas::render(const Ref& window, const Rect2i& viewport, const Vec4f& area, float gamma) { + WG_AUTO_PROFILE_RENDER("Canvas::render"); + + if (m_cmd_buffer.empty() || (m_cmd_buffer.size() == 1 && m_cmd_buffer[0].elements == 0)) { + return; + } + + Engine* engine = Engine::instance(); + GfxCtx* gfx_ctx = engine->gfx_ctx(); + GfxDriver* gfx_drvier = engine->gfx_driver(); + + ShaderCanvas::Params& params = *((ShaderCanvas::Params*) gfx_ctx->map_uniform_buffer(m_params)); + { + params.ClipProjView = (gfx_drvier->clip_matrix() * Math3d::orthographic(area.x(), area.z(), area.y(), area.w(), -1.0f, 1.0f)).transpose(); + params.InverseGamma = 1.0f / gamma; + } + gfx_ctx->unmap_uniform_buffer(m_params); + + gfx_ctx->execute([&](GfxCtx* thread_ctx) { + thread_ctx->begin_render_pass({}, SID("Canvas::render")); + thread_ctx->bind_target(window); + thread_ctx->viewport(viewport); + + if (thread_ctx->bind_pipeline(m_shared->pipeline_srgb)) { + thread_ctx->bind_desc_set(m_params_set, ShaderCanvas::PARAMS_SET); + + const int num_cmds = int(m_gpu_cmd_buffer.get_size()); + for (int cmd_id = 0; cmd_id < num_cmds; cmd_id++) { + const CanvasDrawCmd& cmd = m_cmd_buffer[cmd_id]; + + if (cmd.elements > 0) { + const int tex_set_idx = cmd.texture_idx >= 0 ? cmd.texture_idx / MAX_CANVAS_IMAGES : 0; + + thread_ctx->bind_desc_set(m_shared->tex_sets[tex_set_idx], ShaderCanvas::CANVASIMAGE0_SET); + thread_ctx->bind_vert_buffer(m_vtx_buffer.get_buffer(), 0); + thread_ctx->bind_vert_buffer(m_prx_buffer.get_buffer(), 1, int(cmd_id * sizeof(int))); + thread_ctx->bind_index_buffer(m_idx_buffer.get_buffer(), GfxIndexType::Uint32, int(cmd.idx_offset * sizeof(std::uint32_t))); + thread_ctx->draw_indexed(cmd.elements * 3, 0, 1); + } + } + } + + thread_ctx->end_render_pass(); + }); + } + + void Canvas::set_texture() { + const int texture_idx = -1; + + CanvasDrawCmd& cmd = m_cmd_buffer.back(); + if (cmd.texture_idx != texture_idx) { + commit_draw_cmd(); + m_cmd_buffer.back().texture_idx = texture_idx; + } + } + void Canvas::set_texture(const Ref& tex) { + assert(tex); + + int texture_idx = -1; + + auto it = m_shared->tex_map.find(tex); + if (it != m_shared->tex_map.end()) { + texture_idx = it->second; + } else { + texture_idx = int(m_shared->tex_buffer.size()); + m_shared->tex_buffer.push_back(tex); + m_shared->tex_map[tex] = texture_idx; + } + + CanvasDrawCmd& cmd = m_cmd_buffer.back(); + if (cmd.texture_idx != texture_idx) { + commit_draw_cmd(); + m_cmd_buffer.back().texture_idx = texture_idx; + } + } + void Canvas::commit_draw_cmd() { + if (m_cmd_buffer.empty() || m_cmd_buffer.back().elements != 0) { + m_prx_buffer.push_back(int(m_cmd_buffer.size())); + m_cmd_buffer.emplace_back(); + } + + const int cmd_idx = int(m_cmd_buffer.size()) - 1; + + CanvasDrawCmd& cmd = m_cmd_buffer.back(); + cmd.idx_offset = m_idx_current; + cmd.vtx_offset = m_vxt_current; + cmd.clip_rect = m_clip_rect_stack.back(); + cmd.transform = m_transform_stack.back(); + } + void Canvas::reserve(int num_vtx, int num_idx) { + assert(num_vtx >= 0); + assert(num_idx >= 0); + + m_vtx_buffer.resize(m_vtx_buffer.get_size() + num_vtx); + m_idx_buffer.resize(m_idx_buffer.get_size() + num_idx); + } + void Canvas::write_vtx(const Vec2f& pos, const Vec2f& uv, const Vec4f& color) { + CanvasVert vert; + vert.pos = pos; + vert.uv = uv; + vert.color = color; + m_vtx_buffer[m_vxt_current++] = vert; + } + void Canvas::write_idx(int i1, int i2, int i3) { + m_cmd_buffer.back().elements += 1; + m_idx_buffer[m_idx_current++] = std::uint32_t(i1); + m_idx_buffer[m_idx_current++] = std::uint32_t(i2); + m_idx_buffer[m_idx_current++] = std::uint32_t(i3); + } + int Canvas::tessellate(float angle, int num_segments) { + if (num_segments == 0) { + num_segments = int(Math::ceil(Math::abs(angle) / Math::PIf * float(NUM_SEGMENTS_PER_PI))); + } + return Math::max(num_segments, 1); + } + + bool Canvas::need_rounding(float rounding, CanvasFlags flags) { + CanvasFlags rounding_mask = { + CanvasFlag::Rounded, + CanvasFlag::RoundedCornerLU, + CanvasFlag::RoundedCornerRU, + CanvasFlag::RoundedCornerLB, + CanvasFlag::RoundedCornerRB, + }; + + return rounding > 0.5f && (rounding_mask.bits & flags.bits).any(); + } + +}// namespace wmoge \ No newline at end of file diff --git a/engine/render/canvas.hpp b/engine/render/canvas.hpp new file mode 100644 index 000000000..1b53fac2d --- /dev/null +++ b/engine/render/canvas.hpp @@ -0,0 +1,198 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +#ifndef WMOGE_CANVAS_HPP +#define WMOGE_CANVAS_HPP + +#include "core/array_view.hpp" +#include "core/fast_map.hpp" +#include "core/fast_vector.hpp" +#include "core/mask.hpp" +#include "gfx/gfx_buffers.hpp" +#include "gfx/gfx_desc_set.hpp" +#include "gfx/gfx_pipeline.hpp" +#include "gfx/gfx_vector.hpp" +#include "math/color.hpp" +#include "math/mat.hpp" +#include "math/math_utils.hpp" +#include "math/math_utils2d.hpp" +#include "math/transform.hpp" +#include "math/vec.hpp" +#include "resource/font.hpp" +#include "resource/texture.hpp" + +#include "shaders/generated/auto_canvas_reflection.hpp" + +#include +#include +#include +#include + +namespace wmoge { + + /** + * @brief Canvas drawing primitive flags + */ + enum class CanvasFlag { + None = 0,//< Default + Rounded = 1,//< All sides rounded + RoundedCornerLU = 2,//< Round left upper corner + RoundedCornerRU = 3,//< Round right upper corner + RoundedCornerLB = 4,//< Round left bottom corner + RoundedCornerRB = 5,//< Round right bottom corner + }; + + /** + * @brief Canvas flags set + */ + using CanvasFlags = Mask; + + /** + * @class CanvasVert + * @brief Canvas vert attributes for drawing on gpu + */ + struct CanvasVert { + Vec2f pos; + Vec4f color; + Vec2f uv; + }; + + /** + * @class CanvasDrawCmd + * @brief Canvas single draw cmd to dispatch gfx draw call + */ + struct CanvasDrawCmd { + Mat3x3f transform; + Vec4f clip_rect; + int texture_idx = -1; + int vtx_offset = 0; + int idx_offset = 0; + int elements = 0; + }; + + /** + * @class CanvasSharedData + * @brief Shared data for canvas primitives rendering + */ + struct CanvasSharedData { + static constexpr int MAX_CANVAS_IMAGES = int(ShaderCanvas::MAX_CANVAS_IMAGES); + + CanvasSharedData(); + CanvasSharedData(const CanvasSharedData&) = delete; + CanvasSharedData(CanvasSharedData&&) = delete; + ~CanvasSharedData() = default; + + void compile(); + void clear(); + + std::vector> tex_buffer; //< Texures referenced in cmds, store separately to pack batched into descriptor sets + fast_map, int> tex_map; //< Map used textures to ids (to batch used textures together) + fast_vector> tex_sets; //< Descriptor sets with textures to bind + Ref pipeline_srgb; //< Cached pso to draw all primitives + Ref pipeline_linear;//< Cached pso to draw all primitives + }; + + /** + * @brief Canvas struct to pack draw cmd data for gpu + */ + using GPUCanvasDrawCmd = ShaderCanvas::DrawCmdData; + + /** + * @class Canvas + * @brief Low-level primitives for 2d drawing using lines, polygones, text and images + */ + class Canvas { + public: + static constexpr int INLINE_STACK_SIZE = 16; + static constexpr int NUM_SEGMENTS_PER_PI = 32; + static constexpr int MAX_CANVAS_IMAGES = int(ShaderCanvas::MAX_CANVAS_IMAGES); + + Canvas(); + Canvas(std::shared_ptr shared); + Canvas(const Canvas&) = delete; + Canvas(Canvas&&) = delete; + ~Canvas() = default; + + void push_clip_rect(const Vec4f& clip_rect); + void pop_clip_rect(); + const Vec4f& peek_clip_rect(); + void push_transform(const Vec2f& translate, float rotate_rad, const Vec2f& scale); + void push_transform(const Vec2f& translate, float rotate_rad); + void push_transform(const Transform2d& transform); + void push_transform(const Mat3x3f& matr); + void pop_transform(); + const Mat3x3f& peek_transform(); + void add_line(const Vec2f& p1, const Vec2f& p2, const Color4f& color, float thickness = 1.0f); + void add_rect(const Vec2f& p_min, const Vec2f& p_max, const Color4f& color, float rounding = 0.0f, CanvasFlags flags = {}, float thickness = 1.0f); + void add_rect_filled(const Vec2f& p_min, const Vec2f& p_max, const Color4f& color, float rounding = 0.0f, CanvasFlags flags = {}); + void add_triangle(const Vec2f& p1, const Vec2f& p2, const Vec2f& p3, const Color4f& color, float thickness = 1.0f); + void add_triangle_filled(const Vec2f& p1, const Vec2f& p2, const Vec2f& p3, const Color4f& color); + void add_polyline(const ArrayView& points, const Color4f& color, float thickness = 1.0f); + void add_polygone(const ArrayView& points, const Color4f& color); + void add_text(const std::string& text, const Ref& font, float font_size, const Vec2f& p, const Color4f& color); + void add_image(const Ref& image, const Vec2f& p_min, const Vec2f& p_max, const Vec2f& uv_min, const Vec2f& uv_max, const Color4f& color); + void path_line_to(const Vec2f& p); + void path_arc_to(const Vec2f& p, float r, float start_rad, float end_rad, int num_segments = 0); + void path_stroke(const Color4f& color, float thickness); + void path_stroke_filled(const Color4f& color); + void path_clear(); + + void clear(bool clear_shared_data = false); + void compile(bool compile_shared_data = false); + void render(const Ref& window, const Rect2i& viewport, const Vec4f& area, float gamma); + + private: + void set_texture(); + void set_texture(const Ref& tex); + void commit_draw_cmd(); + void reserve(int num_vtx, int num_idx); + void write_vtx(const Vec2f& pos, const Vec2f& uv, const Vec4f& color); + void write_idx(int i1, int i2, int i3); + int tessellate(float angle, int num_segments); + bool need_rounding(float rounding, CanvasFlags flags); + + private: + std::vector m_cmd_buffer;//< Cmds to draw, map to 1 draw call to Gfx driver + GfxVector m_vtx_buffer;//< Gpu vertex data for drawing + GfxVector m_idx_buffer;//< Gpu index data for drawing + GfxVector m_prx_buffer;//< Gpu per-instance cmd id buffer to fetch cmd data for drawing + + int m_vxt_current = 0;//< Current vertex to write + int m_idx_current = 0;//< Current index to write + + std::vector m_path; //< Internal tmp buffer to draw path + std::shared_ptr m_shared; //< Shared state amond all canvas classes for cmds rendering + fast_vector m_clip_rect_stack;//< Context stack + fast_vector m_transform_stack;//< Context stack + GfxVector m_gpu_cmd_buffer; //< Packed cmd data for gpu + Ref m_params; //< Cached ubo to fill with const params + Ref m_params_set; //< Cached ubo to fill with const params and draw cmds buffer + }; + +}// namespace wmoge + +#endif//WMOGE_CANVAS_HPP \ No newline at end of file diff --git a/engine/render/render_camera.cpp b/engine/render/render_camera.cpp index 918669a8c..97e2e692c 100644 --- a/engine/render/render_camera.cpp +++ b/engine/render/render_camera.cpp @@ -93,18 +93,11 @@ namespace wmoge { data.up_prev = camera.get_up(); if (camera_prev.has_value()) { - data.proj_prev = camera_prev->get_proj(); - data.view_prev = camera_prev->get_view(); - data.proj_view_prev = camera_prev->get_proj_view(); - data.direction_prev = camera_prev->get_direction(); - data.position_prev = camera_prev->get_position(); - data.up_prev = camera_prev->get_up(); - data.movement = data.position - data.position_prev; + set_prev_params(index, *camera_prev); } if (type == CameraType::Color) { data.pass_relevance.set(MeshPassType::Background); - data.pass_relevance.set(MeshPassType::Shadow); data.pass_relevance.set(MeshPassType::GBuffer); data.pass_relevance.set(MeshPassType::Forward); data.pass_relevance.set(MeshPassType::Pfx); @@ -119,6 +112,18 @@ namespace wmoge { return index; } + void RenderCameras::set_prev_params(int index, const RenderCamera& camera_prev) { + RenderCameraData& data = m_cameras[index]; + + data.proj_prev = camera_prev.get_proj(); + data.view_prev = camera_prev.get_view(); + data.proj_view_prev = camera_prev.get_proj_view(); + data.direction_prev = camera_prev.get_direction(); + data.position_prev = camera_prev.get_position(); + data.up_prev = camera_prev.get_up(); + data.movement = data.position - data.position_prev; + } + const RenderCamera& RenderCameras::camera_at(int index) const { return m_cameras[index].camera; } diff --git a/engine/render/render_camera.hpp b/engine/render/render_camera.hpp index 83bf69c77..848b91f55 100644 --- a/engine/render/render_camera.hpp +++ b/engine/render/render_camera.hpp @@ -125,6 +125,7 @@ namespace wmoge { class RenderCameras final { public: int add_camera(CameraType type, const RenderCamera& camera, std::optional camera_prev); + void set_prev_params(int index, const RenderCamera& camera_prev); const RenderCamera& camera_at(int index) const; const RenderCameraData& data_at(int index) const; const RenderCameraData& camera_main() const; diff --git a/engine/render/render_engine.cpp b/engine/render/render_engine.cpp index a0ff98979..c5a31161f 100644 --- a/engine/render/render_engine.cpp +++ b/engine/render/render_engine.cpp @@ -61,6 +61,9 @@ namespace wmoge { void RenderEngine::set_scene(RenderScene* scene) { m_scene = scene; } + void RenderEngine::set_visiblity(VisibilitySystem* visibility) { + m_visibility = visibility; + } void RenderEngine::begin_rendering() { WG_AUTO_PROFILE_RENDER("RenderEngine::begin_rendering"); @@ -184,17 +187,22 @@ namespace wmoge { void RenderEngine::collect_batches() { WG_AUTO_PROFILE_RENDER("RenderEngine::collect_batches"); - ArrayView objects = m_scene->get_objects(); - ArrayView vis = m_scene->get_objects_vis(); - GPURenderObjectDataVector& data = m_scene->get_objects_gpu_data(); + ArrayView objects = m_scene->get_objects(); + ArrayView vis = m_scene->get_objects_vis(); + GPURenderObjectDataVector& data = m_scene->get_objects_gpu_data(); std::atomic_int total{0}; TaskParallelFor task_compile(SID("collect_batches"), [&](TaskContext&, int id, int) { - const RenderCameraMask cam_mask = vis[id]; + if (!objects[id]) { + return 0; + } + + const VisibilityItem vis_item = vis[id]; + const VisibilityItemResult vis_result = m_visibility->get_item_result(vis_item); - if (cam_mask.any()) { - objects[id]->collect(m_cameras, cam_mask, m_batch_collector); + if (vis_result.cam_mask.any()) { + objects[id]->collect(m_cameras, vis_result.cam_mask, m_batch_collector); total.fetch_add(1, std::memory_order_relaxed); } @@ -278,6 +286,17 @@ namespace wmoge { m_scene->flush_buffers(Engine::instance()->gfx_ctx()); } + void RenderEngine::render_canvas(Canvas& canvas, const Vec4f& area) { + WG_AUTO_PROFILE_RENDER("RenderEngine::render_canvas"); + + if (m_cameras.is_empty()) { + return; + } + + const RenderCameraData& main_cam = m_cameras.camera_main(); + canvas.render(m_main_target, main_cam.viewport, area, 2.2f); + } + void RenderEngine::render_aux_geom(AuxDrawManager& aux_draw_manager) { WG_AUTO_PROFILE_RENDER("RenderEngine::render_aux_geom"); diff --git a/engine/render/render_engine.hpp b/engine/render/render_engine.hpp index d440f408c..21d2cd926 100644 --- a/engine/render/render_engine.hpp +++ b/engine/render/render_engine.hpp @@ -39,6 +39,7 @@ #include "mesh/mesh_pass.hpp" #include "platform/window.hpp" #include "render/aux_draw_manager.hpp" +#include "render/canvas.hpp" #include "render/render_camera.hpp" #include "render/render_defs.hpp" #include "render/render_object.hpp" @@ -90,6 +91,7 @@ namespace wmoge { void set_target(const Ref& window); void set_clear_color(const Color4f& color); void set_scene(RenderScene* scene); + void set_visiblity(VisibilitySystem* visibility); void begin_rendering(); void end_rendering(); @@ -102,6 +104,7 @@ namespace wmoge { void sort_queues(); void merge_cmds(); void flush_buffers(); + void render_canvas(Canvas& canvas, const Vec4f& area); void render_aux_geom(AuxDrawManager& aux_draw_manager); [[nodiscard]] RenderCameras& get_cameras() { return m_cameras; } @@ -130,7 +133,8 @@ namespace wmoge { Ref m_main_target; Ref m_frame_data; std::optional m_camera_prev; - RenderScene* m_scene = nullptr; + RenderScene* m_scene = nullptr; + VisibilitySystem* m_visibility = nullptr; float m_time = 0.0f; float m_delta_time = 0.0f; diff --git a/engine/render/render_scene.cpp b/engine/render/render_scene.cpp index 071ac7dab..dd14f1725 100644 --- a/engine/render/render_scene.cpp +++ b/engine/render/render_scene.cpp @@ -40,7 +40,7 @@ namespace wmoge { m_objects_ids.set_name(SID("objects_ids")); } - void RenderScene::add_object(RenderObject* object) { + void RenderScene::add_object(RenderObject* object, VisibilityItem vis_item) { assert(object); if (m_free_objects_ids.empty()) { @@ -60,7 +60,7 @@ namespace wmoge { m_free_objects_ids.pop_back(); m_objects[new_id] = object; - m_objects_vis[new_id] = RenderCameraMask(); + m_objects_vis[new_id] = vis_item; m_objects_gpu_data[new_id] = GPURenderObjectData(); object->set_primitive_id(new_id); @@ -73,7 +73,7 @@ namespace wmoge { m_free_objects_ids.push_back(id); m_objects[id] = nullptr; - m_objects_vis[id] = RenderCameraMask(); + m_objects_vis[id] = VisibilityItem(); m_objects_gpu_data[id] = GPURenderObjectData(); } diff --git a/engine/render/render_scene.hpp b/engine/render/render_scene.hpp index 1a935b064..6acb6cec6 100644 --- a/engine/render/render_scene.hpp +++ b/engine/render/render_scene.hpp @@ -34,6 +34,7 @@ #include "mesh/mesh_bucket.hpp" #include "mesh/mesh_pass.hpp" #include "render/render_defs.hpp" +#include "render/visibility.hpp" #include "shaders/generated/auto_material_reflection.hpp" @@ -71,7 +72,7 @@ namespace wmoge { public: RenderScene(); - void add_object(class RenderObject* object); + void add_object(class RenderObject* object, VisibilityItem vis_item); void remove_object(class RenderObject* object); void flush_buffers(class GfxCtx* gfx_ctx); @@ -79,14 +80,14 @@ namespace wmoge { [[nodiscard]] GPURenderObjectDataVector& get_objects_gpu_data() { return m_objects_gpu_data; } [[nodiscard]] GPURenderObjectIdVector& get_objects_ids() { return m_objects_ids; } [[nodiscard]] ArrayView get_objects() { return m_objects; } - [[nodiscard]] ArrayView get_objects_vis() { return m_objects_vis; } + [[nodiscard]] ArrayView get_objects_vis() { return m_objects_vis; } private: MeshBucketMap m_bucket_map[MESH_PASSES_TOTAL];//< Bucket slot map per pass type for dynamic instancing GPURenderObjectIdVector m_objects_ids; //< Remap ids to render data GPURenderObjectDataVector m_objects_gpu_data; //< Scene render objects gpu data (to fetch in shader by id) std::vector m_objects; //< Renderable scene objects - std::vector m_objects_vis; //< Renderable scene objects visibility mask + std::vector m_objects_vis; //< Renderable scene objects visibility items std::vector m_free_objects_ids; //< Pool with free ids }; diff --git a/engine/render/shader_manager.cpp b/engine/render/shader_manager.cpp index 37cd08f62..233f4a698 100644 --- a/engine/render/shader_manager.cpp +++ b/engine/render/shader_manager.cpp @@ -41,8 +41,8 @@ #include "resource/shader.hpp" // built-in passes -#include "shaders/generated/auto_aux_draw_canvas_pass.hpp" #include "shaders/generated/auto_base_pass.hpp" +#include "shaders/generated/auto_canvas_pass.hpp" #include "shaders/generated/auto_material_pass.hpp" #include "shaders/generated/auto_text_pass.hpp" @@ -353,7 +353,7 @@ namespace wmoge { // register engine shader passes here register_pass(std::make_unique()); register_pass(std::make_unique()); - register_pass(std::make_unique()); + register_pass(std::make_unique()); register_pass(std::make_unique()); } void ShaderManager::load_sources_from_disk() { diff --git a/engine/render/texture_manager.cpp b/engine/render/texture_manager.cpp index b69da4dc0..f3d2cba2c 100644 --- a/engine/render/texture_manager.cpp +++ b/engine/render/texture_manager.cpp @@ -26,3 +26,33 @@ /**********************************************************************************/ #include "texture_manager.hpp" + +#include "core/engine.hpp" +#include "debug/profiler.hpp" +#include "gfx/gfx_ctx.hpp" +#include "gfx/gfx_driver.hpp" + +namespace wmoge { + + TextureManager::TextureManager() { + WG_AUTO_PROFILE_RENDER("TextureManager::TextureManager"); + + Engine* engine = Engine::instance(); + m_gfx_driver = engine->gfx_driver(); + m_gfx_ctx = engine->gfx_ctx(); + + unsigned char white[] = {0xff, 0xff, 0xff, 0xff}; + unsigned char black[] = {0x00, 0x00, 0x00, 0xff}; + unsigned char red[] = {0xff, 0x00, 0x00, 0xff}; + + m_gfx_default_sampler = m_gfx_driver->make_sampler(GfxSamplerDesc{}, SID("default")); + m_gfx_default_texture_white = m_gfx_driver->make_texture_2d(1, 1, 1, GfxFormat::RGBA8, {GfxTexUsageFlag::Sampling}, GfxMemUsage::GpuLocal, GfxTexSwizz::None, SID("default_1x1_white")); + m_gfx_default_texture_black = m_gfx_driver->make_texture_2d(1, 1, 1, GfxFormat::RGBA8, {GfxTexUsageFlag::Sampling}, GfxMemUsage::GpuLocal, GfxTexSwizz::None, SID("default_1x1_black")); + m_gfx_default_texture_red = m_gfx_driver->make_texture_2d(1, 1, 1, GfxFormat::RGBA8, {GfxTexUsageFlag::Sampling}, GfxMemUsage::GpuLocal, GfxTexSwizz::None, SID("default_1x1_red")); + + m_gfx_ctx->update_texture_2d(m_gfx_default_texture_white, 0, Rect2i(0, 0, 1, 1), make_ref(white, sizeof(white))); + m_gfx_ctx->update_texture_2d(m_gfx_default_texture_black, 0, Rect2i(0, 0, 1, 1), make_ref(black, sizeof(black))); + m_gfx_ctx->update_texture_2d(m_gfx_default_texture_red, 0, Rect2i(0, 0, 1, 1), make_ref(red, sizeof(red))); + } + +}// namespace wmoge diff --git a/engine/render/texture_manager.hpp b/engine/render/texture_manager.hpp index 32f975c5f..57efd9212 100644 --- a/engine/render/texture_manager.hpp +++ b/engine/render/texture_manager.hpp @@ -28,13 +28,32 @@ #ifndef WMOGE_TEXTURE_MANAGER_HPP #define WMOGE_TEXTURE_MANAGER_HPP +#include "gfx/gfx_sampler.hpp" +#include "gfx/gfx_texture.hpp" + namespace wmoge { /** * @class TextureManager * @brief Manages allocation and streaming of all engine textures */ - class TextureManager { + class TextureManager final { + public: + TextureManager(); + + [[nodiscard]] const Ref& get_gfx_default_texture_white() const { return m_gfx_default_texture_white; } + [[nodiscard]] const Ref& get_gfx_default_texture_black() const { return m_gfx_default_texture_black; } + [[nodiscard]] const Ref& get_gfx_default_texture_red() const { return m_gfx_default_texture_red; } + [[nodiscard]] const Ref& get_gfx_default_sampler() const { return m_gfx_default_sampler; } + + private: + Ref m_gfx_default_texture_white; + Ref m_gfx_default_texture_black; + Ref m_gfx_default_texture_red; + Ref m_gfx_default_sampler; + + class GfxDriver* m_gfx_driver; + class GfxCtx* m_gfx_ctx; }; }// namespace wmoge diff --git a/engine/render/vertex_factory.cpp b/engine/render/vertex_factory.cpp index e85c9df05..a5ef70f9b 100644 --- a/engine/render/vertex_factory.cpp +++ b/engine/render/vertex_factory.cpp @@ -52,7 +52,7 @@ namespace wmoge { void VertexFactory::cache_vert_format(class GfxDriver* driver, const GfxVertElements& elements, VertexInputType input_type) { const int idx = int(input_type); const StringId debug_name = SID(get_friendly_name() + " " + Enum::to_str(input_type)); - m_gfx_formats[idx] = driver->vert_fmt_cache()->get_or_create(elements, debug_name); + m_gfx_formats[idx] = driver->make_vert_format(elements, debug_name); } const VertexFactoryType& VertexFactory::get_type_info() const { diff --git a/engine/render/visibility.cpp b/engine/render/visibility.cpp index ebd63f4e4..8d08f741a 100644 --- a/engine/render/visibility.cpp +++ b/engine/render/visibility.cpp @@ -38,8 +38,6 @@ namespace wmoge { VisibilityItem VisibilitySystem::alloc_item() { - std::unique_lock guard(m_mutex); - if (m_free.empty()) { const int curr_capacity = int(m_items.size()); const int new_capacity = curr_capacity + ALLOC_BATCH_SIZE; @@ -57,51 +55,45 @@ namespace wmoge { VisibilityItem new_item = m_free.back(); m_free.pop_back(); - m_items[new_item] = VisibilityItemData(); - m_result[new_item] = VisibilityItemResult(); + m_items[new_item.id] = VisibilityItemData(); + m_result[new_item.id] = VisibilityItemResult(); - m_items[new_item].id = new_item; + m_items[new_item.id].id = new_item; return new_item; } void VisibilitySystem::release_item(VisibilityItem item) { - std::unique_lock guard(m_mutex); + assert(item.is_valid()); - m_items[item] = VisibilityItemData(); - m_result[item] = VisibilityItemResult(); + m_items[item.id] = VisibilityItemData(); + m_result[item.id] = VisibilityItemResult(); m_free.push_back(item); } void VisibilitySystem::update_item_min_dist(const VisibilityItem& item, float min_dist) { - std::shared_lock guard(m_mutex); - - assert(item != VIS_ITEM_INVALID); + assert(item.is_valid()); - m_items[item].min_dist_2 = min_dist * min_dist; + m_items[item.id].min_dist_2 = min_dist * min_dist; } void VisibilitySystem::update_item_max_dist(const VisibilityItem& item, float max_dist) { - std::shared_lock guard(m_mutex); + assert(item.is_valid()); - assert(item != VIS_ITEM_INVALID); - - m_items[item].max_dist_2 = max_dist * max_dist; + m_items[item.id].max_dist_2 = max_dist * max_dist; } void VisibilitySystem::update_item_bbox(const VisibilityItem& item, const Aabbf& aabbf) { - std::shared_lock guard(m_mutex); - - assert(item != VIS_ITEM_INVALID); + assert(item.is_valid()); - m_items[item].aabb = aabbf; + m_items[item.id].aabb = aabbf; } VisibilityItemResult VisibilitySystem::get_item_result(const VisibilityItem& item) { - assert(item != VIS_ITEM_INVALID); + assert(item.is_valid()); - return m_result[item]; + return m_result[item.id]; } void VisibilitySystem::cull(const RenderCameras& cameras) { diff --git a/engine/render/visibility.hpp b/engine/render/visibility.hpp index 1e410bf38..2da17aead 100644 --- a/engine/render/visibility.hpp +++ b/engine/render/visibility.hpp @@ -30,7 +30,7 @@ #include "core/array_view.hpp" #include "core/string_id.hpp" -#include "core/synchronization.hpp" +#include "core/string_utils.hpp" #include "core/unrolled_list.hpp" #include "math/aabb.hpp" #include "math/frustum.hpp" @@ -42,11 +42,26 @@ namespace wmoge { - /** @brief Id of the item to reference in visibility system */ - using VisibilityItem = int; + /** + * @class + * @brief Id of the item to reference in visibility system + */ + struct VisibilityItem { + VisibilityItem() = default; + VisibilityItem(int id) : id(id) {} + + bool operator==(const VisibilityItem& other) const { return id == other.id; } + bool operator!=(const VisibilityItem& other) const { return id != other.id; } + + bool is_valid() const { return id != -1; } - /** @brief Id of invalid item */ - static constexpr VisibilityItem VIS_ITEM_INVALID = -1; + operator int() const { return id; } + operator bool() const { return is_valid(); } + + [[nodiscard]] std::string to_string() const { return StringUtils::from_int(id); } + + int id = -1; + }; /** * @class VisibilityItemData @@ -56,7 +71,7 @@ namespace wmoge { Aabbf aabb; float min_dist_2 = 0.0f; float max_dist_2 = 10000000000.0f; - VisibilityItem id = VIS_ITEM_INVALID; + VisibilityItem id; }; /** @@ -94,8 +109,6 @@ namespace wmoge { std::vector m_result; std::vector m_free; int m_task_batch = 16; - - RwMutexWritePrefer m_mutex; }; }// namespace wmoge diff --git a/engine/resource/font.cpp b/engine/resource/font.cpp index 68ee9bba1..3c4ba39f9 100644 --- a/engine/resource/font.cpp +++ b/engine/resource/font.cpp @@ -175,7 +175,7 @@ namespace wmoge { TexCompressionParams compression_params{}; compression_params.format = TexCompressionFormat::BC4; - m_texture = make_ref(GfxFormat::R8, bitmap_width, bitmap_height); + m_texture = make_ref(GfxFormat::R8, bitmap_width, bitmap_height, GfxTexSwizz::RRRRtoRGBA); m_texture->set_name(SID(get_name().str() + "_texture")); m_texture->set_sampler_from_desc(sampler_desc); m_texture->set_compression(compression_params); diff --git a/engine/resource/texture.cpp b/engine/resource/texture.cpp index 69f5d61e4..388166f91 100644 --- a/engine/resource/texture.cpp +++ b/engine/resource/texture.cpp @@ -112,13 +112,14 @@ namespace wmoge { return StatusCode::Ok; } - Texture::Texture(GfxFormat format, int width, int height, int depth, int array_slices) { + Texture::Texture(GfxFormat format, int width, int height, int depth, int array_slices, GfxTexSwizz swizz) { m_format = format; m_width = width; m_height = height; m_depth = depth; m_array_slices = array_slices; m_mips = 1; + m_swizz = swizz; } void Texture::set_source_images(std::vector> images) { @@ -239,7 +240,7 @@ namespace wmoge { switch (m_tex_type) { case GfxTex::Tex2d: - m_texture = gfx_driver->make_texture_2d(m_width, m_height, m_mips, format, m_usages, m_mem_usage, get_name()); + m_texture = gfx_driver->make_texture_2d(m_width, m_height, m_mips, format, m_usages, m_mem_usage, m_swizz, get_name()); break; case GfxTex::Tex2dArray: m_texture = gfx_driver->make_texture_2d_array(m_width, m_height, m_mips, m_array_slices, format, m_usages, m_mem_usage, get_name()); @@ -316,7 +317,7 @@ namespace wmoge { cls->add_field(ClassField(VarType::Int, SID("srgb")), &Texture::m_srgb); } - Texture2d::Texture2d(GfxFormat format, int width, int height) : Texture(format, width, height) { + Texture2d::Texture2d(GfxFormat format, int width, int height, GfxTexSwizz swizz) : Texture(format, width, height, 1, 1, swizz) { m_tex_type = GfxTex::Tex2d; } Status Texture2d::copy_to(Object& copy) const { diff --git a/engine/resource/texture.hpp b/engine/resource/texture.hpp index d1df8f96e..2a9330f82 100644 --- a/engine/resource/texture.hpp +++ b/engine/resource/texture.hpp @@ -107,8 +107,9 @@ namespace wmoge { * @param height Height of the texture in pixels * @param depth Depth of the texture in pixels (in most cases 1) * @param array_slices Number of slices for array or cube texture (in most cases 1) + * @param swizz Texture channels swizzling */ - Texture(GfxFormat format, int width, int height, int depth = 1, int array_slices = 1); + Texture(GfxFormat format, int width, int height, int depth = 1, int array_slices = 1, GfxTexSwizz swizz = GfxTexSwizz::None); virtual void set_source_images(std::vector> images); virtual void set_sampler(const Ref& sampler); @@ -134,6 +135,7 @@ namespace wmoge { [[nodiscard]] GfxFormat get_format() const { return m_format; } [[nodiscard]] GfxFormat get_format_compressed() const { return m_format_compressed; } [[nodiscard]] GfxTex get_tex_type() const { return m_tex_type; } + [[nodiscard]] GfxTexSwizz get_tex_swizz() const { return m_swizz; } [[nodiscard]] GfxMemUsage get_mem_usage() const { return m_mem_usage; } [[nodiscard]] GfxTexUsages get_usages() const { return m_usages; } [[nodiscard]] bool get_srgb() const { return m_srgb; } @@ -154,6 +156,7 @@ namespace wmoge { GfxFormat m_format = GfxFormat::Unknown; GfxFormat m_format_compressed = GfxFormat::Unknown; GfxTex m_tex_type = GfxTex::Tex2d; + GfxTexSwizz m_swizz = GfxTexSwizz::None; GfxMemUsage m_mem_usage = GfxMemUsage::GpuLocal; GfxTexUsages m_usages = {GfxTexUsageFlag::Sampling}; bool m_srgb = false; @@ -168,7 +171,7 @@ namespace wmoge { public: WG_OBJECT(Texture2d, Texture); - Texture2d(GfxFormat format, int width, int height); + Texture2d(GfxFormat format, int width, int height, GfxTexSwizz swizz = GfxTexSwizz::None); Status copy_to(Object& other) const override; }; diff --git a/engine/scene/scene.cpp b/engine/scene/scene.cpp index 16d9e1766..fa7199709 100644 --- a/engine/scene/scene.cpp +++ b/engine/scene/scene.cpp @@ -114,10 +114,11 @@ namespace wmoge { void Scene::add_mesh_static(EcsEntity entity, const SceneDataMeshStatic& data) { EcsComponentMeshStatic& ecs_mesh = get_ecs_world()->get_component_rw(entity); - ecs_mesh.mesh = std::make_unique(data.model.get_safe()); - get_render_scene()->add_object(ecs_mesh.mesh.get()); + ecs_mesh.mesh = std::make_unique(data.model.get_safe()); + ecs_mesh.vis_item = get_visibility_system()->alloc_item(); + + get_render_scene()->add_object(ecs_mesh.mesh.get(), ecs_mesh.vis_item); - ecs_mesh.vis_item = get_visibility_system()->alloc_item(); ecs_mesh.primitive_id = ecs_mesh.mesh->get_primitive_id(); ecs_mesh.dirty = true; } diff --git a/engine/scene/scene_camera.cpp b/engine/scene/scene_camera.cpp index c21da3a01..5945e7d50 100644 --- a/engine/scene/scene_camera.cpp +++ b/engine/scene/scene_camera.cpp @@ -31,6 +31,8 @@ #include "event/event_action.hpp" #include "event/event_manager.hpp" #include "math/quat.hpp" +#include "platform/window.hpp" +#include "platform/window_manager.hpp" namespace wmoge { @@ -195,6 +197,14 @@ namespace wmoge { } return filtered; } + void CameraManager::fill_render_cameras(RenderCameras& cameras) { + Ref camera = find_active().value_or(get_default_camera()); + camera->update_render_camera(Engine::instance()->window_manager()->primary_window()->fbo_size()); + const RenderCamera& camera_curr = camera->get_render_camera(); + + cameras.clear(); + cameras.add_camera(CameraType::Color, camera_curr, std::nullopt); + } bool CameraManager::is_default(const Camera* camera) const { return camera == m_camera_default.get(); } diff --git a/engine/scene/scene_camera.hpp b/engine/scene/scene_camera.hpp index 1b314a17b..7e6330ca1 100644 --- a/engine/scene/scene_camera.hpp +++ b/engine/scene/scene_camera.hpp @@ -115,6 +115,7 @@ namespace wmoge { std::optional> find_active(); std::optional> find_first(const std::function&)>& pred); std::vector> filter(const std::function&)>& pred); + void fill_render_cameras(RenderCameras& cameras); [[nodiscard]] ArrayView> get_cameras() const { return m_cameras; } [[nodiscard]] Ref get_debug_camera() const { return m_camera_debug; } diff --git a/engine/scene/scene_components.hpp b/engine/scene/scene_components.hpp index e3eeee95b..04a98bce1 100644 --- a/engine/scene/scene_components.hpp +++ b/engine/scene/scene_components.hpp @@ -146,7 +146,7 @@ namespace wmoge { WG_ECS_COMPONENT(EcsComponentMeshStatic, 9); std::unique_ptr mesh; - VisibilityItem vis_item = VIS_ITEM_INVALID; + VisibilityItem vis_item; int primitive_id = -1; bool dirty = true; }; diff --git a/engine/scene/scene_manager.cpp b/engine/scene/scene_manager.cpp index 34d714d2b..7d403d7e0 100644 --- a/engine/scene/scene_manager.cpp +++ b/engine/scene/scene_manager.cpp @@ -161,6 +161,38 @@ namespace wmoge { ecs_world->execute_system(sys_update_static_meshes); } + void SceneManager::scene_cameras() { + WG_AUTO_PROFILE_SCENE("SceneManager::scene_cameras"); + + Engine* engine = Engine::instance(); + RenderEngine* render_engine = engine->render_engine(); + + Scene* scene = m_running.get(); + CameraManager* camera_manager = scene->get_cameras(); + RenderCameras& render_cameras = render_engine->get_cameras(); + + camera_manager->fill_render_cameras(render_cameras); + } + + void SceneManager::scene_visibility() { + WG_AUTO_PROFILE_SCENE("SceneManager::scene_visibility"); + + Engine* engine = Engine::instance(); + RenderEngine* render_engine = engine->render_engine(); + + Scene* scene = m_running.get(); + EcsWorld* ecs_world = scene->get_ecs_world(); + VisibilitySystem* vis_system = scene->get_visibility_system(); + const RenderCameras& render_cameras = render_engine->get_cameras(); + + vis_system->cull(render_cameras); + + EcsSysPocessVisStaticMeshes sys_process_vis_static_meshes; + sys_process_vis_static_meshes.render_scene = scene->get_render_scene(); + sys_process_vis_static_meshes.vis_system = scene->get_visibility_system(); + ecs_world->execute_system(sys_process_vis_static_meshes); + } + void SceneManager::scene_render() { WG_AUTO_PROFILE_SCENE("SceneManager::scene_render"); @@ -170,35 +202,15 @@ namespace wmoge { WindowManager* window_manager = engine->window_manager(); Ref window = window_manager->primary_window(); - Scene* scene = m_running.get(); - EcsWorld* ecs_world = scene->get_ecs_world(); - VisibilitySystem* vis_system = scene->get_visibility_system(); - CameraManager* camera_manager = scene->get_cameras(); + Scene* scene = m_running.get(); render_engine->begin_rendering(); - Ref camera = camera_manager->find_active().value_or(camera_manager->get_default_camera()); - camera->update_render_camera(window->fbo_size()); - RenderCamera camera_curr = camera->get_render_camera(); - - RenderCameras& render_cameras = render_engine->get_cameras(); - render_cameras.clear(); - render_cameras.add_camera(CameraType::Color, camera_curr, render_engine->get_camera_prev()); - - vis_system->cull(render_cameras); - { - WG_AUTO_PROFILE_SCENE("SceneManager::process_visibility"); - - EcsSysPocessVisStaticMeshes sys_process_vis_static_meshes; - sys_process_vis_static_meshes.render_scene = scene->get_render_scene(); - sys_process_vis_static_meshes.vis_system = scene->get_visibility_system(); - ecs_world->execute_system(sys_process_vis_static_meshes); - } - render_engine->set_time(scene->get_time()); render_engine->set_delta_time(scene->get_delta_time()); render_engine->set_target(window); render_engine->set_scene(scene->get_render_scene()); + render_engine->set_visiblity(scene->get_visibility_system()); render_engine->prepare_frame_data(); render_engine->allocate_veiws(); @@ -209,16 +221,17 @@ namespace wmoge { render_engine->merge_cmds(); render_engine->flush_buffers(); - gfx_ctx->begin_render_pass({}, SID("PassGeomGBuffer::execute")); - { - gfx_ctx->bind_target(render_engine->get_main_target()); - gfx_ctx->viewport(render_cameras.data_at(0).viewport); - gfx_ctx->clear(0, render_engine->get_clear_color()); - gfx_ctx->clear(1.0f, 0); - - render_engine->get_views()[0].queues[int(MeshPassType::GBuffer)].execute(gfx_ctx); - } - gfx_ctx->end_render_pass(); + gfx_ctx->execute([&](GfxCtx* thread_ctx) { + thread_ctx->begin_render_pass({}, SID("PassGeomGBuffer::execute")); + { + thread_ctx->bind_target(render_engine->get_main_target()); + thread_ctx->viewport(render_engine->get_cameras().data_at(0).viewport); + thread_ctx->clear(0, render_engine->get_clear_color()); + thread_ctx->clear(1.0f, 0); + render_engine->get_views()[0].queues[int(MeshPassType::GBuffer)].execute(thread_ctx); + } + thread_ctx->end_render_pass(); + }); render_engine->end_rendering(); } @@ -274,6 +287,8 @@ namespace wmoge { scene_hier(); scene_transforms(); + scene_cameras(); + scene_visibility(); scene_render(); scene_pfx(); scene_scripting(); diff --git a/engine/scene/scene_manager.hpp b/engine/scene/scene_manager.hpp index a106c87e0..17c53dc91 100644 --- a/engine/scene/scene_manager.hpp +++ b/engine/scene/scene_manager.hpp @@ -55,6 +55,8 @@ namespace wmoge { private: void scene_hier(); void scene_transforms(); + void scene_cameras(); + void scene_visibility(); void scene_render(); void scene_pfx(); void scene_scripting(); diff --git a/engine/shaders/aux_draw_canvas.frag b/engine/shaders/aux_draw_canvas.frag deleted file mode 100644 index 77970c50e..000000000 --- a/engine/shaders/aux_draw_canvas.frag +++ /dev/null @@ -1,27 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/**********************************************************************************/ - -#include "common_funcs.glsl" - -layout(location = 0) out vec4 fs_color; - -LAYOUT_LOCATION(0) in vec4 in_color; -LAYOUT_LOCATION(1) in vec2 in_uv; - -void main() { - #ifdef CANVAS_FONT_BITMAP - float mask = texture(Texture, in_uv).r; - fs_color = vec4(in_color.rgb, in_color.a * mask); - #else - vec4 tex_color_srgb = texture(Texture, in_uv).rgba; - vec4 tex_color_linear = vec4(ColorSrgbToLinear(tex_color_srgb.rgb, gamma), tex_color_srgb.a); - - fs_color = vec4(in_color.rgba * tex_color_linear); - #endif -} \ No newline at end of file diff --git a/engine/shaders/aux_draw_canvas.vert b/engine/shaders/aux_draw_canvas.vert deleted file mode 100644 index 319e24dc7..000000000 --- a/engine/shaders/aux_draw_canvas.vert +++ /dev/null @@ -1,23 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/**********************************************************************************/ - -#include "common_funcs.glsl" - -layout(location = 0) in vec2 in_pos; -layout(location = 1) in vec2 in_uv; -layout(location = 2) in vec4 in_col; - -LAYOUT_LOCATION(0) out vec4 out_color; -LAYOUT_LOCATION(1) out vec2 out_uv; - -void main() { - out_color = in_col; - out_uv = UnpackUv(in_uv); - gl_Position = clip_proj_screen * vec4(in_pos, 0.0f, 1.0f); -} \ No newline at end of file diff --git a/engine/shaders/base.frag b/engine/shaders/base.frag index 5c5e02d25..4bdd1e25a 100644 --- a/engine/shaders/base.frag +++ b/engine/shaders/base.frag @@ -9,8 +9,6 @@ #version 450 core -#define INOUT in -#define FRAGMENT_SHADER #include "inout_attributes.glsl" #include "common_funcs.glsl" diff --git a/engine/shaders/base.vert b/engine/shaders/base.vert index 1543ce702..74c44fc55 100644 --- a/engine/shaders/base.vert +++ b/engine/shaders/base.vert @@ -9,8 +9,6 @@ #version 450 core -#define INOUT out -#define VERTEX_SHADER #include "inout_attributes.glsl" #include "vertex_attributes.glsl" #include "common_defines.glsl" diff --git a/engine/shaders/canvas.frag b/engine/shaders/canvas.frag new file mode 100644 index 000000000..57164f3ac --- /dev/null +++ b/engine/shaders/canvas.frag @@ -0,0 +1,62 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/**********************************************************************************/ + +#include "common_funcs.glsl" +#include "inout_attributes.glsl + +layout (location = 0) out vec4 out_color; + +DrawCmdData GetCmdData(in int idx) { + return DrawCmds[idx]; +} + +bool ChechClipRect(in vec4 clipRect, in vec2 pos) { + const vec2 clipMin = clipRect.xy; + const vec2 clipMax = clipRect.zw; + + return pos.x < clipMin.x || pos.x > clipMax.x || + pos.y < clipMin.y || pos.y > clipMax.y; +} + +vec4 SampleImage(in int idx, in vec2 uv) { + if (idx == 0) { + return texture(CanvasImage0, uv).rgba; + } + if (idx == 1) { + return texture(CanvasImage1, uv).rgba; + } + if (idx == 2) { + return texture(CanvasImage2, uv).rgba; + } + if (idx == 4) { + return texture(CanvasImage3, uv).rgba; + } + + return vec4(1,1,1,1); +} + +void main() { + const InoutAttributes attributes = ReadInoutAttributes(); + const DrawCmdData cmdData = GetCmdData(attributes.primitiveId); + const vec2 pos = attributes.worldPos.xy; + const vec4 clipRect = cmdData.ClipRect; + const int textureIdx = cmdData.TextureIdx; + + if (ChechClipRect(clipRect, pos)) { + discard; + } + + vec4 color = SampleImage(textureIdx, attributes.uv[0]) * attributes.col[0]; + + #ifdef OUT_SRGB + color.rgb = ColorSrgbToLinear(color.rgb, InverseGamma); + #endif + + out_color = color; +} \ No newline at end of file diff --git a/engine/shaders/canvas.vert b/engine/shaders/canvas.vert new file mode 100644 index 000000000..c69fb13a9 --- /dev/null +++ b/engine/shaders/canvas.vert @@ -0,0 +1,38 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/**********************************************************************************/ + +#include "common_funcs.glsl" +#include "vertex_attributes.glsl" +#include "inout_attributes.glsl + +DrawCmdData GetCmdData(in int idx) { + return DrawCmds[idx]; +} + +mat3 GetDrawCmdTransform(in int idx) { + const DrawCmdData data = GetCmdData(idx); + return mat3(data.Transform0.xyz, + data.Transform1.xyz, + data.Transform2.xyz); +} + +void main() { + const VertexAttributes vertex = ReadVertexAttributes(); + const mat3 transform = GetDrawCmdTransform(vertex.primitiveId); + + InoutAttributes result; + result.worldPos = transform * vec3(vertex.pos2, 1.0f); + result.col[0] = vertex.col[0]; + result.uv[0] = UnpackUv(vertex.uv[0]); + result.primitiveId = vertex.primitiveId; + + StoreInoutAttributes(result); + + gl_Position = ClipProjView * vec4(result.worldPos, 1.0f); +} \ No newline at end of file diff --git a/engine/shaders/generated/auto_aux_draw_canvas_gl410_frag.hpp b/engine/shaders/generated/auto_aux_draw_canvas_gl410_frag.hpp deleted file mode 100644 index 6de0169b1..000000000 --- a/engine/shaders/generated/auto_aux_draw_canvas_gl410_frag.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify - -#pragma once - -#include "core/string_id.hpp" -#include "core/string_utf.hpp" -#include "core/string_utils.hpp" -#include "gfx/gfx_defs.hpp" -#include "math/mat.hpp" -#include "math/vec.hpp" - -namespace wmoge { - - static const char source_aux_draw_canvas_gl410_frag[] = R"( -uniform sampler2D Texture; - -layout (std140) uniform Params { -mat4 clip_proj_screen; -float gamma; -float inverse_gamma; -}; - - -#define TARGET_VULKAN -#if defined(TARGET_VULKAN) -#define LAYOUT_LOCATION(idx) layout(location = idx) -#else -#define LAYOUT_LOCATION(idx) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) -#else -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) -#else -#define LAYOUT_SAMPLER(set_idx, binding_idx) -#endif -vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { - return pow(color, vec3(gamma)); -} -vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { - return pow(color, vec3(inverse_gamma)); -} -vec2 UnpackUv(in vec2 uv) { - #ifdef TARGET_VULKAN - return vec2(uv.x, 1.0f - uv.y); - #else - return uv; - #endif -} -mat4 GetIdentity4x4() { - mat4 matrix = mat4( - vec4(1,0,0,0), - vec4(0,1,0,0), - vec4(0,0,1,0), - vec4(0,0,0,1)); - - return matrix; -} -vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { - return (localToWorld * vec4(posLocal, 1.0f)).xyz; -} -vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { - return (normalMatrix * vec4(normLocal, 0.0f)).xyz; -} -layout(location = 0) out vec4 fs_color; -LAYOUT_LOCATION(0) in vec4 in_color; -LAYOUT_LOCATION(1) in vec2 in_uv; -void main() { - #ifdef CANVAS_FONT_BITMAP - float mask = texture(Texture, in_uv).r; - fs_color = vec4(in_color.rgb, in_color.a * mask); - #else - vec4 tex_color_srgb = texture(Texture, in_uv).rgba; - vec4 tex_color_linear = vec4(ColorSrgbToLinear(tex_color_srgb.rgb, gamma), tex_color_srgb.a); - fs_color = vec4(in_color.rgba * tex_color_linear); - #endif -} - -)"; -} diff --git a/engine/shaders/generated/auto_aux_draw_canvas_gl410_vert.hpp b/engine/shaders/generated/auto_aux_draw_canvas_gl410_vert.hpp deleted file mode 100644 index ccd11c981..000000000 --- a/engine/shaders/generated/auto_aux_draw_canvas_gl410_vert.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify - -#pragma once - -#include "core/string_id.hpp" -#include "core/string_utf.hpp" -#include "core/string_utils.hpp" -#include "gfx/gfx_defs.hpp" -#include "math/mat.hpp" -#include "math/vec.hpp" - -namespace wmoge { - - static const char source_aux_draw_canvas_gl410_vert[] = R"( -uniform sampler2D Texture; - -layout (std140) uniform Params { -mat4 clip_proj_screen; -float gamma; -float inverse_gamma; -}; - - -#define TARGET_VULKAN -#if defined(TARGET_VULKAN) -#define LAYOUT_LOCATION(idx) layout(location = idx) -#else -#define LAYOUT_LOCATION(idx) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) -#else -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) -#else -#define LAYOUT_SAMPLER(set_idx, binding_idx) -#endif -vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { - return pow(color, vec3(gamma)); -} -vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { - return pow(color, vec3(inverse_gamma)); -} -vec2 UnpackUv(in vec2 uv) { - #ifdef TARGET_VULKAN - return vec2(uv.x, 1.0f - uv.y); - #else - return uv; - #endif -} -mat4 GetIdentity4x4() { - mat4 matrix = mat4( - vec4(1,0,0,0), - vec4(0,1,0,0), - vec4(0,0,1,0), - vec4(0,0,0,1)); - - return matrix; -} -vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { - return (localToWorld * vec4(posLocal, 1.0f)).xyz; -} -vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { - return (normalMatrix * vec4(normLocal, 0.0f)).xyz; -} -layout(location = 0) in vec2 in_pos; -layout(location = 1) in vec2 in_uv; -layout(location = 2) in vec4 in_col; -LAYOUT_LOCATION(0) out vec4 out_color; -LAYOUT_LOCATION(1) out vec2 out_uv; -void main() { - out_color = in_col; - out_uv = UnpackUv(in_uv); - gl_Position = clip_proj_screen * vec4(in_pos, 0.0f, 1.0f); -} - -)"; -} diff --git a/engine/shaders/generated/auto_aux_draw_canvas_vk450_frag.hpp b/engine/shaders/generated/auto_aux_draw_canvas_vk450_frag.hpp deleted file mode 100644 index 81439b4c8..000000000 --- a/engine/shaders/generated/auto_aux_draw_canvas_vk450_frag.hpp +++ /dev/null @@ -1,110 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify - -#pragma once - -#include "core/string_id.hpp" -#include "core/string_utf.hpp" -#include "core/string_utils.hpp" -#include "gfx/gfx_defs.hpp" -#include "math/mat.hpp" -#include "math/vec.hpp" - -namespace wmoge { - - static const char source_aux_draw_canvas_vk450_frag[] = R"( -layout (set = 0, binding = 1) uniform sampler2D Texture; - -layout (set = 0, binding = 0, std140) uniform Params { -mat4 clip_proj_screen; -float gamma; -float inverse_gamma; -}; - - -#define TARGET_VULKAN -#if defined(TARGET_VULKAN) -#define LAYOUT_LOCATION(idx) layout(location = idx) -#else -#define LAYOUT_LOCATION(idx) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) -#else -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) -#else -#define LAYOUT_SAMPLER(set_idx, binding_idx) -#endif -vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { - return pow(color, vec3(gamma)); -} -vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { - return pow(color, vec3(inverse_gamma)); -} -vec2 UnpackUv(in vec2 uv) { - #ifdef TARGET_VULKAN - return vec2(uv.x, 1.0f - uv.y); - #else - return uv; - #endif -} -mat4 GetIdentity4x4() { - mat4 matrix = mat4( - vec4(1,0,0,0), - vec4(0,1,0,0), - vec4(0,0,1,0), - vec4(0,0,0,1)); - - return matrix; -} -vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { - return (localToWorld * vec4(posLocal, 1.0f)).xyz; -} -vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { - return (normalMatrix * vec4(normLocal, 0.0f)).xyz; -} -layout(location = 0) out vec4 fs_color; -LAYOUT_LOCATION(0) in vec4 in_color; -LAYOUT_LOCATION(1) in vec2 in_uv; -void main() { - #ifdef CANVAS_FONT_BITMAP - float mask = texture(Texture, in_uv).r; - fs_color = vec4(in_color.rgb, in_color.a * mask); - #else - vec4 tex_color_srgb = texture(Texture, in_uv).rgba; - vec4 tex_color_linear = vec4(ColorSrgbToLinear(tex_color_srgb.rgb, gamma), tex_color_srgb.a); - fs_color = vec4(in_color.rgba * tex_color_linear); - #endif -} - -)"; -} diff --git a/engine/shaders/generated/auto_aux_draw_canvas_vk450_vert.hpp b/engine/shaders/generated/auto_aux_draw_canvas_vk450_vert.hpp deleted file mode 100644 index 1f4c5a7a5..000000000 --- a/engine/shaders/generated/auto_aux_draw_canvas_vk450_vert.hpp +++ /dev/null @@ -1,107 +0,0 @@ -/**********************************************************************************/ -/* Wmoge game engine */ -/* Available at github https://github.com/EgorOrachyov/wmoge */ -/**********************************************************************************/ -/* MIT License */ -/* */ -/* Copyright (c) 2023 Egor Orachyov */ -/* */ -/* Permission is hereby granted, free of charge, to any person obtaining a copy */ -/* of this software and associated documentation files (the "Software"), to deal */ -/* in the Software without restriction, including without limitation the rights */ -/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ -/* copies of the Software, and to permit persons to whom the Software is */ -/* furnished to do so, subject to the following conditions: */ -/* */ -/* The above copyright notice and this permission notice shall be included in all */ -/* copies or substantial portions of the Software. */ -/* */ -/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ -/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ -/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ -/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ -/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ -/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ -/* SOFTWARE. */ -/**********************************************************************************/ - -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify - -#pragma once - -#include "core/string_id.hpp" -#include "core/string_utf.hpp" -#include "core/string_utils.hpp" -#include "gfx/gfx_defs.hpp" -#include "math/mat.hpp" -#include "math/vec.hpp" - -namespace wmoge { - - static const char source_aux_draw_canvas_vk450_vert[] = R"( -layout (set = 0, binding = 1) uniform sampler2D Texture; - -layout (set = 0, binding = 0, std140) uniform Params { -mat4 clip_proj_screen; -float gamma; -float inverse_gamma; -}; - - -#define TARGET_VULKAN -#if defined(TARGET_VULKAN) -#define LAYOUT_LOCATION(idx) layout(location = idx) -#else -#define LAYOUT_LOCATION(idx) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) -#else -#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) -#endif -#if defined(TARGET_VULKAN) -#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) -#else -#define LAYOUT_SAMPLER(set_idx, binding_idx) -#endif -vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { - return pow(color, vec3(gamma)); -} -vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { - return pow(color, vec3(inverse_gamma)); -} -vec2 UnpackUv(in vec2 uv) { - #ifdef TARGET_VULKAN - return vec2(uv.x, 1.0f - uv.y); - #else - return uv; - #endif -} -mat4 GetIdentity4x4() { - mat4 matrix = mat4( - vec4(1,0,0,0), - vec4(0,1,0,0), - vec4(0,0,1,0), - vec4(0,0,0,1)); - - return matrix; -} -vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { - return (localToWorld * vec4(posLocal, 1.0f)).xyz; -} -vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { - return (normalMatrix * vec4(normLocal, 0.0f)).xyz; -} -layout(location = 0) in vec2 in_pos; -layout(location = 1) in vec2 in_uv; -layout(location = 2) in vec4 in_col; -LAYOUT_LOCATION(0) out vec4 out_color; -LAYOUT_LOCATION(1) out vec2 out_uv; -void main() { - out_color = in_col; - out_uv = UnpackUv(in_uv); - gl_Position = clip_proj_screen * vec4(in_pos, 0.0f, 1.0f); -} - -)"; -} diff --git a/engine/shaders/generated/auto_base_gl410_frag.hpp b/engine/shaders/generated/auto_base_gl410_frag.hpp index 7f7968e39..7b4a204d0 100644 --- a/engine/shaders/generated/auto_base_gl410_frag.hpp +++ b/engine/shaders/generated/auto_base_gl410_frag.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -49,8 +49,6 @@ float mix_weight_3; }; -#define INOUT in -#define FRAGMENT_SHADER #define TARGET_VULKAN #if defined(TARGET_VULKAN) #define LAYOUT_LOCATION(idx) layout(location = idx) diff --git a/engine/shaders/generated/auto_base_gl410_vert.hpp b/engine/shaders/generated/auto_base_gl410_vert.hpp index fb83a87f9..718bb244d 100644 --- a/engine/shaders/generated/auto_base_gl410_vert.hpp +++ b/engine/shaders/generated/auto_base_gl410_vert.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -49,8 +49,6 @@ float mix_weight_3; }; -#define INOUT out -#define VERTEX_SHADER #define TARGET_VULKAN #if defined(TARGET_VULKAN) #define LAYOUT_LOCATION(idx) layout(location = idx) diff --git a/engine/shaders/generated/auto_base_pass.hpp b/engine/shaders/generated/auto_base_pass.hpp index e9c29b275..4551c6bbf 100644 --- a/engine/shaders/generated/auto_base_pass.hpp +++ b/engine/shaders/generated/auto_base_pass.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_base_reflection.hpp b/engine/shaders/generated/auto_base_reflection.hpp index 2c94e1c8a..04e0337e1 100644 --- a/engine/shaders/generated/auto_base_reflection.hpp +++ b/engine/shaders/generated/auto_base_reflection.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_base_vk450_frag.hpp b/engine/shaders/generated/auto_base_vk450_frag.hpp index d247660f3..85b651c59 100644 --- a/engine/shaders/generated/auto_base_vk450_frag.hpp +++ b/engine/shaders/generated/auto_base_vk450_frag.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -49,8 +49,6 @@ float mix_weight_3; }; -#define INOUT in -#define FRAGMENT_SHADER #define TARGET_VULKAN #if defined(TARGET_VULKAN) #define LAYOUT_LOCATION(idx) layout(location = idx) diff --git a/engine/shaders/generated/auto_base_vk450_vert.hpp b/engine/shaders/generated/auto_base_vk450_vert.hpp index a7e587e65..a226ea71a 100644 --- a/engine/shaders/generated/auto_base_vk450_vert.hpp +++ b/engine/shaders/generated/auto_base_vk450_vert.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -49,8 +49,6 @@ float mix_weight_3; }; -#define INOUT out -#define VERTEX_SHADER #define TARGET_VULKAN #if defined(TARGET_VULKAN) #define LAYOUT_LOCATION(idx) layout(location = idx) diff --git a/engine/shaders/generated/auto_canvas_gl410_frag.hpp b/engine/shaders/generated/auto_canvas_gl410_frag.hpp new file mode 100644 index 000000000..224a0c4e1 --- /dev/null +++ b/engine/shaders/generated/auto_canvas_gl410_frag.hpp @@ -0,0 +1,309 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify + +#pragma once + +#include "core/string_id.hpp" +#include "core/string_utf.hpp" +#include "core/string_utils.hpp" +#include "gfx/gfx_defs.hpp" +#include "math/mat.hpp" +#include "math/vec.hpp" + +namespace wmoge { + + static const char source_canvas_gl410_frag[] = R"( +struct DrawCmdData{ +vec4 Transform0; +vec4 Transform1; +vec4 Transform2; +vec4 ClipRect; +int TextureIdx; +int _dc_pad0; +int _dc_pad1; +int _dc_pad2; +}; + +#define MAX_CANVAS_IMAGES (4) + +uniform sampler2D CanvasImage0; + +uniform sampler2D CanvasImage1; + +uniform sampler2D CanvasImage2; + +uniform sampler2D CanvasImage3; + +layout (std140) uniform Params { +mat4 ClipProjView; +float InverseGamma; +float _pr_pad0; +float _pr_pad1; +float _pr_pad2; +}; + +layout (std430) readonly buffer DrawCmdsData { +DrawCmdData DrawCmds[]; +}; + + +#define TARGET_VULKAN +#if defined(TARGET_VULKAN) +#define LAYOUT_LOCATION(idx) layout(location = idx) +#else +#define LAYOUT_LOCATION(idx) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) +#else +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) +#else +#define LAYOUT_SAMPLER(set_idx, binding_idx) +#endif +vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { + return pow(color, vec3(gamma)); +} +vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { + return pow(color, vec3(inverse_gamma)); +} +vec2 UnpackUv(in vec2 uv) { + #ifdef TARGET_VULKAN + return vec2(uv.x, 1.0f - uv.y); + #else + return uv; + #endif +} +mat4 GetIdentity4x4() { + mat4 matrix = mat4( + vec4(1,0,0,0), + vec4(0,1,0,0), + vec4(0,0,1,0), + vec4(0,0,0,1)); + + return matrix; +} +vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { + return (localToWorld * vec4(posLocal, 1.0f)).xyz; +} +vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { + return (normalMatrix * vec4(normLocal, 0.0f)).xyz; +} +#ifdef VERTEX_SHADER + #define INOUT out +#endif +#ifdef FRAGMENT_SHADER + #define INOUT in +#endif +#ifndef INOUT + #error "Must be defined" +#endif +#if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + LAYOUT_LOCATION( 0) INOUT vec3 inout_worldPos; +#endif +#ifdef ATTRIB_Norm3f + LAYOUT_LOCATION( 1) INOUT vec3 inout_worldNorm; +#endif +#ifdef ATTRIB_Tang3f + LAYOUT_LOCATION( 2) INOUT vec3 inout_worldTang; +#endif +#ifdef ATTRIB_Col04f + LAYOUT_LOCATION( 3) INOUT vec4 inout_col0; +#endif +#ifdef ATTRIB_Col14f + LAYOUT_LOCATION( 4) INOUT vec4 inout_col1; +#endif +#ifdef ATTRIB_Col24f + LAYOUT_LOCATION( 5) INOUT vec4 inout_col2; +#endif +#ifdef ATTRIB_Col34f + LAYOUT_LOCATION( 6) INOUT vec4 inout_col3; +#endif +#ifdef ATTRIB_Uv02f + LAYOUT_LOCATION( 7) INOUT vec2 inout_uv0; +#endif +#ifdef ATTRIB_Uv12f + LAYOUT_LOCATION( 8) INOUT vec2 inout_uv1; +#endif +#ifdef ATTRIB_Uv22f + LAYOUT_LOCATION( 9) INOUT vec2 inout_uv2; +#endif +#ifdef ATTRIB_Uv32f + LAYOUT_LOCATION(10) INOUT vec2 inout_uv3; +#endif +#ifdef ATTRIB_PrimitiveIdi + LAYOUT_LOCATION(11) flat INOUT int inout_primitiveId; +#endif +struct InoutAttributes { + vec3 worldPos; + vec3 worldNorm; + vec3 worldTang; + vec4 col[4]; + vec2 uv[4]; + int primitiveId; +}; +#ifdef VERTEX_SHADER +void StoreInoutAttributes(in InoutAttributes attributes) { + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + inout_worldPos = attributes.worldPos; + #endif + #ifdef ATTRIB_Norm3f + inout_worldNorm = attributes.worldNorm; + #endif + #ifdef ATTRIB_Tang3f + inout_worldTang = attributes.worldTang; + #endif + #ifdef ATTRIB_Col04f + inout_col0 = attributes.col[0]; + #endif + #ifdef ATTRIB_Col14f + inout_col1 = attributes.col[1]; + #endif + #ifdef ATTRIB_Col24f + inout_col2 = attributes.col[2]; + #endif + #ifdef ATTRIB_Col34f + inout_col3 = attributes.col[3]; + #endif + #ifdef ATTRIB_Uv02f + inout_uv0 = attributes.uv[0]; + #endif + #ifdef ATTRIB_Uv12f + inout_uv1 = attributes.uv[1]; + #endif + #ifdef ATTRIB_Uv22f + inout_uv2 = attributes.uv[2]; + #endif + #ifdef ATTRIB_Uv32f + inout_uv3 = attributes.uv[3]; + #endif + #ifdef ATTRIB_PrimitiveIdi + inout_primitiveId = attributes.primitiveId; + #endif +} +#endif//VERTEX_SHADER +#ifdef FRAGMENT_SHADER +InoutAttributes ReadInoutAttributes() { + InoutAttributes attributes; + attributes.worldPos = vec3(0,0,0); + attributes.worldNorm = vec3(0,0,0); + attributes.worldTang = vec3(0,0,0); + attributes.col[0] = vec4(0,0,0,0); + attributes.col[1] = vec4(0,0,0,0); + attributes.col[2] = vec4(0,0,0,0); + attributes.col[3] = vec4(0,0,0,0); + attributes.uv[0] = vec2(0,0); + attributes.uv[1] = vec2(0,0); + attributes.uv[2] = vec2(0,0); + attributes.uv[3] = vec2(0,0); + attributes.primitiveId = -1; + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + attributes.worldPos = inout_worldPos; + #endif + #ifdef ATTRIB_Norm3f + attributes.worldNorm = inout_worldNorm; + #endif + #ifdef ATTRIB_Tang3f + attributes.worldTang = inout_worldTang; + #endif + #ifdef ATTRIB_Col04f + attributes.col[0] = inout_col0; + #endif + #ifdef ATTRIB_Col14f + attributes.col[1] = inout_col1; + #endif + #ifdef ATTRIB_Col24f + attributes.col[2] = inout_col2; + #endif + #ifdef ATTRIB_Col34f + attributes.col[3] = inout_col3; + #endif + #ifdef ATTRIB_Uv02f + attributes.uv[0] = inout_uv0; + #endif + #ifdef ATTRIB_Uv12f + attributes.uv[1] = inout_uv1; + #endif + #ifdef ATTRIB_Uv22f + attributes.uv[2] = inout_uv2; + #endif + #ifdef ATTRIB_Uv32f + attributes.uv[3] = inout_uv3; + #endif + #ifdef ATTRIB_PrimitiveIdi + attributes.primitiveId = inout_primitiveId; + #endif + return attributes; +} +#endif//FRAGMENT_SHADER +layout (location = 0) out vec4 out_color; +DrawCmdData GetCmdData(in int idx) { + return DrawCmds[idx]; +} +bool ChechClipRect(in vec4 clipRect, in vec2 pos) { + const vec2 clipMin = clipRect.xy; + const vec2 clipMax = clipRect.zw; + return pos.x < clipMin.x || pos.x > clipMax.x || + pos.y < clipMin.y || pos.y > clipMax.y; +} +vec4 SampleImage(in int idx, in vec2 uv) { + if (idx == 0) { + return texture(CanvasImage0, uv).rgba; + } + if (idx == 1) { + return texture(CanvasImage1, uv).rgba; + } + if (idx == 2) { + return texture(CanvasImage2, uv).rgba; + } + if (idx == 4) { + return texture(CanvasImage3, uv).rgba; + } + return vec4(1,1,1,1); +} +void main() { + const InoutAttributes attributes = ReadInoutAttributes(); + const DrawCmdData cmdData = GetCmdData(attributes.primitiveId); + const vec2 pos = attributes.worldPos.xy; + const vec4 clipRect = cmdData.ClipRect; + const int textureIdx = cmdData.TextureIdx; + if (ChechClipRect(clipRect, pos)) { + discard; + } + vec4 color = SampleImage(textureIdx, attributes.uv[0]) * attributes.col[0]; + #ifdef OUT_SRGB + color.rgb = ColorSrgbToLinear(color.rgb, InverseGamma); + #endif + out_color = color; +} + +)"; +} diff --git a/engine/shaders/generated/auto_canvas_gl410_vert.hpp b/engine/shaders/generated/auto_canvas_gl410_vert.hpp new file mode 100644 index 000000000..0b1e20f72 --- /dev/null +++ b/engine/shaders/generated/auto_canvas_gl410_vert.hpp @@ -0,0 +1,370 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify + +#pragma once + +#include "core/string_id.hpp" +#include "core/string_utf.hpp" +#include "core/string_utils.hpp" +#include "gfx/gfx_defs.hpp" +#include "math/mat.hpp" +#include "math/vec.hpp" + +namespace wmoge { + + static const char source_canvas_gl410_vert[] = R"( +struct DrawCmdData{ +vec4 Transform0; +vec4 Transform1; +vec4 Transform2; +vec4 ClipRect; +int TextureIdx; +int _dc_pad0; +int _dc_pad1; +int _dc_pad2; +}; + +#define MAX_CANVAS_IMAGES (4) + +uniform sampler2D CanvasImage0; + +uniform sampler2D CanvasImage1; + +uniform sampler2D CanvasImage2; + +uniform sampler2D CanvasImage3; + +layout (std140) uniform Params { +mat4 ClipProjView; +float InverseGamma; +float _pr_pad0; +float _pr_pad1; +float _pr_pad2; +}; + +layout (std430) readonly buffer DrawCmdsData { +DrawCmdData DrawCmds[]; +}; + + +#define TARGET_VULKAN +#if defined(TARGET_VULKAN) +#define LAYOUT_LOCATION(idx) layout(location = idx) +#else +#define LAYOUT_LOCATION(idx) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) +#else +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) +#else +#define LAYOUT_SAMPLER(set_idx, binding_idx) +#endif +vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { + return pow(color, vec3(gamma)); +} +vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { + return pow(color, vec3(inverse_gamma)); +} +vec2 UnpackUv(in vec2 uv) { + #ifdef TARGET_VULKAN + return vec2(uv.x, 1.0f - uv.y); + #else + return uv; + #endif +} +mat4 GetIdentity4x4() { + mat4 matrix = mat4( + vec4(1,0,0,0), + vec4(0,1,0,0), + vec4(0,0,1,0), + vec4(0,0,0,1)); + + return matrix; +} +vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { + return (localToWorld * vec4(posLocal, 1.0f)).xyz; +} +vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { + return (normalMatrix * vec4(normLocal, 0.0f)).xyz; +} +struct VertexAttributes { + vec3 pos3; + vec2 pos2; + vec3 norm; + vec3 tang; + ivec4 boneIds; + vec4 boneWeigths; + vec4 col[4]; + vec2 uv[4]; + int primitiveId; +}; +VertexAttributes GetVertexAttributesDefault() { + VertexAttributes attributes; + attributes.pos3 = vec3(0,0,0); + attributes.pos2 = vec2(0,0); + attributes.norm = vec3(0,0,0); + attributes.tang = vec3(0,0,0); + attributes.boneIds = ivec4(0,0,0,0); + attributes.boneWeigths = vec4(0,0,0,0); + attributes.col[0] = vec4(0,0,0,0); + attributes.col[1] = vec4(0,0,0,0); + attributes.col[2] = vec4(0,0,0,0); + attributes.col[3] = vec4(0,0,0,0); + attributes.uv[0] = vec2(0,0); + attributes.uv[1] = vec2(0,0); + attributes.uv[2] = vec2(0,0); + attributes.uv[3] = vec2(0,0); + attributes.primitiveId = -1; + + return attributes; +} +VertexAttributes ReadVertexAttributes() { + VertexAttributes attributes = GetVertexAttributesDefault(); + #ifdef ATTRIB_Pos3f + attributes.pos3 = inPos3f; + #endif + #ifdef ATTRIB_Pos2f + attributes.pos2 = inPos2f; + #endif + #ifdef ATTRIB_Norm3f + attributes.norm = inNorm3f; + #endif + #ifdef ATTRIB_Tang3f + attributes.tang = inTang3f; + #endif + #ifdef ATTRIB_BoneIds4i + attributes.boneIds = inBoneIds4i; + #endif + #ifdef ATTRIB_BoneWeights4f + attributes.boneWeigths = inBoneWeights4f; + #endif + #ifdef ATTRIB_Col04f + attributes.col[0] = inCol04f; + #endif + #ifdef ATTRIB_Col14f + attributes.col[1] = inCol14f; + #endif + #ifdef ATTRIB_Col24f + attributes.col[2] = inCol24f; + #endif + #ifdef ATTRIB_Col34f + attributes.col[3] = inCol34f; + #endif + #ifdef ATTRIB_Uv02f + attributes.uv[0] = inUv02f; + #endif + #ifdef ATTRIB_Uv12f + attributes.uv[1] = inUv12f; + #endif + #ifdef ATTRIB_Uv22f + attributes.uv[2] = inUv22f; + #endif + #ifdef ATTRIB_Uv32f + attributes.uv[3] = inUv32f; + #endif + #ifdef ATTRIB_PrimitiveIdi + attributes.primitiveId = inPrimitiveIdi; + #endif + return attributes; +} +#ifdef VERTEX_SHADER + #define INOUT out +#endif +#ifdef FRAGMENT_SHADER + #define INOUT in +#endif +#ifndef INOUT + #error "Must be defined" +#endif +#if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + LAYOUT_LOCATION( 0) INOUT vec3 inout_worldPos; +#endif +#ifdef ATTRIB_Norm3f + LAYOUT_LOCATION( 1) INOUT vec3 inout_worldNorm; +#endif +#ifdef ATTRIB_Tang3f + LAYOUT_LOCATION( 2) INOUT vec3 inout_worldTang; +#endif +#ifdef ATTRIB_Col04f + LAYOUT_LOCATION( 3) INOUT vec4 inout_col0; +#endif +#ifdef ATTRIB_Col14f + LAYOUT_LOCATION( 4) INOUT vec4 inout_col1; +#endif +#ifdef ATTRIB_Col24f + LAYOUT_LOCATION( 5) INOUT vec4 inout_col2; +#endif +#ifdef ATTRIB_Col34f + LAYOUT_LOCATION( 6) INOUT vec4 inout_col3; +#endif +#ifdef ATTRIB_Uv02f + LAYOUT_LOCATION( 7) INOUT vec2 inout_uv0; +#endif +#ifdef ATTRIB_Uv12f + LAYOUT_LOCATION( 8) INOUT vec2 inout_uv1; +#endif +#ifdef ATTRIB_Uv22f + LAYOUT_LOCATION( 9) INOUT vec2 inout_uv2; +#endif +#ifdef ATTRIB_Uv32f + LAYOUT_LOCATION(10) INOUT vec2 inout_uv3; +#endif +#ifdef ATTRIB_PrimitiveIdi + LAYOUT_LOCATION(11) flat INOUT int inout_primitiveId; +#endif +struct InoutAttributes { + vec3 worldPos; + vec3 worldNorm; + vec3 worldTang; + vec4 col[4]; + vec2 uv[4]; + int primitiveId; +}; +#ifdef VERTEX_SHADER +void StoreInoutAttributes(in InoutAttributes attributes) { + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + inout_worldPos = attributes.worldPos; + #endif + #ifdef ATTRIB_Norm3f + inout_worldNorm = attributes.worldNorm; + #endif + #ifdef ATTRIB_Tang3f + inout_worldTang = attributes.worldTang; + #endif + #ifdef ATTRIB_Col04f + inout_col0 = attributes.col[0]; + #endif + #ifdef ATTRIB_Col14f + inout_col1 = attributes.col[1]; + #endif + #ifdef ATTRIB_Col24f + inout_col2 = attributes.col[2]; + #endif + #ifdef ATTRIB_Col34f + inout_col3 = attributes.col[3]; + #endif + #ifdef ATTRIB_Uv02f + inout_uv0 = attributes.uv[0]; + #endif + #ifdef ATTRIB_Uv12f + inout_uv1 = attributes.uv[1]; + #endif + #ifdef ATTRIB_Uv22f + inout_uv2 = attributes.uv[2]; + #endif + #ifdef ATTRIB_Uv32f + inout_uv3 = attributes.uv[3]; + #endif + #ifdef ATTRIB_PrimitiveIdi + inout_primitiveId = attributes.primitiveId; + #endif +} +#endif//VERTEX_SHADER +#ifdef FRAGMENT_SHADER +InoutAttributes ReadInoutAttributes() { + InoutAttributes attributes; + attributes.worldPos = vec3(0,0,0); + attributes.worldNorm = vec3(0,0,0); + attributes.worldTang = vec3(0,0,0); + attributes.col[0] = vec4(0,0,0,0); + attributes.col[1] = vec4(0,0,0,0); + attributes.col[2] = vec4(0,0,0,0); + attributes.col[3] = vec4(0,0,0,0); + attributes.uv[0] = vec2(0,0); + attributes.uv[1] = vec2(0,0); + attributes.uv[2] = vec2(0,0); + attributes.uv[3] = vec2(0,0); + attributes.primitiveId = -1; + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + attributes.worldPos = inout_worldPos; + #endif + #ifdef ATTRIB_Norm3f + attributes.worldNorm = inout_worldNorm; + #endif + #ifdef ATTRIB_Tang3f + attributes.worldTang = inout_worldTang; + #endif + #ifdef ATTRIB_Col04f + attributes.col[0] = inout_col0; + #endif + #ifdef ATTRIB_Col14f + attributes.col[1] = inout_col1; + #endif + #ifdef ATTRIB_Col24f + attributes.col[2] = inout_col2; + #endif + #ifdef ATTRIB_Col34f + attributes.col[3] = inout_col3; + #endif + #ifdef ATTRIB_Uv02f + attributes.uv[0] = inout_uv0; + #endif + #ifdef ATTRIB_Uv12f + attributes.uv[1] = inout_uv1; + #endif + #ifdef ATTRIB_Uv22f + attributes.uv[2] = inout_uv2; + #endif + #ifdef ATTRIB_Uv32f + attributes.uv[3] = inout_uv3; + #endif + #ifdef ATTRIB_PrimitiveIdi + attributes.primitiveId = inout_primitiveId; + #endif + return attributes; +} +#endif//FRAGMENT_SHADER +DrawCmdData GetCmdData(in int idx) { + return DrawCmds[idx]; +} +mat3 GetDrawCmdTransform(in int idx) { + const DrawCmdData data = GetCmdData(idx); + return mat3(data.Transform0.xyz, + data.Transform1.xyz, + data.Transform2.xyz); +} +void main() { + const VertexAttributes vertex = ReadVertexAttributes(); + const mat3 transform = GetDrawCmdTransform(vertex.primitiveId); + + InoutAttributes result; + result.worldPos = transform * vec3(vertex.pos2, 1.0f); + result.col[0] = vertex.col[0]; + result.uv[0] = UnpackUv(vertex.uv[0]); + result.primitiveId = vertex.primitiveId; + StoreInoutAttributes(result); + gl_Position = ClipProjView * vec4(result.worldPos, 1.0f); +} + +)"; +} diff --git a/engine/shaders/generated/auto_aux_draw_canvas_pass.hpp b/engine/shaders/generated/auto_canvas_pass.hpp similarity index 56% rename from engine/shaders/generated/auto_aux_draw_canvas_pass.hpp rename to engine/shaders/generated/auto_canvas_pass.hpp index 3e4dfcf32..fd61292bd 100644 --- a/engine/shaders/generated/auto_aux_draw_canvas_pass.hpp +++ b/engine/shaders/generated/auto_canvas_pass.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -37,59 +37,83 @@ #include "math/vec.hpp" #include "render/shader_pass.hpp" -#include "auto_aux_draw_canvas_gl410_frag.hpp" -#include "auto_aux_draw_canvas_gl410_vert.hpp" -#include "auto_aux_draw_canvas_vk450_frag.hpp" -#include "auto_aux_draw_canvas_vk450_vert.hpp" +#include "auto_canvas_gl410_frag.hpp" +#include "auto_canvas_gl410_vert.hpp" +#include "auto_canvas_vk450_frag.hpp" +#include "auto_canvas_vk450_vert.hpp" namespace wmoge { - /** @brief Auto generated pass for 'aux_draw_canvas' shader */ - class ShaderPassAuxDrawCanvas final : public ShaderPass { + /** @brief Auto generated pass for 'canvas' shader */ + class ShaderPassCanvas final : public ShaderPass { public: - ShaderPassAuxDrawCanvas() = default; - ~ShaderPassAuxDrawCanvas() override = default; - StringId get_name() override { return SID("aux_draw_canvas"); } + ShaderPassCanvas() = default; + ~ShaderPassCanvas() override = default; + StringId get_name() override { return SID("canvas"); } void fill_layout(GfxDescSetLayoutDescs& layouts_desc, Shader* shader) override { // fill set num = 0 { - auto& layout = layouts_desc.emplace_back(); - auto& binding_Params = layout.emplace_back(); - binding_Params.name = SID("Params"); - binding_Params.binding = 0; - binding_Params.count = 1; - binding_Params.type = GfxBindingType::UniformBuffer; - auto& binding_Texture = layout.emplace_back(); - binding_Texture.name = SID("Texture"); - binding_Texture.binding = 1; - binding_Texture.count = 1; - binding_Texture.type = GfxBindingType::SampledTexture; + auto& layout = layouts_desc.emplace_back(); + auto& binding_Params = layout.emplace_back(); + binding_Params.name = SID("Params"); + binding_Params.binding = 0; + binding_Params.count = 1; + binding_Params.type = GfxBindingType::UniformBuffer; + auto& binding_DrawCmdsData = layout.emplace_back(); + binding_DrawCmdsData.name = SID("DrawCmdsData"); + binding_DrawCmdsData.binding = 1; + binding_DrawCmdsData.count = 1; + binding_DrawCmdsData.type = GfxBindingType::StorageBuffer; + } + // fill set num = 1 + { + auto& layout = layouts_desc.emplace_back(); + auto& binding_CanvasImage0 = layout.emplace_back(); + binding_CanvasImage0.name = SID("CanvasImage0"); + binding_CanvasImage0.binding = 0; + binding_CanvasImage0.count = 1; + binding_CanvasImage0.type = GfxBindingType::SampledTexture; + auto& binding_CanvasImage1 = layout.emplace_back(); + binding_CanvasImage1.name = SID("CanvasImage1"); + binding_CanvasImage1.binding = 1; + binding_CanvasImage1.count = 1; + binding_CanvasImage1.type = GfxBindingType::SampledTexture; + auto& binding_CanvasImage2 = layout.emplace_back(); + binding_CanvasImage2.name = SID("CanvasImage2"); + binding_CanvasImage2.binding = 2; + binding_CanvasImage2.count = 1; + binding_CanvasImage2.type = GfxBindingType::SampledTexture; + auto& binding_CanvasImage3 = layout.emplace_back(); + binding_CanvasImage3.name = SID("CanvasImage3"); + binding_CanvasImage3.binding = 3; + binding_CanvasImage3.count = 1; + binding_CanvasImage3.type = GfxBindingType::SampledTexture; } } Status reload_sources(const std::string& folder, FileSystem* file_system) override { // lang is vk450 { - const auto file_path = folder + '/' + "auto_aux_draw_canvas_vk450_vert.glsl"; + const auto file_path = folder + '/' + "auto_canvas_vk450_vert.glsl"; if (file_system->read_file(file_path, m_vertex[0])) { WG_LOG_INFO("reload shader from file " << file_path); } } // lang is gl410 { - const auto file_path = folder + '/' + "auto_aux_draw_canvas_gl410_vert.glsl"; + const auto file_path = folder + '/' + "auto_canvas_gl410_vert.glsl"; if (file_system->read_file(file_path, m_vertex[1])) { WG_LOG_INFO("reload shader from file " << file_path); } } // lang is vk450 { - const auto file_path = folder + '/' + "auto_aux_draw_canvas_vk450_frag.glsl"; + const auto file_path = folder + '/' + "auto_canvas_vk450_frag.glsl"; if (file_system->read_file(file_path, m_fragment[0])) { WG_LOG_INFO("reload shader from file " << file_path); } } // lang is gl410 { - const auto file_path = folder + '/' + "auto_aux_draw_canvas_gl410_frag.glsl"; + const auto file_path = folder + '/' + "auto_canvas_gl410_frag.glsl"; if (file_system->read_file(file_path, m_fragment[1])) { WG_LOG_INFO("reload shader from file " << file_path); } @@ -97,9 +121,9 @@ namespace wmoge { return StatusCode::Ok; } const std::string& get_vertex(GfxShaderLang lang) override { return m_vertex[int(lang)]; } - std::string m_vertex[2] = {source_aux_draw_canvas_vk450_vert, source_aux_draw_canvas_gl410_vert}; + std::string m_vertex[2] = {source_canvas_vk450_vert, source_canvas_gl410_vert}; const std::string& get_fragment(GfxShaderLang lang) override { return m_fragment[int(lang)]; } - std::string m_fragment[2] = {source_aux_draw_canvas_vk450_frag, source_aux_draw_canvas_gl410_frag}; + std::string m_fragment[2] = {source_canvas_vk450_frag, source_canvas_gl410_frag}; const std::string& get_compute(GfxShaderLang lang) override { return m_compute[int(lang)]; } std::string m_compute[2]; }; diff --git a/engine/shaders/generated/auto_aux_draw_canvas_reflection.hpp b/engine/shaders/generated/auto_canvas_reflection.hpp similarity index 53% rename from engine/shaders/generated/auto_aux_draw_canvas_reflection.hpp rename to engine/shaders/generated/auto_canvas_reflection.hpp index ad77bf5fc..4aa51dd6f 100644 --- a/engine/shaders/generated/auto_aux_draw_canvas_reflection.hpp +++ b/engine/shaders/generated/auto_canvas_reflection.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -38,30 +38,69 @@ namespace wmoge { - /** @brief Auto generated reflection for 'aux_draw_canvas' shader */ - struct ShaderAuxDrawCanvas { - static constexpr const char NAME[] = "aux_draw_canvas"; - static constexpr const char CLS[] = "AuxDrawCanvas"; + /** @brief Auto generated reflection for 'canvas' shader */ + struct ShaderCanvas { + static constexpr const char NAME[] = "canvas"; + static constexpr const char CLS[] = "Canvas"; static constexpr int NUM_FILES = 2; - static constexpr int NUM_CONSTS = 0; - static constexpr int NUM_SAMPLERS = 1; - static constexpr int NUM_BUFFERS = 1; + static constexpr int NUM_CONSTS = 1; + static constexpr int NUM_SAMPLERS = 4; + static constexpr int NUM_BUFFERS = 2; - static constexpr const int TEXTURE_SET = 0; - static constexpr const int TEXTURE_SLOT = 1; - static constexpr const auto TEXTURE_LOC = GfxLocation{0, 1}; - static constexpr const char TEXTURE_NAME[] = "Texture"; + struct DrawCmdData { + Vec4f Transform0; + Vec4f Transform1; + Vec4f Transform2; + Vec4f ClipRect; + int TextureIdx; + int _dc_pad0; + int _dc_pad1; + int _dc_pad2; + }; + + static constexpr const auto MAX_CANVAS_IMAGES = 4; + + static constexpr const int CANVASIMAGE0_SET = 1; + static constexpr const int CANVASIMAGE0_SLOT = 0; + static constexpr const auto CANVASIMAGE0_LOC = GfxLocation{1, 0}; + static constexpr const char CANVASIMAGE0_NAME[] = "CanvasImage0"; + + static constexpr const int CANVASIMAGE1_SET = 1; + static constexpr const int CANVASIMAGE1_SLOT = 1; + static constexpr const auto CANVASIMAGE1_LOC = GfxLocation{1, 1}; + static constexpr const char CANVASIMAGE1_NAME[] = "CanvasImage1"; + + static constexpr const int CANVASIMAGE2_SET = 1; + static constexpr const int CANVASIMAGE2_SLOT = 2; + static constexpr const auto CANVASIMAGE2_LOC = GfxLocation{1, 2}; + static constexpr const char CANVASIMAGE2_NAME[] = "CanvasImage2"; + + static constexpr const int CANVASIMAGE3_SET = 1; + static constexpr const int CANVASIMAGE3_SLOT = 3; + static constexpr const auto CANVASIMAGE3_LOC = GfxLocation{1, 3}; + static constexpr const char CANVASIMAGE3_NAME[] = "CanvasImage3"; struct Params { - Mat4x4f clip_proj_screen; - float gamma; - float inverse_gamma; + Mat4x4f ClipProjView; + float InverseGamma; + float _pr_pad0; + float _pr_pad1; + float _pr_pad2; }; static constexpr const int PARAMS_SET = 0; static constexpr const int PARAMS_SLOT = 0; static constexpr const auto PARAMS_LOC = GfxLocation{0, 0}; static constexpr const char PARAMS_NAME[] = "Params"; + + struct DrawCmdsData { + /* struct DrawCmdData DrawCmds[ UNBOUND ]; */ + }; + + static constexpr const int DRAWCMDSDATA_SET = 0; + static constexpr const int DRAWCMDSDATA_SLOT = 1; + static constexpr const auto DRAWCMDSDATA_LOC = GfxLocation{0, 1}; + static constexpr const char DRAWCMDSDATA_NAME[] = "DrawCmdsData"; }; }// namespace wmoge diff --git a/engine/shaders/generated/auto_canvas_vk450_frag.hpp b/engine/shaders/generated/auto_canvas_vk450_frag.hpp new file mode 100644 index 000000000..1d2560026 --- /dev/null +++ b/engine/shaders/generated/auto_canvas_vk450_frag.hpp @@ -0,0 +1,309 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify + +#pragma once + +#include "core/string_id.hpp" +#include "core/string_utf.hpp" +#include "core/string_utils.hpp" +#include "gfx/gfx_defs.hpp" +#include "math/mat.hpp" +#include "math/vec.hpp" + +namespace wmoge { + + static const char source_canvas_vk450_frag[] = R"( +struct DrawCmdData{ +vec4 Transform0; +vec4 Transform1; +vec4 Transform2; +vec4 ClipRect; +int TextureIdx; +int _dc_pad0; +int _dc_pad1; +int _dc_pad2; +}; + +#define MAX_CANVAS_IMAGES (4) + +layout (set = 1, binding = 0) uniform sampler2D CanvasImage0; + +layout (set = 1, binding = 1) uniform sampler2D CanvasImage1; + +layout (set = 1, binding = 2) uniform sampler2D CanvasImage2; + +layout (set = 1, binding = 3) uniform sampler2D CanvasImage3; + +layout (set = 0, binding = 0, std140) uniform Params { +mat4 ClipProjView; +float InverseGamma; +float _pr_pad0; +float _pr_pad1; +float _pr_pad2; +}; + +layout (set = 0, binding = 1, std430) readonly buffer DrawCmdsData { +DrawCmdData DrawCmds[]; +}; + + +#define TARGET_VULKAN +#if defined(TARGET_VULKAN) +#define LAYOUT_LOCATION(idx) layout(location = idx) +#else +#define LAYOUT_LOCATION(idx) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) +#else +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) +#else +#define LAYOUT_SAMPLER(set_idx, binding_idx) +#endif +vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { + return pow(color, vec3(gamma)); +} +vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { + return pow(color, vec3(inverse_gamma)); +} +vec2 UnpackUv(in vec2 uv) { + #ifdef TARGET_VULKAN + return vec2(uv.x, 1.0f - uv.y); + #else + return uv; + #endif +} +mat4 GetIdentity4x4() { + mat4 matrix = mat4( + vec4(1,0,0,0), + vec4(0,1,0,0), + vec4(0,0,1,0), + vec4(0,0,0,1)); + + return matrix; +} +vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { + return (localToWorld * vec4(posLocal, 1.0f)).xyz; +} +vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { + return (normalMatrix * vec4(normLocal, 0.0f)).xyz; +} +#ifdef VERTEX_SHADER + #define INOUT out +#endif +#ifdef FRAGMENT_SHADER + #define INOUT in +#endif +#ifndef INOUT + #error "Must be defined" +#endif +#if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + LAYOUT_LOCATION( 0) INOUT vec3 inout_worldPos; +#endif +#ifdef ATTRIB_Norm3f + LAYOUT_LOCATION( 1) INOUT vec3 inout_worldNorm; +#endif +#ifdef ATTRIB_Tang3f + LAYOUT_LOCATION( 2) INOUT vec3 inout_worldTang; +#endif +#ifdef ATTRIB_Col04f + LAYOUT_LOCATION( 3) INOUT vec4 inout_col0; +#endif +#ifdef ATTRIB_Col14f + LAYOUT_LOCATION( 4) INOUT vec4 inout_col1; +#endif +#ifdef ATTRIB_Col24f + LAYOUT_LOCATION( 5) INOUT vec4 inout_col2; +#endif +#ifdef ATTRIB_Col34f + LAYOUT_LOCATION( 6) INOUT vec4 inout_col3; +#endif +#ifdef ATTRIB_Uv02f + LAYOUT_LOCATION( 7) INOUT vec2 inout_uv0; +#endif +#ifdef ATTRIB_Uv12f + LAYOUT_LOCATION( 8) INOUT vec2 inout_uv1; +#endif +#ifdef ATTRIB_Uv22f + LAYOUT_LOCATION( 9) INOUT vec2 inout_uv2; +#endif +#ifdef ATTRIB_Uv32f + LAYOUT_LOCATION(10) INOUT vec2 inout_uv3; +#endif +#ifdef ATTRIB_PrimitiveIdi + LAYOUT_LOCATION(11) flat INOUT int inout_primitiveId; +#endif +struct InoutAttributes { + vec3 worldPos; + vec3 worldNorm; + vec3 worldTang; + vec4 col[4]; + vec2 uv[4]; + int primitiveId; +}; +#ifdef VERTEX_SHADER +void StoreInoutAttributes(in InoutAttributes attributes) { + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + inout_worldPos = attributes.worldPos; + #endif + #ifdef ATTRIB_Norm3f + inout_worldNorm = attributes.worldNorm; + #endif + #ifdef ATTRIB_Tang3f + inout_worldTang = attributes.worldTang; + #endif + #ifdef ATTRIB_Col04f + inout_col0 = attributes.col[0]; + #endif + #ifdef ATTRIB_Col14f + inout_col1 = attributes.col[1]; + #endif + #ifdef ATTRIB_Col24f + inout_col2 = attributes.col[2]; + #endif + #ifdef ATTRIB_Col34f + inout_col3 = attributes.col[3]; + #endif + #ifdef ATTRIB_Uv02f + inout_uv0 = attributes.uv[0]; + #endif + #ifdef ATTRIB_Uv12f + inout_uv1 = attributes.uv[1]; + #endif + #ifdef ATTRIB_Uv22f + inout_uv2 = attributes.uv[2]; + #endif + #ifdef ATTRIB_Uv32f + inout_uv3 = attributes.uv[3]; + #endif + #ifdef ATTRIB_PrimitiveIdi + inout_primitiveId = attributes.primitiveId; + #endif +} +#endif//VERTEX_SHADER +#ifdef FRAGMENT_SHADER +InoutAttributes ReadInoutAttributes() { + InoutAttributes attributes; + attributes.worldPos = vec3(0,0,0); + attributes.worldNorm = vec3(0,0,0); + attributes.worldTang = vec3(0,0,0); + attributes.col[0] = vec4(0,0,0,0); + attributes.col[1] = vec4(0,0,0,0); + attributes.col[2] = vec4(0,0,0,0); + attributes.col[3] = vec4(0,0,0,0); + attributes.uv[0] = vec2(0,0); + attributes.uv[1] = vec2(0,0); + attributes.uv[2] = vec2(0,0); + attributes.uv[3] = vec2(0,0); + attributes.primitiveId = -1; + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + attributes.worldPos = inout_worldPos; + #endif + #ifdef ATTRIB_Norm3f + attributes.worldNorm = inout_worldNorm; + #endif + #ifdef ATTRIB_Tang3f + attributes.worldTang = inout_worldTang; + #endif + #ifdef ATTRIB_Col04f + attributes.col[0] = inout_col0; + #endif + #ifdef ATTRIB_Col14f + attributes.col[1] = inout_col1; + #endif + #ifdef ATTRIB_Col24f + attributes.col[2] = inout_col2; + #endif + #ifdef ATTRIB_Col34f + attributes.col[3] = inout_col3; + #endif + #ifdef ATTRIB_Uv02f + attributes.uv[0] = inout_uv0; + #endif + #ifdef ATTRIB_Uv12f + attributes.uv[1] = inout_uv1; + #endif + #ifdef ATTRIB_Uv22f + attributes.uv[2] = inout_uv2; + #endif + #ifdef ATTRIB_Uv32f + attributes.uv[3] = inout_uv3; + #endif + #ifdef ATTRIB_PrimitiveIdi + attributes.primitiveId = inout_primitiveId; + #endif + return attributes; +} +#endif//FRAGMENT_SHADER +layout (location = 0) out vec4 out_color; +DrawCmdData GetCmdData(in int idx) { + return DrawCmds[idx]; +} +bool ChechClipRect(in vec4 clipRect, in vec2 pos) { + const vec2 clipMin = clipRect.xy; + const vec2 clipMax = clipRect.zw; + return pos.x < clipMin.x || pos.x > clipMax.x || + pos.y < clipMin.y || pos.y > clipMax.y; +} +vec4 SampleImage(in int idx, in vec2 uv) { + if (idx == 0) { + return texture(CanvasImage0, uv).rgba; + } + if (idx == 1) { + return texture(CanvasImage1, uv).rgba; + } + if (idx == 2) { + return texture(CanvasImage2, uv).rgba; + } + if (idx == 4) { + return texture(CanvasImage3, uv).rgba; + } + return vec4(1,1,1,1); +} +void main() { + const InoutAttributes attributes = ReadInoutAttributes(); + const DrawCmdData cmdData = GetCmdData(attributes.primitiveId); + const vec2 pos = attributes.worldPos.xy; + const vec4 clipRect = cmdData.ClipRect; + const int textureIdx = cmdData.TextureIdx; + if (ChechClipRect(clipRect, pos)) { + discard; + } + vec4 color = SampleImage(textureIdx, attributes.uv[0]) * attributes.col[0]; + #ifdef OUT_SRGB + color.rgb = ColorSrgbToLinear(color.rgb, InverseGamma); + #endif + out_color = color; +} + +)"; +} diff --git a/engine/shaders/generated/auto_canvas_vk450_vert.hpp b/engine/shaders/generated/auto_canvas_vk450_vert.hpp new file mode 100644 index 000000000..31fa2de9a --- /dev/null +++ b/engine/shaders/generated/auto_canvas_vk450_vert.hpp @@ -0,0 +1,370 @@ +/**********************************************************************************/ +/* Wmoge game engine */ +/* Available at github https://github.com/EgorOrachyov/wmoge */ +/**********************************************************************************/ +/* MIT License */ +/* */ +/* Copyright (c) 2023 Egor Orachyov */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining a copy */ +/* of this software and associated documentation files (the "Software"), to deal */ +/* in the Software without restriction, including without limitation the rights */ +/* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell */ +/* copies of the Software, and to permit persons to whom the Software is */ +/* furnished to do so, subject to the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be included in all */ +/* copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR */ +/* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, */ +/* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE */ +/* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER */ +/* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, */ +/* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE */ +/* SOFTWARE. */ +/**********************************************************************************/ + +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify + +#pragma once + +#include "core/string_id.hpp" +#include "core/string_utf.hpp" +#include "core/string_utils.hpp" +#include "gfx/gfx_defs.hpp" +#include "math/mat.hpp" +#include "math/vec.hpp" + +namespace wmoge { + + static const char source_canvas_vk450_vert[] = R"( +struct DrawCmdData{ +vec4 Transform0; +vec4 Transform1; +vec4 Transform2; +vec4 ClipRect; +int TextureIdx; +int _dc_pad0; +int _dc_pad1; +int _dc_pad2; +}; + +#define MAX_CANVAS_IMAGES (4) + +layout (set = 1, binding = 0) uniform sampler2D CanvasImage0; + +layout (set = 1, binding = 1) uniform sampler2D CanvasImage1; + +layout (set = 1, binding = 2) uniform sampler2D CanvasImage2; + +layout (set = 1, binding = 3) uniform sampler2D CanvasImage3; + +layout (set = 0, binding = 0, std140) uniform Params { +mat4 ClipProjView; +float InverseGamma; +float _pr_pad0; +float _pr_pad1; +float _pr_pad2; +}; + +layout (set = 0, binding = 1, std430) readonly buffer DrawCmdsData { +DrawCmdData DrawCmds[]; +}; + + +#define TARGET_VULKAN +#if defined(TARGET_VULKAN) +#define LAYOUT_LOCATION(idx) layout(location = idx) +#else +#define LAYOUT_LOCATION(idx) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(set = set_idx, binding = binding_idx, fields_layout) +#else +#define LAYOUT_BUFFER(set_idx, binding_idx, fields_layout) layout(fields_layout) +#endif +#if defined(TARGET_VULKAN) +#define LAYOUT_SAMPLER(set_idx, binding_idx) layout(set = set_idx, binding = binding_idx) +#else +#define LAYOUT_SAMPLER(set_idx, binding_idx) +#endif +vec3 ColorSrgbToLinear(in vec3 color, in float gamma) { + return pow(color, vec3(gamma)); +} +vec3 ColorLinearToSrgb(in vec3 color, in float inverse_gamma) { + return pow(color, vec3(inverse_gamma)); +} +vec2 UnpackUv(in vec2 uv) { + #ifdef TARGET_VULKAN + return vec2(uv.x, 1.0f - uv.y); + #else + return uv; + #endif +} +mat4 GetIdentity4x4() { + mat4 matrix = mat4( + vec4(1,0,0,0), + vec4(0,1,0,0), + vec4(0,0,1,0), + vec4(0,0,0,1)); + + return matrix; +} +vec3 TransformLocalToWorld(in vec3 posLocal, in mat4 localToWorld) { + return (localToWorld * vec4(posLocal, 1.0f)).xyz; +} +vec3 TransformLocalToWorldNormal(in vec3 normLocal, in mat4 normalMatrix) { + return (normalMatrix * vec4(normLocal, 0.0f)).xyz; +} +struct VertexAttributes { + vec3 pos3; + vec2 pos2; + vec3 norm; + vec3 tang; + ivec4 boneIds; + vec4 boneWeigths; + vec4 col[4]; + vec2 uv[4]; + int primitiveId; +}; +VertexAttributes GetVertexAttributesDefault() { + VertexAttributes attributes; + attributes.pos3 = vec3(0,0,0); + attributes.pos2 = vec2(0,0); + attributes.norm = vec3(0,0,0); + attributes.tang = vec3(0,0,0); + attributes.boneIds = ivec4(0,0,0,0); + attributes.boneWeigths = vec4(0,0,0,0); + attributes.col[0] = vec4(0,0,0,0); + attributes.col[1] = vec4(0,0,0,0); + attributes.col[2] = vec4(0,0,0,0); + attributes.col[3] = vec4(0,0,0,0); + attributes.uv[0] = vec2(0,0); + attributes.uv[1] = vec2(0,0); + attributes.uv[2] = vec2(0,0); + attributes.uv[3] = vec2(0,0); + attributes.primitiveId = -1; + + return attributes; +} +VertexAttributes ReadVertexAttributes() { + VertexAttributes attributes = GetVertexAttributesDefault(); + #ifdef ATTRIB_Pos3f + attributes.pos3 = inPos3f; + #endif + #ifdef ATTRIB_Pos2f + attributes.pos2 = inPos2f; + #endif + #ifdef ATTRIB_Norm3f + attributes.norm = inNorm3f; + #endif + #ifdef ATTRIB_Tang3f + attributes.tang = inTang3f; + #endif + #ifdef ATTRIB_BoneIds4i + attributes.boneIds = inBoneIds4i; + #endif + #ifdef ATTRIB_BoneWeights4f + attributes.boneWeigths = inBoneWeights4f; + #endif + #ifdef ATTRIB_Col04f + attributes.col[0] = inCol04f; + #endif + #ifdef ATTRIB_Col14f + attributes.col[1] = inCol14f; + #endif + #ifdef ATTRIB_Col24f + attributes.col[2] = inCol24f; + #endif + #ifdef ATTRIB_Col34f + attributes.col[3] = inCol34f; + #endif + #ifdef ATTRIB_Uv02f + attributes.uv[0] = inUv02f; + #endif + #ifdef ATTRIB_Uv12f + attributes.uv[1] = inUv12f; + #endif + #ifdef ATTRIB_Uv22f + attributes.uv[2] = inUv22f; + #endif + #ifdef ATTRIB_Uv32f + attributes.uv[3] = inUv32f; + #endif + #ifdef ATTRIB_PrimitiveIdi + attributes.primitiveId = inPrimitiveIdi; + #endif + return attributes; +} +#ifdef VERTEX_SHADER + #define INOUT out +#endif +#ifdef FRAGMENT_SHADER + #define INOUT in +#endif +#ifndef INOUT + #error "Must be defined" +#endif +#if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + LAYOUT_LOCATION( 0) INOUT vec3 inout_worldPos; +#endif +#ifdef ATTRIB_Norm3f + LAYOUT_LOCATION( 1) INOUT vec3 inout_worldNorm; +#endif +#ifdef ATTRIB_Tang3f + LAYOUT_LOCATION( 2) INOUT vec3 inout_worldTang; +#endif +#ifdef ATTRIB_Col04f + LAYOUT_LOCATION( 3) INOUT vec4 inout_col0; +#endif +#ifdef ATTRIB_Col14f + LAYOUT_LOCATION( 4) INOUT vec4 inout_col1; +#endif +#ifdef ATTRIB_Col24f + LAYOUT_LOCATION( 5) INOUT vec4 inout_col2; +#endif +#ifdef ATTRIB_Col34f + LAYOUT_LOCATION( 6) INOUT vec4 inout_col3; +#endif +#ifdef ATTRIB_Uv02f + LAYOUT_LOCATION( 7) INOUT vec2 inout_uv0; +#endif +#ifdef ATTRIB_Uv12f + LAYOUT_LOCATION( 8) INOUT vec2 inout_uv1; +#endif +#ifdef ATTRIB_Uv22f + LAYOUT_LOCATION( 9) INOUT vec2 inout_uv2; +#endif +#ifdef ATTRIB_Uv32f + LAYOUT_LOCATION(10) INOUT vec2 inout_uv3; +#endif +#ifdef ATTRIB_PrimitiveIdi + LAYOUT_LOCATION(11) flat INOUT int inout_primitiveId; +#endif +struct InoutAttributes { + vec3 worldPos; + vec3 worldNorm; + vec3 worldTang; + vec4 col[4]; + vec2 uv[4]; + int primitiveId; +}; +#ifdef VERTEX_SHADER +void StoreInoutAttributes(in InoutAttributes attributes) { + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + inout_worldPos = attributes.worldPos; + #endif + #ifdef ATTRIB_Norm3f + inout_worldNorm = attributes.worldNorm; + #endif + #ifdef ATTRIB_Tang3f + inout_worldTang = attributes.worldTang; + #endif + #ifdef ATTRIB_Col04f + inout_col0 = attributes.col[0]; + #endif + #ifdef ATTRIB_Col14f + inout_col1 = attributes.col[1]; + #endif + #ifdef ATTRIB_Col24f + inout_col2 = attributes.col[2]; + #endif + #ifdef ATTRIB_Col34f + inout_col3 = attributes.col[3]; + #endif + #ifdef ATTRIB_Uv02f + inout_uv0 = attributes.uv[0]; + #endif + #ifdef ATTRIB_Uv12f + inout_uv1 = attributes.uv[1]; + #endif + #ifdef ATTRIB_Uv22f + inout_uv2 = attributes.uv[2]; + #endif + #ifdef ATTRIB_Uv32f + inout_uv3 = attributes.uv[3]; + #endif + #ifdef ATTRIB_PrimitiveIdi + inout_primitiveId = attributes.primitiveId; + #endif +} +#endif//VERTEX_SHADER +#ifdef FRAGMENT_SHADER +InoutAttributes ReadInoutAttributes() { + InoutAttributes attributes; + attributes.worldPos = vec3(0,0,0); + attributes.worldNorm = vec3(0,0,0); + attributes.worldTang = vec3(0,0,0); + attributes.col[0] = vec4(0,0,0,0); + attributes.col[1] = vec4(0,0,0,0); + attributes.col[2] = vec4(0,0,0,0); + attributes.col[3] = vec4(0,0,0,0); + attributes.uv[0] = vec2(0,0); + attributes.uv[1] = vec2(0,0); + attributes.uv[2] = vec2(0,0); + attributes.uv[3] = vec2(0,0); + attributes.primitiveId = -1; + #if defined(ATTRIB_Pos3f) || defined(ATTRIB_Pos2f) + attributes.worldPos = inout_worldPos; + #endif + #ifdef ATTRIB_Norm3f + attributes.worldNorm = inout_worldNorm; + #endif + #ifdef ATTRIB_Tang3f + attributes.worldTang = inout_worldTang; + #endif + #ifdef ATTRIB_Col04f + attributes.col[0] = inout_col0; + #endif + #ifdef ATTRIB_Col14f + attributes.col[1] = inout_col1; + #endif + #ifdef ATTRIB_Col24f + attributes.col[2] = inout_col2; + #endif + #ifdef ATTRIB_Col34f + attributes.col[3] = inout_col3; + #endif + #ifdef ATTRIB_Uv02f + attributes.uv[0] = inout_uv0; + #endif + #ifdef ATTRIB_Uv12f + attributes.uv[1] = inout_uv1; + #endif + #ifdef ATTRIB_Uv22f + attributes.uv[2] = inout_uv2; + #endif + #ifdef ATTRIB_Uv32f + attributes.uv[3] = inout_uv3; + #endif + #ifdef ATTRIB_PrimitiveIdi + attributes.primitiveId = inout_primitiveId; + #endif + return attributes; +} +#endif//FRAGMENT_SHADER +DrawCmdData GetCmdData(in int idx) { + return DrawCmds[idx]; +} +mat3 GetDrawCmdTransform(in int idx) { + const DrawCmdData data = GetCmdData(idx); + return mat3(data.Transform0.xyz, + data.Transform1.xyz, + data.Transform2.xyz); +} +void main() { + const VertexAttributes vertex = ReadVertexAttributes(); + const mat3 transform = GetDrawCmdTransform(vertex.primitiveId); + + InoutAttributes result; + result.worldPos = transform * vec3(vertex.pos2, 1.0f); + result.col[0] = vertex.col[0]; + result.uv[0] = UnpackUv(vertex.uv[0]); + result.primitiveId = vertex.primitiveId; + StoreInoutAttributes(result); + gl_Position = ClipProjView * vec4(result.worldPos, 1.0f); +} + +)"; +} diff --git a/engine/shaders/generated/auto_material_gl410_frag.hpp b/engine/shaders/generated/auto_material_gl410_frag.hpp index e9edd66c4..a17cecf21 100644 --- a/engine/shaders/generated/auto_material_gl410_frag.hpp +++ b/engine/shaders/generated/auto_material_gl410_frag.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -43,8 +43,6 @@ namespace wmoge { struct RenderObjectData{ mat4 LocalToWorld; mat4 LocalToWorldPrev; -mat4 WorldToLocal; -mat4 WorldToLocalPrev; mat4 NormalMatrix; vec4 AabbPos; vec4 AabbSizeHalf; @@ -281,8 +279,6 @@ RenderObjectData GetRenderObjectDataDefault() { RenderObjectData data; data.LocalToWorld = GetIdentity4x4(); data.LocalToWorldPrev = GetIdentity4x4(); - data.WorldToLocal = GetIdentity4x4(); - data.WorldToLocalPrev = GetIdentity4x4(); data.NormalMatrix = GetIdentity4x4(); data.AabbPos = vec4(0,0,0,0); data.AabbSizeHalf = vec4(0,0,0,0); diff --git a/engine/shaders/generated/auto_material_gl410_vert.hpp b/engine/shaders/generated/auto_material_gl410_vert.hpp index cf7710110..cad86e25c 100644 --- a/engine/shaders/generated/auto_material_gl410_vert.hpp +++ b/engine/shaders/generated/auto_material_gl410_vert.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -43,8 +43,6 @@ namespace wmoge { struct RenderObjectData{ mat4 LocalToWorld; mat4 LocalToWorldPrev; -mat4 WorldToLocal; -mat4 WorldToLocalPrev; mat4 NormalMatrix; vec4 AabbPos; vec4 AabbSizeHalf; @@ -361,8 +359,6 @@ RenderObjectData GetRenderObjectDataDefault() { RenderObjectData data; data.LocalToWorld = GetIdentity4x4(); data.LocalToWorldPrev = GetIdentity4x4(); - data.WorldToLocal = GetIdentity4x4(); - data.WorldToLocalPrev = GetIdentity4x4(); data.NormalMatrix = GetIdentity4x4(); data.AabbPos = vec4(0,0,0,0); data.AabbSizeHalf = vec4(0,0,0,0); diff --git a/engine/shaders/generated/auto_material_pass.hpp b/engine/shaders/generated/auto_material_pass.hpp index c51a93032..7abfd37d2 100644 --- a/engine/shaders/generated/auto_material_pass.hpp +++ b/engine/shaders/generated/auto_material_pass.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_material_reflection.hpp b/engine/shaders/generated/auto_material_reflection.hpp index 4b9f0317c..97836831c 100644 --- a/engine/shaders/generated/auto_material_reflection.hpp +++ b/engine/shaders/generated/auto_material_reflection.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -50,8 +50,6 @@ namespace wmoge { struct RenderObjectData { Mat4x4f LocalToWorld; Mat4x4f LocalToWorldPrev; - Mat4x4f WorldToLocal; - Mat4x4f WorldToLocalPrev; Mat4x4f NormalMatrix; Vec4f AabbPos; Vec4f AabbSizeHalf; diff --git a/engine/shaders/generated/auto_material_vk450_frag.hpp b/engine/shaders/generated/auto_material_vk450_frag.hpp index 3870c7e26..e7c49445a 100644 --- a/engine/shaders/generated/auto_material_vk450_frag.hpp +++ b/engine/shaders/generated/auto_material_vk450_frag.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -43,8 +43,6 @@ namespace wmoge { struct RenderObjectData{ mat4 LocalToWorld; mat4 LocalToWorldPrev; -mat4 WorldToLocal; -mat4 WorldToLocalPrev; mat4 NormalMatrix; vec4 AabbPos; vec4 AabbSizeHalf; @@ -281,8 +279,6 @@ RenderObjectData GetRenderObjectDataDefault() { RenderObjectData data; data.LocalToWorld = GetIdentity4x4(); data.LocalToWorldPrev = GetIdentity4x4(); - data.WorldToLocal = GetIdentity4x4(); - data.WorldToLocalPrev = GetIdentity4x4(); data.NormalMatrix = GetIdentity4x4(); data.AabbPos = vec4(0,0,0,0); data.AabbSizeHalf = vec4(0,0,0,0); diff --git a/engine/shaders/generated/auto_material_vk450_vert.hpp b/engine/shaders/generated/auto_material_vk450_vert.hpp index fa27169c4..fa8ddee09 100644 --- a/engine/shaders/generated/auto_material_vk450_vert.hpp +++ b/engine/shaders/generated/auto_material_vk450_vert.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once @@ -43,8 +43,6 @@ namespace wmoge { struct RenderObjectData{ mat4 LocalToWorld; mat4 LocalToWorldPrev; -mat4 WorldToLocal; -mat4 WorldToLocalPrev; mat4 NormalMatrix; vec4 AabbPos; vec4 AabbSizeHalf; @@ -361,8 +359,6 @@ RenderObjectData GetRenderObjectDataDefault() { RenderObjectData data; data.LocalToWorld = GetIdentity4x4(); data.LocalToWorldPrev = GetIdentity4x4(); - data.WorldToLocal = GetIdentity4x4(); - data.WorldToLocalPrev = GetIdentity4x4(); data.NormalMatrix = GetIdentity4x4(); data.AabbPos = vec4(0,0,0,0); data.AabbSizeHalf = vec4(0,0,0,0); diff --git a/engine/shaders/generated/auto_text_gl410_frag.hpp b/engine/shaders/generated/auto_text_gl410_frag.hpp index b3a9a4b7c..606e432c4 100644 --- a/engine/shaders/generated/auto_text_gl410_frag.hpp +++ b/engine/shaders/generated/auto_text_gl410_frag.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_text_gl410_vert.hpp b/engine/shaders/generated/auto_text_gl410_vert.hpp index c2ac5f3a7..b9a7df918 100644 --- a/engine/shaders/generated/auto_text_gl410_vert.hpp +++ b/engine/shaders/generated/auto_text_gl410_vert.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_text_pass.hpp b/engine/shaders/generated/auto_text_pass.hpp index 72e949bc9..9684a7e7c 100644 --- a/engine/shaders/generated/auto_text_pass.hpp +++ b/engine/shaders/generated/auto_text_pass.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_text_reflection.hpp b/engine/shaders/generated/auto_text_reflection.hpp index 463978b32..bf19a6811 100644 --- a/engine/shaders/generated/auto_text_reflection.hpp +++ b/engine/shaders/generated/auto_text_reflection.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_text_vk450_frag.hpp b/engine/shaders/generated/auto_text_vk450_frag.hpp index ef7f7cce3..6e4656438 100644 --- a/engine/shaders/generated/auto_text_vk450_frag.hpp +++ b/engine/shaders/generated/auto_text_vk450_frag.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/generated/auto_text_vk450_vert.hpp b/engine/shaders/generated/auto_text_vk450_vert.hpp index 59dd0fe16..4cd25f701 100644 --- a/engine/shaders/generated/auto_text_vk450_vert.hpp +++ b/engine/shaders/generated/auto_text_vk450_vert.hpp @@ -25,7 +25,7 @@ /* SOFTWARE. */ /**********************************************************************************/ -// Autogenerated file by 'generator.py' on 2023-10-18 00:59:10.319027, do not modify +// Autogenerated file by 'generator.py' on 2023-10-28 01:42:02.611456, do not modify #pragma once diff --git a/engine/shaders/scene_data.glsl b/engine/shaders/scene_data.glsl index 77e37d7bf..840f5ee17 100644 --- a/engine/shaders/scene_data.glsl +++ b/engine/shaders/scene_data.glsl @@ -13,8 +13,6 @@ RenderObjectData GetRenderObjectDataDefault() { RenderObjectData data; data.LocalToWorld = GetIdentity4x4(); data.LocalToWorldPrev = GetIdentity4x4(); - data.WorldToLocal = GetIdentity4x4(); - data.WorldToLocalPrev = GetIdentity4x4(); data.NormalMatrix = GetIdentity4x4(); data.AabbPos = vec4(0,0,0,0); data.AabbSizeHalf = vec4(0,0,0,0); diff --git a/engine/shaders/scripts/aux_draw_canvas.py b/engine/shaders/scripts/aux_draw_canvas.py deleted file mode 100644 index 8e01da16f..000000000 --- a/engine/shaders/scripts/aux_draw_canvas.py +++ /dev/null @@ -1,24 +0,0 @@ -from reflection import * - -BINDINGS = BindingAllocator() - -SHADER = Shader( - name="aux_draw_canvas", - cls="AuxDrawCanvas", - constants=[], - structs=[], - buffers=[ - UniformBuffer( - "Params", - "std140", - BINDINGS.next(), - [ - StructField(TYPE_MAT4, "clip_proj_screen"), - StructField(TYPE_FLOAT, "gamma"), - StructField(TYPE_FLOAT, "inverse_gamma"), - ], - ) - ], - samplers=[Sampler2d("Texture", BINDINGS.next())], - files=["aux_draw_canvas.vert", "aux_draw_canvas.frag"], -) diff --git a/engine/shaders/scripts/canvas.py b/engine/shaders/scripts/canvas.py new file mode 100644 index 000000000..a61062439 --- /dev/null +++ b/engine/shaders/scripts/canvas.py @@ -0,0 +1,54 @@ +from reflection import * + +BINDINGS = BindingAllocator() + +Params = [ + StructField(TYPE_MAT4, "ClipProjView"), + StructField(TYPE_FLOAT, "InverseGamma"), + StructField(TYPE_FLOAT, "_pr_pad0"), + StructField(TYPE_FLOAT, "_pr_pad1"), + StructField(TYPE_FLOAT, "_pr_pad2"), +] + +DrawCmdData = Struct( + "DrawCmdData", + [ + StructField(TYPE_VEC4, "Transform0"), + StructField(TYPE_VEC4, "Transform1"), + StructField(TYPE_VEC4, "Transform2"), + StructField(TYPE_VEC4, "ClipRect"), + StructField(TYPE_INT, "TextureIdx"), + StructField(TYPE_INT, "_dc_pad0"), + StructField(TYPE_INT, "_dc_pad1"), + StructField(TYPE_INT, "_dc_pad2"), + ], +) + +SHADER = Shader( + name="canvas", + cls="Canvas", + constants=[Constant("MAX_CANVAS_IMAGES", "4")], + structs=[DrawCmdData], + buffers=[ + UniformBuffer( + "Params", + "std140", + BINDINGS.next(0), + Params, + ), + StorageBuffer( + "DrawCmdsData", + "std430", + BINDINGS.next(0), + [StructField(DrawCmdData, "DrawCmds", ArrayQualifier())], + readonly=True, + ), + ], + samplers=[ + Sampler2d("CanvasImage0", BINDINGS.next(1)), + Sampler2d("CanvasImage1", BINDINGS.next(1)), + Sampler2d("CanvasImage2", BINDINGS.next(1)), + Sampler2d("CanvasImage3", BINDINGS.next(1)), + ], + files=["canvas.vert", "canvas.frag"], +) diff --git a/engine/shaders/scripts/material.py b/engine/shaders/scripts/material.py index d8d878cfb..3ed825cfe 100644 --- a/engine/shaders/scripts/material.py +++ b/engine/shaders/scripts/material.py @@ -36,8 +36,6 @@ [ StructField(TYPE_MAT4, "LocalToWorld"), StructField(TYPE_MAT4, "LocalToWorldPrev"), - StructField(TYPE_MAT4, "WorldToLocal"), - StructField(TYPE_MAT4, "WorldToLocalPrev"), StructField(TYPE_MAT4, "NormalMatrix"), StructField(TYPE_VEC4, "AabbPos"), StructField(TYPE_VEC4, "AabbSizeHalf"), @@ -69,7 +67,7 @@ StorageBuffer( "RenderObjectsData", "std430", - BINDINGS.next(0), + BINDINGS.next(), [StructField(RenderObjectData, "RenderObjects", ArrayQualifier())], readonly=True, ), diff --git a/engine/shaders/scripts/shaders.py b/engine/shaders/scripts/shaders.py index 6738fa162..7d68c1e3f 100644 --- a/engine/shaders/scripts/shaders.py +++ b/engine/shaders/scripts/shaders.py @@ -1,11 +1,11 @@ -import aux_draw_canvas import base import text import material +import canvas SHADERS_LIST = [ - aux_draw_canvas.SHADER, base.SHADER, text.SHADER, material.SHADER, + canvas.SHADER, ] diff --git a/engine/systems/system_render.hpp b/engine/systems/system_render.hpp index be39ae4a1..f5320a156 100644 --- a/engine/systems/system_render.hpp +++ b/engine/systems/system_render.hpp @@ -98,8 +98,6 @@ namespace wmoge { if (result.cam_mask.any()) { mesh_static.mesh->procces_visibility(result.cam_mask, result.distance); } - - render_scene->get_objects_vis()[mesh_static.primitive_id] = result.cam_mask; } void process_batch(class EcsWorld& world, EcsArchStorage& storage, int start_entity, int count) override {