glsl弧不能绕圆圈正确旋转

时间:2015-05-26 18:02:42

标签: math geometry glsl webgl

我尝试创建一个有圆弧旋转的着色器,你可以在这里看到一个例子:

https://www.shadertoy.com/view/MljGDK

#define center vec2(0.5)
#define pi 3.1415926535897932384626433832795
#define resolution 250.0
#define arcColor vec4(0.1, 0.2, 0.9, 1.0)

vec4 arc(vec2 uv, vec2 pos, float radius, float angle, vec4 color) {
    vec2 b = (pos * resolution - uv * resolution);
    float d = 1.0 - clamp(length(b) - radius * resolution, 0.0, 1.0);
    float a1 = atan(-b.x, -b.y);
    float a2 = atan(b.x, b.y);
    //return color * smoothstep(0.0, d, angle - a);
    return color * (a2 >= radians(angle) - pi / 8.0 && a2 <= radians(angle) + pi / 8.0 ? d : 0.0);
}

vec4 circle(vec2 uv, vec2 pos, float radius, vec4 color) {
    float d = length(pos * resolution - uv * resolution) - radius * resolution;
    float t = clamp(d, 0.0, 1.0);
    return color * (1.0 - t);
}

void mainImage ( out vec4 fragColor, in vec2 fragCoord ) {
    vec2 uv = fragCoord.xy / iResolution.xy;
    vec4 arcSection = arc(uv, center, 0.5, mod(iGlobalTime*100.0, 360.0), arcColor);
    vec4 hole = circle(uv, center, 0.45, vec4(1.0));
    fragColor = arcSection - hole;
}

然而,我不知道为什么atan会返回切断圆极处弧线的值。我的印象是glsl中的atan(x,y)实现为atan2。

非常感谢任何改进圆弧旋转或使算法更清洁的帮助。

2 个答案:

答案 0 :(得分:1)

您的问题是未能允许结果的循环性质。在摘要中:距角度359.0的角度有多远?根据你的代码,它距离359度而不是1度。

建议的替代方案:

float a2Diff = mod(radians(angle) - a2, pi * 2.0);

return color * ((a2Diff >= pi * 15.0 / 8.0 || a2Diff <= pi / 8.0) ? d : 0.0);

因此,您需要计算两个角度之间的差异,创建一个固定的中心,然后使用mod进行潜在的回绕。

答案 1 :(得分:1)

你需要小心环绕,以便将接近2 * pi的角度视为接近于0.这是一个有效的代码示例:

#define center vec2(0.5, 0.5)
#define pi 3.1415926535897932384626433832795
#define resolution 250.0
#define arcColor vec4(0.1, 0.2, 0.9, 1.0)

vec4 arc(vec2 uv, vec2 pos, float radius1, float radius2, float angle, vec4 color) {
    vec2 b = (pos * resolution - uv * resolution);
    float angdist = mod(atan(b.x, b.y) - angle, 2.0*pi);
    return color * ((angdist < pi/8.0)
                    && (length(b) >= radius1 * resolution)
                    && (length(b) <= radius2 * resolution) ? 1.0 : 0.0);
}

void mainImage ( out vec4 fragColor, in vec2 fragCoord ) {
    vec2 uv = fragCoord.xy / iResolution.xy;
    vec4 arcSection = arc(uv, center, 0.45, 0.5, radians(mod(iGlobalTime*100.0, 360.0)), arcColor);
    fragColor = arcSection;
}