From ec5fc7cbf9e7a48fec5f11aa0723d932f1e2f7ce Mon Sep 17 00:00:00 2001 From: silvialpz <74107990+silvialpz@users.noreply.github.com> Date: Fri, 28 Nov 2025 17:43:09 -0500 Subject: [PATCH] osltoy autodetect output color variable Signed-off-by: silvialpz <74107990+silvialpz@users.noreply.github.com> --- src/osltoy/osltoyapp.cpp | 56 ++++++++++++++++++++++++++++++++++- src/osltoy/osltoyapp.h | 7 +++++ src/osltoy/osltoyrenderer.cpp | 27 ++++++++++++++++- src/osltoy/osltoyrenderer.h | 6 ++++ 4 files changed, 94 insertions(+), 2 deletions(-) diff --git a/src/osltoy/osltoyapp.cpp b/src/osltoy/osltoyapp.cpp index 5071160e68..1cf6c6fc3d 100644 --- a/src/osltoy/osltoyapp.cpp +++ b/src/osltoy/osltoyapp.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -721,6 +722,11 @@ OSLToyMainWindow::OSLToyMainWindow(OSLToyRenderer* rend, int xr, int yr) connect(maintimer, &QTimer::timeout, this, &OSLToyMainWindow::timed_rerender_trigger); maintimer->start(); + + // Provide the callback to the renderer + m_renderer->set_output_getter([this]() { + return this->selected_output(); // Return the selected output + }); } @@ -1249,6 +1255,25 @@ OSLToyMainWindow::build_shader_group() } renderer()->set_shadergroup(group); + // Doing OSLQuery here before the getattribute calls to + // set first output param in param list as renderer output if none selected + if (m_selectedoutput.empty()) { + OSLQuery oslquery = ss->oslquery( + *group, 0); // can I assume that there is only ever one group? + for (size_t p = 0; p < oslquery.nparams(); ++p) { + auto param = oslquery.getparam(p); + // Has to be output and vec3, so we can display as color + if (param->isoutput && param->type.is_vec3()) { + m_selectedoutput = param->name; + break; + } + } + } + + ustring outputs[] = { m_selectedoutput }; + ss->attribute(group.get(), "renderer_outputs", + TypeDesc(TypeDesc::STRING, 1), &outputs); + m_shader_uses_time = false; int num_globals_needed = 0; const ustring* globals_needed = nullptr; @@ -1305,7 +1330,6 @@ OSLToyMainWindow::make_param_adjustment_row(ParamRec* param, connect(diddleCheckbox, &QCheckBox::stateChanged, this, [&](int state) { set_param_diddle(param, state); }); #endif - layout->addWidget(diddleCheckbox, row, 0); std::string typetext(param->type.c_str()); if (param->isclosure) @@ -1314,8 +1338,38 @@ OSLToyMainWindow::make_param_adjustment_row(ParamRec* param, typetext = OSL::fmtformat("struct {}", param->structname); if (param->isoutput) typetext = OSL::fmtformat("output {}", typetext); + + if ((param->isoutput) && (param->type.is_vec3())) { + // Create a radio button for the output parameter + auto outputRadioButton = new QRadioButton(this); + layout->addWidget(outputRadioButton, row, 0); + + // Label for the output parameter + auto nameLabel = new QLabel( + OSL::fmtformat("{}  {}", typetext, param->name) + .c_str()); + nameLabel->setTextFormat(Qt::RichText); + layout->addWidget(nameLabel, row, 1); + + // Connect the radio button to save the selected output and rerender + connect(outputRadioButton, &QRadioButton::toggled, this, + [this, param](bool checked) { + if (checked) { + // Save the selected output parameter + m_selectedoutput = param->name; + } + }); + + // Check the radio button if this parameter is the currently selected output + if (m_selectedoutput == param->name) + outputRadioButton->setChecked(true); + + return; // Skip the rest of the function for output parameters + } // auto typeLabel = QtUtils::mtmt{}{}", typetext); // layout->addWidget (typeLabel, row, 1); + layout->addWidget(diddleCheckbox, row, 0); + auto nameLabel = new QLabel( OSL::fmtformat("{}  {}", typetext, param->name) .c_str()); diff --git a/src/osltoy/osltoyapp.h b/src/osltoy/osltoyapp.h index b8848c48db..9072e900dc 100644 --- a/src/osltoy/osltoyapp.h +++ b/src/osltoy/osltoyapp.h @@ -88,6 +88,8 @@ class OSLToyMainWindow final : public QMainWindow { OSLToyRenderer* renderer() const { return m_renderer.get(); } + ustring selected_output() const { return m_selectedoutput; } + ShadingSystem* shadingsys() const; bool open_file(const std::string& filename); @@ -153,6 +155,8 @@ private slots: // Set up the status bar void createStatusBar(); + + // Actions. To make these do things, put them in the .cpp and give them // bodies. Delete the ones that don't correspond to concepts in your // app. @@ -206,6 +210,9 @@ private slots: std::string m_groupname; bool m_shader_uses_time = false; + // The currently selected output + ustring m_selectedoutput = ustring(""); // Empty until set by user + std::vector m_include_search_paths; diff --git a/src/osltoy/osltoyrenderer.cpp b/src/osltoy/osltoyrenderer.cpp index 932cee26bb..b372a62616 100644 --- a/src/osltoy/osltoyrenderer.cpp +++ b/src/osltoy/osltoyrenderer.cpp @@ -9,7 +9,9 @@ #include #include +#include +#include "osltoyapp.h" #include "osltoyrenderer.h" // Create ustrings for all strings used by the free function renderer services. @@ -115,6 +117,17 @@ OSLToyRenderer::OSLToyRenderer() // That also implies that our normal points to (0,0,1) sg.N = Vec3(0, 0, 1); sg.Ng = Vec3(0, 0, 1); + // In our SimpleRenderer, the "renderstate" itself just a pointer to + // the ShaderGlobals. + // sg.renderstate = &sg; +} + + + +void +OSLToyRenderer::set_output_getter(std::function getter) +{ + m_get_selected_output = getter; } @@ -126,7 +139,19 @@ OSLToyRenderer::render_image() m_framebuffer.reset( OIIO::ImageSpec(m_xres, m_yres, 3, TypeDesc::FLOAT)); - static ustring outputs[] = { ustring("Cout") }; + // Use the getter to get the selected output in the app + ustring selected_output = ustring("Cout"); // Default to "Cout" + if (m_get_selected_output) { + selected_output = m_get_selected_output(); + } else { + std::cerr + << "Warning: m_get_selected_output() is not set. Using default 'Cout'.\n"; + } + + ustring outputs[] = { selected_output }; + m_shadingsys->attribute("renderer_outputs", TypeDesc(TypeDesc::STRING, 1), + &outputs); + OIIO::paropt popt(0, OIIO::paropt::SplitDir::Tile, 4096); shade_image(*shadingsys(), *shadergroup(), &m_shaderglobals_template, m_framebuffer, outputs, ShadePixelCenters, OIIO::ROI(), popt); diff --git a/src/osltoy/osltoyrenderer.h b/src/osltoy/osltoyrenderer.h index 5a6e527909..3e8194fc08 100644 --- a/src/osltoy/osltoyrenderer.h +++ b/src/osltoy/osltoyrenderer.h @@ -4,6 +4,7 @@ #pragma once +#include #include #include #include @@ -62,6 +63,8 @@ class OSLToyRenderer final : public RendererServices { OIIO::ImageBuf& framebuffer() { return m_framebuffer; } + void set_output_getter(std::function getter); + void render_image(); // vvv Methods necessary to be a RendererServices @@ -89,6 +92,9 @@ class OSLToyRenderer final : public RendererServices { ShaderGlobals* sg, void* val); private: + std::function + m_get_selected_output; // Store the getter function that gets selection from app + OIIO::spin_mutex m_mutex; ShadingSystem* m_shadingsys; ShaderGroupRef m_group;