Jump to content
• Advertisement

# Fast way to get spherical coordinates

This topic is 2594 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

## Recommended Posts

I have a 2d texture that I'm reading using sperical coordinates. So two angles theta and phi corresond to uv of texture. As input I'm using xyz vector, that is converted into theta and phi.

Right now my code in hlsl looks like this:
 static const float pi = 3.14159265f; float2 toSphere(float3 n) { float phi = 0; if((n.x>=0) && (n.z>=0)) { phi = atan(n.z/n.x); } if((n.x<0) && (n.z>=0)) { phi = atan(n.z/n.x); phi += pi; } if((n.x<0) && (n.z<0)) { phi = atan(n.z/n.x); phi += pi; } if((n.x>=0) && (n.z<0)) { phi = atan(n.z/n.x); phi += 2 * pi; } phi /= 2.f * pi; float theta = acos(n.y); theta /= pi; return float2(phi, theta); } 

It works correctly and basically just an direct implementation from general math formulas of relation between cartezian and spherical coordinates.
But I don't think that this really an efficient implementation, there are almost no math but four branches and that's not good for shader in the way how it's used (it should break cashing). I hope somebody can direct me towards more effeicient implimentation, I know in past spherical mapping was used a lot. Hope somebody remembers "old tricks" that he could share.

#### Share this post

##### Share on other sites
Advertisement
I am sure there is a more efficient way to get the angles. I would say, you schould never ever use an if statement on the gpu.

But what is the idea behind storing UV coordinates as a Vector? If you would use 2 floats per vertex it would cost less memory and as you can see, the reconstruction is not simple at all. I don't know how exact your reconstruction is but there is a possibility that float inaccuracy causes problems.

#### Share this post

##### Share on other sites
Optimizing by using atan2:

AFAIK HLSL supports the atan2 function, and hence the entire case distinction can be conceded to a predefined function.

Otherwise, optimizing the if-clauses:

In every of the 4 if-clauses the same statement
[color="#1C2837"][color="#000000"]phi [color="#666600"]=[color="#000000"] atan[color="#666600"]([color="#000000"]n[color="#666600"].[color="#000000"]z[color="#666600"]/[color="#000000"]n[color="#666600"].[color="#000000"]x[color="#666600"]);
occurs using the same arguments in any case. So move that statement in front of the if-clauses. Then notice that the 1st if-clause's body is now empty and hence the clause can be dropped. The body of the 2nd and 3rd if-causes are identical and hence can be combined in a single if-clause (but see the comment below).

However:

Your implementation has some flaws. It suffers from division-by-zero problems. The method used to compute the case where both arguments are less than 0 is AFAIK wrong (you add pi instead of subtracting it).

#### Share this post

##### Share on other sites
As heagarr said, HLSL supports atan2.
This is what I'm using. Not particularly optimized but it should be faster than yours. If you want 'y' to be 'theta'-axis you have to change the swizzles.
 float3 CartesianToSpherical( in float3 xyz ) { float r = length( xyz ); xyz *= 1.f/r; float theta = acos( xyz.z ); float phi = atan2( xyz.y, xyz.x ); phi += ( phi < 0 ) ? 2*PI : 0; // only if you want [0,2pi) return float3( phi, theta, r ); } 

#### Share this post

##### Share on other sites
Thanks guys! Exactly what I need.

#### Share this post

##### Share on other sites

• Advertisement

### Announcements

• Advertisement

• ### Popular Contributors

1. 1
2. 2
3. 3
4. 4
Rutin
16
5. 5
• Advertisement

• 12
• 9
• 12
• 37
• 12
• ### Forum Statistics

• Total Topics
631419
• Total Posts
2999981
×

## Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!