Qt Quick 3D - Offline Shaders Example

 // Copyright (C) 2019 The Qt Company Ltd.
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause

 import QtQuick
 import QtQuick.Controls
 import QtQuick.Layouts
 import QtQuick3D
 import QtQuick3D.Helpers

 ApplicationWindow {
     id: window
     width: 1280
     height: 720
     visible: true
     title: qsTr("Lights Example")

     property bool isLandscape: width > height

     View3D {
         id: v3d

         anchors.bottom: parent.bottom
         anchors.right: parent.right
         anchors.left: window.isLandscape ? settingsDrawer.right : parent.left
         anchors.top: window.isLandscape ? parent.top : settingsDrawer.bottom

         environment: SceneEnvironment {
             clearColor: "#808080"
             backgroundMode: SceneEnvironment.Color
             antialiasingMode: SceneEnvironment.MSAA
             antialiasingQuality: SceneEnvironment.High
         }

         PerspectiveCamera {
             position: Qt.vector3d(0, 400, 600)
             eulerRotation.x: -30
             clipFar: 2000
         }

         DirectionalLight {
             id: light1
             color: Qt.rgba(1.0, 0.1, 0.1, 1.0)
             ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
             position: Qt.vector3d(0, 200, 0)
             rotation: Quaternion.fromEulerAngles(-135, -90, 0)
             shadowMapQuality: Light.ShadowMapQualityHigh
             visible: directionalLightCheckBox.checked
             castsShadow: checkBoxShadows.checked
             brightness: directionalLightSlider.value
             SequentialAnimation on rotation {
                 loops: Animation.Infinite
                 QuaternionAnimation {
                     to: Quaternion.fromEulerAngles(-45, -90, 0)
                     duration: 2000
                     easing.type: Easing.InOutQuad
                 }
                 QuaternionAnimation {
                     to: Quaternion.fromEulerAngles(-135, -90, 0)
                     duration: 2000
                     easing.type: Easing.InOutQuad
                 }
             }
         }

         PointLight {
             id: light2
             color: Qt.rgba(0.1, 1.0, 0.1, 1.0)
             ambientColor: Qt.rgba(0.1, 0.1, 0.1, 1.0)
             position: Qt.vector3d(0, 300, 0)
             shadowMapFar: 2000
             shadowMapQuality: Light.ShadowMapQualityHigh
             visible: pointLightCheckBox.checked
             castsShadow: checkBoxShadows.checked
             brightness: pointLightSlider.value
             SequentialAnimation on x {
                 loops: Animation.Infinite
                 NumberAnimation {
                     to: 400
                     duration: 2000
                     easing.type: Easing.InOutQuad
                 }
                 NumberAnimation {
                     to: 0
                     duration: 2000
                     easing.type: Easing.InOutQuad
                 }
             }
         }

         SpotLight {
             id: light4
             color: Qt.rgba(1.0, 0.9, 0.7, 1.0)
             ambientColor: Qt.rgba(0.0, 0.0, 0.0, 0.0)
             position: Qt.vector3d(0, 250, 0)
             eulerRotation.x: -45
             shadowMapFar: 2000
             shadowMapQuality: Light.ShadowMapQualityHigh
             visible: spotLightCheckBox.checked
             castsShadow: checkBoxShadows.checked
             brightness: spotLightSlider.value
             coneAngle: 50
             innerConeAngle: 30
             PropertyAnimation on eulerRotation.y {
                 loops: Animation.Infinite
                 from: 0
                 to: -360
                 duration: 10000
             }
         }

         Model {
             source: "#Rectangle"
             y: -200
             scale: Qt.vector3d(15, 15, 15)
             eulerRotation.x: -90
             materials: [
                 PrincipledMaterial {
                     baseColor: Qt.rgba(0.8, 0.6, 0.4, 1.0)
                 }
             ]
         }
         Model {
             source: "#Rectangle"
             z: -400
             scale: Qt.vector3d(15, 15, 15)
             materials: [
                  PrincipledMaterial {
                     baseColor: Qt.rgba(0.8, 0.8, 0.9, 1.0)
                 }
             ]
         }

         RotatingTeaPot {
             visible: !checkBoxCustomMaterial.checked
             material: PrincipledMaterial {
                 baseColor: Qt.rgba(0.9, 0.9, 0.9, 1.0)
             }
             animate: checkBoxAnimate.checked
         }

         RotatingTeaPot {
             visible: checkBoxCustomMaterial.checked
             material: CustomMaterial {
                 id: customMaterial
                 vertexShader: "custom.vert"
                 property real uAmplitude: 0.5
                 property real uTime: 0.0
                 SequentialAnimation {
                     running: true
                     loops: Animation.Infinite
                     NumberAnimation { target: customMaterial; property: "uTime"; from: 0.0; to: 10.0; duration: 10000 }
                     NumberAnimation { target: customMaterial; property: "uTime"; from: 10.0; to: 0.0; duration: 10000 }
                 }
             }
             animate: checkBoxAnimate.checked
         }

         Model {
             // Directional Light Marker
             property real size: directionalLightSlider.highlight ? 0.2 : 0.1
             source: "#Cube"
             position: light1.position
             rotation: light1.rotation
             scale: Qt.vector3d(size, size, size * 2)
             materials: [
                 PrincipledMaterial {
                     baseColor: light1.color
                     lighting: PrincipledMaterial.NoLighting
                 }
             ]
             castsShadows: false
             visible: directionalLightCheckBox.checked
         }
         Model {
             // Point Light Marker
             source: "#Sphere"
             position: light2.position
             rotation: light2.rotation
             property real size: pointLightSlider.highlight ? 0.2 : 0.1
             scale: Qt.vector3d(size, size, size)
             materials: [
                 PrincipledMaterial {
                     baseColor: light2.color
                     lighting: PrincipledMaterial.NoLighting
                 }
             ]
             castsShadows: false
             visible: pointLightCheckBox.checked
         }
         Node {
             // Spot Light Marker
             position: light4.position
             rotation: light4.rotation
             property real size: spotLightSlider.highlight ? 0.2 : 0.1
             scale: Qt.vector3d(size, size, size)
             Model {
                 source: "#Cone"
                 castsShadows: false
                 eulerRotation.x: 90
                 materials: PrincipledMaterial {
                     baseColor: light4.color
                     lighting: PrincipledMaterial.NoLighting
                 }
             }
             visible: spotLightCheckBox.checked
         }

         DebugView {
             id: dbg
             anchors.top: parent.top
             anchors.right: parent.right
             source: v3d
             visible: debugViewCheckbox.checked
         }
     }

     RowLayout {
         anchors.bottom: v3d.bottom
         anchors.left: v3d.left
         anchors.margins: 10
         Item {
             id: settingsButton
             implicitWidth: 64
             implicitHeight: 64
             Image {
                 anchors.centerIn: parent
                 source: "icon_settings.png"
             }

             HoverHandler {
                 id: hoverHandler
             }
         }
         Text {
             Layout.alignment: Qt.AlignVCenter
             text: settingsDrawer.title
             visible: !settingsDrawer.isOpen
             color: "white"
             font.pointSize: 16
         }
         TapHandler {
             // qmllint disable signal-handler-parameters
             onTapped: settingsDrawer.isOpen = !settingsDrawer.isOpen;
             // qmllint enable signal-handler-parameters
         }
     }

     component SliderWithValue : RowLayout {
         property alias value: slider.value
         property alias from: slider.from
         property alias to: slider.to
         readonly property bool highlight: slider.hovered || slider.pressed
         Slider {
             id: slider
             stepSize: 0.01
             Layout.minimumWidth: 200
             Layout.maximumWidth: 200
         }
         Label {
             id: valueText
             text: slider.value.toFixed(2)
             Layout.minimumWidth: 80
             Layout.maximumWidth: 80
         }
     }

     SettingsDrawer {
         id: settingsDrawer
         title: qsTr("Settings")
         isLandscape: window.isLandscape
         width: window.isLandscape ? implicitWidth : window.width
         height: window.isLandscape ? window.height : window.height * 0.33

         CheckBox {
             id: checkBoxShadows
             text: qsTr("Enable Shadows")
             checked: true
         }
         CheckBox {
             id: checkBoxAnimate
             text: qsTr("Rotate Teapot")
             checked: true
         }
         CheckBox {
             id: checkBoxCustomMaterial
             text: qsTr("Custom Material")
             checked: false
         }

         Label {
             // spacer
         }

         CheckBox {
             id: directionalLightCheckBox
             text: qsTr("Directional Light")
             checked: true
         }
         SliderWithValue {
             id: directionalLightSlider
             value: 0.5
             from: 0
             to: 1
             enabled: directionalLightCheckBox.checked
         }

         Label {
             // spacer
         }

         CheckBox {
             id: pointLightCheckBox
             text: qsTr("Point Light")
             checked: false
         }
         SliderWithValue {
             id: pointLightSlider
             value: 6
             from: 0
             to: 10
             enabled: pointLightCheckBox.checked
         }
         Label {
             // spacer
         }
         CheckBox {
             id: spotLightCheckBox
             text: qsTr("Spot Light")
             checked: false
         }
         SliderWithValue {
             id: spotLightSlider
             value: 10
             from: 0
             to: 30
             enabled: spotLightCheckBox.checked
         }
         Label {
             // spacer
         }
         CheckBox {
             id: debugViewCheckbox
             text: qsTr("Enable Debug View")
             checked: false
         }
     }
 }