I have created one sphere and I want to map onto it a texture map. But I want first to project my map texture to cylinder and then to sphere.

enter image description here

So I want to create a function which takes as parameter a 3D point from sphere and calculate a uv coordinate of this point using cylindrical coordinates. My guess is that I have to transform the spherical coordinates to cylindrical but I am not sure.

Is this possible and how can I implement it ?

  • \$\begingroup\$ @DMGregory I want to project the image (texture) along the side of a cylinder which is subsequently projected onto the sphere orthogonally to the "up" vector. \$\endgroup\$
    – john john
    Commented Jan 7, 2016 at 0:38
  • 1
    \$\begingroup\$ The image you've shown looks like equirectangular projection (ie. latitude & longitude). Is this representative of what you need? If so, you don't need to use a cylinder as an intermediate. \$\endgroup\$
    – DMGregory
    Commented Jan 7, 2016 at 0:43
  • \$\begingroup\$ Ah, or it may be Lambert's Equal-Area Projection (found by reverse image search). This is effectively the same as equirectangular in the horizontal axis, but compresses the vertical axis close to the poles (which might not be desirable for texture mapping, since it will tend to cause loss of detail there. Its aspect ratio of pi:1 is also not as convenient for mipmapping as equirectangular's 2:1) \$\endgroup\$
    – DMGregory
    Commented Jan 7, 2016 at 0:53

2 Answers 2


Assuming atan2 returns an angle in radian between -pi and pi (π) you do something like:

n = Normalize(sphere_surface_point - sphere_center);
u = atan2(n.x, n.z) / (2*pi) + 0.5;
v = n.y * 0.5 + 0.5;

Where sphere_surface_point is the point on the sphere surface.

/ (2*pi) is there to convert the returned angle to a value between -0.5 and 0.5

Add 0.5 to shift it to the range 0..1 for texture mapping that gives you the u texture coordinate.

n.y is already your v texture coordinate.

It's more of a computer graphics (https://computergraphics.stackexchange.com/) question even though texture projections comes up a lot in the context of game dev.

  • \$\begingroup\$ could you please explain to me the reason why in the function atan2 you put as numerator the x value and in the denominator the z value ? \$\endgroup\$
    – john john
    Commented Jan 7, 2016 at 10:13
  • 3
    \$\begingroup\$ The angle around the sphere's equator is the texture's u coordinate. atan2 gives us that angle. Assuming y is the vertical (north-south) axis of your globe. Otherwise swap y and z in the formula if z is the vertical axis in your sphere's coordinate system. \$\endgroup\$ Commented Jan 7, 2016 at 13:12

Leaving this here for myself:

static const float PI = 3.14159265f;

// assumes p is a point on unit sphere

// https://en.wikipedia.org/wiki/File:Equirectangular_projection_SW.jpg
float2 sphere2mapUV_Equirectangular(float3 p)
    return float2(
        atan2(p.x, -p.z) / (2 * PI) + .5,
        p.y * .5 + .5

// https://en.wikipedia.org/wiki/File:Lambert_cylindrical_equal-area_projection_SW.jpg
float2 sphere2mapUV_EqualArea(float3 p)
    return float2(
        (atan2(p.x, -p.z) / PI + 1) / 2,
        asin(p.y) / PI + .5

I added links to example images in case you need a visual reference for checking which projection your map is made with.


float2 uv = sphere2map(normalize(position));

That assumes position is in model space.

In case you're using this in vertex shader the position might already be normalized, so normalization could be skipped.

Your sphere model will usually have center at float3(0,0,0), but if that's not the case you'll have to subtract the sphere_center_position from position.

  • \$\begingroup\$ Does radius matter here or it's assumed to be 1.0? \$\endgroup\$ Commented Apr 13, 2023 at 4:27
  • \$\begingroup\$ @ChaoSXDemon Those functions assume position is normalized, meaning that it is a point on a sphere with radius 1. That is why we have to do normalize(position) when calling those functions. \$\endgroup\$
    – zoran404
    Commented Apr 14, 2023 at 5:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .