I want to create a CircularGauge in QML in which the needle moves anti-clockwise and the shader is drawn from +145 deg to needle position.
I implemented a CircularGaugeStyle for the style property of CircularGauge. I used the below code to make the shader effect on the gauge:
background: Canvas {
onPaint: {
var ctx = getContext("2d");
ctx.reset();
paintBackground(ctx);
}
ShaderEffect {
id: gauge
anchors.fill: parent
opacity: 0.75
// Angles measured clockwise from up, in range -pi to pi
property real angleBase: -2.53073
property real angle: degToRad(needleRotation)
vertexShader: "
uniform highp mat4 qt_Matrix;
attribute highp vec4 qt_Vertex;
attribute highp vec2 qt_MultiTexCoord0;
varying highp vec2 coord;
void main() {
coord = qt_MultiTexCoord0;
gl_Position = qt_Matrix * qt_Vertex;
}"
fragmentShader: "
uniform lowp float qt_Opacity;
uniform highp float angleBase;
uniform highp float angle;
varying highp vec2 coord;
void main() {
gl_FragColor = vec4(0.0,0.0,0.0,0.0);
highp vec2 d=2.0*coord-vec2(1.0,1.0);
highp float r=length(d);
if (0.55<=r && r<=0.95) {
highp float a=atan2(d.x,-d.y);
if (angleBase<=a && a<=angle) {
highp float p=(a-angleBase)/(angle-angleBase);
gl_FragColor = vec4(0.0,0.0,p,p) * qt_Opacity;
}
}
}"
}
}
In this code the needle moves anti-clock wise setting the min max angle but the shader effect is drawn clock-wise. I changed the following:
property real angleBase: 2.53073 // +145 deg
making the baseAngle to +145 deg.
if (0.55<=r && r<=0.95) { // the area in gauge that should be painted
highp float a=atan2(d.y,-d.x); //getting the other side of the angle (pi/2 - theta)
if (a>=angleBase && angle>=a) { //since we want to draw from +2.5 to needle position (in radians)
highp float p=(angleBase-a)/(angleBase-angle);
gl_FragColor = vec4(0.0,0.0,p,p) * qt_Opacity;
}
}
Here is the image of the output with the shader going clock-wise:
The change in code to draw anti-clockwise is not working. What am I doing wrong? Is my understanding of calculating the atan2 not correct?
It all depends on how the current angle
is computed.
In your application 0° seems to be at the top. Keep the angle of -145° (-2.53073)
property real angleBase: -2.53073
In the original code, the angle (a
) was computed by a=atan2(d.x,-d.y);
. If you want to flip that around the y axis, then you the new computation is:
highp vec2 d = coord * 2.0 - vec2(1.0);
highp float r = length(d);
if (0.55<=r && r<=0.95) {
highp float a = atan2(-d.x, -d.y);
if (angleBase <= a && a <= angle) {
highp float p=(a-angleBase)/(angle-angleBase);
// [...]
}
}
In the above algorithm is assumed, that angle
is in range [-145°, 145°]. Further more the top left coord
is (0, 0) and the bottom right coord
is (1, 1)
If angle
is in range [0°, 290°], then alpha has to be suited to the baseAngle
:
if (angleBase <= a && a <= angle) {
if (angleBase <= a && a <= angle+angleBase ) {
// [...]
}