与OpenGL GLSL中的atan(y/x)和atan2(y,x)有什么不同

lin*_*llo 3 opengl math glsl atan2 coordinate-transformation

我在理解glsl中函数atan的结果时遇到了一些问题.文档也缺乏.

例如,我需要将顶点转换为球面坐标,转换球面坐标的半径,然后将其转换回笛卡尔坐标.我在以0为中心的半径为2的二氧化碳球的顶点上使用以下变换.

vec3 to_sphere(vec3 P)
{
    float r = sqrt(P.x*P.x + P.y*P.y + P.z*P.z);
    float theta = atan(P.y,(P.x+1E-18));
    float phi= acos(P.z/r); // in [0,pi]
    return vec3(r,theta, phi);
}

vec3 to_cart(vec3 P)
{
    float r = P.x;
    float theta = P.y;
    float phi = P.z;
    return r * vec3(cos(phi)*sin(theta),sin(phi)*sin(theta),cos(theta);
}

void main()
{
    vec4 V = gl_Vertex.xyz;
    vec3 S = to_sphere(V.xyz);
    S.x += S.y;
    V.xyz = to_cartesian(S);

    gl_Position = gl_ModelViewProjectionMatrix * V;
}
Run Code Online (Sandbox Code Playgroud)

但如果我使用atan(y/x)或者结果会有所不同atan2(y,x).我把小1E-18常数放在一边以避免极点.

为什么会这样?我假设返回的值atan(y/x)atan2(y,x)具有不同的范围.特别是在这个实现中,我认为这theta应该[0-Pi]Phi范围内[0,2Pi].

我对吗?是否有更多数值精确的球坐标变换实现?

rat*_*eak 7

atan2适当考虑所有4个象限并可以处理x==0.

atan2(-1,-1)正常返回-3/4*PIatan(-1/-1)将返回1/4*PI

  • @davidvanbrink [规范文件第8.1节(pdf链接)](https://www.opengl.org/registry/doc/GLSLangSpec.4.50.pdf#page=144)说"如果x和y都是0,结果是不确定的"这使它再次充分有用. (4认同)