GLSL上的稳健atan(y,x)用于将XY坐标转换为角度 [英] Robust atan(y,x) on GLSL for converting XY coordinate to angle

查看:835
本文介绍了GLSL上的稳健atan(y,x)用于将XY坐标转换为角度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在GLSL(我正在使用的3.00)中,有两个版本的 atan():atan(y_over_x)只能返回-PI/2,PI/2之间的角度,而atan(y/x)可以考虑所有4个象限,因此角度范围涵盖了-PI,PI的所有内容,就像C ++.

In GLSL (specifically 3.00 that I'm using), there are two versions of atan(): atan(y_over_x) can only return angles between -PI/2, PI/2, while atan(y/x) can take all 4 quadrants into account so the angle range covers everything from -PI, PI, much like atan2() in C++.

我想使用第二个atan将XY坐标转换为角度. 但是,GLSL中的atan()除了不能处理x = 0之外,还不是很稳定.尤其是在x接近零的情况下,除法运算可能会溢出,从而导致相反的结果角度(您会获得与-PI/2接近的值,假设您会获得近似PI/2的值).

I would like to use the second atan to convert XY coordinates to angle. However, atan() in GLSL, besides not able to handle when x = 0, is not very stable. Especially where x is close to zero, the division can overflow resulting in an opposite resulting angle (you get something close to -PI/2 where you suppose to get approximately PI/2).

什么是我们可以在GLSL atan(y,x)之上构建的更好,更简单的实现呢?

What is a good, simple implementation that we can build on top of GLSL atan(y,x) to make it more robust?

推荐答案

我将回答我自己的问题,以分享我的知识.我们首先注意到,当x接近零时,会发生不稳定性.但是,我们也可以将其翻译为abs(x) << abs(y).因此,首先我们将平面(假设我们在单位圆上)划分为两个区域:一个区域位于|x| <= |y|,另一个区域位于|x| > |y|,如下所示:

I'm going to answer my own question to share my knowledge. We first notice that the instability happens when x is near zero. However, we can also translate that as abs(x) << abs(y). So first we divide the plane (assuming we are on a unit circle) into two regions: one where |x| <= |y| and another where |x| > |y|, as shown below:

我们知道atan(x,y)在绿色区域中要稳定得多-当x接近零时,我们简单地得到一个接近atan(0.0)的值,该值在数值上非常稳定,而通常的atan(y,x)则更稳定在橙色区域.您还可以使自己相信这种关系:

We know that atan(x,y) is much more stable in the green region -- when x is close to zero we simply have something close to atan(0.0) which is very stable numerically, while the usual atan(y,x) is more stable in the orange region. You can also convince yourself that this relationship:

atan(x,y) = PI/2 - atan(y,x)

保留所有未定义的非原点(x,y),我们正在谈论的atan(y,x)能够返回整个-PI,PI范围内的角度值,而不是atan(y_over_x)仅返回-PI/2,PI/2之间的角度.因此,我们强大的GLSL atan2()例程非常简单:

holds for all non-origin (x,y), where it is undefined, and we are talking about atan(y,x) that is able to return angle value in the entire range of -PI,PI, not atan(y_over_x) which only returns angle between -PI/2, PI/2. Therefore, our robust atan2() routine for GLSL is quite simple:

float atan2(in float y, in float x)
{
    bool s = (abs(x) > abs(y));
    return mix(PI/2.0 - atan(x,y), atan(y,x), s);
}

作为旁注,数学函数atan(x)的标识实际上是:

As a side note, the identity for mathematical function atan(x) is actually:

atan(x) + atan(1/x) = sgn(x) * PI/2

这是正确的,因为它的范围是(-PI/2,PI/2).

which is true because its range is (-PI/2, PI/2).

这篇关于GLSL上的稳健atan(y,x)用于将XY坐标转换为角度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