From cf936cbf64cf3fea4f1690e34c0938f39ba92e2c Mon Sep 17 00:00:00 2001 From: Jules Fouchy Date: Sat, 31 Aug 2024 18:28:54 +0200 Subject: [PATCH 1/5] =?UTF-8?q?=F0=9F=8E=89=20[FeedbackLoop]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cool/Exporter/ExporterU.cpp | 6 +++--- src/Cool/Exporter/ExporterU.h | 2 +- src/Cool/Exporter/VideoExportProcess.cpp | 8 ++++---- src/Cool/Exporter/VideoExportProcess.h | 4 ++-- src/Cool/Exporter/internal/Polaroid.h | 16 +++------------- src/Cool/Gpu/OpenGL/Texture.h | 2 ++ src/Cool/Gpu/OpenGL/TextureRef.cpp | 19 +++++++++++++++++++ src/Cool/Gpu/OpenGL/TextureRef.hpp | 17 +++++++++++++++++ src/Cool/Gpu/internal/RenderTarget_Base.h | 4 ++-- .../Gpu/internal/RenderTarget_ImplOpenGL.cpp | 16 +++------------- .../Gpu/internal/RenderTarget_ImplOpenGL.h | 4 ++-- src/Cool/View/RenderView.cpp | 10 +++++----- src/Cool/View/RenderView.h | 11 +++++++---- 13 files changed, 70 insertions(+), 49 deletions(-) create mode 100644 src/Cool/Gpu/OpenGL/TextureRef.cpp create mode 100644 src/Cool/Gpu/OpenGL/TextureRef.hpp diff --git a/src/Cool/Exporter/ExporterU.cpp b/src/Cool/Exporter/ExporterU.cpp index 316d2dd07..d67fae01b 100644 --- a/src/Cool/Exporter/ExporterU.cpp +++ b/src/Cool/Exporter/ExporterU.cpp @@ -5,10 +5,10 @@ namespace Cool::ExporterU { -void export_image(img::Size size, Time time, Time delta_time, Polaroid polaroid, std::filesystem::path const& file_path) +void export_image(img::Size size, Time time, Time delta_time, Polaroid const& polaroid, std::filesystem::path const& file_path) { - polaroid.render(time, delta_time, size); - ImageU::save_png(file_path, polaroid.render_target.download_pixels()); + polaroid.render(size, time, delta_time); + ImageU::save_png(file_path, polaroid.texture.download_pixels()); } } // namespace Cool::ExporterU diff --git a/src/Cool/Exporter/ExporterU.h b/src/Cool/Exporter/ExporterU.h index 80c4016cc..e2d0e5603 100644 --- a/src/Cool/Exporter/ExporterU.h +++ b/src/Cool/Exporter/ExporterU.h @@ -9,6 +9,6 @@ namespace Cool::ExporterU { * * @param file_path The name of the file that you want to create */ -void export_image(img::Size size, Time time, Time delta_time, Polaroid polaroid, std::filesystem::path const& file_path); +void export_image(img::Size size, Time time, Time delta_time, Polaroid const& polaroid, std::filesystem::path const& file_path); } // namespace Cool::ExporterU diff --git a/src/Cool/Exporter/VideoExportProcess.cpp b/src/Cool/Exporter/VideoExportProcess.cpp index fd23e3d8c..cbdcc2e4b 100644 --- a/src/Cool/Exporter/VideoExportProcess.cpp +++ b/src/Cool/Exporter/VideoExportProcess.cpp @@ -24,7 +24,7 @@ VideoExportProcess::VideoExportProcess(VideoExportParams const& params, TimeSpee _thread_pool.start(); } -bool VideoExportProcess::update(Polaroid polaroid) +bool VideoExportProcess::update(Polaroid const& polaroid) { if (_should_stop_asap || _nb_frames_which_finished_exporting.load() == _total_nb_of_frames_in_sequence) return true; // The export is finished @@ -100,13 +100,13 @@ void VideoExportProcess::imgui(std::function const& extra_widgets) extra_widgets(); } -void VideoExportProcess::export_frame(Polaroid polaroid, std::filesystem::path const& file_path) +void VideoExportProcess::export_frame(Polaroid const& polaroid, std::filesystem::path const& file_path) { - polaroid.render(_clock.time(), _clock.delta_time(), _size); + polaroid.render(_size, _clock.time(), _clock.delta_time()); _thread_pool.push_job(ImageExportJob{ file_path, - polaroid.render_target.download_pixels(), + polaroid.texture.download_pixels(), _average_export_time, _average_export_time_mutex, _nb_frames_which_finished_exporting diff --git a/src/Cool/Exporter/VideoExportProcess.h b/src/Cool/Exporter/VideoExportProcess.h index f8f98ffdb..7f5e9e4dc 100644 --- a/src/Cool/Exporter/VideoExportProcess.h +++ b/src/Cool/Exporter/VideoExportProcess.h @@ -12,7 +12,7 @@ namespace Cool { class VideoExportProcess { public: VideoExportProcess(VideoExportParams const& params, TimeSpeed time_speed, std::filesystem::path const& folder_path, img::Size size); - auto update(Polaroid polaroid) -> bool; + auto update(Polaroid const& polaroid) -> bool; void imgui(std::function const& extra_widgets); auto clock() const -> Clock const& { return _clock; } @@ -20,7 +20,7 @@ class VideoExportProcess { private: auto estimated_remaining_time() -> Time; void update_time_estimate(); - void export_frame(Polaroid polaroid, std::filesystem::path const& file_path); + void export_frame(Polaroid const& polaroid, std::filesystem::path const& file_path); private: std::filesystem::path _folder_path; diff --git a/src/Cool/Exporter/internal/Polaroid.h b/src/Cool/Exporter/internal/Polaroid.h index 66e2ec60f..d8f8805b1 100644 --- a/src/Cool/Exporter/internal/Polaroid.h +++ b/src/Cool/Exporter/internal/Polaroid.h @@ -5,20 +5,10 @@ namespace Cool { struct Polaroid { - // The target that we will render to - RenderTarget& render_target; + // The texture that we will render to + TextureRef texture; // The function that renders the desired image - std::function render_fn; - - void render(Time time, Time delta_time) - { - render_fn(render_target, time, delta_time); - } - void render(Time time, Time delta_time, img::Size size) - { - render_target.set_size(size); - render(time, delta_time); - } + std::function render; }; } // namespace Cool \ No newline at end of file diff --git a/src/Cool/Gpu/OpenGL/Texture.h b/src/Cool/Gpu/OpenGL/Texture.h index b081ed5ff..0e358371c 100644 --- a/src/Cool/Gpu/OpenGL/Texture.h +++ b/src/Cool/Gpu/OpenGL/Texture.h @@ -1,10 +1,12 @@ #if defined(COOL_OPENGL) #pragma once #include +#include "TextureRef.hpp" #include "glpp-extended/src/Texture2D.h" #include "img/src/Image.h" #include "img/src/Size.h" + namespace Cool::OpenGL { struct TextureConfig { diff --git a/src/Cool/Gpu/OpenGL/TextureRef.cpp b/src/Cool/Gpu/OpenGL/TextureRef.cpp new file mode 100644 index 000000000..2b1bf0b3f --- /dev/null +++ b/src/Cool/Gpu/OpenGL/TextureRef.cpp @@ -0,0 +1,19 @@ +#include "TextureRef.hpp" +#include "glpp/glpp.hpp" + +namespace Cool { + +auto TextureRef::download_pixels() const -> img::Image +{ + glpp::bind_texture(id); + std::unique_ptr data{new uint8_t[4 * width() * height()]}; + glReadPixels(0, 0, static_cast(width()), static_cast(height()), GL_RGBA, GL_UNSIGNED_BYTE, data.get()); + glpp::bind_texture(0); + return img::Image{ + img::Size{width(), height()}, + 4, + data.release() + }; +} + +} // namespace Cool \ No newline at end of file diff --git a/src/Cool/Gpu/OpenGL/TextureRef.hpp b/src/Cool/Gpu/OpenGL/TextureRef.hpp new file mode 100644 index 000000000..8e04d3a45 --- /dev/null +++ b/src/Cool/Gpu/OpenGL/TextureRef.hpp @@ -0,0 +1,17 @@ +#pragma once + +namespace Cool { + +struct TextureRef { + GLuint id{}; + img::Size size{}; + + auto width() const { return size.width(); } + auto height() const { return size.height(); } + + [[nodiscard]] auto imgui_texture_id() const -> ImTextureID { return reinterpret_cast(static_cast(id)); } + + auto download_pixels() const -> img::Image; +}; + +} // namespace Cool \ No newline at end of file diff --git a/src/Cool/Gpu/internal/RenderTarget_Base.h b/src/Cool/Gpu/internal/RenderTarget_Base.h index f943f0e91..1afaafbf5 100644 --- a/src/Cool/Gpu/internal/RenderTarget_Base.h +++ b/src/Cool/Gpu/internal/RenderTarget_Base.h @@ -1,7 +1,7 @@ #pragma once - #include #include "../RenderTargetInfo.h" +#include "Cool/Gpu/Texture.h" namespace Cool { @@ -9,8 +9,8 @@ template class RenderTarget_Base { public: void render(typename RenderTarget_Impl::RenderFuncType render_fn); - img::Image download_pixels() const { return _impl.download_pixels(); } ImTextureID imgui_texture_id() const { return _impl.imgui_texture_id(); } + auto texture_ref() const -> TextureRef { return _impl.texture_ref(); } RenderTargetInfo info() const { return _impl.info(); } img::Size current_size() const { return _impl.size(); } img::Size desired_size() const { return _desired_size; } diff --git a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp index 3a438ffd0..2654dbc76 100644 --- a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp +++ b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp @@ -21,7 +21,9 @@ RenderTargetInfo RenderTarget_ImplOpenGL::info() const return RenderTargetInfo{ .viewport = { .size = size(), - .bottom_left_corner = {0, 0}}}; + .bottom_left_corner = {0, 0} + } + }; } void RenderTarget_ImplOpenGL::resize(img::Size size) @@ -29,18 +31,6 @@ void RenderTarget_ImplOpenGL::resize(img::Size size) _texture.setSize(size); } -img::Image RenderTarget_ImplOpenGL::download_pixels() const -{ - _texture.bind(); - std::unique_ptr data{new uint8_t[4 * width() * height()]}; - glReadPixels(0, 0, static_cast(width()), static_cast(height()), GL_RGBA, GL_UNSIGNED_BYTE, data.get()); - _texture.unbind(); - return img::Image{ - img::Size{width(), height()}, - 4, - data.release()}; -} - } // namespace Cool #endif \ No newline at end of file diff --git a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h index feb6bcf1b..16170b513 100644 --- a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h +++ b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h @@ -1,7 +1,7 @@ #pragma once #if defined(COOL_OPENGL) - #include +#include "../OpenGL/Texture.h" #include "../OpenGL/TextureFB.h" #include "../RenderTargetInfo.h" @@ -17,8 +17,8 @@ class RenderTarget_ImplOpenGL { img::Size::DataType width() const { return _texture.width(); } img::Size::DataType height() const { return _texture.height(); } img::Size size() const { return _texture.size(); } - img::Image download_pixels() const; GLuint texture_id() const { return _texture.textureID(); } + auto texture_ref() const -> TextureRef { return TextureRef{texture_id(), size()}; } ImTextureID imgui_texture_id() const { return reinterpret_cast(static_cast(_texture.textureID())); } // Double-cast to fix a warning : first we convert to the correct size (uint32_t -> uint64_t) then from integral type to pointer type (uint64_t -> ImTextureID) void imgui_window(); diff --git a/src/Cool/View/RenderView.cpp b/src/Cool/View/RenderView.cpp index c7902fc77..71ecbde21 100644 --- a/src/Cool/View/RenderView.cpp +++ b/src/Cool/View/RenderView.cpp @@ -2,20 +2,20 @@ namespace Cool { -void RenderView::update_size(ImageSizeConstraint const& constraint) +auto RenderView::desired_image_size(ImageSizeConstraint const& constraint) const -> img::Size { if (!window_size().has_value()) - return; - _render_target.set_size(constraint.applied_to(*window_size())); + return {}; + return constraint.applied_to(*window_size()); } auto RenderView::get_image_texture_id() const -> ImTextureID { - return _render_target.imgui_texture_id(); + return _texture.imgui_texture_id(); } auto RenderView::get_image_size() const -> img::Size { - return _render_target.current_size(); + return _texture.size; } } // namespace Cool \ No newline at end of file diff --git a/src/Cool/View/RenderView.h b/src/Cool/View/RenderView.h index 8ab2d883f..28b48d0b9 100644 --- a/src/Cool/View/RenderView.h +++ b/src/Cool/View/RenderView.h @@ -11,17 +11,20 @@ class RenderView : public View { public: using View::View; - void update_size(ImageSizeConstraint const&); + void set_texture(TextureRef texture) { _texture = texture; } - auto render_target() -> RenderTarget& { return _render_target; } - auto render_target() const -> RenderTarget const& { return _render_target; } + auto desired_image_size(ImageSizeConstraint const&) const -> img::Size; + + // auto render_target() -> RenderTarget& { return _render_target; } + // auto render_target() const -> RenderTarget const& { return _render_target; } protected: auto get_image_texture_id() const -> ImTextureID override; auto get_image_size() const -> img::Size override; private: - RenderTarget _render_target; + // RenderTarget _render_target; + TextureRef _texture{}; }; } // namespace Cool From eff4b783d754fdfe9fe82710df2e8e8bcdb0e4ee Mon Sep 17 00:00:00 2001 From: Jules Fouchy Date: Sat, 31 Aug 2024 21:10:13 +0200 Subject: [PATCH 2/5] =?UTF-8?q?=F0=9F=A4=8F=20[Polaroid]=20texxture=20is?= =?UTF-8?q?=20now=20a=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cool/Exporter/ExporterU.cpp | 2 +- src/Cool/Exporter/VideoExportProcess.cpp | 2 +- src/Cool/Exporter/internal/Polaroid.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Cool/Exporter/ExporterU.cpp b/src/Cool/Exporter/ExporterU.cpp index d67fae01b..cf9c48293 100644 --- a/src/Cool/Exporter/ExporterU.cpp +++ b/src/Cool/Exporter/ExporterU.cpp @@ -8,7 +8,7 @@ namespace Cool::ExporterU { void export_image(img::Size size, Time time, Time delta_time, Polaroid const& polaroid, std::filesystem::path const& file_path) { polaroid.render(size, time, delta_time); - ImageU::save_png(file_path, polaroid.texture.download_pixels()); + ImageU::save_png(file_path, polaroid.texture().download_pixels()); } } // namespace Cool::ExporterU diff --git a/src/Cool/Exporter/VideoExportProcess.cpp b/src/Cool/Exporter/VideoExportProcess.cpp index cbdcc2e4b..9e3bb9b59 100644 --- a/src/Cool/Exporter/VideoExportProcess.cpp +++ b/src/Cool/Exporter/VideoExportProcess.cpp @@ -106,7 +106,7 @@ void VideoExportProcess::export_frame(Polaroid const& polaroid, std::filesystem: _thread_pool.push_job(ImageExportJob{ file_path, - polaroid.texture.download_pixels(), + polaroid.texture().download_pixels(), _average_export_time, _average_export_time_mutex, _nb_frames_which_finished_exporting diff --git a/src/Cool/Exporter/internal/Polaroid.h b/src/Cool/Exporter/internal/Polaroid.h index d8f8805b1..8ae10c420 100644 --- a/src/Cool/Exporter/internal/Polaroid.h +++ b/src/Cool/Exporter/internal/Polaroid.h @@ -6,7 +6,7 @@ namespace Cool { struct Polaroid { // The texture that we will render to - TextureRef texture; + std::function texture; // The function that renders the desired image std::function render; }; From 4226931694ce654291af5295e891921765a69855 Mon Sep 17 00:00:00 2001 From: Jules Fouchy Date: Sun, 1 Sep 2024 18:26:49 +0200 Subject: [PATCH 3/5] =?UTF-8?q?=F0=9F=90=9B=20[TextureRef]=20Fix=20downloa?= =?UTF-8?q?d=5Fpixels?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cool/Gpu/OpenGL/TextureRef.cpp | 16 ++++++++-- src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp | 38 +++++++++++++++++++++++ src/Cool/Gpu/OpenGL/copy_tex_pipeline.hpp | 8 +++++ 3 files changed, 59 insertions(+), 3 deletions(-) create mode 100644 src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp create mode 100644 src/Cool/Gpu/OpenGL/copy_tex_pipeline.hpp diff --git a/src/Cool/Gpu/OpenGL/TextureRef.cpp b/src/Cool/Gpu/OpenGL/TextureRef.cpp index 2b1bf0b3f..71506ba6d 100644 --- a/src/Cool/Gpu/OpenGL/TextureRef.cpp +++ b/src/Cool/Gpu/OpenGL/TextureRef.cpp @@ -1,14 +1,24 @@ #include "TextureRef.hpp" +#include "Cool/Gpu/OpenGL/copy_tex_pipeline.hpp" +#include "Cool/Gpu/RenderTarget.h" #include "glpp/glpp.hpp" namespace Cool { auto TextureRef::download_pixels() const -> img::Image { - glpp::bind_texture(id); + static auto rt = RenderTarget{}; + rt.set_size(size); std::unique_ptr data{new uint8_t[4 * width() * height()]}; - glReadPixels(0, 0, static_cast(width()), static_cast(height()), GL_RGBA, GL_UNSIGNED_BYTE, data.get()); - glpp::bind_texture(0); + rt.render([&]() { + // TODO(WebGPU) We shouldn't need to run a shader to get the texture on a framebuffer and then download its pixels + Cool::copy_tex_pipeline().shader()->bind(); + Cool::copy_tex_pipeline().shader()->set_uniform_texture("tex_to_copy", id); + glDisable(GL_BLEND); + Cool::copy_tex_pipeline().draw(); + glEnable(GL_BLEND); + glReadPixels(0, 0, static_cast(width()), static_cast(height()), GL_RGBA, GL_UNSIGNED_BYTE, data.get()); + }); return img::Image{ img::Size{width(), height()}, 4, diff --git a/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp b/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp new file mode 100644 index 000000000..daceedc65 --- /dev/null +++ b/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp @@ -0,0 +1,38 @@ +#include "copy_tex_pipeline.hpp" + +namespace Cool { + +static auto make_copy_tex_pipeline() -> Cool::OpenGL::FullscreenPipeline +{ + auto instance = Cool::OpenGL::FullscreenPipeline{}; + auto const res = instance.compile(R"GLSL( +#version 410 +#include "_COOL_RES_/shaders/shader-utils.glsl" +out vec4 out_Color; +uniform sampler2D tex_to_copy; +void main() +{ + out_Color = texture(tex_to_copy, _uv); +} + )GLSL"); + res.send_error_if_any( + [&](std::string const& message) { + return Cool::Message{ + .category = "Internal", + .message = "Failed to create shader to copy texture:\n" + message, + .severity = Cool::MessageSeverity::Error, + }; + }, + Cool::Log::ToUser::console() + ); + + return instance; +} + +auto copy_tex_pipeline() -> Cool::OpenGL::FullscreenPipeline& +{ + static auto instance = make_copy_tex_pipeline(); + return instance; +} + +} // namespace Cool \ No newline at end of file diff --git a/src/Cool/Gpu/OpenGL/copy_tex_pipeline.hpp b/src/Cool/Gpu/OpenGL/copy_tex_pipeline.hpp new file mode 100644 index 000000000..59dc9052a --- /dev/null +++ b/src/Cool/Gpu/OpenGL/copy_tex_pipeline.hpp @@ -0,0 +1,8 @@ +#pragma once +#include "FullscreenPipeline.h" + +namespace Cool { + +auto copy_tex_pipeline() -> Cool::OpenGL::FullscreenPipeline&; + +} \ No newline at end of file From 473c49f2c301c1f350576c80815295ed8c4bd5ad Mon Sep 17 00:00:00 2001 From: Jules Fouchy Date: Mon, 2 Sep 2024 09:24:34 +0200 Subject: [PATCH 4/5] =?UTF-8?q?=F0=9F=9A=9A=20Rename=20RenderView=20as=20T?= =?UTF-8?q?extureView?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cool/Gpu/OpenGL/Texture.h | 1 - ...nderView.h => ForwardingOrTextureView.hpp} | 12 +++++------ src/Cool/View/RenderView.cpp | 21 ------------------- src/Cool/View/TextureView.cpp | 21 +++++++++++++++++++ .../View/{RenderView.h => TextureView.hpp} | 10 ++------- src/Cool/View/View.h | 2 +- 6 files changed, 30 insertions(+), 37 deletions(-) rename src/Cool/View/{ForwardingOrRenderView.h => ForwardingOrTextureView.hpp} (73%) delete mode 100644 src/Cool/View/RenderView.cpp create mode 100644 src/Cool/View/TextureView.cpp rename src/Cool/View/{RenderView.h => TextureView.hpp} (59%) diff --git a/src/Cool/Gpu/OpenGL/Texture.h b/src/Cool/Gpu/OpenGL/Texture.h index 0e358371c..d34618c66 100644 --- a/src/Cool/Gpu/OpenGL/Texture.h +++ b/src/Cool/Gpu/OpenGL/Texture.h @@ -6,7 +6,6 @@ #include "img/src/Image.h" #include "img/src/Size.h" - namespace Cool::OpenGL { struct TextureConfig { diff --git a/src/Cool/View/ForwardingOrRenderView.h b/src/Cool/View/ForwardingOrTextureView.hpp similarity index 73% rename from src/Cool/View/ForwardingOrRenderView.h rename to src/Cool/View/ForwardingOrTextureView.hpp index b6d1fe1bc..384b8b4ed 100644 --- a/src/Cool/View/ForwardingOrRenderView.h +++ b/src/Cool/View/ForwardingOrTextureView.hpp @@ -1,22 +1,22 @@ #pragma once -#include "RenderView.h" +#include "TextureView.hpp" namespace Cool { -class ForwardingOrRenderView : public RenderView { +class ForwardingOrTextureView : public TextureView { public: - ForwardingOrRenderView(View const& forwarded_view, ViewCreationParams const& p) - : RenderView{p} + ForwardingOrTextureView(View const& forwarded_view, ViewCreationParams const& p) + : TextureView{p} , _forwarded_view{forwarded_view} {} private: auto get_image_texture_id() const -> ImTextureID override { return _forwarded_view.is_open() ? _forwarded_view.get_image_texture_id() - : RenderView::get_image_texture_id(); } + : TextureView::get_image_texture_id(); } auto get_image_size() const -> img::Size override { return _forwarded_view.is_open() ? _forwarded_view.get_image_size() - : RenderView::get_image_size(); } + : TextureView::get_image_size(); } private: View const& _forwarded_view; // NOLINT(cppcoreguidelines-avoid-const-or-ref-data-members) diff --git a/src/Cool/View/RenderView.cpp b/src/Cool/View/RenderView.cpp deleted file mode 100644 index 71ecbde21..000000000 --- a/src/Cool/View/RenderView.cpp +++ /dev/null @@ -1,21 +0,0 @@ -#include "RenderView.h" - -namespace Cool { - -auto RenderView::desired_image_size(ImageSizeConstraint const& constraint) const -> img::Size -{ - if (!window_size().has_value()) - return {}; - return constraint.applied_to(*window_size()); -} - -auto RenderView::get_image_texture_id() const -> ImTextureID -{ - return _texture.imgui_texture_id(); -} -auto RenderView::get_image_size() const -> img::Size -{ - return _texture.size; -} - -} // namespace Cool \ No newline at end of file diff --git a/src/Cool/View/TextureView.cpp b/src/Cool/View/TextureView.cpp new file mode 100644 index 000000000..26ba2a4c1 --- /dev/null +++ b/src/Cool/View/TextureView.cpp @@ -0,0 +1,21 @@ +#include "TextureView.hpp" + +namespace Cool { + +auto TextureView::desired_image_size(ImageSizeConstraint const& constraint) const -> img::Size +{ + if (!window_size().has_value()) + return {}; + return constraint.applied_to(*window_size()); +} + +auto TextureView::get_image_texture_id() const -> ImTextureID +{ + return _texture.imgui_texture_id(); +} +auto TextureView::get_image_size() const -> img::Size +{ + return _texture.size; +} + +} // namespace Cool \ No newline at end of file diff --git a/src/Cool/View/RenderView.h b/src/Cool/View/TextureView.hpp similarity index 59% rename from src/Cool/View/RenderView.h rename to src/Cool/View/TextureView.hpp index 28b48d0b9..28419398c 100644 --- a/src/Cool/View/RenderView.h +++ b/src/Cool/View/TextureView.hpp @@ -5,25 +5,19 @@ namespace Cool { -/// A View that uses a RenderTarget as its image. -/// You can render on that render target however you want. -class RenderView : public View { +/// A View that displays a given texture. +class TextureView : public View { public: using View::View; void set_texture(TextureRef texture) { _texture = texture; } - auto desired_image_size(ImageSizeConstraint const&) const -> img::Size; - // auto render_target() -> RenderTarget& { return _render_target; } - // auto render_target() const -> RenderTarget const& { return _render_target; } - protected: auto get_image_texture_id() const -> ImTextureID override; auto get_image_size() const -> img::Size override; private: - // RenderTarget _render_target; TextureRef _texture{}; }; diff --git a/src/Cool/View/View.h b/src/Cool/View/View.h index 6e70f33ae..2e7787ebc 100644 --- a/src/Cool/View/View.h +++ b/src/Cool/View/View.h @@ -78,7 +78,7 @@ class View { auto is_open() const -> bool { return _is_open; } private: /// Child classes need to implement these functions in order for us to display their image in the View. - friend class ForwardingOrRenderView; + friend class ForwardingOrTextureView; virtual auto get_image_texture_id() const -> ImTextureID = 0; virtual auto get_image_size() const -> img::Size = 0; From f4238d8d55beee065adc5a51e043ba640dc2b2ea Mon Sep 17 00:00:00 2001 From: Jules Fouchy Date: Mon, 2 Sep 2024 12:03:47 +0200 Subject: [PATCH 5/5] =?UTF-8?q?=F0=9F=A4=8F=20[RenderTarget]=20Reintroduce?= =?UTF-8?q?=20download=5Fpixels()?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp | 4 ++-- src/Cool/Gpu/internal/RenderTarget_Base.h | 3 ++- .../Gpu/internal/RenderTarget_ImplOpenGL.cpp | 19 ++++++++++++++++--- .../Gpu/internal/RenderTarget_ImplOpenGL.h | 13 +++++++------ 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp b/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp index daceedc65..107bdf1f4 100644 --- a/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp +++ b/src/Cool/Gpu/OpenGL/copy_tex_pipeline.cpp @@ -5,7 +5,7 @@ namespace Cool { static auto make_copy_tex_pipeline() -> Cool::OpenGL::FullscreenPipeline { auto instance = Cool::OpenGL::FullscreenPipeline{}; - auto const res = instance.compile(R"GLSL( + auto const err = instance.compile(R"GLSL( #version 410 #include "_COOL_RES_/shaders/shader-utils.glsl" out vec4 out_Color; @@ -15,7 +15,7 @@ void main() out_Color = texture(tex_to_copy, _uv); } )GLSL"); - res.send_error_if_any( + err.send_error_if_any( [&](std::string const& message) { return Cool::Message{ .category = "Internal", diff --git a/src/Cool/Gpu/internal/RenderTarget_Base.h b/src/Cool/Gpu/internal/RenderTarget_Base.h index 1afaafbf5..afac91f1e 100644 --- a/src/Cool/Gpu/internal/RenderTarget_Base.h +++ b/src/Cool/Gpu/internal/RenderTarget_Base.h @@ -1,7 +1,7 @@ #pragma once #include #include "../RenderTargetInfo.h" -#include "Cool/Gpu/Texture.h" +#include "Cool/Gpu/OpenGL/TextureRef.hpp" namespace Cool { @@ -9,6 +9,7 @@ template class RenderTarget_Base { public: void render(typename RenderTarget_Impl::RenderFuncType render_fn); + img::Image download_pixels() const { return _impl.download_pixels(); } ImTextureID imgui_texture_id() const { return _impl.imgui_texture_id(); } auto texture_ref() const -> TextureRef { return _impl.texture_ref(); } RenderTargetInfo info() const { return _impl.info(); } diff --git a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp index 2654dbc76..b5d6cd432 100644 --- a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp +++ b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.cpp @@ -11,9 +11,9 @@ RenderTarget_ImplOpenGL::RenderTarget_ImplOpenGL(img::Size size) void RenderTarget_ImplOpenGL::render(RenderFuncType render_fn) { - _texture.bind(); + _texture_fb.bind(); render_fn(); - _texture.unbind(); + _texture_fb.unbind(); } RenderTargetInfo RenderTarget_ImplOpenGL::info() const @@ -28,7 +28,20 @@ RenderTargetInfo RenderTarget_ImplOpenGL::info() const void RenderTarget_ImplOpenGL::resize(img::Size size) { - _texture.setSize(size); + _texture_fb.setSize(size); +} + +img::Image RenderTarget_ImplOpenGL::download_pixels() const +{ + _texture_fb.bind(); + std::unique_ptr data{new uint8_t[4 * width() * height()]}; + glReadPixels(0, 0, static_cast(width()), static_cast(height()), GL_RGBA, GL_UNSIGNED_BYTE, data.get()); + _texture_fb.unbind(); + return img::Image{ + img::Size{width(), height()}, + 4, + data.release() + }; } } // namespace Cool diff --git a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h index 16170b513..fec358665 100644 --- a/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h +++ b/src/Cool/Gpu/internal/RenderTarget_ImplOpenGL.h @@ -14,19 +14,20 @@ class RenderTarget_ImplOpenGL { void render(RenderFuncType render_fn); RenderTargetInfo info() const; - img::Size::DataType width() const { return _texture.width(); } - img::Size::DataType height() const { return _texture.height(); } - img::Size size() const { return _texture.size(); } - GLuint texture_id() const { return _texture.textureID(); } + img::Size::DataType width() const { return _texture_fb.width(); } + img::Size::DataType height() const { return _texture_fb.height(); } + img::Size size() const { return _texture_fb.size(); } + img::Image download_pixels() const; + GLuint texture_id() const { return _texture_fb.textureID(); } auto texture_ref() const -> TextureRef { return TextureRef{texture_id(), size()}; } - ImTextureID imgui_texture_id() const { return reinterpret_cast(static_cast(_texture.textureID())); } // Double-cast to fix a warning : first we convert to the correct size (uint32_t -> uint64_t) then from integral type to pointer type (uint64_t -> ImTextureID) + ImTextureID imgui_texture_id() const { return reinterpret_cast(static_cast(_texture_fb.textureID())); } // Double-cast to fix a warning : first we convert to the correct size (uint32_t -> uint64_t) then from integral type to pointer type (uint64_t -> ImTextureID) void imgui_window(); void resize(img::Size size); private: - TextureFB _texture; + TextureFB _texture_fb; }; } // namespace Cool