Qt 3D的研究(四):指定渲染的材质以及效果
转自@http://blog.csdn.net/gamesdev/article/details/43983493
-
Entity -
{ -
Mesh -
{ -
id: mesh -
objectName: "toyPlane" -
source: "qrc:/toyplane.obj" -
} -
//! [4] -
PhongMaterial -
{ -
id: phongMaterial -
} -
//! [4] -
components: [ mesh, phongMaterial ] -
}
运行结果如下:
这里我们在//! [4]之间添加了一个常用的材质:Phong材质。Phong光照模型是一种常见的光照模型,他揭示了生成高光的方法。以前我的博客也介绍并且实现了这样的光照模型。之所以它的广泛性,Qt 3D将其封装了一个类,方便操作。图中显示的是使用Phong光照模型,让玩具飞机呈现光滑透明的效果。我们也可以设定具体的参数,让光照呈现不同的效果:设定全局光(ambient)、漫反射(diffuse)、镜面反射(specular)以及自发光亮度(shininess)。添加的代码如下所示:
-
import Qt3D 2.0 -
import Qt3D.Render 2.0 -
Entity -
{ -
id: root -
Camera -
{ -
id: camera -
position: Qt.vector3d( 0.0, 0.0, 40.0 ) -
projectionType: CameraLens.PerspectiveProjection -
fieldOfView: 45 -
aspectRatio: 16.0 / 9.0 -
nearPlane : 0.1 -
farPlane : 1000.0 -
upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) -
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) -
} -
components: FrameGraph -
{ -
ForwardRenderer -
{ -
clearColor: Qt.rgba( 0, 0, 0, 1 ) -
camera: camera -
} -
} -
Entity -
{ -
Mesh -
{ -
id: mesh -
objectName: "toyPlane" -
source: "qrc:/toyplane.obj" -
} -
//! [4] -
PhongMaterial -
{ -
id: phongMaterial -
ambient: Qt.rgba( 0.6, 0.2, 0.1, 1 ) -
diffuse: Qt.rgba( 0.2, 0.6, 0.1, 1 ) -
specular: Qt.rgba( 0.2, 0.9, 0.1, 1 ) -
shininess: 0.6 -
} -
//! [4] -
components: [ mesh, phongMaterial ] -
} -
Configuration -
{ -
controlledCamera: camera -
} -
}
程序运行结果如下所示:
这里呈现了一个金光闪闪的玩具飞机模型。
如果我们想自己写着色器来为我们的模型着色,Qt 3D也提供了相应的方法,可以不借助C++代码来实现,直接在QML指定即可。这里我们需要设定Effect(效果)、Technique(使用的OpenGL技术)、RenderPass(渲染遍数)、ShaderProgram(着色器)。下面是QML代码:
-
import Qt3D 2.0 -
import Qt3D.Render 2.0 -
Entity -
{ -
id: root -
Camera -
{ -
id: camera -
position: Qt.vector3d( 0.0, 0.0, 40.0 ) -
projectionType: CameraLens.PerspectiveProjection -
fieldOfView: 45 -
aspectRatio: 16.0 / 9.0 -
nearPlane : 0.1 -
farPlane : 1000.0 -
upVector: Qt.vector3d( 0.0, 1.0, 0.0 ) -
viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 ) -
} -
components: FrameGraph -
{ -
ForwardRenderer -
{ -
clearColor: Qt.rgba( 0, 0, 0, 1 ) -
camera: camera -
} -
} -
Entity -
{ -
Mesh -
{ -
id: mesh -
source: "qrc:/toyplane.obj" -
} -
//! [5] -
Material -
{ -
id: material -
effect: effect -
Effect -
{ -
id: effect -
techniques: [ technique ] -
Technique -
{ -
id: technique -
openGLFilter -
{ -
api: OpenGLFilter.Desktop -
profile: OpenGLFilter.None -
majorVersion: 2 -
minorVersion: 0 -
} -
renderPasses: [ renderPass ] -
RenderPass -
{ -
id: renderPass -
shaderProgram: simpleSP -
ShaderProgram -
{ -
id: simpleSP -
vertexShaderCode: loadSource( "qrc:/Simple.vert" ) -
fragmentShaderCode: loadSource( "qrc:/Simple.frag" ) -
} -
} -
} -
} -
} -
//! [5] -
components: [ mesh, material ] -
} -
Configuration -
{ -
controlledCamera: camera -
} -
}
代码新添加的部分在//! [5]中。这里我们没有使用默认的PhoneMaterial,而是使用它的父类Material,并且通过指定Effect来实现自己需要的渲染效果。Effect中含有的Technique表示使用的OpenGL技术,因为OpenGL有多个版本,分OpenGL和OpenGL ES,还分core profile和compatibility profile,这样使得种种技术变得十分繁杂。所以Qt 3D提出了Technique这个概念。通过指定api、profile以及majorVersion和minorVersion版本,来使用我们需要的OpenGL API。接着是RenderPass渲染遍(这个翻译总感觉不好),它表示一次渲染需要多少遍渲染操作。比如说在shadow map这个技术中,需要渲染不止一遍,所以要指定两个RenderPass。而每一遍的RenderPass,需要指定着色器程序。因此,我们载入相应的着色器文件,来让系统编译以及链接之,最后得以渲染。本例中,我们实现一个最简单的着色器Simple.vert以及Simple.frag,他们如下所示:
-
// Simple.vert -
#version 100 -
attribute vec3 vertexPosition; -
uniform mat4 mvp; -
void main( void ) -
{ -
gl_Position = mvp * vec4( vertexPosition, 1.0 ); -
}
-
// Simple.frag -
#version 100 -
void main( void ) -
{ -
gl_FragColor = vec4( 1.0, 0.8, 0.2, 1.0 ); -
}
这里需要说明的是,Qt 3D在MeshData中指定了默认的属性(attribute)变量和一致性(uniform)变量,它们如下:
|
属性(attribute)变量 |
一致性(uniform)变量 |
|
vertexPosition |
modelMatrix |
|
vertexTexCoord |
viewMatrix |
|
vertexNormal |
projectionMatrix |
|
vertexColor |
modelView |
|
vertexTangent |
modelViewProjection |
|
|
mvp |
|
|
inverseModelMatrix |
|
|
inverViewMatrix |
|
|
inverseProjectionMatrix |
|
|
inverseModelView |
|
|
inverseModelViewProjection |
|
|
modelNormalMatrix |
|
|
modelViewNormal |
|
|
viewportMatrix |
|
|
inverseViewportMatrix |
|
|
time |
※这些变量并没有在文档中列出,可能随着版本的变化而变得不同
这是一个非常简单的着色器,它以单色输出。下面是运行截图:
通过逐渐丰富着色器的内容,可以让程序获取更加美妙的渲染效果。