From a4de7b3c0077d116e6ba52485df8af3b5805657f Mon Sep 17 00:00:00 2001 From: Jonathan Stone Date: Tue, 4 Oct 2022 18:49:54 -0700 Subject: [PATCH] Improvements to advanced viewer options (#1093) - Simplify the Viewing Options section, and move it to the top for quick access. - Create dedicated sections for Scene Options and Asset Loading Options. - Fix an edge case with the Split Direct Light option. --- source/MaterialXView/Viewer.cpp | 265 +++++++++++++++----------------- source/MaterialXView/Viewer.h | 22 +-- 2 files changed, 131 insertions(+), 156 deletions(-) diff --git a/source/MaterialXView/Viewer.cpp b/source/MaterialXView/Viewer.cpp index 156944d777..5f4552b558 100644 --- a/source/MaterialXView/Viewer.cpp +++ b/source/MaterialXView/Viewer.cpp @@ -250,13 +250,13 @@ Viewer::Viewer(const std::string& materialFilename, _genContextMdl(mx::MdlShaderGenerator::create()), #endif _unitRegistry(mx::UnitConverterRegistry::create()), + _drawEnvironment(false), + _outlineSelection(false), + _renderTransparency(true), + _renderDoubleSided(true), _splitByUdims(true), _mergeMaterials(false), _showAllInputs(false), - _renderTransparency(true), - _renderDoubleSided(true), - _outlineSelection(false), - _drawEnvironment(false), _targetShader("standard_surface"), _captureRequested(false), _exitRequested(false), @@ -436,7 +436,7 @@ void Viewer::loadEnvironmentLight() } // Look for an irradiance map using an expected filename convention. - mx::ImagePtr envIrradianceMap; + mx::ImagePtr envIrradianceMap = _imageHandler->getInvalidImage(); if (!_normalizeEnvironment && !_splitDirectLight) { mx::FilePath envIrradiancePath = _envRadianceFilename.getParentPath() / IRRADIANCE_MAP_FOLDER / _envRadianceFilename.getBaseName(); @@ -688,62 +688,90 @@ void Viewer::createAdvancedSettings(Widget* parent) ng::Widget* advancedPopup = new ng::Widget(scrollPanel); advancedPopup->set_layout(new ng::GroupLayout(13)); - ng::Label* meshLabel = new ng::Label(advancedPopup, "Mesh Options"); - meshLabel->set_font_size(20); - meshLabel->set_font("sans-bold"); + ng::Label* viewLabel = new ng::Label(advancedPopup, "Viewing Options"); + viewLabel->set_font_size(20); + viewLabel->set_font("sans-bold"); - ng::CheckBox* splitUdimsBox = new ng::CheckBox(advancedPopup, "Split By UDIMs"); - splitUdimsBox->set_checked(_splitByUdims); - splitUdimsBox->set_callback([this](bool enable) + ng::CheckBox* drawEnvironmentBox = new ng::CheckBox(advancedPopup, "Draw Environment"); + drawEnvironmentBox->set_checked(_drawEnvironment); + drawEnvironmentBox->set_callback([this](bool enable) { - _splitByUdims = enable; + _drawEnvironment = enable; }); - ng::Label* materialLabel = new ng::Label(advancedPopup, "Material Options"); - materialLabel->set_font_size(20); - materialLabel->set_font("sans-bold"); + ng::CheckBox* outlineSelectedGeometryBox = new ng::CheckBox(advancedPopup, "Outline Selected Geometry"); + outlineSelectedGeometryBox->set_checked(_outlineSelection); + outlineSelectedGeometryBox->set_callback([this](bool enable) + { + _outlineSelection = enable; + }); - ng::CheckBox* mergeMaterialsBox = new ng::CheckBox(advancedPopup, "Merge Materials"); - mergeMaterialsBox->set_checked(_mergeMaterials); - mergeMaterialsBox->set_callback([this](bool enable) + ng::Label* renderLabel = new ng::Label(advancedPopup, "Render Options"); + renderLabel->set_font_size(20); + renderLabel->set_font("sans-bold"); + + ng::CheckBox* transparencyBox = new ng::CheckBox(advancedPopup, "Render Transparency"); + transparencyBox->set_checked(_renderTransparency); + transparencyBox->set_callback([this](bool enable) { - _mergeMaterials = enable; + _renderTransparency = enable; }); - ng::CheckBox* showInputsBox = new ng::CheckBox(advancedPopup, "Show All Inputs"); - showInputsBox->set_checked(_showAllInputs); - showInputsBox->set_callback([this](bool enable) + ng::CheckBox* doubleSidedBox = new ng::CheckBox(advancedPopup, "Render Double-Sided"); + doubleSidedBox->set_checked(_renderDoubleSided); + doubleSidedBox->set_callback([this](bool enable) { - _showAllInputs = enable; - }); + _renderDoubleSided = enable; + }); - Widget* unitGroup = new Widget(advancedPopup); - unitGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); - new ng::Label(unitGroup, "Distance Unit:"); - ng::ComboBox* distanceUnitBox = new ng::ComboBox(unitGroup, _distanceUnitOptions); - distanceUnitBox->set_fixed_size(ng::Vector2i(100, 20)); - distanceUnitBox->set_chevron_icon(-1); - if (_distanceUnitConverter) + ng::CheckBox* importanceSampleBox = new ng::CheckBox(advancedPopup, "Environment FIS"); + importanceSampleBox->set_checked(_genContext.getOptions().hwSpecularEnvironmentMethod == mx::SPECULAR_ENVIRONMENT_FIS); + importanceSampleBox->set_callback([this](bool enable) { - distanceUnitBox->set_selected_index(_distanceUnitConverter->getUnitAsInteger("meter")); - } - distanceUnitBox->set_callback([this](int index) + _genContext.getOptions().hwSpecularEnvironmentMethod = enable ? mx::SPECULAR_ENVIRONMENT_FIS : mx::SPECULAR_ENVIRONMENT_PREFILTER; + _genContextEssl.getOptions().hwSpecularEnvironmentMethod = _genContext.getOptions().hwSpecularEnvironmentMethod; + reloadShaders(); + }); + + ng::CheckBox* refractionBox = new ng::CheckBox(advancedPopup, "Transmission Refraction"); + refractionBox->set_checked(_genContext.getOptions().hwTransmissionRenderMethod == mx::TRANSMISSION_REFRACTION); + refractionBox->set_callback([this](bool enable) + { + _genContext.getOptions().hwTransmissionRenderMethod = enable ? mx::TRANSMISSION_REFRACTION : mx::TRANSMISSION_OPACITY; + _genContextEssl.getOptions().hwTransmissionRenderMethod = _genContext.getOptions().hwTransmissionRenderMethod; + reloadShaders(); + }); + + Widget* albedoGroup = new Widget(advancedPopup); + albedoGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); + new ng::Label(albedoGroup, "Albedo Method:"); + mx::StringVec albedoOptions = { "Analytic", "Table", "MC" }; + ng::ComboBox* albedoBox = new ng::ComboBox(albedoGroup, albedoOptions); + albedoBox->set_chevron_icon(-1); + albedoBox->set_selected_index((int) _genContext.getOptions().hwDirectionalAlbedoMethod ); + albedoBox->set_callback([this](int index) + { + _genContext.getOptions().hwDirectionalAlbedoMethod = (mx::HwDirectionalAlbedoMethod) index; + reloadShaders(); + updateAlbedoTable(); + }); + + Widget* sampleGroup = new Widget(advancedPopup); + sampleGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); + new ng::Label(sampleGroup, "Environment Samples:"); + mx::StringVec sampleOptions; + for (int i = MIN_ENV_SAMPLE_COUNT; i <= MAX_ENV_SAMPLE_COUNT; i *= 4) { m_process_events = false; - _genContext.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; - _genContextEssl.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; -#if MATERIALX_BUILD_GEN_OSL - _genContextOsl.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; -#endif -#if MATERIALX_BUILD_GEN_MDL - _genContextMdl.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; -#endif - for (MaterialPtr material : _materials) - { - material->bindShader(); - material->bindUnits(_unitRegistry, _genContext); - } + sampleOptions.push_back(std::to_string(i)); m_process_events = true; + } + ng::ComboBox* sampleBox = new ng::ComboBox(sampleGroup, sampleOptions); + sampleBox->set_chevron_icon(-1); + sampleBox->set_selected_index((int)std::log2(_lightHandler->getEnvSampleCount() / MIN_ENV_SAMPLE_COUNT) / 2); + sampleBox->set_callback([this](int index) + { + _lightHandler->setEnvSampleCount(MIN_ENV_SAMPLE_COUNT * (int) std::pow(4, index)); }); ng::Label* lightingLabel = new ng::Label(advancedPopup, "Lighting Options"); @@ -764,20 +792,6 @@ void Viewer::createAdvancedSettings(Widget* parent) _lightHandler->setIndirectLighting(enable); }); - ng::CheckBox* normalizeEnvironmentBox = new ng::CheckBox(advancedPopup, "Normalize Environment"); - normalizeEnvironmentBox->set_checked(_normalizeEnvironment); - normalizeEnvironmentBox->set_callback([this](bool enable) - { - _normalizeEnvironment = enable; - }); - - ng::CheckBox* splitDirectLightBox = new ng::CheckBox(advancedPopup, "Split Direct Light"); - splitDirectLightBox->set_checked(_splitDirectLight); - splitDirectLightBox->set_callback([this](bool enable) - { - _splitDirectLight = enable; - }); - ng::Widget* lightRotationRow = new ng::Widget(advancedPopup); lightRotationRow->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); mx::UIProperties ui; @@ -820,109 +834,70 @@ void Viewer::createAdvancedSettings(Widget* parent) }); ambientOcclusionGainBox->set_editable(true); - ng::Label* renderLabel = new ng::Label(advancedPopup, "Render Options"); - renderLabel->set_font_size(20); - renderLabel->set_font("sans-bold"); - - ng::CheckBox* transparencyBox = new ng::CheckBox(advancedPopup, "Render Transparency"); - transparencyBox->set_checked(_renderTransparency); - transparencyBox->set_callback([this](bool enable) - { - _renderTransparency = enable; - }); - - ng::CheckBox* doubleSidedBox = new ng::CheckBox(advancedPopup, "Render Double-Sided"); - doubleSidedBox->set_checked(_renderDoubleSided); - doubleSidedBox->set_callback([this](bool enable) - { - _renderDoubleSided = enable; - }); - - ng::CheckBox* importanceSampleBox = new ng::CheckBox(advancedPopup, "Environment FIS"); - importanceSampleBox->set_checked(_genContext.getOptions().hwSpecularEnvironmentMethod == mx::SPECULAR_ENVIRONMENT_FIS); - importanceSampleBox->set_callback([this](bool enable) - { - _genContext.getOptions().hwSpecularEnvironmentMethod = enable ? mx::SPECULAR_ENVIRONMENT_FIS : mx::SPECULAR_ENVIRONMENT_PREFILTER; - _genContextEssl.getOptions().hwSpecularEnvironmentMethod = _genContext.getOptions().hwSpecularEnvironmentMethod; - reloadShaders(); - }); - - ng::CheckBox* refractionBox = new ng::CheckBox(advancedPopup, "Transmission Refraction"); - refractionBox->set_checked(_genContext.getOptions().hwTransmissionRenderMethod == mx::TRANSMISSION_REFRACTION); - refractionBox->set_callback([this](bool enable) - { - _genContext.getOptions().hwTransmissionRenderMethod = enable ? mx::TRANSMISSION_REFRACTION : mx::TRANSMISSION_OPACITY; - _genContextEssl.getOptions().hwTransmissionRenderMethod = _genContext.getOptions().hwTransmissionRenderMethod; - reloadShaders(); - }); + ng::Label* sceneLabel = new ng::Label(advancedPopup, "Scene Options"); + sceneLabel->set_font_size(20); + sceneLabel->set_font("sans-bold"); - Widget* albedoGroup = new Widget(advancedPopup); - albedoGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); - new ng::Label(albedoGroup, "Albedo Method:"); - mx::StringVec albedoOptions = { "Analytic", "Table", "MC" }; - ng::ComboBox* albedoBox = new ng::ComboBox(albedoGroup, albedoOptions); - albedoBox->set_chevron_icon(-1); - albedoBox->set_selected_index((int) _genContext.getOptions().hwDirectionalAlbedoMethod ); - albedoBox->set_callback([this](int index) + Widget* unitGroup = new Widget(advancedPopup); + unitGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); + new ng::Label(unitGroup, "Distance Unit:"); + ng::ComboBox* distanceUnitBox = new ng::ComboBox(unitGroup, _distanceUnitOptions); + distanceUnitBox->set_fixed_size(ng::Vector2i(100, 20)); + distanceUnitBox->set_chevron_icon(-1); + if (_distanceUnitConverter) { - _genContext.getOptions().hwDirectionalAlbedoMethod = (mx::HwDirectionalAlbedoMethod) index; - reloadShaders(); - updateAlbedoTable(); - }); - - Widget* sampleGroup = new Widget(advancedPopup); - sampleGroup->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); - new ng::Label(sampleGroup, "Environment Samples:"); - mx::StringVec sampleOptions; - for (int i = MIN_ENV_SAMPLE_COUNT; i <= MAX_ENV_SAMPLE_COUNT; i *= 4) + distanceUnitBox->set_selected_index(_distanceUnitConverter->getUnitAsInteger("meter")); + } + distanceUnitBox->set_callback([this](int index) { m_process_events = false; - sampleOptions.push_back(std::to_string(i)); + _genContext.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; + _genContextEssl.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; +#if MATERIALX_BUILD_GEN_OSL + _genContextOsl.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; +#endif +#if MATERIALX_BUILD_GEN_MDL + _genContextMdl.getOptions().targetDistanceUnit = _distanceUnitOptions[index]; +#endif + for (MaterialPtr material : _materials) + { + material->bindShader(); + material->bindUnits(_unitRegistry, _genContext); + } m_process_events = true; - } - ng::ComboBox* sampleBox = new ng::ComboBox(sampleGroup, sampleOptions); - sampleBox->set_chevron_icon(-1); - sampleBox->set_selected_index((int)std::log2(_lightHandler->getEnvSampleCount() / MIN_ENV_SAMPLE_COUNT) / 2); - sampleBox->set_callback([this](int index) - { - _lightHandler->setEnvSampleCount(MIN_ENV_SAMPLE_COUNT * (int) std::pow(4, index)); }); - ng::Label* viewLabel = new ng::Label(advancedPopup, "Viewing Options"); - viewLabel->set_font_size(20); - viewLabel->set_font("sans-bold"); + ng::Label* loadingLabel = new ng::Label(advancedPopup, "Asset Loading Options"); + loadingLabel->set_font_size(20); + loadingLabel->set_font("sans-bold"); - ng::CheckBox* outlineSelectedGeometryBox = new ng::CheckBox(advancedPopup, "Outline Selected Geometry"); - outlineSelectedGeometryBox->set_checked(_outlineSelection); - outlineSelectedGeometryBox->set_callback([this](bool enable) + ng::CheckBox* splitUdimsBox = new ng::CheckBox(advancedPopup, "Split By UDIMs"); + splitUdimsBox->set_checked(_splitByUdims); + splitUdimsBox->set_callback([this](bool enable) { - _outlineSelection = enable; + _splitByUdims = enable; }); - ng::CheckBox* drawEnvironmentBox = new ng::CheckBox(advancedPopup, "Render Environment"); - drawEnvironmentBox->set_checked(_drawEnvironment); - drawEnvironmentBox->set_callback([this](bool enable) + ng::CheckBox* mergeMaterialsBox = new ng::CheckBox(advancedPopup, "Merge Materials"); + mergeMaterialsBox->set_checked(_mergeMaterials); + mergeMaterialsBox->set_callback([this](bool enable) { - _drawEnvironment = enable; + _mergeMaterials = enable; }); - ng::CheckBox* turntableEnabledCheckBox = new ng::CheckBox(advancedPopup, "Enable Turntable"); - turntableEnabledCheckBox->set_checked(_turntableEnabled); - turntableEnabledCheckBox->set_callback([this](bool enable) + ng::CheckBox* showInputsBox = new ng::CheckBox(advancedPopup, "Show All Inputs"); + showInputsBox->set_checked(_showAllInputs); + showInputsBox->set_callback([this](bool enable) { - toggleTurntable(enable); + _showAllInputs = enable; }); - ng::Widget* meshTurntableRow = new ng::Widget(advancedPopup); - meshTurntableRow->set_layout(new ng::BoxLayout(ng::Orientation::Horizontal)); - ui.uiMin = mx::Value::createValue(2); - ui.uiMax = mx::Value::createValue(360); - ng::IntBox* meshTurntableBox = createIntWidget(meshTurntableRow, "Turntable Steps:", - _turntableSteps, &ui, [this](int value) + ng::CheckBox* splitDirectLightBox = new ng::CheckBox(advancedPopup, "Split Direct Light"); + splitDirectLightBox->set_checked(_splitDirectLight); + splitDirectLightBox->set_callback([this](bool enable) { - _turntableSteps = std::clamp(value, 2, 360); + _splitDirectLight = enable; }); - meshTurntableBox->set_editable(true); ng::Label* translationLabel = new ng::Label(advancedPopup, "Translation Options (T)"); translationLabel->set_font_size(20); diff --git a/source/MaterialXView/Viewer.h b/source/MaterialXView/Viewer.h index 615a5a2ba5..82654e9966 100644 --- a/source/MaterialXView/Viewer.h +++ b/source/MaterialXView/Viewer.h @@ -375,22 +375,22 @@ class Viewer : public ng::Screen // Unit registry mx::UnitConverterRegistryPtr _unitRegistry; - // Mesh options - bool _splitByUdims; + // Viewing options + bool _drawEnvironment; + bool _outlineSelection; - // Material options - bool _mergeMaterials; - bool _showAllInputs; + // Render options + bool _renderTransparency; + bool _renderDoubleSided; - // Unit options + // Scene options mx::StringVec _distanceUnitOptions; mx::LinearUnitConverterPtr _distanceUnitConverter; - // Render options - bool _renderTransparency; - bool _renderDoubleSided; - bool _outlineSelection; - bool _drawEnvironment; + // Asset loading options + bool _splitByUdims; + bool _mergeMaterials; + bool _showAllInputs; // Shader translation std::string _targetShader;