Qt Quick 3D渲染

Qt Quick 3D是Qt框架中用于创建3D图形界面的强大模块,它提供了声明式的QML API,使得开发者无需深入底层图形API就能构建复杂的3D场景。本文将全面介绍Qt Quick 3D的核心概念和技术细节,包括3D场景坐标系统、场景环境设置、光照与材质系统、相机控制、渲染优化等关键技术点。

Qt Quick 3D概述

Qt Quick 3D是Qt 6.0中引入的重要模块,它为QML提供了高性能的3D渲染能力,使开发者能够创建丰富的3D用户界面和应用程序。与传统的Qt 3D模块相比,Qt Quick 3D设计更注重与2D界面的无缝集成,适用于轻量级的3D场景。当应用程序中大部分内容是2D界面,但某些部分需要简单的3D显示(如产品模型展示或数据可视化)时,Qt Quick 3D是理想的选择。

Qt Quick 3D的整体架构分为几个层次:

  • QML应用层:开发者使用的声明式接口,提供View3D、Model、Material等QML类型
  • 场景图适配层:将3D场景集成到Qt Quick场景图中,处理2D和3D元素的混合渲染
  • 渲染引擎层:基于RHI(Render Hardware Interface),支持Vulkan、Metal、Direct3D和OpenGL
  • 资源管理层:处理模型、纹理等资源的加载与缓存,包含异步加载系统

3D场景基础与坐标系统

View3D与场景容器

View3D是Qt Quick 3D中3D场景的容器,相当于Qt Quick 2D中的Canvas。它是所有3D内容的根容器,定义了3D场景的视口范围和渲染环境。

复制代码
View3D {
        // 3D视图容器,填充父元素
        anchors.fill: parent
        // 使用透视相机
        camera: perspectiveCamera

        // 定义透视相机(相当于观察者的视角)
        PerspectiveCamera {
            id: perspectiveCamera
            // 相机位置在3D空间中的坐标(x,y,z)
            position: Qt.vector3d(300, 300, 300)
            // 相机的旋转角度
            eulerRotation.x: -45  // 绕x轴旋转-45度
            eulerRotation.y: 45   // 绕y轴旋转45度
        }
}

3D坐标系统

Qt Quick 3D使用右手坐标系,其中:

  • X轴:水平向右
  • Y轴:垂直向上
  • Z轴:从屏幕向外

初始状态窗口的中心点坐标为原点Qt.vector3d(0, 0, 0),所有3D对象(Node及其子类)都具有以下基本空间属性:

属性 类型 描述 示例值
position vector3d 对象在父坐标系中的位置 Qt.vector3d(0, 0, 0)
rotation vector3d 欧拉角旋转(x,y,z度) Qt.vector3d(30, 45, 0)
scale vector3d 各轴缩放比例 Qt.vector3d(1, 1, 1)
pivot vector3d 变换的中心点 Qt.vector3d(0, -50, 0)

场景层次结构通过父子节点关系建立,子节点会继承父节点的变换(位置、旋转、缩放)。例如,创建一个包含多个模型的场景:

复制代码
Node {
    id: sceneRoot
    
    // 父节点
    Node {
        position: Qt.vector3d(100, 0, 0)
        
        // 子节点,位置相对于父节点
        Model {
            position: Qt.vector3d(0, 50, 0)
            source: "#Cube"
        }
    }
    
    // 另一个独立节点
    Model {
        position: Qt.vector3d(-100, 0, 0)
        source: "#Sphere"
    }
}

场景环境(SceneEnvironment)配置

SceneEnvironment定义了3D场景的全局渲染环境和后期处理效果。它是View3D的核心属性之一,控制着场景的背景、光照处理和视觉效果。

主要属性

