From 8aae71d17c3927af76fae980cd0f04f93c628abd Mon Sep 17 00:00:00 2001 From: Stanislaw Halik Date: Wed, 26 Oct 2022 03:51:18 +0200 Subject: a --- main/draw.cpp | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 main/draw.cpp (limited to 'main/draw.cpp') diff --git a/main/draw.cpp b/main/draw.cpp new file mode 100644 index 00000000..f1d4e4d8 --- /dev/null +++ b/main/draw.cpp @@ -0,0 +1,139 @@ +#include "main-impl.hpp" +#include "floormat/app.hpp" +#include "src/camera-offset.hpp" +#include + +namespace floormat { + +void main_impl::recalc_viewport(Vector2i size) noexcept +{ + update_window_state(); + GL::defaultFramebuffer.setViewport({{}, size }); + _msaa_framebuffer.detach(GL::Framebuffer::ColorAttachment{0}); + _msaa_renderbuffer = Magnum::GL::Renderbuffer{}; + _msaa_renderbuffer.setStorageMultisample(s.msaa_samples, GL::RenderbufferFormat::RGBA8, size); + _msaa_framebuffer.setViewport({{}, size }); + _msaa_framebuffer.attachRenderbuffer(GL::Framebuffer::ColorAttachment{0}, _msaa_renderbuffer); + _shader.set_scale(Vector2{size}); + app.on_viewport_event(size); +} + +global_coords main_impl::pixel_to_tile(Vector2d position) const noexcept +{ + constexpr Vector2d pixel_size{dTILE_SIZE[0], dTILE_SIZE[1]}; + constexpr Vector2d half{.5, .5}; + const Vector2d px = position - Vector2d{windowSize()}*.5 - _shader.camera_offset()*.5; + const Vector2d vec = tile_shader::unproject(px) / pixel_size + half; + const auto x = (std::int32_t)std::floor(vec[0]), y = (std::int32_t)std::floor(vec[1]); + return { x, y }; +} + +auto main_impl::get_draw_bounds() const noexcept -> draw_bounds +{ + + using limits = std::numeric_limits; + auto x0 = limits::max(), x1 = limits::min(), y0 = limits::max(), y1 = limits::min(); + + for (const auto win = Vector2d(windowSize()); + auto p : {pixel_to_tile(Vector2d{0, 0}).chunk(), + pixel_to_tile(Vector2d{win[0]-1, 0}).chunk(), + pixel_to_tile(Vector2d{0, win[1]-1}).chunk(), + pixel_to_tile(Vector2d{win[0]-1, win[1]-1}).chunk()}) + { + x0 = std::min(x0, p.x); + x1 = std::max(x1, p.x); + y0 = std::min(y0, p.y); + y1 = std::max(y1, p.y); + } + return {x0, x1, y0, y1}; +} + +void main_impl::draw_world() noexcept +{ + auto [minx, maxx, miny, maxy] = get_draw_bounds(); + + for (std::int16_t y = miny; y <= maxy; y++) + for (std::int16_t x = minx; x <= maxx; x++) + { + if (const chunk_coords c = {x, y}; !_world.contains(c)) + app.maybe_initialize_chunk(c, _world[c]); + const chunk_coords c{x, y}; + const with_shifted_camera_offset o{_shader, c}; + _floor_mesh.draw(_shader, _world[c]); + } + + for (std::int16_t y = miny; y <= maxy; y++) + for (std::int16_t x = minx; x <= maxx; x++) + { + const chunk_coords c{x, y}; + const with_shifted_camera_offset o{_shader, c}; + _wall_mesh.draw(_shader, _world[c]); + } +} + +void main_impl::drawEvent() +{ + float dt = timeline.previousFrameDuration(); + if (dt > 0) + { + const float RC1 = dt_expected.do_sleep ? 1.f : 1.f/15, + RC2 = dt_expected.do_sleep ? 1.f/15 : 1.f/60; + const float alpha1 = dt/(dt + RC1); + const float alpha2 = dt/(dt + RC2); + + _frame_time1 = _frame_time1*(1-alpha1) + alpha1*dt; + _frame_time2 = _frame_time1*(1-alpha2) + alpha2*dt; + constexpr float max_deviation = 5 * 1e-3f; + if (std::fabs(_frame_time1 - _frame_time2) > max_deviation) + _frame_time1 = _frame_time2; + } + else + { + swapBuffers(); + timeline.nextFrame(); + } + + dt = std::clamp(dt, 1e-5f, std::fmaxf(1e-1f, dt_expected.value)); + + app.update(dt); + _shader.set_tint({1, 1, 1, 1}); + + { + GL::defaultFramebuffer.clear(GL::FramebufferClear::Color); +#ifndef FM_SKIP_MSAA + _msaa_framebuffer.clear(GL::FramebufferClear::Color); + _msaa_framebuffer.bind(); +#endif + draw_world(); + app.draw_msaa(); +#ifndef FM_SKIP_MSAA + GL::defaultFramebuffer.bind(); + GL::Framebuffer::blit(_msaa_framebuffer, GL::defaultFramebuffer, {{}, windowSize()}, GL::FramebufferBlit::Color); +#endif + } + + app.draw(); + + swapBuffers(); + redraw(); + + if (dt_expected.do_sleep) + { + constexpr float eps = 1e-3f; + const float Δt൦ = timeline.currentFrameDuration(), sleep_secs = dt_expected.value - Δt൦ - dt_expected.jitter; + if (sleep_secs > eps) + std::this_thread::sleep_for(std::chrono::nanoseconds((long long)(sleep_secs * 1e9f))); + //fm_debug("jitter:%.1f sleep:%.0f", dt_expected.jitter*1000, sleep_secs*1000); + const float Δt = timeline.currentFrameDuration() - dt_expected.value; + constexpr float α = .1f; + dt_expected.jitter = std::fmax(dt_expected.jitter + Δt * α, + dt_expected.jitter * (1-α) + Δt * α); + dt_expected.jitter = std::copysignf(std::fminf(dt_expected.value, std::fabsf(dt_expected.jitter)), dt_expected.jitter); + } + else + dt_expected.jitter = 0; + timeline.nextFrame(); +} + +} // namespace floormat + -- cgit v1.2.3