Qt 3D的研究(四):指定渲染的材质以及效果

时间:2024-03-19 14:02:58

 

Qt 3D的研究(四):指定渲染的材质以及效果

转自@http://blog.csdn.net/gamesdev/article/details/43983493

   

  1. Entity

  2. {

  3. Mesh

  4. {

  5. id: mesh

  6. objectName: "toyPlane"

  7. source: "qrc:/toyplane.obj"

  8. }

  9.  
  10. //! [4]

  11. PhongMaterial

  12. {

  13. id: phongMaterial

  14. }

  15. //! [4]

  16.  
  17. components: [ mesh, phongMaterial ]

  18. }

       运行结果如下:

Qt 3D的研究(四):指定渲染的材质以及效果

       这里我们在//! [4]之间添加了一个常用的材质:Phong材质。Phong光照模型是一种常见的光照模型,他揭示了生成高光的方法。以前我的博客也介绍并且实现了这样的光照模型。之所以它的广泛性,Qt 3D将其封装了一个类,方便操作。图中显示的是使用Phong光照模型,让玩具飞机呈现光滑透明的效果。我们也可以设定具体的参数,让光照呈现不同的效果:设定全局光(ambient)、漫反射(diffuse)、镜面反射(specular)以及自发光亮度(shininess)。添加的代码如下所示:

 
 
  1. import Qt3D 2.0

  2. import Qt3D.Render 2.0

  3.  
  4. Entity

  5. {

  6. id: root

  7.  
  8. Camera

  9. {

  10. id: camera

  11. position: Qt.vector3d( 0.0, 0.0, 40.0 )

  12. projectionType: CameraLens.PerspectiveProjection

  13. fieldOfView: 45

  14. aspectRatio: 16.0 / 9.0

  15. nearPlane : 0.1

  16. farPlane : 1000.0

  17. upVector: Qt.vector3d( 0.0, 1.0, 0.0 )

  18. viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )

  19. }

  20.  
  21. components: FrameGraph

  22. {

  23. ForwardRenderer

  24. {

  25. clearColor: Qt.rgba( 0, 0, 0, 1 )

  26. camera: camera

  27. }

  28. }

  29.  
  30. Entity

  31. {

  32. Mesh

  33. {

  34. id: mesh

  35. objectName: "toyPlane"

  36. source: "qrc:/toyplane.obj"

  37. }

  38.  
  39. //! [4]

  40. PhongMaterial

  41. {

  42. id: phongMaterial

  43. ambient: Qt.rgba( 0.6, 0.2, 0.1, 1 )

  44. diffuse: Qt.rgba( 0.2, 0.6, 0.1, 1 )

  45. specular: Qt.rgba( 0.2, 0.9, 0.1, 1 )

  46. shininess: 0.6

  47. }

  48. //! [4]

  49.  
  50. components: [ mesh, phongMaterial ]

  51. }

  52.  
  53. Configuration

  54. {

  55. controlledCamera: camera

  56. }

  57. }

 

       程序运行结果如下所示:

Qt 3D的研究(四):指定渲染的材质以及效果

       这里呈现了一个金光闪闪的玩具飞机模型。

       如果我们想自己写着色器来为我们的模型着色,Qt 3D也提供了相应的方法,可以不借助C++代码来实现,直接在QML指定即可。这里我们需要设定Effect(效果)、Technique(使用的OpenGL技术)、RenderPass(渲染遍数)、ShaderProgram(着色器)。下面是QML代码:

 
 
  1. import Qt3D 2.0

  2. import Qt3D.Render 2.0

  3.  
  4. Entity

  5. {

  6. id: root

  7.  
  8. Camera

  9. {

  10. id: camera

  11. position: Qt.vector3d( 0.0, 0.0, 40.0 )

  12. projectionType: CameraLens.PerspectiveProjection

  13. fieldOfView: 45

  14. aspectRatio: 16.0 / 9.0

  15. nearPlane : 0.1

  16. farPlane : 1000.0

  17. upVector: Qt.vector3d( 0.0, 1.0, 0.0 )

  18. viewCenter: Qt.vector3d( 0.0, 0.0, 0.0 )

  19. }

  20.  
  21. components: FrameGraph

  22. {

  23. ForwardRenderer

  24. {

  25. clearColor: Qt.rgba( 0, 0, 0, 1 )

  26. camera: camera

  27. }

  28. }

  29.  
  30. Entity

  31. {

  32. Mesh

  33. {

  34. id: mesh

  35. source: "qrc:/toyplane.obj"

  36. }

  37.  
  38. //! [5]

  39. Material

  40. {

  41. id: material

  42. effect: effect

  43.  
  44. Effect

  45. {

  46. id: effect

  47. techniques: [ technique ]

  48.  
  49. Technique

  50. {

  51. id: technique

  52. openGLFilter

  53. {

  54. api: OpenGLFilter.Desktop

  55. profile: OpenGLFilter.None

  56. majorVersion: 2

  57. minorVersion: 0

  58. }

  59.  
  60. renderPasses: [ renderPass ]

  61.  
  62. RenderPass

  63. {

  64. id: renderPass

  65. shaderProgram: simpleSP

  66.  
  67. ShaderProgram

  68. {

  69. id: simpleSP

  70. vertexShaderCode: loadSource( "qrc:/Simple.vert" )

  71. fragmentShaderCode: loadSource( "qrc:/Simple.frag" )

  72. }

  73. }

  74. }

  75. }

  76. }

  77. //! [5]

  78.  
  79. components: [ mesh, material ]

  80. }

  81.  
  82. Configuration

  83. {

  84. controlledCamera: camera

  85. }

  86. }

       代码新添加的部分在//! [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,他们如下所示:

 
 
  1. // Simple.vert

  2. #version 100

  3.  
  4. attribute vec3 vertexPosition;

  5. uniform mat4 mvp;

  6.  
  7. void main( void )

  8. {

  9. gl_Position = mvp * vec4( vertexPosition, 1.0 );

  10. }

 
  1. // Simple.frag

  2. #version 100

  3.  
  4. void main( void )

  5. {

  6. gl_FragColor = vec4( 1.0, 0.8, 0.2, 1.0 );

  7. }

 

       这里需要说明的是,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

※这些变量并没有在文档中列出,可能随着版本的变化而变得不同

 

       这是一个非常简单的着色器,它以单色输出。下面是运行截图:

Qt 3D的研究(四):指定渲染的材质以及效果

       通过逐渐丰富着色器的内容,可以让程序获取更加美妙的渲染效果。

Qt 3D的研究(四):指定渲染的材质以及效果