属性 类型 描述 示例值
backgroundMode enum 背景类型(Color, SkyBox, Transparent等) SceneEnvironment.SkyBox
clearColor color 当backgroundMode为Color时的背景色 "#222840"
lightProbe Texture 用于图像照明(IBL)的HDR环境贴图 lightProbeTexture
probeExposure real 环境探针的曝光值 1.0
probeHorizon real 环境探针的水平线阈值 0.0
tonemapMode enum 色调映射模式(Linear, Filmic等) SceneEnvironment.Filmic
antialiasingMode enum 抗锯齿模式(NoAA, MSAA等) SceneEnvironment.MSAA
antialiasingQuality enum 抗锯齿质量(Medium, High等) SceneEnvironment.High

完整示例​:

复制代码
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")

    View3D {
        // 3D视图容器,填充父元素
        anchors.fill: parent
        // 指定使用的相机
        camera: camera
        // 设置场景环境属性
        environment: SceneEnvironment {
            antialiasingMode: SceneEnvironment.MSAA  // 使用多重采样抗锯齿
            antialiasingQuality: SceneEnvironment.High  // 高质量抗锯齿
            backgroundMode: SceneEnvironment.Color  // 使用纯色背景
            clearColor: "#80111111"  // 背景色(半透明深灰色)
        }

        // 定义透视相机(观察者视角)
        PerspectiveCamera {
            id: camera  // 相机唯一标识
            position: Qt.vector3d(300, 300, 300)  // 相机位置(x,y,z)
            eulerRotation.x: -45  // 绕x轴旋转-45度(向下倾斜)
            eulerRotation.y: 45   // 绕y轴旋转45度(侧向视角)
        }

        // 定义方向光(模拟太阳光)
        DirectionalLight {
            position: Qt.vector3d(-500, 500, -100)  // 光源位置
            color: Qt.rgba(1, 1, 1, 1)  // 白光(RGBA格式)
        }

        // 另一个方向光(补充光源)
        DirectionalLight {
            position: Qt.vector3d(500, -500, 100)  // 光源位置
            color: Qt.rgba(1, 1, 1, 1)  // 白光
            eulerRotation.x: -45  // 光源倾斜角度
            eulerRotation.y: 45
        }

        // 创建一个3D模型(球体)
        Model {
            source: "#Sphere"  // 使用内置的球体模型
            materials: [  // 定义材质
                DefaultMaterial {
                    diffuseColor: "gold"  // 漫反射颜色设为金色
                }
            ]
            position: Qt.vector3d(0, 0, 0)  // 球体位于场景中心
        }

        // 辅助坐标系(显示x/y/z轴,用于调试)
        AxisHelper {
        }
    }

    // WASD控制器(通过键盘WASD键控制相机移动)
    WasdController {
        controlledObject: camera  // 控制的对象是前面定义的相机
    }
}

天空盒(SkyBox)与图像照明(IBL)

天空盒 是一种将场景包裹在立方体纹理中的技术,提供远距离环境背景。​基于图像的照明 ​(Image Based Lighting, IBL)用于照亮场景或单个材质。它是一种使用图像照亮场景的照明技术,可以在场景中创建逼真的照明和反射。可以将任何图像文件用于IBL,但建议使用HDR图像,它具有更高的动态范围,通过从非常亮到非常暗的大范围亮度级别提供更加真实的照明。

使用IBL需要将图像作为纹理贴图添加到SceneEnvironmentlightProbe 属性,再将backgroundMode 属性设置为SceneEnvironment .SkyBox就实现天空盒效果,此场景中的所有模型都会由lightProbe 照亮。如果只想在对应材质而不是整个场景上使用IBL,可以将图像指定到模型特定材质的lightProbe属性。

复制代码
SceneEnvironment {
    id: sceneEnv
    backgroundMode: SceneEnvironment.SkyBox
    lightProbe: Texture {
        source: "qrc:/environments/industrial_sunset_02_puresky_1k.hdr"
    }
    probeExposure: 1.5
    probeHorizon: 0.2
    tonemapMode: SceneEnvironment.Filmic
}

