Skip to content

Commit

Permalink
🔀 Merge pull request #107 from CoolLibs/feedback-loop
Browse files Browse the repository at this point in the history
Feedback loop
  • Loading branch information
JulesFouchy authored Sep 2, 2024
2 parents 5fe227c + ec15d3c commit 0f09d94
Show file tree
Hide file tree
Showing 34 changed files with 750 additions and 444 deletions.
8 changes: 8 additions & 0 deletions Nodes/10 Image/Feedback (One frame delay).clbnode
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// To learn how to write nodes, see https://coollab-art.com/Tutorials/Writing%20Nodes/Intro

INPUT UV->sRGB_StraightA 'Image';

sRGB_StraightA main(UV uv)
{
return vec4(); // Doesn't matter, this node file is just a hack to have a node with the right input and output pins
}
7 changes: 0 additions & 7 deletions Nodes/10 Image/Feedback (Previous frame).clbnode

This file was deleted.

44 changes: 24 additions & 20 deletions src/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ namespace Lab {

App::App(Cool::WindowManager& windows, Cool::ViewsManager& views)
: _main_window{windows.main_window()}
, _output_view{views.make_view<Cool::RenderView>(Cool::ViewCreationParams{
, _output_view{views.make_view<Cool::TextureView>(Cool::ViewCreationParams{
.name = Cool::icon_fmt("Output", ICOMOON_IMAGE),
.is_output_view = true,
.is_closable = true,
.start_open = false,
})}
, _preview_view{views.make_view<Cool::ForwardingOrRenderView>(
, _preview_view{views.make_view<Cool::ForwardingOrTextureView>(
_output_view,
Cool::ViewCreationParams{
.name = Cool::icon_fmt("View", ICOMOON_IMAGE),
Expand Down Expand Up @@ -116,6 +116,9 @@ void App::update()
initial_project_opening(command_execution_context());
}

if (DebugOptions::force_rerender_every_frame())
_project.modules_graph->request_rerender_all();

Cool::user_settings().color_themes.update();

_project.audio.set_force_mute(_project.exporter.is_exporting());
Expand All @@ -141,16 +144,16 @@ void App::update()

if (inputs_are_allowed()) // Must update() before we render() to make sure the modules are ready (e.g. Nodes need to parse the definitions of the nodes from files)
{
_nodes_library_manager.update(_project.modules_graph->regenerate_code_flag(), _project.modules_graph->graph(), _project.modules_graph->nodes_config(ui(), _project.audio, _nodes_library_manager.library()));
_nodes_library_manager.update(_project.modules_graph->rebuild_modules_graph_flag(), _project.modules_graph->graph(), _project.modules_graph->nodes_config(ui(), _project.audio, _nodes_library_manager.library()));
_project.modules_graph->update();
check_inputs();
}

if (!_project.exporter.is_exporting())
{
_project.clock.update();
render_view().update_size(_project.view_constraint); // TODO(JF) Integrate the notion of View Constraint inside the RenderView ? But that's maybe too much coupling
polaroid().render(_project.clock.time(), _project.clock.delta_time());
auto const render_size = render_view().desired_image_size(_project.view_constraint); // TODO(JF) Integrate the notion of View Constraint inside the TextureView ? But that's may be too much coupling
polaroid().render(render_size, _project.clock.time(), _project.clock.delta_time());
}
else
{
Expand Down Expand Up @@ -196,7 +199,7 @@ void App::request_rerender() // TODO(Modules) Sometimes we don't need to call th
_project.modules_graph->request_rerender_all();
}

auto App::render_view() -> Cool::RenderView&
auto App::render_view() -> Cool::TextureView&
{
if (_output_view.is_open())
return _output_view;
Expand All @@ -206,14 +209,9 @@ auto App::render_view() -> Cool::RenderView&
Cool::Polaroid App::polaroid()
{
return {
.render_target = render_view().render_target(), // TODO(Modules) Each module should have its own render target that it renders on. The views shouldn't have a render target, but receive the one of the top-most module by reference.
.render_fn = [this](Cool::RenderTarget& render_target, Cool::Time time, Cool::Time delta_time) {
if (_last_time != time)
{
_last_time = time;
on_time_changed();
}
render(render_target, time, delta_time);
.texture = [this]() { return _project.modules_graph->final_texture(); },
.render = [this](img::Size size, Cool::Time time, Cool::Time delta_time) {
render(size, time, delta_time);
}
};
}
Expand All @@ -236,11 +234,15 @@ static void imgui_window_console()
#endif
}

void App::render(Cool::RenderTarget& render_target, Cool::Time time, Cool::Time delta_time)
void App::render(img::Size size, Cool::Time time, Cool::Time delta_time)
{
if (_last_time != time)
{
_last_time = time;
on_time_changed();
}
_project.modules_graph->render(
render_target,
data_to_pass_to_shader(render_target.desired_size(), time, delta_time),
data_to_pass_to_shader(size, time, delta_time),
data_to_generate_shader_code()
);
}
Expand Down Expand Up @@ -280,10 +282,12 @@ void App::imgui_window_view()
}

_project.modules_graph->submit_gizmos(_preview_view.gizmos_manager(), command_executor(), _project.camera_2D_manager.camera());
_output_view.set_texture(_project.modules_graph->final_texture());
_output_view.imgui_window({
.on_open = [&]() { request_rerender(); }, // When we switch between using the _output_view and the _nodes_view
.on_close = [&]() { request_rerender(); }, // as our render target, we need to rerender.
});
_preview_view.set_texture(_project.modules_graph->final_texture());
_preview_view.imgui_window({
.fullscreen = view_in_fullscreen,
.extra_widgets = [&]() {
Expand Down Expand Up @@ -354,7 +358,7 @@ void App::imgui_window_meshing()
{
_meshing_gui.imgui_window(
_mesh_export_settings,
data_to_pass_to_shader(render_view().render_target().current_size(), _project.clock.time(), _project.clock.delta_time()),
data_to_pass_to_shader(render_view().desired_image_size(_project.view_constraint), _project.clock.time(), _project.clock.delta_time()),
data_to_generate_shader_code()
);
}
Expand Down Expand Up @@ -405,8 +409,8 @@ void App::imgui_windows_only_when_inputs_are_allowed()
// Share online
_gallery_poster.imgui_window([&](img::Size size) {
auto the_polaroid = polaroid();
the_polaroid.render(_project.clock.time(), _project.clock.delta_time(), size);
auto const image = the_polaroid.render_target.download_pixels();
the_polaroid.render(size, _project.clock.time(), _project.clock.delta_time());
auto const image = the_polaroid.texture().download_pixels();
return img::save_png_to_string(image);
});
// Recently opened projects
Expand Down
15 changes: 7 additions & 8 deletions src/App.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
#include <Cool/Gpu/RenderTarget.h>
#include <Cool/Path/Path.h>
#include <Cool/Time/Clock_Realtime.h>
#include <Cool/View/RenderView.h>
#include <Cool/View/ViewsManager.h>
#include <Cool/Window/WindowManager.h>
#include <Nodes/NodesLibraryManager.h>
Expand All @@ -35,8 +34,8 @@
#include "Cool/StrongTypes/Camera2D.h"
#include "Cool/Time/Clock_Realtime.h"
#include "Cool/Tips/TipsManager.h"
#include "Cool/View/ForwardingOrRenderView.h"
#include "Cool/View/RenderView.h"
#include "Cool/View/ForwardingOrTextureView.hpp"
#include "Cool/View/TextureView.hpp"
#include "Cool/View/ViewsManager.h"
#include "Cool/Webcam/WebcamsConfigs.h"
#include "Cool/Window/WindowManager.h"
Expand Down Expand Up @@ -78,10 +77,10 @@ class App : public Cool::IApp {
auto nodes_library() const -> Cool::NodesLibrary const& { return _nodes_library_manager.library(); }

private:
void render(Cool::RenderTarget& render_target, Cool::Time time, Cool::Time delta_time);
void render(img::Size size, Cool::Time time, Cool::Time delta_time);
void on_time_changed();
void on_time_reset();
auto render_view() -> Cool::RenderView&;
auto render_view() -> Cool::TextureView&;

void check_inputs();
void check_inputs__history();
Expand All @@ -97,7 +96,7 @@ class App : public Cool::IApp {
auto command_executor () { return CommandExecutor{command_execution_context()}; }
auto system_values (img::Size render_target_size, Cool::Time time, Cool::Time delta_time) const { return SystemValues{render_target_size, time, delta_time, _project.camera_2D_manager.camera(), _project.camera_3D_manager.camera(), _project.audio}; }
auto ui () { return Ui_Ref{command_executor()}; }
auto data_to_pass_to_shader (img::Size render_target_size, Cool::Time time, Cool::Time delta_time) const { return DataToPassToShader{system_values(render_target_size, time, delta_time), _project.modules_graph->graph(), _project.modules_graph->compositing_module().feedback_double_buffer() }; }
auto data_to_pass_to_shader (img::Size render_target_size, Cool::Time time, Cool::Time delta_time) const { return DataToPassToShader{system_values(render_target_size, time, delta_time), _project.modules_graph->graph() }; }
auto data_to_generate_shader_code () const { return DataToGenerateShaderCode{_project.modules_graph->graph(), Cool::GetNodeDefinition_Ref<NodeDefinition>{_nodes_library_manager.library()} }; }
// clang-format on

Expand All @@ -123,8 +122,8 @@ class App : public Cool::IApp {

private:
Cool::Window& _main_window;
Cool::RenderView& _output_view;
Cool::ForwardingOrRenderView& _preview_view; // Must be after _output_view because it stores a reference to it
Cool::TextureView& _output_view;
Cool::ForwardingOrTextureView& _preview_view; // Must be after _output_view because it stores a reference to it
Project _project{};
std::optional<std::filesystem::path> _current_project_path{};
RecentlyOpened _recently_opened_projects{};
Expand Down
5 changes: 5 additions & 0 deletions src/Debug/generate_debug_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ def all_debug_options():
name_in_ui="Show nodes and links registries",
available_in_release=True,
),
DebugOption(
name_in_code="force_rerender_every_frame",
name_in_ui="Force rerender every frame",
available_in_release=True,
),
DebugOption(
name_in_code="log_when_rendering",
name_in_ui="Log when rendering",
Expand Down
16 changes: 16 additions & 0 deletions src/Debug/generated/DebugOptions.inl
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public:
}
}
[[nodiscard]] static auto show_nodes_and_links_registries() -> bool& { return instance().show_nodes_and_links_registries; }
[[nodiscard]] static auto force_rerender_every_frame() -> bool& { return instance().force_rerender_every_frame; }
[[nodiscard]] static auto log_when_rendering() -> bool& { return instance().log_when_rendering; }
[[nodiscard]] static auto log_when_updating_particles() -> bool& { return instance().log_when_updating_particles; }
[[nodiscard]] static auto log_when_compiling_nodes() -> bool& { return instance().log_when_compiling_nodes; }
Expand Down Expand Up @@ -90,6 +91,7 @@ private:
bool show_imgui_demo_window{false};
bool show_history_window{false};
bool show_nodes_and_links_registries{false};
bool force_rerender_every_frame{false};
bool log_when_rendering{false};
bool log_when_updating_particles{false};
bool log_when_compiling_nodes{false};
Expand All @@ -113,6 +115,7 @@ private:
ser20::make_nvp("ImGui Demo window", show_imgui_demo_window),
ser20::make_nvp("Show history", show_history_window),
ser20::make_nvp("Show nodes and links registries", show_nodes_and_links_registries),
ser20::make_nvp("Force rerender every frame", force_rerender_every_frame),
ser20::make_nvp("Log when rendering", log_when_rendering),
ser20::make_nvp("Log when updating particles", log_when_updating_particles),
ser20::make_nvp("Log when compiling nodes", log_when_compiling_nodes),
Expand All @@ -128,6 +131,7 @@ private:
ser20::make_nvp("ImGui Demo window", show_imgui_demo_window),
ser20::make_nvp("Show history", show_history_window),
ser20::make_nvp("Show nodes and links registries", show_nodes_and_links_registries),
ser20::make_nvp("Force rerender every frame", force_rerender_every_frame),
ser20::make_nvp("Log when rendering", log_when_rendering),
ser20::make_nvp("Log when updating particles", log_when_updating_particles),
ser20::make_nvp("Log when compiling nodes", log_when_compiling_nodes),
Expand All @@ -150,6 +154,7 @@ private:
instance().show_imgui_demo_window = false;
instance().show_history_window = false;
instance().show_nodes_and_links_registries = false;
instance().force_rerender_every_frame = false;
instance().log_when_rendering = false;
instance().log_when_updating_particles = false;
instance().log_when_compiling_nodes = false;
Expand Down Expand Up @@ -218,6 +223,11 @@ private:
Cool::ImGuiExtras::toggle("Show nodes and links registries", &instance().show_nodes_and_links_registries);
}

if (wafl::similarity_match({filter, "Force rerender every frame"}) >= wafl::Matches::Strongly)
{
Cool::ImGuiExtras::toggle("Force rerender every frame", &instance().force_rerender_every_frame);
}

if (wafl::similarity_match({filter, "Log when rendering"}) >= wafl::Matches::Strongly)
{
Cool::ImGuiExtras::toggle("Log when rendering", &instance().log_when_rendering);
Expand Down Expand Up @@ -308,6 +318,12 @@ private:
throw 0.f; // To understand why we need to throw, see `toggle_first_option()` in <Cool/DebugOptions/DebugOptionsManager.h>
}

if (wafl::similarity_match({filter, "Force rerender every frame"}) >= wafl::Matches::Strongly)
{
instance().force_rerender_every_frame = !instance().force_rerender_every_frame;
throw 0.f; // To understand why we need to throw, see `toggle_first_option()` in <Cool/DebugOptions/DebugOptionsManager.h>
}

if (wafl::similarity_match({filter, "Log when rendering"}) >= wafl::Matches::Strongly)
{
instance().log_when_rendering = !instance().log_when_rendering;
Expand Down
2 changes: 1 addition & 1 deletion src/Meshing/MeshingGui.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ static void gen_and_export_mesh(Cool::NodeId const& main_node_id, MeshingSetting
// auto const node_def = data_to_generate_shader_code.get_node_definition(maybe_node->id_names());
// is_shape_3D(node_def->signature());

auto const maybe_mesh = gen_mesh_from_sdf(main_node_id, meshing_settings, data_to_pass_to_shader, data_to_generate_shader_code);
auto const maybe_mesh = gen_mesh_from_sdf(main_node_id, meshing_settings, data_to_pass_to_shader, data_to_generate_shader_code, {}); // TODO(Meshing) We need to generate an entire ModulesGraph, so that we can properly handle the fact that our module might depend on other modules
if (!maybe_mesh)
return; // TODO(Meshing) Error message should be handled here
export_mesh(*maybe_mesh, mesh_export_settings);
Expand Down
18 changes: 11 additions & 7 deletions src/Meshing/gen_mesh_from_sdf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,11 @@ void cool_main()
}

auto gen_mesh_from_sdf(
Cool::NodeId const& main_node_id,
MeshingSettings const& meshing_settings,
DataToPassToShader const& data_to_pass_to_shader,
DataToGenerateShaderCode const& data_to_generate_shader_code
Cool::NodeId const& main_node_id,
MeshingSettings const& meshing_settings,
DataToPassToShader const& data_to_pass_to_shader,
DataToGenerateShaderCode const& data_to_generate_shader_code,
std::vector<std::shared_ptr<Module>> const& module_dependencies
) -> std::optional<Cool::Mesh>
{
if constexpr (COOL_OPENGL_VERSION < 430)
Expand Down Expand Up @@ -122,10 +123,13 @@ auto gen_mesh_from_sdf(
meshing_compute_shader->set_uniform("_step_size", meshing_settings.step_size().x);

{
auto dependencies = ModuleDependencies{};
auto dependencies = ModuleDependencies{};
auto nodes_that_we_depend_on = std::vector<Cool::NodeId>{}; // TODO(Meshing) Properly compute the nodes that we depend on
for (auto const& [id, _] : data_to_pass_to_shader.nodes_graph.nodes())
nodes_that_we_depend_on.emplace_back(id);
update_dependencies_from_shader_code(dependencies, *shader_code);
update_dependencies_from_nodes_graph(dependencies, data_to_pass_to_shader.nodes_graph);
set_uniforms_for_shader_based_module(*meshing_compute_shader, dependencies, data_to_pass_to_shader);
update_dependencies_from_nodes_graph(dependencies, data_to_pass_to_shader.nodes_graph, nodes_that_we_depend_on);
set_uniforms_for_shader_based_module(*meshing_compute_shader, dependencies, data_to_pass_to_shader, module_dependencies, nodes_that_we_depend_on);
}

meshing_compute_shader->compute(meshing_settings.samples_count);
Expand Down
10 changes: 9 additions & 1 deletion src/Meshing/gen_mesh_from_sdf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@

namespace Lab {

class Module;

// TODO(Meshing) Return error message in case of failure (tl::expected)
auto gen_mesh_from_sdf(Cool::NodeId const& main_node_id, MeshingSettings const&, DataToPassToShader const&, DataToGenerateShaderCode const&) -> std::optional<Cool::Mesh>;
auto gen_mesh_from_sdf(
Cool::NodeId const& main_node_id,
MeshingSettings const&,
DataToPassToShader const&,
DataToGenerateShaderCode const&,
std::vector<std::shared_ptr<Module>> const& module_dependencies
) -> std::optional<Cool::Mesh>;

} // namespace Lab
7 changes: 7 additions & 0 deletions src/Module/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,11 @@ void Module::log_module_error(Cool::OptionalErrorMessage const& maybe_err, Cool:
});
}

auto Module::needs_to_rerender() const -> bool
{
return _needs_to_rerender_flag.is_dirty() || std::any_of(_modules_that_we_depend_on.begin(), _modules_that_we_depend_on.end(), [&](auto&& module) {
return module->needs_to_rerender();
});
};

} // namespace Lab
Loading

0 comments on commit 0f09d94

Please sign in to comment.