Skip to content

Commit ec5fc7c

Browse files
committed
osltoy autodetect output color variable
Signed-off-by: silvialpz <[email protected]>
1 parent 190c3f0 commit ec5fc7c

File tree

4 files changed

+94
-2
lines changed

4 files changed

+94
-2
lines changed

src/osltoy/osltoyapp.cpp

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <QPixmap>
2424
#include <QPlainTextEdit>
2525
#include <QPushButton>
26+
#include <QRadioButton>
2627
#include <QScrollArea>
2728
#include <QSlider>
2829
#include <QSpinBox>
@@ -721,6 +722,11 @@ OSLToyMainWindow::OSLToyMainWindow(OSLToyRenderer* rend, int xr, int yr)
721722
connect(maintimer, &QTimer::timeout, this,
722723
&OSLToyMainWindow::timed_rerender_trigger);
723724
maintimer->start();
725+
726+
// Provide the callback to the renderer
727+
m_renderer->set_output_getter([this]() {
728+
return this->selected_output(); // Return the selected output
729+
});
724730
}
725731

726732

@@ -1249,6 +1255,25 @@ OSLToyMainWindow::build_shader_group()
12491255
}
12501256
renderer()->set_shadergroup(group);
12511257

1258+
// Doing OSLQuery here before the getattribute calls to
1259+
// set first output param in param list as renderer output if none selected
1260+
if (m_selectedoutput.empty()) {
1261+
OSLQuery oslquery = ss->oslquery(
1262+
*group, 0); // can I assume that there is only ever one group?
1263+
for (size_t p = 0; p < oslquery.nparams(); ++p) {
1264+
auto param = oslquery.getparam(p);
1265+
// Has to be output and vec3, so we can display as color
1266+
if (param->isoutput && param->type.is_vec3()) {
1267+
m_selectedoutput = param->name;
1268+
break;
1269+
}
1270+
}
1271+
}
1272+
1273+
ustring outputs[] = { m_selectedoutput };
1274+
ss->attribute(group.get(), "renderer_outputs",
1275+
TypeDesc(TypeDesc::STRING, 1), &outputs);
1276+
12521277
m_shader_uses_time = false;
12531278
int num_globals_needed = 0;
12541279
const ustring* globals_needed = nullptr;
@@ -1305,7 +1330,6 @@ OSLToyMainWindow::make_param_adjustment_row(ParamRec* param,
13051330
connect(diddleCheckbox, &QCheckBox::stateChanged, this,
13061331
[&](int state) { set_param_diddle(param, state); });
13071332
#endif
1308-
layout->addWidget(diddleCheckbox, row, 0);
13091333

13101334
std::string typetext(param->type.c_str());
13111335
if (param->isclosure)
@@ -1314,8 +1338,38 @@ OSLToyMainWindow::make_param_adjustment_row(ParamRec* param,
13141338
typetext = OSL::fmtformat("struct {}", param->structname);
13151339
if (param->isoutput)
13161340
typetext = OSL::fmtformat("output {}", typetext);
1341+
1342+
if ((param->isoutput) && (param->type.is_vec3())) {
1343+
// Create a radio button for the output parameter
1344+
auto outputRadioButton = new QRadioButton(this);
1345+
layout->addWidget(outputRadioButton, row, 0);
1346+
1347+
// Label for the output parameter
1348+
auto nameLabel = new QLabel(
1349+
OSL::fmtformat("<i>{}</i>&nbsp; <b>{}</b>", typetext, param->name)
1350+
.c_str());
1351+
nameLabel->setTextFormat(Qt::RichText);
1352+
layout->addWidget(nameLabel, row, 1);
1353+
1354+
// Connect the radio button to save the selected output and rerender
1355+
connect(outputRadioButton, &QRadioButton::toggled, this,
1356+
[this, param](bool checked) {
1357+
if (checked) {
1358+
// Save the selected output parameter
1359+
m_selectedoutput = param->name;
1360+
}
1361+
});
1362+
1363+
// Check the radio button if this parameter is the currently selected output
1364+
if (m_selectedoutput == param->name)
1365+
outputRadioButton->setChecked(true);
1366+
1367+
return; // Skip the rest of the function for output parameters
1368+
}
13171369
// auto typeLabel = QtUtils::mtmt{}<i>{}</i>", typetext);
13181370
// layout->addWidget (typeLabel, row, 1);
1371+
layout->addWidget(diddleCheckbox, row, 0);
1372+
13191373
auto nameLabel = new QLabel(
13201374
OSL::fmtformat("<i>{}</i>&nbsp; <b>{}</b>", typetext, param->name)
13211375
.c_str());

src/osltoy/osltoyapp.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@ class OSLToyMainWindow final : public QMainWindow {
8888

8989
OSLToyRenderer* renderer() const { return m_renderer.get(); }
9090

91+
ustring selected_output() const { return m_selectedoutput; }
92+
9193
ShadingSystem* shadingsys() const;
9294

9395
bool open_file(const std::string& filename);
@@ -153,6 +155,8 @@ private slots:
153155
// Set up the status bar
154156
void createStatusBar();
155157

158+
159+
156160
// Actions. To make these do things, put them in the .cpp and give them
157161
// bodies. Delete the ones that don't correspond to concepts in your
158162
// app.
@@ -206,6 +210,9 @@ private slots:
206210
std::string m_groupname;
207211
bool m_shader_uses_time = false;
208212

213+
// The currently selected output
214+
ustring m_selectedoutput = ustring(""); // Empty until set by user
215+
209216
std::vector<std::string> m_include_search_paths;
210217

211218

src/osltoy/osltoyrenderer.cpp

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99

1010
#include <OSL/hashes.h>
1111
#include <OSL/oslexec.h>
12+
#include <OSL/oslquery.h>
1213

14+
#include "osltoyapp.h"
1315
#include "osltoyrenderer.h"
1416

1517
// Create ustrings for all strings used by the free function renderer services.
@@ -115,6 +117,17 @@ OSLToyRenderer::OSLToyRenderer()
115117
// That also implies that our normal points to (0,0,1)
116118
sg.N = Vec3(0, 0, 1);
117119
sg.Ng = Vec3(0, 0, 1);
120+
// In our SimpleRenderer, the "renderstate" itself just a pointer to
121+
// the ShaderGlobals.
122+
// sg.renderstate = &sg;
123+
}
124+
125+
126+
127+
void
128+
OSLToyRenderer::set_output_getter(std::function<ustring()> getter)
129+
{
130+
m_get_selected_output = getter;
118131
}
119132

120133

@@ -126,7 +139,19 @@ OSLToyRenderer::render_image()
126139
m_framebuffer.reset(
127140
OIIO::ImageSpec(m_xres, m_yres, 3, TypeDesc::FLOAT));
128141

129-
static ustring outputs[] = { ustring("Cout") };
142+
// Use the getter to get the selected output in the app
143+
ustring selected_output = ustring("Cout"); // Default to "Cout"
144+
if (m_get_selected_output) {
145+
selected_output = m_get_selected_output();
146+
} else {
147+
std::cerr
148+
<< "Warning: m_get_selected_output() is not set. Using default 'Cout'.\n";
149+
}
150+
151+
ustring outputs[] = { selected_output };
152+
m_shadingsys->attribute("renderer_outputs", TypeDesc(TypeDesc::STRING, 1),
153+
&outputs);
154+
130155
OIIO::paropt popt(0, OIIO::paropt::SplitDir::Tile, 4096);
131156
shade_image(*shadingsys(), *shadergroup(), &m_shaderglobals_template,
132157
m_framebuffer, outputs, ShadePixelCenters, OIIO::ROI(), popt);

src/osltoy/osltoyrenderer.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
#pragma once
66

7+
#include <functional>
78
#include <map>
89
#include <memory>
910
#include <unordered_map>
@@ -62,6 +63,8 @@ class OSLToyRenderer final : public RendererServices {
6263

6364
OIIO::ImageBuf& framebuffer() { return m_framebuffer; }
6465

66+
void set_output_getter(std::function<ustring()> getter);
67+
6568
void render_image();
6669

6770
// vvv Methods necessary to be a RendererServices
@@ -89,6 +92,9 @@ class OSLToyRenderer final : public RendererServices {
8992
ShaderGlobals* sg, void* val);
9093

9194
private:
95+
std::function<ustring()>
96+
m_get_selected_output; // Store the getter function that gets selection from app
97+
9298
OIIO::spin_mutex m_mutex;
9399
ShadingSystem* m_shadingsys;
94100
ShaderGroupRef m_group;

0 commit comments

Comments
 (0)