完整示例​:创建一个具有HDR环境照明的场景

相机(Camera)系统

相机决定了观察者如何查看3D场景。Qt Quick 3D提供多种相机类型和控制器。

相机类型

类型 描述 典型用途
PerspectiveCamera 透视投影,模拟人眼视觉效果 大多数3D场景
OrthographicCamera 正交投影,保持物体大小不变 工程制图、CAD
FrustumCamera 自定义截头体投影 特殊投影需求

相机属性

属性 类型 描述 示例值
position vector3d 相机位置 Qt.vector3d(0, 0, 600)
rotation vector3d 相机旋转欧拉角 Qt.vector3d(30, 0, 0)
clipNear real 近裁剪面距离 1.0
clipFar real 远裁剪面距离 10000.0
fieldOfView real 透视相机的视野角度(度) 60.0
projectionMode enum 投影模式(Perspective/Orthographic) Camera.Perspective

相机控制器

相机控制器将用户输入转换为相机运动,常见的有:

复制代码
// 轨道控制器(围绕目标旋转)
OrbitCameraController {
    camera: camera
    anchors.fill: parent
}

// 第一人称控制器(WASD移动)
FirstPersonCameraController {
    camera: camera
    anchors.fill: parent
    movementSpeed: 100
    lookSpeed: 1
}

光源(Light)系统

光照是3D场景中创造真实感和深度的关键元素。Qt Quick 3D支持多种光源类型,每种都有不同的特性和用途。

光源类型及属性

光源类型 描述 关键属性 示例
DirectionalLight 方向光(如太阳光) direction, castsShadow, shadowFactor 阳光、月光
PointLight 点光源(如灯泡) constantFade, linearFade, quadraticFade 灯泡、蜡烛
SpotLight 聚光灯 coneAngle, innerConeAngle 手电筒、舞台灯
AreaLight 区域光 width, height 荧光灯、灯箱
AmbientLight 环境光 color, brightness 全局基础照明

方向光示例​:创建带阴影的太阳光

复制代码
DirectionalLight {
    eulerRotation.x: -45
    eulerRotation.y: -30
    castsShadow: true
    shadowFactor: 5
    shadowMapQuality: Light.ShadowMapQualityHigh
    brightness: 1.5
}

点光源示例​:创建闪烁的灯泡效果

复制代码
PointLight {
    position: Qt.vector3d(0, 100, 0)
    color: "yellow"
    brightness: 2.0
    constantFade: 1.0
    linearFade: 0.0
    quadraticFade: 0.001
    
    // 动画效果
    SequentialAnimation on brightness {
        loops: Animation.Infinite
        NumberAnimation { to: 3.0; duration: 800; easing.type: Easing.InOutQuad }
        NumberAnimation { to: 1.5; duration: 1200; easing.type: Easing.InOutQuad }
    }
}

材质(Material)与纹理(Texture)

材质定义了物体表面的视觉表现,包括颜色、反射率、粗糙度等属性。Qt Quick 3D提供了多种材质类型,满足不同渲染需求。

材质类型对比

材质类型 描述 适用场景
PrincipledMaterial 基于物理的渲染(PBR)材质 真实感表面(金属、塑料等)
DefaultMaterial 传统非PBR材质 简单表面、性能敏感场景
CustomMaterial 自定义着色器材质 特殊效果、高级着色
SpecularGlossyMaterial 镜面光泽材质 特定PBR工作流

PrincipledMaterial关键属性

属性 类型 描述 示例值
baseColor color 基础颜色 "red"
baseColorMap Texture 基础颜色贴图 colorTexture
metalness real 金属度(0-1) 0.9(金属)
roughness real 粗糙度(0-1) 0.1(光滑)
normalMap Texture 法线贴图 normalTexture
normalStrength real 法线强度 1.0
emissiveColor color 自发光颜色 "white"
emissiveMap Texture 自发光贴图 emissiveTexture
opacity real 透明度(0-1) 0.8
alphaMode enum 透明模式(Opaque, Mask, Blend) DefaultMaterial.Blend

