Revision control
Copy as Markdown
// Copyright (C) 2026 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick.Controls
import QtQuick.Layouts
import QtQuick3D
Page {
id: root
required property var sun
required property var advancedSky
required property var sunAnimator
property bool animateSun: true
property real sunSweepSpeed: 0.4
property bool showDebugView: false
header: ToolBar {
Label {
anchors.centerIn: parent
text: "Settings"
font.pointSize: 17
}
}
ScrollView {
id: scrollView
anchors.fill: parent
ScrollBar.vertical.policy: ScrollBar.AsNeeded
ScrollBar.horizontal.policy: ScrollBar.AlwaysOff
padding: 20
contentHeight: settingsColumn.implicitHeight
contentWidth: skyGroup.implicitWidth
ColumnLayout {
id: settingsColumn
width: parent.width
spacing: 8
component SliderWithValue : RowLayout {
id: sliderWithValue
property alias value: slider.value
property alias from: slider.from
property alias to: slider.to
property alias stepSize: slider.stepSize
property alias snapMode: slider.snapMode
property int numDecimals: 0
signal moved(real v)
Slider {
id: slider
onMoved: sliderWithValue.moved(slider.value)
}
Label {
text: slider.value.toFixed(sliderWithValue.numDecimals)
Layout.minimumWidth: 40
horizontalAlignment: Text.AlignRight
}
}
GroupBox {
id: skyGroup
Layout.fillWidth: true
title: "Sky"
ColumnLayout {
width: parent.width
spacing: 5
Switch {
Layout.fillWidth: true
text: "Animate sun"
checked: root.animateSun
onToggled: root.animateSun = checked
}
Label { text: "Cycle speed" }
SliderWithValue {
from: 0.01; to: 1.0; stepSize: 0.01; snapMode: Slider.SnapAlways
numDecimals: 2
value: root.sunSweepSpeed
onMoved: (v) => root.sunSweepSpeed = v
}
Label {
text: "Sun elevation"
}
SliderWithValue {
from: 0; to: 180; stepSize: 1; snapMode: Slider.SnapAlways
value: -root.sun.eulerRotation.x
onMoved: (v) => {
root.sun.eulerRotation.x = -v
root.sunAnimator.updatePhaseFromSun()
}
}
Switch {
Layout.fillWidth: true
text: "Enable clouds"
checked: root.advancedSky.cloudsEnabled
onToggled: root.advancedSky.cloudsEnabled = checked
}
Label {
text: "Cloud coverage"
enabled: root.advancedSky.cloudsEnabled
}
SliderWithValue {
enabled: root.advancedSky.cloudsEnabled
from: 0.0; to: 1.0; stepSize: 0.01
numDecimals: 2
value: root.advancedSky.cloudCoverage
onMoved: (v) => root.advancedSky.cloudCoverage = v
}
Switch {
id: animateWindSwitch
Layout.fillWidth: true
text: "Animate wind"
checked: true
enabled: root.advancedSky.cloudsEnabled
}
}
}
FrameAnimation {
running: animateWindSwitch.checked && root.advancedSky.cloudsEnabled
onTriggered: {
const speed = 0.1
const off = root.advancedSky.cloudWindOffset
root.advancedSky.cloudWindOffset = Qt.vector2d(
off.x + speed * frameTime,
off.y + speed * frameTime * 0.3)
root.advancedSky.cloudTimeOffset += speed * frameTime * 0.05
}
}
GroupBox {
Layout.fillWidth: true
title: "Rendering"
ColumnLayout {
width: parent.width
spacing: 5
Switch {
Layout.fillWidth: true
text: "Show debug view (FPS)"
checked: root.showDebugView
onToggled: root.showDebugView = checked
}
// What the SkyMaterial outputs for the background: the IBL/radiance cube
// (cheapest for a static sky) or a per-frame screen-space render at one
// of three scales (lower = cheaper, softer).
Label { text: "Skybox mode" }
ComboBox {
Layout.fillWidth: true
model: [
{ value: SkyMaterial.Cubemap, text: "Cubemap (IBL size)" },
{ value: SkyMaterial.ScreenSpaceFull, text: "Screen space — Full" },
{ value: SkyMaterial.ScreenSpaceHalf, text: "Screen space — Half" },
{ value: SkyMaterial.ScreenSpaceQuarter, text: "Screen space — Quarter" },
]
textRole: "text"
valueRole: "value"
currentIndex: root.advancedSky.skyboxMode
onActivated: root.advancedSky.skyboxMode = currentValue
}
Label {
text: "IBL render frames"
enabled: root.advancedSky.enableIBL
}
SliderWithValue {
enabled: root.advancedSky.enableIBL
from: 0; to: 6; stepSize: 1; snapMode: Slider.SnapAlways
value: root.advancedSky.iblRenderFrames
onMoved: (v) => root.advancedSky.iblRenderFrames = Math.round(v)
}
Switch {
Layout.fillWidth: true
text: "Enable IBL"
checked: root.advancedSky.enableIBL
onToggled: root.advancedSky.enableIBL = checked
}
Label {
text: "IBL sample count"
enabled: root.advancedSky.enableIBL
}
SliderWithValue {
enabled: root.advancedSky.enableIBL
from: 1; to: 256; stepSize: 1; snapMode: Slider.SnapAlways
value: root.advancedSky.iblSampleCount
onMoved: (v) => root.advancedSky.iblSampleCount = Math.round(v)
}
Label {
text: "Radiance map size (IBL)"
enabled: root.advancedSky.enableIBL
}
ComboBox {
Layout.fillWidth: true
enabled: root.advancedSky.enableIBL
model: [
{ value: 16, text: "16" },
{ value: 32, text: "32" },
{ value: 64, text: "64" },
{ value: 128, text: "128" },
{ value: 256, text: "256" },
{ value: 512, text: "512" },
{ value: 1024, text: "1024" },
]
textRole: "text"
valueRole: "value"
currentValue: 512
onActivated: root.advancedSky.radianceMapSize = currentValue
}
}
}
}
}
}