使用 ShaderEffect 的 fragmentShader 属性 在 QML CircularGaugeStyle 中逆时针着色

Shading anti-clockwise in QML CircularGaugeStyle using thge fragmentShader property of ShaderEffect

我想在 QML 中创建一个 CircularGauge,其中指针逆时针移动,着色器从指针位置 +145 度绘制。

我为 CircularGauge 的样式 属性 实现了 CircularGaugeStyle。我使用以下代码在仪表上制作着色器效果:

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;
              }
            }
          }"
      }
}

在此代码中,指针逆时针移动,设置最小最大角度,但着色器效果是顺时针绘制的。我更改了以下内容:

property real angleBase: 2.53073 // +145 deg

使 baseAngle 为 +145 度。

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;
  }
}

这是着色器顺时针方向的输出图像:

逆时针绘制的代码更改无效。我究竟做错了什么?我对计算atan2的理解不正确吗?

这完全取决于当前 angle 的计算方式。

在您的应用程序中,0° 似乎在顶部。保持-145°的角度(-2.53073)

property real angleBase: -2.53073

在原来的代码中,角度(a)是由a=atan2(d.x,-d.y);计算出来的。如果你想围绕 y 轴翻转它,那么你的新计算是:

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);
        
        // [...]
    }
}

在上述算法中,假设angle在[-145°, 145°]范围内。此外,左上角 coord 是 (0, 0) 右下角 coord 是 (1, 1)

如果 angle 在 [0°, 290°] 范围内,则 alpha 必须适合 baseAngle:

if (angleBase <= a && a <= angle) {

if (angleBase <= a && a <= angle+angleBase ) {
    // [...]
}