diff options
-rw-r--r-- | editor/app.cpp | 1 | ||||
-rw-r--r-- | editor/app.hpp | 4 | ||||
-rw-r--r-- | editor/imgui.cpp | 42 | ||||
-rw-r--r-- | floormat/main.hpp | 3 | ||||
-rw-r--r-- | main/draw.cpp | 16 | ||||
-rw-r--r-- | main/main-impl.cpp | 1 | ||||
-rw-r--r-- | main/main-impl.hpp | 5 | ||||
-rw-r--r-- | main/setup.cpp | 2 | ||||
-rw-r--r-- | shaders/lightmap.cpp | 61 |
9 files changed, 105 insertions, 30 deletions
diff --git a/editor/app.cpp b/editor/app.cpp index f988f230..fa1c9b76 100644 --- a/editor/app.cpp +++ b/editor/app.cpp @@ -78,6 +78,7 @@ void app::reset_world(struct world&& w_) _editor.on_release(); _editor.clear_selection(); kill_popups(true); + _tested_light = 0; clear_keys(); const auto pixel = cursor.pixel; diff --git a/editor/app.hpp b/editor/app.hpp index b739d34c..37cdcccf 100644 --- a/editor/app.hpp +++ b/editor/app.hpp @@ -114,6 +114,8 @@ private: void draw_collision_boxes(); void draw_clickables(); void draw_light_info(); + void draw_lightmap_test(); + void draw_editor_pane(float main_menu_height); void draw_inspector(); bool check_inspector_exists(const popup_target& p); @@ -159,6 +161,8 @@ private: cursor_state cursor; popup_target _popup_target; + object_id _tested_light = 0; + int8_t _z_level = 0; bool _pending_popup : 1 = false; diff --git a/editor/imgui.cpp b/editor/imgui.cpp index df75501a..5b02d134 100644 --- a/editor/imgui.cpp +++ b/editor/imgui.cpp @@ -4,6 +4,7 @@ #include "src/world.hpp" #include "src/anim-atlas.hpp" #include "shaders/shader.hpp" +#include "shaders/lightmap.hpp" #include "main/clickable.hpp" #include "imgui-raii.hpp" #include "src/light.hpp" @@ -109,6 +110,8 @@ void app::draw_ui() draw_clickables(); if (_render_vobjs) draw_light_info(); + if (_tested_light) + draw_lightmap_test(); const float main_menu_height = draw_main_menu(); [[maybe_unused]] auto font = font_saver{ctx.FontSize*dpi}; @@ -197,6 +200,41 @@ void app::draw_light_info() } } +void app::draw_lightmap_test() +{ + fm_debug_assert(_tested_light != 0); + + ImGui::SetNextWindowSize({1024, 1024}); + + auto& w = M->world(); + auto L = w.find_entity(_tested_light); + + constexpr auto flags = + ImGuiWindowFlags_NoTitleBar | + ImGuiWindowFlags_NoResize | + ImGuiWindowFlags_NoMove | + ImGuiWindowFlags_NoScrollbar; + + if (L && ImGui::Begin("Lightmap", nullptr, flags)) + { + fm_assert(L->type() == entity_type::light); + auto& shader = M->lightmap_shader(); + light_s light { + .center = {8 * 64, 8 * 64}, + .dist = 4, + .color = {255, 255, 255}, + .falloff = light_falloff::linear, + }; + shader.begin({0, 0}, light); + shader.end(); + M->bind(); + ImGui::Image(&shader.texture(), {1024, 1024}); + ImGui::End(); + } + else + _tested_light = 0; +} + static constexpr auto SCENERY_POPUP_NAME = "##scenery-popup"_s; bool app::check_inspector_exists(const popup_target& p) @@ -244,6 +282,10 @@ void app::do_popup_menu() if (bool b_ins = !check_inspector_exists(_popup_target); ImGui::MenuItem("Inspect", nullptr, !b_ins, b_ins)) inspectors.push_back(std::exchange(_popup_target, {})); + if (bool b_testing = e.id == _tested_light; + e.type() == entity_type::light) + if (ImGui::MenuItem("Test", nullptr, b_testing)) + _tested_light = e.id; ImGui::SeparatorText("Modify"); if (auto next_rot = e.atlas->next_rotation_from(e.r); ImGui::MenuItem("Rotate", nullptr, false, next_rot != e.r && e.can_rotate(next_rot))) diff --git a/floormat/main.hpp b/floormat/main.hpp index 95f90610..b80d92ce 100644 --- a/floormat/main.hpp +++ b/floormat/main.hpp @@ -13,6 +13,7 @@ namespace floormat { struct fm_settings; struct floormat_app; struct tile_shader; +struct lightmap_shader; struct world; struct scenery; struct anim_atlas; @@ -44,7 +45,9 @@ struct floormat_main virtual Magnum::Math::Vector2<int> window_size() const noexcept; virtual tile_shader& shader() noexcept = 0; + virtual struct lightmap_shader& lightmap_shader() noexcept = 0; virtual const tile_shader& shader() const noexcept = 0; + virtual void bind() noexcept = 0; constexpr float smoothed_dt() const noexcept { return _frame_time; } virtual fm_settings& settings() noexcept = 0; virtual const fm_settings& settings() const noexcept = 0; diff --git a/main/draw.cpp b/main/draw.cpp index 322f4f66..40e438c6 100644 --- a/main/draw.cpp +++ b/main/draw.cpp @@ -222,20 +222,22 @@ void main_impl::do_update() app.update(dt); } +void main_impl::bind() noexcept +{ + framebuffer.fb.bind(); +} + void main_impl::drawEvent() { _shader.set_tint({1, 1, 1, 1}); - { - const auto clear_color = 0x222222ff_rgbaf; + const auto clear_color = 0x222222ff_rgbaf; #ifdef FM_USE_DEPTH32 - framebuffer.fb.clearColor(0, clear_color); + framebuffer.fb.clearColor(0, clear_color); #else - GL::defaultFramebuffer.clearColor(clear_color); + GL::defaultFramebuffer.clearColor(clear_color); #endif - draw_world(); - GL::Renderer::disable(GL::Renderer::Feature::DepthTest); - } + draw_world(); app.draw(); GL::Renderer::flush(); diff --git a/main/main-impl.cpp b/main/main-impl.cpp index c774e589..de9fb45b 100644 --- a/main/main-impl.cpp +++ b/main/main-impl.cpp @@ -21,6 +21,7 @@ fm_settings& main_impl::settings() noexcept { return s; } const fm_settings& main_impl::settings() const noexcept { return s; } tile_shader& main_impl::shader() noexcept { return _shader; } const tile_shader& main_impl::shader() const noexcept { return _shader; } +struct lightmap_shader& main_impl::lightmap_shader() noexcept { return _lightmap_shader; } bool main_impl::is_text_input_active() const noexcept { return const_cast<main_impl&>(*this).isTextInputActive(); } void main_impl::start_text_input() noexcept { startTextInput(); } void main_impl::stop_text_input() noexcept { stopTextInput(); } diff --git a/main/main-impl.hpp b/main/main-impl.hpp index f5dc5010..97640d15 100644 --- a/main/main-impl.hpp +++ b/main/main-impl.hpp @@ -49,6 +49,8 @@ struct main_impl final : Platform::Sdl2Application, floormat_main tile_shader& shader() noexcept override; const tile_shader& shader() const noexcept override; + struct lightmap_shader& lightmap_shader() noexcept override; + struct world& world() noexcept override; struct world& reset_world() noexcept override; struct world& reset_world(struct world&& w) noexcept override; @@ -78,6 +80,7 @@ struct main_impl final : Platform::Sdl2Application, floormat_main [[maybe_unused]] void anyEvent(SDL_Event& event) override; void drawEvent() override; + void bind() noexcept override; void do_update(); void update_window_state(); struct meshes meshes() noexcept override; @@ -96,7 +99,7 @@ private: [[maybe_unused]] char _dummy = (register_debug_callback(), '\0'); floormat_app& app; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) tile_shader _shader; - lightmap_shader _lightmap_shader; + struct lightmap_shader _lightmap_shader; std::vector<clickable> _clickable_scenery; struct world _world{}; Magnum::Timeline timeline; diff --git a/main/setup.cpp b/main/setup.cpp index 569e43bb..93f3b943 100644 --- a/main/setup.cpp +++ b/main/setup.cpp @@ -56,7 +56,9 @@ auto main_impl::make_gl_conf(const fm_settings&) -> GLConfiguration flags |= GLConfiguration::Flag::ForwardCompatible; return GLConfiguration{} .setFlags(flags) +#ifdef FM_USE_DEPTH32 .setDepthBufferSize(0) +#endif .setColorBufferSize({8, 8, 8, 0}) .setStencilBufferSize(0); } diff --git a/shaders/lightmap.cpp b/shaders/lightmap.cpp index 8e8e1884..a599cfc9 100644 --- a/shaders/lightmap.cpp +++ b/shaders/lightmap.cpp @@ -31,7 +31,7 @@ auto lightmap_shader::make_framebuffer() -> Framebuffer framebuffer.fb = GL::Framebuffer{{ {}, image_size }}; framebuffer.color = GL::Texture2D{}; - framebuffer.color.setStorage(1, GL::TextureFormat::RGBA8, image_size); + framebuffer.color.setStorage(1, GL::TextureFormat::RGB8, image_size); //framebuffer.depth = GL::Renderbuffer{}; //framebuffer.depth.setStorage(GL::RenderbufferFormat::DepthComponent32F, fb_size); @@ -80,18 +80,17 @@ lightmap_shader::lightmap_shader() : void lightmap_shader::flush_vertexes() { - // todo -} - -void lightmap_shader::clear() -{ - framebuffer.fb.clearColor(0, Color4{1.f, 0.f, 1.f, 1.f}); - //framebuffer.fb.clearDepth(0); -} - -void lightmap_shader::bind() -{ - framebuffer.fb.bind(); + if (_count > 0) + { + _index_buf.setSubData(0, ArrayView<std::array<UnsignedShort, 6>>{_indexes, 1}); + _vertex_buf.setSubData(0, ArrayView<std::array<Vector2, 4>>{_quads, 1}); + + GL::MeshView mesh{_mesh}; + mesh.setCount((int)(6 * _count)); + mesh.setIndexRange(0, 0, (uint32_t)(_count * 6 - 1)); + AbstractShaderProgram::draw(mesh); + _count = 0; + } } std::array<UnsignedShort, 6> lightmap_shader::quad_indexes(size_t N) @@ -106,40 +105,51 @@ std::array<UnsignedShort, 6> lightmap_shader::quad_indexes(size_t N) void lightmap_shader::add_light(Vector2i neighbor_offset, const light_s& light) { fm_debug_assert(_count == 0); + fm_debug_assert(_quads.size() > 0); constexpr auto tile_size = TILE_SIZE2.sum()/2; constexpr auto scale = 2/chunk_size; auto dist = std::fmax(0.f, light.dist * tile_size); + auto dist_clip = dist * tile_size; auto center = light.center + chunk_offset + Vector2(neighbor_offset)*chunk_size; auto center_clip = Vector2{center} * scale; // clip coordinate constexpr auto image_size_factor = Vector2(image_size) / Vector2(chunk_size); auto center_fragcoord = center * image_size_factor; // window-relative coordinates - _indexes[0] = quad_indexes(0); - _quads[0] = std::array<Vector2, 4>{{ - { dist + center_clip.x(), -dist + center_clip.y() }, - { dist + center_clip.x(), dist + center_clip.y() }, - { -dist + center_clip.x(), -dist + center_clip.y() }, - { -dist + center_clip.x(), dist + center_clip.y() }, + _indexes[_count] = quad_indexes(0); + _quads[_count] = std::array<Vector2, 4>{{ + { dist_clip + center_clip.x(), -dist_clip + center_clip.y() }, + { dist_clip + center_clip.x(), dist_clip + center_clip.y() }, + { -dist_clip + center_clip.x(), -dist_clip + center_clip.y() }, + { -dist_clip + center_clip.x(), dist_clip + center_clip.y() }, }}; - _index_buf.setSubData(0, ArrayView<std::array<UnsignedShort, 6>>{_indexes, 1}); - _vertex_buf.setSubData(0, ArrayView<std::array<Vector2, 4>>{_quads, 1}); + _count++; setUniform(ColorIntensityUniform, Vector4{Vector3{light.color}, dist}); setUniform(CenterUniform, center_fragcoord); setUniform(FalloffUniform, (uint32_t)light.falloff); setUniform(SizeUniform, chunk_size); +} +lightmap_shader::~lightmap_shader() = default; +void lightmap_shader::clear() +{ + framebuffer.fb.clearColor(0, Color4{1.f, 0.f, 1.f, 1.f}); + //framebuffer.fb.clearDepth(0); } -lightmap_shader::~lightmap_shader() = default; +void lightmap_shader::bind() +{ + framebuffer.fb.bind(); +} void lightmap_shader::begin(Vector2i neighbor_offset, const light_s& light) { fm_assert(_count == 0); clear(); + bind(); add_light(neighbor_offset, light); } @@ -148,6 +158,13 @@ void lightmap_shader::end() flush_vertexes(); } +GL::Texture2D& lightmap_shader::texture() +{ + fm_assert(_count == 0); + fm_debug_assert(framebuffer.color.id()); + return framebuffer.color; +} + bool light_s::operator==(const light_s&) const noexcept = default; } // namespace floormat |