Revision control

Copy as Markdown

// Copyright (C) 2025 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers
import QtQuick.Controls
import QtQuick.Layouts
import "assets"
ApplicationWindow {
width: 1480
height: 900
visible: true
title: qsTr("QtQuick3D SSGI Lightmap Demo")
id: window
View3D {
id: view
anchors.fill: parent
property Loader3D currentLoader: loaderCornell
property SceneBase currentScene
property url currentSource: "assets/CornellBox/CornellBox.qml"
onCurrentSourceChanged: {
updateLoadedScene()
}
environment: ExtendedSceneEnvironment {
id: env
clearColor: "black"
backgroundMode: SceneEnvironment.Color
}
function updateLoadedScene() {
posAnim.stop()
rotAnim.stop()
let loaders = [loaderCornell, loaderBedroom, loaderSponza]
for (let i = 0; i < loaders.length; i++) {
let loader = loaders[i]
let item = loader.item
if (item === null) {
continue
}
if (loader.source === view.currentSource) {
env.lightmapper = item.lightmapper
env.backgroundMode = item.backgroundMode
env.lightProbe = item.lightProbe
env.ssgiEnabled = buttonSSGI.checked
cameraNode.position = item.cameraPositions[item.cameraIndex]
cameraNode.eulerRotation = item.cameraRotations[item.cameraIndex]
item.enableLightmaps = buttonBaked.checked
env.ssgiIndirectLightBoost = item.ssgiIndirectLightBoost
env.probeExposure = item.probeExposure
item.visible = true
view.currentLoader = loader
view.currentScene = loader.item as SceneBase
} else {
item.enableLightmaps = false
item.visible = false
}
}
}
Loader3D {
id: loaderCornell
asynchronous: true
source: "assets/CornellBox/CornellBox.qml"
onStatusChanged: () => {
if (status === Loader3D.Ready)
view.updateLoadedScene()
}
}
Loader3D {
id: loaderBedroom
asynchronous: true
source: "assets/Bedroom/Bedroom.qml"
onStatusChanged: () => {
if (status === Loader3D.Ready)
view.updateLoadedScene()
}
}
Loader3D {
id: loaderSponza
asynchronous: true
source: "assets/Sponza/Sponza.qml"
onStatusChanged: () => {
if (status === Loader3D.Ready)
view.updateLoadedScene()
}
}
WasdController {
controlledObject: cameraNode
}
PerspectiveCamera {
id: cameraNode
z: 300
y: 100
}
}
RowLayout {
id: buttonRow
spacing: 12
anchors.horizontalCenter: parent.horizontalCenter
anchors.bottom: parent.bottom
anchors.bottomMargin: 20
IconButton {
id: buttonSSGI
text: "SSGI"
conflictingButtons: [buttonOff, buttonBaked]
iconSource: "qrc:/assets/icons/ssgi.svg"
onCheckedChanged: {
if (checked) {
env.ssgiEnabled = true
if (view.currentScene) {
view.currentScene.enableLightmaps = false
}
}
}
}
IconButton {
id: buttonBaked
checked: true
text: "Baked"
conflictingButtons: [buttonOff, buttonSSGI]
iconSource: "qrc:/assets/icons/baked.svg"
onCheckedChanged: {
if (checked) {
env.ssgiEnabled = false
if (view.currentScene) {
view.currentScene.enableLightmaps = true
}
}
}
}
IconButton {
id: buttonOff
text: "Off"
iconSource: "qrc:/assets/icons/off.svg"
conflictingButtons: [buttonBaked, buttonSSGI]
onCheckedChanged: {
if (checked) {
env.ssgiEnabled = false
if (view.currentScene) {
view.currentScene.enableLightmaps = false
}
}
}
}
Rectangle {
implicitWidth: 1
implicitHeight: 60
color: "#aaa"
opacity: 0.4
} // separator
IconButton {
id: demoButton
text: "Demo"
iconSource: "qrc:/assets/icons/reset-camera.svg"
toggable: true
onClicked: {
if (demoButton.checked) {
window.nextCamera()
}
}
}
IconButton {
text: "Next View"
iconSource: "qrc:/assets/icons/right-arrow.svg"
checkable: false
onClicked: {
window.nextCamera()
}
}
Rectangle {
implicitWidth: 1
implicitHeight: 60
color: "#aaa"
opacity: 0.4
} // separator
IconButton {
id: buttonBedroom
text: "Bedroom"
iconSource: "qrc:/assets/icons/bedroom.svg"
conflictingButtons: [buttonCornell, buttonSponza]
onCheckedChanged: {
if (checked)
view.currentSource = "assets/Bedroom/Bedroom.qml"
}
}
IconButton {
id: buttonCornell
text: "Cornell"
iconSource: "qrc:/assets/icons/cornell.svg"
checked: true
conflictingButtons: [buttonBedroom, buttonSponza]
onCheckedChanged: {
if (checked)
view.currentSource = "assets/CornellBox/CornellBox.qml"
}
}
IconButton {
id: buttonSponza
text: "Sponza"
iconSource: "qrc:/assets/icons/sponza.svg"
conflictingButtons: [buttonCornell, buttonBedroom]
onCheckedChanged: {
if (checked)
view.currentSource = "assets/Sponza/Sponza.qml"
}
}
}
function nextCamera() {
if (!view.currentScene)
return
posAnim.stop()
rotAnim.stop()
let item = view.currentScene
item.cameraIndex = (item.cameraIndex + 1) % item.cameraPositions.length
posAnim.to = item.cameraPositions[item.cameraIndex]
rotAnim.to = item.cameraRotations[item.cameraIndex]
posAnim.start()
rotAnim.start()
}
Timer {
id: demoTimer
interval: 7500
repeat: true
running: demoButton.checked
onTriggered: {
window.nextCamera()
}
}
// Animations
Vector3dAnimation {
id: posAnim
target: cameraNode
property: "position"
duration: demoButton.checked ? 2000 : 1000
easing.type: Easing.InOutQuad
}
Vector3dAnimation {
id: rotAnim
target: cameraNode
property: "eulerRotation"
duration: demoButton.checked ? 2000 : 1000
easing.type: Easing.InOutQuad
}
}