April 10, 2012

hailong hailong
Lab Rat
28 posts

question about Qt Quick Shader (4.8)

 

Hi, I want to use Qt Quick shader to generate a Rotating Rectangle animation, I tried the following code at first:

  1. import QtQuick 1.1
  2. import Qt.labs.shaders 1.0
  3. Item{
  4.     id:container
  5.     width: 800
  6.     height: 800
  7.     Rectangle {id: bookpage;
  8.         color:"yellow"
  9.         width: parent.width/2;
  10.         height: parent.height}
  11.     Rectangle {id: bookpage2;
  12.         color: "green"
  13.         width: parent.width/2;
  14.         height: parent.height}
  15.     ShaderEffectItem {
  16.         width: parent.width/2
  17.         height: parent.height
  18.         meshResolution: Qt.size(10, 10)
  19.  
  20.         property variant frontSource: ShaderEffectSource { sourceItem: bookpage; hideSource: true }
  21.         property variant backSource: ShaderEffectSource { sourceItem: bookpage2; hideSource: true }
  22.         property real t: 1
  23.  
  24.         SequentialAnimation on t {
  25.             loops: Animation.Infinite
  26.             NumberAnimation { to: 0; duration: 2000; easing.type: Easing.Linear }
  27.             PauseAnimation { duration: 1600 }
  28.             NumberAnimation { to: 1; duration: 2000; easing.type: Easing.Linear }
  29.             PauseAnimation { duration: 1600 }
  30.         }
  31.  
  32.         vertexShader:"
  33.        uniform highp mat4 qt_ModelViewProjectionMatrix;
  34.        attribute highp vec4 qt_Vertex;
  35.        attribute highp vec2 qt_MultiTexCoord0;
  36.        varying highp vec2 qt_TexCoord0;
  37.        uniform highp float t;
  38.  
  39.        void main() {
  40.            const float M_PI = 3.14159265358979323846;
  41.            float rho = t*M_PI;
  42.  
  43.                qt_TexCoord0 = qt_MultiTexCoord0;
  44.                highp vec4 pos = qt_Vertex;
  45.  
  46.                pos.x = pos.x*cos(rho)-pos.z*sin(rho);
  47.                pos.y = pos.y;
  48.                pos.z = pos.x*sin(rho)+pos.z*cos(rho);
  49.                gl_Position =  qt_ModelViewProjectionMatrix * pos;
  50.            }"
  51.         fragmentShader: "
  52.            uniform sampler2D frontSource;
  53.            uniform sampler2D backSource;
  54.            uniform lowp float qt_Opacity;
  55.            varying highp vec2 qt_TexCoord0;
  56.            varying lowp float shade;
  57.            void main() {
  58.                gl_FragColor = (gl_FrontFacing ? texture2D(frontSource, qt_TexCoord0)
  59.                                               : texture2D(backSource, qt_TexCoord0))
  60.                              * qt_Opacity;
  61.            }
  62.        "
  63.     }
  64. }

But I don’t get what I want, the rectangle rotated around the left edge (I think this is because the origin is in the left-top corner of the GLViewport)and can’t see the rotation animation(just some quick flash, why? what is the value of qt_Vertex?)

