From 9a6a381432294f4502a3bff0f9c45f5959eeee30 Mon Sep 17 00:00:00 2001 From: Gray Olson Date: Thu, 30 May 2019 01:45:02 -0700 Subject: [PATCH 01/34] new tabs and light path layer Co-authored-by: Kevin Masson --- ...=> lightpaths_toolbar_next_light_path.png} | Bin ...aths_toolbar_next_light_path_disabled.png} | Bin ...htpaths_toolbar_next_light_path_hover.png} | Bin ...=> lightpaths_toolbar_prev_light_path.png} | Bin ...aths_toolbar_prev_light_path_disabled.png} | Bin ...htpaths_toolbar_prev_light_path_hover.png} | Bin ...> lightpaths_toolbar_save_light_paths.png} | Bin ...ths_toolbar_save_light_paths_disabled.png} | Bin ...tpaths_toolbar_save_light_paths_hover.png} | Bin ...pengl_viewport_tab_synchronize_camera.png} | Bin ...viewport_tab_synchronize_camera_hover.png} | Bin ..._viewport_tab_toggle_backface_culling.png} | Bin ...ort_tab_toggle_backface_culling_hover.png} | Bin src/appleseed.studio/CMakeLists.txt | 32 +- src/appleseed.studio/main/main.cpp | 2 +- .../mainwindow/mainwindow.cpp | 275 ++++++---- src/appleseed.studio/mainwindow/mainwindow.h | 37 +- ...ndertab.cpp => finalrenderviewporttab.cpp} | 339 ++++++------ .../{rendertab.h => finalrenderviewporttab.h} | 109 ++-- ...{lightpathswidget.cpp => glscenelayer.cpp} | 510 ++++-------------- .../mainwindow/rendering/glscenelayer.h | 150 ++++++ .../mainwindow/rendering/lightpathslayer.cpp | 507 +++++++++++++++++ .../mainwindow/rendering/lightpathslayer.h | 143 +++++ .../rendering/lightpathsmanager.cpp | 241 +++++++++ .../mainwindow/rendering/lightpathsmanager.h | 107 ++++ .../rendering/lightpathspickinghandler.cpp | 141 ++--- .../rendering/lightpathspickinghandler.h | 23 +- .../mainwindow/rendering/lightpathstab.cpp | 341 ------------ .../rendering/lightpathsviewporttoolbar.cpp | 240 +++++++++ .../rendering/lightpathsviewporttoolbar.h | 116 ++++ .../mainwindow/rendering/lightpathswidget.h | 167 ------ .../rendering/openglviewporttab.cpp | 268 +++++++++ .../{lightpathstab.h => openglviewporttab.h} | 79 +-- .../mainwindow/rendering/qttilecallback.cpp | 32 +- .../mainwindow/rendering/qttilecallback.h | 6 +- .../mainwindow/rendering/renderingmanager.cpp | 37 +- .../mainwindow/rendering/renderingmanager.h | 9 +- .../{renderwidget.cpp => renderlayer.cpp} | 159 +++--- .../{renderwidget.h => renderlayer.h} | 64 ++- .../rendering/scenepickinghandler.cpp | 2 +- .../mainwindow/rendering/viewportcanvas.cpp | 440 +++++++++++++++ .../mainwindow/rendering/viewportcanvas.h | 175 ++++++ ...cpp => viewportregionselectionhandler.cpp} | 25 +- ...ler.h => viewportregionselectionhandler.h} | 6 +- .../mainwindow/rendering/viewporttab.cpp | 150 ++++++ .../mainwindow/rendering/viewporttab.h | 125 +++++ src/appleseed.studio/resources/resources.qrc | 3 + .../resources/shaders/final_render.frag | 41 ++ .../resources/shaders/fullscreen_tri.vert | 48 ++ .../resources/shaders/lightpaths.frag | 34 +- .../resources/shaders/lightpaths.vert | 127 ++++- .../resources/shaders/oit_resolve.frag | 52 ++ .../resources/shaders/scene.frag | 2 +- .../resources/shaders/scene.vert | 2 +- src/appleseed.studio/utility/gl.cpp | 152 ++++++ src/appleseed.studio/utility/gl.h | 75 +++ .../lighting/directlightingintegrator.cpp | 2 + .../kernel/lighting/lightpathrecorder.cpp | 4 + .../kernel/lighting/lightpathrecorder.h | 1 + .../kernel/lighting/lightpathstream.cpp | 19 +- .../kernel/lighting/lightpathstream.h | 9 +- .../kernel/lighting/pt/ptlightingengine.cpp | 3 +- .../modeling/camera/orthographiccamera.cpp | 19 +- .../modeling/camera/perspectivecamera.cpp | 31 +- 64 files changed, 4107 insertions(+), 1574 deletions(-) rename sandbox/icons/{lightpathstab_next_light_path.png => lightpaths_toolbar_next_light_path.png} (100%) rename sandbox/icons/{lightpathstab_next_light_path_disabled.png => lightpaths_toolbar_next_light_path_disabled.png} (100%) rename sandbox/icons/{lightpathstab_next_light_path_hover.png => lightpaths_toolbar_next_light_path_hover.png} (100%) rename sandbox/icons/{lightpathstab_prev_light_path.png => lightpaths_toolbar_prev_light_path.png} (100%) rename sandbox/icons/{lightpathstab_prev_light_path_disabled.png => lightpaths_toolbar_prev_light_path_disabled.png} (100%) rename sandbox/icons/{lightpathstab_prev_light_path_hover.png => lightpaths_toolbar_prev_light_path_hover.png} (100%) rename sandbox/icons/{lightpathstab_save_light_paths.png => lightpaths_toolbar_save_light_paths.png} (100%) rename sandbox/icons/{lightpathstab_save_light_paths_disabled.png => lightpaths_toolbar_save_light_paths_disabled.png} (100%) rename sandbox/icons/{lightpathstab_save_light_paths_hover.png => lightpaths_toolbar_save_light_paths_hover.png} (100%) rename sandbox/icons/{lightpathstab_synchronize_camera.png => opengl_viewport_tab_synchronize_camera.png} (100%) rename sandbox/icons/{lightpathstab_synchronize_camera_hover.png => opengl_viewport_tab_synchronize_camera_hover.png} (100%) rename sandbox/icons/{lightpathstab_toggle_backface_culling.png => opengl_viewport_tab_toggle_backface_culling.png} (100%) rename sandbox/icons/{lightpathstab_toggle_backface_culling_hover.png => opengl_viewport_tab_toggle_backface_culling_hover.png} (100%) rename src/appleseed.studio/mainwindow/rendering/{rendertab.cpp => finalrenderviewporttab.cpp} (56%) rename src/appleseed.studio/mainwindow/rendering/{rendertab.h => finalrenderviewporttab.h} (63%) rename src/appleseed.studio/mainwindow/rendering/{lightpathswidget.cpp => glscenelayer.cpp} (52%) create mode 100644 src/appleseed.studio/mainwindow/rendering/glscenelayer.h create mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp create mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathslayer.h create mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp create mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h delete mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathstab.cpp create mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp create mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h delete mode 100644 src/appleseed.studio/mainwindow/rendering/lightpathswidget.h create mode 100644 src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp rename src/appleseed.studio/mainwindow/rendering/{lightpathstab.h => openglviewporttab.h} (54%) rename src/appleseed.studio/mainwindow/rendering/{renderwidget.cpp => renderlayer.cpp} (80%) rename src/appleseed.studio/mainwindow/rendering/{renderwidget.h => renderlayer.h} (74%) create mode 100644 src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp create mode 100644 src/appleseed.studio/mainwindow/rendering/viewportcanvas.h rename src/appleseed.studio/mainwindow/rendering/{renderregionhandler.cpp => viewportregionselectionhandler.cpp} (84%) rename src/appleseed.studio/mainwindow/rendering/{renderregionhandler.h => viewportregionselectionhandler.h} (95%) create mode 100644 src/appleseed.studio/mainwindow/rendering/viewporttab.cpp create mode 100644 src/appleseed.studio/mainwindow/rendering/viewporttab.h create mode 100644 src/appleseed.studio/resources/shaders/final_render.frag create mode 100644 src/appleseed.studio/resources/shaders/fullscreen_tri.vert create mode 100644 src/appleseed.studio/resources/shaders/oit_resolve.frag create mode 100644 src/appleseed.studio/utility/gl.cpp create mode 100644 src/appleseed.studio/utility/gl.h diff --git a/sandbox/icons/lightpathstab_next_light_path.png b/sandbox/icons/lightpaths_toolbar_next_light_path.png similarity index 100% rename from sandbox/icons/lightpathstab_next_light_path.png rename to sandbox/icons/lightpaths_toolbar_next_light_path.png diff --git a/sandbox/icons/lightpathstab_next_light_path_disabled.png b/sandbox/icons/lightpaths_toolbar_next_light_path_disabled.png similarity index 100% rename from sandbox/icons/lightpathstab_next_light_path_disabled.png rename to sandbox/icons/lightpaths_toolbar_next_light_path_disabled.png diff --git a/sandbox/icons/lightpathstab_next_light_path_hover.png b/sandbox/icons/lightpaths_toolbar_next_light_path_hover.png similarity index 100% rename from sandbox/icons/lightpathstab_next_light_path_hover.png rename to sandbox/icons/lightpaths_toolbar_next_light_path_hover.png diff --git a/sandbox/icons/lightpathstab_prev_light_path.png b/sandbox/icons/lightpaths_toolbar_prev_light_path.png similarity index 100% rename from sandbox/icons/lightpathstab_prev_light_path.png rename to sandbox/icons/lightpaths_toolbar_prev_light_path.png diff --git a/sandbox/icons/lightpathstab_prev_light_path_disabled.png b/sandbox/icons/lightpaths_toolbar_prev_light_path_disabled.png similarity index 100% rename from sandbox/icons/lightpathstab_prev_light_path_disabled.png rename to sandbox/icons/lightpaths_toolbar_prev_light_path_disabled.png diff --git a/sandbox/icons/lightpathstab_prev_light_path_hover.png b/sandbox/icons/lightpaths_toolbar_prev_light_path_hover.png similarity index 100% rename from sandbox/icons/lightpathstab_prev_light_path_hover.png rename to sandbox/icons/lightpaths_toolbar_prev_light_path_hover.png diff --git a/sandbox/icons/lightpathstab_save_light_paths.png b/sandbox/icons/lightpaths_toolbar_save_light_paths.png similarity index 100% rename from sandbox/icons/lightpathstab_save_light_paths.png rename to sandbox/icons/lightpaths_toolbar_save_light_paths.png diff --git a/sandbox/icons/lightpathstab_save_light_paths_disabled.png b/sandbox/icons/lightpaths_toolbar_save_light_paths_disabled.png similarity index 100% rename from sandbox/icons/lightpathstab_save_light_paths_disabled.png rename to sandbox/icons/lightpaths_toolbar_save_light_paths_disabled.png diff --git a/sandbox/icons/lightpathstab_save_light_paths_hover.png b/sandbox/icons/lightpaths_toolbar_save_light_paths_hover.png similarity index 100% rename from sandbox/icons/lightpathstab_save_light_paths_hover.png rename to sandbox/icons/lightpaths_toolbar_save_light_paths_hover.png diff --git a/sandbox/icons/lightpathstab_synchronize_camera.png b/sandbox/icons/opengl_viewport_tab_synchronize_camera.png similarity index 100% rename from sandbox/icons/lightpathstab_synchronize_camera.png rename to sandbox/icons/opengl_viewport_tab_synchronize_camera.png diff --git a/sandbox/icons/lightpathstab_synchronize_camera_hover.png b/sandbox/icons/opengl_viewport_tab_synchronize_camera_hover.png similarity index 100% rename from sandbox/icons/lightpathstab_synchronize_camera_hover.png rename to sandbox/icons/opengl_viewport_tab_synchronize_camera_hover.png diff --git a/sandbox/icons/lightpathstab_toggle_backface_culling.png b/sandbox/icons/opengl_viewport_tab_toggle_backface_culling.png similarity index 100% rename from sandbox/icons/lightpathstab_toggle_backface_culling.png rename to sandbox/icons/opengl_viewport_tab_toggle_backface_culling.png diff --git a/sandbox/icons/lightpathstab_toggle_backface_culling_hover.png b/sandbox/icons/opengl_viewport_tab_toggle_backface_culling_hover.png similarity index 100% rename from sandbox/icons/lightpathstab_toggle_backface_culling_hover.png rename to sandbox/icons/opengl_viewport_tab_toggle_backface_culling_hover.png diff --git a/src/appleseed.studio/CMakeLists.txt b/src/appleseed.studio/CMakeLists.txt index c99875173e..644b9d9402 100644 --- a/src/appleseed.studio/CMakeLists.txt +++ b/src/appleseed.studio/CMakeLists.txt @@ -252,14 +252,22 @@ source_group ("mainwindow\\pythonconsole" FILES set (mainwindow_rendering_sources mainwindow/rendering/cameracontroller.cpp mainwindow/rendering/cameracontroller.h + mainwindow/rendering/finalrenderviewporttab.cpp + mainwindow/rendering/finalrenderviewporttab.h + mainwindow/rendering/glscenelayer.cpp + mainwindow/rendering/glscenelayer.h + mainwindow/rendering/lightpathslayer.cpp + mainwindow/rendering/lightpathslayer.h + mainwindow/rendering/lightpathsmanager.cpp + mainwindow/rendering/lightpathsmanager.h mainwindow/rendering/lightpathspickinghandler.cpp mainwindow/rendering/lightpathspickinghandler.h - mainwindow/rendering/lightpathstab.cpp - mainwindow/rendering/lightpathstab.h - mainwindow/rendering/lightpathswidget.cpp - mainwindow/rendering/lightpathswidget.h + mainwindow/rendering/lightpathsviewporttoolbar.cpp + mainwindow/rendering/lightpathsviewporttoolbar.h mainwindow/rendering/materialdrophandler.cpp mainwindow/rendering/materialdrophandler.h + mainwindow/rendering/openglviewporttab.cpp + mainwindow/rendering/openglviewporttab.h mainwindow/rendering/pixelcolortracker.cpp mainwindow/rendering/pixelcolortracker.h mainwindow/rendering/pixelinspectorhandler.cpp @@ -272,14 +280,16 @@ set (mainwindow_rendering_sources mainwindow/rendering/renderclipboardhandler.h mainwindow/rendering/renderingmanager.cpp mainwindow/rendering/renderingmanager.h - mainwindow/rendering/renderregionhandler.cpp - mainwindow/rendering/renderregionhandler.h - mainwindow/rendering/rendertab.cpp - mainwindow/rendering/rendertab.h - mainwindow/rendering/renderwidget.cpp - mainwindow/rendering/renderwidget.h + mainwindow/rendering/renderlayer.cpp + mainwindow/rendering/renderlayer.h mainwindow/rendering/scenepickinghandler.cpp mainwindow/rendering/scenepickinghandler.h + mainwindow/rendering/viewportregionselectionhandler.cpp + mainwindow/rendering/viewportregionselectionhandler.h + mainwindow/rendering/viewporttab.cpp + mainwindow/rendering/viewporttab.h + mainwindow/rendering/viewportcanvas.cpp + mainwindow/rendering/viewportcanvas.h ) list (APPEND appleseed.studio_sources ${mainwindow_rendering_sources} @@ -343,6 +353,8 @@ source_group ("python\\studio" FILES ) set (utility_sources + utility/gl.cpp + utility/gl.h utility/inputwidgetproxies.cpp utility/inputwidgetproxies.h utility/settingskeys.h diff --git a/src/appleseed.studio/main/main.cpp b/src/appleseed.studio/main/main.cpp index 2746a9503d..ad79d6983a 100644 --- a/src/appleseed.studio/main/main.cpp +++ b/src/appleseed.studio/main/main.cpp @@ -332,7 +332,7 @@ int main(int argc, char* argv[]) // Set default surface format before creating application instance. This is // required on macOS in order to use an OpenGL Core profile context. QSurfaceFormat default_format; - default_format.setVersion(3, 3); + default_format.setVersion(4, 2); default_format.setProfile(QSurfaceFormat::CoreProfile); QSurfaceFormat::setDefaultFormat(default_format); diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index 380444ed29..d687423fdd 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -39,8 +39,12 @@ #include "mainwindow/project/attributeeditor.h" #include "mainwindow/project/projectexplorer.h" #include "mainwindow/pythonconsole/pythonconsolewidget.h" -#include "mainwindow/rendering/lightpathstab.h" -#include "mainwindow/rendering/renderwidget.h" +#include "mainwindow/rendering/finalrenderviewporttab.h" +#include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/materialdrophandler.h" +#include "mainwindow/rendering/openglviewporttab.h" +#include "mainwindow/rendering/renderlayer.h" +#include "mainwindow/rendering/viewportcanvas.h" #include "utility/settingskeys.h" // appleseed.qtcommon headers. @@ -130,7 +134,6 @@ MainWindow::MainWindow(QWidget* parent) , m_project_explorer(nullptr) , m_attribute_editor(nullptr) , m_project_file_watcher(nullptr) - , m_light_paths_tab(nullptr) { initialize_ocio(); @@ -203,7 +206,7 @@ bool MainWindow::open_project(const QString& filepath) m_rendering_manager.wait_until_rendering_end(); } - remove_render_tabs(); + remove_viewport_tabs(); set_file_widgets_enabled(false, RenderingMode::NotRendering); set_project_explorer_enabled(false); @@ -218,7 +221,7 @@ bool MainWindow::open_project(const QString& filepath) } else { - recreate_render_tabs(); + recreate_viewport_tabs(); update_workspace(); } @@ -235,7 +238,7 @@ void MainWindow::open_project_async(const QString& filepath) m_rendering_manager.wait_until_rendering_end(); } - remove_render_tabs(); + remove_viewport_tabs(); set_file_widgets_enabled(false, RenderingMode::NotRendering); set_project_explorer_enabled(false); @@ -727,6 +730,10 @@ void MainWindow::build_connections() connect( &m_rendering_manager, SIGNAL(signal_rendering_end()), SLOT(slot_rendering_end())); + + connect( + m_ui->tab_render_channels, &QTabWidget::currentChanged, + this, &MainWindow::slot_current_tab_changed); } void MainWindow::update_workspace() @@ -740,12 +747,6 @@ void MainWindow::update_workspace() set_diagnostics_widgets_enabled(true, RenderingMode::NotRendering); update_pause_resume_checkbox(false); m_ui->attribute_editor_scrollarea_contents->setEnabled(true); - - // Add/remove light paths tab. - if (m_project_manager.is_project_open() && - m_project_manager.get_project()->get_light_path_recorder().get_light_path_count() > 0) - add_light_paths_tab(); - else remove_light_paths_tab(); } void MainWindow::update_project_explorer() @@ -883,27 +884,25 @@ void MainWindow::set_rendering_widgets_enabled(const bool is_enabled, const Rend m_ui->action_rendering_rendering_settings->setEnabled(allow_start); m_action_rendering_settings->setEnabled(allow_start); - // Render tab buttons. + // Viewport tab buttons. const int current_tab_index = m_ui->tab_render_channels->currentIndex(); if (current_tab_index != -1) { - const auto render_tab_it = m_tab_index_to_render_tab.find(current_tab_index); - if (render_tab_it != m_tab_index_to_render_tab.end()) - { - RenderTab* render_tab = render_tab_it->second; + // Clear frame. + m_final_render_viewport_tab->set_clear_frame_button_enabled( + is_enabled && is_project_open && rendering_mode == RenderingMode::NotRendering); - // Clear frame. - render_tab->set_clear_frame_button_enabled( - is_enabled && is_project_open && rendering_mode == RenderingMode::NotRendering); + // Set/clear rendering region. + m_final_render_viewport_tab->set_render_region_buttons_enabled( + is_enabled && is_project_open && rendering_mode != RenderingMode::FinalRendering); - // Set/clear rendering region. - render_tab->set_render_region_buttons_enabled( - is_enabled && is_project_open && rendering_mode != RenderingMode::FinalRendering); + // Scene picker. + m_final_render_viewport_tab->get_scene_picking_handler()->set_enabled( + is_enabled && is_project_open && rendering_mode != RenderingMode::FinalRendering); - // Scene picker. - render_tab->get_scene_picking_handler()->set_enabled( - is_enabled && is_project_open && rendering_mode != RenderingMode::FinalRendering); - } + // Light paths overlay. + const bool enable_light_paths_overlay = is_enabled && is_project_open && rendering_mode == RenderingMode::NotRendering; + m_final_render_viewport_tab->set_light_paths_toggle_enabled(enable_light_paths_overlay); } } @@ -921,18 +920,18 @@ void MainWindow::save_state_before_project_open() m_state_before_project_open->m_is_rendering = m_rendering_manager.is_rendering(); - for (const_each i = m_render_tabs; i; ++i) - m_state_before_project_open->m_render_tab_states[i->first] = i->second->save_state(); + for (const_each i = m_viewport_tabs; i; ++i) + m_state_before_project_open->m_viewport_tab_states[i->first] = i->second->save_state(); } void MainWindow::restore_state_after_project_open() { if (m_state_before_project_open.get()) { - for (const_each i = m_render_tabs; i; ++i) + for (const_each i = m_viewport_tabs; i; ++i) { - const RenderTabStateCollection& tab_states = m_state_before_project_open->m_render_tab_states; - const RenderTabStateCollection::const_iterator tab_state_it = tab_states.find(i->first); + const ViewportTabStateCollection& tab_states = m_state_before_project_open->m_viewport_tab_states; + const ViewportTabStateCollection::const_iterator tab_state_it = tab_states.find(i->first); if (tab_state_it != tab_states.end()) i->second->load_state(tab_state_it->second); @@ -943,112 +942,144 @@ void MainWindow::restore_state_after_project_open() } } -void MainWindow::recreate_render_tabs() +void MainWindow::recreate_viewport_tabs() { - remove_render_tabs(); + remove_viewport_tabs(); if (m_project_manager.is_project_open()) - add_render_tab("RGB"); + { + m_light_paths_manager.reset( + new LightPathsManager( + *m_project_manager.get_project(), + m_application_settings)); + + create_final_render_tab(); + create_opengl_tab(); + + // Connect tabs together once they are all created. + connect_tabs(); + } } -void MainWindow::remove_render_tabs() +void MainWindow::remove_viewport_tabs() { - for (const_each i = m_render_tabs; i; ++i) - delete i->second; - - m_render_tabs.clear(); - m_tab_index_to_render_tab.clear(); + m_ui->tab_render_channels->blockSignals(true); while (m_ui->tab_render_channels->count() > 0) m_ui->tab_render_channels->removeTab(0); + + m_ui->tab_render_channels->blockSignals(false); + + for (const_each i = m_viewport_tabs; i; ++i) + delete i->second; + + m_viewport_tabs.clear(); + m_tab_index_to_viewport_tab.clear(); + + m_final_render_viewport_tab = 0; + m_opengl_viewport_tab = 0; } -void MainWindow::add_render_tab(const QString& label) +void MainWindow::create_final_render_tab() { - // Create render tab. - RenderTab* render_tab = - new RenderTab( + m_final_render_viewport_tab = + new FinalRenderViewportTab( *m_project_explorer, *m_project_manager.get_project(), m_rendering_manager, - m_ocio_config); + *m_light_paths_manager, + m_ocio_config, + m_application_settings); - // Connect the render tab to the main window and the rendering manager. - connect( - render_tab, SIGNAL(signal_render_widget_context_menu(const QPoint&)), - SLOT(slot_render_widget_context_menu(const QPoint&))); + // Connect the beauty viewport tab to the main window and the rendering manager. connect( - render_tab, SIGNAL(signal_set_render_region(const QRect&)), + m_final_render_viewport_tab, SIGNAL(signal_set_render_region(const QRect&)), SLOT(slot_set_render_region(const QRect&))); connect( - render_tab, SIGNAL(signal_clear_render_region()), + m_final_render_viewport_tab, SIGNAL(signal_viewport_canvas_context_menu(const QPoint&)), + SLOT(slot_viewport_canvas_context_menu(const QPoint&))); + connect( + m_final_render_viewport_tab, SIGNAL(signal_clear_render_region()), SLOT(slot_clear_render_region())); connect( - render_tab, SIGNAL(signal_save_frame_and_aovs()), + m_final_render_viewport_tab, SIGNAL(signal_save_frame_and_aovs()), SLOT(slot_save_frame_and_aovs())); connect( - render_tab, SIGNAL(signal_quicksave_frame_and_aovs()), + m_final_render_viewport_tab, SIGNAL(signal_quicksave_frame_and_aovs()), SLOT(slot_quicksave_frame_and_aovs())); connect( - render_tab, SIGNAL(signal_reset_zoom()), + m_final_render_viewport_tab, SIGNAL(signal_reset_zoom()), SLOT(slot_reset_zoom())); connect( - render_tab, SIGNAL(signal_clear_frame()), + m_final_render_viewport_tab, SIGNAL(signal_clear_frame()), SLOT(slot_clear_frame())); connect( - render_tab, SIGNAL(signal_entity_picked(renderer::ScenePicker::PickingResult)), + m_final_render_viewport_tab, SIGNAL(signal_entity_picked(renderer::ScenePicker::PickingResult)), SLOT(slot_clear_filter())); connect( - render_tab, SIGNAL(signal_camera_change_begin()), + m_final_render_viewport_tab, SIGNAL(signal_camera_change_begin()), &m_rendering_manager, SLOT(slot_camera_change_begin())); connect( - render_tab, SIGNAL(signal_camera_change_end()), + m_final_render_viewport_tab, SIGNAL(signal_camera_change_end()), &m_rendering_manager, SLOT(slot_camera_change_end())); connect( - render_tab, SIGNAL(signal_camera_changed()), + m_final_render_viewport_tab, SIGNAL(signal_camera_changed()), &m_rendering_manager, SLOT(slot_camera_changed())); - // Add the render tab to the tab bar. - const int tab_index = m_ui->tab_render_channels->addTab(render_tab, label); + m_final_render_viewport_tab_index = add_viewport_tab(m_final_render_viewport_tab, "Beauty"); +} - // Update mappings. - m_render_tabs[label.toStdString()] = render_tab; - m_tab_index_to_render_tab[tab_index] = render_tab; +void MainWindow::create_opengl_tab() +{ + m_opengl_viewport_tab = + new OpenGLViewportTab( + *m_project_explorer, + *m_project_manager.get_project(), + m_rendering_manager, + *m_light_paths_manager, + m_ocio_config, + m_application_settings); + + // Connect the opengl viewport tab to the main window and the rendering manager. + connect( + m_opengl_viewport_tab, SIGNAL(signal_viewport_canvas_context_menu(const QPoint&)), + SLOT(slot_viewport_canvas_context_menu(const QPoint&))); + connect( + m_opengl_viewport_tab, SIGNAL(signal_reset_zoom()), + SLOT(slot_reset_zoom())); + + m_opengl_viewport_tab_index = add_viewport_tab(m_opengl_viewport_tab, "OpenGL"); } -void MainWindow::add_light_paths_tab() +int MainWindow::add_viewport_tab(ViewportTab* viewport_tab, const QString& label) { - if (m_light_paths_tab == nullptr) - { - // Create light paths tab. - m_light_paths_tab = - new LightPathsTab( - *m_project_manager.get_project(), - m_application_settings); + const int tab_index = static_cast(m_viewport_tabs.size()); - // Connect render tabs to the light paths tab. - for (const auto& kv : m_render_tabs) - { - connect( - kv.second, SIGNAL(signal_entity_picked(renderer::ScenePicker::PickingResult)), - m_light_paths_tab, SLOT(slot_entity_picked(renderer::ScenePicker::PickingResult))); - connect( - kv.second, SIGNAL(signal_rectangle_selection(const QRect&)), - m_light_paths_tab, SLOT(slot_rectangle_selection(const QRect&))); - } + // Update mappings before inserting the tab. + // When inserting a tab, it may show the tab and + // trigger QTabWidget::currentChanged signal. + // We want to make sure our mappings are ready + // before running our slots. + m_viewport_tabs[label.toStdString()] = viewport_tab; + m_tab_index_to_viewport_tab[tab_index] = viewport_tab; - // Add the light paths tab to the tab bar. - m_ui->tab_render_channels->addTab(m_light_paths_tab, "Light Paths"); - } + // Add the viewport tab to the tab bar. + const int final_tab_index = m_ui->tab_render_channels->insertTab(tab_index, viewport_tab, label); + + assert(final_tab_index == tab_index); + + return final_tab_index; } -void MainWindow::remove_light_paths_tab() +void MainWindow::connect_tabs() { - if (m_light_paths_tab != nullptr) - { - delete m_light_paths_tab; - m_light_paths_tab = nullptr; - } + assert(m_final_render_viewport_tab); + assert(m_opengl_viewport_tab); + + // Connect final render tab light paths selection to opengl tab. + //connect( + //m_final_render_viewport_tab, &FinalRenderViewportTab::signal_entity_picked, + //m_opengl_viewport_tab, &OpenGLViewportTab::slot_entity_picked); } ParamArray MainWindow::get_project_params(const char* configuration_name) const @@ -1124,7 +1155,7 @@ bool MainWindow::can_close_project() void MainWindow::on_project_change() { update_project_explorer(); - recreate_render_tabs(); + recreate_viewport_tabs(); update_override_shading_menu_item(); m_false_colors_window.reset(); @@ -1220,6 +1251,9 @@ void MainWindow::start_rendering(const RenderingMode rendering_mode) m_false_colors_window.reset(); + // Switch to the final render viewport tab. + m_ui->tab_render_channels->setCurrentIndex(m_final_render_viewport_tab_index); + // Enable/disable menus and widgets appropriately. set_file_widgets_enabled(false, rendering_mode); set_project_explorer_enabled(rendering_mode == RenderingMode::InteractiveRendering); @@ -1227,9 +1261,6 @@ void MainWindow::start_rendering(const RenderingMode rendering_mode) set_diagnostics_widgets_enabled(rendering_mode == RenderingMode::InteractiveRendering, rendering_mode); m_ui->attribute_editor_scrollarea_contents->setEnabled(rendering_mode == RenderingMode::InteractiveRendering); - // Remove light paths tab. - remove_light_paths_tab(); - // Stop monitoring the project file in Final rendering mode. if (rendering_mode == RenderingMode::FinalRendering) { @@ -1240,13 +1271,14 @@ void MainWindow::start_rendering(const RenderingMode rendering_mode) Project* project = m_project_manager.get_project(); Frame* frame = project->get_frame(); + project->get_light_path_recorder().clear(); + m_light_paths_manager->clear_light_paths_selection(); frame->clear_main_and_aov_images(); // Darken render widgets. - for (const_each i = m_render_tabs; i; ++i) + for (const_each i = m_viewport_tabs; i; ++i) { - i->second->darken(); - i->second->update(); + i->second->render_began(); } // Retrieve the appropriate rendering configuration. @@ -1261,7 +1293,7 @@ void MainWindow::start_rendering(const RenderingMode rendering_mode) rendering_mode == RenderingMode::InteractiveRendering ? RenderingManager::RenderingMode::InteractiveRendering : RenderingManager::RenderingMode::FinalRendering, - m_render_tabs["RGB"]); + m_final_render_viewport_tab); } void MainWindow::apply_false_colors_settings() @@ -1299,10 +1331,10 @@ void MainWindow::apply_false_colors_settings() else { // Blit the regular frame into the render widget. - for (const_each i = m_render_tabs; i; ++i) + for (const_each i = m_viewport_tabs; i; ++i) { - i->second->get_render_widget()->blit_frame(*frame); - i->second->get_render_widget()->update(); + i->second->get_viewport_canvas()->get_render_layer()->blit_frame(*frame); + i->second->get_viewport_canvas()->get_render_layer()->update(); } } } @@ -1322,10 +1354,10 @@ void MainWindow::apply_post_processing_stage( stage.execute(working_frame); // Blit the frame copy into the render widget. - for (const_each i = m_render_tabs; i; ++i) + for (const_each i = m_viewport_tabs; i; ++i) { - i->second->get_render_widget()->blit_frame(working_frame); - i->second->get_render_widget()->update(); + i->second->get_viewport_canvas()->get_render_layer()->blit_frame(working_frame); + i->second->get_viewport_canvas()->get_render_layer()->update(); } } } @@ -1372,7 +1404,7 @@ void MainWindow::closeEvent(QCloseEvent* event) if (m_benchmark_window.get()) m_benchmark_window->close(); - remove_render_tabs(); + remove_viewport_tabs(); m_project_manager.close_project(); @@ -1490,7 +1522,7 @@ void MainWindow::slot_open_project_complete(const QString& filepath, const bool else { show_project_file_loading_failed_message_box(this, filepath); - recreate_render_tabs(); + recreate_viewport_tabs(); update_workspace(); } } @@ -1929,7 +1961,7 @@ void MainWindow::slot_set_render_region(const QRect& rect) } } -void MainWindow::slot_render_widget_context_menu(const QPoint& point) +void MainWindow::slot_viewport_canvas_context_menu(const QPoint& point) { if (!(QApplication::keyboardModifiers() & Qt::ShiftModifier)) return; @@ -2069,7 +2101,7 @@ void MainWindow::slot_save_render_widget_content() return; // todo: this is sketchy. The render tab should be retrieved from the signal. - m_render_tabs["RGB"]->get_render_widget()->capture().save(filepath); + m_viewport_tabs["Beauty"]->get_viewport_canvas()->get_render_layer()->capture().save(filepath); RENDERER_LOG_INFO("wrote image file %s.", filepath.toStdString().c_str()); } @@ -2080,16 +2112,18 @@ void MainWindow::slot_clear_frame() frame->clear_main_and_aov_images(); // Clear all render widgets to black. - for (const_each i = m_render_tabs; i; ++i) - i->second->clear(); + for (const std::pair& kvp : m_viewport_tabs) + { + kvp.second->clear(); + } } void MainWindow::slot_reset_zoom() { const int current_tab_index = m_ui->tab_render_channels->currentIndex(); - const auto render_tab_it = m_tab_index_to_render_tab.find(current_tab_index); - if (render_tab_it != m_tab_index_to_render_tab.end()) - render_tab_it->second->reset_zoom(); + const auto viewport_tab_it = m_tab_index_to_viewport_tab.find(current_tab_index); + if (viewport_tab_it != m_tab_index_to_viewport_tab.end()) + viewport_tab_it->second->reset_zoom(); } void MainWindow::slot_filter_text_changed(const QString& pattern) @@ -2105,7 +2139,7 @@ void MainWindow::slot_clear_filter() void MainWindow::slot_frame_modified() { - for (each i = m_render_tabs; i; ++i) + for (each i = m_viewport_tabs; i; ++i) i->second->update_size(); } @@ -2143,6 +2177,15 @@ void MainWindow::slot_check_fullscreen() m_action_fullscreen->setChecked(is_fullscreen); } +void MainWindow::slot_current_tab_changed(int index) +{ + if (index == -1) return; + + ViewportTab* tab = m_tab_index_to_viewport_tab[index]; + + tab->on_tab_selected(); +} + void MainWindow::slot_show_application_settings_window() { if (m_application_settings_window.get() == nullptr) diff --git a/src/appleseed.studio/mainwindow/mainwindow.h b/src/appleseed.studio/mainwindow/mainwindow.h index ba6b8c20c5..4904c9f73c 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.h +++ b/src/appleseed.studio/mainwindow/mainwindow.h @@ -35,7 +35,9 @@ #include "mainwindow/applicationsettingswindow.h" #include "mainwindow/falsecolorswindow.h" #include "mainwindow/rendering/renderingmanager.h" -#include "mainwindow/rendering/rendertab.h" +#include "mainwindow/rendering/finalrenderviewporttab.h" +#include "mainwindow/rendering/openglviewporttab.h" +#include "mainwindow/rendering/viewporttab.h" #include "mainwindow/renderingsettingswindow.h" #include "mainwindow/statusbar.h" @@ -62,8 +64,8 @@ namespace OCIO = OCIO_NAMESPACE; // Forward declarations. namespace appleseed { namespace studio { class AttributeEditor; } } -namespace appleseed { namespace studio { class LightPathsTab; } } namespace appleseed { namespace studio { class MinimizeButton; } } +namespace appleseed { namespace studio { class LightPathsManager; } } namespace appleseed { namespace studio { class ProjectExplorer; } } namespace renderer { class Project; } namespace Ui { class MainWindow; } @@ -161,17 +163,22 @@ class MainWindow AttributeEditor* m_attribute_editor; RenderingManager m_rendering_manager; - typedef std::map RenderTabCollection; - typedef std::map RenderTabStateCollection; + typedef std::map ViewportTabCollection; + typedef std::map ViewportTabStateCollection; - RenderTabCollection m_render_tabs; - std::map m_tab_index_to_render_tab; - LightPathsTab* m_light_paths_tab; + ViewportTabCollection m_viewport_tabs; + std::map m_tab_index_to_viewport_tab; + + FinalRenderViewportTab* m_final_render_viewport_tab; + int m_final_render_viewport_tab_index; + OpenGLViewportTab* m_opengl_viewport_tab; + int m_opengl_viewport_tab_index; + std::unique_ptr m_light_paths_manager; struct StateBeforeProjectOpen { bool m_is_rendering; - RenderTabStateCollection m_render_tab_states; + ViewportTabStateCollection m_viewport_tab_states; }; std::unique_ptr m_state_before_project_open; @@ -208,11 +215,12 @@ class MainWindow void restore_state_after_project_open(); // Render tabs. - void recreate_render_tabs(); - void remove_render_tabs(); - void add_render_tab(const QString& label); - void add_light_paths_tab(); - void remove_light_paths_tab(); + void recreate_viewport_tabs(); + void remove_viewport_tabs(); + void create_final_render_tab(); + void create_opengl_tab(); + int add_viewport_tab(ViewportTab* viewport_tab, const QString& label); + void connect_tabs(); // Project file handling. renderer::ParamArray get_project_params(const char* configuration_name) const; @@ -289,7 +297,7 @@ class MainWindow void slot_set_render_region(const QRect& rect); // Render widget actions. - void slot_render_widget_context_menu(const QPoint& point); + void slot_viewport_canvas_context_menu(const QPoint& point); void slot_save_frame(); void slot_save_frame_and_aovs(); void slot_quicksave_frame_and_aovs(); @@ -305,6 +313,7 @@ class MainWindow // General UI actions. void slot_fullscreen(); void slot_check_fullscreen(); + void slot_current_tab_changed(int index); // Child windows. void slot_show_application_settings_window(); diff --git a/src/appleseed.studio/mainwindow/rendering/rendertab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp similarity index 56% rename from src/appleseed.studio/mainwindow/rendering/rendertab.cpp rename to src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 7552f27ca9..9d06b38a04 100644 --- a/src/appleseed.studio/mainwindow/rendering/rendertab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -5,8 +5,7 @@ // // This software is released under the MIT license. // -// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited -// Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization +// Copyright (c) 2020 Kevin Masson, The appleseedhq Organization // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -28,25 +27,19 @@ // // Interface header. -#include "rendertab.h" +#include "finalrenderviewporttab.h" // appleseed.studio headers. #include "mainwindow/project/projectexplorer.h" -#include "mainwindow/rendering/renderwidget.h" - -// appleseed.qtcommon headers. -#include "utility/miscellaneous.h" +#include "mainwindow/rendering/lightpathspickinghandler.h" +#include "mainwindow/rendering/renderingmanager.h" // appleseed.renderer headers. #include "renderer/api/frame.h" #include "renderer/api/project.h" -// appleseed.foundation headers. -#include "foundation/image/canvasproperties.h" -#include "foundation/image/image.h" - -// OpenColorIO headers. -#include +// appleseed.qtcommon headers. +#include "utility/miscellaneous.h" // Qt headers. #include @@ -60,9 +53,6 @@ #include #include -// Standard headers. -#include - using namespace appleseed::qtcommon; using namespace foundation; using namespace renderer; @@ -71,169 +61,195 @@ namespace OCIO = OCIO_NAMESPACE; namespace appleseed { namespace studio { -// -// RenderTab class implementation. -// - -RenderTab::RenderTab( - ProjectExplorer& project_explorer, - Project& project, - RenderingManager& rendering_manager, - OCIO::ConstConfigRcPtr ocio_config) - : m_project_explorer(project_explorer) - , m_project(project) - , m_rendering_manager(rendering_manager) - , m_ocio_config(ocio_config) +FinalRenderViewportTab::FinalRenderViewportTab( + ProjectExplorer& project_explorer, + Project& project, + RenderingManager& rendering_manager, + LightPathsManager& light_paths_manager, + OCIO::ConstConfigRcPtr ocio_config, + renderer::ParamArray application_settings) + : ViewportTab( + project_explorer, + project, + rendering_manager, + ocio_config, + application_settings) + , m_light_paths_manager(light_paths_manager) { - setObjectName("render_widget_tab"); + setObjectName("final_render_viewport_tab"); setLayout(new QGridLayout()); layout()->setSpacing(0); layout()->setMargin(0); - create_render_widget(); + create_viewport_canvas(); create_toolbar(); create_scrollarea(); - layout()->addWidget(m_toolbar); - layout()->addWidget(m_scroll_area); - recreate_handlers(); -} -RenderWidget* RenderTab::get_render_widget() const -{ - return m_render_widget; -} + layout()->addWidget(m_toolbar); + layout()->addWidget(m_light_paths_viewport_toolbar->toolbar()); + layout()->addWidget(m_scroll_area); -CameraController* RenderTab::get_camera_controller() const -{ - return m_camera_controller.get(); + get_viewport_canvas()->set_base_layer(ViewportCanvas::BaseLayer::FinalRender); } -ScenePickingHandler* RenderTab::get_scene_picking_handler() const +ViewportCanvas* FinalRenderViewportTab::get_viewport_canvas() const { - return m_scene_picking_handler.get(); + return m_viewport_canvas; } -void RenderTab::set_clear_frame_button_enabled(const bool enabled) +void FinalRenderViewportTab::set_clear_frame_button_enabled(const bool enabled) { m_clear_frame_button->setEnabled(enabled); } -void RenderTab::set_render_region_buttons_enabled(const bool enabled) +void FinalRenderViewportTab::set_render_region_buttons_enabled(const bool enabled) { m_set_render_region_button->setEnabled(enabled); m_clear_render_region_button->setEnabled(enabled); } -void RenderTab::clear() +void FinalRenderViewportTab::render_began() { - m_render_widget->clear(); - m_render_widget->repaint(); + ViewportTab::render_began(); + + m_light_paths_viewport_toolbar.get()->reset(&m_project); } -void RenderTab::darken() +void FinalRenderViewportTab::update_size() { - m_render_widget->multiply(0.2f); + ViewportTab::update_size(); + + m_set_render_region_button->setChecked(false); + + recreate_handlers(); } -void RenderTab::reset_zoom() +void FinalRenderViewportTab::on_tab_selected() { - m_zoom_handler->reset_zoom(); + const bool display_light_paths = m_light_paths_manager.should_display_light_paths(); + m_light_paths_viewport_toolbar->set_enabled(display_light_paths); + m_light_paths_toggle_button->setChecked(display_light_paths); } -void RenderTab::update() +CameraController* FinalRenderViewportTab::get_camera_controller() const { - m_render_widget->update(); + return m_camera_controller.get(); } -void RenderTab::update_size() +ScenePickingHandler* FinalRenderViewportTab::get_scene_picking_handler() const { - m_set_render_region_button->setChecked(false); - - const CanvasProperties& props = m_project.get_frame()->image().properties(); - - m_render_widget->resize( - props.m_canvas_width, - props.m_canvas_height); - - recreate_handlers(); + return m_scene_picking_handler.get(); } -RenderTab::State RenderTab::save_state() const +void FinalRenderViewportTab::slot_camera_changed() { - State state; - state.m_zoom_handler_state = m_zoom_handler->save_state(); - state.m_pan_handler_state = m_pan_handler->save_state(); - return state; + m_viewport_canvas->get_light_paths_layer()->set_transform(m_camera_controller->get_transform()); + m_viewport_canvas->get_gl_scene_layer()->set_transform(m_camera_controller->get_transform()); + update(); } -void RenderTab::load_state(const State& state) +void FinalRenderViewportTab::slot_toggle_render_region(const bool checked) { - // The order matters here. - m_zoom_handler->load_state(state.m_zoom_handler_state); - m_pan_handler->load_state(state.m_pan_handler_state); + m_scene_picking_handler->set_enabled(!checked); + m_viewport_selection_handler->set_mode( + checked + ? ViewportRegionSelectionHandler::RenderRegionMode + : ViewportRegionSelectionHandler::RectangleSelectionMode); } -void RenderTab::slot_render_widget_context_menu(const QPoint& point) +void FinalRenderViewportTab::slot_toggle_light_paths(const bool checked) { - emit signal_render_widget_context_menu(m_render_widget->mapToGlobal(point)); + m_light_paths_picking_handler->set_enabled(checked); + m_light_paths_viewport_toolbar->set_enabled(checked); + m_scene_picking_handler->set_enabled(!checked); + m_light_paths_manager.display_light_paths(checked); } -void RenderTab::slot_toggle_render_region(const bool checked) +void FinalRenderViewportTab::slot_toggle_pixel_inspector(const bool checked) { - m_scene_picking_handler->set_enabled(!checked); - m_render_region_handler->set_mode( - checked - ? RenderRegionHandler::RenderRegionMode - : RenderRegionHandler::RectangleSelectionMode); + m_pixel_inspector_handler->set_enabled(checked); + m_pixel_inspector_handler->update_tooltip_visibility(); } -void RenderTab::slot_set_render_region(const QRect& rect) +void FinalRenderViewportTab::slot_set_render_region(const QRect& rect) { m_set_render_region_button->setChecked(false); emit signal_set_render_region(rect); } -void RenderTab::slot_toggle_pixel_inspector(const bool checked) +void FinalRenderViewportTab::slot_viewport_canvas_context_menu(const QPoint& point) { - m_pixel_inspector_handler->set_enabled(checked); - m_pixel_inspector_handler->update_tooltip_visibility(); + emit signal_viewport_canvas_context_menu(m_viewport_canvas->mapToGlobal(point)); } -void RenderTab::create_render_widget() +void FinalRenderViewportTab::slot_clear_frame() +{ + m_light_paths_toggle_button->setChecked(false); + m_light_paths_toggle_button->setEnabled(false); + m_light_paths_picking_handler->set_enabled(false); + m_light_paths_viewport_toolbar->set_enabled(false); + m_scene_picking_handler->set_enabled(false); + m_light_paths_manager.clear_light_paths_selection(); + + emit signal_clear_frame(); +} + +void FinalRenderViewportTab::create_viewport_canvas() { const CanvasProperties& props = m_project.get_frame()->image().properties(); - m_render_widget = - new RenderWidget( + m_viewport_canvas = + new ViewportCanvas( + m_project, props.m_canvas_width, props.m_canvas_height, - m_ocio_config); + m_ocio_config, + m_light_paths_manager, + this); - m_render_widget->setContextMenuPolicy(Qt::CustomContextMenu); + m_viewport_canvas->setContextMenuPolicy(Qt::CustomContextMenu); connect( - m_render_widget, SIGNAL(customContextMenuRequested(const QPoint&)), - SLOT(slot_render_widget_context_menu(const QPoint&))); + m_viewport_canvas, &ViewportCanvas::customContextMenuRequested, + this, &FinalRenderViewportTab::slot_viewport_canvas_context_menu); - m_render_widget->setMouseTracking(true); + m_viewport_canvas->setMouseTracking(true); } -void RenderTab::create_toolbar() +void FinalRenderViewportTab::create_toolbar() { + // Create the light path toolbar. + m_light_paths_viewport_toolbar.reset( + new LightPathsViewportToolbar( + this, + &m_project, + m_light_paths_manager)); + // Create the render toolbar. m_toolbar = new QToolBar(); m_toolbar->setObjectName("render_toolbar"); m_toolbar->setIconSize(QSize(18, 18)); + // Display Light Paths button. + m_light_paths_toggle_button = new QToolButton(); + m_light_paths_toggle_button->setText("Display Light Paths Overlay"); + m_light_paths_toggle_button->setCheckable(true); + connect( + m_light_paths_toggle_button, &QToolButton::toggled, + this, &FinalRenderViewportTab::slot_toggle_light_paths); + m_toolbar->addWidget(m_light_paths_toggle_button); + + m_toolbar->addSeparator(); + // Save Frame and AOVs button. QToolButton* save_aovs_button = new QToolButton(); save_aovs_button->setIcon(load_icons("rendertab_save_all_aovs")); save_aovs_button->setToolTip("Save Frame and AOVs..."); connect( - save_aovs_button, SIGNAL(clicked()), - SIGNAL(signal_save_frame_and_aovs())); + save_aovs_button, &QToolButton::clicked, + this, &FinalRenderViewportTab::signal_save_frame_and_aovs); m_toolbar->addWidget(save_aovs_button); // Quicksave Frame and AOVs button. @@ -241,8 +257,8 @@ void RenderTab::create_toolbar() quicksave_aovs_button->setIcon(load_icons("rendertab_quicksave_all_aovs")); quicksave_aovs_button->setToolTip("Quicksave Frame and AOVs"); connect( - quicksave_aovs_button, SIGNAL(clicked()), - SIGNAL(signal_quicksave_frame_and_aovs())); + quicksave_aovs_button, &QToolButton::clicked, + this, &FinalRenderViewportTab::signal_quicksave_frame_and_aovs); m_toolbar->addWidget(quicksave_aovs_button); m_toolbar->addSeparator(); @@ -254,8 +270,8 @@ void RenderTab::create_toolbar() m_set_render_region_button->setToolTip(combine_name_and_shortcut("Set Render Region", m_set_render_region_button->shortcut())); m_set_render_region_button->setCheckable(true); connect( - m_set_render_region_button, SIGNAL(toggled(bool)), - SLOT(slot_toggle_render_region(const bool))); + m_set_render_region_button, &QToolButton::toggled, + this, &FinalRenderViewportTab::slot_toggle_render_region); m_toolbar->addWidget(m_set_render_region_button); // Clear Render Region button. @@ -264,8 +280,8 @@ void RenderTab::create_toolbar() m_clear_render_region_button->setShortcut(Qt::Key_C); m_clear_render_region_button->setToolTip(combine_name_and_shortcut("Clear Render Region", m_clear_render_region_button->shortcut())); connect( - m_clear_render_region_button, SIGNAL(clicked()), - SIGNAL(signal_clear_render_region())); + m_clear_render_region_button, &QToolButton::clicked, + this, &FinalRenderViewportTab::signal_clear_render_region); m_toolbar->addWidget(m_clear_render_region_button); // Clear Frame button. @@ -274,8 +290,8 @@ void RenderTab::create_toolbar() m_clear_frame_button->setShortcut(Qt::Key_X); m_clear_frame_button->setToolTip(combine_name_and_shortcut("Clear Frame", m_clear_frame_button->shortcut())); connect( - m_clear_frame_button, SIGNAL(clicked()), - SIGNAL(signal_clear_frame())); + m_clear_frame_button, &QToolButton::clicked, + this, &FinalRenderViewportTab::slot_clear_frame); m_toolbar->addWidget(m_clear_frame_button); m_toolbar->addSeparator(); @@ -286,8 +302,8 @@ void RenderTab::create_toolbar() reset_zoom_button->setShortcut(Qt::Key_Asterisk); reset_zoom_button->setToolTip(combine_name_and_shortcut("Reset Zoom", reset_zoom_button->shortcut())); connect( - reset_zoom_button, SIGNAL(clicked()), - SIGNAL(signal_reset_zoom())); + reset_zoom_button, &QToolButton::clicked, + this, &FinalRenderViewportTab::signal_reset_zoom); m_toolbar->addWidget(reset_zoom_button); m_toolbar->addSeparator(); @@ -300,8 +316,8 @@ void RenderTab::create_toolbar() pixel_inspector_button->setCheckable(true); pixel_inspector_button->setChecked(false); connect( - pixel_inspector_button, SIGNAL(toggled(bool)), - SLOT(slot_toggle_pixel_inspector(const bool))); + pixel_inspector_button, &QToolButton::toggled, + this, &FinalRenderViewportTab::slot_toggle_pixel_inspector); m_toolbar->addWidget(pixel_inspector_button); m_toolbar->addSeparator(); @@ -320,12 +336,12 @@ void RenderTab::create_toolbar() m_toolbar->addSeparator(); // Create the label preceding the display combobox. - QLabel* display_label = new QLabel("Display:"); + QLabel* display_label = new QLabel("Display Transform:"); display_label->setObjectName("display_label"); m_toolbar->addWidget(display_label); // Create the display combobox. - QComboBox* m_display_transform_combo = new QComboBox(); + m_display_transform_combo = new QComboBox(); m_display_transform_combo->setObjectName("display_combo"); { const char* display_name = m_ocio_config->getDefaultDisplay(); @@ -345,8 +361,8 @@ void RenderTab::create_toolbar() } m_toolbar->addWidget(m_display_transform_combo); connect( - m_display_transform_combo, SIGNAL(currentIndexChanged(QString)), - m_render_widget, SLOT(slot_display_transform_changed(QString))); + m_display_transform_combo, qOverload(&QComboBox::currentIndexChanged), + m_viewport_canvas, &ViewportCanvas::slot_display_transform_changed); // Add stretchy spacer. // This places interactive widgets on the left and info on the right. @@ -384,7 +400,7 @@ void RenderTab::create_toolbar() m_toolbar->addWidget(m_a_label); } -void RenderTab::create_scrollarea() +void FinalRenderViewportTab::create_scrollarea() { // Encapsulate the render widget into another widget that adds a margin around it. QWidget* render_widget_wrapper = new QWidget(); @@ -392,7 +408,7 @@ void RenderTab::create_scrollarea() render_widget_wrapper->setLayout(new QGridLayout()); render_widget_wrapper->layout()->setSizeConstraint(QLayout::SetFixedSize); render_widget_wrapper->layout()->setContentsMargins(20, 20, 20, 20); - render_widget_wrapper->layout()->addWidget(m_render_widget); + render_widget_wrapper->layout()->addWidget(m_viewport_canvas); // Wrap the render widget in a scroll area. m_scroll_area = new QScrollArea(); @@ -401,13 +417,13 @@ void RenderTab::create_scrollarea() m_scroll_area->setWidget(render_widget_wrapper); } -void RenderTab::recreate_handlers() +void FinalRenderViewportTab::recreate_handlers() { // Handler for zooming the render widget in and out with the keyboard or the mouse wheel. m_zoom_handler.reset( new WidgetZoomHandler( m_scroll_area, - m_render_widget)); + m_viewport_canvas)); // Handler for panning the render widget with the mouse. m_pan_handler.reset( @@ -417,13 +433,13 @@ void RenderTab::recreate_handlers() // Handler for tracking and displaying mouse coordinates. m_mouse_tracker.reset( new MouseCoordinatesTracker( - m_render_widget, + m_viewport_canvas, m_info_label)); - // Handle for tracking and displaying the color of the pixel under the mouse cursor. + // Handler for tracking and displaying the color of the pixel under the mouse cursor. m_pixel_color_tracker.reset( new PixelColorTracker( - m_render_widget, + m_viewport_canvas, m_r_label, m_g_label, m_b_label, @@ -434,74 +450,97 @@ void RenderTab::recreate_handlers() // Handler for pixel inspection in the render widget. m_pixel_inspector_handler.reset( new PixelInspectorHandler( - m_render_widget, + m_viewport_canvas, *m_mouse_tracker.get(), m_project)); // Camera handler. m_camera_controller.reset( new CameraController( - m_render_widget, + m_viewport_canvas, m_project)); connect( - m_camera_controller.get(), SIGNAL(signal_camera_change_begin()), - SIGNAL(signal_camera_change_begin())); + m_camera_controller.get(), &CameraController::signal_camera_change_begin, + this, &FinalRenderViewportTab::signal_camera_change_begin); + connect( + m_camera_controller.get(), &CameraController::signal_camera_change_end, + this, &FinalRenderViewportTab::signal_camera_change_end); connect( - m_camera_controller.get(), SIGNAL(signal_camera_change_end()), - SIGNAL(signal_camera_change_end())); + m_camera_controller.get(), &CameraController::signal_camera_changed, + this, &FinalRenderViewportTab::signal_camera_changed); connect( - m_camera_controller.get(), SIGNAL(signal_camera_changed()), - SIGNAL(signal_camera_changed())); + m_camera_controller.get(), &CameraController::signal_camera_changed, + this, &FinalRenderViewportTab::slot_camera_changed); connect( - &m_project_explorer, SIGNAL(signal_frame_modified()), - m_camera_controller.get(), SLOT(slot_frame_modified())); + &m_project_explorer, &ProjectExplorer::signal_frame_modified, + m_camera_controller.get(), &CameraController::slot_frame_modified); // Handler for picking scene entities in the render widget. m_scene_picking_handler.reset( new ScenePickingHandler( - m_render_widget, + m_viewport_canvas, m_picking_mode_combo, *m_mouse_tracker.get(), m_project_explorer, m_project)); connect( - m_scene_picking_handler.get(), SIGNAL(signal_entity_picked(renderer::ScenePicker::PickingResult)), - SIGNAL(signal_entity_picked(renderer::ScenePicker::PickingResult))); + m_scene_picking_handler.get(), &ScenePickingHandler::signal_entity_picked, + this, &FinalRenderViewportTab::signal_entity_picked); connect( - m_scene_picking_handler.get(), SIGNAL(signal_entity_picked(renderer::ScenePicker::PickingResult)), - m_camera_controller.get(), SLOT(slot_entity_picked(renderer::ScenePicker::PickingResult))); + m_scene_picking_handler.get(), &ScenePickingHandler::signal_entity_picked, + m_camera_controller.get(), &CameraController::slot_entity_picked); - // Handler for setting render regions with the mouse. - m_render_region_handler.reset( - new RenderRegionHandler( - m_render_widget, - *m_mouse_tracker.get())); - connect( - m_render_region_handler.get(), SIGNAL(signal_rectangle_selection(const QRect&)), - SIGNAL(signal_rectangle_selection(const QRect&))); - connect( - m_render_region_handler.get(), SIGNAL(signal_render_region(const QRect&)), - SLOT(slot_set_render_region(const QRect&))); + // Light paths picking handler. + m_light_paths_picking_handler.reset( + new LightPathsPickingHandler( + m_light_paths_manager, + m_viewport_canvas, + m_project)); + m_light_paths_picking_handler->set_enabled(false); // Clipboard handler. - m_clipboard_handler.reset(new RenderClipboardHandler(m_render_widget, m_render_widget)); + m_clipboard_handler.reset(new RenderClipboardHandler(m_viewport_canvas, m_viewport_canvas)); // Material drop handler. m_material_drop_handler.reset( new MaterialDropHandler( m_project, m_rendering_manager)); + + // Handler for setting render regions with the mouse. + m_viewport_selection_handler.reset( + new ViewportRegionSelectionHandler( + m_viewport_canvas, + *m_mouse_tracker.get())); connect( - m_render_widget, SIGNAL(signal_material_dropped(const foundation::Vector2d&, const QString&)), - m_material_drop_handler.get(), SLOT(slot_material_dropped(const foundation::Vector2d&, const QString&))); + m_viewport_selection_handler.get(), &ViewportRegionSelectionHandler::signal_rectangle_selection, + m_light_paths_picking_handler.get(), &LightPathsPickingHandler::slot_rectangle_selection); + connect( + m_viewport_selection_handler.get(), &ViewportRegionSelectionHandler::signal_render_region, + this, &FinalRenderViewportTab::slot_set_render_region); + connect( + m_viewport_selection_handler.get(), &ViewportRegionSelectionHandler::signal_render_region, + this, &FinalRenderViewportTab::slot_set_render_region); // Set initial state. m_pixel_inspector_handler->set_enabled(false); m_camera_controller->set_enabled(false); m_scene_picking_handler->set_enabled(true); + + connect( + m_viewport_canvas, &ViewportCanvas::signal_material_dropped, + m_material_drop_handler.get(), &MaterialDropHandler::slot_material_dropped); +} + +void FinalRenderViewportTab::set_light_paths_toggle_enabled(const bool enabled) +{ + if (!enabled) + m_light_paths_toggle_button->setChecked(false); + + m_light_paths_toggle_button->setDisabled(!enabled); } } // namespace studio } // namespace appleseed -#include "mainwindow/rendering/moc_cpp_rendertab.cxx" +#include "mainwindow/rendering/moc_cpp_finalrenderviewporttab.cxx" diff --git a/src/appleseed.studio/mainwindow/rendering/rendertab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h similarity index 63% rename from src/appleseed.studio/mainwindow/rendering/rendertab.h rename to src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index 62008a2979..20daa7b0f0 100644 --- a/src/appleseed.studio/mainwindow/rendering/rendertab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -5,8 +5,7 @@ // // This software is released under the MIT license. // -// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited -// Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization +// Copyright (c) 2020 Kevin Masson, The appleseedhq Organization // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -30,93 +29,59 @@ #pragma once // appleseed.studio headers. -#include "mainwindow/rendering/cameracontroller.h" -#include "mainwindow/rendering/materialdrophandler.h" -#include "mainwindow/rendering/pixelcolortracker.h" -#include "mainwindow/rendering/pixelinspectorhandler.h" -#include "mainwindow/rendering/renderclipboardhandler.h" -#include "mainwindow/rendering/renderregionhandler.h" -#include "mainwindow/rendering/scenepickinghandler.h" - -// appleseed.qtcommon headers. -#include "widgets/mousecoordinatestracker.h" -#include "widgets/scrollareapanhandler.h" -#include "widgets/widgetzoomhandler.h" +#include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/viewporttab.h" // OpenColorIO headers. #include namespace OCIO = OCIO_NAMESPACE; -// Qt headers. -#include -#include - -// Standard headers. -#include - // Forward declarations. +namespace appleseed { namespace studio { class LightPathsPickingHandler; } } namespace appleseed { namespace studio { class ProjectExplorer; } } namespace appleseed { namespace studio { class RenderingManager; } } -namespace appleseed { namespace studio { class RenderWidget; } } namespace renderer { class Project; } -class QComboBox; -class QLabel; -class QPoint; -class QRect; -class QScrollArea; -class QToolBar; class QToolButton; namespace appleseed { namespace studio { -// -// A tab wrapping a render widget and its toolbar. -// - -class RenderTab - : public QWidget +class FinalRenderViewportTab + : public ViewportTab { Q_OBJECT public: - RenderTab( - ProjectExplorer& project_explorer, - renderer::Project& project, - RenderingManager& rendering_manager, - OCIO::ConstConfigRcPtr ocio_config); + FinalRenderViewportTab( + ProjectExplorer& project_explorer, + renderer::Project& project, + RenderingManager& rendering_manager, + LightPathsManager& light_paths_manager, + OCIO::ConstConfigRcPtr ocio_config, + renderer::ParamArray application_settings); + + ViewportCanvas* get_viewport_canvas() const override; + + void set_light_paths_toggle_enabled(const bool enabled); + + void render_began() override; + void update_size() override; + void on_tab_selected() override; - RenderWidget* get_render_widget() const; CameraController* get_camera_controller() const; ScenePickingHandler* get_scene_picking_handler() const; void set_clear_frame_button_enabled(const bool enabled); void set_render_region_buttons_enabled(const bool enabled); - void clear(); - void darken(); - void reset_zoom(); - - void update(); - void update_size(); - - struct State - { - qtcommon::WidgetZoomHandler::State m_zoom_handler_state; - qtcommon::ScrollAreaPanHandler::State m_pan_handler_state; - }; - - State save_state() const; - void load_state(const State& state); - signals: void signal_save_frame_and_aovs(); void signal_quicksave_frame_and_aovs(); void signal_set_render_region(const QRect& rect); void signal_clear_render_region(); - void signal_render_widget_context_menu(const QPoint& point); void signal_reset_zoom(); void signal_clear_frame(); + void signal_viewport_canvas_context_menu(const QPoint& point); void signal_camera_change_begin(); void signal_camera_changed(); @@ -126,43 +91,45 @@ class RenderTab void signal_rectangle_selection(const QRect& rect); private slots: - void slot_render_widget_context_menu(const QPoint& point); + void slot_camera_changed(); + void slot_toggle_pixel_inspector(const bool checked); void slot_toggle_render_region(const bool checked); + void slot_toggle_light_paths(const bool checked); void slot_set_render_region(const QRect& rect); - void slot_toggle_pixel_inspector(const bool checked); + void slot_viewport_canvas_context_menu(const QPoint& point); + void slot_clear_frame(); private: - RenderWidget* m_render_widget; - QScrollArea* m_scroll_area; - QToolBar* m_toolbar; + ViewportCanvas* m_viewport_canvas; QToolButton* m_set_render_region_button; QToolButton* m_clear_render_region_button; QToolButton* m_clear_frame_button; + QScrollArea* m_scroll_area; + QToolBar* m_toolbar; + QToolButton* m_light_paths_toggle_button; QComboBox* m_picking_mode_combo; + QComboBox* m_display_transform_combo; + QComboBox* m_base_layer_combo; QLabel* m_info_label; QLabel* m_r_label; QLabel* m_g_label; QLabel* m_b_label; QLabel* m_a_label; - ProjectExplorer& m_project_explorer; - renderer::Project& m_project; - RenderingManager& m_rendering_manager; - - std::unique_ptr m_zoom_handler; - std::unique_ptr m_pan_handler; std::unique_ptr m_material_drop_handler; std::unique_ptr m_mouse_tracker; std::unique_ptr m_pixel_color_tracker; std::unique_ptr m_pixel_inspector_handler; std::unique_ptr m_camera_controller; std::unique_ptr m_scene_picking_handler; - std::unique_ptr m_render_region_handler; + std::unique_ptr m_viewport_selection_handler; std::unique_ptr m_clipboard_handler; - OCIO::ConstConfigRcPtr m_ocio_config; + LightPathsManager& m_light_paths_manager; + std::unique_ptr m_light_paths_viewport_toolbar; + std::unique_ptr m_light_paths_picking_handler; - void create_render_widget(); + void create_viewport_canvas(); void create_toolbar(); void create_scrollarea(); void recreate_handlers(); diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathswidget.cpp b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp similarity index 52% rename from src/appleseed.studio/mainwindow/rendering/lightpathswidget.cpp rename to src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp index 953052b245..fe8b6ec4e0 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathswidget.cpp +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp @@ -5,7 +5,7 @@ // // This software is released under the MIT license. // -// Copyright (c) 2018 Francois Beaune, The appleseedhq Organization +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -27,11 +27,14 @@ // // Interface header. -#include "lightpathswidget.h" +#include "glscenelayer.h" // appleseed.qtcommon headers. #include "utility/miscellaneous.h" +// appleseed.studio headers. +#include "utility/gl.h" + // appleseed.renderer headers. #include "renderer/api/camera.h" #include "renderer/api/entity.h" @@ -51,7 +54,9 @@ // Qt headers. #include -#include +#include +#include +#include #include #include @@ -59,7 +64,6 @@ #include #include -using namespace appleseed::qtcommon; using namespace foundation; using namespace renderer; @@ -129,115 +133,50 @@ namespace }; } -LightPathsWidget::LightPathsWidget( - const Project& project, - const size_t width, - const size_t height) +GLSceneLayer::GLSceneLayer( + const Project& project, + const size_t width, + const size_t height) : m_project(project) , m_camera(*m_project.get_uncached_active_camera()) , m_backface_culling_enabled(false) - , m_selected_light_path_index(-1) - , m_gl_initialized(false) + , m_initialized(false) { - setFocusPolicy(Qt::StrongFocus); - setFixedWidth(static_cast(width)); - setFixedHeight(static_cast(height)); - + m_camera.transform_sequence().prepare(); const float time = m_camera.get_shutter_middle_time(); set_transform(m_camera.transform_sequence().evaluate(time)); } -QImage LightPathsWidget::capture() +GLSceneLayer::~GLSceneLayer() { - return grabFramebuffer(); + cleanup_gl_data(); } -void LightPathsWidget::set_transform(const Transformd& transform) +void GLSceneLayer::set_gl_functions(QOpenGLFunctions_4_1_Core* functions) { - m_camera_matrix = transform.get_parent_to_local(); - m_gl_view_matrix = transpose(m_camera_matrix); + m_gl = functions; } -void LightPathsWidget::set_light_paths(const LightPathArray& light_paths) +void GLSceneLayer::set_transform(const Transformd& transform) { - m_light_paths = light_paths; - - if (m_light_paths.size() > 1) - { - // Sort paths by descending radiance at the camera. - const auto& light_path_recorder = m_project.get_light_path_recorder(); - std::sort( - &m_light_paths[0], - &m_light_paths[0] + m_light_paths.size(), - [&light_path_recorder](const LightPath& lhs, const LightPath& rhs) - { - LightPathVertex lhs_v; - light_path_recorder.get_light_path_vertex(lhs.m_vertex_end_index - 1, lhs_v); - - LightPathVertex rhs_v; - light_path_recorder.get_light_path_vertex(rhs.m_vertex_end_index - 1, rhs_v); - - return - sum_value(Color3f::from_array(lhs_v.m_radiance)) > - sum_value(Color3f::from_array(rhs_v.m_radiance)); - }); - } - - // Display all paths by default. - set_selected_light_path_index(-1); - load_light_paths_data(); -} - -void LightPathsWidget::set_selected_light_path_index(const int selected_light_path_index) -{ - m_selected_light_path_index = selected_light_path_index; - - dump_selected_light_path(); - update(); - - emit signal_light_path_selection_changed( - m_selected_light_path_index, - static_cast(m_light_paths.size())); -} - -void LightPathsWidget::slot_display_all_light_paths() -{ - if (m_selected_light_path_index > -1) - set_selected_light_path_index(-1); -} - -void LightPathsWidget::slot_display_previous_light_path() -{ - if (m_selected_light_path_index > -1) - set_selected_light_path_index(m_selected_light_path_index - 1); -} - -void LightPathsWidget::slot_display_next_light_path() -{ - if (m_selected_light_path_index < static_cast(m_light_paths.size()) - 1) - set_selected_light_path_index(m_selected_light_path_index + 1); -} - -void LightPathsWidget::slot_toggle_backface_culling(const bool checked) -{ - m_backface_culling_enabled = checked; - update(); + m_camera_matrix = transform.get_parent_to_local(); + m_gl_view_matrix = transpose(m_camera_matrix); } -void LightPathsWidget::slot_synchronize_camera() +void GLSceneLayer::slot_synchronize_camera() { m_camera.transform_sequence().clear(); m_camera.transform_sequence().set_transform(0.0f, Transformd::from_local_to_parent(inverse(m_camera_matrix))); } -void LightPathsWidget::load_object_instance( +void GLSceneLayer::load_object_instance( const ObjectInstance& object_instance, const Matrix4f& assembly_transform_matrix) { Object* object = object_instance.find_object(); - // This would already be logged in LightPathsWidget::load_scene_data + // This would already be logged in GLSceneLayer::load_scene_data if (object == nullptr) return; @@ -264,13 +203,13 @@ void LightPathsWidget::load_object_instance( reinterpret_cast(&gl_matrix[0])); } -void LightPathsWidget::load_assembly_instance( +void GLSceneLayer::load_assembly_instance( const AssemblyInstance& assembly_instance, const float time) { const Assembly* assembly = assembly_instance.find_assembly(); - // This would already be logged in LightPathsWidget::load_scene_data + // This would already be logged in GLSceneLayer::load_scene_data if (assembly == nullptr) return; @@ -285,7 +224,7 @@ void LightPathsWidget::load_assembly_instance( load_assembly_instance(child_assembly_instance, time); } -void LightPathsWidget::load_object_data(const Object& object) +void GLSceneLayer::load_object_data(const Object& object) { const std::string obj_name = std::string(object.get_name()); RENDERER_LOG_DEBUG("opengl: uploading mesh data for object \"%s\"...", obj_name.c_str()); @@ -334,7 +273,7 @@ void LightPathsWidget::load_object_data(const Object& object) } } -void LightPathsWidget::load_assembly_data(const Assembly& assembly) +void GLSceneLayer::load_assembly_data(const Assembly& assembly) { for (const auto& object : assembly.objects()) load_object_data(object); @@ -343,7 +282,7 @@ void LightPathsWidget::load_assembly_data(const Assembly& assembly) load_assembly_data(child_assembly); } -void LightPathsWidget::load_scene_data() +void GLSceneLayer::load_scene_data() { const float time = m_camera.get_shutter_middle_time(); @@ -362,9 +301,10 @@ void LightPathsWidget::load_scene_data() } // Generate instance buffers for each object - m_gl->glGenBuffers( - static_cast(m_scene_object_instance_vbos.size()), - &m_scene_object_instance_vbos[0]); + if (m_scene_object_instance_vbos.size() > 0) + m_gl->glGenBuffers( + static_cast(m_scene_object_instance_vbos.size()), + &m_scene_object_instance_vbos[0]); // Figure out how many instances of each mesh are required for all assembly instances for (const auto& assembly_instance : m_project.get_scene()->assembly_instances()) @@ -434,189 +374,32 @@ void LightPathsWidget::load_scene_data() load_assembly_instance(assembly_instance, time); } -void LightPathsWidget::load_light_paths_data() -{ - m_light_paths_index_offsets.clear(); - if (!m_light_paths.empty()) - { - m_light_paths_index_offsets.push_back(0); - - const auto& light_path_recorder = m_project.get_light_path_recorder(); - - const size_t total_gl_vertex_count = 2 * (light_path_recorder.get_vertex_count() - 2) + 2; - GLsizei total_index_count = 0; - std::vector buffer; - buffer.reserve(total_gl_vertex_count * LightPathVertexFloatStride); - for (size_t light_path_idx = 0; light_path_idx < m_light_paths.size(); light_path_idx++) - { - const auto& path = m_light_paths[light_path_idx]; - assert(path.m_vertex_end_index - path.m_vertex_begin_index >= 2); - - LightPathVertex prev; - light_path_recorder.get_light_path_vertex(path.m_vertex_begin_index, prev); - for (size_t vertex_idx = path.m_vertex_begin_index + 1; vertex_idx < path.m_vertex_end_index; vertex_idx++) - { - LightPathVertex curr; - light_path_recorder.get_light_path_vertex(vertex_idx, curr); - - auto piece_radiance = Color3f::from_array(curr.m_radiance); - piece_radiance /= piece_radiance + Color3f(1.0f); // Reinhard tone mapping - piece_radiance = linear_rgb_to_srgb(piece_radiance); - - const float temp_store[LightPathVertexLineFloatStride] = - { - prev.m_position[0], prev.m_position[1], prev.m_position[2], - piece_radiance[0], piece_radiance[1], piece_radiance[2], - - curr.m_position[0], curr.m_position[1], curr.m_position[2], - piece_radiance[0], piece_radiance[1], piece_radiance[2], - }; - buffer.insert(buffer.end(), temp_store, temp_store + 12); - - total_index_count += 2; - prev = curr; - } - m_light_paths_index_offsets.push_back(total_index_count); - } - - m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_light_paths_vbo); - m_gl->glBufferData( - GL_ARRAY_BUFFER, - buffer.size() * sizeof(float), - reinterpret_cast(&buffer[0]), - GL_STATIC_DRAW); - } -} - -namespace +void GLSceneLayer::init_gl(QSurfaceFormat format) { - std::string shader_kind_to_string(const GLint shader_kind) - { - switch (shader_kind) - { - case GL_VERTEX_SHADER: - return "Vertex"; - case GL_FRAGMENT_SHADER: - return "Fragment"; - default: - return "Unknown Kind"; - } - } - - void compile_shader( - QOpenGLFunctions_3_3_Core* f, - const GLuint shader, - const GLsizei count, - const GLchar** src_string, - const GLint* length) - { - f->glShaderSource(shader, count, src_string, length); - f->glCompileShader(shader); - GLint success; - f->glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - - if (!success) - { - char info_log[1024]; - f->glGetShaderInfoLog(shader, 1024, NULL, info_log); - - GLint shader_kind; - f->glGetShaderiv(shader, GL_SHADER_TYPE, &shader_kind); - const std::string shader_kind_string = shader_kind_to_string(shader_kind); - - RENDERER_LOG_ERROR("opengl: %s shader compilation failed:\n%s", shader_kind_string.c_str(), info_log); - } - } - - void link_shader_program( - QOpenGLFunctions_3_3_Core* f, - const GLuint program, - const GLuint vert, - const GLuint frag) - { - f->glAttachShader(program, vert); - f->glAttachShader(program, frag); - f->glLinkProgram(program); - - GLint success; - f->glGetProgramiv(program, GL_LINK_STATUS, &success); - - if (!success) - { - char info_log[1024]; - f->glGetProgramInfoLog(program, 1024, NULL, info_log); - RENDERER_LOG_ERROR("opengl: shader program linking failed:\n%s", info_log); - } - } - - void create_shader_program( - QOpenGLFunctions_3_3_Core* f, - GLuint& program, - const QByteArray& vert_source, - const QByteArray& frag_source) - { - GLuint vert = f->glCreateShader(GL_VERTEX_SHADER); - GLuint frag = f->glCreateShader(GL_FRAGMENT_SHADER); - - auto gl_vert_source = static_cast(vert_source.constData()); - auto gl_vert_source_length = static_cast(vert_source.size()); - - auto gl_frag_source = static_cast(frag_source.constData()); - auto gl_frag_source_length = static_cast(frag_source.size()); - - compile_shader(f, vert, 1, &gl_vert_source, &gl_vert_source_length); - compile_shader(f, frag, 1, &gl_frag_source, &gl_frag_source_length); - - program = f->glCreateProgram(); - link_shader_program(f, program, vert, frag); - - f->glDeleteShader(vert); - f->glDeleteShader(frag); - } -} - -void LightPathsWidget::initializeGL() -{ - m_gl = QOpenGLContext::currentContext()->versionFunctions(); // If there was already previous data, clean up - LightPathsWidget::cleanup_gl_data(); - - const auto qgl_format = format(); - - if (!m_gl->initializeOpenGLFunctions()) - { - const int major_version = qgl_format.majorVersion(); - const int minor_version = qgl_format.minorVersion(); - RENDERER_LOG_ERROR( - "opengl: could not load required gl functions: loaded version %d.%d, required version 3.3.", - major_version, - minor_version); - m_gl_initialized = false; - return; - } - - glEnable(GL_DEPTH_TEST); + GLSceneLayer::cleanup_gl_data(); - glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + auto vertex_shader = load_gl_shader("scene.vert"); + auto fragment_shader = load_gl_shader("scene.frag"); create_shader_program( m_gl, m_scene_shader_program, - load_gl_shader("scene.vert"), - load_gl_shader("scene.frag")); - - create_shader_program( - m_gl, - m_light_paths_shader_program, - load_gl_shader("lightpaths.vert"), - load_gl_shader("lightpaths.frag")); + &vertex_shader, + &fragment_shader); m_scene_view_mat_location = m_gl->glGetUniformLocation(m_scene_shader_program, "u_view"); m_scene_proj_mat_location = m_gl->glGetUniformLocation(m_scene_shader_program, "u_proj"); - m_light_paths_view_mat_location = m_gl->glGetUniformLocation(m_light_paths_shader_program, "u_view"); - m_light_paths_proj_mat_location = m_gl->glGetUniformLocation(m_light_paths_shader_program, "u_proj"); + create_shader_program( + m_gl, + m_depthonly_shader_program, + &vertex_shader, + nullptr); + + m_depthonly_view_mat_location = m_gl->glGetUniformLocation(m_depthonly_shader_program, "u_view"); + m_depthonly_proj_mat_location = m_gl->glGetUniformLocation(m_depthonly_shader_program, "u_proj"); const float z_near = 0.01f; const float z_far = 1000.0f; @@ -638,41 +421,12 @@ void LightPathsWidget::initializeGL() // from the FBO to the default framebuffer, which flips the image. m_gl_proj_matrix = transpose(Matrix4f::make_frustum(top, bottom, left, right, z_near, z_far)); - GLuint temp_light_paths_vao = 0; - GLuint temp_light_paths_vbo = 0; - m_gl->glGenVertexArrays(1, &temp_light_paths_vao); - m_gl->glGenBuffers(1, &temp_light_paths_vbo); - m_light_paths_vao = temp_light_paths_vao; - m_light_paths_vbo = temp_light_paths_vbo; - - m_gl->glBindVertexArray(m_light_paths_vao); - m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_light_paths_vbo); - m_gl->glVertexAttribPointer( - 0, - 3, - GL_FLOAT, - GL_FALSE, - LightPathVertexByteStride, - reinterpret_cast(0)); - m_gl->glVertexAttribPointer( - 1, - 3, - GL_FLOAT, - GL_FALSE, - LightPathVertexByteStride, - reinterpret_cast(LightPathVertexByteStride / 2)); - m_gl->glEnableVertexAttribArray(0); - m_gl->glEnableVertexAttribArray(1); - - m_gl->glBindVertexArray(0); - load_scene_data(); - load_light_paths_data(); - m_gl_initialized = true; + m_initialized = true; } -void LightPathsWidget::cleanup_gl_data() +void GLSceneLayer::cleanup_gl_data() { if (!m_scene_object_vaos.empty()) { @@ -699,9 +453,9 @@ void LightPathsWidget::cleanup_gl_data() { m_gl->glDeleteProgram(m_scene_shader_program); } - if (m_light_paths_shader_program != 0) + if (m_depthonly_shader_program != 0) { - m_gl->glDeleteProgram(m_light_paths_shader_program); + m_gl->glDeleteProgram(m_depthonly_shader_program); } m_scene_object_index_map.clear(); m_scene_object_data_index_counts.clear(); @@ -709,65 +463,78 @@ void LightPathsWidget::cleanup_gl_data() m_scene_object_current_instances.clear(); } -void LightPathsWidget::resizeGL(int w, int h) +void GLSceneLayer::toggle_backface_culling(const bool checked) { - glViewport(0, 0, static_cast(w), static_cast(h)); + m_backface_culling_enabled = checked; } -void LightPathsWidget::paintGL() +void GLSceneLayer::draw() { - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - if (!m_gl_initialized) + if (!m_initialized) return; if (m_backface_culling_enabled) glEnable(GL_CULL_FACE); else glDisable(GL_CULL_FACE); - render_geometry(); - render_light_paths(); -} + m_gl->glDepthMask(GL_FALSE); + m_gl->glEnable(GL_DEPTH_TEST); + m_gl->glDepthFunc(GL_LEQUAL); + m_gl->glUseProgram(m_scene_shader_program); -void LightPathsWidget::keyPressEvent(QKeyEvent* event) -{ - switch (event->key()) - { - // Home key: display all paths. - case Qt::Key_Home: - slot_display_all_light_paths(); - break; - - // Left key: display previous path. - case Qt::Key_Left: - slot_display_previous_light_path(); - break; - - // Right key: display next path. - case Qt::Key_Right: - slot_display_next_light_path(); - break; - - default: - QOpenGLWidget::keyPressEvent(event); - break; - } + m_gl->glUniformMatrix4fv( + m_scene_view_mat_location, + 1, + false, + const_cast(&m_gl_view_matrix[0])); + m_gl->glUniformMatrix4fv( + m_scene_proj_mat_location, + 1, + false, + const_cast(&m_gl_proj_matrix[0])); + + render_scene(); + + m_gl->glDepthMask(GL_TRUE); + + glDisable(GL_CULL_FACE); } -void LightPathsWidget::render_geometry() +void GLSceneLayer::draw_depth_only() { - m_gl->glUseProgram(m_scene_shader_program); + if (!m_initialized) + return; + + if (m_backface_culling_enabled) + glEnable(GL_CULL_FACE); + else glDisable(GL_CULL_FACE); + + m_gl->glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + m_gl->glDepthMask(GL_TRUE); + m_gl->glEnable(GL_DEPTH_TEST); + m_gl->glDepthFunc(GL_LEQUAL); + m_gl->glUseProgram(m_depthonly_shader_program); + m_gl->glUniformMatrix4fv( - m_scene_view_mat_location, + m_depthonly_view_mat_location, 1, false, const_cast(&m_gl_view_matrix[0])); m_gl->glUniformMatrix4fv( - m_scene_proj_mat_location, + m_depthonly_proj_mat_location, 1, false, const_cast(&m_gl_proj_matrix[0])); + render_scene(); + + m_gl->glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + + glDisable(GL_CULL_FACE); +} + +void GLSceneLayer::render_scene() +{ for (size_t i = 0; i < m_scene_object_data_vbos.size(); i++) { GLuint vao = m_scene_object_vaos[i]; @@ -775,7 +542,6 @@ void LightPathsWidget::render_geometry() int instance_count = m_scene_object_instance_counts[i]; m_gl->glBindVertexArray(vao); - m_gl->glDrawArraysInstanced( GL_TRIANGLES, 0, @@ -784,81 +550,5 @@ void LightPathsWidget::render_geometry() } } -void LightPathsWidget::render_light_paths() -{ - if (m_light_paths_index_offsets.size() > 1) - { - m_gl->glUseProgram(m_light_paths_shader_program); - m_gl->glUniformMatrix4fv( - m_light_paths_view_mat_location, - 1, - false, - const_cast(&m_gl_view_matrix[0])); - m_gl->glUniformMatrix4fv( - m_light_paths_proj_mat_location, - 1, - false, - const_cast(&m_gl_proj_matrix[0])); - - m_gl->glBindVertexArray(m_light_paths_vao); - - GLint first; - GLsizei count; - assert(m_selected_light_path_index >= -1); - if (m_selected_light_path_index == -1) - { - first = 0; - count = m_light_paths_index_offsets[m_light_paths_index_offsets.size() - 1]; - } - else - { - first = static_cast(m_light_paths_index_offsets[m_selected_light_path_index]); - count = m_light_paths_index_offsets[m_selected_light_path_index + 1] - first; - } - glDrawArrays(GL_LINES, first, count); - } -} - -void LightPathsWidget::dump_selected_light_path() const -{ - if (m_selected_light_path_index == -1) - { - if (m_light_paths.empty()) - RENDERER_LOG_INFO("no light path to display."); - else - { - RENDERER_LOG_INFO("displaying all %s light path%s.", - pretty_uint(m_light_paths.size()).c_str(), - m_light_paths.size() > 1 ? "s" : ""); - } - } - else - { - RENDERER_LOG_INFO("displaying light path %s:", - pretty_int(m_selected_light_path_index + 1).c_str()); - - const auto& light_path_recorder = m_project.get_light_path_recorder(); - const auto& path = m_light_paths[m_selected_light_path_index]; - - for (size_t i = path.m_vertex_begin_index; i < path.m_vertex_end_index; ++i) - { - LightPathVertex v; - light_path_recorder.get_light_path_vertex(i, v); - - const std::string entity_name = - v.m_entity != nullptr - ? foundation::format("\"{0}\"", v.m_entity->get_path().c_str()) - : "n/a"; - - RENDERER_LOG_INFO(" vertex " FMT_SIZE_T ": entity: %s - position: (%f, %f, %f) - radiance: (%f, %f, %f) - total radiance: %f", - i - path.m_vertex_begin_index + 1, - entity_name.c_str(), - v.m_position[0], v.m_position[1], v.m_position[2], - v.m_radiance[0], v.m_radiance[1], v.m_radiance[2], - v.m_radiance[0] + v.m_radiance[1] + v.m_radiance[2]); - } - } -} - } // namespace studio } // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/glscenelayer.h b/src/appleseed.studio/mainwindow/rendering/glscenelayer.h new file mode 100644 index 0000000000..6f00d449e8 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.h @@ -0,0 +1,150 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// appleseed.studio headers. +#include "mainwindow/rendering/renderclipboardhandler.h" + +// appleseed.renderer headers. +#include "renderer/api/lighting.h" + +// appleseed.foundation headers. +#include "foundation/math/matrix.h" +#include "foundation/math/transform.h" +#include "foundation/math/vector.h" + +// Qt headers. +#include +#include + +// Standard headers. +#include +#include +#include +#include + +// Forward declarations. +namespace renderer { class Assembly; } +namespace renderer { class AssemblyInstance; } +namespace renderer { class Camera; } +namespace renderer { class Object; } +namespace renderer { class ObjectInstance; } +namespace renderer { class Project; } +class QImage; +class QKeyEvent; +class QOpenGLFunctions_4_1_Core; +class QSurfaceFormat; + +namespace appleseed { +namespace studio { + +// +// A widget providing an hardware-accelerated visualization of the loaded scene. +// + +class GLSceneLayer + : public QObject +{ + Q_OBJECT + + public: + GLSceneLayer( + const renderer::Project& project, + const std::size_t width, + const std::size_t height); + + ~GLSceneLayer(); + + void init_gl( + QSurfaceFormat format); + + void set_transform( + const foundation::Transformd& transform); + + void set_gl_functions( + QOpenGLFunctions_4_1_Core* functions); + + void toggle_backface_culling(const bool checked); + + void draw(); + void draw_depth_only(); + + public slots: + void slot_synchronize_camera(); + + private: + const renderer::Project& m_project; + renderer::Camera& m_camera; + foundation::Matrix4d m_camera_matrix; + + bool m_backface_culling_enabled; + + QOpenGLFunctions_4_1_Core* m_gl; + + std::vector m_scene_object_data_vbos; + std::vector m_scene_object_data_index_counts; + std::vector m_scene_object_instance_vbos; + std::vector m_scene_object_instance_counts; + std::vector m_scene_object_current_instances; + std::vector m_scene_object_vaos; + std::unordered_map m_scene_object_index_map; + GLuint m_scene_shader_program; + GLint m_scene_view_mat_location; + GLint m_scene_proj_mat_location; + + GLuint m_depthonly_shader_program; + GLint m_depthonly_view_mat_location; + GLint m_depthonly_proj_mat_location; + + foundation::Matrix4f m_gl_view_matrix; + foundation::Matrix4f m_gl_proj_matrix; + + bool m_initialized; + + void render_scene(); + void cleanup_gl_data(); + void load_scene_data(); + + void load_assembly_data( + const renderer::Assembly& object); + + void load_assembly_instance( + const renderer::AssemblyInstance& assembly_instance, + const float time); + + void load_object_data( + const renderer::Object& object); + + void load_object_instance( + const renderer::ObjectInstance& object_instance, + const foundation::Matrix4f& assembly_transform_matrix); +}; + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp new file mode 100644 index 0000000000..163610385e --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp @@ -0,0 +1,507 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +// Interface header. +#include "lightpathslayer.h" + +// appleseed.studio headers. +#include "utility/gl.h" + +// appleseed.renderer headers. +#include "renderer/api/camera.h" +#include "renderer/api/entity.h" +#include "renderer/api/object.h" +#include "renderer/api/project.h" +#include "renderer/api/rasterization.h" +#include "renderer/api/scene.h" +#include "renderer/api/utility.h" + +// appleseed.foundation headers. +#include "foundation/image/color.h" +#include "foundation/image/colorspace.h" +#include "foundation/math/scalar.h" +#include "foundation/string/string.h" +#include "foundation/utility/api/apistring.h" + +// Qt headers. +#include +#include +#include +#include + +// Standard headers. +#include +#include +#include + +using namespace foundation; +using namespace renderer; + +namespace appleseed { +namespace studio { + +namespace +{ + // Byte stride of a vec3. + constexpr std::size_t Vec3ByteStride = sizeof(float) * 3; + + // Struct of an element of the "others" vertex buffer + struct OtherAttributes { + GLint v_bitmask; + GLfloat v_color[3]; + GLfloat v_surface_normal[3]; + }; +} + +LightPathsLayer::LightPathsLayer( + const Project& project, + const LightPathsManager& light_paths_manager, + const std::size_t width, + const std::size_t height) + : m_project(project) + , m_light_paths_manager(light_paths_manager) + , m_camera(*m_project.get_uncached_active_camera()) + , m_gl_initialized(false) + , m_width(width) + , m_height(height) +{ + const float time = m_camera.get_shutter_middle_time(); + set_transform(m_camera.transform_sequence().evaluate(time)); + + connect( + &m_light_paths_manager, &LightPathsManager::signal_light_path_selection_changed, + this, &LightPathsLayer::slot_light_path_selection_changed); +} + +void LightPathsLayer::resize(const std::size_t width, const std::size_t height) +{ + m_width = width, + m_height = height; +} + +void LightPathsLayer::set_gl_functions(QOpenGLFunctions_4_1_Core* functions) +{ + m_gl = functions; +} + +void LightPathsLayer::update_render_camera_transform() +{ + const float time = m_camera.get_shutter_middle_time(); + m_render_camera_matrix = m_camera.transform_sequence().evaluate(time).get_parent_to_local(); + m_gl_render_view_matrix = transpose(m_render_camera_matrix); +} + +void LightPathsLayer::set_transform(const Transformd& transform) +{ + m_camera_matrix = transform.get_parent_to_local(); + m_gl_view_matrix = transpose(m_camera_matrix); +} + +void LightPathsLayer::slot_synchronize_camera() +{ + m_camera.transform_sequence().clear(); + m_camera.transform_sequence().set_transform( + 0.0f, + Transformd::from_local_to_parent(inverse(m_camera_matrix))); +} + +void LightPathsLayer::slot_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths) +{ + load_light_paths_data(); +} + +void LightPathsLayer::load_light_paths_data() +{ + m_path_terminator_vertex_indices.clear(); + + const renderer::LightPathArray& light_paths = m_light_paths_manager.light_paths(); + + if (!light_paths.empty()) + { + m_path_terminator_vertex_indices.push_back(0); + + const auto& light_path_recorder = m_project.get_light_path_recorder(); + + m_total_triangle_count = 0; + + // Vertex count * 4 since we will be adding two vertices for each point along the line and will + // be adding each point twice for the beginning and end parts of each segment + // Add two because we need extra at the front and back for the extra 'previous' and 'next' attributes + const std::size_t total_gl_vertex_count = 2 * (light_path_recorder.get_vertex_count() + 2); + + std::vector indices; + std::vector positions_buffer; + // * 3 since we want 3 floats per position + positions_buffer.reserve(total_gl_vertex_count * 3); + indices.reserve(total_gl_vertex_count); + + // Add an empty vertex at the beginning to serve as first 'previous' + std::array empty_positions = + { + 0.0, 0.0, 0.0, + 0.0, 0.0, 0.0, + }; + positions_buffer.insert( + positions_buffer.end(), + empty_positions.begin(), + empty_positions.end()); + + std::vector others_buffer; + others_buffer.reserve(total_gl_vertex_count); + std::array others; + + for (size_t light_path_idx = 0; light_path_idx < light_paths.size(); light_path_idx++) + { + const auto& path = light_paths[light_path_idx]; + assert(path.m_vertex_end_index - path.m_vertex_begin_index >= 2); + + LightPathVertex prev; + light_path_recorder.get_light_path_vertex(path.m_vertex_begin_index, prev); + + for (size_t vertex_idx = path.m_vertex_begin_index + 1; vertex_idx < path.m_vertex_end_index; vertex_idx++) + { + LightPathVertex vert; + light_path_recorder.get_light_path_vertex(vertex_idx, vert); + + auto piece_radiance = Color3f::from_array(vert.m_radiance); + piece_radiance = linear_rgb_to_srgb(piece_radiance); + auto piece_luminance = luminance(piece_radiance); + piece_radiance /= piece_luminance; + + std::array positions_temp_store = { + prev.m_position[0], prev.m_position[1], prev.m_position[2], + prev.m_position[0], prev.m_position[1], prev.m_position[2], + vert.m_position[0], vert.m_position[1], vert.m_position[2], + vert.m_position[0], vert.m_position[1], vert.m_position[2], + }; + positions_buffer.insert( + positions_buffer.end(), + positions_temp_store.begin(), + positions_temp_store.end()); + + unsigned int start_index = static_cast(others_buffer.size()); + + GLint end = 2; + + others = {{ + { + 0, + {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + {prev.m_surface_normal[0], prev.m_surface_normal[1], prev.m_surface_normal[2]} + }, + { + 1, + {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + {prev.m_surface_normal[0], prev.m_surface_normal[1], prev.m_surface_normal[2]} + }, + { + end, + {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + {vert.m_surface_normal[0], vert.m_surface_normal[1], vert.m_surface_normal[2]} + }, + { + 1 | end, + {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + {vert.m_surface_normal[0], vert.m_surface_normal[1], vert.m_surface_normal[2]} + }, + }}; + others_buffer.insert( + others_buffer.end(), + others.begin(), + others.end()); + + std::array indices_scratch = { + start_index, start_index + 1, start_index + 2, + start_index + 1, start_index + 2, start_index + 3, + }; + indices.insert( + indices.end(), + indices_scratch.begin(), + indices_scratch.end()); + + m_total_triangle_count += 6; + prev = vert; + } + + m_path_terminator_vertex_indices.push_back(static_cast(others_buffer.size() - 1)); + } + + // Add an empty vertex at the end to serve as last 'next' + positions_buffer.insert( + positions_buffer.end(), + empty_positions.begin(), + empty_positions.end()); + + // Upload the data to the buffers + m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_positions_vbo); + m_gl->glBufferData( + GL_ARRAY_BUFFER, + positions_buffer.size() * sizeof(float), + reinterpret_cast(&positions_buffer[0]), + GL_STATIC_DRAW); + m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_others_vbo); + m_gl->glBufferData( + GL_ARRAY_BUFFER, + others_buffer.size() * sizeof(OtherAttributes), + reinterpret_cast(&others_buffer[0]), + GL_STATIC_DRAW); + m_gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices_ebo); + m_gl->glBufferData( + GL_ELEMENT_ARRAY_BUFFER, + indices.size() * sizeof(unsigned int), + reinterpret_cast(&indices[0]), + GL_STATIC_DRAW); + } +} + +void LightPathsLayer::init_gl(QSurfaceFormat format) +{ + // If there was already previous data, clean up + LightPathsLayer::cleanup_gl_data(); + + glEnable(GL_DEPTH_TEST); + + glClearColor(0.0f, 0.0f, 0.0f, 1.0f); + + auto vertex_shader = load_gl_shader("lightpaths.vert"); + auto fragment_shader = load_gl_shader("lightpaths.frag"); + + create_shader_program( + m_gl, + m_shader_program, + &vertex_shader, + &fragment_shader); + + m_view_mat_loc = m_gl->glGetUniformLocation(m_shader_program, "u_view"); + m_proj_mat_loc = m_gl->glGetUniformLocation(m_shader_program, "u_proj"); + m_res_loc = m_gl->glGetUniformLocation(m_shader_program, "u_res"); + m_first_selected_loc = m_gl->glGetUniformLocation(m_shader_program, "u_first_selected"); + m_last_selected_loc = m_gl->glGetUniformLocation(m_shader_program, "u_last_selected"); + + const float z_near = 0.01f; + const float z_far = 1000.0f; + + const auto& rc = m_camera.get_rasterization_camera(); + + const float fy = tan(rc.m_hfov / rc.m_aspect_ratio * 0.5) * z_near; + const float fx = fy * rc.m_aspect_ratio; + + const float shift_x = rc.m_shift_x * 2.0 * fx; + const float shift_y = rc.m_shift_y * 2.0 * fy; + + const float left = -fx + shift_x; + const float right = fx + shift_x; + const float top = -fy + shift_y; + const float bottom = fy + shift_y; + + // Top and bottom are flipped because QOpenGLWidget draws to a framebuffer object and then blits + // from the FBO to the default framebuffer, which flips the image. + m_gl_proj_matrix = transpose(Matrix4f::make_frustum(top, bottom, left, right, z_near, z_far)); + + GLuint temp_light_paths_vao = 0; + m_gl->glGenVertexArrays(1, &temp_light_paths_vao); + m_light_paths_vao = temp_light_paths_vao; + + GLuint temp_vbos[3] = {0, 0, 0}; + m_gl->glGenBuffers(3, &temp_vbos[0]); + m_positions_vbo = temp_vbos[0]; + m_others_vbo = temp_vbos[1]; + m_indices_ebo = temp_vbos[2]; + + m_gl->glBindVertexArray(m_light_paths_vao); + + m_gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices_ebo); + + // v_previous, v_position, and v_next all reference offsets into the same vertex data buffer. + // v_previous is at vertex offset 0, v_position is at vertex offset 2 and v_next is at vertex offset 4. + // See http://codeflow.org/entries/2012/aug/05/webgl-rendering-of-solid-trails/ for reference. + m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_positions_vbo); + + // vec3 v_previous; + GLint layout_attribute_location = 0; + m_gl->glVertexAttribPointer( + layout_attribute_location, + 3, + GL_FLOAT, + GL_FALSE, + Vec3ByteStride, + reinterpret_cast(0)); + m_gl->glEnableVertexAttribArray(layout_attribute_location); + + // vec3 v_position; + layout_attribute_location = 1; + m_gl->glVertexAttribPointer( + layout_attribute_location, + 3, + GL_FLOAT, + GL_FALSE, + Vec3ByteStride, + reinterpret_cast(Vec3ByteStride * 2)); + m_gl->glEnableVertexAttribArray(layout_attribute_location); + + // vec3 v_next; + layout_attribute_location = 2; + m_gl->glVertexAttribPointer( + layout_attribute_location, + 3, + GL_FLOAT, + GL_FALSE, + Vec3ByteStride, + reinterpret_cast(Vec3ByteStride * 4)); + m_gl->glEnableVertexAttribArray(layout_attribute_location); + + // The rest of the attributes are stored in a separate data buffer, interleaved. + m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_others_vbo); + + // This attribute stores 2 bools: + // bit 0: normal direction which maps to -1.0 (false) or 1.0 (true) + // bit 1: whether this is the end vertex of a new path + // int v_bitmask; + layout_attribute_location = 3; + unsigned long long offset = 0; + m_gl->glVertexAttribIPointer( + layout_attribute_location, + 1, + GL_INT, + sizeof(OtherAttributes), + reinterpret_cast(offset)); + m_gl->glEnableVertexAttribArray(layout_attribute_location); + + // vec3 v_color; + layout_attribute_location = 4; + offset += sizeof(GLint); + m_gl->glVertexAttribPointer( + layout_attribute_location, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(OtherAttributes), + reinterpret_cast(offset)); + m_gl->glEnableVertexAttribArray(layout_attribute_location); + + // vec3 v_surface_normal; + layout_attribute_location = 5; + offset += 3 * sizeof(GLfloat); + m_gl->glVertexAttribPointer( + layout_attribute_location, + 3, + GL_FLOAT, + GL_FALSE, + sizeof(OtherAttributes), + reinterpret_cast(offset)); + m_gl->glEnableVertexAttribArray(layout_attribute_location); + + m_gl->glBindVertexArray(0); + m_gl->glBindBuffer(GL_ARRAY_BUFFER, 0); + + load_light_paths_data(); + + m_gl_initialized = true; +} + +void LightPathsLayer::cleanup_gl_data() +{ + if (m_shader_program != 0) + { + m_gl->glDeleteProgram(m_shader_program); + } +} + +void LightPathsLayer::draw_render_camera() const +{ + auto gl_view_matrix = const_cast(&m_gl_render_view_matrix[0]); + + render_scene(gl_view_matrix); +} + +void LightPathsLayer::draw() const +{ + auto gl_view_matrix = const_cast(&m_gl_view_matrix[0]); + + render_scene(gl_view_matrix); +} + +void LightPathsLayer::render_scene(const GLfloat* gl_view_matrix) const +{ + if (!m_gl_initialized) + return; + + if (m_total_triangle_count > 1) + { + const int selected_light_path_index = m_light_paths_manager.get_selected_light_paths_index(); + + GLint first_selected, last_selected; + + if (selected_light_path_index == -1) + { + first_selected = 0; + last_selected = static_cast(m_path_terminator_vertex_indices[m_path_terminator_vertex_indices.size() - 1]); + } + else + { + assert(m_path_terminator_vertex_indices.size() > selected_light_path_index + 1); + first_selected = static_cast(m_path_terminator_vertex_indices[selected_light_path_index]); + last_selected = static_cast(m_path_terminator_vertex_indices[selected_light_path_index + 1]); + } + + m_gl->glUseProgram(m_shader_program); + + m_gl->glUniformMatrix4fv( + m_view_mat_loc, + 1, + false, + gl_view_matrix); + m_gl->glUniformMatrix4fv( + m_proj_mat_loc, + 1, + false, + const_cast(&m_gl_proj_matrix[0])); + m_gl->glUniform2f( + m_res_loc, + (GLfloat)m_width, + (GLfloat)m_height); + m_gl->glUniform1i( + m_first_selected_loc, + first_selected); + m_gl->glUniform1i( + m_last_selected_loc, + last_selected); + + m_gl->glBindVertexArray(m_light_paths_vao); + + m_gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indices_ebo); + m_gl->glDrawElements(GL_TRIANGLES, m_total_triangle_count, GL_UNSIGNED_INT, static_cast(0)); + m_gl->glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } +} + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h new file mode 100644 index 0000000000..cbe6d12c83 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h @@ -0,0 +1,143 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// appleseed.studio headers. +#include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/renderclipboardhandler.h" + +// appleseed.renderer headers. +#include "renderer/api/lighting.h" + +// appleseed.foundation headers. +#include "foundation/math/matrix.h" +#include "foundation/math/transform.h" +#include "foundation/math/vector.h" + +// Qt headers. +#include +#include + +// Standard headers. +#include +#include +#include +#include + +// Forward declarations. +namespace renderer { class Assembly; } +namespace renderer { class AssemblyInstance; } +namespace renderer { class Camera; } +namespace renderer { class Object; } +namespace renderer { class ObjectInstance; } +namespace renderer { class Project; } +class QKeyEvent; +class QImage; +class QOpenGLFunctions_4_1_Core; + +namespace appleseed { +namespace studio { + +// +// A widget providing an hardware-accelerated visualization of recorded light paths. +// + +class LightPathsLayer: public QObject +{ + Q_OBJECT + + public: + LightPathsLayer( + const renderer::Project& project, + const LightPathsManager& light_paths_manager, + const std::size_t width, + const std::size_t height); + + void resize(const std::size_t width, const std::size_t height); + + void update_render_camera_transform(); + + void set_transform( + const foundation::Transformd& transform); + + void set_gl_functions( + QOpenGLFunctions_4_1_Core* functions); + + void init_gl(QSurfaceFormat format); + + void draw() const; + + void draw_render_camera() const; + + public slots: + void slot_synchronize_camera(); + + private slots: + void slot_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths); + + private: + const renderer::Project& m_project; + const LightPathsManager& m_light_paths_manager; + renderer::Camera& m_camera; + foundation::Matrix4d m_camera_matrix; + foundation::Matrix4d m_render_camera_matrix; + + std::size_t m_width; + std::size_t m_height; + + QOpenGLFunctions_4_1_Core* m_gl; + + GLuint m_positions_vbo; + GLuint m_others_vbo; + GLuint m_indices_ebo; + std::vector m_path_terminator_vertex_indices; // Store the first and last vertex index of each light path. + GLsizei m_total_triangle_count; + GLuint m_light_paths_vao; + GLuint m_shader_program; + GLint m_view_mat_loc; + GLint m_proj_mat_loc; + GLint m_res_loc; + GLint m_first_selected_loc; + GLint m_last_selected_loc; + foundation::Matrix4f m_gl_render_view_matrix; + foundation::Matrix4f m_gl_view_matrix; + foundation::Matrix4f m_gl_proj_matrix; + bool m_gl_initialized; + + void cleanup_gl_data(); + void load_light_paths_data(); + + void render_scene(const GLfloat* gl_view_matrix) const; +}; + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp new file mode 100644 index 0000000000..e92780e57e --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp @@ -0,0 +1,241 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2020 Kevin Masson, The appleseedhq Organization +// +// 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. +// + +// Interface header. +#include "lightpathsmanager.h" + +// appleseed.studio headers. +#include "mainwindow/rendering/lightpathslayer.h" +#include "mainwindow/rendering/viewportcanvas.h" +#include "utility/settingskeys.h" + +// appleseed.qtcommon headers. +#include "utility/miscellaneous.h" + +// appleseed.renderer headers. +#include "renderer/api/frame.h" +#include "renderer/api/lighting.h" +#include "renderer/api/log.h" +#include "renderer/api/project.h" + +// appleseed.foundation headers. +#include "foundation/image/canvasproperties.h" +#include "foundation/image/image.h" +#include "foundation/math/vector.h" +#include "foundation/string/string.h" + +// Qt headers. +#include +#include +#include +#include +#include + +// Standard headers. +#include +#include +#include + +using namespace appleseed::qtcommon; +using namespace foundation; +using namespace renderer; + +namespace appleseed { +namespace studio { + +LightPathsManager::LightPathsManager( + const renderer::Project& project, + renderer::ParamArray& application_settings) + : m_project(project) + , m_application_settings(application_settings) + , m_selected_light_path_index(-1) + , m_display_light_paths(false) +{ +} + +void LightPathsManager::set_light_paths(const LightPathArray& light_paths) +{ + m_light_paths = light_paths; + + if (m_light_paths.size() > 1) + { + // Sort paths by descending radiance at the camera. + const auto& light_path_recorder = m_project.get_light_path_recorder(); + std::sort( + &m_light_paths[0], + &m_light_paths[0] + m_light_paths.size(), + [&light_path_recorder](const LightPath& lhs, const LightPath& rhs) + { + LightPathVertex lhs_v; + light_path_recorder.get_light_path_vertex(lhs.m_vertex_end_index - 1, lhs_v); + + LightPathVertex rhs_v; + light_path_recorder.get_light_path_vertex(rhs.m_vertex_end_index - 1, rhs_v); + + return + sum_value(Color3f::from_array(lhs_v.m_radiance)) > + sum_value(Color3f::from_array(rhs_v.m_radiance)); + }); + } + + set_selected_light_path_index(-1); +} + +void LightPathsManager::clear_light_paths_selection() +{ + m_light_paths.clear(); + set_selected_light_path_index(-1); +} + +void LightPathsManager::display_light_paths(const bool on) +{ + m_display_light_paths = on; + set_selected_light_path_index(m_selected_light_path_index); +} + +bool LightPathsManager::should_display_light_paths() const +{ + return m_display_light_paths; +} + +void LightPathsManager::save_all_light_paths(QWidget* source) const +{ + QString filepath = + get_save_filename( + source, + "Save Light Paths As...", + "Light Paths Files (*.aspaths);;All Files (*.*)", + m_application_settings, + SETTINGS_FILE_DIALOG_LIGHT_PATHS); + + if (filepath.isEmpty()) + return; + + if (QFileInfo(filepath).suffix().isEmpty()) + filepath += ".aspaths"; + + // Write light paths to disk. + m_project.get_light_path_recorder().write(filepath.toUtf8().constData()); +} + +const renderer::LightPathArray& LightPathsManager::light_paths() const +{ + return m_light_paths; +} + +int LightPathsManager::get_selected_light_paths_index() const +{ + return m_selected_light_path_index; +} + +std::size_t LightPathsManager::get_selected_light_paths_count() const +{ + return m_light_paths.size(); +} + +void LightPathsManager::slot_select_all_light_paths() +{ + set_selected_light_path_index(-1); +} + +void LightPathsManager::slot_select_previous_light_path() +{ + if (m_selected_light_path_index > -1) + set_selected_light_path_index(m_selected_light_path_index - 1); +} + +void LightPathsManager::slot_select_next_light_path() +{ + if (m_selected_light_path_index < static_cast(m_light_paths.size()) - 1) + set_selected_light_path_index(m_selected_light_path_index + 1); +} + +void LightPathsManager::slot_clear_light_paths() +{ + m_light_paths.clear(); + set_selected_light_path_index(-1); + + m_project.get_light_path_recorder().clear(); +} + +void LightPathsManager::set_selected_light_path_index(int index) +{ + m_selected_light_path_index = index; + + print_selected_light_paths(); + + emit signal_light_path_selection_changed( + m_display_light_paths, + m_selected_light_path_index, + static_cast(m_light_paths.size())); +} + +void LightPathsManager::print_selected_light_paths() const +{ + if (m_selected_light_path_index == -1) + { + if (m_light_paths.empty()) + RENDERER_LOG_INFO("no light path to display."); + else + { + RENDERER_LOG_INFO("displaying %s light path%s.", + pretty_uint(m_light_paths.size()).c_str(), + m_light_paths.size() > 1 ? "s" : ""); + } + } + else + { + RENDERER_LOG_INFO("displaying light path %s/%s:", + pretty_int(m_selected_light_path_index + 1).c_str(), + pretty_int(m_light_paths.size()).c_str()); + + const auto& light_path_recorder = m_project.get_light_path_recorder(); + const auto& path = m_light_paths[m_selected_light_path_index]; + + for (std::size_t i = path.m_vertex_begin_index; i < path.m_vertex_end_index; ++i) + { + LightPathVertex v; + light_path_recorder.get_light_path_vertex(i, v); + + const std::string entity_name = + v.m_entity != nullptr + ? foundation::format("\"{0}\"", v.m_entity->get_path().c_str()) + : "n/a"; + + RENDERER_LOG_INFO(" vertex " FMT_SIZE_T ": entity: %s - position: (%f, %f, %f) - radiance: (%f, %f, %f) - total radiance: %f", + i - path.m_vertex_begin_index + 1, + entity_name.c_str(), + v.m_position[0], v.m_position[1], v.m_position[2], + v.m_radiance[0], v.m_radiance[1], v.m_radiance[2], + v.m_radiance[0] + v.m_radiance[1] + v.m_radiance[2]); + } + } +} + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h new file mode 100644 index 0000000000..53c2a348ab --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h @@ -0,0 +1,107 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2020 Kevin Masson, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// appleseed.foundation headers. +#include "foundation/math/aabb.h" +#include "foundation/math/vector.h" + +// appleseed.renderer headers. +#include "renderer/api/lighting.h" +#include "renderer/utility/paramarray.h" + +// Qt headers. +#include + +// Forward declarations. +namespace appleseed { namespace studio { class LightPathsLayer; } } +namespace appleseed { namespace studio { class ViewportCanvas; } } +namespace renderer { class Project; } +class QEvent; +class QPoint; +class QWidget; + +namespace appleseed { +namespace studio { + +// +// Keep track of selected light paths. +// + +class LightPathsManager + : public QObject +{ + Q_OBJECT + + public: + LightPathsManager( + const renderer::Project& project, + renderer::ParamArray& application_settings); + + void set_light_paths( + const renderer::LightPathArray& light_paths); + + void clear_light_paths_selection(); + + void display_light_paths(const bool on); + bool should_display_light_paths() const; + + void save_all_light_paths(QWidget* source) const; + + const renderer::LightPathArray& light_paths() const; + + int get_selected_light_paths_index() const; + std::size_t get_selected_light_paths_count() const; + + signals: + void signal_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths) const; + + public slots: + void slot_select_all_light_paths(); + void slot_select_previous_light_path(); + void slot_select_next_light_path(); + void slot_clear_light_paths(); + + private: + const renderer::Project& m_project; + renderer::ParamArray& m_application_settings; + + renderer::LightPathArray m_light_paths; + int m_selected_light_path_index; // The index of the shown path. All paths are displayed when using -1. + bool m_display_light_paths; + + void set_selected_light_path_index(int index); + void print_selected_light_paths() const; +}; + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.cpp index ef06f45a09..36f349ab57 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.cpp @@ -30,10 +30,8 @@ #include "lightpathspickinghandler.h" // appleseed.studio headers. -#include "mainwindow/rendering/lightpathswidget.h" - -// appleseed.qtcommon headers. -#include "widgets/mousecoordinatestracker.h" +#include "mainwindow/rendering/lightpathslayer.h" +#include "mainwindow/rendering/viewportcanvas.h" // appleseed.renderer headers. #include "renderer/api/frame.h" @@ -52,7 +50,6 @@ #include #include -using namespace appleseed::qtcommon; using namespace foundation; using namespace renderer; @@ -60,20 +57,15 @@ namespace appleseed { namespace studio { LightPathsPickingHandler::LightPathsPickingHandler( - LightPathsWidget* light_paths_widget, - const MouseCoordinatesTracker& mouse_tracker, + LightPathsManager& light_paths_manager, + ViewportCanvas* viewport_canvas, const Project& project) - : m_light_paths_widget(light_paths_widget) - , m_mouse_tracker(mouse_tracker) + : m_light_paths_manager(light_paths_manager) + , m_viewport_canvas(viewport_canvas) , m_project(project) - , m_enabled(true) + , m_enabled(false) { - m_light_paths_widget->installEventFilter(this); -} - -LightPathsPickingHandler::~LightPathsPickingHandler() -{ - m_light_paths_widget->removeEventFilter(this); + m_viewport_canvas->installEventFilter(this); } void LightPathsPickingHandler::set_enabled(const bool enabled) @@ -81,63 +73,40 @@ void LightPathsPickingHandler::set_enabled(const bool enabled) m_enabled = enabled; } -void LightPathsPickingHandler::pick(const Vector2i& pixel) const +void LightPathsPickingHandler::slot_rectangle_selection(const QRect& rect) { - const Image& image = m_project.get_frame()->image(); - const CanvasProperties& props = image.properties(); + if (!m_enabled) return; - if (pixel.x >= 0 && - pixel.y >= 0 && - pixel.x < static_cast(props.m_canvas_width) && - pixel.y < static_cast(props.m_canvas_height)) - { - LightPathArray light_paths; - m_project.get_light_path_recorder().query( - static_cast(pixel.x), - static_cast(pixel.y), - static_cast(pixel.x), - static_cast(pixel.y), - light_paths); - - if (light_paths.empty()) - RENDERER_LOG_INFO("no light path found at pixel (%d, %d).", pixel.x, pixel.y); - else - { - RENDERER_LOG_INFO( - "%s light path%s found at pixel (%d, %d).", - pretty_uint(light_paths.size()).c_str(), - light_paths.size() > 1 ? "s" : "", - pixel.x, - pixel.y); - } - - m_light_paths_widget->set_light_paths(light_paths); - m_light_paths_widget->update(); - } -} - -void LightPathsPickingHandler::pick(const AABB2i& rect) const -{ const Image& image = m_project.get_frame()->image(); const CanvasProperties& props = image.properties(); + const AABB2i rectangle_selection( + Vector2i(rect.x(), rect.y()), + Vector2i(rect.x() + rect.width() - 1, rect.y() + rect.height() - 1)); + const AABB2i image_rect( Vector2i(0, 0), Vector2i( static_cast(props.m_canvas_width - 1), static_cast(props.m_canvas_height - 1))); - const auto final_rect = AABB2i::intersect(rect, image_rect); + const auto final_rect = AABB2i::intersect(rectangle_selection, image_rect); if (final_rect.is_valid()) { LightPathArray light_paths; - m_project.get_light_path_recorder().query( - static_cast(final_rect.min.x), - static_cast(final_rect.min.y), - static_cast(final_rect.max.x), - static_cast(final_rect.max.y), - light_paths); + + const LightPathRecorder& light_path_recorder = m_project.get_light_path_recorder(); + + if (light_path_recorder.get_light_path_count() > 0) + { + light_path_recorder.query( + static_cast(final_rect.min.x), + static_cast(final_rect.min.y), + static_cast(final_rect.max.x), + static_cast(final_rect.max.y), + light_paths); + } if (light_paths.empty()) { @@ -159,8 +128,55 @@ void LightPathsPickingHandler::pick(const AABB2i& rect) const final_rect.max.y); } - m_light_paths_widget->set_light_paths(light_paths); - m_light_paths_widget->update(); + m_light_paths_manager.set_light_paths(light_paths); + } +} + +void LightPathsPickingHandler::pick(const QPoint& point) const +{ + const Image& image = m_project.get_frame()->image(); + const CanvasProperties& props = image.properties(); + + const Vector2d ndc( + static_cast(point.x()) / m_viewport_canvas->width(), + static_cast(point.y()) / m_viewport_canvas->height()); + + const Vector2i pixel( + ndc[0] * static_cast(props.m_canvas_width), + ndc[1] * static_cast(props.m_canvas_height)); + + if (pixel.x >= 0 && + pixel.y >= 0 && + pixel.x < static_cast(props.m_canvas_width) && + pixel.y < static_cast(props.m_canvas_height)) + { + LightPathArray light_paths; + + const LightPathRecorder& light_path_recorder = m_project.get_light_path_recorder(); + + if (light_path_recorder.get_light_path_count() > 0) + { + light_path_recorder.query( + static_cast(pixel.x), + static_cast(pixel.y), + static_cast(pixel.x), + static_cast(pixel.y), + light_paths); + } + + if (light_paths.empty()) + RENDERER_LOG_INFO("no light path found at pixel (%d, %d).", pixel.x, pixel.y); + else + { + RENDERER_LOG_INFO( + "%s light path%s found at pixel (%d, %d).", + pretty_uint(light_paths.size()).c_str(), + light_paths.size() > 1 ? "s" : "", + pixel.x, + pixel.y); + } + + m_light_paths_manager.set_light_paths(light_paths); } } @@ -168,14 +184,15 @@ bool LightPathsPickingHandler::eventFilter(QObject* object, QEvent* event) { if (m_enabled) { - if (event->type() == QEvent::MouseButtonPress) + if (event->type() == QEvent::MouseButtonRelease) { const QMouseEvent* mouse_event = static_cast(event); if (!(mouse_event->modifiers() & (Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier))) { if (mouse_event->button() == Qt::LeftButton) { - pick(m_mouse_tracker.widget_to_pixel(mouse_event->pos())); + pick(mouse_event->pos()); + return true; } } diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.h b/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.h index f2c8cadbe6..f786734e8e 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.h +++ b/src/appleseed.studio/mainwindow/rendering/lightpathspickinghandler.h @@ -28,6 +28,9 @@ #pragma once +// appleseed.studio headers. +#include "mainwindow/rendering/lightpathsmanager.h" + // appleseed.foundation headers. #include "foundation/math/aabb.h" #include "foundation/math/vector.h" @@ -36,10 +39,10 @@ #include // Forward declarations. -namespace appleseed { namespace qtcommon { class MouseCoordinatesTracker; } } -namespace appleseed { namespace studio { class LightPathsWidget; } } +namespace appleseed { namespace studio { class ViewportCanvas; } } namespace renderer { class Project; } class QEvent; +class QPoint; namespace appleseed { namespace studio { @@ -51,23 +54,23 @@ class LightPathsPickingHandler public: LightPathsPickingHandler( - LightPathsWidget* light_paths_widget, - const qtcommon::MouseCoordinatesTracker& mouse_tracker, + LightPathsManager& light_paths_manager, + ViewportCanvas* viewport_canvas, const renderer::Project& project); - ~LightPathsPickingHandler() override; - void set_enabled(const bool enabled); - void pick(const foundation::Vector2i& pixel) const; - void pick(const foundation::AABB2i& rect) const; + public slots: + void slot_rectangle_selection(const QRect& rect); private: - LightPathsWidget* m_light_paths_widget; - const qtcommon::MouseCoordinatesTracker& m_mouse_tracker; + LightPathsManager& m_light_paths_manager; + ViewportCanvas* m_viewport_canvas; const renderer::Project& m_project; bool m_enabled; + void pick(const QPoint& point) const; + bool eventFilter(QObject* object, QEvent* event) override; }; diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathstab.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathstab.cpp deleted file mode 100644 index 2ace0d3416..0000000000 --- a/src/appleseed.studio/mainwindow/rendering/lightpathstab.cpp +++ /dev/null @@ -1,341 +0,0 @@ - -// -// This source file is part of appleseed. -// Visit https://appleseedhq.net/ for additional information and resources. -// -// This software is released under the MIT license. -// -// Copyright (c) 2018 Francois Beaune, The appleseedhq Organization -// -// 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. -// - -// Interface header. -#include "lightpathstab.h" - -// appleseed.studio headers. -#include "mainwindow/rendering/lightpathspickinghandler.h" -#include "mainwindow/rendering/lightpathswidget.h" -#include "utility/settingskeys.h" - -// appleseed.qtcommon headers. -#include "utility/miscellaneous.h" - -// appleseed.renderer headers. -#include "renderer/api/frame.h" -#include "renderer/api/lighting.h" -#include "renderer/api/project.h" - -// appleseed.foundation headers. -#include "foundation/image/canvasproperties.h" -#include "foundation/image/image.h" -#include "foundation/math/aabb.h" -#include "foundation/math/vector.h" - -// Qt headers. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Standard headers. -#include - -using namespace appleseed::qtcommon; -using namespace foundation; -using namespace renderer; - -namespace appleseed { -namespace studio { - -// -// LightPathsTab class implementation. -// - -LightPathsTab::LightPathsTab(Project& project, ParamArray& settings) - : m_project(project) - , m_settings(settings) -{ - setObjectName("render_widget_tab"); - setLayout(new QGridLayout()); - layout()->setSpacing(0); - layout()->setMargin(0); - - create_light_paths_widget(); - create_toolbar(); - create_scrollarea(); - - layout()->addWidget(m_toolbar); - layout()->addWidget(m_scroll_area); - - recreate_handlers(); -} - -void LightPathsTab::slot_entity_picked(const ScenePicker::PickingResult& result) -{ - const CanvasProperties& props = m_project.get_frame()->image().properties(); - - m_screen_space_paths_picking_handler->pick( - Vector2i( - result.m_ndc[0] * static_cast(props.m_canvas_width), - result.m_ndc[1] * static_cast(props.m_canvas_height))); -} - -void LightPathsTab::slot_rectangle_selection(const QRect& rect) -{ - m_screen_space_paths_picking_handler->pick( - AABB2i( - Vector2i(rect.x(), rect.y()), - Vector2i(rect.x() + rect.width() - 1, rect.y() + rect.height() - 1))); -} - -void LightPathsTab::slot_light_path_selection_changed( - const int selected_light_path_index, - const int total_light_paths) const -{ - if (total_light_paths > 0) - { - m_prev_path_button->setEnabled(selected_light_path_index > -1); - m_next_path_button->setEnabled(selected_light_path_index < total_light_paths - 1); - } - else - { - m_prev_path_button->setEnabled(false); - m_next_path_button->setEnabled(false); - } -} - -void LightPathsTab::slot_context_menu(const QPoint& point) -{ - if (!(QApplication::keyboardModifiers() & Qt::ShiftModifier)) - return; - - QMenu* menu = new QMenu(this); - - const auto light_path_count = m_project.get_light_path_recorder().get_light_path_count(); - menu->addAction( - QString("Save %1 Light Path%2...") - .arg(QString::fromStdString(pretty_uint(light_path_count))) - .arg(light_path_count > 1 ? "s" : ""), - this, SLOT(slot_save_light_paths())); - - menu->exec(m_light_paths_widget->mapToGlobal(point)); -} - -void LightPathsTab::slot_save_light_paths() -{ - QString filepath = - get_save_filename( - this, - "Save Light Paths As...", - "Light Paths Files (*.aspaths);;All Files (*.*)", - m_settings, - SETTINGS_FILE_DIALOG_LIGHT_PATHS); - - if (filepath.isEmpty()) - return; - - if (QFileInfo(filepath).suffix().isEmpty()) - filepath += ".aspaths"; - - // Write light paths to disk. - m_project.get_light_path_recorder().write(filepath.toUtf8().constData()); -} - -void LightPathsTab::slot_camera_changed() -{ - m_light_paths_widget->set_transform(m_camera_controller->get_transform()); - m_light_paths_widget->update(); -} - -void LightPathsTab::create_light_paths_widget() -{ - // Create the OpenGL widget. - const CanvasProperties& props = m_project.get_frame()->image().properties(); - m_light_paths_widget = - new LightPathsWidget( - m_project, - props.m_canvas_width, - props.m_canvas_height); - - // Enable context menu on the OpenGL widget. - m_light_paths_widget->setContextMenuPolicy(Qt::CustomContextMenu); - connect( - m_light_paths_widget, SIGNAL(signal_light_path_selection_changed(const int, const int)), - SLOT(slot_light_path_selection_changed(const int, const int))); - connect( - m_light_paths_widget, SIGNAL(customContextMenuRequested(const QPoint&)), - SLOT(slot_context_menu(const QPoint&))); -} - -void LightPathsTab::create_toolbar() -{ - // Create the render toolbar. - m_toolbar = new QToolBar(); - m_toolbar->setObjectName("render_toolbar"); - m_toolbar->setIconSize(QSize(18, 18)); - - // Save Light Paths button. - QToolButton* save_light_paths_button = new QToolButton(); - save_light_paths_button->setIcon(load_icons("lightpathstab_save_light_paths")); - const auto light_path_count = m_project.get_light_path_recorder().get_light_path_count(); - save_light_paths_button->setToolTip( - QString("Save %1 Light Path%2...") - .arg(QString::fromStdString(pretty_uint(light_path_count))) - .arg(light_path_count > 1 ? "s" : "")); - connect( - save_light_paths_button , SIGNAL(clicked()), - SLOT(slot_save_light_paths())); - m_toolbar->addWidget(save_light_paths_button); - - m_toolbar->addSeparator(); - - // Previous Light Path button. - m_prev_path_button = new QToolButton(); - m_prev_path_button->setIcon(load_icons("lightpathstab_prev_light_path")); - m_prev_path_button->setToolTip("Display previous light path"); - m_prev_path_button->setEnabled(false); - connect( - m_prev_path_button, SIGNAL(clicked()), - m_light_paths_widget, SLOT(slot_display_previous_light_path())); - m_toolbar->addWidget(m_prev_path_button); - - // Next Light Path button. - m_next_path_button = new QToolButton(); - m_next_path_button->setIcon(load_icons("lightpathstab_next_light_path")); - m_next_path_button->setToolTip("Display next light path"); - m_next_path_button->setEnabled(false); - connect( - m_next_path_button, SIGNAL(clicked()), - m_light_paths_widget, SLOT(slot_display_next_light_path())); - m_toolbar->addWidget(m_next_path_button); - - m_toolbar->addSeparator(); - - // Toggle Backface Culling button. - QToolButton* backface_culling_button = new QToolButton(); - backface_culling_button->setIcon(load_icons("lightpathstab_toggle_backface_culling")); - backface_culling_button->setToolTip("Show/hide backfacing surfaces"); - backface_culling_button->setCheckable(true); - backface_culling_button->setChecked(false); - connect( - backface_culling_button, SIGNAL(toggled(bool)), - m_light_paths_widget, SLOT(slot_toggle_backface_culling(const bool))); - m_toolbar->addWidget(backface_culling_button); - - // Synchronize Camera button. - QToolButton* sync_camera_button = new QToolButton(); - sync_camera_button->setIcon(load_icons("lightpathstab_synchronize_camera")); - sync_camera_button->setToolTip("Synchronize the rendering camera with this camera"); - connect( - sync_camera_button, SIGNAL(clicked()), - m_light_paths_widget, SLOT(slot_synchronize_camera())); - m_toolbar->addWidget(sync_camera_button); - - // Add stretchy spacer. - // This places interactive widgets on the left and info on the right. - QWidget* spacer = new QWidget(); - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); - m_toolbar->addWidget(spacer); - - // Create a label to display various information such as mouse coordinates, etc. - m_info_label = new QLabel(); - m_info_label->setObjectName("info_label"); - m_toolbar->addWidget(m_info_label); -} - -void LightPathsTab::create_scrollarea() -{ - // Encapsulate the OpenGL widget into another widget that adds a margin around it. - QWidget* gl_widget_wrapper = new QWidget(); - gl_widget_wrapper->setObjectName("render_widget_wrapper"); - gl_widget_wrapper->setLayout(new QGridLayout()); - gl_widget_wrapper->layout()->setSizeConstraint(QLayout::SetFixedSize); - gl_widget_wrapper->layout()->setContentsMargins(20, 20, 20, 20); - gl_widget_wrapper->layout()->addWidget(m_light_paths_widget); - - // Wrap the OpenGL widget in a scroll area. - m_scroll_area = new QScrollArea(); - m_scroll_area->setObjectName("render_widget_scrollarea"); - m_scroll_area->setAlignment(Qt::AlignCenter); - m_scroll_area->setWidget(gl_widget_wrapper); -} - -void LightPathsTab::recreate_handlers() -{ - // Handler for zooming the render widget in and out with the keyboard or the mouse wheel. - m_zoom_handler.reset( - new WidgetZoomHandler( - m_scroll_area, - m_light_paths_widget)); - - // Handler for panning the render widget with the mouse. - m_pan_handler.reset( - new ScrollAreaPanHandler( - m_scroll_area)); - - // Handler for tracking and displaying mouse coordinates. - m_mouse_tracker.reset( - new MouseCoordinatesTracker( - m_light_paths_widget, - m_info_label)); - - // The screen-space paths picking handler is used to pick paths from the render widget. - m_screen_space_paths_picking_handler.reset( - new LightPathsPickingHandler( - m_light_paths_widget, - *m_mouse_tracker.get(), - m_project)); - m_screen_space_paths_picking_handler->set_enabled(false); - - // The world-space paths picking handler is used to pick paths in the light paths widget. - // Commented out because we don't want to allow that. - // m_world_space_paths_picking_handler.reset( - // new LightPathsPickingHandler( - // m_light_paths_widget, - // *m_mouse_tracker.get(), - // m_project)); - - // Camera handler. - m_light_paths_widget->setMouseTracking(true); - m_camera_controller.reset( - new CameraController( - m_light_paths_widget, - m_project, - m_project.get_uncached_active_camera())); - connect( - m_camera_controller.get(), SIGNAL(signal_camera_changed()), - SLOT(slot_camera_changed())); - - // Clipboard handler. - m_clipboard_handler.reset(new RenderClipboardHandler(m_light_paths_widget, m_light_paths_widget)); -} - -} // namespace studio -} // namespace appleseed - -#include "mainwindow/rendering/moc_cpp_lightpathstab.cxx" diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp new file mode 100644 index 0000000000..189249a62d --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp @@ -0,0 +1,240 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2018 Francois Beaune, The appleseedhq Organization +// +// 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. +// + +// Interface header. +#include "lightpathsviewporttoolbar.h" + +// appleseed.studio headers. +#include "mainwindow/rendering/lightpathspickinghandler.h" +#include "mainwindow/rendering/lightpathslayer.h" +#include "mainwindow/rendering/viewporttab.h" +#include "utility/settingskeys.h" + +// appleseed.qtcommon headers. +#include "utility/miscellaneous.h" + +// appleseed.renderer headers. +#include "renderer/api/frame.h" +#include "renderer/api/lighting.h" +#include "renderer/api/project.h" + +// appleseed.foundation headers. +#include "foundation/image/canvasproperties.h" +#include "foundation/image/image.h" +#include "foundation/math/aabb.h" +#include "foundation/math/vector.h" + +// Qt headers. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Standard headers. +#include + +using namespace appleseed::qtcommon; +using namespace foundation; +using namespace renderer; + +namespace appleseed { +namespace studio { + +// +// LightPathsViewportToolbar class implementation. +// + +LightPathsViewportToolbar::LightPathsViewportToolbar( + ViewportTab* viewport_tab, + Project* project, + LightPathsManager& light_paths_manager) + : m_enabled(false) + , m_project(project) + , m_light_paths_manager(light_paths_manager) + , m_viewport_canvas(viewport_tab->get_viewport_canvas()) +{ + LightPathsLayer* light_paths_layer = m_viewport_canvas->get_light_paths_layer(); + + connect( + &m_light_paths_manager, &LightPathsManager::signal_light_path_selection_changed, + this, &LightPathsViewportToolbar::slot_light_path_selection_changed); + connect( + this, &LightPathsViewportToolbar::signal_display_next_light_path, + &m_light_paths_manager, &LightPathsManager::slot_select_next_light_path); + connect( + this, &LightPathsViewportToolbar::signal_display_previous_light_path, + &m_light_paths_manager, &LightPathsManager::slot_select_previous_light_path); + + create_toolbar(); + + m_viewport_canvas->installEventFilter(this); +} + +void LightPathsViewportToolbar::reset(renderer::Project* project) +{ + m_project = project; +} + +void LightPathsViewportToolbar::set_enabled(const bool enabled) +{ + m_enabled = enabled; + + if (enabled) + { + refresh_toolbar(); + m_toolbar->show(); + } + else + { + m_toolbar->hide(); + } + + m_toolbar->setDisabled(!enabled); +} + +QToolBar* LightPathsViewportToolbar::toolbar() const +{ + return m_toolbar; +} + +void LightPathsViewportToolbar::slot_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths) +{ + if (total_light_paths > 0) + { + m_prev_path_button->setEnabled(selected_light_path_index > -1); + m_next_path_button->setEnabled(selected_light_path_index < total_light_paths - 1); + } + else + { + m_prev_path_button->setEnabled(false); + m_next_path_button->setEnabled(false); + } +} + +void LightPathsViewportToolbar::slot_save_light_paths() +{ + m_light_paths_manager.save_all_light_paths(m_toolbar); +} + +void LightPathsViewportToolbar::clear_selection() const +{ + m_light_paths_manager.clear_light_paths_selection(); +} + +void LightPathsViewportToolbar::create_toolbar() +{ + // Create the render toolbar. + m_toolbar = new QToolBar(); + m_toolbar->setObjectName("light_paths_viewport_toolbar"); + m_toolbar->setIconSize(QSize(18, 18)); + + // Save Light Paths button. + m_save_light_paths_button = new QToolButton(); + m_save_light_paths_button->setIcon(load_icons("lightpaths_toolbar_save_light_paths")); + connect( + m_save_light_paths_button , &QToolButton::clicked, + this, &LightPathsViewportToolbar::slot_save_light_paths); + m_toolbar->addWidget(m_save_light_paths_button); + + m_toolbar->addSeparator(); + + // Previous Light Path button. + m_prev_path_button = new QToolButton(); + m_prev_path_button->setIcon(load_icons("lightpaths_toolbar_prev_light_path")); + m_prev_path_button->setToolTip("Display previous light path"); + m_prev_path_button->setEnabled(false); + connect( + m_prev_path_button, &QToolButton::clicked, + &m_light_paths_manager, &LightPathsManager::slot_select_previous_light_path); + m_toolbar->addWidget(m_prev_path_button); + + // Next Light Path button. + m_next_path_button = new QToolButton(); + m_next_path_button->setIcon(load_icons("lightpaths_toolbar_next_light_path")); + m_next_path_button->setToolTip("Display next light path"); + m_next_path_button->setEnabled(false); + connect( + m_next_path_button, &QToolButton::clicked, + &m_light_paths_manager, &LightPathsManager::slot_select_next_light_path); + m_toolbar->addWidget(m_next_path_button); + + m_toolbar->setDisabled(true); + m_toolbar->hide(); +} + +void LightPathsViewportToolbar::refresh_toolbar() const +{ + const auto light_path_count = m_project->get_light_path_recorder().get_light_path_count(); + + m_save_light_paths_button->setToolTip( + QString("Save %1 Light Path%2...") + .arg(QString::fromStdString(pretty_uint(light_path_count))) + .arg(light_path_count > 1 ? "s" : "")); +} + +bool LightPathsViewportToolbar::eventFilter(QObject* object, QEvent* event) +{ + if (m_enabled) + { + if (event->type() == QEvent::KeyRelease) + { + const QKeyEvent* key_event = static_cast(event); + + if (!(key_event->modifiers() & (Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier))) + { + const int key = key_event->key(); + + if (key == Qt::Key_Escape) + clear_selection(); + else if (key == Qt::Key_Left) + emit signal_display_previous_light_path(); + else if (key == Qt::Key_Right) + emit signal_display_next_light_path(); + } + } + } + + return QObject::eventFilter(object, event); +} + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h new file mode 100644 index 0000000000..348cd41e93 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h @@ -0,0 +1,116 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2018 Francois Beaune, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// appleseed.studio headers. +#include "mainwindow/rendering/cameracontroller.h" +#include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/renderclipboardhandler.h" +#include "mainwindow/rendering/viewportcanvas.h" + +// appleseed.qtcommon headers. +#include "widgets/scrollareapanhandler.h" +#include "widgets/widgetzoomhandler.h" + +// appleseed.renderer headers. +#include "renderer/api/rendering.h" + +// Qt headers. +#include +#include + +// Forward declarations. +namespace appleseed { namespace studio { class ViewportTab; } } +namespace renderer { class PamArray; } +namespace renderer { class Project; } +class QAction; +class QEvent; +class QLabel; +class QPoint; +class QRect; +class QScrollArea; +class QToolBar; +class QToolButton; + +namespace appleseed { +namespace studio { + +// +// Control pannel for light paths. +// + +class LightPathsViewportToolbar + : public QObject +{ + Q_OBJECT + + public: + LightPathsViewportToolbar( + ViewportTab* viewport_tab, + renderer::Project* project, + LightPathsManager& light_paths_manager); + + void reset(renderer::Project* project); + + QToolBar* toolbar() const; + + void set_enabled(const bool enabled); + + signals: + void signal_display_next_light_path(); + void signal_display_previous_light_path(); + + private slots: + void slot_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths); + void slot_save_light_paths(); + + private: + bool m_enabled; + + renderer::Project* m_project; + LightPathsManager& m_light_paths_manager; + ViewportCanvas* m_viewport_canvas; + QToolBar* m_toolbar; + QToolButton* m_save_light_paths_button; + QToolButton* m_prev_path_button; + QToolButton* m_next_path_button; + + void clear_selection() const; + + void create_toolbar(); + void refresh_toolbar() const; + + bool eventFilter(QObject* object, QEvent* event) override; +}; + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathswidget.h b/src/appleseed.studio/mainwindow/rendering/lightpathswidget.h deleted file mode 100644 index d3d33f10f9..0000000000 --- a/src/appleseed.studio/mainwindow/rendering/lightpathswidget.h +++ /dev/null @@ -1,167 +0,0 @@ - -// -// This source file is part of appleseed. -// Visit https://appleseedhq.net/ for additional information and resources. -// -// This software is released under the MIT license. -// -// Copyright (c) 2018 Francois Beaune, The appleseedhq Organization -// -// 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. -// - -#pragma once - -// appleseed.studio headers. -#include "mainwindow/rendering/renderclipboardhandler.h" - -// appleseed.renderer headers. -#include "renderer/api/lighting.h" - -// appleseed.foundation headers. -#include "foundation/math/matrix.h" -#include "foundation/math/transform.h" -#include "foundation/math/vector.h" - -// Qt headers. -#include -#include - -// Standard headers. -#include -#include -#include -#include - -// Forward declarations. -namespace renderer { class Assembly; } -namespace renderer { class AssemblyInstance; } -namespace renderer { class Camera; } -namespace renderer { class Object; } -namespace renderer { class ObjectInstance; } -namespace renderer { class Project; } -class QKeyEvent; -class QImage; -class QOpenGLFunctions_3_3_Core; - -namespace appleseed { -namespace studio { - -// -// A widget providing an hardware-accelerated visualization of recorded light paths. -// - -class LightPathsWidget - : public QOpenGLWidget - , public ICapturableWidget -{ - Q_OBJECT - - public: - LightPathsWidget( - const renderer::Project& project, - const size_t width, - const size_t height); - - QImage capture() override; - - void set_transform( - const foundation::Transformd& transform); - - void set_light_paths( - const renderer::LightPathArray& light_paths); - - void set_selected_light_path_index( - const int selected_light_path_index); - - signals: - void signal_light_path_selection_changed( - const int selected_light_path_index, - const int total_light_paths) const; - - public slots: - void slot_display_all_light_paths(); - void slot_display_previous_light_path(); - void slot_display_next_light_path(); - void slot_toggle_backface_culling(const bool checked); - void slot_synchronize_camera(); - - private: - const renderer::Project& m_project; - renderer::Camera& m_camera; - foundation::Matrix4d m_camera_matrix; - - bool m_backface_culling_enabled; - - renderer::LightPathArray m_light_paths; - int m_selected_light_path_index; // -1 == display all paths - - QOpenGLFunctions_3_3_Core* m_gl; - - std::vector m_scene_object_data_vbos; - std::vector m_scene_object_data_index_counts; - std::vector m_scene_object_instance_vbos; - std::vector m_scene_object_instance_counts; - std::vector m_scene_object_current_instances; - std::vector m_scene_object_vaos; - std::unordered_map m_scene_object_index_map; - GLuint m_scene_shader_program; - GLint m_scene_view_mat_location; - GLint m_scene_proj_mat_location; - GLuint m_light_paths_vbo; - std::vector m_light_paths_index_offsets; - GLuint m_light_paths_vao; - GLuint m_light_paths_shader_program; - GLint m_light_paths_view_mat_location; - GLint m_light_paths_proj_mat_location; - foundation::Matrix4f m_gl_view_matrix; - foundation::Matrix4f m_gl_proj_matrix; - bool m_gl_initialized; - - void initializeGL() override; - void resizeGL(int w, int h) override; - void paintGL() override; - void keyPressEvent(QKeyEvent* event) override; - - void cleanup_gl_data(); - void load_scene_data(); - void load_light_paths_data(); - - void load_assembly_data( - const renderer::Assembly& object); - - void load_assembly_instance( - const renderer::AssemblyInstance& assembly_instance, - const float time); - - void load_object_data( - const renderer::Object& object); - - void load_object_instance( - const renderer::ObjectInstance& object_instance, - const foundation::Matrix4f& assembly_transform_matrix); - - void render_geometry(); - void render_light_paths(); - - void dump_selected_light_path() const; -}; - -} // namespace studio -} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp new file mode 100644 index 0000000000..44dd05feb7 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -0,0 +1,268 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2020 Kevin Masson, The appleseedhq Organization +// +// 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. +// + +// Interface header. +#include "openglviewporttab.h" + +// appleseed.studio headers. +#include "mainwindow/project/projectexplorer.h" +#include "mainwindow/rendering/renderingmanager.h" + +// appleseed.renderer headers. +#include "renderer/api/frame.h" +#include "renderer/api/project.h" + +// appleseed.qtcommon headers. +#include "utility/miscellaneous.h" + +// Qt headers. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace appleseed::qtcommon; +using namespace foundation; +using namespace renderer; +namespace OCIO = OCIO_NAMESPACE; + +namespace appleseed { +namespace studio { + +OpenGLViewportTab::OpenGLViewportTab( + ProjectExplorer& project_explorer, + Project& project, + RenderingManager& rendering_manager, + LightPathsManager& light_paths_manager, + OCIO::ConstConfigRcPtr ocio_config, + renderer::ParamArray application_settings) + : ViewportTab( + project_explorer, + project, + rendering_manager, + ocio_config, + application_settings) + , m_light_paths_manager(light_paths_manager) +{ + setObjectName("opengl_viewport_tab"); + setLayout(new QGridLayout()); + layout()->setSpacing(0); + layout()->setMargin(0); + + create_viewport_canvas(); + create_toolbar(); + create_scrollarea(); + + recreate_handlers(); + + layout()->addWidget(m_toolbar); + layout()->addWidget(m_light_paths_viewport_toolbar->toolbar()); + layout()->addWidget(m_scroll_area); + + m_camera_controller->set_enabled(true); + + get_viewport_canvas()->set_base_layer(ViewportCanvas::BaseLayer::OpenGL); +} + +ViewportCanvas* OpenGLViewportTab::get_viewport_canvas() const +{ + return m_viewport_canvas; +} + +void OpenGLViewportTab::render_began() +{ + ViewportTab::render_began(); + + m_light_paths_viewport_toolbar.get()->reset(&m_project); +} + +void OpenGLViewportTab::update_size() +{ + ViewportTab::update_size(); + + recreate_handlers(); +} + +void OpenGLViewportTab::on_tab_selected() +{ + const bool display_light_paths = m_light_paths_manager.should_display_light_paths(); + m_light_paths_viewport_toolbar->set_enabled(display_light_paths); + m_light_paths_toggle_button->setChecked(display_light_paths); +} + +void OpenGLViewportTab::slot_camera_changed() +{ + m_viewport_canvas->get_light_paths_layer()->set_transform(m_camera_controller->get_transform()); + m_viewport_canvas->get_gl_scene_layer()->set_transform(m_camera_controller->get_transform()); + update(); +} + +void OpenGLViewportTab::slot_viewport_canvas_context_menu(const QPoint& point) +{ + emit signal_viewport_canvas_context_menu(m_viewport_canvas->mapToGlobal(point)); +} + +void OpenGLViewportTab::create_viewport_canvas() +{ + const CanvasProperties& props = m_project.get_frame()->image().properties(); + + m_viewport_canvas = + new ViewportCanvas( + m_project, + props.m_canvas_width, + props.m_canvas_height, + m_ocio_config, + m_light_paths_manager, + this); + + m_viewport_canvas->setContextMenuPolicy(Qt::CustomContextMenu); + + connect( + m_viewport_canvas, &ViewportCanvas::customContextMenuRequested, + this, &OpenGLViewportTab::slot_viewport_canvas_context_menu); + + m_viewport_canvas->setMouseTracking(true); +} + +void OpenGLViewportTab::create_toolbar() +{ + // Create the light path toolbar. + m_light_paths_viewport_toolbar.reset( + new LightPathsViewportToolbar( + this, + &m_project, + m_light_paths_manager)); + + // Create the render toolbar. + m_toolbar = new QToolBar(); + m_toolbar->setObjectName("render_toolbar"); + m_toolbar->setIconSize(QSize(18, 18)); + + // Display Light Paths button. + m_light_paths_toggle_button = new QToolButton(); + m_light_paths_toggle_button->setText("Display Light Paths Overlay"); + m_light_paths_toggle_button->setCheckable(true); + connect( + m_light_paths_toggle_button, &QToolButton::toggled, + this, &OpenGLViewportTab::slot_toggle_light_paths); + m_toolbar->addWidget(m_light_paths_toggle_button); + + m_toolbar->addSeparator(); + + // Reset Zoom button. + QToolButton* reset_zoom_button = new QToolButton(); + reset_zoom_button->setIcon(load_icons("rendertab_reset_zoom")); + reset_zoom_button->setShortcut(Qt::Key_Asterisk); + reset_zoom_button->setToolTip(combine_name_and_shortcut("Reset Zoom", reset_zoom_button->shortcut())); + connect( + reset_zoom_button, &QToolButton::clicked, + this, &OpenGLViewportTab::signal_reset_zoom); + m_toolbar->addWidget(reset_zoom_button); + + m_toolbar->addSeparator(); + + // Toggle Backface Culling button. + QToolButton* backface_culling_button = new QToolButton(); + backface_culling_button->setIcon(load_icons("opengl_viewport_tab_toggle_backface_culling")); + backface_culling_button->setToolTip("Show/hide backfacing surfaces"); + backface_culling_button->setCheckable(true); + backface_culling_button->setChecked(false); + connect( + backface_culling_button, &QToolButton::toggled , + m_viewport_canvas, &ViewportCanvas::slot_toggle_backface_culling); + m_toolbar->addWidget(backface_culling_button); + + // Synchronize Camera button. + QToolButton* sync_camera_button = new QToolButton(); + sync_camera_button->setIcon(load_icons("opengl_viewport_tab_synchronize_camera")); + sync_camera_button->setToolTip("Synchronize the rendering camera with this camera"); + connect( + sync_camera_button, &QToolButton::clicked, + m_viewport_canvas->get_light_paths_layer(), &LightPathsLayer::slot_synchronize_camera); + m_toolbar->addWidget(sync_camera_button); +} + +void OpenGLViewportTab::create_scrollarea() +{ + // Encapsulate the render widget into another widget that adds a margin around it. + QWidget* render_widget_wrapper = new QWidget(); + render_widget_wrapper->setObjectName("render_widget_wrapper"); + render_widget_wrapper->setLayout(new QGridLayout()); + render_widget_wrapper->layout()->setSizeConstraint(QLayout::SetFixedSize); + render_widget_wrapper->layout()->setContentsMargins(20, 20, 20, 20); + render_widget_wrapper->layout()->addWidget(m_viewport_canvas); + + // Wrap the render widget in a scroll area. + m_scroll_area = new QScrollArea(); + m_scroll_area->setObjectName("render_widget_scrollarea"); + m_scroll_area->setAlignment(Qt::AlignCenter); + m_scroll_area->setWidget(render_widget_wrapper); +} + +void OpenGLViewportTab::recreate_handlers() +{ + // Handler for zooming the render widget in and out with the keyboard or the mouse wheel. + m_zoom_handler.reset( + new WidgetZoomHandler( + m_scroll_area, + m_viewport_canvas)); + + // Handler for panning the render widget with the mouse. + m_pan_handler.reset( + new ScrollAreaPanHandler( + m_scroll_area)); + + // Camera handler. + m_camera_controller.reset( + new CameraController( + m_viewport_canvas, + m_project)); + + connect( + m_camera_controller.get(), &CameraController::signal_camera_changed, + this, &OpenGLViewportTab::slot_camera_changed); + + // Clipboard handler. + m_clipboard_handler.reset(new RenderClipboardHandler(m_viewport_canvas, m_viewport_canvas)); +} + +void OpenGLViewportTab::slot_toggle_light_paths(const bool checked) +{ + m_light_paths_viewport_toolbar->set_enabled(checked); + m_light_paths_manager.display_light_paths(checked); +} + +} // namespace studio +} // namespace appleseed + diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathstab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h similarity index 54% rename from src/appleseed.studio/mainwindow/rendering/lightpathstab.h rename to src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index f3a961e7d8..a693e947d9 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathstab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -5,7 +5,7 @@ // // This software is released under the MIT license. // -// Copyright (c) 2018 Francois Beaune, The appleseedhq Organization +// Copyright (c) 2020 Kevin Masson, The appleseedhq Organization // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal @@ -30,16 +30,25 @@ // appleseed.studio headers. #include "mainwindow/rendering/cameracontroller.h" -#include "mainwindow/rendering/lightpathspickinghandler.h" +#include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/lightpathsviewporttoolbar.h" +#include "mainwindow/rendering/materialdrophandler.h" +#include "mainwindow/rendering/pixelcolortracker.h" +#include "mainwindow/rendering/pixelinspectorhandler.h" #include "mainwindow/rendering/renderclipboardhandler.h" +#include "mainwindow/rendering/scenepickinghandler.h" +#include "mainwindow/rendering/viewportcanvas.h" +#include "mainwindow/rendering/viewportregionselectionhandler.h" +#include "mainwindow/rendering/viewporttab.h" // appleseed.qtcommon headers. #include "widgets/mousecoordinatestracker.h" #include "widgets/scrollareapanhandler.h" #include "widgets/widgetzoomhandler.h" -// appleseed.renderer headers. -#include "renderer/api/rendering.h" +// OpenColorIO headers. +#include +namespace OCIO = OCIO_NAMESPACE; // Qt headers. #include @@ -49,9 +58,11 @@ #include // Forward declarations. -namespace appleseed { namespace studio { class LightPathsWidget; } } -namespace renderer { class ParamArray; } +namespace appleseed { namespace studio { class ProjectExplorer; } } +namespace appleseed { namespace studio { class RenderingManager; } } +namespace renderer { class Entity; } namespace renderer { class Project; } +class QComboBox; class QLabel; class QPoint; class QRect; @@ -62,55 +73,51 @@ class QToolButton; namespace appleseed { namespace studio { -// -// A tab providing an hardware-accelerated visualization of recorded light paths. -// - -class LightPathsTab - : public QWidget +class OpenGLViewportTab + : public ViewportTab { Q_OBJECT public: - LightPathsTab( - renderer::Project& project, - renderer::ParamArray& settings); + OpenGLViewportTab( + ProjectExplorer& project_explorer, + renderer::Project& project, + RenderingManager& rendering_manager, + LightPathsManager& light_paths_manager, + OCIO::ConstConfigRcPtr ocio_config, + renderer::ParamArray application_settings); + + ViewportCanvas* get_viewport_canvas() const override; - public slots: - void slot_entity_picked(const renderer::ScenePicker::PickingResult& result); - void slot_rectangle_selection(const QRect& rect); + void render_began() override; + void update_size() override; + void on_tab_selected() override; + + signals: + void signal_reset_zoom(); + void signal_viewport_canvas_context_menu(const QPoint& point); private slots: - void slot_light_path_selection_changed( - const int selected_light_path_index, - const int total_light_paths) const; - void slot_context_menu(const QPoint& point); - void slot_save_light_paths(); void slot_camera_changed(); + void slot_viewport_canvas_context_menu(const QPoint& point); + void slot_toggle_light_paths(const bool checked); private: - renderer::Project& m_project; - renderer::ParamArray& m_settings; - LightPathsWidget* m_light_paths_widget; + ViewportCanvas* m_viewport_canvas; QScrollArea* m_scroll_area; QToolBar* m_toolbar; - QToolButton* m_prev_path_button; - QToolButton* m_next_path_button; - QLabel* m_info_label; + QToolButton* m_light_paths_toggle_button; - std::unique_ptr m_zoom_handler; - std::unique_ptr m_pan_handler; - std::unique_ptr m_mouse_tracker; std::unique_ptr m_camera_controller; - std::unique_ptr m_screen_space_paths_picking_handler; - std::unique_ptr m_world_space_paths_picking_handler; std::unique_ptr m_clipboard_handler; - void create_light_paths_widget(); + LightPathsManager& m_light_paths_manager; + std::unique_ptr m_light_paths_viewport_toolbar; + + void create_viewport_canvas(); void create_toolbar(); void create_scrollarea(); void recreate_handlers(); - }; } // namespace studio diff --git a/src/appleseed.studio/mainwindow/rendering/qttilecallback.cpp b/src/appleseed.studio/mainwindow/rendering/qttilecallback.cpp index 4a3d5f15f8..ac87f498b1 100644 --- a/src/appleseed.studio/mainwindow/rendering/qttilecallback.cpp +++ b/src/appleseed.studio/mainwindow/rendering/qttilecallback.cpp @@ -31,7 +31,8 @@ #include "qttilecallback.h" // appleseed.studio headers. -#include "mainwindow/rendering/renderwidget.h" +#include "mainwindow/rendering/renderlayer.h" +#include "mainwindow/rendering/viewportcanvas.h" // Qt headers. #include @@ -60,12 +61,12 @@ namespace Q_OBJECT public: - explicit QtTileCallback(RenderWidget* render_widget) - : m_render_widget(render_widget) + explicit QtTileCallback(ViewportCanvas* viewport_canvas) + : m_render_layer(viewport_canvas->get_render_layer()) { connect( this, SIGNAL(signal_update()), - m_render_widget, SLOT(update()), + viewport_canvas, SLOT(repaint()), Qt::QueuedConnection); } @@ -81,9 +82,8 @@ namespace const size_t thread_index, const size_t thread_count) override { - assert(m_render_widget); - m_render_widget->highlight_tile(*frame, tile_x, tile_y, thread_index, thread_count); - + assert(m_render_layer); + m_render_layer->highlight_tile(*frame, tile_x, tile_y, thread_index, thread_count); emit signal_update(); } @@ -92,9 +92,8 @@ namespace const size_t tile_x, const size_t tile_y) override { - assert(m_render_widget); - m_render_widget->blit_tile(*frame, tile_x, tile_y); - + assert(m_render_layer); + m_render_layer->blit_tile(*frame, tile_x, tile_y); emit signal_update(); } @@ -105,9 +104,8 @@ namespace const double /*samples_per_pixel*/, const std::uint64_t /*samples_per_second*/) override { - assert(m_render_widget); - m_render_widget->blit_frame(frame); - + assert(m_render_layer); + m_render_layer->blit_frame(frame); emit signal_update(); } @@ -115,7 +113,7 @@ namespace void signal_update(); private: - RenderWidget* m_render_widget; + RenderLayer* m_render_layer; }; } @@ -124,8 +122,8 @@ namespace // QtTileCallbackFactory class implementation. // -QtTileCallbackFactory::QtTileCallbackFactory(RenderWidget* render_widget) - : m_render_widget(render_widget) +QtTileCallbackFactory::QtTileCallbackFactory(ViewportCanvas* viewport_canvas) + : m_viewport_canvas(viewport_canvas) { } @@ -136,7 +134,7 @@ void QtTileCallbackFactory::release() ITileCallback* QtTileCallbackFactory::create() { - return new QtTileCallback(m_render_widget); + return new QtTileCallback(m_viewport_canvas); } } // namespace studio diff --git a/src/appleseed.studio/mainwindow/rendering/qttilecallback.h b/src/appleseed.studio/mainwindow/rendering/qttilecallback.h index 1366a341f5..587ee7090b 100644 --- a/src/appleseed.studio/mainwindow/rendering/qttilecallback.h +++ b/src/appleseed.studio/mainwindow/rendering/qttilecallback.h @@ -36,7 +36,7 @@ #include "foundation/platform/compiler.h" // Forward declarations. -namespace appleseed { namespace studio { class RenderWidget; } } +namespace appleseed { namespace studio { class ViewportCanvas; } } namespace appleseed { namespace studio { @@ -46,7 +46,7 @@ class QtTileCallbackFactory { public: // Constructor. - explicit QtTileCallbackFactory(RenderWidget* render_widget); + explicit QtTileCallbackFactory(ViewportCanvas* viewport_canvas); // Delete this instance. void release() override; @@ -55,7 +55,7 @@ class QtTileCallbackFactory renderer::ITileCallback* create() override; private: - RenderWidget* m_render_widget; + ViewportCanvas* m_viewport_canvas; }; } // namespace studio diff --git a/src/appleseed.studio/mainwindow/rendering/renderingmanager.cpp b/src/appleseed.studio/mainwindow/rendering/renderingmanager.cpp index 2c34708b21..542cdf1651 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderingmanager.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderingmanager.cpp @@ -32,9 +32,9 @@ // appleseed.studio headers. #include "mainwindow/rendering/cameracontroller.h" +#include "mainwindow/rendering/finalrenderviewporttab.h" #include "mainwindow/rendering/qttilecallback.h" -#include "mainwindow/rendering/rendertab.h" -#include "mainwindow/rendering/renderwidget.h" +#include "mainwindow/rendering/viewportcanvas.h" #include "mainwindow/statusbar.h" // appleseed.common headers. @@ -122,7 +122,7 @@ namespace RenderingManager::RenderingManager(StatusBar& status_bar) : m_status_bar(status_bar) , m_project(nullptr) - , m_render_tab(nullptr) + , m_final_render_viewport_tab(nullptr) { Application::initialize_resource_search_paths(m_resource_search_paths); @@ -189,25 +189,30 @@ RenderingManager::~RenderingManager() clear_sticky_actions(); } +RenderingManager::RenderingMode RenderingManager::get_rendering_mode() const +{ + return m_rendering_mode; +} + void RenderingManager::start_rendering( Project* project, const ParamArray& params, const RenderingMode rendering_mode, - RenderTab* render_tab) + FinalRenderViewportTab* final_render_viewport_tab) { m_project = project; m_params = params; m_rendering_mode = rendering_mode; - m_render_tab = render_tab; + m_final_render_viewport_tab = final_render_viewport_tab; - m_render_tab->get_render_widget()->start_render(); + m_final_render_viewport_tab->get_viewport_canvas()->get_render_layer()->start_render(); TileCallbackCollectionFactory* tile_callback_collection_factory = new TileCallbackCollectionFactory(); tile_callback_collection_factory->insert( new QtTileCallbackFactory( - m_render_tab->get_render_widget())); + m_final_render_viewport_tab->get_viewport_canvas())); tile_callback_collection_factory->insert( new ProgressTileCallbackFactory( @@ -434,7 +439,7 @@ void RenderingManager::slot_rendering_begin() run_scheduled_actions(); if (m_rendering_mode == RenderingMode::InteractiveRendering) - m_render_tab->get_camera_controller()->set_enabled(true); + m_final_render_viewport_tab->get_camera_controller()->set_enabled(true); m_has_camera_changed = false; @@ -461,10 +466,10 @@ void RenderingManager::slot_rendering_end() { // Disable camera interaction. if (m_rendering_mode == RenderingMode::InteractiveRendering) - m_render_tab->get_camera_controller()->set_enabled(false); + m_final_render_viewport_tab->get_camera_controller()->set_enabled(false); - // Save the controller target point into the camera. - m_render_tab->get_camera_controller()->save_camera_target(); + // Save the controller target point into the camera when rendering ends. + m_final_render_viewport_tab->get_camera_controller()->save_camera_target(); // Stop printing rendering time in the status bar. m_status_bar.stop_rendering_time_display(); @@ -484,10 +489,10 @@ void RenderingManager::slot_rendering_failed() { // Disable camera interaction. if (m_rendering_mode == RenderingMode::InteractiveRendering) - m_render_tab->get_camera_controller()->set_enabled(false); + m_final_render_viewport_tab->get_camera_controller()->set_enabled(false); - // Save the controller target point into the camera. - m_render_tab->get_camera_controller()->save_camera_target(); + // Save the controller target point into the camera when rendering ends. + m_final_render_viewport_tab->get_camera_controller()->save_camera_target(); // Stop printing rendering time in the status bar. m_status_bar.stop_rendering_time_display(); @@ -498,7 +503,7 @@ void RenderingManager::slot_frame_begin() // Update the scene's camera before rendering the frame. if (m_has_camera_changed) { - m_render_tab->get_camera_controller()->update_camera_transform(); + m_final_render_viewport_tab->get_camera_controller()->update_camera_transform(); m_has_camera_changed = false; } } @@ -506,7 +511,7 @@ void RenderingManager::slot_frame_begin() void RenderingManager::slot_frame_end() { // Ensure that the render widget is up-to-date. - m_render_tab->get_render_widget()->update(); + m_final_render_viewport_tab->get_viewport_canvas()->update(); } void RenderingManager::slot_camera_change_begin() diff --git a/src/appleseed.studio/mainwindow/rendering/renderingmanager.h b/src/appleseed.studio/mainwindow/rendering/renderingmanager.h index 8fa8995dce..c1d34bae9f 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderingmanager.h +++ b/src/appleseed.studio/mainwindow/rendering/renderingmanager.h @@ -55,7 +55,7 @@ #include // Forward declarations. -namespace appleseed { namespace studio { class RenderTab; } } +namespace appleseed { namespace studio { class FinalRenderViewportTab; } } namespace appleseed { namespace studio { class StatusBar; } } namespace foundation { class IAbortSwitch; } namespace renderer { class Frame; } @@ -87,7 +87,10 @@ class RenderingManager renderer::Project* project, const renderer::ParamArray& params, const RenderingMode rendering_mode, - RenderTab* render_tab); + FinalRenderViewportTab* final_render_viewport_tab); + + // Get current rendering mode + RenderingMode get_rendering_mode() const; // Return true if currently rendering, false otherwise. bool is_rendering() const; @@ -165,7 +168,7 @@ class RenderingManager renderer::ParamArray m_params; foundation::SearchPaths m_resource_search_paths; RenderingMode m_rendering_mode; - RenderTab* m_render_tab; + FinalRenderViewportTab* m_final_render_viewport_tab; std::unique_ptr m_tile_callback_factory; diff --git a/src/appleseed.studio/mainwindow/rendering/renderwidget.cpp b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp similarity index 80% rename from src/appleseed.studio/mainwindow/rendering/renderwidget.cpp rename to src/appleseed.studio/mainwindow/rendering/renderlayer.cpp index c10a6b4e42..7a40b6fb3e 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderwidget.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp @@ -28,7 +28,7 @@ // // Interface header. -#include "renderwidget.h" +#include "renderlayer.h" // appleseed.renderer headers. #include "renderer/api/frame.h" @@ -39,6 +39,8 @@ #include "foundation/image/nativedrawing.h" #include "foundation/image/tile.h" #include "foundation/math/scalar.h" +#include "foundation/platform/types.h" +#include "utility/gl.h" // Qt headers. #include @@ -47,6 +49,9 @@ #include #include #include +#include +#include +#include #include // Standard headers. @@ -61,10 +66,10 @@ namespace appleseed { namespace studio { // -// RenderWidget class implementation. +// RenderLayer class implementation. // -RenderWidget::RenderWidget( +RenderLayer::RenderLayer( const size_t width, const size_t height, OCIO::ConstConfigRcPtr ocio_config, @@ -72,28 +77,85 @@ RenderWidget::RenderWidget( : QWidget(parent) , m_mutex(QMutex::Recursive) , m_ocio_config(ocio_config) + , m_gl_initialized(false) { setFocusPolicy(Qt::StrongFocus); setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent, true); + m_gl_tex = new QOpenGLTexture(QOpenGLTexture::Target2D); + resize(width, height); const char* display_name = m_ocio_config->getDefaultDisplay(); const char* default_transform = m_ocio_config->getDefaultView(display_name); - slot_display_transform_changed(default_transform); + set_display_transform(default_transform); setAcceptDrops(true); } -QImage RenderWidget::capture() +void RenderLayer::draw(GLuint empty_vao, bool paths_display_active) +{ + QMutexLocker locker(&m_mutex); + + m_gl_tex->destroy(); + m_gl_tex->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Nearest); + m_gl_tex->setData(m_image, QOpenGLTexture::MipMapGeneration::DontGenerateMipMaps); + + m_gl->glUseProgram(m_shader_program); + + GLfloat mult = paths_display_active ? 0.6 : 1.0; + m_gl->glUniform1f(m_mult_loc, mult); + + m_gl->glActiveTexture(GL_TEXTURE0); + m_gl_tex->bind(); + m_gl->glDisable(GL_DEPTH_TEST); + m_gl->glDepthMask(GL_FALSE); + m_gl->glBindVertexArray(empty_vao); + m_gl->glDrawArrays(GL_TRIANGLES, 0, 3); + m_gl->glDepthMask(GL_TRUE); +} + +void RenderLayer::init_gl(QSurfaceFormat format) +{ + if (!m_gl) + { + RENDERER_LOG_ERROR("Attempted to initialize GL without first setting GL functions"); + return; + } + + auto vertex_shader = load_gl_shader("fullscreen_tri.vert"); + auto fragment_shader = load_gl_shader("final_render.frag"); + + create_shader_program( + m_gl, + m_shader_program, + &vertex_shader, + &fragment_shader); + + m_mult_loc = m_gl->glGetUniformLocation(m_shader_program, "u_mult"); + + m_gl_initialized = true; +} + +void RenderLayer::set_gl_functions(QOpenGLFunctions_4_1_Core* functions) +{ + m_gl = functions; +} + +QImage RenderLayer::capture() { QMutexLocker locker(&m_mutex); return m_image.copy(); } -void RenderWidget::resize( +void RenderLayer::darken() +{ + multiply(0.2f); +} + +void RenderLayer::resize( const size_t width, const size_t height) { @@ -111,7 +173,7 @@ void RenderWidget::resize( clear(); } -void RenderWidget::clear() +void RenderLayer::clear() { QMutexLocker locker(&m_mutex); @@ -136,14 +198,14 @@ namespace } } -void RenderWidget::start_render() +void RenderLayer::start_render() { // Clear the image storage. if (m_image_storage) m_image_storage->clear(Color4f(0.0f)); } -void RenderWidget::multiply(const float multiplier) +void RenderLayer::multiply(const float multiplier) { QMutexLocker locker(&m_mutex); @@ -199,7 +261,7 @@ namespace } } -void RenderWidget::highlight_tile( +void RenderLayer::highlight_tile( const Frame& frame, const size_t tile_x, const size_t tile_y, @@ -252,7 +314,7 @@ void RenderWidget::highlight_tile( sizeof(BracketColor)); } -void RenderWidget::blit_tile( +void RenderLayer::blit_tile( const Frame& frame, const size_t tile_x, const size_t tile_y) @@ -265,7 +327,7 @@ void RenderWidget::blit_tile( update_tile_no_lock(tile_x, tile_y); } -void RenderWidget::blit_frame(const Frame& frame) +void RenderLayer::blit_frame(const Frame& frame) { QMutexLocker locker(&m_mutex); @@ -283,31 +345,27 @@ void RenderWidget::blit_frame(const Frame& frame) } } -void RenderWidget::slot_display_transform_changed(const QString& transform) +void RenderLayer::set_display_transform(const QString& transform) { - { - QMutexLocker locker(&m_mutex); + QMutexLocker locker(&m_mutex); - OCIO::DisplayTransformRcPtr transform_ptr = OCIO::DisplayTransform::Create(); - transform_ptr->setInputColorSpaceName(OCIO::ROLE_SCENE_LINEAR); - transform_ptr->setDisplay(m_ocio_config->getDefaultDisplay()); - transform_ptr->setView(transform.toStdString().c_str()); + OCIO::DisplayTransformRcPtr transform_ptr = OCIO::DisplayTransform::Create(); + transform_ptr->setInputColorSpaceName(OCIO::ROLE_SCENE_LINEAR); + transform_ptr->setDisplay(m_ocio_config->getDefaultDisplay()); + transform_ptr->setView(transform.toStdString().c_str()); - OCIO::ConstContextRcPtr context = m_ocio_config->getCurrentContext(); - m_ocio_processor = m_ocio_config->getProcessor(context, transform_ptr, OCIO::TRANSFORM_DIR_FORWARD); + OCIO::ConstContextRcPtr context = m_ocio_config->getCurrentContext(); + m_ocio_processor = m_ocio_config->getProcessor(context, transform_ptr, OCIO::TRANSFORM_DIR_FORWARD); - if (m_image_storage) + if (m_image_storage) + { + const CanvasProperties& frame_props = m_image_storage->properties(); + for (size_t y = 0; y < frame_props.m_tile_count_y; ++y) { - const CanvasProperties& frame_props = m_image_storage->properties(); - for (size_t y = 0; y < frame_props.m_tile_count_y; ++y) - { - for (size_t x = 0; x < frame_props.m_tile_count_x; ++x) - update_tile_no_lock(x, y); - } + for (size_t x = 0; x < frame_props.m_tile_count_x; ++x) + update_tile_no_lock(x, y); } } - - update(); } namespace @@ -330,7 +388,7 @@ namespace } } -void RenderWidget::allocate_working_storage(const CanvasProperties& frame_props) +void RenderLayer::allocate_working_storage(const CanvasProperties& frame_props) { if (!m_image_storage || !is_compatible(*m_image_storage, frame_props)) { @@ -365,7 +423,7 @@ void RenderWidget::allocate_working_storage(const CanvasProperties& frame_props) } } -void RenderWidget::blit_tile_no_lock( +void RenderLayer::blit_tile_no_lock( const Frame& frame, const size_t tile_x, const size_t tile_y) @@ -378,7 +436,7 @@ void RenderWidget::blit_tile_no_lock( dst_tile.copy_from(src_tile); } -void RenderWidget::update_tile_no_lock(const size_t tile_x, const size_t tile_y) +void RenderLayer::update_tile_no_lock(const size_t tile_x, const size_t tile_y) { // Retrieve the source tile. const Tile& src_tile = m_image_storage->tile(tile_x, tile_y); @@ -428,40 +486,5 @@ void RenderWidget::update_tile_no_lock(const size_t tile_x, const size_t tile_y) NativeDrawing::blit(dest, dest_stride, uint8_rgb_tile); } -void RenderWidget::paintEvent(QPaintEvent* event) -{ - QMutexLocker locker(&m_mutex); - - m_painter.begin(this); - m_painter.drawImage(rect(), m_image); - m_painter.end(); -} - -void RenderWidget::dragEnterEvent(QDragEnterEvent* event) -{ - if (event->mimeData()->hasFormat("text/plain")) - event->acceptProposedAction(); -} - -void RenderWidget::dragMoveEvent(QDragMoveEvent* event) -{ - if (pos().x() <= event->pos().x() && pos().y() <= event->pos().y() - && event->pos().x() < pos().x() + width() && event->pos().y() < pos().y() + height()) - { - event->accept(); - } - else - event->ignore(); -} - -void RenderWidget::dropEvent(QDropEvent* event) -{ - emit signal_material_dropped( - Vector2d( - static_cast(event->pos().x()) / width(), - static_cast(event->pos().y()) / height()), - event->mimeData()->text()); -} - } // namespace studio } // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/renderwidget.h b/src/appleseed.studio/mainwindow/rendering/renderlayer.h similarity index 74% rename from src/appleseed.studio/mainwindow/rendering/renderwidget.h rename to src/appleseed.studio/mainwindow/rendering/renderlayer.h index 4f82ca88ba..85c2a398cd 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderwidget.h +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.h @@ -44,6 +44,7 @@ namespace OCIO = OCIO_NAMESPACE; // Qt headers. #include #include +#include #include #include @@ -58,7 +59,10 @@ namespace renderer { class Frame; } class QDragEnterEvent; class QDragMoveEvent; class QDropEvent; +class QOpenGLFunctions_4_1_Core; +class QOpenGLTexture; class QPaintEvent; +class QRect; namespace appleseed { namespace studio { @@ -67,7 +71,7 @@ namespace studio { // A render widget based on QImage. // -class RenderWidget +class RenderLayer : public QWidget , public ICapturableWidget { @@ -75,7 +79,7 @@ class RenderWidget public: // Constructor. - RenderWidget( + RenderLayer( const size_t width, const size_t height, OCIO::ConstConfigRcPtr ocio_config, @@ -84,6 +88,9 @@ class RenderWidget // Thread-safe. QImage capture() override; + // Thread-safe. + void darken(); + // Thread-safe. void resize( const size_t width, @@ -108,12 +115,24 @@ class RenderWidget // Thread-safe. void blit_tile( - const renderer::Frame& frame, - const size_t tile_x, - const size_t tile_y); + const renderer::Frame& frame, + const size_t tile_x, + const size_t tile_y); // Thread-safe. - void blit_frame(const renderer::Frame& frame); + void blit_frame( + const renderer::Frame& frame); + + // Thread-safe. + void set_display_transform( + const QString& transform); + + void draw( + GLuint empty_vao, + bool paths_display_active); + + void init_gl(QSurfaceFormat format); + void set_gl_functions(QOpenGLFunctions_4_1_Core* functions); // Direct access to internals for high-performance drawing. QMutex& mutex(); @@ -122,50 +141,47 @@ class RenderWidget signals: void signal_material_dropped( const foundation::Vector2d& drop_pos, - const QString& material_name); - - public slots: - void slot_display_transform_changed(const QString& transform); + const QString& material_name); private: mutable QMutex m_mutex; QImage m_image; - QPainter m_painter; std::unique_ptr m_float_tile_storage; std::unique_ptr m_uint8_tile_storage; std::unique_ptr m_image_storage; + QOpenGLFunctions_4_1_Core* m_gl; + QOpenGLTexture* m_gl_tex; + GLuint m_shader_program; + GLint m_mult_loc; + bool m_gl_initialized; + OCIO::ConstConfigRcPtr m_ocio_config; OCIO::ConstProcessorRcPtr m_ocio_processor; void allocate_working_storage(const foundation::CanvasProperties& frame_props); void blit_tile_no_lock( - const renderer::Frame& frame, - const size_t tile_x, - const size_t tile_y); + const renderer::Frame& frame, + const size_t tile_x, + const size_t tile_y); void update_tile_no_lock( - const size_t tile_x, - const size_t tile_y); - - void paintEvent(QPaintEvent* event) override; - void dragEnterEvent(QDragEnterEvent* event) override; - void dragMoveEvent(QDragMoveEvent* event) override; - void dropEvent(QDropEvent* event) override; + const size_t tile_x, + const size_t tile_y); }; // -// RenderWidget class implementation. +// RenderLayer class implementation. // -inline QMutex& RenderWidget::mutex() +inline QMutex& RenderLayer::mutex() { return m_mutex; } -inline QImage& RenderWidget::image() +inline QImage& RenderLayer::image() { return m_image; } diff --git a/src/appleseed.studio/mainwindow/rendering/scenepickinghandler.cpp b/src/appleseed.studio/mainwindow/rendering/scenepickinghandler.cpp index 328b866e5b..f9866ccb54 100644 --- a/src/appleseed.studio/mainwindow/rendering/scenepickinghandler.cpp +++ b/src/appleseed.studio/mainwindow/rendering/scenepickinghandler.cpp @@ -122,7 +122,7 @@ bool ScenePickingHandler::eventFilter(QObject* object, QEvent* event) { if (m_enabled) { - if (event->type() == QEvent::MouseButtonPress) + if (event->type() == QEvent::MouseButtonRelease) { const QMouseEvent* mouse_event = static_cast(event); if (!(mouse_event->modifiers() & (Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier))) diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp new file mode 100644 index 0000000000..f15e604300 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -0,0 +1,440 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +// Interface header. +#include "viewportcanvas.h" + +// appleseed.studio headers. +#include "utility/gl.h" + +// appleseed.renderer headers. +#include "renderer/api/frame.h" + +// appleseed.foundation headers. +#include "foundation/image/canvasproperties.h" +#include "foundation/image/image.h" +#include "foundation/image/nativedrawing.h" +#include "foundation/image/tile.h" +#include "foundation/math/scalar.h" +#include "foundation/platform/types.h" + +// Qt headers. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Standard headers. +#include +#include + +using namespace foundation; +using namespace renderer; +using namespace std; + +namespace appleseed { +namespace studio { + +// +// ViewportCanvas class implementation. +// + +ViewportCanvas::ViewportCanvas( + const renderer::Project& project, + const size_t width, + const size_t height, + OCIO::ConstConfigRcPtr ocio_config, + const LightPathsManager& light_paths_manager, + QWidget* parent) + : QOpenGLWidget(parent) + , m_project(project) + , m_draw_light_paths(false) + , m_active_base_layer(static_cast(0)) + , m_resolve_program(0) + , m_accum_loc(0) + , m_accum_tex(0) + , m_revealage_loc(0) + , m_revealage_tex(0) + , m_accum_revealage_fb(0) +{ + setFocusPolicy(Qt::StrongFocus); + setFixedWidth(static_cast(width)); + setFixedHeight(static_cast(height)); + setAutoFillBackground(false); + setAttribute(Qt::WA_OpaquePaintEvent, true); + + connect( + &light_paths_manager, &LightPathsManager::signal_light_path_selection_changed, + this, &ViewportCanvas::slot_light_path_selection_changed); + + create_render_layer(ocio_config, width, height); + create_gl_scene_layer(width, height); + create_light_paths_layer(light_paths_manager, width, height); + + resize(width, height); + + setAcceptDrops(true); +} + +ViewportCanvas::~ViewportCanvas() +{ + m_gl->glDeleteProgram(m_resolve_program); + m_gl->glDeleteTextures(1, &m_accum_tex); + m_gl->glDeleteTextures(1, &m_revealage_tex); + m_gl->glDeleteTextures(1, &m_color_tex); + m_gl->glDeleteTextures(1, &m_depth_tex); + m_gl->glDeleteFramebuffers(1, &m_accum_revealage_fb); + m_gl->glDeleteFramebuffers(1, &m_main_fb); +} + +void ViewportCanvas::create_render_layer( + OCIO::ConstConfigRcPtr ocio_config, + const std::size_t width, + const std::size_t height) +{ + m_render_layer = + std::unique_ptr(new RenderLayer( + width, + height, + ocio_config)); +} + +void ViewportCanvas::create_gl_scene_layer( + const std::size_t width, + const std::size_t height) +{ + m_gl_scene_layer = + std::unique_ptr(new GLSceneLayer( + m_project, + width, + height)); +} + +void ViewportCanvas::create_light_paths_layer( + const LightPathsManager& light_paths_manager, + const std::size_t width, + const std::size_t height) +{ + m_light_paths_layer = + std::unique_ptr(new LightPathsLayer( + m_project, + light_paths_manager, + width, + height)); +} + +ViewportCanvas::BaseLayer ViewportCanvas::get_active_layer() const +{ + return m_active_base_layer; +} + +RenderLayer* ViewportCanvas::get_render_layer() +{ + return m_render_layer.get(); +} + +LightPathsLayer* ViewportCanvas::get_light_paths_layer() +{ + return m_light_paths_layer.get(); +} + +GLSceneLayer* ViewportCanvas::get_gl_scene_layer() +{ + return m_gl_scene_layer.get(); +} + +QImage ViewportCanvas::capture() +{ + return grabFramebuffer(); +} + +void ViewportCanvas::initializeGL() { + RENDERER_LOG_INFO("initializing opengl."); + + m_gl = QOpenGLContext::currentContext()->versionFunctions(); + + const auto qs_format = format(); + if (!m_gl->initializeOpenGLFunctions()) + { + const int major_version = qs_format.majorVersion(); + const int minor_version = qs_format.minorVersion(); + RENDERER_LOG_ERROR( + "opengl: could not load required gl functions. loaded version %d.%d, required version 3.3.", + major_version, + minor_version); + return; + } + + m_gl->glGenVertexArrays(1, &m_empty_vao); + m_gl->glBindVertexArray(m_empty_vao); + m_gl->glGenBuffers(1, &m_empty_vbo); + m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_empty_vbo); + float vals[3]{ 0.0f, 0.0f, 0.0f }; + m_gl->glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 3, static_cast(vals), GL_STATIC_DRAW); + m_gl->glVertexAttribPointer(0, sizeof(float), GL_FLOAT, GL_FALSE, sizeof(float), static_cast(0)); + m_gl->glEnableVertexAttribArray(0); + + auto vertex_shader = load_gl_shader("fullscreen_tri.vert"); + auto fragment_shader = load_gl_shader("oit_resolve.frag"); + + create_shader_program( + m_gl, + m_resolve_program, + &vertex_shader, + &fragment_shader); + + m_accum_loc = m_gl->glGetUniformLocation(m_resolve_program, "u_accum_tex"); + m_revealage_loc = m_gl->glGetUniformLocation(m_resolve_program, "u_revealage_tex"); + + GLuint temp_fbs[2]; + m_gl->glGenFramebuffers(2, temp_fbs); + + m_main_fb = temp_fbs[0]; + m_accum_revealage_fb = temp_fbs[1]; + + GLuint temp_texs[4]; + m_gl->glGenTextures(4, temp_texs); + + m_color_tex = temp_texs[0]; + m_depth_tex = temp_texs[1]; + m_accum_tex = temp_texs[2]; + m_revealage_tex = temp_texs[3]; + + resizeGL(width(), height()); + + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_main_fb); + m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_color_tex, 0); + m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depth_tex, 0); + + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_accum_revealage_fb); + m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_accum_tex, 0); + m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, m_revealage_tex, 0); + m_gl->glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_depth_tex, 0); + + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, 0); + + m_gl->glUseProgram(m_resolve_program); + m_gl->glUniform1i(m_accum_loc, 0); + m_gl->glUniform1i(m_revealage_loc, 1); + + m_render_layer->set_gl_functions(m_gl); + m_render_layer->init_gl(qs_format); + m_gl_scene_layer->set_gl_functions(m_gl); + m_gl_scene_layer->init_gl(qs_format); + m_light_paths_layer->set_gl_functions(m_gl); + m_light_paths_layer->init_gl(qs_format); +} + +void ViewportCanvas::resize( + const size_t width, + const size_t height) +{ + m_render_layer->resize(width, height); + m_light_paths_layer->resize(width, height); +} + +void ViewportCanvas::set_base_layer(const BaseLayer base_layer) +{ + m_active_base_layer = base_layer; + update(); +} + +void ViewportCanvas::resizeGL( + int width, + int height) +{ + m_light_paths_layer->resize(width, height); + + m_gl->glBindTexture(GL_TEXTURE_2D, m_color_tex); + m_gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + m_gl->glBindTexture(GL_TEXTURE_2D, m_depth_tex); + m_gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + m_gl->glBindTexture(GL_TEXTURE_2D, m_accum_tex); + m_gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_HALF_FLOAT, NULL); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + m_gl->glBindTexture(GL_TEXTURE_2D, m_revealage_tex); + m_gl->glTexImage2D(GL_TEXTURE_2D, 0, GL_R16F, width, height, 0, GL_RED, GL_HALF_FLOAT, NULL); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + m_gl->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + + m_gl->glBindTexture(GL_TEXTURE_2D, 0); +} + +void ViewportCanvas::paintGL() +{ + + double dpr = static_cast(m_render_layer->image().devicePixelRatio()); + GLsizei w = static_cast(width() * dpr); + GLsizei h = static_cast(height() * dpr); + m_gl->glViewport(0, 0, w, h); + + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_main_fb); + // Clear the main framebuffers + GLfloat main_clear[]{ 0.0, 0.0, 0.0, 0.0 }; + m_gl->glClearBufferfv(GL_COLOR, 0, main_clear); + m_gl->glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); + + if (m_active_base_layer == BaseLayer::FinalRender) + { + m_render_layer->draw(m_empty_vao, m_draw_light_paths); + } + + QOpenGLContext *ctx = const_cast(QOpenGLContext::currentContext()); + + if (m_active_base_layer == BaseLayer::OpenGL || m_draw_light_paths) + m_gl_scene_layer->draw_depth_only(); + + if (m_active_base_layer == BaseLayer::OpenGL) + m_gl_scene_layer->draw(); + + if (m_draw_light_paths) + { + // Bind accum/revealage framebuffer + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_accum_revealage_fb); + + // Set both attachments as active draw buffers + const GLenum buffers[]{ GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 }; + m_gl->glDrawBuffers(2, buffers); + + // Clear the buffers + GLfloat accum_clear_col[]{ 0.0, 0.0, 0.0, 0.0 }; + m_gl->glClearBufferfv(GL_COLOR, 0, accum_clear_col); + GLfloat revealage_clear_col[]{ 1.0, 0.0, 0.0, 0.0 }; + m_gl->glClearBufferfv(GL_COLOR, 1, revealage_clear_col); + + // Enable proper blending for each + m_gl->glEnable(GL_BLEND); + m_gl->glBlendFunci(0, GL_ONE, GL_ONE); + m_gl->glBlendFunci(1, GL_ZERO, GL_ONE_MINUS_SRC_COLOR); + m_gl->glEnable(GL_DEPTH_TEST); + m_gl->glDepthMask(GL_FALSE); + m_gl->glDepthFunc(GL_LESS); + + if (m_active_base_layer == BaseLayer::FinalRender) + m_light_paths_layer->draw_render_camera(); + else + m_light_paths_layer->draw(); + + m_gl->glUseProgram(m_resolve_program); + + // Set default framebuffer object + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_main_fb); + m_gl->glDrawBuffer(GL_COLOR_ATTACHMENT0); + + m_gl->glBindVertexArray(m_empty_vao); + + m_gl->glActiveTexture(GL_TEXTURE0); + m_gl->glBindTexture(GL_TEXTURE_2D, m_accum_tex); + m_gl->glActiveTexture(GL_TEXTURE1); + m_gl->glBindTexture(GL_TEXTURE_2D, m_revealage_tex); + + m_gl->glDisable(GL_DEPTH_TEST); + m_gl->glDepthMask(GL_FALSE); + m_gl->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + m_gl->glDrawArrays(GL_TRIANGLES, 0, 3); + + m_gl->glActiveTexture(GL_TEXTURE1); + m_gl->glBindTexture(GL_TEXTURE_2D, 0); + m_gl->glActiveTexture(GL_TEXTURE0); + m_gl->glBindTexture(GL_TEXTURE_2D, 0); + m_gl->glDepthMask(GL_TRUE); + } + + m_gl->glBindFramebuffer(GL_READ_FRAMEBUFFER, m_main_fb); + m_gl->glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ctx->defaultFramebufferObject()); + m_gl->glBlitFramebuffer(0, 0, w, h, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST); +} + +void ViewportCanvas::dragEnterEvent(QDragEnterEvent* event) +{ + if (event->mimeData()->hasFormat("text/plain")) + event->acceptProposedAction(); +} + +void ViewportCanvas::dragMoveEvent(QDragMoveEvent* event) +{ + if (pos().x() <= event->pos().x() && pos().y() <= event->pos().y() + && event->pos().x() < pos().x() + width() && event->pos().y() < pos().y() + height()) + { + event->accept(); + } + else + event->ignore(); +} + +void ViewportCanvas::dropEvent(QDropEvent* event) +{ + emit signal_material_dropped( + Vector2d( + static_cast(event->pos().x()) / width(), + static_cast(event->pos().y()) / height()), + event->mimeData()->text()); +} + +void ViewportCanvas::slot_toggle_backface_culling(const bool checked) +{ + m_gl_scene_layer->toggle_backface_culling(checked); + update(); +} + +void ViewportCanvas::slot_display_transform_changed(const QString& transform) +{ + m_render_layer->set_display_transform(transform); + + if (m_active_base_layer == BaseLayer::FinalRender) + { + update(); + } +} + +void ViewportCanvas::slot_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths) +{ + m_draw_light_paths = display_light_paths && total_light_paths > 0; + update(); +} + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h new file mode 100644 index 0000000000..f09befe778 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h @@ -0,0 +1,175 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// appleseed.studio headers. +#include "mainwindow/rendering/lightpathslayer.h" +#include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/glscenelayer.h" +#include "mainwindow/rendering/renderclipboardhandler.h" +#include "mainwindow/rendering/renderlayer.h" + + +// appleseed.foundation headers. +#include "foundation/image/image.h" +#include "foundation/image/tile.h" +#include "foundation/math/vector.h" + +// Qt headers. +#include +#include +#include +#include +#include + +// OpenColorIO headers. +#include +namespace OCIO = OCIO_NAMESPACE; + +// Standard headers. +#include +#include +#include + +// Forward declarations. +namespace foundation { class CanvasProperties; } +namespace renderer { class Frame; } +class QDragEnterEvent; +class QDragMoveEvent; +class QDropEvent; +class QPaintEvent; +class QOpenGLFunctions_4_1_Core; + +namespace appleseed { +namespace studio { + +// +// A render widget based on QImage. +// + +class ViewportCanvas + : public QOpenGLWidget + , public ICapturableWidget +{ + Q_OBJECT + + public: + // Constructor. + ViewportCanvas( + const renderer::Project& project, + const size_t width, + const size_t height, + OCIO::ConstConfigRcPtr ocio_config, + const LightPathsManager& lith_paths_manager, + QWidget* parent = nullptr); + + ~ViewportCanvas(); + + enum BaseLayer { + FinalRender, + OpenGL, + BASE_LAYER_MAX_VALUE + }; + + // Thread-safe. + QImage capture() override; + + // Thread-safe. + void resize( + const size_t width, + const size_t height); + + void set_base_layer(const BaseLayer base_layer); + + BaseLayer get_active_layer() const; + RenderLayer* get_render_layer(); + GLSceneLayer* get_gl_scene_layer(); + LightPathsLayer* get_light_paths_layer(); + + signals: + void signal_material_dropped( + const foundation::Vector2d& drop_pos, + const QString& material_name); + + public slots: + void slot_toggle_backface_culling(const bool checked); + void slot_display_transform_changed(const QString& transform); + void slot_light_path_selection_changed( + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths); + + private: + const renderer::Project& m_project; + + QOpenGLFunctions_4_1_Core* m_gl; + QPainter m_painter; + + GLuint m_depth_tex; + GLuint m_color_tex; + GLuint m_accum_tex; + GLuint m_revealage_tex; + GLuint m_main_fb; + GLuint m_accum_revealage_fb; + GLuint m_empty_vao; + GLuint m_empty_vbo; + + GLuint m_resolve_program; + GLint m_accum_loc; + GLint m_revealage_loc; + + std::unique_ptr m_render_layer; + std::unique_ptr m_gl_scene_layer; + std::unique_ptr m_light_paths_layer; + + bool m_draw_light_paths; + BaseLayer m_active_base_layer; + + void create_light_paths_layer( + const LightPathsManager& light_paths_manager, + const std::size_t width, + const std::size_t height); + void create_gl_scene_layer( + const std::size_t width, + const std::size_t height); + void create_render_layer( + OCIO::ConstConfigRcPtr ocio_config, + const std::size_t width, + const std::size_t height); + + void initializeGL() override; + void resizeGL(int width, int height) override; + void paintGL() override; + void dragEnterEvent(QDragEnterEvent* event) override; + void dragMoveEvent(QDragMoveEvent* event) override; + void dropEvent(QDropEvent* event) override; +}; + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/renderregionhandler.cpp b/src/appleseed.studio/mainwindow/rendering/viewportregionselectionhandler.cpp similarity index 84% rename from src/appleseed.studio/mainwindow/rendering/renderregionhandler.cpp rename to src/appleseed.studio/mainwindow/rendering/viewportregionselectionhandler.cpp index 2affd76d12..66159dffa5 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderregionhandler.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportregionselectionhandler.cpp @@ -28,7 +28,7 @@ // // Interface header. -#include "renderregionhandler.h" +#include "viewportregionselectionhandler.h" // appleseed.qtcommon headers. #include "widgets/mousecoordinatestracker.h" @@ -54,7 +54,7 @@ using namespace foundation; namespace appleseed { namespace studio { -RenderRegionHandler::RenderRegionHandler( +ViewportRegionSelectionHandler::ViewportRegionSelectionHandler( QWidget* widget, const MouseCoordinatesTracker& mouse_tracker) : m_widget(widget) @@ -66,22 +66,22 @@ RenderRegionHandler::RenderRegionHandler( m_widget->installEventFilter(this); } -RenderRegionHandler::~RenderRegionHandler() +ViewportRegionSelectionHandler::~ViewportRegionSelectionHandler() { m_widget->removeEventFilter(this); } -void RenderRegionHandler::set_enabled(const bool enabled) +void ViewportRegionSelectionHandler::set_enabled(const bool enabled) { m_enabled = enabled; } -void RenderRegionHandler::set_mode(const Mode mode) +void ViewportRegionSelectionHandler::set_mode(const Mode mode) { m_mode = mode; } -bool RenderRegionHandler::eventFilter(QObject* object, QEvent* event) +bool ViewportRegionSelectionHandler::eventFilter(QObject* object, QEvent* event) { if (m_enabled) { @@ -112,12 +112,19 @@ bool RenderRegionHandler::eventFilter(QObject* object, QEvent* event) { const QMouseEvent* mouse_event = static_cast(event); - if (mouse_event->button() == Qt::LeftButton) + if (mouse_event->button() == Qt::LeftButton && + !(mouse_event->modifiers() & (Qt::AltModifier | Qt::ShiftModifier | Qt::ControlModifier))) { m_rubber_band->hide(); + const QPoint& pos = mouse_event->pos(); + + // Don't consider a click as a selection. + if (m_origin == pos) + break; + const Vector2i p0 = m_mouse_tracker.widget_to_pixel(m_origin); - const Vector2i p1 = m_mouse_tracker.widget_to_pixel(mouse_event->pos()); + const Vector2i p1 = m_mouse_tracker.widget_to_pixel(pos); const int x0 = std::max(std::min(p0.x, p1.x), 0); const int y0 = std::max(std::min(p0.y, p1.y), 0); @@ -129,6 +136,8 @@ bool RenderRegionHandler::eventFilter(QObject* object, QEvent* event) if (m_mode == RectangleSelectionMode) emit signal_rectangle_selection(QRect(x0, y0, w, h)); else emit signal_render_region(QRect(x0, y0, w, h)); + + return true; } break; diff --git a/src/appleseed.studio/mainwindow/rendering/renderregionhandler.h b/src/appleseed.studio/mainwindow/rendering/viewportregionselectionhandler.h similarity index 95% rename from src/appleseed.studio/mainwindow/rendering/renderregionhandler.h rename to src/appleseed.studio/mainwindow/rendering/viewportregionselectionhandler.h index c3ae751899..4d8424c0b2 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderregionhandler.h +++ b/src/appleseed.studio/mainwindow/rendering/viewportregionselectionhandler.h @@ -43,18 +43,18 @@ class QWidget; namespace appleseed { namespace studio { -class RenderRegionHandler +class ViewportRegionSelectionHandler : public QObject { Q_OBJECT public: // Default mode is RectangleSelectionMode. - RenderRegionHandler( + ViewportRegionSelectionHandler( QWidget* widget, const qtcommon::MouseCoordinatesTracker& mouse_tracker); - ~RenderRegionHandler() override; + ~ViewportRegionSelectionHandler() override; void set_enabled(const bool enabled); diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp new file mode 100644 index 0000000000..170d278dce --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -0,0 +1,150 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited +// Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization +// +// 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. +// + +// Interface header. +#include "viewporttab.h" + +// appleseed.studio headers. +#include "mainwindow/project/projectexplorer.h" +#include "mainwindow/rendering/renderingmanager.h" + +// appleseed.qtcommon headers. +#include "utility/miscellaneous.h" + +// appleseed.renderer headers. +#include "renderer/api/frame.h" +#include "renderer/api/project.h" + +// appleseed.foundation headers. +#include "foundation/image/canvasproperties.h" +#include "foundation/image/image.h" + +// OpenColorIO headers. +#include + +// Qt headers. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Standard headers. +#include + +using namespace appleseed::qtcommon; +using namespace foundation; +using namespace renderer; +namespace OCIO = OCIO_NAMESPACE; + +namespace appleseed { +namespace studio { + +// +// ViewportTab class implementation. +// + +ViewportTab::ViewportTab( + ProjectExplorer& project_explorer, + Project& project, + RenderingManager& rendering_manager, + OCIO::ConstConfigRcPtr ocio_config, + renderer::ParamArray application_settings) + : m_application_settings(application_settings) + , m_project_explorer(project_explorer) + , m_project(project) + , m_rendering_manager(rendering_manager) + , m_ocio_config(ocio_config) +{ +} + +void ViewportTab::clear() +{ + ViewportCanvas* viewport_canvas = get_viewport_canvas(); + viewport_canvas->get_render_layer()->clear(); + viewport_canvas->repaint(); +} + +void ViewportTab::render_began() +{ + ViewportCanvas* viewport_canvas = get_viewport_canvas(); + viewport_canvas->get_render_layer()->darken(); + viewport_canvas->get_light_paths_layer()->update_render_camera_transform(); +} + +void ViewportTab::reset_zoom() +{ + m_zoom_handler->reset_zoom(); +} + +void ViewportTab::update() +{ + ViewportCanvas* viewport_canvas = get_viewport_canvas(); + viewport_canvas->update(); +} + +void ViewportTab::update_size() +{ + const CanvasProperties& props = m_project.get_frame()->image().properties(); + + ViewportCanvas* viewport_canvas = get_viewport_canvas(); + viewport_canvas->resize( + props.m_canvas_width, + props.m_canvas_height); +} + +void ViewportTab::on_tab_selected() +{ +} + +ViewportTab::State ViewportTab::save_state() const +{ + State state; + state.m_zoom_handler_state = m_zoom_handler->save_state(); + state.m_pan_handler_state = m_pan_handler->save_state(); + return state; +} + +void ViewportTab::load_state(const State& state) +{ + // The order matters here. + m_zoom_handler->load_state(state.m_zoom_handler_state); + m_pan_handler->load_state(state.m_pan_handler_state); +} + + +} // namespace studio +} // namespace appleseed + +#include "mainwindow/rendering/moc_cpp_viewporttab.cxx" diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h new file mode 100644 index 0000000000..291c3a5b77 --- /dev/null +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -0,0 +1,125 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2010-2013 Francois Beaune, Jupiter Jazz Limited +// Copyright (c) 2014-2018 Francois Beaune, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// appleseed.studio headers. +#include "mainwindow/rendering/cameracontroller.h" +#include "mainwindow/rendering/lightpathsviewporttoolbar.h" +#include "mainwindow/rendering/materialdrophandler.h" +#include "mainwindow/rendering/pixelcolortracker.h" +#include "mainwindow/rendering/pixelinspectorhandler.h" +#include "mainwindow/rendering/renderclipboardhandler.h" +#include "mainwindow/rendering/scenepickinghandler.h" +#include "mainwindow/rendering/viewportcanvas.h" +#include "mainwindow/rendering/viewportregionselectionhandler.h" + +// appleseed.qtcommon headers. +#include "widgets/mousecoordinatestracker.h" +#include "widgets/scrollareapanhandler.h" +#include "widgets/widgetzoomhandler.h" + +// OpenColorIO headers. +#include +namespace OCIO = OCIO_NAMESPACE; + +// Qt headers. +#include +#include + +// Standard headers. +#include + +// Forward declarations. +namespace appleseed { namespace studio { class ProjectExplorer; } } +namespace appleseed { namespace studio { class RenderingManager; } } +namespace renderer { class Entity; } +namespace renderer { class Project; } +class QComboBox; +class QLabel; +class QPoint; +class QRect; +class QScrollArea; +class QToolBar; +class QToolButton; + +namespace appleseed { +namespace studio { + +// +// A tab wrapping a render widget and its toolbar. +// + +class ViewportTab + : public QWidget +{ + Q_OBJECT + + public: + ViewportTab( + ProjectExplorer& project_explorer, + renderer::Project& project, + RenderingManager& rendering_manager, + OCIO::ConstConfigRcPtr ocio_config, + renderer::ParamArray application_settings); + + virtual ViewportCanvas* get_viewport_canvas() const = 0; + + void clear(); + + virtual void render_began(); + void reset_zoom(); + + void update(); + virtual void update_size(); + + virtual void on_tab_selected(); + + struct State + { + qtcommon::WidgetZoomHandler::State m_zoom_handler_state; + qtcommon::ScrollAreaPanHandler::State m_pan_handler_state; + }; + + State save_state() const; + void load_state(const State& state); + + protected: + renderer::ParamArray m_application_settings; + ProjectExplorer& m_project_explorer; + renderer::Project& m_project; + RenderingManager& m_rendering_manager; + OCIO::ConstConfigRcPtr m_ocio_config; + + std::unique_ptr m_zoom_handler; + std::unique_ptr m_pan_handler; +}; + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/resources/resources.qrc b/src/appleseed.studio/resources/resources.qrc index 9dc95f7f95..3ee211c50b 100644 --- a/src/appleseed.studio/resources/resources.qrc +++ b/src/appleseed.studio/resources/resources.qrc @@ -1,8 +1,11 @@ images/appleseed-logo-256.png + shaders/final_render.frag + shaders/fullscreen_tri.vert shaders/lightpaths.frag shaders/lightpaths.vert + shaders/oit_resolve.frag shaders/scene.frag shaders/scene.vert diff --git a/src/appleseed.studio/resources/shaders/final_render.frag b/src/appleseed.studio/resources/shaders/final_render.frag new file mode 100644 index 0000000000..6f9eadf6d7 --- /dev/null +++ b/src/appleseed.studio/resources/shaders/final_render.frag @@ -0,0 +1,41 @@ +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#version 410 + +in vec2 f_uv; + +uniform sampler2D u_render_tex; +uniform float u_mult; + +out vec4 Target0; + +void main() { + vec3 col = texture(u_render_tex, f_uv, 0).rgb; + + Target0 = vec4(col * u_mult, 1.0); +} diff --git a/src/appleseed.studio/resources/shaders/fullscreen_tri.vert b/src/appleseed.studio/resources/shaders/fullscreen_tri.vert new file mode 100644 index 0000000000..7dbb4b2100 --- /dev/null +++ b/src/appleseed.studio/resources/shaders/fullscreen_tri.vert @@ -0,0 +1,48 @@ +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#version 410 + +const vec2 verts[3] = vec2[]( + vec2(3.0, 1.0), + vec2(-1.0, -3.0), + vec2(-1.0, 1.0) +); + +const vec2 uvs[3] = vec2[]( + vec2(2.0, 0.0), + vec2(0.0, 2.0), + vec2(0.0, 0.0) +); + +out vec2 f_uv; + +void main() +{ + f_uv = uvs[gl_VertexID]; + gl_Position = vec4(verts[gl_VertexID], 0.0, 1.0); +} \ No newline at end of file diff --git a/src/appleseed.studio/resources/shaders/lightpaths.frag b/src/appleseed.studio/resources/shaders/lightpaths.frag index f67540108f..cc9e990fcb 100644 --- a/src/appleseed.studio/resources/shaders/lightpaths.frag +++ b/src/appleseed.studio/resources/shaders/lightpaths.frag @@ -25,14 +25,40 @@ // THE SOFTWARE. // -#version 330 +#version 420 #extension GL_ARB_separate_shader_objects : enable -layout(location = 0) in vec3 v_color; +in float f_aa_norm; +flat in vec4 f_color; +flat in float f_thickness; +flat in float f_total_thickness; +flat in float f_aspect_expansion_len; -out vec4 Target0; +uniform vec2 u_res; // resolution of the frame. +// Output requires 2 values to be able to overlay correctly paths over a layer. +// The first output is for paths color and the second output is for paths opacity. +layout(location = 0) out vec4 accum_target; +layout(location = 1) out float revealage_target; + +void write_pixel(vec4 premultiplied_col, vec3 transmit) { + premultiplied_col.a *= 1.0 - clamp((transmit.r + transmit.g + transmit.b) * (1.0 / 3.0), 0, 1); + + const float a = min(1.0, premultiplied_col.a) * 8.0 + 0.01; + const float b = -gl_FragCoord.z * 0.95 + 1.0; + + const float w = clamp(a * a * a * 1e8 * b * b * b, 1e-2, 3e2); + + accum_target = premultiplied_col * w; + revealage_target = premultiplied_col.a; +} void main() { - Target0 = vec4(v_color, 1.0); + const float dist = abs(f_aa_norm) * f_total_thickness - 0.5 / f_aspect_expansion_len; + const float eps = fwidth(dist); + float a = 1.0 - smoothstep(f_thickness - eps, f_thickness + eps, dist); + a *= f_color.a; + + const vec4 premult = vec4(f_color.rgb * a, a); + write_pixel(premult, vec3(0.0)); } diff --git a/src/appleseed.studio/resources/shaders/lightpaths.vert b/src/appleseed.studio/resources/shaders/lightpaths.vert index 6664383094..94364dda12 100644 --- a/src/appleseed.studio/resources/shaders/lightpaths.vert +++ b/src/appleseed.studio/resources/shaders/lightpaths.vert @@ -25,19 +25,130 @@ // THE SOFTWARE. // -#version 330 -#extension GL_ARB_separate_shader_objects : enable +#version 420 -layout(location = 0) in vec3 a_pos; -layout(location = 1) in vec3 a_color; +const float AA_BUFFER_SIZE = 1.0; + +layout(location = 0) in vec3 v_previous; +layout(location = 1) in vec3 v_position; +layout(location = 2) in vec3 v_next; +layout(location = 3) in int v_bitmask; // flag defining which part of a light path is currently drawn. +layout(location = 4) in vec3 v_color; +layout(location = 5) in vec3 v_surface_normal; -uniform mat4 u_view; uniform mat4 u_proj; +uniform mat4 u_view; +uniform vec2 u_res; // resolution of the frame. + +uniform int u_first_selected; +uniform int u_last_selected; + +flat out vec4 f_color; +out float f_aa_norm; +flat out float f_thickness; +flat out float f_total_thickness; +flat out float f_aspect_expansion_len; -layout(location = 0) out vec3 v_color; +// Light path vertex world space position is +// moved away from the surface to avoid clipping. +const float CLIPPING_PREVENTION_FACTOR = 0.0001; + +// Light path thickness in screen space. +const float LINE_THICKNESS = 1.0; + +const float SELECTED_PATH_TRANSPARENCY = 1.0; +const float NON_SELECTED_PATH_TRANSPARENCY = 0.05; + +// +// Reference: +// - https://mattdesl.svbtle.com/drawing-lines-is-hard#screenspace-projected-lines_2 +// + +// Compute current line direction +// depending on which part of the path we +// are drawing (start, middle or end). +vec2 get_line_direction(vec2 curr_screen, vec2 prev_screen, vec2 next_screen) +{ + return + (v_bitmask & 2) == 2 + ? normalize(curr_screen - prev_screen) + : normalize(next_screen - curr_screen); +} + +// Each point on the light path is duplicated to render a real line. +// The duplicated vertex of each light path point is flagged. +bool is_second_point() +{ + return ((v_bitmask & 1) == 1); +} void main() { - v_color = a_color; - gl_Position = u_proj * u_view * vec4(a_pos, 1.0); + // Aspect ratio correction is applied on + // screen points (only on the X axis). + const vec2 aspect_correction = vec2(u_res.x / u_res.y, 1.0); + + // Project points. + // The currently drawn point is offset + // from the surface to ensure path + // doesn't go through it. + const mat4 vp = u_proj * u_view; + const vec4 curr_proj = vp * vec4(v_position + v_surface_normal * CLIPPING_PREVENTION_FACTOR, 1.0); + const vec4 prev_proj = vp * vec4(v_previous, 1.0); + const vec4 next_proj = vp * vec4(v_next, 1.0); + + // Project points in screenspace and apply aspect ratio correction. + const vec2 curr_screen = (curr_proj.xy / curr_proj.w) * aspect_correction; + const vec2 prev_screen = (prev_proj.xy / prev_proj.w) * aspect_correction; + const vec2 next_screen = (next_proj.xy / next_proj.w) * aspect_correction; + + const bool is_second_point = is_second_point(); + + const vec2 line_direction = get_line_direction(curr_screen, prev_screen, next_screen); + + // Compute the normal of the line. + const vec2 line_normal = vec2(-line_direction.y, line_direction.x); + + vec4 normal_clip = vp * vec4(v_surface_normal, 0.0); + normal_clip.x *= aspect_correction.x; + normal_clip = normalize(normal_clip); + + const vec2 tang_clip = vec2(-normal_clip.y, normal_clip.x); + + const float tdp = dot(tang_clip, line_normal); + // it uses tangent to surface unless the tangent to surface is too much aligned with the line direction, + // in which case it uses the line normal as fallback. it does that to reduce the amount of 'pokethrough' of the lines through the geometry. + // if you always expand along line normal then depending on the angle of the line and camera the edges of the rectangle will poke through i the backside of the surface + vec2 expansion = + tdp > 0.05 + ? tang_clip / tdp + : line_normal; + + const vec2 norm_exp = normalize(expansion); + const vec2 res_exp_line_direction = vec2(norm_exp.x * u_res.x, norm_exp.y * u_res.y); + f_aspect_expansion_len = length(res_exp_line_direction); + + const float half_thickness = LINE_THICKNESS * 0.5; + f_thickness = half_thickness / f_aspect_expansion_len; + + f_total_thickness = f_thickness + AA_BUFFER_SIZE / f_aspect_expansion_len; + + expansion *= f_total_thickness; + + // Reverse expansion line_directionection for the duplicated point. + if (is_second_point) expansion *= -1.0; + + vec2 screen_pos = curr_screen + expansion; + screen_pos /= aspect_correction; + gl_Position = vec4(screen_pos * curr_proj.w, curr_proj.z /* curr_proj.w*/, curr_proj.w); + f_aa_norm = is_second_point ? 1.0 : -1.0; + + const bool is_selected = gl_VertexID >= u_first_selected && gl_VertexID < u_last_selected; + + const float alpha = + is_selected + ? SELECTED_PATH_TRANSPARENCY + : NON_SELECTED_PATH_TRANSPARENCY; + + f_color = vec4(v_color, alpha); } diff --git a/src/appleseed.studio/resources/shaders/oit_resolve.frag b/src/appleseed.studio/resources/shaders/oit_resolve.frag new file mode 100644 index 0000000000..3a091797f8 --- /dev/null +++ b/src/appleseed.studio/resources/shaders/oit_resolve.frag @@ -0,0 +1,52 @@ +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#version 410 + +uniform sampler2D u_accum_tex; +uniform sampler2D u_revealage_tex; + +out vec4 Target0; + +float max4(vec4 v) { + return max(max(max(v.x, v.y), v.z), v.w); +} + +void main() { + ivec2 coord = ivec2(gl_FragCoord.xy); + + float revealage = texelFetch(u_revealage_tex, coord, 0).r; + + vec4 accum = texelFetch(u_accum_tex, coord, 0); + // Suppress overflow + if (isinf(max4(abs(accum)))) { + accum.rgb = vec3(accum.a); + } + vec3 averageColor = accum.rgb / max(accum.a, 0.00001); + + Target0 = vec4(averageColor, 1.0 - revealage); +} diff --git a/src/appleseed.studio/resources/shaders/scene.frag b/src/appleseed.studio/resources/shaders/scene.frag index 81ba78f5cb..b7b67880db 100644 --- a/src/appleseed.studio/resources/shaders/scene.frag +++ b/src/appleseed.studio/resources/shaders/scene.frag @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 330 +#version 410 #extension GL_ARB_separate_shader_objects : enable layout(location = 0) in vec3 frag_pos; diff --git a/src/appleseed.studio/resources/shaders/scene.vert b/src/appleseed.studio/resources/shaders/scene.vert index d1fa1f82e3..f5731e6415 100644 --- a/src/appleseed.studio/resources/shaders/scene.vert +++ b/src/appleseed.studio/resources/shaders/scene.vert @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 330 +#version 410 #extension GL_ARB_separate_shader_objects : enable layout(location = 0) in vec3 a_pos; diff --git a/src/appleseed.studio/utility/gl.cpp b/src/appleseed.studio/utility/gl.cpp new file mode 100644 index 0000000000..5d098e529e --- /dev/null +++ b/src/appleseed.studio/utility/gl.cpp @@ -0,0 +1,152 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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 "gl.h" + +// appleseed.studio headers. +#include "renderer/api/utility.h" + +// appleseed.qtcommon headers. +#include "utility/miscellaneous.h" + +// Qt headers. +#include +#include +#include + +using namespace appleseed::qtcommon; +using namespace std; +using namespace renderer; + +namespace appleseed { +namespace studio { + +const string shader_kind_to_string(const GLint shader_kind) +{ + switch (shader_kind) { + case GL_VERTEX_SHADER: + return "Vertex"; + case GL_FRAGMENT_SHADER: + return "Fragment"; + } + return "Unknown Kind"; +} + +void compile_shader( + QOpenGLFunctions_4_1_Core* f, + const GLuint shader, + const GLsizei count, + const GLchar** src_string, + const GLint* length) +{ + f->glShaderSource(shader, count, src_string, length); + f->glCompileShader(shader); + GLint success; + f->glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + + if (!success) + { + char info_log[1024]; + f->glGetShaderInfoLog(shader, 1024, NULL, info_log); + + GLint shader_kind; + f->glGetShaderiv(shader, GL_SHADER_TYPE, &shader_kind); + string shader_kind_string = shader_kind_to_string(shader_kind); + + RENDERER_LOG_ERROR("opengl: %s shader compilation failed:\n%s", shader_kind_string.c_str(), info_log); + } +} + +void link_shader_program( + QOpenGLFunctions_4_1_Core* f, + const GLuint program, + const GLuint vert, + const GLuint frag) +{ + f->glAttachShader(program, vert); + + if (frag != 0) + f->glAttachShader(program, frag); + + f->glLinkProgram(program); + + GLint success; + f->glGetProgramiv(program, GL_LINK_STATUS, &success); + + if (!success) + { + char info_log[1024]; + f->glGetProgramInfoLog(program, 1024, NULL, info_log); + RENDERER_LOG_ERROR("opengl: shader program linking failed:\n%s", info_log); + } +} + +void create_shader_program( + QOpenGLFunctions_4_1_Core* f, + GLuint& program, + const QByteArray* vert_source, + const QByteArray* frag_source) +{ + assert(vert_source != nullptr); + bool has_frag_shader = frag_source != nullptr; + + GLuint vert = f->glCreateShader(GL_VERTEX_SHADER); + GLuint frag = has_frag_shader ? f->glCreateShader(GL_FRAGMENT_SHADER) : 0; + + auto gl_vert_source = static_cast(vert_source->constData()); + auto gl_vert_source_length = static_cast(vert_source->size()); + + compile_shader(f, vert, 1, &gl_vert_source, &gl_vert_source_length); + + if (has_frag_shader) + { + auto gl_frag_source = static_cast(frag_source->constData()); + auto gl_frag_source_length = static_cast(frag_source->size()); + compile_shader(f, frag, 1, &gl_frag_source, &gl_frag_source_length); + } + + program = f->glCreateProgram(); + link_shader_program(f, program, vert, frag); + + f->glDeleteShader(vert); + if (has_frag_shader) + f->glDeleteShader(frag); +} + +QByteArray load_gl_shader(const QString& base_name) +{ + const QString resource_path(QString(":/shaders/%1").arg(base_name)); + + QFile file(resource_path); + file.open(QFile::ReadOnly); + + return file.readAll(); +} + +} // namespace studio +} // namespace appleseed diff --git a/src/appleseed.studio/utility/gl.h b/src/appleseed.studio/utility/gl.h new file mode 100644 index 0000000000..b63b4c583c --- /dev/null +++ b/src/appleseed.studio/utility/gl.h @@ -0,0 +1,75 @@ + +// +// This source file is part of appleseed. +// Visit https://appleseedhq.net/ for additional information and resources. +// +// This software is released under the MIT license. +// +// Copyright (c) 2019 Gray Olson, The appleseedhq Organization +// +// 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. +// + +#pragma once + +// Qt headers. +#include +#include + +// standard headers. +#include + +// Forward declarations. +class QByteArray; +class QString; + +namespace appleseed { +namespace studio { + +// Get a string from an OpenGL shader kind value. +const std::string shader_kind_to_string(const GLint shader_kind); + +// Compile a GL shader. +void compile_shader( + QOpenGLFunctions_4_1_Core* f, + const GLuint shader, + const GLsizei count, + const GLchar** src_string, + const GLint* length); + +// Link a GL shader program. +void link_shader_program( + QOpenGLFunctions_4_1_Core* f, + const GLuint program, + const GLuint vert, + const GLuint frag); + +// Create a GL shader program with a vertex and optional fragment shader. +void create_shader_program( + QOpenGLFunctions_4_1_Core* f, + GLuint& program, + const QByteArray* vert_source, + const QByteArray* frag_source); + +// Load a GLSL shader from file into a QByteArray. +QByteArray load_gl_shader(const QString& base_name); + +} // namespace studio +} // namespace appleseed + diff --git a/src/appleseed/renderer/kernel/lighting/directlightingintegrator.cpp b/src/appleseed/renderer/kernel/lighting/directlightingintegrator.cpp index 23a486935b..2b93e47adf 100644 --- a/src/appleseed/renderer/kernel/lighting/directlightingintegrator.cpp +++ b/src/appleseed/renderer/kernel/lighting/directlightingintegrator.cpp @@ -468,6 +468,7 @@ void DirectLightingIntegrator::add_emitting_shape_sample_contribution( light_path_stream->sampled_emitting_shape( *sample.m_shape, sample.m_point, + sample.m_geometric_normal, material_value.m_beauty, edf_value); } @@ -547,6 +548,7 @@ void DirectLightingIntegrator::add_non_physical_light_sample_contribution( light_path_stream->sampled_non_physical_light( *light, emission_position, + m_material_sampler.get_shading_point().get_geometric_normal(), material_value.m_beauty, light_value); } diff --git a/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp b/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp index 864ed35516..e2541be1eb 100644 --- a/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp +++ b/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp @@ -275,6 +275,10 @@ void LightPathRecorder::get_light_path_vertex( result.m_radiance[0] = source_vertex.m_radiance[0]; result.m_radiance[1] = source_vertex.m_radiance[1]; result.m_radiance[2] = source_vertex.m_radiance[2]; + + result.m_surface_normal[0] = source_vertex.m_surface_normal[0]; + result.m_surface_normal[1] = source_vertex.m_surface_normal[1]; + result.m_surface_normal[2] = source_vertex.m_surface_normal[2]; } bool LightPathRecorder::write(const char* filename) const diff --git a/src/appleseed/renderer/kernel/lighting/lightpathrecorder.h b/src/appleseed/renderer/kernel/lighting/lightpathrecorder.h index cebcebc3d9..93e094c774 100644 --- a/src/appleseed/renderer/kernel/lighting/lightpathrecorder.h +++ b/src/appleseed/renderer/kernel/lighting/lightpathrecorder.h @@ -68,6 +68,7 @@ struct LightPathVertex const Entity* m_entity; float m_position[3]; float m_radiance[3]; + float m_surface_normal[3]; }; diff --git a/src/appleseed/renderer/kernel/lighting/lightpathstream.cpp b/src/appleseed/renderer/kernel/lighting/lightpathstream.cpp index 128c3d3dcd..4cc112e3e9 100644 --- a/src/appleseed/renderer/kernel/lighting/lightpathstream.cpp +++ b/src/appleseed/renderer/kernel/lighting/lightpathstream.cpp @@ -77,7 +77,8 @@ void LightPathStream::clear() void LightPathStream::begin_path( const PixelContext& pixel_context, const Camera* camera, - const Vector3d& camera_vertex_position) + const Vector3d& camera_vertex_position, + const Vector3d& camera_vertex_normal) { assert(m_events.empty()); assert(m_hit_reflector_data.empty()); @@ -90,6 +91,7 @@ void LightPathStream::begin_path( m_camera = camera; m_camera_vertex_position = Vector3f(camera_vertex_position); + m_camera_vertex_normal = Vector3f(camera_vertex_normal); m_pixel_coords = pixel_context.get_pixel_coords(); m_sample_position = Vector2f(pixel_context.get_sample_position()); } @@ -107,6 +109,7 @@ void LightPathStream::hit_reflector(const PathVertex& vertex) HitReflectorData data; data.m_object_instance = &vertex.m_shading_point->get_object_instance(); data.m_vertex_position = Vector3f(vertex.get_point()); + data.m_surface_normal = Vector3f(vertex.get_geometric_normal()); data.m_path_throughput = vertex.m_throughput.to_rgb(g_std_lighting_conditions); m_hit_reflector_data.push_back(data); } @@ -126,6 +129,7 @@ void LightPathStream::hit_emitter( HitEmitterData data; data.m_object_instance = &vertex.m_shading_point->get_object_instance(); data.m_vertex_position = Vector3f(vertex.get_point()); + data.m_surface_normal = Vector3f(vertex.get_geometric_normal()); data.m_path_throughput = vertex.m_throughput.to_rgb(g_std_lighting_conditions); data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions); m_hit_emitter_data.push_back(data); @@ -134,6 +138,7 @@ void LightPathStream::hit_emitter( void LightPathStream::sampled_emitting_shape( const EmittingShape& shape, const Vector3d& emission_position, + const Vector3d& emission_normal, const Spectrum& material_value, const Spectrum& emitted_radiance) { @@ -147,6 +152,7 @@ void LightPathStream::sampled_emitting_shape( shape.get_assembly_instance()->get_assembly().object_instances().get_by_index( shape.get_object_instance_index()); data.m_vertex_position = Vector3f(emission_position); + data.m_surface_normal = Vector3f(emission_normal); data.m_material_value = material_value.to_rgb(g_std_lighting_conditions); data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions); m_sampled_emitter_data.push_back(data); @@ -155,6 +161,7 @@ void LightPathStream::sampled_emitting_shape( void LightPathStream::sampled_non_physical_light( const Light& light, const Vector3d& emission_position, + const Vector3d& emission_normal, const Spectrum& material_value, const Spectrum& emitted_radiance) { @@ -166,6 +173,7 @@ void LightPathStream::sampled_non_physical_light( SampledEmitterData data; data.m_entity = &light; data.m_vertex_position = Vector3f(emission_position); + data.m_surface_normal = Vector3f(emission_normal); data.m_material_value = material_value.to_rgb(g_std_lighting_conditions); data.m_emitted_radiance = emitted_radiance.to_rgb(g_std_lighting_conditions); m_sampled_emitter_data.push_back(data); @@ -244,6 +252,7 @@ void LightPathStream::create_path_from_hit_emitter(const size_t emitter_event_in StoredPathVertex emitter_vertex; emitter_vertex.m_entity = hit_emitter_data.m_object_instance; emitter_vertex.m_position = hit_emitter_data.m_vertex_position; + emitter_vertex.m_surface_normal = hit_emitter_data.m_surface_normal; emitter_vertex.m_radiance = hit_emitter_data.m_emitted_radiance; m_vertices.push_back(emitter_vertex); @@ -264,6 +273,7 @@ void LightPathStream::create_path_from_hit_emitter(const size_t emitter_event_in StoredPathVertex reflector_vertex; reflector_vertex.m_entity = event_data.m_object_instance; reflector_vertex.m_position = event_data.m_vertex_position; + reflector_vertex.m_surface_normal = event_data.m_surface_normal; reflector_vertex.m_radiance = current_radiance; m_vertices.push_back(reflector_vertex); @@ -288,6 +298,7 @@ void LightPathStream::create_path_from_hit_emitter(const size_t emitter_event_in StoredPathVertex camera_vertex; camera_vertex.m_entity = m_camera; camera_vertex.m_position = m_camera_vertex_position; + camera_vertex.m_surface_normal = m_camera_vertex_normal; camera_vertex.m_radiance = current_radiance; m_vertices.push_back(camera_vertex); @@ -319,6 +330,7 @@ void LightPathStream::create_path_from_sampled_emitter(const size_t emitter_even StoredPathVertex emitter_vertex; emitter_vertex.m_entity = sampled_emitter_data.m_entity; emitter_vertex.m_position = sampled_emitter_data.m_vertex_position; + emitter_vertex.m_surface_normal = sampled_emitter_data.m_surface_normal; emitter_vertex.m_radiance = sampled_emitter_data.m_emitted_radiance; m_vertices.push_back(emitter_vertex); @@ -339,6 +351,7 @@ void LightPathStream::create_path_from_sampled_emitter(const size_t emitter_even StoredPathVertex reflector_vertex; reflector_vertex.m_entity = event_data.m_object_instance; reflector_vertex.m_position = event_data.m_vertex_position; + reflector_vertex.m_surface_normal = event_data.m_surface_normal; reflector_vertex.m_radiance = current_radiance; m_vertices.push_back(reflector_vertex); @@ -363,6 +376,7 @@ void LightPathStream::create_path_from_sampled_emitter(const size_t emitter_even StoredPathVertex camera_vertex; camera_vertex.m_entity = m_camera; camera_vertex.m_position = m_camera_vertex_position; + camera_vertex.m_surface_normal = m_camera_vertex_normal; camera_vertex.m_radiance = current_radiance; m_vertices.push_back(camera_vertex); @@ -394,6 +408,7 @@ void LightPathStream::create_path_from_sampled_environment(const size_t env_even StoredPathVertex emitter_vertex; emitter_vertex.m_entity = sampled_env_data.m_environment_edf; emitter_vertex.m_position = last_reflector_data.m_vertex_position + m_scene_diameter * sampled_env_data.m_emission_direction; + emitter_vertex.m_surface_normal = -sampled_env_data.m_emission_direction; emitter_vertex.m_radiance = sampled_env_data.m_emitted_radiance; m_vertices.push_back(emitter_vertex); @@ -414,6 +429,7 @@ void LightPathStream::create_path_from_sampled_environment(const size_t env_even StoredPathVertex reflector_vertex; reflector_vertex.m_entity = event_data.m_object_instance; reflector_vertex.m_position = event_data.m_vertex_position; + reflector_vertex.m_surface_normal = event_data.m_surface_normal; reflector_vertex.m_radiance = current_radiance; m_vertices.push_back(reflector_vertex); @@ -438,6 +454,7 @@ void LightPathStream::create_path_from_sampled_environment(const size_t env_even StoredPathVertex camera_vertex; camera_vertex.m_entity = m_camera; camera_vertex.m_position = m_camera_vertex_position; + camera_vertex.m_surface_normal = m_camera_vertex_normal; camera_vertex.m_radiance = current_radiance; m_vertices.push_back(camera_vertex); diff --git a/src/appleseed/renderer/kernel/lighting/lightpathstream.h b/src/appleseed/renderer/kernel/lighting/lightpathstream.h index 8c008e3b20..9f4c33ffb1 100644 --- a/src/appleseed/renderer/kernel/lighting/lightpathstream.h +++ b/src/appleseed/renderer/kernel/lighting/lightpathstream.h @@ -67,7 +67,8 @@ class LightPathStream void begin_path( const PixelContext& pixel_context, const Camera* camera, - const foundation::Vector3d& camera_vertex_position); + const foundation::Vector3d& camera_vertex_position, + const foundation::Vector3d& camera_vertex_normal); void hit_reflector( const PathVertex& vertex); @@ -79,12 +80,14 @@ class LightPathStream void sampled_emitting_shape( const EmittingShape& shape, const foundation::Vector3d& emission_position, + const foundation::Vector3d& emission_normal, const Spectrum& material_value, const Spectrum& emitted_radiance); void sampled_non_physical_light( const Light& light, const foundation::Vector3d& emission_position, + const foundation::Vector3d& emission_normal, const Spectrum& material_value, const Spectrum& emitted_radiance); @@ -117,6 +120,7 @@ class LightPathStream { const ObjectInstance* m_object_instance; // object instance that was hit foundation::Vector3f m_vertex_position; // world space position of the hit point on the reflector + foundation::Vector3f m_surface_normal; // world space normal of the surface of the reflector foundation::Color3f m_path_throughput; // cumulative path throughput up to but excluding this vertex, in reverse order (i.e. in the order from camera to light source) }; @@ -130,6 +134,7 @@ class LightPathStream { const Entity* m_entity; // object instance or non-physical light that was sampled foundation::Vector3f m_vertex_position; // world space position of the emitting point on the emitter + foundation::Vector3f m_surface_normal; // world space normal of the surface of the emitter foundation::Color3f m_material_value; // BSDF value at the previous vertex foundation::Color3f m_emitted_radiance; // emitted radiance in W.sr^-1.m^-2 }; @@ -157,6 +162,7 @@ class LightPathStream const Entity* m_entity; // object instance or non-physical light foundation::Vector3f m_position; // world space position of this vertex foundation::Color3f m_radiance; // radiance arriving at this vertex, in W.sr^-1.m^-2 + foundation::Vector3f m_surface_normal; }; // Scene. @@ -168,6 +174,7 @@ class LightPathStream foundation::Vector2i m_pixel_coords; foundation::Vector2f m_sample_position; foundation::Vector3f m_camera_vertex_position; + foundation::Vector3f m_camera_vertex_normal; // Scattering events (transient). std::vector m_events; diff --git a/src/appleseed/renderer/kernel/lighting/pt/ptlightingengine.cpp b/src/appleseed/renderer/kernel/lighting/pt/ptlightingengine.cpp index bb217ec5d7..6f87dc8b88 100644 --- a/src/appleseed/renderer/kernel/lighting/pt/ptlightingengine.cpp +++ b/src/appleseed/renderer/kernel/lighting/pt/ptlightingengine.cpp @@ -168,7 +168,8 @@ namespace m_light_path_stream->begin_path( pixel_context, shading_point.get_scene().get_render_data().m_active_camera, - shading_point.get_ray().m_org); + shading_point.get_ray().m_org, + shading_point.get_ray().m_dir); } if (m_params.m_next_event_estimation) diff --git a/src/appleseed/renderer/modeling/camera/orthographiccamera.cpp b/src/appleseed/renderer/modeling/camera/orthographiccamera.cpp index f5f3eb207a..519f02bea3 100644 --- a/src/appleseed/renderer/modeling/camera/orthographiccamera.cpp +++ b/src/appleseed/renderer/modeling/camera/orthographiccamera.cpp @@ -80,6 +80,15 @@ namespace const ParamArray& params) : Camera(name, params) { + // Extract the film dimensions from the camera parameters. + m_film_dimensions = extract_film_dimensions(); + + // Extract the abscissa of the near plane from the camera parameters. + m_near_z = extract_near_z(); + + // Precompute reciprocals of film dimensions. + m_rcp_film_width = 1.0 / m_film_dimensions[0]; + m_rcp_film_height = 1.0 / m_film_dimensions[1]; } void release() override @@ -125,19 +134,9 @@ namespace if (!Camera::on_render_begin(project, parent, recorder, abort_switch)) return false; - // Extract the film dimensions from the camera parameters. - m_film_dimensions = extract_film_dimensions(); - - // Extract the abscissa of the near plane from the camera parameters. - m_near_z = extract_near_z(); - // Retrieve the scene diameter that will be used to position the camera. m_safe_scene_diameter = project.get_scene()->get_render_data().m_safe_diameter; - // Precompute reciprocals of film dimensions. - m_rcp_film_width = 1.0 / m_film_dimensions[0]; - m_rcp_film_height = 1.0 / m_film_dimensions[1]; - // Precompute pixel area. const size_t pixel_count = project.get_frame()->image().properties().m_pixel_count; m_rcp_pixel_area = static_cast(pixel_count / (m_film_dimensions[0] * m_film_dimensions[1])); diff --git a/src/appleseed/renderer/modeling/camera/perspectivecamera.cpp b/src/appleseed/renderer/modeling/camera/perspectivecamera.cpp index 769065d018..ce96322154 100644 --- a/src/appleseed/renderer/modeling/camera/perspectivecamera.cpp +++ b/src/appleseed/renderer/modeling/camera/perspectivecamera.cpp @@ -54,6 +54,21 @@ namespace renderer PerspectiveCamera::PerspectiveCamera(const char* name, const ParamArray& params) : Camera(name, params) { + // Extract the film dimensions from the camera parameters. + m_film_dimensions = extract_film_dimensions(); + + // Extract the focal length from the camera parameters. + m_focal_length = extract_focal_length(m_film_dimensions[0]); + + // Extract the abscissa of the near plane from the camera parameters. + m_near_z = extract_near_z(); + + // Extract the shift from the camera parameters. + m_shift = extract_shift(); + + // Precompute reciprocals of film dimensions. + m_rcp_film_width = 1.0 / m_film_dimensions[0]; + m_rcp_film_height = 1.0 / m_film_dimensions[1]; } const foundation::Vector2d& PerspectiveCamera::get_film_dimensions() const @@ -80,22 +95,6 @@ bool PerspectiveCamera::on_render_begin( if (!Camera::on_render_begin(project, parent, recorder, abort_switch)) return false; - // Extract the film dimensions from the camera parameters. - m_film_dimensions = extract_film_dimensions(); - - // Extract the focal length from the camera parameters. - m_focal_length = extract_focal_length(m_film_dimensions[0]); - - // Extract the abscissa of the near plane from the camera parameters. - m_near_z = extract_near_z(); - - // Extract the shift from the camera parameters. - m_shift = extract_shift(); - - // Precompute reciprocals of film dimensions. - m_rcp_film_width = 1.0 / m_film_dimensions[0]; - m_rcp_film_height = 1.0 / m_film_dimensions[1]; - // Precompute pixel area. const size_t pixel_count = project.get_frame()->image().properties().m_pixel_count; m_pixel_area = m_film_dimensions[0] * m_film_dimensions[1] / pixel_count; From 9388fe32ca24d3d36dc7024dac1663242f9fde3d Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:15:35 +0100 Subject: [PATCH 02/34] explain lightpathstream --- src/appleseed/renderer/kernel/lighting/lightpathstream.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/appleseed/renderer/kernel/lighting/lightpathstream.h b/src/appleseed/renderer/kernel/lighting/lightpathstream.h index 9f4c33ffb1..e838880243 100644 --- a/src/appleseed/renderer/kernel/lighting/lightpathstream.h +++ b/src/appleseed/renderer/kernel/lighting/lightpathstream.h @@ -162,7 +162,7 @@ class LightPathStream const Entity* m_entity; // object instance or non-physical light foundation::Vector3f m_position; // world space position of this vertex foundation::Color3f m_radiance; // radiance arriving at this vertex, in W.sr^-1.m^-2 - foundation::Vector3f m_surface_normal; + foundation::Vector3f m_surface_normal; // world space normal of the surface at this vertex }; // Scene. From 7414b981d647a6ce2e71a06682f933e6fd04f6ed Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:17:09 +0100 Subject: [PATCH 03/34] Reorder files in cmake --- src/appleseed.studio/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/appleseed.studio/CMakeLists.txt b/src/appleseed.studio/CMakeLists.txt index 644b9d9402..36a80abe27 100644 --- a/src/appleseed.studio/CMakeLists.txt +++ b/src/appleseed.studio/CMakeLists.txt @@ -284,12 +284,12 @@ set (mainwindow_rendering_sources mainwindow/rendering/renderlayer.h mainwindow/rendering/scenepickinghandler.cpp mainwindow/rendering/scenepickinghandler.h + mainwindow/rendering/viewportcanvas.cpp + mainwindow/rendering/viewportcanvas.h mainwindow/rendering/viewportregionselectionhandler.cpp mainwindow/rendering/viewportregionselectionhandler.h mainwindow/rendering/viewporttab.cpp mainwindow/rendering/viewporttab.h - mainwindow/rendering/viewportcanvas.cpp - mainwindow/rendering/viewportcanvas.h ) list (APPEND appleseed.studio_sources ${mainwindow_rendering_sources} From 80efbd70270f4b20eb5e125333e44134c478adc9 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:25:08 +0100 Subject: [PATCH 04/34] don't use reference to return int in create_shader_program --- .../mainwindow/rendering/glscenelayer.cpp | 9 +++----- .../mainwindow/rendering/lightpathslayer.cpp | 3 +-- .../mainwindow/rendering/renderlayer.cpp | 3 +-- .../mainwindow/rendering/viewportcanvas.cpp | 3 +-- src/appleseed.studio/utility/gl.cpp | 22 +++++++++---------- src/appleseed.studio/utility/gl.h | 15 ++++++------- 6 files changed, 24 insertions(+), 31 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp index fe8b6ec4e0..f9ae0ae50f 100644 --- a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp @@ -383,20 +383,17 @@ void GLSceneLayer::init_gl(QSurfaceFormat format) auto vertex_shader = load_gl_shader("scene.vert"); auto fragment_shader = load_gl_shader("scene.frag"); - create_shader_program( + m_scene_shader_program = create_shader_program( m_gl, - m_scene_shader_program, &vertex_shader, &fragment_shader); m_scene_view_mat_location = m_gl->glGetUniformLocation(m_scene_shader_program, "u_view"); m_scene_proj_mat_location = m_gl->glGetUniformLocation(m_scene_shader_program, "u_proj"); - create_shader_program( + m_depthonly_shader_program = create_shader_program( m_gl, - m_depthonly_shader_program, - &vertex_shader, - nullptr); + &vertex_shader); m_depthonly_view_mat_location = m_gl->glGetUniformLocation(m_depthonly_shader_program, "u_view"); m_depthonly_proj_mat_location = m_gl->glGetUniformLocation(m_depthonly_shader_program, "u_proj"); diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp index 163610385e..b19b94c0f4 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp @@ -294,9 +294,8 @@ void LightPathsLayer::init_gl(QSurfaceFormat format) auto vertex_shader = load_gl_shader("lightpaths.vert"); auto fragment_shader = load_gl_shader("lightpaths.frag"); - create_shader_program( + m_shader_program = create_shader_program( m_gl, - m_shader_program, &vertex_shader, &fragment_shader); diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp index 7a40b6fb3e..f712162324 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp @@ -127,9 +127,8 @@ void RenderLayer::init_gl(QSurfaceFormat format) auto vertex_shader = load_gl_shader("fullscreen_tri.vert"); auto fragment_shader = load_gl_shader("final_render.frag"); - create_shader_program( + m_shader_program = create_shader_program( m_gl, - m_shader_program, &vertex_shader, &fragment_shader); diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index f15e604300..abe0de4f85 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -208,9 +208,8 @@ void ViewportCanvas::initializeGL() { auto vertex_shader = load_gl_shader("fullscreen_tri.vert"); auto fragment_shader = load_gl_shader("oit_resolve.frag"); - create_shader_program( + m_resolve_program = create_shader_program( m_gl, - m_resolve_program, &vertex_shader, &fragment_shader); diff --git a/src/appleseed.studio/utility/gl.cpp b/src/appleseed.studio/utility/gl.cpp index 5d098e529e..48d6b8ba3f 100644 --- a/src/appleseed.studio/utility/gl.cpp +++ b/src/appleseed.studio/utility/gl.cpp @@ -48,13 +48,12 @@ namespace studio { const string shader_kind_to_string(const GLint shader_kind) { - switch (shader_kind) { - case GL_VERTEX_SHADER: - return "Vertex"; - case GL_FRAGMENT_SHADER: - return "Fragment"; + switch (shader_kind) + { + case GL_VERTEX_SHADER: return "Vertex"; + case GL_FRAGMENT_SHADER: return "Fragment"; + default: return "Unknown Kind"; } - return "Unknown Kind"; } void compile_shader( @@ -106,14 +105,13 @@ void link_shader_program( } } -void create_shader_program( +GLuint create_shader_program( QOpenGLFunctions_4_1_Core* f, - GLuint& program, const QByteArray* vert_source, const QByteArray* frag_source) { - assert(vert_source != nullptr); - bool has_frag_shader = frag_source != nullptr; + assert(vert_source != 0); + const bool has_frag_shader = frag_source != 0; GLuint vert = f->glCreateShader(GL_VERTEX_SHADER); GLuint frag = has_frag_shader ? f->glCreateShader(GL_FRAGMENT_SHADER) : 0; @@ -130,12 +128,14 @@ void create_shader_program( compile_shader(f, frag, 1, &gl_frag_source, &gl_frag_source_length); } - program = f->glCreateProgram(); + const GLuint program = f->glCreateProgram(); link_shader_program(f, program, vert, frag); f->glDeleteShader(vert); if (has_frag_shader) f->glDeleteShader(frag); + + return program; } QByteArray load_gl_shader(const QString& base_name) diff --git a/src/appleseed.studio/utility/gl.h b/src/appleseed.studio/utility/gl.h index b63b4c583c..12b9734623 100644 --- a/src/appleseed.studio/utility/gl.h +++ b/src/appleseed.studio/utility/gl.h @@ -32,7 +32,7 @@ #include #include -// standard headers. +// Standard headers. #include // Forward declarations. @@ -45,7 +45,7 @@ namespace studio { // Get a string from an OpenGL shader kind value. const std::string shader_kind_to_string(const GLint shader_kind); -// Compile a GL shader. +// Compile an OpenGL shader. void compile_shader( QOpenGLFunctions_4_1_Core* f, const GLuint shader, @@ -53,19 +53,18 @@ void compile_shader( const GLchar** src_string, const GLint* length); -// Link a GL shader program. +// Linke an OpenlGL shader program with a vertex and optional fragment shader object. void link_shader_program( QOpenGLFunctions_4_1_Core* f, const GLuint program, const GLuint vert, - const GLuint frag); + const GLuint frag = 0); -// Create a GL shader program with a vertex and optional fragment shader. -void create_shader_program( +// Create an OpenlGL shader program with a vertex and optional fragment shader source code. +GLuint create_shader_program( QOpenGLFunctions_4_1_Core* f, - GLuint& program, const QByteArray* vert_source, - const QByteArray* frag_source); + const QByteArray* frag_source = 0); // Load a GLSL shader from file into a QByteArray. QByteArray load_gl_shader(const QString& base_name); From 1543c81e3f652912aded99a0e8520d4e55681a80 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:32:33 +0100 Subject: [PATCH 05/34] consts where needed --- src/appleseed.studio/utility/gl.cpp | 36 ++++++++++++++++++++--------- src/appleseed.studio/utility/gl.h | 2 +- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/appleseed.studio/utility/gl.cpp b/src/appleseed.studio/utility/gl.cpp index 48d6b8ba3f..c79c77086d 100644 --- a/src/appleseed.studio/utility/gl.cpp +++ b/src/appleseed.studio/utility/gl.cpp @@ -26,6 +26,7 @@ // THE SOFTWARE. // +// Interface header. #include "gl.h" // appleseed.studio headers. @@ -40,13 +41,12 @@ #include using namespace appleseed::qtcommon; -using namespace std; using namespace renderer; namespace appleseed { namespace studio { -const string shader_kind_to_string(const GLint shader_kind) +const std::string shader_kind_to_string(const GLint shader_kind) { switch (shader_kind) { @@ -65,6 +65,8 @@ void compile_shader( { f->glShaderSource(shader, count, src_string, length); f->glCompileShader(shader); + + // Check compilation status. GLint success; f->glGetShaderiv(shader, GL_COMPILE_STATUS, &success); @@ -75,9 +77,13 @@ void compile_shader( GLint shader_kind; f->glGetShaderiv(shader, GL_SHADER_TYPE, &shader_kind); - string shader_kind_string = shader_kind_to_string(shader_kind); - RENDERER_LOG_ERROR("opengl: %s shader compilation failed:\n%s", shader_kind_string.c_str(), info_log); + const std::string shader_kind_string = shader_kind_to_string(shader_kind); + + RENDERER_LOG_ERROR( + "opengl: %s shader compilation failed:\n%s", + shader_kind_string.c_str(), + info_log); } } @@ -94,6 +100,7 @@ void link_shader_program( f->glLinkProgram(program); + // Check linking status. GLint success; f->glGetProgramiv(program, GL_LINK_STATUS, &success); @@ -101,7 +108,10 @@ void link_shader_program( { char info_log[1024]; f->glGetProgramInfoLog(program, 1024, NULL, info_log); - RENDERER_LOG_ERROR("opengl: shader program linking failed:\n%s", info_log); + + RENDERER_LOG_ERROR( + "opengl: shader program linking failed:\n%s", + info_log); } } @@ -113,25 +123,29 @@ GLuint create_shader_program( assert(vert_source != 0); const bool has_frag_shader = frag_source != 0; - GLuint vert = f->glCreateShader(GL_VERTEX_SHADER); - GLuint frag = has_frag_shader ? f->glCreateShader(GL_FRAGMENT_SHADER) : 0; + const GLuint vert = f->glCreateShader(GL_VERTEX_SHADER); + const GLuint frag = has_frag_shader ? f->glCreateShader(GL_FRAGMENT_SHADER) : 0; - auto gl_vert_source = static_cast(vert_source->constData()); - auto gl_vert_source_length = static_cast(vert_source->size()); + // Compile the vertex shader. + const GLchar* gl_vert_source = static_cast(vert_source->constData()); + const GLint gl_vert_source_length = static_cast(vert_source->size()); compile_shader(f, vert, 1, &gl_vert_source, &gl_vert_source_length); + // Compile the fragment shader. if (has_frag_shader) { - auto gl_frag_source = static_cast(frag_source->constData()); - auto gl_frag_source_length = static_cast(frag_source->size()); + const GLchar* gl_frag_source = static_cast(frag_source->constData()); + const GLint gl_frag_source_length = static_cast(frag_source->size()); compile_shader(f, frag, 1, &gl_frag_source, &gl_frag_source_length); } + // Compile both shaders together. const GLuint program = f->glCreateProgram(); link_shader_program(f, program, vert, frag); f->glDeleteShader(vert); + if (has_frag_shader) f->glDeleteShader(frag); diff --git a/src/appleseed.studio/utility/gl.h b/src/appleseed.studio/utility/gl.h index 12b9734623..fd74cbda1d 100644 --- a/src/appleseed.studio/utility/gl.h +++ b/src/appleseed.studio/utility/gl.h @@ -29,8 +29,8 @@ #pragma once // Qt headers. -#include #include +#include // Standard headers. #include From 7fe56bec35b7ce2f0a4d1373a77827e7324cd7b5 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:35:32 +0100 Subject: [PATCH 06/34] Don't expose to public unused methods --- src/appleseed.studio/utility/gl.cpp | 111 +++++++++++++++------------- src/appleseed.studio/utility/gl.h | 22 ------ 2 files changed, 60 insertions(+), 73 deletions(-) diff --git a/src/appleseed.studio/utility/gl.cpp b/src/appleseed.studio/utility/gl.cpp index c79c77086d..abfcaddfe5 100644 --- a/src/appleseed.studio/utility/gl.cpp +++ b/src/appleseed.studio/utility/gl.cpp @@ -40,78 +40,87 @@ #include #include +// Standard headers. +#include + using namespace appleseed::qtcommon; using namespace renderer; namespace appleseed { namespace studio { -const std::string shader_kind_to_string(const GLint shader_kind) -{ - switch (shader_kind) +namespace +{ + // Get a string from an OpenGL shader kind value. + const std::string shader_kind_to_string(const GLint shader_kind) { - case GL_VERTEX_SHADER: return "Vertex"; - case GL_FRAGMENT_SHADER: return "Fragment"; - default: return "Unknown Kind"; + switch (shader_kind) + { + case GL_VERTEX_SHADER: return "Vertex"; + case GL_FRAGMENT_SHADER: return "Fragment"; + default: return "Unknown Kind"; + } } -} -void compile_shader( - QOpenGLFunctions_4_1_Core* f, - const GLuint shader, - const GLsizei count, - const GLchar** src_string, - const GLint* length) -{ - f->glShaderSource(shader, count, src_string, length); - f->glCompileShader(shader); + // Compile an OpenGL shader. + void compile_shader( + QOpenGLFunctions_4_1_Core* f, + const GLuint shader, + const GLsizei count, + const GLchar** src_string, + const GLint* length) + { + f->glShaderSource(shader, count, src_string, length); + f->glCompileShader(shader); - // Check compilation status. - GLint success; - f->glGetShaderiv(shader, GL_COMPILE_STATUS, &success); + // Check compilation status. + GLint success; + f->glGetShaderiv(shader, GL_COMPILE_STATUS, &success); - if (!success) - { - char info_log[1024]; - f->glGetShaderInfoLog(shader, 1024, NULL, info_log); + if (!success) + { + char info_log[1024]; + f->glGetShaderInfoLog(shader, 1024, NULL, info_log); - GLint shader_kind; - f->glGetShaderiv(shader, GL_SHADER_TYPE, &shader_kind); + GLint shader_kind; + f->glGetShaderiv(shader, GL_SHADER_TYPE, &shader_kind); - const std::string shader_kind_string = shader_kind_to_string(shader_kind); + const std::string shader_kind_string = shader_kind_to_string(shader_kind); - RENDERER_LOG_ERROR( - "opengl: %s shader compilation failed:\n%s", - shader_kind_string.c_str(), - info_log); + RENDERER_LOG_ERROR( + "opengl: %s shader compilation failed:\n%s", + shader_kind_string.c_str(), + info_log); + } } -} -void link_shader_program( - QOpenGLFunctions_4_1_Core* f, - const GLuint program, - const GLuint vert, - const GLuint frag) -{ - f->glAttachShader(program, vert); + // Link an OpenlGL shader program with a vertex and optional fragment shader object. + void link_shader_program( + QOpenGLFunctions_4_1_Core* f, + const GLuint program, + const GLuint vert, + const GLuint frag) + { + f->glAttachShader(program, vert); - if (frag != 0) - f->glAttachShader(program, frag); + if (frag != 0) + f->glAttachShader(program, frag); - f->glLinkProgram(program); + f->glLinkProgram(program); - // Check linking status. - GLint success; - f->glGetProgramiv(program, GL_LINK_STATUS, &success); + // Check linking status. + GLint success; + f->glGetProgramiv(program, GL_LINK_STATUS, &success); - if (!success) - { - char info_log[1024]; - f->glGetProgramInfoLog(program, 1024, NULL, info_log); + if (!success) + { + char info_log[1024]; + f->glGetProgramInfoLog(program, 1024, NULL, info_log); - RENDERER_LOG_ERROR( - "opengl: shader program linking failed:\n%s", - info_log); + RENDERER_LOG_ERROR( + "opengl: shader program linking failed:\n%s", + info_log); + } } } diff --git a/src/appleseed.studio/utility/gl.h b/src/appleseed.studio/utility/gl.h index fd74cbda1d..e04fa9c5b7 100644 --- a/src/appleseed.studio/utility/gl.h +++ b/src/appleseed.studio/utility/gl.h @@ -30,10 +30,6 @@ // Qt headers. #include -#include - -// Standard headers. -#include // Forward declarations. class QByteArray; @@ -42,24 +38,6 @@ class QString; namespace appleseed { namespace studio { -// Get a string from an OpenGL shader kind value. -const std::string shader_kind_to_string(const GLint shader_kind); - -// Compile an OpenGL shader. -void compile_shader( - QOpenGLFunctions_4_1_Core* f, - const GLuint shader, - const GLsizei count, - const GLchar** src_string, - const GLint* length); - -// Linke an OpenlGL shader program with a vertex and optional fragment shader object. -void link_shader_program( - QOpenGLFunctions_4_1_Core* f, - const GLuint program, - const GLuint vert, - const GLuint frag = 0); - // Create an OpenlGL shader program with a vertex and optional fragment shader source code. GLuint create_shader_program( QOpenGLFunctions_4_1_Core* f, From a4ffa91e2b3dffbd725ad85eef5b2e50259da61c Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:36:56 +0100 Subject: [PATCH 07/34] Update opengl shader version number --- src/appleseed.studio/resources/shaders/final_render.frag | 4 ++-- src/appleseed.studio/resources/shaders/fullscreen_tri.vert | 6 +++--- src/appleseed.studio/resources/shaders/oit_resolve.frag | 4 ++-- src/appleseed.studio/resources/shaders/scene.frag | 2 +- src/appleseed.studio/resources/shaders/scene.vert | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/appleseed.studio/resources/shaders/final_render.frag b/src/appleseed.studio/resources/shaders/final_render.frag index 6f9eadf6d7..d2cace5378 100644 --- a/src/appleseed.studio/resources/shaders/final_render.frag +++ b/src/appleseed.studio/resources/shaders/final_render.frag @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 410 +#version 420 in vec2 f_uv; @@ -36,6 +36,6 @@ out vec4 Target0; void main() { vec3 col = texture(u_render_tex, f_uv, 0).rgb; - + Target0 = vec4(col * u_mult, 1.0); } diff --git a/src/appleseed.studio/resources/shaders/fullscreen_tri.vert b/src/appleseed.studio/resources/shaders/fullscreen_tri.vert index 7dbb4b2100..76ad297127 100644 --- a/src/appleseed.studio/resources/shaders/fullscreen_tri.vert +++ b/src/appleseed.studio/resources/shaders/fullscreen_tri.vert @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 410 +#version 420 const vec2 verts[3] = vec2[]( vec2(3.0, 1.0), @@ -41,8 +41,8 @@ const vec2 uvs[3] = vec2[]( out vec2 f_uv; -void main() +void main() { f_uv = uvs[gl_VertexID]; gl_Position = vec4(verts[gl_VertexID], 0.0, 1.0); -} \ No newline at end of file +} diff --git a/src/appleseed.studio/resources/shaders/oit_resolve.frag b/src/appleseed.studio/resources/shaders/oit_resolve.frag index 3a091797f8..9a9e576bf5 100644 --- a/src/appleseed.studio/resources/shaders/oit_resolve.frag +++ b/src/appleseed.studio/resources/shaders/oit_resolve.frag @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 410 +#version 420 uniform sampler2D u_accum_tex; uniform sampler2D u_revealage_tex; @@ -47,6 +47,6 @@ void main() { accum.rgb = vec3(accum.a); } vec3 averageColor = accum.rgb / max(accum.a, 0.00001); - + Target0 = vec4(averageColor, 1.0 - revealage); } diff --git a/src/appleseed.studio/resources/shaders/scene.frag b/src/appleseed.studio/resources/shaders/scene.frag index b7b67880db..edd7aaffca 100644 --- a/src/appleseed.studio/resources/shaders/scene.frag +++ b/src/appleseed.studio/resources/shaders/scene.frag @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 410 +#version 420 #extension GL_ARB_separate_shader_objects : enable layout(location = 0) in vec3 frag_pos; diff --git a/src/appleseed.studio/resources/shaders/scene.vert b/src/appleseed.studio/resources/shaders/scene.vert index f5731e6415..3f8185229f 100644 --- a/src/appleseed.studio/resources/shaders/scene.vert +++ b/src/appleseed.studio/resources/shaders/scene.vert @@ -25,7 +25,7 @@ // THE SOFTWARE. // -#version 410 +#version 420 #extension GL_ARB_separate_shader_objects : enable layout(location = 0) in vec3 a_pos; From 8347c10f22cc9c5e3c7319962a80cb163f55e6fc Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:39:24 +0100 Subject: [PATCH 08/34] Format shaders code correctly --- .../resources/shaders/final_render.frag | 5 +++-- .../resources/shaders/oit_resolve.frag | 21 ++++++++++++------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/appleseed.studio/resources/shaders/final_render.frag b/src/appleseed.studio/resources/shaders/final_render.frag index d2cace5378..a8bd7a4c2d 100644 --- a/src/appleseed.studio/resources/shaders/final_render.frag +++ b/src/appleseed.studio/resources/shaders/final_render.frag @@ -34,8 +34,9 @@ uniform float u_mult; out vec4 Target0; -void main() { - vec3 col = texture(u_render_tex, f_uv, 0).rgb; +void main() +{ + const vec3 col = texture(u_render_tex, f_uv, 0).rgb; Target0 = vec4(col * u_mult, 1.0); } diff --git a/src/appleseed.studio/resources/shaders/oit_resolve.frag b/src/appleseed.studio/resources/shaders/oit_resolve.frag index 9a9e576bf5..e752e91d47 100644 --- a/src/appleseed.studio/resources/shaders/oit_resolve.frag +++ b/src/appleseed.studio/resources/shaders/oit_resolve.frag @@ -32,21 +32,26 @@ uniform sampler2D u_revealage_tex; out vec4 Target0; -float max4(vec4 v) { - return max(max(max(v.x, v.y), v.z), v.w); +float max4(vec4 v) +{ + return max(max(max(v.x, v.y), v.z), v.w); } -void main() { - ivec2 coord = ivec2(gl_FragCoord.xy); +void main() +{ + const ivec2 coord = ivec2(gl_FragCoord.xy); - float revealage = texelFetch(u_revealage_tex, coord, 0).r; + const float revealage = texelFetch(u_revealage_tex, coord, 0).r; vec4 accum = texelFetch(u_accum_tex, coord, 0); - // Suppress overflow - if (isinf(max4(abs(accum)))) { + + // Suppress overflow. + if (isinf(max4(abs(accum)))) + { accum.rgb = vec3(accum.a); } - vec3 averageColor = accum.rgb / max(accum.a, 0.00001); + + const vec3 averageColor = accum.rgb / max(accum.a, 0.00001); Target0 = vec4(averageColor, 1.0 - revealage); } From 41c0bb3679df13891c7510561deeebdd11414fe7 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:42:32 +0100 Subject: [PATCH 09/34] Some renaming --- src/appleseed.studio/mainwindow/mainwindow.cpp | 8 ++++---- src/appleseed.studio/mainwindow/mainwindow.h | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index d687423fdd..656f0e7e99 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -733,7 +733,7 @@ void MainWindow::build_connections() connect( m_ui->tab_render_channels, &QTabWidget::currentChanged, - this, &MainWindow::slot_current_tab_changed); + this, &MainWindow::slot_current_viewport_tab_changed); } void MainWindow::update_workspace() @@ -957,7 +957,7 @@ void MainWindow::recreate_viewport_tabs() create_opengl_tab(); // Connect tabs together once they are all created. - connect_tabs(); + connect_viewport_tabs(); } } @@ -1071,7 +1071,7 @@ int MainWindow::add_viewport_tab(ViewportTab* viewport_tab, const QString& label return final_tab_index; } -void MainWindow::connect_tabs() +void MainWindow::connect_viewport_tabs() { assert(m_final_render_viewport_tab); assert(m_opengl_viewport_tab); @@ -2177,7 +2177,7 @@ void MainWindow::slot_check_fullscreen() m_action_fullscreen->setChecked(is_fullscreen); } -void MainWindow::slot_current_tab_changed(int index) +void MainWindow::slot_current_viewport_tab_changed(int index) { if (index == -1) return; diff --git a/src/appleseed.studio/mainwindow/mainwindow.h b/src/appleseed.studio/mainwindow/mainwindow.h index 4904c9f73c..7b65e21e54 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.h +++ b/src/appleseed.studio/mainwindow/mainwindow.h @@ -34,9 +34,9 @@ #include "debug/tests/testwindow.h" #include "mainwindow/applicationsettingswindow.h" #include "mainwindow/falsecolorswindow.h" -#include "mainwindow/rendering/renderingmanager.h" #include "mainwindow/rendering/finalrenderviewporttab.h" #include "mainwindow/rendering/openglviewporttab.h" +#include "mainwindow/rendering/renderingmanager.h" #include "mainwindow/rendering/viewporttab.h" #include "mainwindow/renderingsettingswindow.h" #include "mainwindow/statusbar.h" @@ -64,8 +64,8 @@ namespace OCIO = OCIO_NAMESPACE; // Forward declarations. namespace appleseed { namespace studio { class AttributeEditor; } } -namespace appleseed { namespace studio { class MinimizeButton; } } namespace appleseed { namespace studio { class LightPathsManager; } } +namespace appleseed { namespace studio { class MinimizeButton; } } namespace appleseed { namespace studio { class ProjectExplorer; } } namespace renderer { class Project; } namespace Ui { class MainWindow; } @@ -220,7 +220,7 @@ class MainWindow void create_final_render_tab(); void create_opengl_tab(); int add_viewport_tab(ViewportTab* viewport_tab, const QString& label); - void connect_tabs(); + void connect_viewport_tabs(); // Project file handling. renderer::ParamArray get_project_params(const char* configuration_name) const; @@ -313,7 +313,7 @@ class MainWindow // General UI actions. void slot_fullscreen(); void slot_check_fullscreen(); - void slot_current_tab_changed(int index); + void slot_current_viewport_tab_changed(int index); // Child windows. void slot_show_application_settings_window(); From 38ae1f6c18d37ff7292d4b28b749e9c0075fd1f9 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:47:01 +0100 Subject: [PATCH 10/34] Remove unused method --- src/appleseed.studio/mainwindow/mainwindow.cpp | 14 -------------- src/appleseed.studio/mainwindow/mainwindow.h | 1 - 2 files changed, 15 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index 656f0e7e99..cb63408b32 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -955,9 +955,6 @@ void MainWindow::recreate_viewport_tabs() create_final_render_tab(); create_opengl_tab(); - - // Connect tabs together once they are all created. - connect_viewport_tabs(); } } @@ -1071,17 +1068,6 @@ int MainWindow::add_viewport_tab(ViewportTab* viewport_tab, const QString& label return final_tab_index; } -void MainWindow::connect_viewport_tabs() -{ - assert(m_final_render_viewport_tab); - assert(m_opengl_viewport_tab); - - // Connect final render tab light paths selection to opengl tab. - //connect( - //m_final_render_viewport_tab, &FinalRenderViewportTab::signal_entity_picked, - //m_opengl_viewport_tab, &OpenGLViewportTab::slot_entity_picked); -} - ParamArray MainWindow::get_project_params(const char* configuration_name) const { ParamArray params; diff --git a/src/appleseed.studio/mainwindow/mainwindow.h b/src/appleseed.studio/mainwindow/mainwindow.h index 7b65e21e54..d4992cc73c 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.h +++ b/src/appleseed.studio/mainwindow/mainwindow.h @@ -220,7 +220,6 @@ class MainWindow void create_final_render_tab(); void create_opengl_tab(); int add_viewport_tab(ViewportTab* viewport_tab, const QString& label); - void connect_viewport_tabs(); // Project file handling. renderer::ParamArray get_project_params(const char* configuration_name) const; From 50b433ffb5a5267c5f40b8a96cdb9da3142c326f Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 11:56:23 +0100 Subject: [PATCH 11/34] no more key search in tabs --- src/appleseed.studio/mainwindow/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index cb63408b32..1b0e1d6528 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -2087,7 +2087,7 @@ void MainWindow::slot_save_render_widget_content() return; // todo: this is sketchy. The render tab should be retrieved from the signal. - m_viewport_tabs["Beauty"]->get_viewport_canvas()->get_render_layer()->capture().save(filepath); + m_final_render_viewport_tab->get_viewport_canvas()->get_render_layer()->capture().save(filepath); RENDERER_LOG_INFO("wrote image file %s.", filepath.toStdString().c_str()); } From 17143c42b92156754f10e0eb49ba8337c9fd92b3 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 12:10:20 +0100 Subject: [PATCH 12/34] format glscene layer correctly --- .../mainwindow/rendering/glscenelayer.cpp | 112 ++++++++++-------- .../mainwindow/rendering/glscenelayer.h | 15 +-- 2 files changed, 69 insertions(+), 58 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp index f9ae0ae50f..3f463bbc7d 100644 --- a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp @@ -53,10 +53,10 @@ #include "foundation/utility/api/apistring.h" // Qt headers. +#include #include -#include #include -#include +#include #include #include @@ -72,39 +72,39 @@ namespace studio { namespace { - // Number of floats per OpenGL vertex for a piece of scene geometry + // Number of floats per OpenGL vertex for a piece of scene geometry. // Vector3 position and Vector3 normal. - const size_t SceneVertexFloatStride = 6; + const std::size_t SceneVertexFloatStride = 6; // Number of bytes per OpenGL vertex for a piece of scene geometry. - const size_t SceneVertexByteStride = SceneVertexFloatStride * sizeof(float); + const std::size_t SceneVertexByteStride = SceneVertexFloatStride * sizeof(float); // Number of floats per triangle for a piece of scene geometry. - const size_t SceneTriangleFloatStride = SceneVertexFloatStride * 3; + const std::size_t SceneTriangleFloatStride = SceneVertexFloatStride * 3; - // Number of floats per OpenGL vertex for a light path + // Number of floats per OpenGL vertex for a light path. // Vector3 position and Vector3 color. - const size_t LightPathVertexFloatStride = 6; + const std::size_t LightPathVertexFloatStride = 6; // Number of bytes per OpenGL vertex for a piece of scene geometry. - const size_t LightPathVertexByteStride = LightPathVertexFloatStride * sizeof(float); + const std::size_t LightPathVertexByteStride = LightPathVertexFloatStride * sizeof(float); // Number of floats per line for a light path. - const size_t LightPathVertexLineFloatStride = LightPathVertexFloatStride * 2; + const std::size_t LightPathVertexLineFloatStride = LightPathVertexFloatStride * 2; // Number of floats per OpenGL transform matrix. - const size_t TransformFloatStride = 16; + const std::size_t TransformFloatStride = 16; // Number of bytes per OpenGL transform matrix. - const size_t TransformByteStride = TransformFloatStride * sizeof(float); + const std::size_t TransformByteStride = TransformFloatStride * sizeof(float); struct OpenGLRasterizer : public ObjectRasterizer { std::vector m_buffer; - size_t m_prim_count; + std::size_t m_prim_count; - void begin_object(const size_t triangle_count_hint) override + void begin_object(const std::size_t triangle_count_hint) override { m_buffer.clear(); m_buffer.reserve(triangle_count_hint * SceneTriangleFloatStride); @@ -126,6 +126,7 @@ namespace static_cast(triangle.m_v2[0]), static_cast(triangle.m_v2[1]), static_cast(triangle.m_v2[2]), static_cast(triangle.m_n2[0]), static_cast(triangle.m_n2[1]), static_cast(triangle.m_n2[2]), }; + m_buffer.reserve(m_buffer.size() + SceneTriangleFloatStride); m_buffer.insert(m_buffer.end(), temp_store, temp_store + SceneTriangleFloatStride); m_prim_count++; @@ -166,15 +167,17 @@ void GLSceneLayer::set_transform(const Transformd& transform) void GLSceneLayer::slot_synchronize_camera() { m_camera.transform_sequence().clear(); - m_camera.transform_sequence().set_transform(0.0f, - Transformd::from_local_to_parent(inverse(m_camera_matrix))); + m_camera.transform_sequence() + .set_transform( + 0.0f, + Transformd::from_local_to_parent(inverse(m_camera_matrix))); } void GLSceneLayer::load_object_instance( const ObjectInstance& object_instance, const Matrix4f& assembly_transform_matrix) { - Object* object = object_instance.find_object(); + const Object* object = object_instance.find_object(); // This would already be logged in GLSceneLayer::load_scene_data if (object == nullptr) @@ -184,17 +187,18 @@ void GLSceneLayer::load_object_instance( const Matrix4f& object_transform_matrix(transform.get_local_to_parent()); const Matrix4f model_matrix = assembly_transform_matrix * object_transform_matrix; - // Object vertex buffer data has already been loaded; just add an instance + // Object vertex buffer data has already been loaded, just add an instance. const std::string obj_name = std::string(object->get_name()); - size_t buf_idx = m_scene_object_index_map.at(obj_name); + const std::size_t buffer_index = m_scene_object_index_map.at(obj_name); - const GLuint object_instances_vbo = m_scene_object_instance_vbos[buf_idx]; - const GLuint object_vao = m_scene_object_vaos[buf_idx]; - const GLsizei current_instance = m_scene_object_current_instances[buf_idx]; - m_scene_object_current_instances[buf_idx] += 1; + const GLuint object_instances_vbo = m_scene_object_instance_vbos[buffer_index]; + const GLuint object_vao = m_scene_object_vaos[buffer_index]; + const GLsizei current_instance = m_scene_object_current_instances[buffer_index]; + m_scene_object_current_instances[buffer_index] += 1; m_gl->glBindVertexArray(object_vao); m_gl->glBindBuffer(GL_ARRAY_BUFFER, object_instances_vbo); + const Matrix4f gl_matrix = transpose(model_matrix); m_gl->glBufferSubData( GL_ARRAY_BUFFER, @@ -214,7 +218,6 @@ void GLSceneLayer::load_assembly_instance( return; const Transformd transform = assembly_instance.transform_sequence().evaluate(time); - const Matrix4f transform_matrix(transform.get_local_to_parent()); for (const auto& object_instance : assembly->object_instances()) @@ -227,14 +230,17 @@ void GLSceneLayer::load_assembly_instance( void GLSceneLayer::load_object_data(const Object& object) { const std::string obj_name = std::string(object.get_name()); + RENDERER_LOG_DEBUG("opengl: uploading mesh data for object \"%s\"...", obj_name.c_str()); if (m_scene_object_index_map.count(obj_name) == 0) { - // Object vertex buffer data has not been loaded; load it - const size_t buf_idx = m_scene_object_data_vbos.size(); + // Object vertex buffer data has not been loaded, load it. + const size_t buffer_index = m_scene_object_data_vbos.size(); + GLuint object_vao; m_gl->glGenVertexArrays(1, &object_vao); + GLuint object_data_vbo; m_gl->glGenBuffers(1, &object_data_vbo); m_gl->glBindVertexArray(object_vao); @@ -242,7 +248,7 @@ void GLSceneLayer::load_object_data(const Object& object) m_scene_object_vaos.push_back(object_vao); m_scene_object_data_vbos.push_back(object_data_vbo); - m_scene_object_index_map[obj_name] = buf_idx; + m_scene_object_index_map[obj_name] = buffer_index; OpenGLRasterizer rasterizer; object.rasterize(rasterizer); @@ -268,6 +274,7 @@ void GLSceneLayer::load_object_data(const Object& object) GL_FALSE, SceneVertexByteStride, reinterpret_cast(SceneVertexByteStride / 2)); + m_gl->glEnableVertexAttribArray(0); m_gl->glEnableVertexAttribArray(1); } @@ -275,10 +282,10 @@ void GLSceneLayer::load_object_data(const Object& object) void GLSceneLayer::load_assembly_data(const Assembly& assembly) { - for (const auto& object : assembly.objects()) + for (const Object& object : assembly.objects()) load_object_data(object); - for (const auto& child_assembly : assembly.assemblies()) + for (const Assembly& child_assembly : assembly.assemblies()) load_assembly_data(child_assembly); } @@ -293,7 +300,7 @@ void GLSceneLayer::load_scene_data() load_assembly_data(assembly); // Create space for per-instance data - for (size_t i = 0; i < m_scene_object_index_map.size(); i++) + for (std::size_t i = 0; i < m_scene_object_index_map.size(); i++) { m_scene_object_instance_vbos.push_back(0); m_scene_object_instance_counts.push_back(0); @@ -307,7 +314,7 @@ void GLSceneLayer::load_scene_data() &m_scene_object_instance_vbos[0]); // Figure out how many instances of each mesh are required for all assembly instances - for (const auto& assembly_instance : m_project.get_scene()->assembly_instances()) + for (const AssemblyInstance& assembly_instance : m_project.get_scene()->assembly_instances()) { const Assembly* assembly = assembly_instance.find_assembly(); @@ -319,9 +326,9 @@ void GLSceneLayer::load_scene_data() continue; } - for (const auto& object_instance : assembly->object_instances()) + for (const ObjectInstance& object_instance : assembly->object_instances()) { - Object* object = object_instance.find_object(); + const Object* object = object_instance.find_object(); if (object == nullptr) { @@ -332,14 +339,14 @@ void GLSceneLayer::load_scene_data() } const std::string obj_name = std::string(object->get_name()); - const size_t buf_idx = m_scene_object_index_map[obj_name]; + const std::size_t buf_idx = m_scene_object_index_map[obj_name]; m_scene_object_instance_counts[buf_idx] += 1; } } // Setup instance buffers by allocating a buffer big enough for the number - // of required instances and setting up vertex attributes - for (size_t i = 0; i < m_scene_object_instance_vbos.size(); i++) + // of required instances and setting up vertex attributes. + for (std::size_t i = 0; i < m_scene_object_instance_vbos.size(); i++) { const GLuint object_vao = m_scene_object_vaos[i]; const GLuint object_instance_vbo = m_scene_object_instance_vbos[i]; @@ -353,7 +360,7 @@ void GLSceneLayer::load_scene_data() NULL, GL_DYNAMIC_DRAW); - // Attributes for a 4x4 model matrix; requires four separate attributes + // Attributes for a 4x4 model matrix requires four separate attributes // to be setup, one for each column of the matrix. for (int i = 0; i < 4; i++) { @@ -369,19 +376,19 @@ void GLSceneLayer::load_scene_data() } } - // Actually load the transform data for each instance into the allocated instance buffers - for (const auto& assembly_instance : m_project.get_scene()->assembly_instances()) + // Actually load the transform data for each instance into the allocated instance buffers. + for (const AssemblyInstance& assembly_instance : m_project.get_scene()->assembly_instances()) load_assembly_instance(assembly_instance, time); } void GLSceneLayer::init_gl(QSurfaceFormat format) { - // If there was already previous data, clean up - GLSceneLayer::cleanup_gl_data(); + // If there was already previous data, clean up. + cleanup_gl_data(); - auto vertex_shader = load_gl_shader("scene.vert"); - auto fragment_shader = load_gl_shader("scene.frag"); + const QByteArray vertex_shader = load_gl_shader("scene.vert"); + const QByteArray fragment_shader = load_gl_shader("scene.frag"); m_scene_shader_program = create_shader_program( m_gl, @@ -401,7 +408,7 @@ void GLSceneLayer::init_gl(QSurfaceFormat format) const float z_near = 0.01f; const float z_far = 1000.0f; - const auto& rc = m_camera.get_rasterization_camera(); + const RasterizationCamera& rc = m_camera.get_rasterization_camera(); const float fy = std::tan(rc.m_hfov / rc.m_aspect_ratio * 0.5) * z_near; const float fx = fy * rc.m_aspect_ratio; @@ -432,6 +439,7 @@ void GLSceneLayer::cleanup_gl_data() &m_scene_object_vaos[0]); m_scene_object_vaos.clear(); } + if (!m_scene_object_data_vbos.empty()) { m_gl->glDeleteBuffers( @@ -439,6 +447,7 @@ void GLSceneLayer::cleanup_gl_data() &m_scene_object_data_vbos[0]); m_scene_object_data_vbos.clear(); } + if (!m_scene_object_instance_vbos.empty()) { m_gl->glDeleteBuffers( @@ -446,14 +455,17 @@ void GLSceneLayer::cleanup_gl_data() &m_scene_object_instance_vbos[0]); m_scene_object_instance_vbos.clear(); } + if (m_scene_shader_program != 0) { m_gl->glDeleteProgram(m_scene_shader_program); } + if (m_depthonly_shader_program != 0) { m_gl->glDeleteProgram(m_depthonly_shader_program); } + m_scene_object_index_map.clear(); m_scene_object_data_index_counts.clear(); m_scene_object_instance_counts.clear(); @@ -472,7 +484,8 @@ void GLSceneLayer::draw() if (m_backface_culling_enabled) glEnable(GL_CULL_FACE); - else glDisable(GL_CULL_FACE); + else + glDisable(GL_CULL_FACE); m_gl->glDepthMask(GL_FALSE); m_gl->glEnable(GL_DEPTH_TEST); @@ -532,11 +545,11 @@ void GLSceneLayer::draw_depth_only() void GLSceneLayer::render_scene() { - for (size_t i = 0; i < m_scene_object_data_vbos.size(); i++) + for (std::size_t i = 0; i < m_scene_object_data_vbos.size(); i++) { - GLuint vao = m_scene_object_vaos[i]; - int index_count = m_scene_object_data_index_counts[i]; - int instance_count = m_scene_object_instance_counts[i]; + const GLuint vao = m_scene_object_vaos[i]; + const int index_count = m_scene_object_data_index_counts[i]; + const int instance_count = m_scene_object_instance_counts[i]; m_gl->glBindVertexArray(vao); m_gl->glDrawArraysInstanced( @@ -549,3 +562,4 @@ void GLSceneLayer::render_scene() } // namespace studio } // namespace appleseed + diff --git a/src/appleseed.studio/mainwindow/rendering/glscenelayer.h b/src/appleseed.studio/mainwindow/rendering/glscenelayer.h index 6f00d449e8..68c27bf463 100644 --- a/src/appleseed.studio/mainwindow/rendering/glscenelayer.h +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.h @@ -81,14 +81,11 @@ class GLSceneLayer ~GLSceneLayer(); - void init_gl( - QSurfaceFormat format); + void init_gl(QSurfaceFormat format); - void set_transform( - const foundation::Transformd& transform); + void set_transform(const foundation::Transformd& transform); - void set_gl_functions( - QOpenGLFunctions_4_1_Core* functions); + void set_gl_functions(QOpenGLFunctions_4_1_Core* functions); void toggle_backface_culling(const bool checked); @@ -132,14 +129,13 @@ class GLSceneLayer void load_scene_data(); void load_assembly_data( - const renderer::Assembly& object); + const renderer::Assembly& object); void load_assembly_instance( const renderer::AssemblyInstance& assembly_instance, const float time); - void load_object_data( - const renderer::Object& object); + void load_object_data(const renderer::Object& object); void load_object_instance( const renderer::ObjectInstance& object_instance, @@ -148,3 +144,4 @@ class GLSceneLayer } // namespace studio } // namespace appleseed + From 9803a97cbb6ec2b09e26ab90f134ebab57e0caa0 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 12:14:44 +0100 Subject: [PATCH 13/34] remove unused paramemter application_settings --- src/appleseed.studio/mainwindow/mainwindow.cpp | 6 ++---- .../mainwindow/rendering/finalrenderviewporttab.cpp | 6 ++---- .../mainwindow/rendering/finalrenderviewporttab.h | 6 +++--- .../mainwindow/rendering/openglviewporttab.cpp | 6 ++---- .../mainwindow/rendering/openglviewporttab.h | 3 +-- src/appleseed.studio/mainwindow/rendering/viewporttab.cpp | 6 ++---- src/appleseed.studio/mainwindow/rendering/viewporttab.h | 4 +--- 7 files changed, 13 insertions(+), 24 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index 1b0e1d6528..2b26b83ed3 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -985,8 +985,7 @@ void MainWindow::create_final_render_tab() *m_project_manager.get_project(), m_rendering_manager, *m_light_paths_manager, - m_ocio_config, - m_application_settings); + m_ocio_config); // Connect the beauty viewport tab to the main window and the rendering manager. connect( @@ -1034,8 +1033,7 @@ void MainWindow::create_opengl_tab() *m_project_manager.get_project(), m_rendering_manager, *m_light_paths_manager, - m_ocio_config, - m_application_settings); + m_ocio_config); // Connect the opengl viewport tab to the main window and the rendering manager. connect( diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 9d06b38a04..ff63f15c63 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -66,14 +66,12 @@ FinalRenderViewportTab::FinalRenderViewportTab( Project& project, RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, - OCIO::ConstConfigRcPtr ocio_config, - renderer::ParamArray application_settings) + OCIO::ConstConfigRcPtr ocio_config) : ViewportTab( project_explorer, project, rendering_manager, - ocio_config, - application_settings) + ocio_config) , m_light_paths_manager(light_paths_manager) { setObjectName("final_render_viewport_tab"); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index 20daa7b0f0..d363d33eef 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -57,8 +57,7 @@ class FinalRenderViewportTab renderer::Project& project, RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, - OCIO::ConstConfigRcPtr ocio_config, - renderer::ParamArray application_settings); + OCIO::ConstConfigRcPtr ocio_config); ViewportCanvas* get_viewport_canvas() const override; @@ -100,6 +99,8 @@ class FinalRenderViewportTab void slot_clear_frame(); private: + LightPathsManager& m_light_paths_manager; + ViewportCanvas* m_viewport_canvas; QToolButton* m_set_render_region_button; QToolButton* m_clear_render_region_button; @@ -125,7 +126,6 @@ class FinalRenderViewportTab std::unique_ptr m_viewport_selection_handler; std::unique_ptr m_clipboard_handler; - LightPathsManager& m_light_paths_manager; std::unique_ptr m_light_paths_viewport_toolbar; std::unique_ptr m_light_paths_picking_handler; diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 44dd05feb7..1b88d31111 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -65,14 +65,12 @@ OpenGLViewportTab::OpenGLViewportTab( Project& project, RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, - OCIO::ConstConfigRcPtr ocio_config, - renderer::ParamArray application_settings) + OCIO::ConstConfigRcPtr ocio_config) : ViewportTab( project_explorer, project, rendering_manager, - ocio_config, - application_settings) + ocio_config) , m_light_paths_manager(light_paths_manager) { setObjectName("opengl_viewport_tab"); diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index a693e947d9..25824c790a 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -84,8 +84,7 @@ class OpenGLViewportTab renderer::Project& project, RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, - OCIO::ConstConfigRcPtr ocio_config, - renderer::ParamArray application_settings); + OCIO::ConstConfigRcPtr ocio_config); ViewportCanvas* get_viewport_canvas() const override; diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 170d278dce..119b417e8c 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -79,10 +79,8 @@ ViewportTab::ViewportTab( ProjectExplorer& project_explorer, Project& project, RenderingManager& rendering_manager, - OCIO::ConstConfigRcPtr ocio_config, - renderer::ParamArray application_settings) - : m_application_settings(application_settings) - , m_project_explorer(project_explorer) + OCIO::ConstConfigRcPtr ocio_config) + : m_project_explorer(project_explorer) , m_project(project) , m_rendering_manager(rendering_manager) , m_ocio_config(ocio_config) diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index 291c3a5b77..357d5d6054 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -86,8 +86,7 @@ class ViewportTab ProjectExplorer& project_explorer, renderer::Project& project, RenderingManager& rendering_manager, - OCIO::ConstConfigRcPtr ocio_config, - renderer::ParamArray application_settings); + OCIO::ConstConfigRcPtr ocio_config); virtual ViewportCanvas* get_viewport_canvas() const = 0; @@ -111,7 +110,6 @@ class ViewportTab void load_state(const State& state); protected: - renderer::ParamArray m_application_settings; ProjectExplorer& m_project_explorer; renderer::Project& m_project; RenderingManager& m_rendering_manager; From 80588838aa561ebbeac25bed37d590675382fbbb Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 12:17:28 +0100 Subject: [PATCH 14/34] Pass the project explorer only to the final render tab --- src/appleseed.studio/mainwindow/mainwindow.cpp | 1 - .../mainwindow/rendering/finalrenderviewporttab.cpp | 2 +- .../mainwindow/rendering/finalrenderviewporttab.h | 1 + .../mainwindow/rendering/openglviewporttab.cpp | 3 --- .../mainwindow/rendering/openglviewporttab.h | 2 -- src/appleseed.studio/mainwindow/rendering/viewporttab.cpp | 5 +---- src/appleseed.studio/mainwindow/rendering/viewporttab.h | 3 --- 7 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index 2b26b83ed3..59e368a28f 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -1029,7 +1029,6 @@ void MainWindow::create_opengl_tab() { m_opengl_viewport_tab = new OpenGLViewportTab( - *m_project_explorer, *m_project_manager.get_project(), m_rendering_manager, *m_light_paths_manager, diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index ff63f15c63..421667b29f 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -68,10 +68,10 @@ FinalRenderViewportTab::FinalRenderViewportTab( LightPathsManager& light_paths_manager, OCIO::ConstConfigRcPtr ocio_config) : ViewportTab( - project_explorer, project, rendering_manager, ocio_config) + , m_project_explorer(project_explorer) , m_light_paths_manager(light_paths_manager) { setObjectName("final_render_viewport_tab"); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index d363d33eef..c78225b766 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -99,6 +99,7 @@ class FinalRenderViewportTab void slot_clear_frame(); private: + ProjectExplorer& m_project_explorer; LightPathsManager& m_light_paths_manager; ViewportCanvas* m_viewport_canvas; diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 1b88d31111..8e296a3074 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -30,7 +30,6 @@ #include "openglviewporttab.h" // appleseed.studio headers. -#include "mainwindow/project/projectexplorer.h" #include "mainwindow/rendering/renderingmanager.h" // appleseed.renderer headers. @@ -61,13 +60,11 @@ namespace appleseed { namespace studio { OpenGLViewportTab::OpenGLViewportTab( - ProjectExplorer& project_explorer, Project& project, RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, OCIO::ConstConfigRcPtr ocio_config) : ViewportTab( - project_explorer, project, rendering_manager, ocio_config) diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index 25824c790a..eb9d30df88 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -58,7 +58,6 @@ namespace OCIO = OCIO_NAMESPACE; #include // Forward declarations. -namespace appleseed { namespace studio { class ProjectExplorer; } } namespace appleseed { namespace studio { class RenderingManager; } } namespace renderer { class Entity; } namespace renderer { class Project; } @@ -80,7 +79,6 @@ class OpenGLViewportTab public: OpenGLViewportTab( - ProjectExplorer& project_explorer, renderer::Project& project, RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 119b417e8c..8b4d62aa36 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -31,7 +31,6 @@ #include "viewporttab.h" // appleseed.studio headers. -#include "mainwindow/project/projectexplorer.h" #include "mainwindow/rendering/renderingmanager.h" // appleseed.qtcommon headers. @@ -76,12 +75,10 @@ namespace studio { // ViewportTab::ViewportTab( - ProjectExplorer& project_explorer, Project& project, RenderingManager& rendering_manager, OCIO::ConstConfigRcPtr ocio_config) - : m_project_explorer(project_explorer) - , m_project(project) + : m_project(project) , m_rendering_manager(rendering_manager) , m_ocio_config(ocio_config) { diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index 357d5d6054..c404c9e3a4 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -57,7 +57,6 @@ namespace OCIO = OCIO_NAMESPACE; #include // Forward declarations. -namespace appleseed { namespace studio { class ProjectExplorer; } } namespace appleseed { namespace studio { class RenderingManager; } } namespace renderer { class Entity; } namespace renderer { class Project; } @@ -83,7 +82,6 @@ class ViewportTab public: ViewportTab( - ProjectExplorer& project_explorer, renderer::Project& project, RenderingManager& rendering_manager, OCIO::ConstConfigRcPtr ocio_config); @@ -110,7 +108,6 @@ class ViewportTab void load_state(const State& state); protected: - ProjectExplorer& m_project_explorer; renderer::Project& m_project; RenderingManager& m_rendering_manager; OCIO::ConstConfigRcPtr m_ocio_config; From a13b02bbec4e4941c4a8db757a98c610912e966d Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 12:19:26 +0100 Subject: [PATCH 15/34] Pass the rendering manager only to the final render tab --- src/appleseed.studio/mainwindow/mainwindow.cpp | 1 - .../mainwindow/rendering/finalrenderviewporttab.cpp | 2 +- .../mainwindow/rendering/finalrenderviewporttab.h | 1 + .../mainwindow/rendering/openglviewporttab.cpp | 5 ----- .../mainwindow/rendering/openglviewporttab.h | 2 -- src/appleseed.studio/mainwindow/rendering/viewporttab.cpp | 5 ----- src/appleseed.studio/mainwindow/rendering/viewporttab.h | 3 --- 7 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index 59e368a28f..37a432b996 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -1030,7 +1030,6 @@ void MainWindow::create_opengl_tab() m_opengl_viewport_tab = new OpenGLViewportTab( *m_project_manager.get_project(), - m_rendering_manager, *m_light_paths_manager, m_ocio_config); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 421667b29f..c65ddb2d44 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -69,9 +69,9 @@ FinalRenderViewportTab::FinalRenderViewportTab( OCIO::ConstConfigRcPtr ocio_config) : ViewportTab( project, - rendering_manager, ocio_config) , m_project_explorer(project_explorer) + , m_rendering_manager(rendering_manager) , m_light_paths_manager(light_paths_manager) { setObjectName("final_render_viewport_tab"); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index c78225b766..66beed7d21 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -100,6 +100,7 @@ class FinalRenderViewportTab private: ProjectExplorer& m_project_explorer; + RenderingManager& m_rendering_manager; LightPathsManager& m_light_paths_manager; ViewportCanvas* m_viewport_canvas; diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 8e296a3074..8984fc0768 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -29,9 +29,6 @@ // Interface header. #include "openglviewporttab.h" -// appleseed.studio headers. -#include "mainwindow/rendering/renderingmanager.h" - // appleseed.renderer headers. #include "renderer/api/frame.h" #include "renderer/api/project.h" @@ -61,12 +58,10 @@ namespace studio { OpenGLViewportTab::OpenGLViewportTab( Project& project, - RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, OCIO::ConstConfigRcPtr ocio_config) : ViewportTab( project, - rendering_manager, ocio_config) , m_light_paths_manager(light_paths_manager) { diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index eb9d30df88..9c5da53e4d 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -58,7 +58,6 @@ namespace OCIO = OCIO_NAMESPACE; #include // Forward declarations. -namespace appleseed { namespace studio { class RenderingManager; } } namespace renderer { class Entity; } namespace renderer { class Project; } class QComboBox; @@ -80,7 +79,6 @@ class OpenGLViewportTab public: OpenGLViewportTab( renderer::Project& project, - RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, OCIO::ConstConfigRcPtr ocio_config); diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 8b4d62aa36..52c9e927c5 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -30,9 +30,6 @@ // Interface header. #include "viewporttab.h" -// appleseed.studio headers. -#include "mainwindow/rendering/renderingmanager.h" - // appleseed.qtcommon headers. #include "utility/miscellaneous.h" @@ -76,10 +73,8 @@ namespace studio { ViewportTab::ViewportTab( Project& project, - RenderingManager& rendering_manager, OCIO::ConstConfigRcPtr ocio_config) : m_project(project) - , m_rendering_manager(rendering_manager) , m_ocio_config(ocio_config) { } diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index c404c9e3a4..a22eb5ee5c 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -57,7 +57,6 @@ namespace OCIO = OCIO_NAMESPACE; #include // Forward declarations. -namespace appleseed { namespace studio { class RenderingManager; } } namespace renderer { class Entity; } namespace renderer { class Project; } class QComboBox; @@ -83,7 +82,6 @@ class ViewportTab public: ViewportTab( renderer::Project& project, - RenderingManager& rendering_manager, OCIO::ConstConfigRcPtr ocio_config); virtual ViewportCanvas* get_viewport_canvas() const = 0; @@ -109,7 +107,6 @@ class ViewportTab protected: renderer::Project& m_project; - RenderingManager& m_rendering_manager; OCIO::ConstConfigRcPtr m_ocio_config; std::unique_ptr m_zoom_handler; From 6c8657309185a5a4f80aace91005ea6372ef9929 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 12:22:05 +0100 Subject: [PATCH 16/34] Don't store OCIO config in the main viewport tab class --- .../mainwindow/rendering/finalrenderviewporttab.cpp | 5 ++--- .../mainwindow/rendering/finalrenderviewporttab.h | 1 + .../mainwindow/rendering/openglviewporttab.cpp | 5 ++--- .../mainwindow/rendering/openglviewporttab.h | 4 +++- .../mainwindow/rendering/viewporttab.cpp | 9 +-------- src/appleseed.studio/mainwindow/rendering/viewporttab.h | 9 +-------- 6 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index c65ddb2d44..cc48a6efcf 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -67,12 +67,11 @@ FinalRenderViewportTab::FinalRenderViewportTab( RenderingManager& rendering_manager, LightPathsManager& light_paths_manager, OCIO::ConstConfigRcPtr ocio_config) - : ViewportTab( - project, - ocio_config) + : ViewportTab(project) , m_project_explorer(project_explorer) , m_rendering_manager(rendering_manager) , m_light_paths_manager(light_paths_manager) + , m_ocio_config(ocio_config) { setObjectName("final_render_viewport_tab"); setLayout(new QGridLayout()); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index 66beed7d21..bba3a65133 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -102,6 +102,7 @@ class FinalRenderViewportTab ProjectExplorer& m_project_explorer; RenderingManager& m_rendering_manager; LightPathsManager& m_light_paths_manager; + OCIO::ConstConfigRcPtr m_ocio_config; ViewportCanvas* m_viewport_canvas; QToolButton* m_set_render_region_button; diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 8984fc0768..375a2708d4 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -60,10 +60,9 @@ OpenGLViewportTab::OpenGLViewportTab( Project& project, LightPathsManager& light_paths_manager, OCIO::ConstConfigRcPtr ocio_config) - : ViewportTab( - project, - ocio_config) + : ViewportTab(project) , m_light_paths_manager(light_paths_manager) + , m_ocio_config(ocio_config) { setObjectName("opengl_viewport_tab"); setLayout(new QGridLayout()); diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index 9c5da53e4d..f97bfe7813 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -98,6 +98,9 @@ class OpenGLViewportTab void slot_toggle_light_paths(const bool checked); private: + LightPathsManager& m_light_paths_manager; + OCIO::ConstConfigRcPtr m_ocio_config; + ViewportCanvas* m_viewport_canvas; QScrollArea* m_scroll_area; QToolBar* m_toolbar; @@ -106,7 +109,6 @@ class OpenGLViewportTab std::unique_ptr m_camera_controller; std::unique_ptr m_clipboard_handler; - LightPathsManager& m_light_paths_manager; std::unique_ptr m_light_paths_viewport_toolbar; void create_viewport_canvas(); diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 52c9e927c5..390eb4d397 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -41,9 +41,6 @@ #include "foundation/image/canvasproperties.h" #include "foundation/image/image.h" -// OpenColorIO headers. -#include - // Qt headers. #include #include @@ -62,7 +59,6 @@ using namespace appleseed::qtcommon; using namespace foundation; using namespace renderer; -namespace OCIO = OCIO_NAMESPACE; namespace appleseed { namespace studio { @@ -71,11 +67,8 @@ namespace studio { // ViewportTab class implementation. // -ViewportTab::ViewportTab( - Project& project, - OCIO::ConstConfigRcPtr ocio_config) +ViewportTab::ViewportTab(Project& project) : m_project(project) - , m_ocio_config(ocio_config) { } diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index a22eb5ee5c..63cbac926d 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -45,10 +45,6 @@ #include "widgets/scrollareapanhandler.h" #include "widgets/widgetzoomhandler.h" -// OpenColorIO headers. -#include -namespace OCIO = OCIO_NAMESPACE; - // Qt headers. #include #include @@ -80,9 +76,7 @@ class ViewportTab Q_OBJECT public: - ViewportTab( - renderer::Project& project, - OCIO::ConstConfigRcPtr ocio_config); + ViewportTab(renderer::Project& project); virtual ViewportCanvas* get_viewport_canvas() const = 0; @@ -107,7 +101,6 @@ class ViewportTab protected: renderer::Project& m_project; - OCIO::ConstConfigRcPtr m_ocio_config; std::unique_ptr m_zoom_handler; std::unique_ptr m_pan_handler; From e163d7f97521579b43e2f322c395f3c6214b526e Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 22 Mar 2020 12:32:04 +0100 Subject: [PATCH 17/34] Cleanup includes --- .../rendering/finalrenderviewporttab.cpp | 2 +- .../rendering/finalrenderviewporttab.h | 8 +++++++ .../mainwindow/rendering/openglviewporttab.h | 10 +-------- .../mainwindow/rendering/viewporttab.cpp | 21 ------------------- .../mainwindow/rendering/viewporttab.h | 17 --------------- 5 files changed, 10 insertions(+), 48 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index cc48a6efcf..442d58359f 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -40,6 +40,7 @@ // appleseed.qtcommon headers. #include "utility/miscellaneous.h" +#include "widgets/mousecoordinatestracker.h" // Qt headers. #include @@ -540,4 +541,3 @@ void FinalRenderViewportTab::set_light_paths_toggle_enabled(const bool enabled) } // namespace studio } // namespace appleseed -#include "mainwindow/rendering/moc_cpp_finalrenderviewporttab.cxx" diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index bba3a65133..aa18f49ac4 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -29,14 +29,22 @@ #pragma once // appleseed.studio headers. +#include "mainwindow/rendering/cameracontroller.h" #include "mainwindow/rendering/lightpathsmanager.h" +#include "mainwindow/rendering/lightpathsviewporttoolbar.h" +#include "mainwindow/rendering/materialdrophandler.h" +#include "mainwindow/rendering/pixelcolortracker.h" +#include "mainwindow/rendering/pixelinspectorhandler.h" +#include "mainwindow/rendering/scenepickinghandler.h" #include "mainwindow/rendering/viewporttab.h" +#include "mainwindow/rendering/viewportregionselectionhandler.h" // OpenColorIO headers. #include namespace OCIO = OCIO_NAMESPACE; // Forward declarations. +namespace appleseed { namespace qtcommon { class MouseCoordinatesTracker; } } namespace appleseed { namespace studio { class LightPathsPickingHandler; } } namespace appleseed { namespace studio { class ProjectExplorer; } } namespace appleseed { namespace studio { class RenderingManager; } } diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index f97bfe7813..987aa05898 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -32,20 +32,11 @@ #include "mainwindow/rendering/cameracontroller.h" #include "mainwindow/rendering/lightpathsmanager.h" #include "mainwindow/rendering/lightpathsviewporttoolbar.h" -#include "mainwindow/rendering/materialdrophandler.h" -#include "mainwindow/rendering/pixelcolortracker.h" -#include "mainwindow/rendering/pixelinspectorhandler.h" #include "mainwindow/rendering/renderclipboardhandler.h" -#include "mainwindow/rendering/scenepickinghandler.h" #include "mainwindow/rendering/viewportcanvas.h" #include "mainwindow/rendering/viewportregionselectionhandler.h" #include "mainwindow/rendering/viewporttab.h" -// appleseed.qtcommon headers. -#include "widgets/mousecoordinatestracker.h" -#include "widgets/scrollareapanhandler.h" -#include "widgets/widgetzoomhandler.h" - // OpenColorIO headers. #include namespace OCIO = OCIO_NAMESPACE; @@ -119,3 +110,4 @@ class OpenGLViewportTab } // namespace studio } // namespace appleseed + diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 390eb4d397..825c2487e1 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -30,31 +30,12 @@ // Interface header. #include "viewporttab.h" -// appleseed.qtcommon headers. -#include "utility/miscellaneous.h" - // appleseed.renderer headers. #include "renderer/api/frame.h" #include "renderer/api/project.h" // appleseed.foundation headers. #include "foundation/image/canvasproperties.h" -#include "foundation/image/image.h" - -// Qt headers. -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Standard headers. -#include using namespace appleseed::qtcommon; using namespace foundation; @@ -126,8 +107,6 @@ void ViewportTab::load_state(const State& state) m_pan_handler->load_state(state.m_pan_handler_state); } - } // namespace studio } // namespace appleseed -#include "mainwindow/rendering/moc_cpp_viewporttab.cxx" diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index 63cbac926d..be6bb2346c 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -30,18 +30,9 @@ #pragma once // appleseed.studio headers. -#include "mainwindow/rendering/cameracontroller.h" -#include "mainwindow/rendering/lightpathsviewporttoolbar.h" -#include "mainwindow/rendering/materialdrophandler.h" -#include "mainwindow/rendering/pixelcolortracker.h" -#include "mainwindow/rendering/pixelinspectorhandler.h" -#include "mainwindow/rendering/renderclipboardhandler.h" -#include "mainwindow/rendering/scenepickinghandler.h" #include "mainwindow/rendering/viewportcanvas.h" -#include "mainwindow/rendering/viewportregionselectionhandler.h" // appleseed.qtcommon headers. -#include "widgets/mousecoordinatestracker.h" #include "widgets/scrollareapanhandler.h" #include "widgets/widgetzoomhandler.h" @@ -53,15 +44,7 @@ #include // Forward declarations. -namespace renderer { class Entity; } namespace renderer { class Project; } -class QComboBox; -class QLabel; -class QPoint; -class QRect; -class QScrollArea; -class QToolBar; -class QToolButton; namespace appleseed { namespace studio { From dde46f20ba6fb420b51f9173ceb4614bf3e402fc Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:11:47 +0100 Subject: [PATCH 18/34] give layer to constructor --- .../rendering/finalrenderviewporttab.cpp | 3 +-- .../rendering/openglviewporttab.cpp | 3 +-- .../mainwindow/rendering/viewportcanvas.cpp | 21 +++++++------------ .../mainwindow/rendering/viewportcanvas.h | 15 +++++++------ 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 442d58359f..a406b520f6 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -88,8 +88,6 @@ FinalRenderViewportTab::FinalRenderViewportTab( layout()->addWidget(m_toolbar); layout()->addWidget(m_light_paths_viewport_toolbar->toolbar()); layout()->addWidget(m_scroll_area); - - get_viewport_canvas()->set_base_layer(ViewportCanvas::BaseLayer::FinalRender); } ViewportCanvas* FinalRenderViewportTab::get_viewport_canvas() const @@ -205,6 +203,7 @@ void FinalRenderViewportTab::create_viewport_canvas() props.m_canvas_height, m_ocio_config, m_light_paths_manager, + ViewportCanvas::BaseLayer::FinalRender, this); m_viewport_canvas->setContextMenuPolicy(Qt::CustomContextMenu); diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 375a2708d4..ec35873464 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -80,8 +80,6 @@ OpenGLViewportTab::OpenGLViewportTab( layout()->addWidget(m_scroll_area); m_camera_controller->set_enabled(true); - - get_viewport_canvas()->set_base_layer(ViewportCanvas::BaseLayer::OpenGL); } ViewportCanvas* OpenGLViewportTab::get_viewport_canvas() const @@ -133,6 +131,7 @@ void OpenGLViewportTab::create_viewport_canvas() props.m_canvas_height, m_ocio_config, m_light_paths_manager, + ViewportCanvas::BaseLayer::OpenGL, this); m_viewport_canvas->setContextMenuPolicy(Qt::CustomContextMenu); diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index abe0de4f85..7c5a42e567 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -71,16 +71,17 @@ namespace studio { // ViewportCanvas::ViewportCanvas( - const renderer::Project& project, - const size_t width, - const size_t height, - OCIO::ConstConfigRcPtr ocio_config, - const LightPathsManager& light_paths_manager, - QWidget* parent) + const renderer::Project& project, + const size_t width, + const size_t height, + OCIO::ConstConfigRcPtr ocio_config, + const LightPathsManager& light_paths_manager, + const ViewportCanvas::BaseLayer layer, + QWidget* parent) : QOpenGLWidget(parent) , m_project(project) , m_draw_light_paths(false) - , m_active_base_layer(static_cast(0)) + , m_active_base_layer(layer) , m_resolve_program(0) , m_accum_loc(0) , m_accum_tex(0) @@ -263,12 +264,6 @@ void ViewportCanvas::resize( m_light_paths_layer->resize(width, height); } -void ViewportCanvas::set_base_layer(const BaseLayer base_layer) -{ - m_active_base_layer = base_layer; - update(); -} - void ViewportCanvas::resizeGL( int width, int height) diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h index f09befe778..a2c12f9bb1 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h @@ -80,6 +80,12 @@ class ViewportCanvas Q_OBJECT public: + enum BaseLayer { + FinalRender, + OpenGL, + BASE_LAYER_MAX_VALUE + }; + // Constructor. ViewportCanvas( const renderer::Project& project, @@ -87,16 +93,11 @@ class ViewportCanvas const size_t height, OCIO::ConstConfigRcPtr ocio_config, const LightPathsManager& lith_paths_manager, + const BaseLayer layer, QWidget* parent = nullptr); ~ViewportCanvas(); - enum BaseLayer { - FinalRender, - OpenGL, - BASE_LAYER_MAX_VALUE - }; - // Thread-safe. QImage capture() override; @@ -105,8 +106,6 @@ class ViewportCanvas const size_t width, const size_t height); - void set_base_layer(const BaseLayer base_layer); - BaseLayer get_active_layer() const; RenderLayer* get_render_layer(); GLSceneLayer* get_gl_scene_layer(); From f2547bd8d45cc8c0629900797a903084ee51858e Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:35:03 +0100 Subject: [PATCH 19/34] remove unused method --- src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp | 5 ----- src/appleseed.studio/mainwindow/rendering/viewportcanvas.h | 1 - 2 files changed, 6 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index 7c5a42e567..5f576e2fc9 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -155,11 +155,6 @@ void ViewportCanvas::create_light_paths_layer( height)); } -ViewportCanvas::BaseLayer ViewportCanvas::get_active_layer() const -{ - return m_active_base_layer; -} - RenderLayer* ViewportCanvas::get_render_layer() { return m_render_layer.get(); diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h index a2c12f9bb1..3d37e84d6b 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h @@ -106,7 +106,6 @@ class ViewportCanvas const size_t width, const size_t height); - BaseLayer get_active_layer() const; RenderLayer* get_render_layer(); GLSceneLayer* get_gl_scene_layer(); LightPathsLayer* get_light_paths_layer(); From 54b0e07693825cf8b61ef3b360c5011b45ce9717 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:41:51 +0100 Subject: [PATCH 20/34] put backface culling slot in the openglviewporttab --- .../mainwindow/rendering/viewportcanvas.cpp | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index 5f576e2fc9..394153ebba 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -52,6 +52,7 @@ #include #include #include +#include #include #include @@ -175,20 +176,23 @@ QImage ViewportCanvas::capture() return grabFramebuffer(); } -void ViewportCanvas::initializeGL() { +void ViewportCanvas::initializeGL() +{ RENDERER_LOG_INFO("initializing opengl."); m_gl = QOpenGLContext::currentContext()->versionFunctions(); - const auto qs_format = format(); + const QSurfaceFormat qs_format = format(); if (!m_gl->initializeOpenGLFunctions()) { const int major_version = qs_format.majorVersion(); const int minor_version = qs_format.minorVersion(); + RENDERER_LOG_ERROR( "opengl: could not load required gl functions. loaded version %d.%d, required version 3.3.", major_version, minor_version); + return; } @@ -290,22 +294,19 @@ void ViewportCanvas::resizeGL( void ViewportCanvas::paintGL() { - double dpr = static_cast(m_render_layer->image().devicePixelRatio()); GLsizei w = static_cast(width() * dpr); GLsizei h = static_cast(height() * dpr); m_gl->glViewport(0, 0, w, h); - m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_main_fb); // Clear the main framebuffers + m_gl->glBindFramebuffer(GL_FRAMEBUFFER, m_main_fb); GLfloat main_clear[]{ 0.0, 0.0, 0.0, 0.0 }; m_gl->glClearBufferfv(GL_COLOR, 0, main_clear); m_gl->glClearBufferfi(GL_DEPTH_STENCIL, 0, 1.0, 0); if (m_active_base_layer == BaseLayer::FinalRender) - { m_render_layer->draw(m_empty_vao, m_draw_light_paths); - } QOpenGLContext *ctx = const_cast(QOpenGLContext::currentContext()); @@ -400,12 +401,6 @@ void ViewportCanvas::dropEvent(QDropEvent* event) event->mimeData()->text()); } -void ViewportCanvas::slot_toggle_backface_culling(const bool checked) -{ - m_gl_scene_layer->toggle_backface_culling(checked); - update(); -} - void ViewportCanvas::slot_display_transform_changed(const QString& transform) { m_render_layer->set_display_transform(transform); From 14fe8a71b3ee36326f1f955ac0c63a431b49ed1d Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:43:39 +0100 Subject: [PATCH 21/34] put the backface culling toggle slot in the opengl tab --- .../mainwindow/rendering/openglviewporttab.cpp | 8 +++++++- .../mainwindow/rendering/openglviewporttab.h | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index ec35873464..9f8a42ee12 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -188,7 +188,7 @@ void OpenGLViewportTab::create_toolbar() backface_culling_button->setChecked(false); connect( backface_culling_button, &QToolButton::toggled , - m_viewport_canvas, &ViewportCanvas::slot_toggle_backface_culling); + this, &OpenGLViewportTab::slot_toggle_backface_culling); m_toolbar->addWidget(backface_culling_button); // Synchronize Camera button. @@ -251,6 +251,12 @@ void OpenGLViewportTab::slot_toggle_light_paths(const bool checked) m_light_paths_manager.display_light_paths(checked); } +void OpenGLViewportTab::slot_toggle_backface_culling(const bool checked) +{ + m_viewport_canvas->get_gl_scene_layer()->toggle_backface_culling(checked); + m_viewport_canvas->update(); +} + } // namespace studio } // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index 987aa05898..d739ef8995 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -87,6 +87,7 @@ class OpenGLViewportTab void slot_camera_changed(); void slot_viewport_canvas_context_menu(const QPoint& point); void slot_toggle_light_paths(const bool checked); + void slot_toggle_backface_culling(const bool checked); private: LightPathsManager& m_light_paths_manager; From 47b52938a091a407c9b64316e9dc39f27e39b904 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:44:48 +0100 Subject: [PATCH 22/34] Place the transform combo slot in the final viewport tab --- .../mainwindow/rendering/finalrenderviewporttab.cpp | 8 +++++++- .../mainwindow/rendering/finalrenderviewporttab.h | 1 + .../mainwindow/rendering/viewportcanvas.cpp | 9 --------- .../mainwindow/rendering/viewportcanvas.h | 2 -- 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index a406b520f6..3645225d7b 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -192,6 +192,12 @@ void FinalRenderViewportTab::slot_clear_frame() emit signal_clear_frame(); } +void FinalRenderViewportTab::slot_display_transform_changed(const QString& transform) +{ + m_viewport_canvas->get_render_layer()->set_display_transform(transform); + m_viewport_canvas->update(); +} + void FinalRenderViewportTab::create_viewport_canvas() { const CanvasProperties& props = m_project.get_frame()->image().properties(); @@ -359,7 +365,7 @@ void FinalRenderViewportTab::create_toolbar() m_toolbar->addWidget(m_display_transform_combo); connect( m_display_transform_combo, qOverload(&QComboBox::currentIndexChanged), - m_viewport_canvas, &ViewportCanvas::slot_display_transform_changed); + this, &FinalRenderViewportTab::slot_display_transform_changed); // Add stretchy spacer. // This places interactive widgets on the left and info on the right. diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index aa18f49ac4..3469c08057 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -105,6 +105,7 @@ class FinalRenderViewportTab void slot_set_render_region(const QRect& rect); void slot_viewport_canvas_context_menu(const QPoint& point); void slot_clear_frame(); + void slot_display_transform_changed(const QString& transform); private: ProjectExplorer& m_project_explorer; diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index 394153ebba..e6958e8bfe 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -401,15 +401,6 @@ void ViewportCanvas::dropEvent(QDropEvent* event) event->mimeData()->text()); } -void ViewportCanvas::slot_display_transform_changed(const QString& transform) -{ - m_render_layer->set_display_transform(transform); - - if (m_active_base_layer == BaseLayer::FinalRender) - { - update(); - } -} void ViewportCanvas::slot_light_path_selection_changed( const bool display_light_paths, diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h index 3d37e84d6b..b0f6c3e62e 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h @@ -116,8 +116,6 @@ class ViewportCanvas const QString& material_name); public slots: - void slot_toggle_backface_culling(const bool checked); - void slot_display_transform_changed(const QString& transform); void slot_light_path_selection_changed( const bool display_light_paths, const int selected_light_path_index, From 910a8de5d7eeac4f58abb4d5ada32765c025f2cd Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:54:48 +0100 Subject: [PATCH 23/34] Format render layer --- .../mainwindow/rendering/renderlayer.cpp | 98 +++++++++---------- .../mainwindow/rendering/renderlayer.h | 35 +++---- .../mainwindow/rendering/viewportcanvas.cpp | 1 - 3 files changed, 64 insertions(+), 70 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp index f712162324..a9af01f007 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp @@ -70,8 +70,8 @@ namespace studio { // RenderLayer::RenderLayer( - const size_t width, - const size_t height, + const std::size_t width, + const std::size_t height, OCIO::ConstConfigRcPtr ocio_config, QWidget* parent) : QWidget(parent) @@ -155,8 +155,8 @@ void RenderLayer::darken() } void RenderLayer::resize( - const size_t width, - const size_t height) + const std::size_t width, + const std::size_t height) { QMutexLocker locker(&m_mutex); @@ -188,9 +188,9 @@ namespace } inline std::uint8_t* get_image_pointer( - QImage& image, - const size_t x, - const size_t y) + QImage& image, + const std::size_t x, + const std::size_t y) { std::uint8_t* scanline = static_cast(image.scanLine(static_cast(y))); return scanline + x * image.depth() / 8; @@ -210,17 +210,17 @@ void RenderLayer::multiply(const float multiplier) assert(multiplier >= 0.0f && multiplier <= 1.0f); - const size_t image_width = static_cast(m_image.width()); - const size_t image_height = static_cast(m_image.height()); - const size_t dest_stride = static_cast(m_image.bytesPerLine()); + const auto image_width = static_cast(m_image.width()); + const auto image_height = static_cast(m_image.height()); + const auto dest_stride = static_cast(m_image.bytesPerLine()); std::uint8_t* dest = get_image_pointer(m_image); - for (size_t y = 0; y < image_height; ++y) + for (std::size_t y = 0; y < image_height; ++y) { std::uint8_t* row = dest + y * dest_stride; - for (size_t x = 0; x < image_width * 3; ++x) + for (std::size_t x = 0; x < image_width * 3; ++x) row[x] = truncate(row[x] * multiplier); } } @@ -229,18 +229,18 @@ namespace { void draw_bracket( std::uint8_t* dest, - const size_t dest_width, - const size_t dest_height, - const size_t dest_stride, - const size_t bracket_extent, + const std::size_t dest_width, + const std::size_t dest_height, + const std::size_t dest_stride, + const std::size_t bracket_extent, const std::uint8_t* pixel, - const size_t pixel_size) + const std::size_t pixel_size) { const int w = static_cast(std::min(bracket_extent, dest_width)); const int h = static_cast(std::min(bracket_extent, dest_height)); - const size_t right = (dest_width - 1) * pixel_size; - const size_t bottom = (dest_height - 1) * dest_stride; + const std::size_t right = (dest_width - 1) * pixel_size; + const std::size_t bottom = (dest_height - 1) * dest_stride; // Top-left corner. NativeDrawing::draw_hline(dest, w, pixel, pixel_size); @@ -261,27 +261,27 @@ namespace } void RenderLayer::highlight_tile( - const Frame& frame, - const size_t tile_x, - const size_t tile_y, - const size_t thread_index, - const size_t thread_count) + const Frame& frame, + const std::size_t tile_x, + const std::size_t tile_y, + const std::size_t thread_index, + const std::size_t thread_count) { QMutexLocker locker(&m_mutex); // Retrieve tile bounds. const Image& frame_image = frame.image(); const CanvasProperties& frame_props = frame_image.properties(); - const size_t x = tile_x * frame_props.m_tile_width; - const size_t y = tile_y * frame_props.m_tile_height; + const std::size_t x = tile_x * frame_props.m_tile_width; + const std::size_t y = tile_y * frame_props.m_tile_height; const Tile& tile = frame_image.tile(tile_x, tile_y); - const size_t width = tile.get_width(); - const size_t height = tile.get_height(); + const std::size_t width = tile.get_width(); + const std::size_t height = tile.get_height(); // Retrieve destination image information. - APPLESEED_UNUSED const size_t image_width = static_cast(m_image.width()); - APPLESEED_UNUSED const size_t image_height = static_cast(m_image.height()); - const size_t dest_stride = static_cast(m_image.bytesPerLine()); + APPLESEED_UNUSED const auto image_width = static_cast(m_image.width()); + APPLESEED_UNUSED const auto image_height = static_cast(m_image.height()); + const auto dest_stride = static_cast(m_image.bytesPerLine()); // Clipping is not supported. assert(x < image_width); @@ -302,7 +302,7 @@ void RenderLayer::highlight_tile( BracketColor[2] = 128 + static_cast(127.5f * (-0.5f * cos_t + 0.866f * sin_t)); // Draw a bracket around the tile. - const size_t BracketExtent = 5; + const std::size_t BracketExtent = 5; draw_bracket( dest, width, @@ -314,9 +314,9 @@ void RenderLayer::highlight_tile( } void RenderLayer::blit_tile( - const Frame& frame, - const size_t tile_x, - const size_t tile_y) + const Frame& frame, + const std::size_t tile_x, + const std::size_t tile_y) { QMutexLocker locker(&m_mutex); @@ -334,9 +334,9 @@ void RenderLayer::blit_frame(const Frame& frame) allocate_working_storage(frame_props); - for (size_t y = 0; y < frame_props.m_tile_count_y; ++y) + for (std::size_t y = 0; y < frame_props.m_tile_count_y; ++y) { - for (size_t x = 0; x < frame_props.m_tile_count_x; ++x) + for (std::size_t x = 0; x < frame_props.m_tile_count_x; ++x) { blit_tile_no_lock(frame, x, y); update_tile_no_lock(x, y); @@ -359,9 +359,9 @@ void RenderLayer::set_display_transform(const QString& transform) if (m_image_storage) { const CanvasProperties& frame_props = m_image_storage->properties(); - for (size_t y = 0; y < frame_props.m_tile_count_y; ++y) + for (std::size_t y = 0; y < frame_props.m_tile_count_y; ++y) { - for (size_t x = 0; x < frame_props.m_tile_count_x; ++x) + for (std::size_t x = 0; x < frame_props.m_tile_count_x; ++x) update_tile_no_lock(x, y); } } @@ -423,9 +423,9 @@ void RenderLayer::allocate_working_storage(const CanvasProperties& frame_props) } void RenderLayer::blit_tile_no_lock( - const Frame& frame, - const size_t tile_x, - const size_t tile_y) + const Frame& frame, + const std::size_t tile_x, + const std::size_t tile_y) { // Retrieve the source tile. const Tile& src_tile = frame.image().tile(tile_x, tile_y); @@ -435,7 +435,7 @@ void RenderLayer::blit_tile_no_lock( dst_tile.copy_from(src_tile); } -void RenderLayer::update_tile_no_lock(const size_t tile_x, const size_t tile_y) +void RenderLayer::update_tile_no_lock(const std::size_t tile_x, const std::size_t tile_y) { // Retrieve the source tile. const Tile& src_tile = m_image_storage->tile(tile_x, tile_y); @@ -455,7 +455,7 @@ void RenderLayer::update_tile_no_lock(const size_t tile_x, const size_t tile_y) m_ocio_processor->apply(image_desc); // Convert the tile to 8-bit RGB for display. - static const size_t shuffle_table[4] = { 0, 1, 2, Pixel::SkipChannel }; + static const std::size_t shuffle_table[4] = { 0, 1, 2, Pixel::SkipChannel }; Tile uint8_rgb_tile( float_tile, PixelFormatUInt8, @@ -463,14 +463,14 @@ void RenderLayer::update_tile_no_lock(const size_t tile_x, const size_t tile_y) m_uint8_tile_storage->get_storage()); // Retrieve destination image information. - APPLESEED_UNUSED const size_t image_width = static_cast(m_image.width()); - APPLESEED_UNUSED const size_t image_height = static_cast(m_image.height()); - const size_t dest_stride = static_cast(m_image.bytesPerLine()); + APPLESEED_UNUSED const auto image_width = static_cast(m_image.width()); + APPLESEED_UNUSED const auto image_height = static_cast(m_image.height()); + const auto dest_stride = static_cast(m_image.bytesPerLine()); // Compute the coordinates of the first destination pixel. const CanvasProperties& frame_props = m_image_storage->properties(); - const size_t x = tile_x * frame_props.m_tile_width; - const size_t y = tile_y * frame_props.m_tile_height; + const std::size_t x = tile_x * frame_props.m_tile_width; + const std::size_t y = tile_y * frame_props.m_tile_height; // Clipping is not supported. assert(x < image_width); diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.h b/src/appleseed.studio/mainwindow/rendering/renderlayer.h index 85c2a398cd..49cdae1d9c 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.h +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.h @@ -80,8 +80,8 @@ class RenderLayer public: // Constructor. RenderLayer( - const size_t width, - const size_t height, + const std::size_t width, + const std::size_t height, OCIO::ConstConfigRcPtr ocio_config, QWidget* parent = nullptr); @@ -93,8 +93,8 @@ class RenderLayer // Thread-safe. void resize( - const size_t width, - const size_t height); + const std::size_t width, + const std::size_t height); // Thread-safe. void clear(); @@ -107,17 +107,17 @@ class RenderLayer // Thread-safe. void highlight_tile( - const renderer::Frame& frame, - const size_t tile_x, - const size_t tile_y, - const size_t thread_index, - const size_t thread_count); + const renderer::Frame& frame, + const std::size_t tile_x, + const std::size_t tile_y, + const std::size_t thread_index, + const std::size_t thread_count); // Thread-safe. void blit_tile( const renderer::Frame& frame, - const size_t tile_x, - const size_t tile_y); + const std::size_t tile_x, + const std::size_t tile_y); // Thread-safe. void blit_frame( @@ -138,11 +138,6 @@ class RenderLayer QMutex& mutex(); QImage& image(); - signals: - void signal_material_dropped( - const foundation::Vector2d& drop_pos, - const QString& material_name); - private: mutable QMutex m_mutex; QImage m_image; @@ -163,12 +158,12 @@ class RenderLayer void blit_tile_no_lock( const renderer::Frame& frame, - const size_t tile_x, - const size_t tile_y); + const std::size_t tile_x, + const std::size_t tile_y); void update_tile_no_lock( - const size_t tile_x, - const size_t tile_y); + const std::size_t tile_x, + const std::size_t tile_y); }; diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index e6958e8bfe..084f5419a6 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -401,7 +401,6 @@ void ViewportCanvas::dropEvent(QDropEvent* event) event->mimeData()->text()); } - void ViewportCanvas::slot_light_path_selection_changed( const bool display_light_paths, const int selected_light_path_index, From d987c4069d866b7f910165bbc4a2a5db7b35c977 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 21:57:10 +0100 Subject: [PATCH 24/34] Format glscenelayer --- src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp index 3f463bbc7d..90662fc61c 100644 --- a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp @@ -136,8 +136,8 @@ namespace GLSceneLayer::GLSceneLayer( const Project& project, - const size_t width, - const size_t height) + const std::size_t width, + const std::size_t height) : m_project(project) , m_camera(*m_project.get_uncached_active_camera()) , m_backface_culling_enabled(false) @@ -236,7 +236,7 @@ void GLSceneLayer::load_object_data(const Object& object) if (m_scene_object_index_map.count(obj_name) == 0) { // Object vertex buffer data has not been loaded, load it. - const size_t buffer_index = m_scene_object_data_vbos.size(); + const std::size_t buffer_index = m_scene_object_data_vbos.size(); GLuint object_vao; m_gl->glGenVertexArrays(1, &object_vao); From 022e30ff5e1ba9acd7eb2f0395ad0de3e80a4dde Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 22:08:17 +0100 Subject: [PATCH 25/34] Minor improvements --- .../mainwindow/rendering/lightpathslayer.cpp | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp index b19b94c0f4..471da84384 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp @@ -40,6 +40,7 @@ #include "renderer/api/rasterization.h" #include "renderer/api/scene.h" #include "renderer/api/utility.h" +#include "renderer/kernel/lighting/lightpathrecorder.h" // appleseed.foundation headers. #include "foundation/image/color.h" @@ -56,8 +57,8 @@ // Standard headers. #include -#include #include +#include using namespace foundation; using namespace renderer; @@ -178,23 +179,24 @@ void LightPathsLayer::load_light_paths_data() others_buffer.reserve(total_gl_vertex_count); std::array others; - for (size_t light_path_idx = 0; light_path_idx < light_paths.size(); light_path_idx++) + for (std::size_t light_path_idx = 0; light_path_idx < light_paths.size(); light_path_idx++) { - const auto& path = light_paths[light_path_idx]; + const LightPath& path = light_paths[light_path_idx]; assert(path.m_vertex_end_index - path.m_vertex_begin_index >= 2); LightPathVertex prev; light_path_recorder.get_light_path_vertex(path.m_vertex_begin_index, prev); - for (size_t vertex_idx = path.m_vertex_begin_index + 1; vertex_idx < path.m_vertex_end_index; vertex_idx++) + for (std::size_t vertex_idx = path.m_vertex_begin_index + 1; vertex_idx < path.m_vertex_end_index; vertex_idx++) { LightPathVertex vert; light_path_recorder.get_light_path_vertex(vertex_idx, vert); - auto piece_radiance = Color3f::from_array(vert.m_radiance); - piece_radiance = linear_rgb_to_srgb(piece_radiance); - auto piece_luminance = luminance(piece_radiance); - piece_radiance /= piece_luminance; + const Color3f piece_radiance = + linear_rgb_to_srgb( + Color3f::from_array(vert.m_radiance)); + const float piece_luminance = luminance(piece_radiance); + const Color3f normalized_piece_radiance = piece_radiance / piece_luminance; std::array positions_temp_store = { prev.m_position[0], prev.m_position[1], prev.m_position[2], @@ -207,29 +209,27 @@ void LightPathsLayer::load_light_paths_data() positions_temp_store.begin(), positions_temp_store.end()); - unsigned int start_index = static_cast(others_buffer.size()); + const auto start_index = static_cast(others_buffer.size()); - GLint end = 2; - others = {{ { 0, - {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + {normalized_piece_radiance[0], normalized_piece_radiance[1], normalized_piece_radiance[2]}, {prev.m_surface_normal[0], prev.m_surface_normal[1], prev.m_surface_normal[2]} }, { 1, - {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + {normalized_piece_radiance[0], normalized_piece_radiance[1], normalized_piece_radiance[2]}, {prev.m_surface_normal[0], prev.m_surface_normal[1], prev.m_surface_normal[2]} }, { - end, - {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + 2, + {normalized_piece_radiance[0], normalized_piece_radiance[1], normalized_piece_radiance[2]}, {vert.m_surface_normal[0], vert.m_surface_normal[1], vert.m_surface_normal[2]} }, { - 1 | end, - {piece_radiance[0], piece_radiance[1], piece_radiance[2]}, + 3, + {normalized_piece_radiance[0], normalized_piece_radiance[1], normalized_piece_radiance[2]}, {vert.m_surface_normal[0], vert.m_surface_normal[1], vert.m_surface_normal[2]} }, }}; From 5a186fae3d8441d2bbb207be7a15fecb1108f292 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 22:12:09 +0100 Subject: [PATCH 26/34] minor --- .../mainwindow/rendering/lightpathslayer.cpp | 30 ++++++++----------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp index 471da84384..22dca2727c 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp @@ -153,9 +153,9 @@ void LightPathsLayer::load_light_paths_data() m_total_triangle_count = 0; - // Vertex count * 4 since we will be adding two vertices for each point along the line and will - // be adding each point twice for the beginning and end parts of each segment - // Add two because we need extra at the front and back for the extra 'previous' and 'next' attributes + // Vertex count * 4 since we will be adding two vertices for each point along the line and + // will be adding each point twice for the beginning and end parts of each segment. + // Add two because we need extra at the front and back for the extra 'previous' and 'next' attributes. const std::size_t total_gl_vertex_count = 2 * (light_path_recorder.get_vertex_count() + 2); std::vector indices; @@ -164,7 +164,7 @@ void LightPathsLayer::load_light_paths_data() positions_buffer.reserve(total_gl_vertex_count * 3); indices.reserve(total_gl_vertex_count); - // Add an empty vertex at the beginning to serve as first 'previous' + // Add an empty vertex at the beginning to serve as first 'previous'. std::array empty_positions = { 0.0, 0.0, 0.0, @@ -254,13 +254,13 @@ void LightPathsLayer::load_light_paths_data() m_path_terminator_vertex_indices.push_back(static_cast(others_buffer.size() - 1)); } - // Add an empty vertex at the end to serve as last 'next' + // Add an empty vertex at the end to serve as last 'next'. positions_buffer.insert( positions_buffer.end(), empty_positions.begin(), empty_positions.end()); - // Upload the data to the buffers + // Upload the data to the buffers. m_gl->glBindBuffer(GL_ARRAY_BUFFER, m_positions_vbo); m_gl->glBufferData( GL_ARRAY_BUFFER, @@ -284,15 +284,15 @@ void LightPathsLayer::load_light_paths_data() void LightPathsLayer::init_gl(QSurfaceFormat format) { - // If there was already previous data, clean up - LightPathsLayer::cleanup_gl_data(); + // If there was already previous data, clean up. + cleanup_gl_data(); glEnable(GL_DEPTH_TEST); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); - auto vertex_shader = load_gl_shader("lightpaths.vert"); - auto fragment_shader = load_gl_shader("lightpaths.frag"); + const QByteArray vertex_shader = load_gl_shader("lightpaths.vert"); + const QByteArray fragment_shader = load_gl_shader("lightpaths.frag"); m_shader_program = create_shader_program( m_gl, @@ -308,7 +308,7 @@ void LightPathsLayer::init_gl(QSurfaceFormat format) const float z_near = 0.01f; const float z_far = 1000.0f; - const auto& rc = m_camera.get_rasterization_camera(); + const RasterizationCamera& rc = m_camera.get_rasterization_camera(); const float fy = tan(rc.m_hfov / rc.m_aspect_ratio * 0.5) * z_near; const float fx = fy * rc.m_aspect_ratio; @@ -429,22 +429,18 @@ void LightPathsLayer::init_gl(QSurfaceFormat format) void LightPathsLayer::cleanup_gl_data() { if (m_shader_program != 0) - { m_gl->glDeleteProgram(m_shader_program); - } } void LightPathsLayer::draw_render_camera() const { - auto gl_view_matrix = const_cast(&m_gl_render_view_matrix[0]); - + const auto gl_view_matrix = const_cast(&m_gl_render_view_matrix[0]); render_scene(gl_view_matrix); } void LightPathsLayer::draw() const { - auto gl_view_matrix = const_cast(&m_gl_view_matrix[0]); - + const auto gl_view_matrix = const_cast(&m_gl_view_matrix[0]); render_scene(gl_view_matrix); } From 1d92be6e1ca811913f9d3f498c0bc7de0a0ce42b Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Fri, 27 Mar 2020 22:13:57 +0100 Subject: [PATCH 27/34] don't print display light paths when not displaying --- .../mainwindow/rendering/lightpathsmanager.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp index e92780e57e..9db237774a 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp @@ -187,7 +187,8 @@ void LightPathsManager::set_selected_light_path_index(int index) { m_selected_light_path_index = index; - print_selected_light_paths(); + if (m_display_light_paths) + print_selected_light_paths(); emit signal_light_path_selection_changed( m_display_light_paths, From cd6ca740a992d465cd91066ec0ff26bfb234090b Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 29 Mar 2020 15:21:21 +0200 Subject: [PATCH 28/34] improve log --- src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index 084f5419a6..bdb6b9e195 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -178,7 +178,7 @@ QImage ViewportCanvas::capture() void ViewportCanvas::initializeGL() { - RENDERER_LOG_INFO("initializing opengl."); + RENDERER_LOG_DEBUG("initializing OpenGL context..."); m_gl = QOpenGLContext::currentContext()->versionFunctions(); @@ -189,7 +189,7 @@ void ViewportCanvas::initializeGL() const int minor_version = qs_format.minorVersion(); RENDERER_LOG_ERROR( - "opengl: could not load required gl functions. loaded version %d.%d, required version 3.3.", + "could not load required OpenGL functions: loaded version %d.%d, required version 4.2.", major_version, minor_version); From f4154b7b8702c2f0b1a284a4623ecc050b5b4bd7 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 29 Mar 2020 16:02:45 +0200 Subject: [PATCH 29/34] cleanup --- src/appleseed.studio/mainwindow/mainwindow.cpp | 14 -------------- src/appleseed.studio/mainwindow/mainwindow.h | 1 - .../rendering/finalrenderviewporttab.cpp | 2 +- .../mainwindow/rendering/glscenelayer.cpp | 4 ++-- .../mainwindow/rendering/openglviewporttab.cpp | 2 +- .../mainwindow/rendering/viewportcanvas.cpp | 5 +++-- .../mainwindow/rendering/viewporttab.cpp | 10 +++++----- .../mainwindow/rendering/viewporttab.h | 4 +++- src/appleseed.studio/utility/gl.cpp | 10 +++++----- 9 files changed, 20 insertions(+), 32 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index 37a432b996..dc5ce4f934 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -1003,9 +1003,6 @@ void MainWindow::create_final_render_tab() connect( m_final_render_viewport_tab, SIGNAL(signal_quicksave_frame_and_aovs()), SLOT(slot_quicksave_frame_and_aovs())); - connect( - m_final_render_viewport_tab, SIGNAL(signal_reset_zoom()), - SLOT(slot_reset_zoom())); connect( m_final_render_viewport_tab, SIGNAL(signal_clear_frame()), SLOT(slot_clear_frame())); @@ -1037,9 +1034,6 @@ void MainWindow::create_opengl_tab() connect( m_opengl_viewport_tab, SIGNAL(signal_viewport_canvas_context_menu(const QPoint&)), SLOT(slot_viewport_canvas_context_menu(const QPoint&))); - connect( - m_opengl_viewport_tab, SIGNAL(signal_reset_zoom()), - SLOT(slot_reset_zoom())); m_opengl_viewport_tab_index = add_viewport_tab(m_opengl_viewport_tab, "OpenGL"); } @@ -2100,14 +2094,6 @@ void MainWindow::slot_clear_frame() } } -void MainWindow::slot_reset_zoom() -{ - const int current_tab_index = m_ui->tab_render_channels->currentIndex(); - const auto viewport_tab_it = m_tab_index_to_viewport_tab.find(current_tab_index); - if (viewport_tab_it != m_tab_index_to_viewport_tab.end()) - viewport_tab_it->second->reset_zoom(); -} - void MainWindow::slot_filter_text_changed(const QString& pattern) { m_ui->pushbutton_clear_filter->setEnabled(!pattern.isEmpty()); diff --git a/src/appleseed.studio/mainwindow/mainwindow.h b/src/appleseed.studio/mainwindow/mainwindow.h index d4992cc73c..1c6d23d963 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.h +++ b/src/appleseed.studio/mainwindow/mainwindow.h @@ -302,7 +302,6 @@ class MainWindow void slot_quicksave_frame_and_aovs(); void slot_save_render_widget_content(); void slot_clear_frame(); - void slot_reset_zoom(); // Project explorer. void slot_filter_text_changed(const QString& pattern); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 3645225d7b..804a245094 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -306,7 +306,7 @@ void FinalRenderViewportTab::create_toolbar() reset_zoom_button->setToolTip(combine_name_and_shortcut("Reset Zoom", reset_zoom_button->shortcut())); connect( reset_zoom_button, &QToolButton::clicked, - this, &FinalRenderViewportTab::signal_reset_zoom); + this, &FinalRenderViewportTab::slot_reset_zoom); m_toolbar->addWidget(reset_zoom_button); m_toolbar->addSeparator(); diff --git a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp index 90662fc61c..6c14ffb437 100644 --- a/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/glscenelayer.cpp @@ -231,7 +231,7 @@ void GLSceneLayer::load_object_data(const Object& object) { const std::string obj_name = std::string(object.get_name()); - RENDERER_LOG_DEBUG("opengl: uploading mesh data for object \"%s\"...", obj_name.c_str()); + RENDERER_LOG_DEBUG("uploading OpenGL mesh data for object \"%s\"...", obj_name.c_str()); if (m_scene_object_index_map.count(obj_name) == 0) { @@ -293,7 +293,7 @@ void GLSceneLayer::load_scene_data() { const float time = m_camera.get_shutter_middle_time(); - RENDERER_LOG_DEBUG("opengl: uploading scene data..."); + RENDERER_LOG_DEBUG("uploading OpenGL scene data..."); // First, load all the unique object vertex buffer data into static VBOs for (const auto& assembly : m_project.get_scene()->assemblies()) diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 9f8a42ee12..00dec63c88 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -175,7 +175,7 @@ void OpenGLViewportTab::create_toolbar() reset_zoom_button->setToolTip(combine_name_and_shortcut("Reset Zoom", reset_zoom_button->shortcut())); connect( reset_zoom_button, &QToolButton::clicked, - this, &OpenGLViewportTab::signal_reset_zoom); + this, &OpenGLViewportTab::slot_reset_zoom); m_toolbar->addWidget(reset_zoom_button); m_toolbar->addSeparator(); diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index bdb6b9e195..ef6394febe 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -91,8 +91,6 @@ ViewportCanvas::ViewportCanvas( , m_accum_revealage_fb(0) { setFocusPolicy(Qt::StrongFocus); - setFixedWidth(static_cast(width)); - setFixedHeight(static_cast(height)); setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent, true); @@ -259,6 +257,9 @@ void ViewportCanvas::resize( const size_t width, const size_t height) { + setFixedWidth(static_cast(width)); + setFixedHeight(static_cast(height)); + m_render_layer->resize(width, height); m_light_paths_layer->resize(width, height); } diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 825c2487e1..5bda8d108c 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -67,11 +67,6 @@ void ViewportTab::render_began() viewport_canvas->get_light_paths_layer()->update_render_camera_transform(); } -void ViewportTab::reset_zoom() -{ - m_zoom_handler->reset_zoom(); -} - void ViewportTab::update() { ViewportCanvas* viewport_canvas = get_viewport_canvas(); @@ -107,6 +102,11 @@ void ViewportTab::load_state(const State& state) m_pan_handler->load_state(state.m_pan_handler_state); } +void ViewportTab::slot_reset_zoom() +{ + m_zoom_handler->reset_zoom(); +} + } // namespace studio } // namespace appleseed diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index be6bb2346c..01600d3a52 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -66,7 +66,6 @@ class ViewportTab void clear(); virtual void render_began(); - void reset_zoom(); void update(); virtual void update_size(); @@ -82,6 +81,9 @@ class ViewportTab State save_state() const; void load_state(const State& state); + protected slots: + void slot_reset_zoom(); + protected: renderer::Project& m_project; diff --git a/src/appleseed.studio/utility/gl.cpp b/src/appleseed.studio/utility/gl.cpp index abfcaddfe5..9d59f84af2 100644 --- a/src/appleseed.studio/utility/gl.cpp +++ b/src/appleseed.studio/utility/gl.cpp @@ -80,7 +80,7 @@ namespace if (!success) { char info_log[1024]; - f->glGetShaderInfoLog(shader, 1024, NULL, info_log); + f->glGetShaderInfoLog(shader, sizeof(info_log), NULL, info_log); GLint shader_kind; f->glGetShaderiv(shader, GL_SHADER_TYPE, &shader_kind); @@ -88,13 +88,13 @@ namespace const std::string shader_kind_string = shader_kind_to_string(shader_kind); RENDERER_LOG_ERROR( - "opengl: %s shader compilation failed:\n%s", + "%s OpenGL shader compilation failed:\n%s", shader_kind_string.c_str(), info_log); } } - // Link an OpenlGL shader program with a vertex and optional fragment shader object. + // Link an OpenGL shader program with a vertex and optional fragment shader object. void link_shader_program( QOpenGLFunctions_4_1_Core* f, const GLuint program, @@ -115,10 +115,10 @@ namespace if (!success) { char info_log[1024]; - f->glGetProgramInfoLog(program, 1024, NULL, info_log); + f->glGetProgramInfoLog(program, sizeof(info_log), NULL, info_log); RENDERER_LOG_ERROR( - "opengl: shader program linking failed:\n%s", + "OpenGL shader program linking failed:\n%s", info_log); } } From 16856c733914bfa4d20b0d30602361b58a99acd9 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 29 Mar 2020 16:54:11 +0200 Subject: [PATCH 30/34] Recreate viewports when resolution change --- .../mainwindow/mainwindow.cpp | 9 +++--- src/appleseed.studio/mainwindow/mainwindow.h | 2 +- .../mainwindow/project/projectbuilder.cpp | 8 ++++-- .../mainwindow/project/projectbuilder.h | 2 +- .../mainwindow/project/projectexplorer.cpp | 4 +-- .../mainwindow/project/projectexplorer.h | 2 +- .../mainwindow/rendering/cameracontroller.cpp | 5 ---- .../mainwindow/rendering/cameracontroller.h | 1 - .../rendering/finalrenderviewporttab.cpp | 12 -------- .../rendering/finalrenderviewporttab.h | 1 - .../mainwindow/rendering/lightpathslayer.cpp | 3 +- .../mainwindow/rendering/lightpathslayer.h | 9 +++--- .../rendering/openglviewporttab.cpp | 7 ----- .../mainwindow/rendering/openglviewporttab.h | 1 - .../mainwindow/rendering/renderlayer.cpp | 28 ++++++------------- .../mainwindow/rendering/renderlayer.h | 5 ---- .../mainwindow/rendering/viewportcanvas.cpp | 19 ++----------- .../mainwindow/rendering/viewportcanvas.h | 13 +++------ .../mainwindow/rendering/viewporttab.cpp | 18 +----------- .../mainwindow/rendering/viewporttab.h | 3 -- 20 files changed, 39 insertions(+), 113 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index dc5ce4f934..aa627cf6c7 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -779,8 +779,8 @@ void MainWindow::update_project_explorer() SLOT(slot_project_modified())); connect( - m_project_explorer, SIGNAL(signal_frame_modified()), - SLOT(slot_frame_modified())); + m_project_explorer, &ProjectExplorer::signal_frame_resolution_changed, + this, &MainWindow::slot_frame_resolution_changed); } m_ui->lineedit_filter->clear(); @@ -2105,10 +2105,9 @@ void MainWindow::slot_clear_filter() m_ui->lineedit_filter->clear(); } -void MainWindow::slot_frame_modified() +void MainWindow::slot_frame_resolution_changed() { - for (each i = m_viewport_tabs; i; ++i) - i->second->update_size(); + recreate_viewport_tabs(); } void MainWindow::slot_fullscreen() diff --git a/src/appleseed.studio/mainwindow/mainwindow.h b/src/appleseed.studio/mainwindow/mainwindow.h index 1c6d23d963..451a35c897 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.h +++ b/src/appleseed.studio/mainwindow/mainwindow.h @@ -306,7 +306,7 @@ class MainWindow // Project explorer. void slot_filter_text_changed(const QString& pattern); void slot_clear_filter(); - void slot_frame_modified(); + void slot_frame_resolution_changed(); // General UI actions. void slot_fullscreen(); diff --git a/src/appleseed.studio/mainwindow/project/projectbuilder.cpp b/src/appleseed.studio/mainwindow/project/projectbuilder.cpp index f9a3870005..5033179a25 100644 --- a/src/appleseed.studio/mainwindow/project/projectbuilder.cpp +++ b/src/appleseed.studio/mainwindow/project/projectbuilder.cpp @@ -70,13 +70,17 @@ Frame* ProjectBuilder::edit_frame( const size_t new_canvas_width = new_frame->image().properties().m_canvas_width; const size_t new_canvas_height = new_frame->image().properties().m_canvas_height; - if (new_canvas_width != old_canvas_width || new_canvas_height != old_canvas_height) + const bool resolution_changed = new_canvas_width != old_canvas_width || new_canvas_height != old_canvas_height; + + if (resolution_changed) new_frame->reset_crop_window(); m_project.set_frame(new_frame); slot_notify_project_modification(); - emit signal_frame_modified(); + + if (resolution_changed) + emit signal_frame_resolution_changed(); return m_project.get_frame(); } diff --git a/src/appleseed.studio/mainwindow/project/projectbuilder.h b/src/appleseed.studio/mainwindow/project/projectbuilder.h index 54e6ffc7d9..8fd7d35840 100644 --- a/src/appleseed.studio/mainwindow/project/projectbuilder.h +++ b/src/appleseed.studio/mainwindow/project/projectbuilder.h @@ -101,7 +101,7 @@ class ProjectBuilder signals: void signal_project_modified() const; - void signal_frame_modified() const; + void signal_frame_resolution_changed() const; public slots: void slot_notify_project_modification() const; diff --git a/src/appleseed.studio/mainwindow/project/projectexplorer.cpp b/src/appleseed.studio/mainwindow/project/projectexplorer.cpp index 7f6f9306da..ff14f811ee 100644 --- a/src/appleseed.studio/mainwindow/project/projectexplorer.cpp +++ b/src/appleseed.studio/mainwindow/project/projectexplorer.cpp @@ -116,8 +116,8 @@ ProjectExplorer::ProjectExplorer( SIGNAL(signal_project_modified())); connect( - &m_project_builder, SIGNAL(signal_frame_modified()), - SIGNAL(signal_frame_modified())); + &m_project_builder, &ProjectBuilder::signal_frame_resolution_changed, + this, &ProjectExplorer::signal_frame_resolution_changed); } ProjectExplorer::~ProjectExplorer() diff --git a/src/appleseed.studio/mainwindow/project/projectexplorer.h b/src/appleseed.studio/mainwindow/project/projectexplorer.h index 67730da9e5..06db60ab5f 100644 --- a/src/appleseed.studio/mainwindow/project/projectexplorer.h +++ b/src/appleseed.studio/mainwindow/project/projectexplorer.h @@ -86,7 +86,7 @@ class ProjectExplorer signals: void signal_project_modified() const; - void signal_frame_modified() const; + void signal_frame_resolution_changed() const; private: QTreeWidget* m_tree_widget; diff --git a/src/appleseed.studio/mainwindow/rendering/cameracontroller.cpp b/src/appleseed.studio/mainwindow/rendering/cameracontroller.cpp index fc95cd8a54..645275b8cd 100644 --- a/src/appleseed.studio/mainwindow/rendering/cameracontroller.cpp +++ b/src/appleseed.studio/mainwindow/rendering/cameracontroller.cpp @@ -146,11 +146,6 @@ void CameraController::slot_entity_picked(ScenePicker::PickingResult result) } } -void CameraController::slot_frame_modified() -{ - configure_controller(); -} - bool CameraController::eventFilter(QObject* object, QEvent* event) { if (m_enabled) diff --git a/src/appleseed.studio/mainwindow/rendering/cameracontroller.h b/src/appleseed.studio/mainwindow/rendering/cameracontroller.h index 449fe5ec17..09d0bfbae7 100644 --- a/src/appleseed.studio/mainwindow/rendering/cameracontroller.h +++ b/src/appleseed.studio/mainwindow/rendering/cameracontroller.h @@ -86,7 +86,6 @@ class CameraController public slots: void slot_entity_picked(renderer::ScenePicker::PickingResult result); - void slot_frame_modified(); signals: void signal_camera_change_begin(); diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 804a245094..77da7d73ae 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -113,15 +113,6 @@ void FinalRenderViewportTab::render_began() m_light_paths_viewport_toolbar.get()->reset(&m_project); } -void FinalRenderViewportTab::update_size() -{ - ViewportTab::update_size(); - - m_set_render_region_button->setChecked(false); - - recreate_handlers(); -} - void FinalRenderViewportTab::on_tab_selected() { const bool display_light_paths = m_light_paths_manager.should_display_light_paths(); @@ -474,9 +465,6 @@ void FinalRenderViewportTab::recreate_handlers() connect( m_camera_controller.get(), &CameraController::signal_camera_changed, this, &FinalRenderViewportTab::slot_camera_changed); - connect( - &m_project_explorer, &ProjectExplorer::signal_frame_modified, - m_camera_controller.get(), &CameraController::slot_frame_modified); // Handler for picking scene entities in the render widget. m_scene_picking_handler.reset( diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h index 3469c08057..12d064d9f5 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.h @@ -72,7 +72,6 @@ class FinalRenderViewportTab void set_light_paths_toggle_enabled(const bool enabled); void render_began() override; - void update_size() override; void on_tab_selected() override; CameraController* get_camera_controller() const; diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp index 22dca2727c..cb244ac246 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp @@ -72,7 +72,8 @@ namespace constexpr std::size_t Vec3ByteStride = sizeof(float) * 3; // Struct of an element of the "others" vertex buffer - struct OtherAttributes { + struct OtherAttributes + { GLint v_bitmask; GLfloat v_color[3]; GLfloat v_surface_normal[3]; diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h index cbe6d12c83..aa674176f6 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.h @@ -68,7 +68,8 @@ namespace studio { // A widget providing an hardware-accelerated visualization of recorded light paths. // -class LightPathsLayer: public QObject +class LightPathsLayer + : public QObject { Q_OBJECT @@ -100,9 +101,9 @@ class LightPathsLayer: public QObject private slots: void slot_light_path_selection_changed( - const bool display_light_paths, - const int selected_light_path_index, - const int total_light_paths); + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths); private: const renderer::Project& m_project; diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 00dec63c88..918481a1fa 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -94,13 +94,6 @@ void OpenGLViewportTab::render_began() m_light_paths_viewport_toolbar.get()->reset(&m_project); } -void OpenGLViewportTab::update_size() -{ - ViewportTab::update_size(); - - recreate_handlers(); -} - void OpenGLViewportTab::on_tab_selected() { const bool display_light_paths = m_light_paths_manager.should_display_light_paths(); diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h index d739ef8995..0faa4c8684 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.h @@ -76,7 +76,6 @@ class OpenGLViewportTab ViewportCanvas* get_viewport_canvas() const override; void render_began() override; - void update_size() override; void on_tab_selected() override; signals: diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp index a9af01f007..ac54b4179f 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp @@ -80,12 +80,20 @@ RenderLayer::RenderLayer( , m_gl_initialized(false) { setFocusPolicy(Qt::StrongFocus); + setFixedWidth(static_cast(width)); + setFixedHeight(static_cast(height)); setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent, true); m_gl_tex = new QOpenGLTexture(QOpenGLTexture::Target2D); - resize(width, height); + m_image = + QImage( + static_cast(width), + static_cast(height), + QImage::Format_RGB888); + + clear(); const char* display_name = m_ocio_config->getDefaultDisplay(); const char* default_transform = m_ocio_config->getDefaultView(display_name); @@ -154,24 +162,6 @@ void RenderLayer::darken() multiply(0.2f); } -void RenderLayer::resize( - const std::size_t width, - const std::size_t height) -{ - QMutexLocker locker(&m_mutex); - - setFixedWidth(static_cast(width)); - setFixedHeight(static_cast(height)); - - m_image = - QImage( - static_cast(width), - static_cast(height), - QImage::Format_RGB888); - - clear(); -} - void RenderLayer::clear() { QMutexLocker locker(&m_mutex); diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.h b/src/appleseed.studio/mainwindow/rendering/renderlayer.h index 49cdae1d9c..d2159a780a 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.h +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.h @@ -91,11 +91,6 @@ class RenderLayer // Thread-safe. void darken(); - // Thread-safe. - void resize( - const std::size_t width, - const std::size_t height); - // Thread-safe. void clear(); diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp index ef6394febe..313adbc40b 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.cpp @@ -91,6 +91,8 @@ ViewportCanvas::ViewportCanvas( , m_accum_revealage_fb(0) { setFocusPolicy(Qt::StrongFocus); + setFixedWidth(static_cast(width)); + setFixedHeight(static_cast(height)); setAutoFillBackground(false); setAttribute(Qt::WA_OpaquePaintEvent, true); @@ -102,8 +104,6 @@ ViewportCanvas::ViewportCanvas( create_gl_scene_layer(width, height); create_light_paths_layer(light_paths_manager, width, height); - resize(width, height); - setAcceptDrops(true); } @@ -253,20 +253,7 @@ void ViewportCanvas::initializeGL() m_light_paths_layer->init_gl(qs_format); } -void ViewportCanvas::resize( - const size_t width, - const size_t height) -{ - setFixedWidth(static_cast(width)); - setFixedHeight(static_cast(height)); - - m_render_layer->resize(width, height); - m_light_paths_layer->resize(width, height); -} - -void ViewportCanvas::resizeGL( - int width, - int height) +void ViewportCanvas::resizeGL(int width, int height) { m_light_paths_layer->resize(width, height); diff --git a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h index b0f6c3e62e..3c7cd43ef8 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h +++ b/src/appleseed.studio/mainwindow/rendering/viewportcanvas.h @@ -101,11 +101,6 @@ class ViewportCanvas // Thread-safe. QImage capture() override; - // Thread-safe. - void resize( - const size_t width, - const size_t height); - RenderLayer* get_render_layer(); GLSceneLayer* get_gl_scene_layer(); LightPathsLayer* get_light_paths_layer(); @@ -113,13 +108,13 @@ class ViewportCanvas signals: void signal_material_dropped( const foundation::Vector2d& drop_pos, - const QString& material_name); + const QString& material_name); public slots: void slot_light_path_selection_changed( - const bool display_light_paths, - const int selected_light_path_index, - const int total_light_paths); + const bool display_light_paths, + const int selected_light_path_index, + const int total_light_paths); private: const renderer::Project& m_project; diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp index 5bda8d108c..965a4d3b88 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.cpp @@ -57,7 +57,7 @@ void ViewportTab::clear() { ViewportCanvas* viewport_canvas = get_viewport_canvas(); viewport_canvas->get_render_layer()->clear(); - viewport_canvas->repaint(); + viewport_canvas->update(); } void ViewportTab::render_began() @@ -67,22 +67,6 @@ void ViewportTab::render_began() viewport_canvas->get_light_paths_layer()->update_render_camera_transform(); } -void ViewportTab::update() -{ - ViewportCanvas* viewport_canvas = get_viewport_canvas(); - viewport_canvas->update(); -} - -void ViewportTab::update_size() -{ - const CanvasProperties& props = m_project.get_frame()->image().properties(); - - ViewportCanvas* viewport_canvas = get_viewport_canvas(); - viewport_canvas->resize( - props.m_canvas_width, - props.m_canvas_height); -} - void ViewportTab::on_tab_selected() { } diff --git a/src/appleseed.studio/mainwindow/rendering/viewporttab.h b/src/appleseed.studio/mainwindow/rendering/viewporttab.h index 01600d3a52..f5a977b1cb 100644 --- a/src/appleseed.studio/mainwindow/rendering/viewporttab.h +++ b/src/appleseed.studio/mainwindow/rendering/viewporttab.h @@ -67,9 +67,6 @@ class ViewportTab virtual void render_began(); - void update(); - virtual void update_size(); - virtual void on_tab_selected(); struct State From dcc40d2c5b88c7bdc7e682c3960a917db544e7f5 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 29 Mar 2020 17:03:17 +0200 Subject: [PATCH 31/34] Draw when moving camera --- .../mainwindow/rendering/finalrenderviewporttab.cpp | 2 +- src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 77da7d73ae..96fae91a4a 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -134,7 +134,7 @@ void FinalRenderViewportTab::slot_camera_changed() { m_viewport_canvas->get_light_paths_layer()->set_transform(m_camera_controller->get_transform()); m_viewport_canvas->get_gl_scene_layer()->set_transform(m_camera_controller->get_transform()); - update(); + m_viewport_canvas->update(); } void FinalRenderViewportTab::slot_toggle_render_region(const bool checked) diff --git a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp index 918481a1fa..17ea2bdf4b 100644 --- a/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/openglviewporttab.cpp @@ -105,7 +105,7 @@ void OpenGLViewportTab::slot_camera_changed() { m_viewport_canvas->get_light_paths_layer()->set_transform(m_camera_controller->get_transform()); m_viewport_canvas->get_gl_scene_layer()->set_transform(m_camera_controller->get_transform()); - update(); + m_viewport_canvas->update(); } void OpenGLViewportTab::slot_viewport_canvas_context_menu(const QPoint& point) From 5d0627a0624681e8bb45e4a42d689c56200e9fb2 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 29 Mar 2020 17:35:14 +0200 Subject: [PATCH 32/34] Clear light paths when clearing frame ans changing resolution --- .../mainwindow/mainwindow.cpp | 21 ++++++++++--------- .../rendering/finalrenderviewporttab.cpp | 2 -- .../mainwindow/rendering/lightpathslayer.cpp | 4 ++-- .../rendering/lightpathsmanager.cpp | 11 +++------- .../mainwindow/rendering/lightpathsmanager.h | 9 ++++---- .../rendering/lightpathsviewporttoolbar.cpp | 7 +------ .../rendering/lightpathsviewporttoolbar.h | 2 -- .../kernel/lighting/lightpathrecorder.cpp | 5 ++++- 8 files changed, 25 insertions(+), 36 deletions(-) diff --git a/src/appleseed.studio/mainwindow/mainwindow.cpp b/src/appleseed.studio/mainwindow/mainwindow.cpp index aa627cf6c7..157e4761f2 100644 --- a/src/appleseed.studio/mainwindow/mainwindow.cpp +++ b/src/appleseed.studio/mainwindow/mainwindow.cpp @@ -1245,17 +1245,14 @@ void MainWindow::start_rendering(const RenderingMode rendering_mode) } Project* project = m_project_manager.get_project(); - Frame* frame = project->get_frame(); - + project->get_frame()->clear_main_and_aov_images(); project->get_light_path_recorder().clear(); - m_light_paths_manager->clear_light_paths_selection(); - frame->clear_main_and_aov_images(); + + m_light_paths_manager->clear_light_paths(); // Darken render widgets. for (const_each i = m_viewport_tabs; i; ++i) - { i->second->render_began(); - } // Retrieve the appropriate rendering configuration. const char* configuration_name = @@ -2084,14 +2081,15 @@ void MainWindow::slot_save_render_widget_content() void MainWindow::slot_clear_frame() { - Frame* frame = m_project_manager.get_project()->get_frame(); - frame->clear_main_and_aov_images(); + Project* project = m_project_manager.get_project(); + project->get_frame()->clear_main_and_aov_images(); + project->get_light_path_recorder().clear(); + + m_light_paths_manager->clear_light_paths(); // Clear all render widgets to black. for (const std::pair& kvp : m_viewport_tabs) - { kvp.second->clear(); - } } void MainWindow::slot_filter_text_changed(const QString& pattern) @@ -2107,6 +2105,9 @@ void MainWindow::slot_clear_filter() void MainWindow::slot_frame_resolution_changed() { + m_project_manager.get_project()->get_light_path_recorder().clear(); + m_light_paths_manager->clear_light_paths(); + recreate_viewport_tabs(); } diff --git a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp index 96fae91a4a..1e7216e137 100644 --- a/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp +++ b/src/appleseed.studio/mainwindow/rendering/finalrenderviewporttab.cpp @@ -174,11 +174,9 @@ void FinalRenderViewportTab::slot_viewport_canvas_context_menu(const QPoint& poi void FinalRenderViewportTab::slot_clear_frame() { m_light_paths_toggle_button->setChecked(false); - m_light_paths_toggle_button->setEnabled(false); m_light_paths_picking_handler->set_enabled(false); m_light_paths_viewport_toolbar->set_enabled(false); m_scene_picking_handler->set_enabled(false); - m_light_paths_manager.clear_light_paths_selection(); emit signal_clear_frame(); } diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp index cb244ac246..2ea0d6f8e7 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathslayer.cpp @@ -144,7 +144,7 @@ void LightPathsLayer::load_light_paths_data() { m_path_terminator_vertex_indices.clear(); - const renderer::LightPathArray& light_paths = m_light_paths_manager.light_paths(); + const renderer::LightPathArray& light_paths = m_light_paths_manager.get_light_paths(); if (!light_paths.empty()) { @@ -452,7 +452,7 @@ void LightPathsLayer::render_scene(const GLfloat* gl_view_matrix) const if (m_total_triangle_count > 1) { - const int selected_light_path_index = m_light_paths_manager.get_selected_light_paths_index(); + const int selected_light_path_index = m_light_paths_manager.get_selected_light_path_index(); GLint first_selected, last_selected; diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp index 9db237774a..e9a47f4091 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.cpp @@ -106,7 +106,7 @@ void LightPathsManager::set_light_paths(const LightPathArray& light_paths) set_selected_light_path_index(-1); } -void LightPathsManager::clear_light_paths_selection() +void LightPathsManager::clear_light_paths() { m_light_paths.clear(); set_selected_light_path_index(-1); @@ -143,21 +143,16 @@ void LightPathsManager::save_all_light_paths(QWidget* source) const m_project.get_light_path_recorder().write(filepath.toUtf8().constData()); } -const renderer::LightPathArray& LightPathsManager::light_paths() const +const renderer::LightPathArray& LightPathsManager::get_light_paths() const { return m_light_paths; } -int LightPathsManager::get_selected_light_paths_index() const +int LightPathsManager::get_selected_light_path_index() const { return m_selected_light_path_index; } -std::size_t LightPathsManager::get_selected_light_paths_count() const -{ - return m_light_paths.size(); -} - void LightPathsManager::slot_select_all_light_paths() { set_selected_light_path_index(-1); diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h index 53c2a348ab..1ab1145559 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsmanager.h @@ -65,19 +65,18 @@ class LightPathsManager renderer::ParamArray& application_settings); void set_light_paths( - const renderer::LightPathArray& light_paths); + const renderer::LightPathArray& light_paths); - void clear_light_paths_selection(); + void clear_light_paths(); void display_light_paths(const bool on); bool should_display_light_paths() const; void save_all_light_paths(QWidget* source) const; - const renderer::LightPathArray& light_paths() const; + const renderer::LightPathArray& get_light_paths() const; - int get_selected_light_paths_index() const; - std::size_t get_selected_light_paths_count() const; + int get_selected_light_path_index() const; signals: void signal_light_path_selection_changed( diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp index 189249a62d..f6f166a74a 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.cpp @@ -155,11 +155,6 @@ void LightPathsViewportToolbar::slot_save_light_paths() m_light_paths_manager.save_all_light_paths(m_toolbar); } -void LightPathsViewportToolbar::clear_selection() const -{ - m_light_paths_manager.clear_light_paths_selection(); -} - void LightPathsViewportToolbar::create_toolbar() { // Create the render toolbar. @@ -224,7 +219,7 @@ bool LightPathsViewportToolbar::eventFilter(QObject* object, QEvent* event) const int key = key_event->key(); if (key == Qt::Key_Escape) - clear_selection(); + m_light_paths_manager.clear_light_paths(); else if (key == Qt::Key_Left) emit signal_display_previous_light_path(); else if (key == Qt::Key_Right) diff --git a/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h index 348cd41e93..d429c0108e 100644 --- a/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h +++ b/src/appleseed.studio/mainwindow/rendering/lightpathsviewporttoolbar.h @@ -104,8 +104,6 @@ class LightPathsViewportToolbar QToolButton* m_prev_path_button; QToolButton* m_next_path_button; - void clear_selection() const; - void create_toolbar(); void refresh_toolbar() const; diff --git a/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp b/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp index e2541be1eb..d3ebd97784 100644 --- a/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp +++ b/src/appleseed/renderer/kernel/lighting/lightpathrecorder.cpp @@ -236,7 +236,10 @@ void LightPathRecorder::query( { for (size_t x = x0; x <= x1; ++x) { - const auto& index_entry = impl->m_index[y * impl->m_render_width + x]; + const std::size_t pixel_index = y * impl->m_render_width + x; + assert(pixel_index < impl->m_index.size()); + + const auto& index_entry = impl->m_index[pixel_index]; for (size_t p = index_entry.m_begin_path; p < index_entry.m_end_path; ++p) { From f3a5ef0c8fdf2d339b7cb89227538f04952c52a3 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Sun, 29 Mar 2020 18:06:03 +0200 Subject: [PATCH 33/34] Use a dirty flag to regenerate the final render widget OpenGL texture --- .../mainwindow/rendering/renderlayer.cpp | 20 ++++++++++++++++--- .../mainwindow/rendering/renderlayer.h | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp index ac54b4179f..3aeb980d36 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp @@ -106,9 +106,13 @@ void RenderLayer::draw(GLuint empty_vao, bool paths_display_active) { QMutexLocker locker(&m_mutex); - m_gl_tex->destroy(); - m_gl_tex->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Nearest); - m_gl_tex->setData(m_image, QOpenGLTexture::MipMapGeneration::DontGenerateMipMaps); + if (m_refresh_gl_texture) + { + m_gl_tex->destroy(); + m_gl_tex->setMinMagFilters(QOpenGLTexture::Linear, QOpenGLTexture::Nearest); + m_gl_tex->setData(m_image, QOpenGLTexture::MipMapGeneration::DontGenerateMipMaps); + m_refresh_gl_texture = false; + } m_gl->glUseProgram(m_shader_program); @@ -168,6 +172,8 @@ void RenderLayer::clear() m_image.fill(QColor(0, 0, 0)); m_image_storage.reset(); + + m_refresh_gl_texture = true; } namespace @@ -213,6 +219,8 @@ void RenderLayer::multiply(const float multiplier) for (std::size_t x = 0; x < image_width * 3; ++x) row[x] = truncate(row[x] * multiplier); } + + m_refresh_gl_texture = true; } namespace @@ -301,6 +309,8 @@ void RenderLayer::highlight_tile( BracketExtent, BracketColor, sizeof(BracketColor)); + + m_refresh_gl_texture = true; } void RenderLayer::blit_tile( @@ -314,6 +324,8 @@ void RenderLayer::blit_tile( blit_tile_no_lock(frame, tile_x, tile_y); update_tile_no_lock(tile_x, tile_y); + + m_refresh_gl_texture = true; } void RenderLayer::blit_frame(const Frame& frame) @@ -332,6 +344,8 @@ void RenderLayer::blit_frame(const Frame& frame) update_tile_no_lock(x, y); } } + + m_refresh_gl_texture = true; } void RenderLayer::set_display_transform(const QString& transform) diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.h b/src/appleseed.studio/mainwindow/rendering/renderlayer.h index d2159a780a..6488048efb 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.h +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.h @@ -145,6 +145,7 @@ class RenderLayer GLuint m_shader_program; GLint m_mult_loc; bool m_gl_initialized; + bool m_refresh_gl_texture; OCIO::ConstConfigRcPtr m_ocio_config; OCIO::ConstProcessorRcPtr m_ocio_processor; From 4aa76b45787948efcb2715223ba860606bf04770 Mon Sep 17 00:00:00 2001 From: Kevin Masson Date: Tue, 31 Mar 2020 09:46:06 +0200 Subject: [PATCH 34/34] Initialize bool --- src/appleseed.studio/mainwindow/rendering/renderlayer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp index 3aeb980d36..b83158c2ee 100644 --- a/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp +++ b/src/appleseed.studio/mainwindow/rendering/renderlayer.cpp @@ -78,6 +78,7 @@ RenderLayer::RenderLayer( , m_mutex(QMutex::Recursive) , m_ocio_config(ocio_config) , m_gl_initialized(false) + , m_refresh_gl_texture(false) { setFocusPolicy(Qt::StrongFocus); setFixedWidth(static_cast(width));