使用 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 ) {
// [...]
}
我想在 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 ) {
// [...]
}