材质示例​:创建金属材质表面

复制代码
PrincipledMaterial {
    baseColor: "#ffd700"
    metalness: 0.9
    roughness: 0.2
    specularAmount: 1.0
    indexOfRefraction: 2.5
    normalMap: Texture {
        source: "qrc:/textures/metal_normal.png"
    }
    metalnessMap: Texture {
        source: "qrc:/textures/metal_roughness.png"
    }
}

纹理(Texture)应用

纹理可以增强材质的真实感,Qt Quick 3D支持多种纹理映射技术:

纹理类型 描述 示例
颜色贴图 定义表面基础颜色 木纹、墙纸
法线贴图 模拟表面凹凸细节 砖墙、锈迹
金属/粗糙度贴图 控制PBR材质参数 磨损金属
环境遮挡贴图 添加表面阴影细节 角落暗部
自发光贴图 定义发光区域 霓虹灯、屏幕

纹理组合示例​:

复制代码
PrincipledMaterial {
    baseColorMap: Texture {
        source: "qrc:/textures/concrete_diffuse.jpg"
    }
    normalMap: Texture {
        source: "qrc:/textures/concrete_normal.jpg"
    }
    roughnessMap: Texture {
        source: "qrc:/textures/concrete_roughness.jpg"
    }
    metalnessMap: Texture {
        source: "qrc:/textures/concrete_metallic.jpg"
    }
    occlusionMap: Texture {
        source: "qrc:/textures/concrete_ao.jpg"
    }
}

2D内容与3D场景的集成

Qt Quick 3D的一个强大特性是能够无缝集成2D和3D内容。这种混合渲染能力使得开发者可以在3D场景中嵌入UI元素、视频或2D图形。

2D内容嵌入3D场景的方法

方法 描述 适用场景
Texture + Sprite 将2D内容作为纹理应用到3D表面 电视屏幕、画布
Layer + View3D 使用Qt Quick的Layer将2D内容渲染到纹理 动态UI元素
QtQuick Items 直接在3D场景上方叠加2D元素 HUD、UI控件

在3D场景中创建2D UI面板

复制代码
View3D {
    id: view3D
    anchors.fill: parent
}

// 叠加在3D场景上的2D控制面板
Rectangle {
    anchors.bottom: parent.bottom
    width: parent.width
    height: 80
    color: "#80000000"
    
    Row {
        anchors.centerIn: parent
        spacing: 20
        
        Button {
            text: "旋转"
            onClicked: animation.start()
        }
        
        Slider {
            width: 200
            from: 30
            to: 90
            value: camera.fieldOfView
            onValueChanged: camera.fieldOfView = value
        }
    }
}

高级渲染技术

实例化渲染(Instanced Rendering)

实例化渲染是一种高效渲染大量相似对象的技术,可以显著减少绘制调用。Qt Quick 3D通过InstanceListInstancing实现这一功能。

实例化渲染属性​:

属性 类型 描述 示例
instancing Instancing 实例化数据源 InstanceList
instanceCount int 实例数量 1000
color color 实例颜色(可选) "red"

示例​:创建10000个随机分布的立方体

复制代码
import QtQuick
import QtQuick3D
import QtQuick3D.Helpers

