本章开始,陆续学习Qt 3D 的官方实例,其中遇到的组件或类,将一一进行解释理解(opengl ),文章看起来会比较琐碎
Simple-qml 应用程序演示了如何在Qt 3 d渲染场景
main.cpp
#include
#include
int main(int argc, char* argv[])
{
QGuiApplication app(argc, argv);
Qt3DExtras::Quick::Qt3DQuickWindow view;
view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}
main.qml
import QtQuick 2.2 as QQ2
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
Entity {
id: sceneRoot
Camera {
id: camera
projectionType: CameraLens.PerspectiveProjection
fieldOfView: 45
aspectRatio: 16/9
nearPlane : 0.1
farPlane : 1000.0
position: Qt.vector3d( 0.0, 0.0, -40.0 )
upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
}
OrbitCameraController {
camera: camera
}
components: [
RenderSettings {
activeFrameGraph: ForwardRenderer {
clearColor: Qt.rgba(0, 0.5, 1, 1)
camera: camera
}
},
// Event Source will be set by the Qt3DQuickWindow
InputSettings { }
]
PhongMaterial {
id: material
}
TorusMesh {
id: torusMesh
radius: 5
minorRadius: 1
rings: 100
slices: 20
}
Transform {
id: torusTransform
scale3D: Qt.vector3d(1.5, 1, 0.5)
rotation: fromAxisAndAngle(Qt.vector3d(1, 0, 0), 45)
}
Entity {
id: torusEntity
components: [ torusMesh, material, torusTransform ]
}
SphereMesh {
id: sphereMesh
radius: 3
}
Transform {
id: sphereTransform
property real userAngle: 0.0
matrix: {
var m = Qt.matrix4x4();
m.rotate(userAngle, Qt.vector3d(0, 1, 0));
m.translate(Qt.vector3d(20, 0, 0));
return m;
}
}
QQ2.NumberAnimation {
target: sphereTransform
property: "userAngle"
duration: 10000
from: 0
to: 360
loops: QQ2.Animation.Infinite
running: true
}
Entity {
id: sphereEntity
components: [ sphereMesh, material, sphereTransform ]
}
}
ECS,即 Entity-Component-System(实体-组件-系统) 的缩写,其模式遵循组合优于继承原则,游戏内的每一个基本单元都是一个实体,每个实体又由一个或多个组件构成,每个组件仅仅包含代表其特性的数据(即在组件中没有任何方法),例如:移动相关的组件MoveComponent包含速度、位置、朝向等属性,一旦一个实体拥有了MoveComponent组件便可以认为它拥有了移动的能力,系统便是来处理拥有一个或多个相同组件的实体集合的工具,其只拥有行为(即在系统中没有任何数据),在这个例子中,处理移动的系统仅仅关心拥有移动能力的实体,它会遍历所有拥有MoveComponent组件的实体,并根据相关的数据(速度、位置、朝向等),更新实体的位置。
实体与组件是一个一对多的关系,实体拥有怎样的能力,完全是取决于其拥有哪些组件,通过动态添加或删除组件,可以在(游戏)运行时改变实体的行为。
Qt 3D 中,ECS框架即 QEntity、QComponent、Aspect(切面)组成;Entity/Component数据拆分可灵活管理API,系统分离使行为远离数据避免组件之间的依赖关系(MVC).
Qt3DCore::QNode 是Qt3D所有类的基类,它是QObject的子类,提供了属性变化自动通知切面和程序唯一ID。切面存在于额外的线程中,Qt3DCore::QNode简化了面向用户对象和切面之间的数据传输。
QEntity只是一个空壳,它的行为由QComponent定义。Qt3D后端将解析和处理QEntity,识别有哪些QComponent,然后调用相应的aspect去执行。比如有的aspect专门处理QComponent的变形(Qt3DCore::QTransform),而另外有一个aspect专门处理鼠标事件(Qt3DInput::QMouseHandler)
Entity {
id: torusEntity
components: [ torusMesh, material, torusTransform ]
}
其中components是一个list< Component3D >容器。而主要的还是看里面的3项:Mesh、Material、Transform。
Mesh是加载的元素形状网格数据,也就是元素的形状。
Material元素的渲染方法,比如颜色等。
Transform元素的移动旋转等。
QSurface是一个可渲染的抽象类,继承自QOffscreenSurface和QWindow。
size():设置接口大小。
format():设置渲染的特殊属性。
QSurfaceFormat代表QSurface的一种格式,包括颜色缓冲(、红、绿、蓝、alpha缓冲)、深度缓冲、多重采样数量等;
Camera 定义了3D渲染场景中的一个观察点。详情可阅读learnOpengl中入门章节的坐标系统和摄像机
观察空间经常被人们称之OpenGL的摄像机(Camera)(所以有时也称为摄像机空间(Camera Space)或视觉空间(Eye Space))。观察空间是将世界空间坐标转化为用户视野前方的坐标而产生的结果。因此观察空间就是从摄像机的视角所观察到的空间。
Camera {
id: camera
projectionType: CameraLens.PerspectiveProjection //投影类型:正交投影、透视投影、截锥投影、自定义投影
fieldOfView: 45
aspectRatio: 16/9
nearPlane : 0.1
farPlane : 1000.0
position: Qt.vector3d( 0.0, 0.0, -40.0 )
upVector: Qt.vector3d( 0.0, 1.0, 0.0 )
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )
}
其中定义了投影方式、视野大小、宽高比、近平面、远平面、坐标、向上的一个向量、视口中心
其中upVector可以自己调整下参数,看下效果
比如 upVector: Qt.vector3d( 1.0, 0.0, 0.0 ) 效果
比如 upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) 效果
比如 upVector: Qt.vector3d( 1.0, 1.0, 0.0 ) 效果
正射投影:
为正射投影没有使用透视,远处的物体不会显得更小,由于这个原因,正射投影主要用于二维渲染以及一些建筑或工程的程序,在这些场景中我们更希望顶点不会被透视所干扰
透视投影:
如果你曾经体验过实际生活给你带来的景象,你就会注意到离你越远的东西看起来更小。这个奇怪的效果称之为透视(Perspective)。透视的效果在我们看一条无限长的高速公路或铁路时尤其明显,正如下面图片显示的那样:
轨道相机控制器(围绕物体旋转),默认行为是 鼠标左键移动摄像头。 - 用鼠标右键旋转相机
Properties
camera : Camera
linearSpeed : real
lookSpeed : real
zoomLimit : real
components: [
RenderSettings {
activeFrameGraph: ForwardRenderer {
clearColor: Qt.rgba(0, 0.5, 1, 1)
camera: camera
}
},
// Event Source will be set by the Qt3DQuickWindow
InputSettings { }
]
Properties
activeFrameGraph : FrameGraphNode
pickingSettings : PickingSettings
renderPolicy : enumeration
“渲染设置”组件必须设置为场景根实体的组件。它指定渲染策略和拾取设置,并承载活动帧图。
RenderSettings他只有三个属性activeFrameGraph、pickingSettings、renderPolicy。而我们则设置了他的第一个属性。
ForwardRenderer
是一个单叶框架图树,它包含一个视区、一个CameraSelector和一个ClearBuffers
默认视口占据整个屏幕,且透明颜色为白色。还启用了截锥剔除
InputSettings组件必须设置为场景根实体的组件。它存储一个指向对象的指针,该对象作为各种输入类处理的输入事件的源。例如,窗口实例可以是事件源。
在本例中,窗口可以接受鼠标左键、右键、滚轮事件,如果把InputSettings注释掉,则没有响应了
Properties
ambient : QColor //环境光
diffuse : QColor // 漫反射
shininess : float // 光泽度
specular : QColor //镜面反射
该类已
被弃用;改用QDiffuseSpecularMaterial。
phong照明效果基于环境光、漫反射光和镜面反射光三种照明组件的组合。这些组件的相对强度由其反射率系数控制,反射率系数被建模为RGB三元组:
环境光是物体在没有任何其他光源的情况下发出的颜色。
漫反射是灯光在粗糙表面反射时发出的颜色。
镜面反射是灯光照射下发光表面反射发出的颜色。
曲面的光泽度由浮动特性控制。
该材质使用具有单个渲染过程的效果,并执行逐片段照明。提供了OpenGL 2、OpenGL 3或更高版本以及OpenGL ES 2的技术。
环形网格
Properties
minorRadius : real
radius : real
rings : int
slices : int
球面网格
变换组件不能在多个实体之间共享。变换组件由作为vector3d缩放、四元数旋转和vector3d平移组件。变换将按该顺序应用于网格。当设置Transform::matrix属性时,它将分解为这些变换组件,并发出相应的变换信号。
提供了几个辅助函数来设置转换;From Axis AndAngle和From Axes AndAngles可用于设定围绕特定轴的旋转,From Eulerangles可用于设定基于欧拉角度的旋转,rotateAround可用于相对于局部原点围绕特定点旋转对象
属性动画
simple-qml 实例定义了一个环状网格 TorusMesh 和 一个 球面网格SphereMesh,一个 Camera和 OrbitCameraController ,其中球面网格根据NumberAnimation 永久动画,来改变球面网格的Transform