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:
@import QtQuick 1.1
import Qt.labs.shaders 1.0
Item{
id:container
width: 800
height: 800
Rectangle {id: bookpage;
color:"yellow"
width: parent.width/2;
height: parent.height}
Rectangle {id: bookpage2;
color: "green"
width: parent.width/2;
height: parent.height}
ShaderEffectItem {
width: parent.width/2
height: parent.height
meshResolution: Qt.size(10, 10)property variant frontSource: ShaderEffectSource { sourceItem: bookpage; hideSource: true } property variant backSource: ShaderEffectSource { sourceItem: bookpage2; hideSource: true } property real t: 1 SequentialAnimation on t { loops: Animation.Infinite NumberAnimation { to: 0; duration: 2000; easing.type: Easing.Linear } PauseAnimation { duration: 1600 } NumberAnimation { to: 1; duration: 2000; easing.type: Easing.Linear } PauseAnimation { duration: 1600 } } vertexShader:" uniform highp mat4 qt_ModelViewProjectionMatrix; attribute highp vec4 qt_Vertex; attribute highp vec2 qt_MultiTexCoord0; varying highp vec2 qt_TexCoord0; uniform highp float t; void main() { const float M_PI = 3.14159265358979323846; float rho = t*M_PI; qt_TexCoord0 = qt_MultiTexCoord0; highp vec4 pos = qt_Vertex; pos.x = pos.x*cos(rho)-pos.z*sin(rho); pos.y = pos.y; pos.z = pos.x*sin(rho)+pos.z*cos(rho); gl_Position = qt_ModelViewProjectionMatrix * pos; }" fragmentShader: " uniform sampler2D frontSource; uniform sampler2D backSource; uniform lowp float qt_Opacity; varying highp vec2 qt_TexCoord0; varying lowp float shade; void main() { gl_FragColor = (gl_FrontFacing ? texture2D(frontSource, qt_TexCoord0) : texture2D(backSource, qt_TexCoord0)) * qt_Opacity; } " }
}
@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; "
@
import QtQuick 1.1
import Qt.labs.shaders 1.0Item{
id:container
width: 800
height: 800
Rectangle {id: bookpage;
color:"yellow"
width: parent.width/2;
height: parent.height}
Rectangle {id: bookpage2;
color: "green"
width: parent.width/2;
height: parent.height}
ShaderEffectItem {
width: parent.width/2
height: parent.height
meshResolution: Qt.size(10, 10)property variant frontSource: ShaderEffectSource { sourceItem: bookpage; hideSource: true } property variant backSource: ShaderEffectSource { sourceItem: bookpage2; hideSource: true } property real t: 1 SequentialAnimation on t { loops: Animation.Infinite NumberAnimation { to: 0; duration: 2000; easing.type: Easing.Linear } PauseAnimation { duration: 1600 } NumberAnimation { to: 1; duration: 2000; easing.type: Easing.Linear } PauseAnimation { duration: 1600 } } vertexShader:" uniform highp mat4 qt_ModelViewProjectionMatrix; attribute highp vec4 qt_Vertex; attribute highp vec2 qt_MultiTexCoord0; varying highp vec2 qt_TexCoord0; uniform highp float t; void main() { const float M_PI = 3.14159265358979323846; float rho = t*M_PI; qt_TexCoord0 = qt_MultiTexCoord0; highp vec4 pos = qt_ModelViewProjectionMatrix * qt_Vertex; pos.x = pos.x*cos(rho)-pos.z*sin(rho); pos.y = pos.y; pos.z = pos.x*sin(rho)+pos.z*cos(rho); gl_Position = pos; }" fragmentShader: " uniform sampler2D frontSource; uniform sampler2D backSource; uniform lowp float qt_Opacity; varying highp vec2 qt_TexCoord0; varying lowp float shade; void main() { gl_FragColor = (gl_FrontFacing ? texture2D(frontSource, qt_TexCoord0) : texture2D(backSource, qt_TexCoord0)) * qt_Opacity; } " }
}
@
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 :)
-
third: I want to add a menu on the left and show the rotating rectangle on the right: this is the code
@
import QtQuick 1.1
import Qt.labs.shaders 1.0
Item
{
width: 900
height: 800
Rectangle{
id:rect
color : "black"
width: 100
height: 800
}
Item{
id:container
width: 800
height: 800
anchors.left: rect.right
Rectangle {id: bookpage;
color:"yellow"
width: parent.width/2;
height: parent.height}
Rectangle {id: bookpage2;
color: "green"
width: parent.width/2;
height: parent.height}
ShaderEffectItem {
width: parent.width/2
height: parent.height
meshResolution: Qt.size(10, 10)property variant frontSource: ShaderEffectSource { sourceItem: bookpage; hideSource: true } property variant backSource: ShaderEffectSource { sourceItem: bookpage2; hideSource: true } property real t: 1 SequentialAnimation on t { loops: Animation.Infinite NumberAnimation { to: 0; duration: 2000; easing.type: Easing.Linear } PauseAnimation { duration: 1600 } NumberAnimation { to: 1; duration: 2000; easing.type: Easing.Linear } PauseAnimation { duration: 1600 } } vertexShader:" uniform highp mat4 qt_ModelViewProjectionMatrix; attribute highp vec4 qt_Vertex; attribute highp vec2 qt_MultiTexCoord0; varying highp vec2 qt_TexCoord0; uniform highp float t; void main() { const float M_PI = 3.14159265358979323846; float rho = t*M_PI; qt_TexCoord0 = qt_MultiTexCoord0; highp vec4 pos = qt_ModelViewProjectionMatrix * qt_Vertex; pos.x = pos.x*cos(rho)-pos.z*sin(rho); pos.y = pos.y; pos.z = pos.x*sin(rho)+pos.z*cos(rho); gl_Position = pos; }" fragmentShader: " uniform sampler2D frontSource; uniform sampler2D backSource; uniform lowp float qt_Opacity; varying highp vec2 qt_TexCoord0; varying lowp float shade; void main() { gl_FragColor = (gl_FrontFacing ? texture2D(frontSource, qt_TexCoord0) : texture2D(backSource, qt_TexCoord0)) * qt_Opacity; } " }
}
}
@
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?) -
any help?
-
Hello.
First, this code
@pos.x = pos.xcos(rho)-pos.zsin(rho);
pos.y = pos.y;
pos.z = pos.xsin(rho)+pos.zcos(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:- shift your geometry by {-rotation_origin.x,0,-rotation_origin.z}
- rotate
- shift your geometry back by {rotation_origin.x,0,rotation_origin.z}
In your case I would add uniforms for rotation origin:
@
uniform highp float rotation_origin_x;
uniform highp float rotation_origin_z;
@and modify rotation code like this:
@
float tmpX = pos.x - rotation_origin_x;
float tmpZ = pos.z - rotation_origin_z;pos.x = tmpXcos(rho)-tmpZsin(rho);
pos.z = tmpXsin(rho)+tmpZcos(rho);pos.x += rotation_origin_x;
pos.z += rotation_origin_z;
@