c++ - GLSL 上的强大 atan(y,x) 用于将 XY 坐标转换为角度

标签 c++ glsl coordinates atan2 numerical-stability

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

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

我们可以在 GLSL atan(y,x) 之上构建什么好的、简单的实现以使其更健壮?

最佳答案

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

two regions

我们知道 atan(x,y)在绿色区域更加稳定——当 x 接近于零时,我们只是有一个接近 atan(0.0) 的值,它在数值上非常稳定,而通常的 atan(y,x)在橙色区域更稳定。你也可以说服自己这种关系:

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

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

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)实际上是:

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

这是真的,因为它的范围是 (-PI/2, PI/2)。

graph

关于c++ - GLSL 上的强大 atan(y,x) 用于将 XY 坐标转换为角度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26070410/

相关文章:

java - 如何根据中心坐标确定矩形的左上坐标?

math - 如何检查一个点是否在另外两个点之间,但不限于在一条直线上对齐?

体系结构 x86_64 的 C++ undefined symbol (类似)

c++ - 在某些情况下,我的快速排序实现失败

opengl - 选择性 nvidia #pragma optionNV(全部展开)

opengl - 几何着色器中的宽线表现得很奇怪

c++ - 使用 constexpr 或模板元编程简化较长的展开循环表达式

c++ - C++ 应用程序的 XML 用法

java - OpenGL绘制三角形不显示+ glClearColor不设置屏幕颜色

image - 从 PDF 中提取具有坐标和大小的图像和单词