Unwrap sphere textures

When rendering 3d graphics today there exists an underlying geometric model which is visually spiced up by wrapping texture bitmaps round the basic surface. So each time a pixel of the object is drawn on the screen the geometric three dimensional coordinates are known. To derive the pixel’s color the coordinates must be mapped to a point in the texture image. Therefore texture coordinates are stored at each vertex of the geometric model. When drawing pixels which are not vertices the texture coordinates are interpolated using the neighbouring vertices. But where do those texture coordinates come from? There are basically two possibilities. Either the coordinates are specified manually (for example with the help of the modelling software) or the coordinates are generated automagically.

texture-on-sphere.pngLet’s have a deeper look at how an automatic mapping might work with a sphere. To specify the coordinates in the texture image, $u \in [0; 1]$ is used for the horizontal direction and $v \in [0; 1]$ for the vertical direction. For the sphere two coordinates $\theta$ and $\phi$ are also enough to mark a point on the surface (remember geographical latitude and longitude). The following equations relate spherical coordinates and cartesian coordinates:

$\left( \begin{array}{c} x \\ y \\ z \end{array} \right) = r \left( \begin{array}{c} \sin \theta \cos \phi \\ \sin \theta \sin \phi \\ \cos \theta \end{array} \right) \qquad \theta \in [0; \pi], \phi \in [0; 2 \pi] $

So a possible mapping for the $(\theta, \phi)$ to the $(u, v)$ coordinates is easy to define – just normalize the range:

$u = \frac{\phi}{2 \pi} \qquad v = \frac{\theta}{\pi}$

Back to our above scenario. To draw a pixel of the sphere object the color needs to be determined. So the cartesian coordinates $(x, y, z)$ are converted to sphere coordinates $(\theta, \phi)$. Those can be used to convert to the texture coordinates $(u, v)$. By looking up the color in the texture image at position $(u, v)$ we know the pixel’s color and draw it to the screen buffer.

Now let’s reverse this process. We start with a readily rendered scene or an ordinary photo. For example some ball or orange is depicted. How can we generate the texture image? For each pixel in the texture we start with the $(u, v)$ coordinates, convert them to sphere coordinates and finally calculate the cartesian coordinates.

$\left( \begin{array}{c} x \\ y \\ z \end{array} \right) = \left( \begin{array}{c} c_x \\ c_y \\ c_z \end{array} \right) + r \left( \begin{array}{c} \sin \left( v \pi \right) \cos \left( u \pi \right) \\ \sin \left( v \pi \right) \sin \left( u \pi \right) \\ \cos \left( v \pi \right) \end{array} \right)$

Since the back of the sphere is missing the above equations use $\theta = u \pi$ instead of $\theta = u 2 \pi $.
Up until now we skipped an important step. The three dimensional coordinates have to be somehow mapped to the screen which requires a projection from three dimensions to two. There exist different types of projections. For simplicity let’s stick with the easiest one: Orthographic projection. To project the sphere to the screen the depth coordinate is thrown away. In our case the second component. Otherwise not all pixels of the projected image are used to generate the texture.

In my subversion repository you can find an implementation which is capable of reading several image formats and writing a png file (link). The command line application requires the SDL, SDL_image and libpng libraries (the latter two dependencies can be removed quite easily). A possible execution might look like:

# make
...
# ./untexture
usage: untexture <bitmap> <centerx> <centery> <radius>
# ./untexture res/orange.jpg 1234 1337 311

Some appetizers:

An orange A generated orange texture
tennisball.jpg tennisball-texture.jpg

5 Responses to “Unwrap sphere textures”

  1. roel says:

    hey, i tried it, but eventho the whole equation thingy looks spectacular, it doesnt work for me… i used the tennisball texture you made, placed it on a sphere, and it looks nothing like the photo left of it. it’s one mess… can you please be a little clearer and not use so many old greek signs?
    thx peace

  2. macin says:

    Remember that this is just a texture for a hemisphere. Mirror the tennisball texture once and append it to the right of the texture of the hemisphere to get a texture for the full sphere. Sorry for the greek variables but that is probably as easy as it gets.

  3. James says:

    Ha old greek signs…

    Those signs are used in maths… it appears to me that you don’t understand the method provided here which is probably why it isn’t working. Replacing the symbols with any others will still work, but it’s nice to acknowledge how to do it the proper way.

  4. Steve says:

    Howdy.

    I’m trying this code out and given the example of -

    ./untexture res/orange.jpg 1234 1337 311

    I get –

    Loading image…
    Position not within image borders.

    Can anyone tell me how to sort this out ?? How do l know the size of the borders ??

  5. Use an image editor like gimp to figure out the size of your image and the center and radius of the circle. The circle must be completely within the image.

Leave a Reply