Window {
    width: 640
    height: 480
    visible: true
    title: qsTr("Hello World")
    
    // 3D视图容器(集成到Qt Quick 2D界面)
    View3D {
        anchors.fill: parent  // 填充父容器
        environment: SceneEnvironment {
            backgroundMode: SceneEnvironment.SkyBox  // 使用HDR天空盒作为背景
            lightProbe: Texture {  // 基于图像的照明(IBL)探针
                source: "DoschAsiaRoads.hdr"  // HDR环境贴图路径(提供全局光照)
            }
            probeExposure: 3  // 增强环境光曝光强度(提升场景亮度)
        }
        
        // 透视相机配置(带俯视角)
        PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, 300, 500)  // 相机位置(Y轴抬高300,Z轴后退500)
            eulerRotation.x: -25  // X轴旋转-25度(产生俯视效果)
        }
        
        // 随机实例化配置(高效渲染大量相似对象)
        RandomInstancing {
            id: randomInstancing
            instanceCount: 10000  // 实例数量(1万个立方体)
            
            // 位置随机范围(X轴±5000米,Y轴-2000~200米,Z轴-9000~500米)
            position: InstanceRange {
                from: Qt.vector3d(-5000, -2000, -9000)
                to: Qt.vector3d(5000, 200, 500)
            }
            
            // 旋转随机范围(Y轴不旋转,X/Z轴±180度)
            rotation: InstanceRange {
                from: Qt.vector3d(-180, 0, -45)
                to: Qt.vector3d(180, 0, 45)
            }
            
            // 颜色随机范围(从深灰到纯白)
            color: InstanceRange {
                from: Qt.rgba(0.1, 0.1, 0.1, 1)
                to: Qt.rgba(1, 1, 1, 1)
            }
        }
        
        // 主模型定义(使用实例化渲染)
        Model {
            instancing: randomInstancing  // 应用随机实例化配置
            source: "#Cube"  // 内置立方体网格
            materials: PrincipledMaterial {
                metalness: 1  // 完全金属质感
                roughness: 0.1  // 低粗糙度(高反射效果)
                baseColor: "#FFFFFF"  // 基础色白色(实际由实例化颜色覆盖)
            }
            
            // 旋转动画(所有实例同步旋转)
            NumberAnimation on eulerRotation.y {
                from: 0
                to: 360  // 绕Y轴旋转360度
                duration: 3000  // 3秒完成
                loops: Animation.Infinite  // 无限循环
            }
        }
        
        // 相机控制器(WASD键盘交互)
        WasdController {
            controlledObject: camera  // 绑定透视相机实现第一人称移动
        }
    }
}

粒子系统

Qt Quick 3D支持3D空间中的粒子效果,可以用于创建火焰、烟雾、魔法效果等。

粒子系统核心组件​:

组件 描述 关键属性
ParticleEmitter3D 粒子发射器 emitRate, lifeSpan, particleScale
ParticleModel3D 粒子模型 model, fadeInDuration, fadeOutDuration
ParticleDirection3D 粒子方向控制 direction, directionVariation

示例​:创建雪花粒子效果

复制代码
import QtQuick
import QtQuick.Controls
import QtQuick3D
import QtQuick3D.Particles3D
import QtQuick3D.Helpers

