Study on Qt 3D (5): Gooch Shader and goochshader
Study on Qt 3D (5): Gooch Shader
A major advantage of Qt 3D is data-driven representation of C ++ and GLSL using QML. The advantage of Dynamic Language is obvious. In the previous study, I implemented a very simple coloring tool. Next, we can create more colorful coloring effects by setting the data of the coloring tool. In the beginning, let's start with several Non-real pasters (Non-Photorealistic Rendering.
Jiang caiyang's original article, first published at: http://blog.csdn.net/gamesdev/article/details/44007495. Welcome to the discussion.
First, we start to study the Gooch shader. The Gooch shader is a variant of the Phong shader and is generally used in technical illustrations. For example, the effect of the following illustration can be completed using the Gooch shader.
Next, we will slightly modify the QML code in the previous article to support our Gooch shader. The following code is added:
import Qt3D 2.0import Qt3D.Render 2.0Entity{ 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( 1.0, 0.8, 0.2, 1 ) camera: camera } } Entity { Mesh { id: mesh source: "qrc:/toyplane.obj" } 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 ] //! [5] parameters: [ Parameter { name: "lightPosition" value: camera.position }, Parameter { name: "surfaceColor" value: Qt.rgba( 0.9, 0.9, 0.9, 1 ) }, Parameter { name: "warmColor" value: Qt.rgba( 0.8, 0.3, 0.0, 1 ) }, Parameter { name: "coolColor" value: Qt.rgba( 0.0, 0.3, 0.2, 1 ) }, Parameter { name: "diffuseWarm" value: 0.4 }, Parameter { name: "diffuseCool" value: 0.6 } ] //! [5] RenderPass { id: renderPass shaderProgram: goochSP ShaderProgram { id: goochSP vertexShaderCode: loadSource( "qrc:/Gooch.vert" ) fragmentShaderCode: loadSource( "qrc:/Gooch.frag" ) } } } } } components: [ mesh, material ] } Configuration { controlledCamera: camera }}
At //! [5] defines some parameters to be passed in. They are lightPosition, surfaceColor, warmColor, coolColor, diffuseWarm, and diffuseCool. These are the uniform parameters that need to be defined in the shader, so we must specify them explicitly in QML. In fact, the definition of Parameter, Qt 3D is exquisite. Qt 3D is such a rule: Parameter defined on the outer layer will overwrite the same name Parameter on the inner layer. That is to say, the Parameter on the inner layer can be modified as a default Parameter through the Parameter on the outer layer. Currently, the top priority of Qt3D coverage is: Material → Effect → Technique → RenderPass → GLSL default value.
After all, let's see how GLSL works.
// Gooch. vert # version 100 // default attribute vec3 vertexPosition provided by Qt 3D; attribute vec3 vertexNormal; uniform mat4 modelView; uniform mat4 modelNormalMatrix; uniform mat4 mvp; // independently provided parameter uniform vec3 lightPosition; varying vec3 reflectVec; varying vec3 viewVec; varying float NdotL; void main (void) {vec3 ecPos = (modelView * vec4 (vertexPosition, 1.0 )). xyz; vec3 normal = normalize (modelNormalMatrix * vec4 (vertexNormal, 1.0 )). xyz; vec3 lightVec = normalize (lightPosition-ecPos); reflectVec = normalize (reflect (-lightVec, normal); viewVec = normalize (-ecPos); NdotL = (dot (lightVec, normal) + 1.0) * 0.5; gl_Position = mvp * vec4 (vertexPosition, 1.0 );}
In the vertex coloring tool, we still find NdotL like the Phong illumination model and use it in the part coloring tool. Then we calculate reflectVec and viewVec as the unit vectors of reflection and vision vectors, used in the part coloring tool.
// Gooch. frag # version 100 // The uniform vec3 surfaceColor, uniform vec3 warmColor, uniform vec3 coolColor, uniform float volume, uniform float diffuseCool, varying vec3 volume, and varying vec3 viewVec; varying float NdotL; void main (void) {vec3 kcool = min (coolColor + diffuseCool * surfaceColor, 1.0); vec3 kwarm = min (warmColor + diffuseWarm * surfaceColor, 1.0 ); vec3 kfinal = mix (kcool, kwarm, NdotL); float spec = max (dot (reflectVec, viewVec), 0.0); spec = pow (spec, 32.0 ); gl_FragColor = vec4 (min (kfinal + spec, 1.0), 1.0 );}
In the part coloring tool, we define the plane color, warm color, cold color and their corresponding parameters. These parameters require us to use the mix function (linear interpolation function) to finally obtain the basic color, and then we calculate the reflected light on the mirror to make the model aircraft shine, and finally add these values, the color of the clip is obtained.
The demo program is as follows:
Well, you can adjust parameters to get better effects. However, a better method is to define a color texture to get more interesting rendering effects:
The method is as follows: first, we define a color palette texture:
Then add such a parameter and the corresponding texture object to QML:
parameters:[Parameter{name: "lightPosition"value: camera.position},Parameter{name: "surfaceColor"value: Qt.rgba( 0.9, 0.9, 0.9, 1 )},Parameter{name: "warmColor"value: Qt.rgba( 0.8, 0.3, 0.0, 1 )},Parameter{name: "coolColor"value: Qt.rgba( 0.0, 0.3, 0.2, 1 )},Parameter{name: "diffuseWarm"value: 0.4},Parameter{name: "diffuseCool"value: 0.6},//! [6]Parameter{name: "texPalette"value: texPalette}]Texture2D{id: texPaletteTextureImage{source: "qrc:/texturePalette.png"}}//! [6]
The Texture2D class and TextureImage class are defined here. As the texture loader, The TextureImage class can accept the image types that QImage can load. Then, as the default attribute of the Texture2D class, a texture sampler2D (texture sampler2D) is generated ), load it into GLSL as an uniform variable.
The vertex shader in GLSL remains unchanged, and the part shader is modified as follows:
// Gooch. frag # version 100 // The uniform vec3 surfaceColor, uniform vec3 warmColor, uniform vec3 coolColor, uniform float volume, uniform float diffuseCool, varying vec3 volume, and varying vec3 viewVec; varying float NdotL; uniform extends texPalette; void main (void) {vec3 kcool = min (coolColor + diffuseCool * surfaceColor, 1.0); vec3 kwarm = min (warmColor + diffuseWarm * surfaceColor, 1.0 ); //! [6] vec3 kfinal = texture2D (texPalette, vec2 (NdotL, 1.0). xyz ;//! [6] float spec = max (dot (reflectVec, viewVec), 0.0); spec = pow (spec, 32.0); gl_FragColor = vec4 (min (kfinal + spec, 1.0 ), (1.0 );}
Here, the sampler2D variable texturePalette is added and the value of kfinal is modified.
References:
Http://www.jonatron.ca/tag/shader/
Http://shiba.hpe.sh.cn/jiaoyanzu/wuli/showArticle.aspx? ArticleId = 333 & classId = 4