diff options
author | Christian Strømme <christian.stromme@qt.io> | 2024-04-10 15:15:49 +0200 |
---|---|---|
committer | Tim Jenssen <tim.jenssen@qt.io> | 2024-04-24 15:24:35 +0000 |
commit | cd7e89070579dd220fbc64c48f138585e55b6b8d (patch) | |
tree | ff72f11bb6ef9d4319eb1574088ce15c29af0338 | |
parent | c8bcda86bde2c9bcad8718244f5894bc6712ff98 (diff) |
Enable usage of the IBL probe exposure with the ExtendedSceneEnvironment6.7-experimental
Since the ExtendedSceneEnvironment is not using the built-in tonemapping of the
engine but instead uses its own custom tonemapping code, the internal tonemapping,
and therefore the exposure, was disabled. With this change the exposure and tonemapping
is decoupled when used with custom tonemapping code (internal only),
which allows the ExtendedSceneEnvironment to force the exposure values
to be added to the output.
Fixes: QTBUG-123846
Change-Id: I00cbdd85f4e3d3d58afff7899a5ca2ce61365a55
Reviewed-by: Tim Jenssen <tim.jenssen@qt.io>
-rw-r--r-- | examples/quick3d/sceneeffects/SettingsPage.qml | 13 | ||||
-rw-r--r-- | src/quick3d/qquick3dscenerenderer_p.h | 8 | ||||
-rw-r--r-- | src/runtimerender/CMakeLists.txt | 35 | ||||
-rw-r--r-- | src/runtimerender/graphobjects/qssgrenderlayer_p.h | 5 | ||||
-rw-r--r-- | src/runtimerender/qssgrendershadercache.cpp | 4 | ||||
-rw-r--r-- | src/runtimerender/qssgrendershadercache_p.h | 3 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssglayerrenderdata.cpp | 3 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssglayerrenderdata_p.h | 2 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp | 7 | ||||
-rw-r--r-- | src/runtimerender/rendererimpl/qssgrenderpass.cpp | 3 | ||||
-rw-r--r-- | src/runtimerender/res/effectlib/tonemapping.glsllib | 8 | ||||
-rw-r--r-- | tests/baseline/data/view3d/SceneEffecsExposure.qml | 107 |
12 files changed, 189 insertions, 9 deletions
diff --git a/examples/quick3d/sceneeffects/SettingsPage.qml b/examples/quick3d/sceneeffects/SettingsPage.qml index 27afe9f7..1867951b 100644 --- a/examples/quick3d/sceneeffects/SettingsPage.qml +++ b/examples/quick3d/sceneeffects/SettingsPage.qml @@ -207,6 +207,19 @@ Page { } Label { + text: "Probe Exposure (" + (toolPage.sceneEnvironment.probeExposure).toFixed(2) + ")" + Layout.fillWidth: true + } + Slider { + Layout.fillWidth: true + from: 0.0 + to: 10.0 + value: toolPage.sceneEnvironment.probeExposure + onValueChanged: + toolPage.sceneEnvironment.probeExposure = value + } + + Label { enabled: !(toolPage.sceneEnvironment.tonemapMode === SceneEnvironment.TonemapModeLinear || toolPage.sceneEnvironment.tonemapMode === SceneEnvironment.TonemapModeNone) text: "White Point (" + (toolPage.sceneEnvironment.whitePoint).toFixed(2) + ")" Layout.fillWidth: true diff --git a/src/quick3d/qquick3dscenerenderer_p.h b/src/quick3d/qquick3dscenerenderer_p.h index 33bafdd0..c22c08ec 100644 --- a/src/quick3d/qquick3dscenerenderer_p.h +++ b/src/quick3d/qquick3dscenerenderer_p.h @@ -48,8 +48,12 @@ public: static QSSGRenderLayer::TonemapMode getTonemapMode(const QQuick3DSceneEnvironment &environment) { - return environment.useBuiltinTonemapper() ? QSSGRenderLayer::TonemapMode(environment.tonemapMode()) - : QSSGRenderLayer::TonemapMode::None; + if (environment.useBuiltinTonemapper()) + return QSSGRenderLayer::TonemapMode(environment.tonemapMode()); + + // Special case for the extend scene environment... + return (environment.tonemapMode() != QQuick3DSceneEnvironment::QQuick3DEnvironmentTonemapModes::TonemapModeNone) ? QSSGRenderLayer::TonemapMode::Custom + : QSSGRenderLayer::TonemapMode::None; } protected: diff --git a/src/runtimerender/CMakeLists.txt b/src/runtimerender/CMakeLists.txt index f05d78c5..0c194fcc 100644 --- a/src/runtimerender/CMakeLists.txt +++ b/src/runtimerender/CMakeLists.txt @@ -332,6 +332,41 @@ qt_internal_add_shaders(Quick3DRuntimeRender "res_shaders_skybox_rgbe_none" DEFINES QSSG_ENABLE_RGBE_LIGHT_PROBE=1 ) +qt_internal_add_shaders(Quick3DRuntimeRender "res_shaders_skybox_hdr_custom" + SILENT + PRECOMPILE + OPTIMIZED + MULTIVIEW + GLSL "300es,150" + PREFIX + "/" + FILES + res/rhishaders/skybox.vert + res/rhishaders/skybox.frag + OUTPUTS + res/rhishaders/skybox_hdr_custom.vert.qsb + res/rhishaders/skybox_hdr_custom.frag.qsb + DEFINES + QSSG_FORCE_IBL_EXPOSURE=1 +) +qt_internal_add_shaders(Quick3DRuntimeRender "res_shaders_skybox_rgbe_custom" + SILENT + PRECOMPILE + OPTIMIZED + MULTIVIEW + GLSL "300es,150" + PREFIX + "/" + FILES + res/rhishaders/skybox.vert + res/rhishaders/skybox.frag + OUTPUTS + res/rhishaders/skybox_rgbe_custom.vert.qsb + res/rhishaders/skybox_rgbe_custom.frag.qsb + DEFINES + QSSG_ENABLE_RGBE_LIGHT_PROBE=1 + QSSG_FORCE_IBL_EXPOSURE=1 +) qt_internal_add_shaders(Quick3DRuntimeRender "res_shaders_skybox_hdr_linear" SILENT PRECOMPILE diff --git a/src/runtimerender/graphobjects/qssgrenderlayer_p.h b/src/runtimerender/graphobjects/qssgrenderlayer_p.h index 33a223fd..73cefdd8 100644 --- a/src/runtimerender/graphobjects/qssgrenderlayer_p.h +++ b/src/runtimerender/graphobjects/qssgrenderlayer_p.h @@ -90,9 +90,10 @@ struct Q_QUICK3DRUNTIMERENDER_EXPORT QSSGRenderLayer : public QSSGRenderNode Linear, Aces, HejlDawson, - Filmic + Filmic, + Custom }; - static size_t constexpr TonemapModeCount = 5; + static size_t constexpr TonemapModeCount = 6; enum class LayerFlag { diff --git a/src/runtimerender/qssgrendershadercache.cpp b/src/runtimerender/qssgrendershadercache.cpp index b5a2e827..d022c083 100644 --- a/src/runtimerender/qssgrendershadercache.cpp +++ b/src/runtimerender/qssgrendershadercache.cpp @@ -75,7 +75,9 @@ static constexpr DefineEntry DefineTable[] { { "QSSG_ENABLE_OPAQUE_DEPTH_PRE_PASS", QSSGShaderFeatures::Feature::OpaqueDepthPrePass }, { "QSSG_ENABLE_REFLECTION_PROBE", QSSGShaderFeatures::Feature::ReflectionProbe }, { "QSSG_REDUCE_MAX_NUM_LIGHTS", QSSGShaderFeatures::Feature::ReduceMaxNumLights }, - { "QSSG_ENABLE_LIGHTMAP", QSSGShaderFeatures::Feature::Lightmap } + { "QSSG_ENABLE_LIGHTMAP", QSSGShaderFeatures::Feature::Lightmap }, + { "QSSG_DISABLE_MULTIVIEW", QSSGShaderFeatures::Feature::DisableMultiView }, + { "QSSG_FORCE_IBL_EXPOSURE", QSSGShaderFeatures::Feature::ForceIblExposure } }; static_assert(std::size(DefineTable) == QSSGShaderFeatures::Count, "Missing feature define?"); diff --git a/src/runtimerender/qssgrendershadercache_p.h b/src/runtimerender/qssgrendershadercache_p.h index a19297f0..ec66e23e 100644 --- a/src/runtimerender/qssgrendershadercache_p.h +++ b/src/runtimerender/qssgrendershadercache_p.h @@ -81,6 +81,8 @@ enum class Feature : FlagType ReflectionProbe = (1 << 21) + 13, ReduceMaxNumLights = (1 << 22) + 14, Lightmap = (1 << 23) + 15, + DisableMultiView = (1 << 24) + 16, + ForceIblExposure = (1 << 25) + 17, LastFeature }; @@ -105,6 +107,7 @@ void disableTonemapping() set(Feature::AcesTonemapping, false); set(Feature::FilmicTonemapping, false); set(Feature::HejlDawsonTonemapping, false); + set(Feature::ForceIblExposure, false); } inline friend QDebug operator<<(QDebug stream, const QSSGShaderFeatures &features) diff --git a/src/runtimerender/rendererimpl/qssglayerrenderdata.cpp b/src/runtimerender/rendererimpl/qssglayerrenderdata.cpp index 62ee1e1d..691b46c8 100644 --- a/src/runtimerender/rendererimpl/qssglayerrenderdata.cpp +++ b/src/runtimerender/rendererimpl/qssglayerrenderdata.cpp @@ -2191,6 +2191,9 @@ void QSSGLayerRenderData::prepareForRender() } else { layer.lightProbe = nullptr; } + + const bool forceIblExposureValues = (features.isSet(QSSGShaderFeatures::Feature::LightProbe) && layer.tonemapMode == QSSGRenderLayer::TonemapMode::Custom); + features.set(QSSGShaderFeatures::Feature::ForceIblExposure, forceIblExposureValues); } // Gather Spatial Nodes from Render Tree diff --git a/src/runtimerender/rendererimpl/qssglayerrenderdata_p.h b/src/runtimerender/rendererimpl/qssglayerrenderdata_p.h index 7ab3e0bf..21ae3819 100644 --- a/src/runtimerender/rendererimpl/qssglayerrenderdata_p.h +++ b/src/runtimerender/rendererimpl/qssglayerrenderdata_p.h @@ -371,6 +371,8 @@ public: tonemapMode == QSSGRenderLayer::TonemapMode::HejlDawson); features.set(QSSGShaderFeatures::Feature::FilmicTonemapping, tonemapMode == QSSGRenderLayer::TonemapMode::Filmic); + features.set(QSSGShaderFeatures::Feature::ForceIblExposure, + tonemapMode == QSSGRenderLayer::TonemapMode::Custom); } QSSGPrepContextId getOrCreateExtensionContext(const QSSGRenderExtension &ext, diff --git a/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp b/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp index e014ae5b..9137f535 100644 --- a/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp +++ b/src/runtimerender/rendererimpl/qssgrendererimplshaders_rhi.cpp @@ -77,6 +77,8 @@ static inline constexpr size_t getSkyboxIndex(QSSGRenderLayer::TonemapMode tonem return 3 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); case QSSGRenderLayer::TonemapMode::Filmic: return 4 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); + case QSSGRenderLayer::TonemapMode::Custom: + return 5 + (size_t(isRGBE) * QSSGRenderLayer::TonemapModeCount); } Q_UNREACHABLE_RETURN(0); @@ -91,11 +93,14 @@ QSSGRhiShaderPipelinePtr QSSGBuiltInRhiShaderCache::getRhiSkyBoxShader(QSSGRende "skybox_hdr_aces", "skybox_hdr_hejldawson", "skybox_hdr_filmic", + "skybox_hdr_custom", "skybox_rgbe_none", "skybox_rgbe_linear", "skybox_rgbe_aces", "skybox_rgbe_hejldawson", - "skybox_rgbe_filmic" }; + "skybox_rgbe_filmic", + "skybox_rgbe_custom", + }; const size_t skyboxIndex = getSkyboxIndex(tonemapMode, isRGBE); return getBuiltinRhiShader(QByteArray::fromRawData(variant[skyboxIndex], std::char_traits<char>::length(variant[skyboxIndex])), m_skyBoxRhiShader[skyboxIndex]); diff --git a/src/runtimerender/rendererimpl/qssgrenderpass.cpp b/src/runtimerender/rendererimpl/qssgrenderpass.cpp index e37bba61..279292e0 100644 --- a/src/runtimerender/rendererimpl/qssgrenderpass.cpp +++ b/src/runtimerender/rendererimpl/qssgrenderpass.cpp @@ -822,7 +822,8 @@ void SkyboxPass::renderPass(QSSGRenderer &renderer) // Note: We get the shader here, as the screen map pass might modify the state of // the tonemap mode. - QSSGRenderLayer::TonemapMode tonemapMode = skipTonemapping ? QSSGRenderLayer::TonemapMode::None : layer->tonemapMode; + + QSSGRenderLayer::TonemapMode tonemapMode = skipTonemapping && (layer->tonemapMode != QSSGRenderLayer::TonemapMode::Custom) ? QSSGRenderLayer::TonemapMode::None : layer->tonemapMode; const auto &shaderCache = renderer.contextInterface()->shaderCache(); auto shaderPipeline = shaderCache->getBuiltInRhiShaders().getRhiSkyBoxShader(tonemapMode, layer->skyBoxIsRgbe8); QSSG_CHECK(shaderPipeline); diff --git a/src/runtimerender/res/effectlib/tonemapping.glsllib b/src/runtimerender/res/effectlib/tonemapping.glsllib index 23d657b5..87fe6493 100644 --- a/src/runtimerender/res/effectlib/tonemapping.glsllib +++ b/src/runtimerender/res/effectlib/tonemapping.glsllib @@ -23,6 +23,9 @@ #ifndef QSSG_ENABLE_FILMIC_TONEMAPPING #define QSSG_ENABLE_FILMIC_TONEMAPPING 0 #endif +#ifndef QSSG_FORCE_IBL_EXPOSURE +#define QSSG_FORCE_IBL_EXPOSURE 0 +#endif // The following methods are described in this article: // http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html @@ -148,10 +151,11 @@ vec4 qt_tonemap(vec4 color) vec3 qt_exposure(vec3 color, float exposure) { -#if QSSG_ENABLE_ACES_TONEMAPPING || QSSG_ENABLE_HEJLDAWSON_TONEMAPPING || QSSG_ENABLE_FILMIC_TONEMAPPING || QSSG_ENABLE_LINEAR_TONEMAPPING +#if QSSG_ENABLE_ACES_TONEMAPPING || QSSG_ENABLE_HEJLDAWSON_TONEMAPPING || QSSG_ENABLE_FILMIC_TONEMAPPING || QSSG_ENABLE_LINEAR_TONEMAPPING || QSSG_FORCE_IBL_EXPOSURE return vec3(vec3(1.0) - exp(-color * exposure)); -#endif +#else return color; +#endif } #endif // TONEMAPPPING_GLSLIB diff --git a/tests/baseline/data/view3d/SceneEffecsExposure.qml b/tests/baseline/data/view3d/SceneEffecsExposure.qml new file mode 100644 index 00000000..4b56c975 --- /dev/null +++ b/tests/baseline/data/view3d/SceneEffecsExposure.qml @@ -0,0 +1,107 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Layouts +import QtQuick3D +import QtQuick3D.Helpers + +Item { + id: rootItem + width: 460 + height: 460 + + Node { + id: scene + PerspectiveCamera { + id: camera + z: 100 + } + + DirectionalLight { + + } + + Model { + source: "#Sphere" + materials: [ PrincipledMaterial { + id: sphereMaterial + baseColor: "green" + metalness: 0.5 + } ] + } + } + + GridLayout { + columns: 2 + anchors.fill: parent + + View3D { + implicitHeight: rootItem.height / 2 + implicitWidth: rootItem.width / 2 + environment: ExtendedSceneEnvironment { + backgroundMode: SceneEnvironment.SkyBox + lightProbe: Texture { + source: "../shared/maps/TestEnvironment-512.hdr" + mappingMode: Texture.LightProbe + } + + probeExposure: 0 + exposure: 1.0 + } + + importScene: scene + } + + View3D { + implicitHeight: rootItem.height / 2 + implicitWidth: rootItem.width / 2 + environment: ExtendedSceneEnvironment { + backgroundMode: SceneEnvironment.SkyBox + lightProbe: Texture { + source: "../shared/maps/TestEnvironment-512.hdr" + mappingMode: Texture.LightProbe + } + + probeExposure: 10.0 + exposure: 1.0 + } + + importScene: scene + } + + View3D { + implicitHeight: rootItem.height / 2 + implicitWidth: rootItem.width / 2 + environment: ExtendedSceneEnvironment { + backgroundMode: SceneEnvironment.SkyBox + lightProbe: Texture { + source: "../shared/maps/TestEnvironment-512.hdr" + mappingMode: Texture.LightProbe + } + + probeExposure: 1.0 + exposure: 1.0 + } + + importScene: scene + } + + View3D { + implicitHeight: rootItem.height / 2 + implicitWidth: rootItem.width / 2 + environment: ExtendedSceneEnvironment { + backgroundMode: SceneEnvironment.SkyBox + lightProbe: Texture { + source: "../shared/maps/TestEnvironment-512.hdr" + mappingMode: Texture.LightProbe + } + + probeExposure: 1.0 + exposure: 10.0 + } + + importScene: scene + } + } +} |