Window {
    width: 1024
    height: 768
    visible: true
    title: qsTr("Hello World")

    // 3D视图容器(集成到Qt Quick 2D界面)
    View3D {
        anchors.fill: parent  // 填充父容器
        environment: SceneEnvironment {
            backgroundMode: SceneEnvironment.SkyBox  // HDR天空盒背景模式
            antialiasingMode: SceneEnvironment.MSAA  // 多重采样抗锯齿
            antialiasingQuality: SceneEnvironment.VeryHigh  // 最高抗锯齿质量
            lightProbe: Texture {  // 基于图像的照明(IBL)探针
                source: "NordnesPark.hdr"  // HDR环境贴图路径(提供全局光照)
            }
            probeExposure: 0.5  // 降低环境光曝光(模拟雪天柔和光照)
        }

        // 透视相机配置(默认视角)
        PerspectiveCamera {
            id: camera
            position: Qt.vector3d(0, 100, 300)  // 相机位置(Y轴抬高100,Z轴后退300)
        }

        // 3D粒子系统(模拟雪花效果)
        ParticleSystem3D {
            id: particleSystem3D

            // 粒子精灵定义(单个雪花属性)
            SpriteParticle3D {
                id: snowParticle
                sprite: Texture {  // 粒子贴图
                    source: "snowflake.png"  // 雪花纹理路径
                }
                maxAmount: 15000  // 最大粒子数(控制性能)
                color: "#FFFFFF"  // 基础白色
                colorVariation: Qt.vector4d(0.05, 0.05, 0.05, 0.5)  // RGBA随机变化范围
                fadeInDuration: 1000  // 淡入时间(毫秒)
                fadeOutDuration: 1000  // 淡出时间(毫秒)
            }

            // 粒子发射器配置
            ParticleEmitter3D {
                id: emitter
                particle: snowParticle  // 绑定粒子类型
                position: Qt.vector3d(0, 300, -300)  // 发射器位置(场景上方)
                depthBias: -100  // 深度偏移(防止与场景穿插)
                scale: Qt.vector3d(15, 0, 15)  // 发射区域缩放(X/Z平面扩展)
                shape: ParticleShape3D {  // 发射器形状
                    type: ParticleShape3D.Sphere  // 球形发射区域
                }
                particleRotationVariation: Qt.vector3d(180, 180, 180)  // 初始旋转随机范围
                particleRotationVelocityVariation: Qt.vector3d(50, 50, 50)  // 旋转速度随机范围
                particleScale: sizeSlider.value  // 粒子大小(绑定外部滑块)
                particleScaleVariation: 0.5  // 大小随机变化幅度
                velocity: VectorDirection3D {  // 粒子运动方向
                    direction: Qt.vector3d(0, -200 * rotationSlider.value, 0)  // 主要下落速度
                    directionVariation: Qt.vector3d(0, -200 * 0.5 * rotationSlider.value, 0)  // 速度随机变化
                }
                emitRate: emitRateSlider.value  // 发射速率(粒子数/秒,绑定滑块)
                lifeSpan: 10000  // 粒子生命周期(毫秒)
                lifeSpanVariation: 2000  // 生命周期随机变化
            }
        }
    }

    // 相机控制器(WASD键盘交互)
    WasdController {
        controlledObject: camera  // 绑定透视相机实现第一人称移动
    }

    Button {
        width: 100
        height: 50
        anchors.left: parent.left
        anchors.leftMargin: 50
        y: 600
        text: particleSystem3D.running ? "停止" : "开始"

        onClicked: {
            particleSystem3D.running = !particleSystem3D.running
        }
    }

    Row {
        width: parent.width
        anchors.left: parent.left
        anchors.leftMargin: 50
        y: 700
        spacing: 10

        Label { text: "雪花数量: "; color: "white" }

        Slider {
            id: emitRateSlider
            width: 200
            height: 20
            from: 100
            to: 5000
            stepSize: 100
            value: 500
        }
    }

    Row {
        width: parent.width
        anchors.left: parent.left
        anchors.leftMargin: 400
        y: 700
        spacing: 10

        Label { text: "雪花大小: "; color: "white" }

        Slider {
            id: sizeSlider
            width: 200
            height: 20
            from: 1
            to: 5
            stepSize: 0.05
            value: 1
        }
    }

    Row {
        width: parent.width
        anchors.left: parent.left
        anchors.leftMargin: 750
        y: 700
        spacing: 10

        Label { text: "旋转: "; color: "white" }

        Slider {
            id: rotationSlider
            width: 200
            height: 20
            from: 1
            to: 20
            stepSize: 0.1
            value: 2
        }
    }

}

总结

Qt Quick 3D为QML开发者提供了强大的3D图形能力,通过声明式语法简化了3D场景的创建和管理。从基础场景设置到高级渲染技术,Qt Quick 3D覆盖了游戏开发、产品展示、数据可视化等多种应用场景。掌握3D坐标系统、场景环境配置、材质光照系统和性能优化技巧,开发者可以创建出既美观又高效的3D应用程序。