Then I tried the following code, just change pos “highp vec4 pos = qt_ModelViewProjectionMatrix * qt_Vertex; “

  1. import QtQuick 1.1
  2. import Qt.labs.shaders 1.0
  3.  
  4. Item{
  5.     id:container
  6.     width: 800
  7.     height: 800
  8.     Rectangle {id: bookpage;
  9.         color:"yellow"
  10.         width: parent.width/2;
  11.         height: parent.height}
  12.     Rectangle {id: bookpage2;
  13.         color: "green"
  14.         width: parent.width/2;
  15.         height: parent.height}
  16.     ShaderEffectItem {
  17.         width: parent.width/2
  18.         height: parent.height
  19.         meshResolution: Qt.size(10, 10)
  20.  
  21.         property variant frontSource: ShaderEffectSource { sourceItem: bookpage; hideSource: true }
  22.         property variant backSource: ShaderEffectSource { sourceItem: bookpage2; hideSource: true }
  23.         property real t: 1
  24.  
  25.         SequentialAnimation on t {
  26.             loops: Animation.Infinite
  27.             NumberAnimation { to: 0; duration: 2000; easing.type: Easing.Linear }
  28.             PauseAnimation { duration: 1600 }
  29.             NumberAnimation { to: 1; duration: 2000; easing.type: Easing.Linear }
  30.             PauseAnimation { duration: 1600 }
  31.         }
  32.  
  33.         vertexShader:"
  34.        uniform highp mat4 qt_ModelViewProjectionMatrix;
  35.        attribute highp vec4 qt_Vertex;
  36.        attribute highp vec2 qt_MultiTexCoord0;
  37.        varying highp vec2 qt_TexCoord0;
  38.        uniform highp float t;
  39.  
  40.        void main() {
  41.            const float M_PI = 3.14159265358979323846;
  42.            float rho = t*M_PI;
  43.  
  44.                qt_TexCoord0 = qt_MultiTexCoord0;
  45.                highp vec4 pos = qt_ModelViewProjectionMatrix * qt_Vertex;
  46.  
  47.                pos.x = pos.x*cos(rho)-pos.z*sin(rho);
  48.                pos.y = pos.y;
  49.                pos.z = pos.x*sin(rho)+pos.z*cos(rho);
  50.                gl_Position =  pos;
  51.            }"
  52.         fragmentShader: "
  53.            uniform sampler2D frontSource;
  54.            uniform sampler2D backSource;
  55.            uniform lowp float qt_Opacity;
  56.            varying highp vec2 qt_TexCoord0;
  57.            varying lowp float shade;
  58.            void main() {
  59.                gl_FragColor = (gl_FrontFacing ? texture2D(frontSource, qt_TexCoord0)
  60.                                               : texture2D(backSource, qt_TexCoord0))
  61.                              * qt_Opacity;
  62.            }
  63.        "
  64.     }
  65. }

I got what I want :) (after “qt_ModelViewProjectionMatrix * qt_Vertex”, I find the geometry turns into [
(-1,-1), (1,-1)
(-1,1) , (1,1)
]) so the y axis is in the center of the glwidget so my rectangle rotates around the center of the GLWidget, but why it doesn’t flash any more?

to be continued :)

3 replies

April 10, 2012

hailong hailong
Lab Rat
28 posts

