diff --git a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml index 5bac374fb5..a928b1379f 100644 --- a/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml +++ b/interface/resources/qml/hifi/dialogs/graphics/GraphicsSettings.qml @@ -4,6 +4,7 @@ // // Created by Zach Fox on 2019-07-10 // Copyright 2019 High Fidelity, Inc. +// Copyright 2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -212,8 +213,8 @@ Flickable { ColumnLayout { anchors.left: renderingEffectsHeader.right anchors.leftMargin: 20 - Layout.preferredWidth: parent.width - spacing: 0 + Layout.preferredWidth: parent.width + spacing: 0 enabled: performanceCustom.checked HifiControlsUit.RadioButton { @@ -267,6 +268,45 @@ Flickable { Render.shadowsEnabled = renderingEffectShadows.checked; } } + HifiControlsUit.CheckBox { + id: renderingEffectHaze + checked: Render.hazeEnabled + boxSize: 16 + text: "Haze" + spacing: -1 + colorScheme: hifi.colorSchemes.dark + anchors.left: parent.left + anchors.top: renderingEffectShadows.bottom + onCheckedChanged: { + Render.hazeEnabled = renderingEffectHaze.checked; + } + } + HifiControlsUit.CheckBox { + id: renderingEffectBloom + checked: Render.bloomEnabled + boxSize: 16 + text: "Bloom" + spacing: -1 + colorScheme: hifi.colorSchemes.dark + anchors.left: parent.left + anchors.top: renderingEffectHaze.bottom + onCheckedChanged: { + Render.bloomEnabled = renderingEffectBloom.checked; + } + } + HifiControlsUit.CheckBox { + id: renderingEffectAO + checked: Render.ambientOcclusionEnabled + boxSize: 16 + text: "AO" + spacing: -1 + colorScheme: hifi.colorSchemes.dark + anchors.left: parent.left + anchors.top: renderingEffectBloom.bottom + onCheckedChanged: { + Render.ambientOcclusionEnabled = renderingEffectAO.checked; + } + } HifiControlsUit.CheckBox { id: renderingEffectLocalLights enabled: false @@ -277,41 +317,11 @@ Flickable { spacing: -1 colorScheme: hifi.colorSchemes.dark anchors.left: parent.left - anchors.top: renderingEffectShadows.bottom + anchors.top: renderingEffectAO.bottom //onCheckedChanged: { // Render.localLightsEnabled = renderingEffectLocalLightsEnabled.checked; //} } - HifiControlsUit.CheckBox { - id: renderingEffectFog - enabled: false - //checked: Render.fogEnabled - checked: renderingEffectsEnabled.checked - boxSize: 16 - text: "Fog" - spacing: -1 - colorScheme: hifi.colorSchemes.dark - anchors.left: parent.left - anchors.top: renderingEffectLocalLights.bottom - //onCheckedChanged: { - // Render.fogEnabled = renderingEffectFogEnabled.checked; - //} - } - HifiControlsUit.CheckBox { - id: renderingEffectBloom - enabled: false - //checked: Render.bloomEnabled - checked: renderingEffectsEnabled.checked - boxSize: 16 - text: "Bloom" - spacing: -1 - colorScheme: hifi.colorSchemes.dark - anchors.left: parent.left - anchors.top: renderingEffectFog.bottom - //onCheckedChanged: { - // Render.bloomEnabled = renderingEffectBloomEnabled.checked; - //} - } } } } @@ -811,6 +821,42 @@ Flickable { } } + ColumnLayout { + Layout.topMargin: 20 + Layout.preferredWidth: parent.width + spacing: 0 + + Item { + Layout.preferredWidth: parent.width + Layout.preferredHeight: 35 + + HifiStylesUit.RalewayRegular { + id: proceduralMaterialsHeader + text: "Procedural Materials" + anchors.left: parent.left + anchors.top: parent.top + width: 150 + height: parent.height + size: 16 + color: "#FFFFFF" + } + + HifiControlsUit.CheckBox { + id: renderingEffectProceduralMaterials + checked: Render.proceduralMaterialsEnabled + boxSize: 16 + spacing: -1 + colorScheme: hifi.colorSchemes.dark + anchors.left: proceduralMaterialsHeader.right + anchors.leftMargin: 20 + anchors.top: parent.top + onCheckedChanged: { + Render.proceduralMaterialsEnabled = renderingEffectProceduralMaterials.checked; + } + } + } + } + } } diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7017f2a083..2f2c31e27d 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -538,10 +538,8 @@ Menu::Menu() { addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ComputeBlendshapes, 0, true, DependencyManager::get().data(), SLOT(setComputeBlendshapes(bool))); - action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false); - connect(action, &QAction::triggered, [action] { - ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); - }); + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, RenderScriptingInterface::getInstance()->getProceduralMaterialsEnabled(), + RenderScriptingInterface::getInstance(), SLOT(setProceduralMaterialsEnabled(bool))); { auto drawStatusConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.DrawStatus"); diff --git a/interface/src/PerformanceManager.cpp b/interface/src/PerformanceManager.cpp index fc67de219b..2307edc656 100644 --- a/interface/src/PerformanceManager.cpp +++ b/interface/src/PerformanceManager.cpp @@ -95,11 +95,13 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::RenderMethod::DEFERRED : RenderScriptingInterface::RenderMethod::FORWARD ) ); - RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommendedPpiScale); - RenderScriptingInterface::getInstance()->setShadowsEnabled(true); - qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); + RenderScriptingInterface::getInstance()->setHazeEnabled(true); + RenderScriptingInterface::getInstance()->setBloomEnabled(true); + RenderScriptingInterface::getInstance()->setAmbientOcclusionEnabled(true); + RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommendedPpiScale); + qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); DependencyManager::get()->setWorldDetailQuality(WORLD_DETAIL_MEDIUM); break; @@ -108,30 +110,39 @@ void PerformanceManager::applyPerformancePreset(PerformanceManager::PerformanceP RenderScriptingInterface::RenderMethod::DEFERRED : RenderScriptingInterface::RenderMethod::FORWARD)); + RenderScriptingInterface::getInstance()->setShadowsEnabled(false); + RenderScriptingInterface::getInstance()->setHazeEnabled(true); + RenderScriptingInterface::getInstance()->setBloomEnabled(true); + RenderScriptingInterface::getInstance()->setAmbientOcclusionEnabled(false); RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommendedPpiScale); - RenderScriptingInterface::getInstance()->setShadowsEnabled(false); qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); DependencyManager::get()->setWorldDetailQuality(WORLD_DETAIL_MEDIUM); break; case PerformancePreset::LOW: RenderScriptingInterface::getInstance()->setRenderMethod(RenderScriptingInterface::RenderMethod::FORWARD); - RenderScriptingInterface::getInstance()->setShadowsEnabled(false); - qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); + RenderScriptingInterface::getInstance()->setShadowsEnabled(false); + RenderScriptingInterface::getInstance()->setHazeEnabled(true); + RenderScriptingInterface::getInstance()->setBloomEnabled(false); + RenderScriptingInterface::getInstance()->setAmbientOcclusionEnabled(false); RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommendedPpiScale); + qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::REALTIME); DependencyManager::get()->setWorldDetailQuality(WORLD_DETAIL_LOW); break; case PerformancePreset::LOW_POWER: RenderScriptingInterface::getInstance()->setRenderMethod(RenderScriptingInterface::RenderMethod::FORWARD); - RenderScriptingInterface::getInstance()->setShadowsEnabled(false); - qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::ECO); + RenderScriptingInterface::getInstance()->setShadowsEnabled(false); + RenderScriptingInterface::getInstance()->setHazeEnabled(false); + RenderScriptingInterface::getInstance()->setBloomEnabled(false); + RenderScriptingInterface::getInstance()->setAmbientOcclusionEnabled(false); RenderScriptingInterface::getInstance()->setViewportResolutionScale(recommendedPpiScale); + qApp->getRefreshRateManager().setRefreshRateProfile(RefreshRateManager::RefreshRateProfile::ECO); DependencyManager::get()->setWorldDetailQuality(WORLD_DETAIL_LOW); break; diff --git a/interface/src/scripting/RenderScriptingInterface.cpp b/interface/src/scripting/RenderScriptingInterface.cpp index 47f772b4bc..e11bf32702 100644 --- a/interface/src/scripting/RenderScriptingInterface.cpp +++ b/interface/src/scripting/RenderScriptingInterface.cpp @@ -16,6 +16,8 @@ #include #include "ScreenName.h" +#include + STATIC_SCRIPT_TYPES_INITIALIZER((+[](ScriptManager* manager){ auto scriptEngine = manager->engine().get(); @@ -43,16 +45,17 @@ RenderScriptingInterface::RenderScriptingInterface() { }); } - void RenderScriptingInterface::loadSettings() { _renderSettingLock.withReadLock([&] { - _renderMethod = (_renderMethodSetting.get()); - _shadowsEnabled = (_shadowsEnabledSetting.get()); - _ambientOcclusionEnabled = (_ambientOcclusionEnabledSetting.get()); - //_antialiasingMode = (_antialiasingModeSetting.get()); + _renderMethod = _renderMethodSetting.get(); + _shadowsEnabled = _shadowsEnabledSetting.get(); + _hazeEnabled = _hazeEnabledSetting.get(); + _bloomEnabled = _bloomEnabledSetting.get(); + _ambientOcclusionEnabled = _ambientOcclusionEnabledSetting.get(); + _proceduralMaterialsEnabled = _proceduralMaterialsEnabledSetting.get(); _antialiasingMode = static_cast(_antialiasingModeSetting.get()); - _viewportResolutionScale = (_viewportResolutionScaleSetting.get()); - _fullScreenScreen = (_fullScreenScreenSetting.get()); + _viewportResolutionScale = _viewportResolutionScaleSetting.get(); + _fullScreenScreen = _fullScreenScreenSetting.get(); }); // If full screen screen is not initialized, or set to an invalid value, @@ -65,7 +68,10 @@ void RenderScriptingInterface::loadSettings() { forceRenderMethod((RenderMethod)_renderMethod); forceShadowsEnabled(_shadowsEnabled); + forceHazeEnabled(_hazeEnabled); + forceBloomEnabled(_bloomEnabled); forceAmbientOcclusionEnabled(_ambientOcclusionEnabled); + forceProceduralMaterialsEnabled(_proceduralMaterialsEnabled); forceAntialiasingMode(_antialiasingMode); forceViewportResolutionScale(_viewportResolutionScale); } @@ -118,6 +124,33 @@ QStringList RenderScriptingInterface::getRenderMethodNames() const { return refrenderMethodNames; } +void recursivelyUpdateLightingModel(const QString& parentTaskName, std::function updateLambda, int depth = -1) { + if (depth == -1) { + auto secondaryLightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderSecondView.LightingModel"); + if (secondaryLightingModelConfig) { + updateLambda(secondaryLightingModelConfig); + } + + auto mainLightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.LightingModel"); + if (mainLightingModelConfig) { + updateLambda(mainLightingModelConfig); + } + + recursivelyUpdateLightingModel("RenderMainView", updateLambda, depth + 1); + } else if (depth == RenderMirrorTask::MAX_MIRROR_DEPTH) { + return; + } + + for (size_t mirrorIndex = 0; mirrorIndex < RenderMirrorTask::MAX_MIRRORS_PER_LEVEL; mirrorIndex++) { + std::string mirrorTaskString = parentTaskName.toStdString() + ".RenderMirrorView" + std::to_string(mirrorIndex) + "Depth" + std::to_string(depth); + auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig(mirrorTaskString + ".LightingModel"); + if (lightingModelConfig) { + updateLambda(lightingModelConfig); + recursivelyUpdateLightingModel(QString::fromStdString(mirrorTaskString), updateLambda, depth + 1); + } + } +} + bool RenderScriptingInterface::getShadowsEnabled() const { return _shadowsEnabled; } @@ -134,18 +167,49 @@ void RenderScriptingInterface::forceShadowsEnabled(bool enabled) { _shadowsEnabled = (enabled); _shadowsEnabledSetting.set(enabled); - auto renderConfig = qApp->getRenderEngine()->getConfiguration(); - assert(renderConfig); - auto lightingModelConfig = renderConfig->getConfig("RenderMainView.LightingModel"); - if (lightingModelConfig) { - Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled); - lightingModelConfig->setShadow(enabled); - } - auto secondaryLightingModelConfig = renderConfig->getConfig("RenderSecondView.LightingModel"); - if (secondaryLightingModelConfig) { - Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled); - secondaryLightingModelConfig->setShadow(enabled); - } + Menu::getInstance()->setIsOptionChecked(MenuOption::Shadows, enabled); + + recursivelyUpdateLightingModel("", [enabled] (MakeLightingModelConfig *config) { config->setShadow(enabled); }); + }); +} + +bool RenderScriptingInterface::getHazeEnabled() const { + return _hazeEnabled; +} + +void RenderScriptingInterface::setHazeEnabled(bool enabled) { + if (_hazeEnabled != enabled) { + forceHazeEnabled(enabled); + emit settingsChanged(); + } +} + +void RenderScriptingInterface::forceHazeEnabled(bool enabled) { + _renderSettingLock.withWriteLock([&] { + _hazeEnabled = (enabled); + _hazeEnabledSetting.set(enabled); + + recursivelyUpdateLightingModel("", [enabled] (MakeLightingModelConfig *config) { config->setHaze(enabled); }); + }); +} + +bool RenderScriptingInterface::getBloomEnabled() const { + return _bloomEnabled; +} + +void RenderScriptingInterface::setBloomEnabled(bool enabled) { + if (_bloomEnabled != enabled) { + forceBloomEnabled(enabled); + emit settingsChanged(); + } +} + +void RenderScriptingInterface::forceBloomEnabled(bool enabled) { + _renderSettingLock.withWriteLock([&] { + _bloomEnabled = (enabled); + _bloomEnabledSetting.set(enabled); + + recursivelyUpdateLightingModel("", [enabled] (MakeLightingModelConfig *config) { config->setBloom(enabled); }); }); } @@ -165,11 +229,30 @@ void RenderScriptingInterface::forceAmbientOcclusionEnabled(bool enabled) { _ambientOcclusionEnabled = (enabled); _ambientOcclusionEnabledSetting.set(enabled); - auto lightingModelConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.LightingModel"); - if (lightingModelConfig) { - Menu::getInstance()->setIsOptionChecked(MenuOption::AmbientOcclusion, enabled); - lightingModelConfig->setAmbientOcclusion(enabled); - } + Menu::getInstance()->setIsOptionChecked(MenuOption::AmbientOcclusion, enabled); + + recursivelyUpdateLightingModel("", [enabled] (MakeLightingModelConfig *config) { config->setAmbientOcclusion(enabled); }); + }); +} + +bool RenderScriptingInterface::getProceduralMaterialsEnabled() const { + return _proceduralMaterialsEnabled; +} + +void RenderScriptingInterface::setProceduralMaterialsEnabled(bool enabled) { + if (_proceduralMaterialsEnabled != enabled) { + forceProceduralMaterialsEnabled(enabled); + emit settingsChanged(); + } +} + +void RenderScriptingInterface::forceProceduralMaterialsEnabled(bool enabled) { + _renderSettingLock.withWriteLock([&] { + _proceduralMaterialsEnabled = (enabled); + _proceduralMaterialsEnabledSetting.set(enabled); + + Menu::getInstance()->setIsOptionChecked(MenuOption::MaterialProceduralShaders, enabled); + ModelMeshPartPayload::enableMaterialProceduralShaders = enabled; }); } @@ -209,44 +292,51 @@ void setAntialiasingModeForView(AntialiasingConfig::Mode mode, JitterSampleConfi } } -void RenderScriptingInterface::forceAntialiasingMode(AntialiasingConfig::Mode mode) { - _renderSettingLock.withWriteLock([&] { - _antialiasingMode = mode; +void recursivelyUpdateAntialiasingMode(const QString& parentTaskName, AntialiasingConfig::Mode mode, int depth = -1) { + if (depth == -1) { + auto secondViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderSecondView.JitterCam"); + auto secondViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderSecondView.Antialiasing"); + if (secondViewJitterCamConfig && secondViewAntialiasingConfig) { + setAntialiasingModeForView(mode, secondViewJitterCamConfig, secondViewAntialiasingConfig); + } auto mainViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.JitterCam"); auto mainViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderMainView.Antialiasing"); - auto secondViewJitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderSecondView.JitterCam"); - auto secondViewAntialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig("RenderSecondView.Antialiasing"); - if (mode != AntialiasingConfig::Mode::NONE - && mode != AntialiasingConfig::Mode::TAA - && mode != AntialiasingConfig::Mode::FXAA) { - _antialiasingMode = AntialiasingConfig::Mode::NONE; - } if (mainViewJitterCamConfig && mainViewAntialiasingConfig) { setAntialiasingModeForView( mode, mainViewJitterCamConfig, mainViewAntialiasingConfig); } - if (secondViewJitterCamConfig && secondViewAntialiasingConfig) { - setAntialiasingModeForView( mode, secondViewJitterCamConfig, secondViewAntialiasingConfig); + + recursivelyUpdateAntialiasingMode("RenderMainView", mode, depth + 1); + } else if (depth == RenderMirrorTask::MAX_MIRROR_DEPTH) { + return; + } + + for (size_t mirrorIndex = 0; mirrorIndex < RenderMirrorTask::MAX_MIRRORS_PER_LEVEL; mirrorIndex++) { + std::string mirrorTaskString = parentTaskName.toStdString() + ".RenderMirrorView" + std::to_string(mirrorIndex) + "Depth" + std::to_string(depth); + auto jitterCamConfig = qApp->getRenderEngine()->getConfiguration()->getConfig(mirrorTaskString + ".JitterCam"); + auto antialiasingConfig = qApp->getRenderEngine()->getConfiguration()->getConfig(mirrorTaskString + ".Antialiasing"); + if (jitterCamConfig && antialiasingConfig) { + setAntialiasingModeForView(mode, jitterCamConfig, antialiasingConfig); + recursivelyUpdateAntialiasingMode(QString::fromStdString(mirrorTaskString), mode, depth + 1); } - - _antialiasingModeSetting.set(_antialiasingMode); - }); -} - - -float RenderScriptingInterface::getViewportResolutionScale() const { - return _viewportResolutionScale; -} - -void RenderScriptingInterface::setViewportResolutionScale(float scale) { - if (_viewportResolutionScale != scale) { - forceViewportResolutionScale(scale); - emit settingsChanged(); } } +void RenderScriptingInterface::forceAntialiasingMode(AntialiasingConfig::Mode mode) { + if ((int)mode < 0 || mode >= AntialiasingConfig::Mode::MODE_COUNT) { + mode = AntialiasingConfig::Mode::NONE; + } + + _renderSettingLock.withWriteLock([&] { + _antialiasingMode = mode; + _antialiasingModeSetting.set(_antialiasingMode); + + recursivelyUpdateAntialiasingMode("", _antialiasingMode); + }); +} + void RenderScriptingInterface::setVerticalFieldOfView(float fieldOfView) { - if (getViewportResolutionScale() != fieldOfView) { + if (qApp->getFieldOfView() != fieldOfView) { qApp->setFieldOfView(fieldOfView); emit settingsChanged(); } @@ -286,6 +376,16 @@ QString RenderScriptingInterface::getFullScreenScreen() const { return _fullScreenScreen; } +float RenderScriptingInterface::getViewportResolutionScale() const { + return _viewportResolutionScale; +} + +void RenderScriptingInterface::setViewportResolutionScale(float scale) { + if (_viewportResolutionScale != scale) { + forceViewportResolutionScale(scale); + emit settingsChanged(); + } +} void RenderScriptingInterface::forceViewportResolutionScale(float scale) { // just not negative values or zero diff --git a/interface/src/scripting/RenderScriptingInterface.h b/interface/src/scripting/RenderScriptingInterface.h index 73ef077c3c..56b474cf31 100644 --- a/interface/src/scripting/RenderScriptingInterface.h +++ b/interface/src/scripting/RenderScriptingInterface.h @@ -29,8 +29,12 @@ * * @property {Render.RenderMethod} renderMethod - The render method being used. * @property {boolean} shadowsEnabled - true if shadows are enabled, false if they're disabled. + * @property {boolean} hazeEnabled - true if haze (fog) is enabled, false if it's disabled. + * @property {boolean} bloomEnabled - true if bloom is enabled, false if it's disabled. * @property {boolean} ambientOcclusionEnabled - true if ambient occlusion is enabled, false if it's * disabled. + * @property {boolean} proceduralMaterialsEnabled - true if procedural shaders are enabled, false if + * they're disabled. * @property {integer} antialiasingMode - The active anti-aliasing mode. * @property {number} viewportResolutionScale - The view port resolution scale, > 0.0. */ @@ -38,7 +42,10 @@ class RenderScriptingInterface : public QObject { Q_OBJECT Q_PROPERTY(RenderMethod renderMethod READ getRenderMethod WRITE setRenderMethod NOTIFY settingsChanged) Q_PROPERTY(bool shadowsEnabled READ getShadowsEnabled WRITE setShadowsEnabled NOTIFY settingsChanged) + Q_PROPERTY(bool hazeEnabled READ getHazeEnabled WRITE setHazeEnabled NOTIFY settingsChanged) + Q_PROPERTY(bool bloomEnabled READ getBloomEnabled WRITE setBloomEnabled NOTIFY settingsChanged) Q_PROPERTY(bool ambientOcclusionEnabled READ getAmbientOcclusionEnabled WRITE setAmbientOcclusionEnabled NOTIFY settingsChanged) + Q_PROPERTY(bool proceduralMaterialsEnabled READ getProceduralMaterialsEnabled WRITE setProceduralMaterialsEnabled NOTIFY settingsChanged) Q_PROPERTY(AntialiasingConfig::Mode antialiasingMode READ getAntialiasingMode WRITE setAntialiasingMode NOTIFY settingsChanged) Q_PROPERTY(float viewportResolutionScale READ getViewportResolutionScale WRITE setViewportResolutionScale NOTIFY settingsChanged) Q_PROPERTY(float verticalFieldOfView READ getVerticalFieldOfView WRITE setVerticalFieldOfView NOTIFY settingsChanged) @@ -134,6 +141,34 @@ public slots: */ void setShadowsEnabled(bool enabled); + /*@jsdoc + * Gets whether or not haze is enabled. + * @function Render.getHazeEnabled + * @returns {boolean} true if haze is enabled, false if it's disabled. + */ + bool getHazeEnabled() const; + + /*@jsdoc + * Sets whether or not haze is enabled. + * @function Render.setHazeEnabled + * @param {boolean} enabled - true to enable haze, false to disable. + */ + void setHazeEnabled(bool enabled); + + /*@jsdoc + * Gets whether or not bloom is enabled. + * @function Render.getBloomEnabled + * @returns {boolean} true if bloom is enabled, false if it's disabled. + */ + bool getBloomEnabled() const; + + /*@jsdoc + * Sets whether or not bloom is enabled. + * @function Render.setBloomEnabled + * @param {boolean} enabled - true to enable bloom, false to disable. + */ + void setBloomEnabled(bool enabled); + /*@jsdoc * Gets whether or not ambient occlusion is enabled. * @function Render.getAmbientOcclusionEnabled @@ -148,6 +183,20 @@ public slots: */ void setAmbientOcclusionEnabled(bool enabled); + /*@jsdoc + * Gets whether or not procedural materials are enabled. + * @function Render.getProceduralMaterialsEnabled + * @returns {boolean} true if procedural materials are enabled, false if they're disabled. + */ + bool getProceduralMaterialsEnabled() const; + + /*@jsdoc + * Sets whether or not procedural materials are enabled. + * @function Render.setProceduralMaterialsEnabled + * @param {boolean} enabled - true to enable procedural materials, false to disable. + */ + void setProceduralMaterialsEnabled(bool enabled); + /*@jsdoc * Gets the active anti-aliasing mode. * @function Render.getAntialiasingMode @@ -235,7 +284,10 @@ private: // Runtime value of each settings int _renderMethod { RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED }; bool _shadowsEnabled { true }; + bool _hazeEnabled { true }; + bool _bloomEnabled { true }; bool _ambientOcclusionEnabled { true }; + bool _proceduralMaterialsEnabled { true }; AntialiasingConfig::Mode _antialiasingMode { AntialiasingConfig::Mode::NONE }; float _viewportResolutionScale { 1.0f }; QString _fullScreenScreen; @@ -243,8 +295,10 @@ private: // Actual settings saved on disk Setting::Handle _renderMethodSetting { "renderMethod", RENDER_FORWARD ? render::Args::RenderMethod::FORWARD : render::Args::RenderMethod::DEFERRED }; Setting::Handle _shadowsEnabledSetting { "shadowsEnabled", true }; + Setting::Handle _hazeEnabledSetting { "hazeEnabled", true }; + Setting::Handle _bloomEnabledSetting { "bloomEnabled", true }; Setting::Handle _ambientOcclusionEnabledSetting { "ambientOcclusionEnabled", true }; - //Setting::Handle _antialiasingModeSetting { "antialiasingMode", AntialiasingConfig::Mode::TAA }; + Setting::Handle _proceduralMaterialsEnabledSetting { "proceduralMaterialsEnabled", true }; Setting::Handle _antialiasingModeSetting { "antialiasingMode", AntialiasingConfig::Mode::NONE }; Setting::Handle _viewportResolutionScaleSetting { "viewportResolutionScale", 1.0f }; Setting::Handle _fullScreenScreenSetting { "fullScreenScreen", "" }; @@ -252,7 +306,10 @@ private: // Force assign both setting AND runtime value to the parameter value void forceRenderMethod(RenderMethod renderMethod); void forceShadowsEnabled(bool enabled); + void forceHazeEnabled(bool enabled); + void forceBloomEnabled(bool enabled); void forceAmbientOcclusionEnabled(bool enabled); + void forceProceduralMaterialsEnabled(bool enabled); void forceAntialiasingMode(AntialiasingConfig::Mode mode); void forceViewportResolutionScale(float scale); diff --git a/libraries/render-utils/src/DrawHaze.cpp b/libraries/render-utils/src/DrawHaze.cpp index 012161ec03..71845be731 100644 --- a/libraries/render-utils/src/DrawHaze.cpp +++ b/libraries/render-utils/src/DrawHaze.cpp @@ -31,6 +31,10 @@ namespace gr { using graphics::slot::buffer::Buffer; } +gpu::PipelinePointer DrawHaze::_hazePipeline = nullptr; +gpu::PipelinePointer DrawHaze::_separateHazePipeline = nullptr; +gpu::PipelinePointer DrawHaze::_separateHazeBackgroundPipeline = nullptr; + void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inputs& inputs) { const auto hazeFrame = inputs.get0(); const auto& hazeStage = renderContext->args->_scene->getStage(); @@ -55,15 +59,29 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu if (!_hazePipeline) { gpu::ShaderPointer program = gpu::Shader::createProgram(shader::render_utils::program::haze); - gpu::StatePointer state = std::make_shared(); - state->setBlendFunction(true, - gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, - gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + auto createState = []() { + gpu::StatePointer state = std::make_shared(); + state->setBlendFunction(true, + gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA, + gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE); + return state; + }; // Mask out haze on the tablet - PrepareStencil::testMask(*state); - _hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + auto hazeState = createState(); + PrepareStencil::testMask(*hazeState); + _hazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, hazeState)); + + // For our separated passes, we perform one pass on anything marked shape, and one on just the background + auto hazeSeparatedState = createState(); + PrepareStencil::testShape(*hazeSeparatedState); + _separateHazePipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, hazeSeparatedState)); + + gpu::ShaderPointer backgroundProgram = gpu::Shader::createProgram(shader::render_utils::program::haze_background); + auto hazeBackgroundSeparatedState = createState(); + PrepareStencil::testBackground(*hazeBackgroundSeparatedState); + _separateHazeBackgroundPipeline = gpu::PipelinePointer(gpu::Pipeline::create(backgroundProgram, hazeBackgroundSeparatedState)); } auto outputFramebufferSize = glm::ivec2(outputBuffer->getSize()); @@ -77,7 +95,6 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu batch.resetViewTransform(); batch.setModelTransform(gpu::Framebuffer::evalSubregionTexcoordTransform(outputFramebufferSize, args->_viewport)); - batch.setPipeline(_hazePipeline); batch.setUniformBuffer(graphics::slot::buffer::Buffer::HazeParams, haze->getHazeParametersBuffer()); batch.setUniformBuffer(ru::Buffer::DeferredFrameTransform, transformBuffer->getFrameTransformBuffer()); @@ -92,6 +109,15 @@ void DrawHaze::run(const render::RenderContextPointer& renderContext, const Inpu } } - batch.draw(gpu::TRIANGLE_STRIP, 4); + if (!_separateBackgroundPass) { + batch.setPipeline(_hazePipeline); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } else { + batch.setPipeline(_separateHazePipeline); + batch.draw(gpu::TRIANGLE_STRIP, 4); + + batch.setPipeline(_separateHazeBackgroundPipeline); + batch.draw(gpu::TRIANGLE_STRIP, 4); + } }); } diff --git a/libraries/render-utils/src/DrawHaze.h b/libraries/render-utils/src/DrawHaze.h index 9236543068..82e8beaa9b 100644 --- a/libraries/render-utils/src/DrawHaze.h +++ b/libraries/render-utils/src/DrawHaze.h @@ -33,10 +33,16 @@ public: using Inputs = render::VaryingSet6; using JobModel = render::Job::ModelI; + DrawHaze(bool separateBackgroundPass) : _separateBackgroundPass(separateBackgroundPass) {} + void run(const render::RenderContextPointer& renderContext, const Inputs& inputs); private: - gpu::PipelinePointer _hazePipeline; + bool _separateBackgroundPass { false }; + + static gpu::PipelinePointer _hazePipeline; + static gpu::PipelinePointer _separateHazePipeline; + static gpu::PipelinePointer _separateHazeBackgroundPipeline; }; #endif // hifi_render_utils_DrawHaze_h diff --git a/libraries/render-utils/src/Haze.slf b/libraries/render-utils/src/Haze.slf index 899f36b8eb..9be64e7695 100644 --- a/libraries/render-utils/src/Haze.slf +++ b/libraries/render-utils/src/Haze.slf @@ -21,10 +21,16 @@ <@include graphics/Haze.slh@> +<@if not HIFI_USE_BACKGROUND@> LAYOUT(binding=RENDER_UTILS_TEXTURE_HAZE_LINEAR_DEPTH) uniform sampler2D linearDepthMap; +<@endif@> vec4 unpackPositionFromZeye(vec2 texcoord) { +<@if not HIFI_USE_BACKGROUND@> float Zeye = -texture(linearDepthMap, texcoord).x; +<@else@> + float Zeye = 1.0; // We just want to get the direction first +<@endif@> float check = float(isStereo()); float check2 = check * float(texcoord.x > 0.5); @@ -44,8 +50,14 @@ void main(void) { } vec4 fragPositionES = unpackPositionFromZeye(varTexCoord0); - mat4 viewInverse = getViewInverse(); + +<@if HIFI_USE_BACKGROUND@> + // We choose an arbitrary large number > BLEND_DISTANCE in Haze.slh + const float SKYBOX_DISTANCE = 32000.0; + fragPositionES = vec4(-SKYBOX_DISTANCE * normalize(fragPositionES.xyz), 1.0); +<@endif@> + vec4 fragPositionWS = viewInverse * fragPositionES; vec4 eyePositionWS = viewInverse[3]; diff --git a/libraries/render-utils/src/LightingModel.h b/libraries/render-utils/src/LightingModel.h index 5298fb2ceb..c5811b1110 100644 --- a/libraries/render-utils/src/LightingModel.h +++ b/libraries/render-utils/src/LightingModel.h @@ -197,6 +197,8 @@ public: bool isAmbientOcclusionEnabled() const { return enableAmbientOcclusion; } void setShadow(bool enable) { enableShadow = enable; emit dirty(); } bool isShadowEnabled() const { return enableShadow; } + void setHaze(bool enable) { enableHaze = enable; emit dirty(); } + void setBloom(bool enable) { enableBloom = enable; emit dirty(); } signals: void dirty(); diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 4bcfc9663b..b8bc9a542b 100644 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -225,7 +225,7 @@ void RenderDeferredTask::build(JobModel& task, const render::Varying& input, ren task.addJob("DrawBackgroundDeferred", backgroundInputs); const auto drawHazeInputs = render::Varying(DrawHaze::Inputs(hazeFrame, lightingFramebuffer, linearDepthTarget, deferredFrameTransform, lightingModel, lightFrame)); - task.addJob("DrawHazeDeferred", drawHazeInputs); + task.addJob("DrawHazeDeferred", drawHazeInputs, depth > 0); // Render transparent objects forward in LightingBuffer const auto transparentsInputs = RenderTransparentDeferred::Inputs(transparents, hazeFrame, lightFrame, lightingModel, lightClusters, shadowFrame, jitter).asVarying(); diff --git a/libraries/render-utils/src/render-utils/haze.slp b/libraries/render-utils/src/render-utils/haze.slp index 805b855c8d..7cfd358e3d 100644 --- a/libraries/render-utils/src/render-utils/haze.slp +++ b/libraries/render-utils/src/render-utils/haze.slp @@ -1,2 +1,3 @@ VERTEX gpu::vertex::DrawViewportQuadTransformTexcoord FRAGMENT Haze +DEFINES background:f