main.cpp
#include <QGuiApplication>
#include <QQuickView>
#include <QOpenGLContext>
#include <Qt3DRender/qt3drender-config.h>
void setSurfaceFormat()
{
QSurfaceFormat format;
#if QT_CONFIG(opengles2)
format.setRenderableType(QSurfaceFormat::OpenGLES);
#else
if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
format.setVersion(4, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
}
#endif
format.setDepthBufferSize(24);
format.setSamples(4);
format.setStencilBufferSize(8);
QSurfaceFormat::setDefaultFormat(format);
#if !QT_CONFIG(qt3d_rhi_renderer)
qputenv("QSG_RHI_BACKEND", "opengl");
#endif
}
int main(int argc, char **argv)
{
QGuiApplication app(argc, argv);
setSurfaceFormat();
QQuickView view;
view.resize(1920, 1080);
view.setResizeMode(QQuickView::SizeRootObjectToView);
view.setSource(QUrl("qrc:/main.qml"));
view.show();
return app.exec();
}
main.qml
import QtQuick 2.0
import QtQuick.Scene3D 2.0
import Qt3D.Render 2.0
import QtQuick.Controls 2.0
Item {
Rectangle {
id: scene
property bool colorChange: true
anchors.fill: parent
color: "#2d2d2d"
对于典型的 3D 类旋转,您通常会同时指定原点和轴。
transform: Rotation {
id: sceneRotation
axis.x: 1
axis.y: 0
axis.z: 0
origin.x: scene.width / 2
origin.y: scene.height / 2
}
Rectangle {
id: controlsbg
anchors.fill: parent
anchors.leftMargin: 10
anchors.topMargin: 10
anchors.rightMargin: 1720
anchors.bottomMargin: 10
color: "grey"
Column {
anchors.fill: parent
anchors.leftMargin: 5
anchors.topMargin: 5
spacing: 10
Rectangle {
id: slidertexscale
width: 180
height: 60
color: "#2d2d2d"
Text {
id: scaletext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "TEXTURE SCALE"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider1
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 1.0
from: 0.3
}
}
Rectangle {
id: slidertexturespeed
width: 180
height: 60
color: "#2d2d2d"
Text {
id: texturespeedtext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "TEXTURE SPEED"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider5
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 1.1
to: 4.0
from: 0.0
}
}
Rectangle {
id: sliderspecularity
width: 180
height: 60
color: "#2d2d2d"
Text {
id: specularitytext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "SPECULARITY"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider3
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 1.0
to: 3.0
from: 0.0
}
}
Rectangle {
id: sliderdistortion
width: 180
height: 60
color: "#2d2d2d"
Text {
id: distortiontext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "DISTORTION"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider7
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 0.015
to: 0.1
from: 0.0
}
}
Rectangle {
id: slidernormal
width: 180
height: 60
color: "#2d2d2d"
Text {
id: normaltext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "NORMAL AMOUNT"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider8
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 2.2
to: 4.0
from: 0.0
}
}
Rectangle {
id: sliderwavespeed
width: 180
height: 60
color: "#2d2d2d"
Text {
id: wawespeedtext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "WAVE SPEED"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider2
live: false
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 0.75
to: 4.0
from: 0.1
}
}
Rectangle {
id: sliderwaveheight
width: 180
height: 60
color: "#2d2d2d"
Text {
id: waweheighttext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "WAVE HEIGHT"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider6
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 0.2
to: 0.5
from: 0.02
}
}
Rectangle {
id: slidermeshrotation
width: 180
height: 60
color: "#2d2d2d"
Text {
id: meshrotationtext
anchors.horizontalCenter: parent.horizontalCenter
anchors.top: parent.top
anchors.topMargin: 10
text: "MESH ROTATION"
color: "white"
font.bold: true
font.pointSize: 12
}
Slider {
id: slider4
anchors.fill: parent
anchors.topMargin: 30
anchors.rightMargin: 10
anchors.leftMargin: 10
value: 35.0
to: 360.0
from: 0.0
}
}
}
}
Scene3D {
id: scene3d
anchors.fill: parent
anchors.leftMargin: 200
anchors.topMargin: 10
anchors.rightMargin: 10
anchors.bottomMargin: 10
focus: true
aspects: ["input", "logic"]
cameraAspectRatioMode: Scene3D.AutomaticAspectRatio
SceneRoot {
id: root
}
}
}
}
SceneRoot.qml
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Extras 2.0
import Qt3D.Input 2.0
import QtQuick 2.0 as QQ2
Entity {
id: sceneRoot
Camera {
id: camera
projectionType: CameraLens.PerspectiveProjection
fieldOfView 仅在projectionType 为
fieldOfView: 45
nearPlane: 0.1
farPlane: 1000.0
position: Qt.vector3d(0.0, 4.0, 15.0)
upVector: Qt.vector3d(0.0, 1.0, 0.0)
viewCenter: Qt.vector3d(0.0, -2.0, 0.0)
}
FirstPersonCameraController {
camera: camera
}
Entity {
DirectionalLight {
id: directional
worldDirection: Qt.vector3d(0.3, -1.0, 5.0).normalized();
color: "#fff2a3"
intensity: 0.01
}
Transform {
id: lightpostransform
translation: Qt.vector3d(0.0, 50.0, 60.0)
}
components: [lightpostransform, directional]
}
Entity {
PointLight {
id: pointL
color: "#fff2a3"
}
Transform{
id: plightpostransform
translation: Qt.vector3d(0.0, 4.0, 15.0)
}
components: [plightpostransform, pointL]
}
components: [
RenderSettings {
activeFrameGraph: ForwardRenderer {
id: renderer
clearColor: "black"
camera: camera
}
},
InputSettings { }
]
Water { }
}
Water.qml
import Qt3D.Core 2.0
import Qt3D.Render 2.0
import Qt3D.Input 2.0
import Qt3D.Extras 2.0
import QtQuick 2.0 as QQ2
Entity {
id: water
WaterMaterial {
id: watermaterial
property real tox: 0.0
property real toy: 0.0
property real vertY: 1.0
property real waveRandomAnim: 0.0
diffuse: "qrc:/textures/WaterDiffuse.jpg"
normal: "qrc:/textures/WaterNormal.jpg"
specular: "qrc:/textures/WaterSpecular.jpg"
wave: "qrc:/textures/Waterwave.jpg"
sky: "qrc:/textures/sky.jpg"
foam: "qrc:/textures/foam.jpg"
textureScale: slider1.value
wavescale: vertY * slider2.value
specularity: slider3.value
offsetx: tox * slider5.value
offsety: toy * slider5.value
normalAmount: slider8.value
waveheight: slider6.value
waveStrenght: slider7.value
shininess: 100
waveRandom: waveRandomAnim
}
Mesh {
id: watermesh
source: "qrc:/models/waterPlane.obj"
}
Transform {
id: waterTransform
property real scale: 1.0
property real rotx: 0.0
scale3D: Qt.vector3d(scale, scale, scale)
rotationY: slider4.value
}
Entity {
id: waterEntity
components: [watermesh, watermaterial, waterTransform]
}
QQ2.SequentialAnimation {
QQ2.NumberAnimation {
target: watermaterial
property: "waveRandomAnim"
to: 3.0
duration: 4000
}
QQ2.NumberAnimation {
target: watermaterial
property: "waveRandomAnim"
to: 1.0
duration: 4000
}
}
QQ2.SequentialAnimation {
running: true
loops: QQ2.Animation.Infinite
QQ2.ParallelAnimation {
QQ2.NumberAnimation {
target: watermaterial
property: "toy"
to: 10.0
duration: 100000
}
QQ2.NumberAnimation {
target: watermaterial
property: "tox"
to: 10.0
duration: 100000
}
}
QQ2.ParallelAnimation {
QQ2.NumberAnimation {
target: watermaterial
property: "toy"
to: 0.0
duration: 0
}
QQ2.NumberAnimation {
target: watermaterial
property: "tox"
to: 0.0
duration: 0
}
}
}
QQ2.SequentialAnimation {
running: true
loops: QQ2.Animation.Infinite
QQ2.NumberAnimation {
target: watermaterial
property: "vertY"
to: 200
duration: 200000
}
QQ2.NumberAnimation {
target: watermaterial
property: "vertY"
to: 2
duration: 200000
}
}
}
WaterMaterial.qml
import Qt3D.Core 2.0
import Qt3D.Render 2.0
Material {
id: root
property color ambient: Qt.rgba(0.15, 0.35, 0.50, 1.0)
property alias diffuse: diffuseTextureImage.source
property alias normal: normalTextureImage.source
property alias wave: waveTextureImage.source
property alias specular: specularTextureImage.source
property alias sky: skyTextureImage.source
property alias foam: foamTextureImage.source
property color specularColor: Qt.rgba(0.2, 0.2, 0.2, 1.0)
property real shininess: 150.0
property real textureScale: 1.0
property real offsetx: 0.0
property real offsety: 0.0
property real wavescale: 0.0
property real specularity: 1.0
property real waveheight: 0.1
property real waveStrenght: 0.1
property real normalAmount: 2.0
property real waveRandom: 1.0
parameters: [
Parameter { name: "ka"; value: Qt.vector3d(root.ambient.r, root.ambient.g, root.ambient.b) },
Parameter {
name: "foamTexture"
value: Texture2D {
id: foamTexture
minificationFilter: Texture.LinearMipMapLinear
magnificationFilter: Texture.Linear
wrapMode {
x: WrapMode.Repeat
y: WrapMode.Repeat
}
generateMipMaps: true
maximumAnisotropy: 16.0
TextureImage { id: foamTextureImage }
}
},
Parameter {
name: "skyTexture"
value: Texture2D {
id: skyTexture
minificationFilter: Texture.LinearMipMapLinear
magnificationFilter: Texture.Linear
wrapMode {
x: WrapMode.Repeat
y: WrapMode.Repeat
}
generateMipMaps: true
maximumAnisotropy: 16.0
TextureImage { id: skyTextureImage }
}
},
Parameter {
name: "waveTexture"
value: Texture2D {
id: waveTexture
minificationFilter: Texture.LinearMipMapLinear
magnificationFilter: Texture.Linear
wrapMode {
x: WrapMode.Repeat
y: WrapMode.Repeat
}
generateMipMaps: true
maximumAnisotropy: 16.0
TextureImage { id: waveTextureImage }
}
},
Parameter {
name: "specularTexture"
value: Texture2D {
id: specularTexture
minificationFilter: Texture.LinearMipMapLinear
magnificationFilter: Texture.Linear
wrapMode {
x: WrapMode.Repeat
y: WrapMode.Repeat
}
generateMipMaps: true
maximumAnisotropy: 16.0
TextureImage { id: specularTextureImage }
}
},
Parameter {
name: "diffuseTexture"
value: Texture2D {
id: diffuseTexture
minificationFilter: Texture.LinearMipMapLinear
magnificationFilter: Texture.Linear
wrapMode {
x: WrapMode.Repeat
y: WrapMode.Repeat
}
generateMipMaps: true
maximumAnisotropy: 16.0
TextureImage { id: diffuseTextureImage }
}
},
Parameter {
name: "normalTexture"
value: Texture2D {
id: normalTexture
minificationFilter: Texture.LinearMipMapLinear
magnificationFilter: Texture.Linear
wrapMode {
x: WrapMode.Repeat
y: WrapMode.Repeat
}
generateMipMaps: true
maximumAnisotropy: 16.0
TextureImage { id: normalTextureImage }
}
},
Parameter {
name: "specularColor"
value: Qt.vector3d(root.specularColor.r, root.specularColor.g, root.specularColor.b)
},
Parameter { name: "shininess"; value: root.shininess },
Parameter { name: "texCoordScale"; value: textureScale },
Parameter { name: "offsetx"; value: root.offsetx },
Parameter { name: "offsety"; value: root.offsety },
Parameter { name: "vertYpos"; value: root.wavescale },
Parameter { name: "specularity"; value: root.specularity },
Parameter { name: "waveheight"; value: root.waveheight },
Parameter { name: "waveStrenght"; value: root.waveStrenght },
Parameter { name: "waveRandom"; value: root.waveRandom },
Parameter { name: "normalAmount"; value: root.normalAmount }
]
effect: Effect {
property string vertex: "qrc:/shaders/gl3/water.vert"
property string fragment: "qrc:/shaders/gl3/water.frag"
property string vertexES: "qrc:/shaders/es2/water.vert"
property string fragmentES: "qrc:/shaders/es2/water.frag"
property string vertexRHI: "qrc:/shaders/rhi/water.vert"
property string fragmentRHI: "qrc:/shaders/rhi/water.frag"
FilterKey {
id: forward
name: "renderingStyle"
value: "forward"
}
ShaderProgram {
id: gl3Shader
vertexShaderCode: loadSource(parent.vertex)
fragmentShaderCode: loadSource(parent.fragment)
}
ShaderProgram {
id: esShader
vertexShaderCode: loadSource(parent.vertexES)
fragmentShaderCode: loadSource(parent.fragmentES)
}
ShaderProgram {
id: rhiShader
vertexShaderCode: loadSource(parent.vertexRHI)
fragmentShaderCode: loadSource(parent.fragmentRHI)
}
AlphaCoverage { id: alphaCoverage }
DepthTest {
id: depth
depthFunction: DepthTest.Less }
techniques: [
Technique {
filterKeys: [ forward ]
graphicsApiFilter {
api: GraphicsApiFilter.OpenGL
profile: GraphicsApiFilter.CoreProfile
majorVersion: 3
minorVersion: 1
}
renderPasses: RenderPass {
shaderProgram: gl3Shader
renderStates: [alphaCoverage ]
}
},
Technique {
filterKeys: [ forward ]
graphicsApiFilter {
api: GraphicsApiFilter.OpenGLES
majorVersion: 2
minorVersion: 0
}
renderPasses: RenderPass {
shaderProgram: esShader
renderStates: [ alphaCoverage ]
}
},
Technique {
filterKeys: [ forward ]
graphicsApiFilter {
api: GraphicsApiFilter.OpenGLES
profile: GraphicsApiFilter.NoProfile
majorVersion: 2
minorVersion: 0
}
renderPasses: RenderPass {
shaderProgram: esShader
renderStates: [ alphaCoverage ]
}
},
Technique {
filterKeys: [ forward ]
graphicsApiFilter {
api: GraphicsApiFilter.RHI
profile: GraphicsApiFilter.NoProfile
majorVersion: 1
minorVersion: 0
}
renderPasses: RenderPass {
shaderProgram: rhiShader
renderStates: [ alphaCoverage ]
}
}
]
}
}
water.vert
#version 150 core
in vec3 vertexPosition;
in vec3 vertexNormal;
in vec2 vertexTexCoord;
in vec4 vertexTangent;
out vec3 worldPosition;
out vec3 worldNormal;
out vec4 worldTangent;
out vec2 texCoord;
out vec2 movtexCoord;
out vec2 multexCoord;
out vec2 waveTexCoord;
out vec2 skyTexCoord;
out vec3 vpos;
uniform mat4 modelMatrix;
uniform mat3 modelNormalMatrix;
uniform mat4 mvp;
uniform float offsetx;
uniform float offsety;
uniform float vertYpos;
uniform float texCoordScale;
uniform float waveheight;
uniform float waveRandom;
void main()
{
texCoord = vertexTexCoord * texCoordScale;
movtexCoord = vertexTexCoord * texCoordScale;
multexCoord = vertexTexCoord * (texCoordScale*0.5);
waveTexCoord = vertexTexCoord * (texCoordScale * 6);
skyTexCoord = vertexTexCoord * (texCoordScale * 0.2);
movtexCoord = vec2(texCoord.x+offsetx,texCoord.y+offsety);
multexCoord = vec2(texCoord.x-offsetx,texCoord.y+offsety);
skyTexCoord = vec2(texCoord.x-(offsetx/2),texCoord.y-(offsety/2));
worldPosition = vec3(modelMatrix * vec4(vertexPosition, 1.0));
worldNormal = normalize(modelNormalMatrix * vertexNormal);
worldTangent.xyz = normalize(vec3(modelMatrix * vec4(vertexTangent.xyz, 0.0)));
worldTangent.w = vertexTangent.w;
float sinPos = (vertexPosition.z)+(vertexPosition.x);
float sinPos2 = (vertexPosition.y/2)+(vertexPosition.z);
vec3 vertMod = vec3(vertexPosition.x,vertexPosition.y,vertexPosition.z);
vertMod = vec3(vertMod.x+=sin(vertYpos*2.2-sinPos2)*waveheight,
vertMod.y=sin(vertYpos*2.2+sinPos)*waveheight,
vertMod.z-=sin(vertYpos*2.2-cos(sinPos2))*waveheight);
vec3 vertModCom = vec3(vertMod.x+=cos(vertYpos*2.2-cos(sinPos2))*waveheight,
vertMod.y=sin(vertYpos*2.2+cos(sinPos))*waveheight,
vertMod.z-=cos(vertYpos*2.2-cos(sinPos))*waveheight);
if(vertexPosition.y < 0.0){vertModCom = vertexPosition;}
else{vertModCom = vertModCom;}
vpos = vertModCom;
gl_Position = mvp * vec4(vertModCom, 1.0);
}
water.frag
#version 150 core
in vec3 worldPosition;
in vec3 worldNormal;
in vec4 worldTangent;
in vec2 texCoord;
in vec2 waveTexCoord;
in vec2 movtexCoord;
in vec2 multexCoord;
in vec2 skyTexCoord;
in vec3 vpos;
in vec3 color;
uniform sampler2D diffuseTexture;
uniform sampler2D specularTexture;
uniform sampler2D normalTexture;
uniform sampler2D waveTexture;
uniform sampler2D skyTexture;
uniform sampler2D foamTexture;
uniform float offsetx;
uniform float offsety;
uniform float specularity;
uniform float waveStrenght;
uniform vec4 ka;
uniform vec3 specularColor;
uniform float shininess;
uniform float normalAmount;
uniform vec3 eyePosition;
out vec4 fragColor;
#pragma include phong.inc.frag
#pragma include coordinatesystems.inc
void main()
{
vec2 waveMovCoord = waveTexCoord;
waveMovCoord.x += offsetx;
waveMovCoord.y -= offsety;
vec4 wave = texture(waveTexture, waveMovCoord);
vec2 newCoord = texCoord;
newCoord.x += wave.r * waveStrenght;
newCoord.y -= wave.b * waveStrenght;
vec4 diffuseTextureColor = texture(diffuseTexture, texCoord);
vec4 specularTextureColor = texture( specularTexture, multexCoord+newCoord) + (texture( specularTexture, movtexCoord+newCoord ));
vec3 tNormal = normalAmount * texture( normalTexture, movtexCoord+newCoord ).rgb - vec3( 1.0 )+(normalAmount * texture( normalTexture, multexCoord+newCoord ).rgb - vec3( 1.0 ));
vec4 skycolor = texture(skyTexture, skyTexCoord);
skycolor = skycolor * 0.4;
vec4 foamTextureColor = texture(foamTexture, texCoord);
mat3 tangentMatrix = calcWorldSpaceToTangentSpaceMatrix(worldNormal, worldTangent);
mat3 invertTangentMatrix = transpose(tangentMatrix);
vec3 wNormal = normalize(invertTangentMatrix * tNormal);
vec3 worldView = normalize(eyePosition - worldPosition);
vec4 diffuse = vec4(diffuseTextureColor.rgb, vpos.y);
vec4 specular = vec4(specularTextureColor.a*specularity);
vec4 outputColor = phongFunction(ka, diffuse, specular, shininess, worldPosition, worldView, wNormal);
outputColor += vec4(skycolor.rgb, vpos.y);
outputColor += (foamTextureColor.rgba*vpos.y);
fragColor = vec4(outputColor.rgb,1.0);
}
|