third: I want to add a menu on the left and show the rotating rectangle on the right: this is the code

  1. import QtQuick 1.1
  2. import Qt.labs.shaders 1.0
  3. Item
  4. {
  5.     width: 900
  6.     height: 800
  7.     Rectangle{
  8.         id:rect
  9.         color : "black"
  10.         width: 100
  11.         height: 800
  12.     }
  13. Item{
  14.     id:container
  15.     width: 800
  16.     height: 800
  17.     anchors.left: rect.right
  18.     Rectangle {id: bookpage;
  19.         color:"yellow"
  20.         width: parent.width/2;
  21.         height: parent.height}
  22.     Rectangle {id: bookpage2;
  23.         color: "green"
  24.         width: parent.width/2;
  25.         height: parent.height}
  26.     ShaderEffectItem {
  27.         width: parent.width/2
  28.         height: parent.height
  29.         meshResolution: Qt.size(10, 10)
  30.  
  31.         property variant frontSource: ShaderEffectSource { sourceItem: bookpage; hideSource: true }
  32.         property variant backSource: ShaderEffectSource { sourceItem: bookpage2; hideSource: true }
  33.         property real t: 1
  34.  
  35.         SequentialAnimation on t {
  36.             loops: Animation.Infinite
  37.             NumberAnimation { to: 0; duration: 2000; easing.type: Easing.Linear }
  38.             PauseAnimation { duration: 1600 }
  39.             NumberAnimation { to: 1; duration: 2000; easing.type: Easing.Linear }
  40.             PauseAnimation { duration: 1600 }
  41.         }
  42.  
  43.         vertexShader:"
  44.        uniform highp mat4 qt_ModelViewProjectionMatrix;
  45.        attribute highp vec4 qt_Vertex;
  46.        attribute highp vec2 qt_MultiTexCoord0;
  47.        varying highp vec2 qt_TexCoord0;
  48.        uniform highp float t;
  49.  
  50.        void main() {
  51.            const float M_PI = 3.14159265358979323846;
  52.            float rho = t*M_PI;
  53.  
  54.                qt_TexCoord0 = qt_MultiTexCoord0;
  55.                highp vec4 pos = qt_ModelViewProjectionMatrix * qt_Vertex;
  56.  
  57.                pos.x = pos.x*cos(rho)-pos.z*sin(rho);
  58.                pos.y = pos.y;
  59.                pos.z = pos.x*sin(rho)+pos.z*cos(rho);
  60.                gl_Position =  pos;
  61.            }"
  62.         fragmentShader: "
  63.            uniform sampler2D frontSource;
  64.            uniform sampler2D backSource;
  65.            uniform lowp float qt_Opacity;
  66.            varying highp vec2 qt_TexCoord0;
  67.            varying lowp float shade;
  68.            void main() {
  69.                gl_FragColor = (gl_FrontFacing ? texture2D(frontSource, qt_TexCoord0)
  70.                                               : texture2D(backSource, qt_TexCoord0))
  71.                              * qt_Opacity;
  72.            }
  73.        "
  74.     }
  75. }
  76. }
but the rotation breaks, seems that the rotating rectangle item can’t find the Y axis correctly, I think because qt_ModelViewProjectionMatrix will only map the result to the whole viewport ,and the y axis for the whole viewport is in the center of the GLWidget, but my item’s center is not the center of the viewport, so I need to move the rectangle’s edge to the center so I can rotate around the y axis then I move the item back, am I right?

How can I put my rotating rectangle item anywhere I want(I mean to make it a child for an item(call this parent item A) and position it inside Item A) in the glWidget? Can I change the viewport Matrix to the child item area(so the Y axis is in the center of the child item instead of the GLWidget)?
I am new to 3d programming and opengl and I have tried to solve this for two days, can anyone help me? It is better if you can tell me how to debug shader(just output some value of the shader, eg. the vertex value?)

April 11, 2012

hailong hailong
Lab Rat
28 posts

any help?

April 11, 2012

SDubitskiy SDubitskiy
Lab Rat
2 posts

Hello.

————————————————
First, this code

  1. pos.x = pos.x*cos(rho)-pos.z*sin(rho);
  2. pos.y = pos.y;
  3. pos.z = pos.x*sin(rho)+pos.z*cos(rho);

is incorrect, because pos.x will be modified already by the time you calculate new pos.z.
You will need to use temporary variables to avoid this.

————————————————
Second,
your code rotates vertices around the origin of coordinate system.
The trick to rotate things around arbitrary point is three step process:
1. shift your geometry by {-rotation_origin.x,0,-rotation_origin.z}
2. rotate
3. shift your geometry back by {rotation_origin.x,0,rotation_origin.z}

In your case I would add uniforms for rotation origin:

  1. uniform highp float rotation_origin_x;
  2. uniform highp float rotation_origin_z;

and modify rotation code like this:

  1. float tmpX = pos.x - rotation_origin_x;
  2. float tmpZ = pos.z - rotation_origin_z;
  3.  
  4. pos.x = tmpX*cos(rho)-tmpZ*sin(rho);
  5. pos.z = tmpX*sin(rho)+tmpZ*cos(rho);
  6.  
  7. pos.x += rotation_origin_x;
  8. pos.z += rotation_origin_z;

 
  ‹‹ [solved] Moved Project folder      [Solved] QML and Javascript ››

You must log in to post a reply. Not a member yet? Register here!