0
101 Jul 27, 2009 at 06:09

Does anyone have any ideas on texture mapping a sphere? I’m trying to a fractal based world MMORPG engine. So far I have the basic terrain generation, LOD, collision detection and my avatar chase camera working. I also have normal generation.

The only way I can think of doing this properly is to use procedural textures. It seems any other method will either give you A) Major compression (probably at the polls) B) One or more seams running though the landscape or C) Really crappy texture maps because the four sides would all have to match each other to get rid of the seams.

Even with procedural generation I’ll have to do some tricks to fix up the seams unless I use 3D noise. However the problem I can see with 3D nose is that if you are tying to use a procedural texture with coarse features your LOD will change the coordinates and therefore change the pattern. For the actual geometry generation I managed to write some special code that fixes seams for doing 2D perlin noise generation on a sphere. The result looks like this:

http://profile.imageshack.us/user/polypterus/images/detail/#58/asteroid1oq5.jpg

I suppose I can write the same thing if I really had to on in HLSL, however it sounds like a big pain in the ass not being able to use the built in noise() function and also I don’t have double precision at my disposal as I do on the CPU.

So now for the question; does anyone know if this type of thing (or something similar) has been solved and if so can you point me in the right direction? I’m thinking I might be kind of out on a limb on this one but it never hurts to throw out a question or two before writing code.

16 Replies

0
105 Jul 27, 2009 at 18:29

Start from the center of the sphere, obtain the lenght of vector from the center to each point, for each point compute the polar coordinates in 3d , from polar to cartesion normalize into the 0…1 range and you have your texture indices

0
165 Jul 27, 2009 at 18:36

v71, he said he doesn’t want pinching at the poles, which is the classic problem with polar coordinates.

0
102 Jul 27, 2009 at 20:02

You could UV map the two hemispheres of the sphere to two circular textures to reduce compression.

0
101 Jul 27, 2009 at 20:53

@JarkkoL

You could UV map the two hemispheres of the sphere to two circular textures to reduce compression.

Actually right now I have it split up into 10 zones which are made up of pairs of triangles from the my original icosahedron so the compression isn’t too bad. The main problem is the seams in-between those zones are going to have visible lines if I use normal texture maps. Using perlin or simplex noise driven procedural textures kind of solves the problem except I still need to do some special cases (like I used for the noise in the terrain geometry generation) to make sure I generate the same vectors across zone borders. However it’s harder on the graphics card because my world can be actual planet sized and I don’t have the use of double precision numbers on the card, as I do on the CPU when generating my UV coordinates. I guess I just have to bite the bullet and start trying some things out. I can probably use sets of UV coordinates tiled across my zones. A least that way there won’t be repeated patterns for 8km given 1mm pattern resolution and 23 bits of floating point precision.

I just wanted to see if I was missing something obvious. Sometimes I post a quesiton and I find out I’m a dumbass and there is already some standard or semi well-known solution.

0
102 Jul 27, 2009 at 21:19

@SyntaxError

The main problem is the seams in-between those zones are going to have visible lines if I use normal texture maps.

There are things you have to take care of to make it work properly with normal maps. You must have tangent space continuous even though there is UV discontinuity and you also have to process your normal map texture so that the normals just outside the edges are mirrored to make it work properly with bilinear filtering. So, it’s just the matter of getting your data right.

0
105 Jul 27, 2009 at 23:09

The method i posted isn’t vertex position critical, it is based on polar coordinates, the pinch in texture is caused by the regular subdivision algorithm which generates the spheres.
He said he uses the icosahedron method, which will give correct results if applied as i tried to explain before.
The problem is when the sphere wraps onto itself, you must be carefull to wrap 1+du , 1+dv to 0,0

0
101 Jul 28, 2009 at 10:17

Why not use a cubemap? No seams, no singularities.

0
101 Jul 28, 2009 at 15:27

@v71

The method i posted isn’t vertex position critical, it is based on polar coordinates, the pinch in texture is caused by the regular subdivision algorithm which generates the spheres.
He said he uses the icosahedron method, which will give correct results if applied as i tried to explain before.
The problem is when the sphere wraps onto itself, you must be carefull to wrap 1+du , 1+dv to 0,0

I think I’ve lost you. I understand the tessellation is more or less even with the icosahedron however I’m not sure how this helps me with the texture mapping. My understanding is the geometry is pretty independent of the texture coordinates. Wouldn’t the texture map still be compressed at the polls if I used polar coordinates? Maybe I’m missing something.

0
101 Jul 28, 2009 at 15:33

@geon

Why not use a cubemap? No seams, no singularities.

My main concern is that for a cube map have realistic terrain and also be able to cover something the size of an actual planet, it would have to be so huge it would not even fit on the hard drive of the computer much less in the graphics card. However I don’t have any direct experience with cube maps so if there is some way around this feel free to fill me in.

0
165 Jul 28, 2009 at 17:24

@SyntaxError

for a cube map have realistic terrain and also be able to cover something the size of an actual planet, it would have to be so huge it would not even fit on the hard drive of the computer

That’s going to be true no matter what representation you use. Of course you can’t pregenerate all the data for a planet and store it. You can maybe store a large scale, low-res representation that outlines the major features (continents, mountain ranges etc.) and then use procedural techniques to refine and add small-scale detail.

0
101 Jul 28, 2009 at 17:52

@Reedbeta

That’s going to be true no matter what representation you use. Of course you can’t pregenerate all the data for a planet and store it. You can maybe store a large scale, low-res representation that outlines the major features (continents, mountain ranges etc.) and then use procedural techniques to refine and add small-scale detail.

I like your idea of using some sort of low rez representation just to mark out features. I can use it to pick the procedures for rendering on the card and also to fade between fractal agorithms on the CPU. One cool thing is it will take hardly any card memory because I don’t need to store textures at all just some extra vertex data.

As I said I’m using 2D perlin nose with some special seam removal code right now for the geometry engine. I think I going to try to go to 2D simplex noise with a similar seam removal algorithm for the speed gain, and also because there is slightly less distortion because simplex noise basically already works with equilateral triangles instead of squares, so it matches my starting grid better.

Once I get that working I’ll try to port it to the graphics card and use it for procedural terrain unless some better idea comes along. At least that way there should be no seams whatsoever on the whole planet.

0
101 Jul 29, 2009 at 13:53

@Reedbeta

he doesn’t want pinching at the poles

Nobody wants pinching at or near his pole; try buying different underwear brands.

Oops, misunderstood the problem! I need more coffee. :P

http://www.ogre3d.org/forums/viewtopic.php?f=11&t=39254&start=0
Or, how Infinity does it:

http://www.infinity-universe.com/Infinity/index.php?option=com_smf&Itemid=75&topic=7598.0
or lots of stuff at:
http://www.vterrain.org
Another funky system is:
http://healpix.jpl.nasa.gov
(always wondered about how to take some of the ideas there and trying it out)

0
101 Jul 29, 2009 at 18:05

http://www.ogre3d.org/forums/viewtopic.php?f=11&t=39254&start=0
Or, how Infinity does it:

http://www.infinity-universe.com/Infinity/index.php?option=com_smf&Itemid=75&topic=7598.0
or lots of stuff at:
http://www.vterrain.org
Another funky system is:
http://healpix.jpl.nasa.gov
(always wondered about how to take some of the ideas there and trying it out)

Good stuff! I’m not sure how many of these take care of seams however. It “seams” like this problem is kind of the skeleton in the closet. Infinity looks particularly good, but given their algorithm I’m guessing there are seams somewhere on the planet. I suppose that’s not the end of the world but I bet It looks bad when you run across one. There was also some discussion of a seamless asteroid that a contributor was playing with. I think he was using basically using a lot of symmetry where needed in his patterns. I noticed it a few places in his pictures but they were from a distance so I’m not sure how well things would look close up. I guess I can try something like this if my simplex noise based shading has issues. However procedural textures get rid of the tiling effect also so it’s still probably still preferable If I can get them to look good, not to mention the fact that they use almost no card memory.

0
101 Jul 29, 2009 at 18:17

Well, I submitted them to you partly because maybe it would spur some idea, or give you people to exchange with directly related to your immediate problem.

0
105 Jul 30, 2009 at 09:05

This will help

    void SphereMap( float x,float y,float z,
float *u,
float *v )
{
float px,py,pz,d;

d=sqrt( x*x+y*y+z*z );

px= x/d;
py= y/d;
pz= z/d;

float normalisedX = 0;
float normalisedZ = -1;

if (((px * px) + (pz * pz)) > 0)
{
normalisedX = sqrt((px * px) / ((px * px) + (pz * pz)));

if (px < 0)
{
normalisedX = -normalisedX;
}

normalisedZ = sqrt((pz * pz) / ((px * px) + (pz * pz)));

if (pz < 0)
{
normalisedZ = -normalisedZ;
}
}

if (normalisedZ == 0)
{
*u = ((normalisedX * __PI) / 2);
}
else
{
*u = atan(normalisedX / normalisedZ);

if (normalisedZ < 0)
{
*u += __PI;
}
}

if (*u < 0)
{
*u += 2 * __PI;
}

*u /= 2 * __PI;
*v = (-py + 1) / 2;

}

0
165 Jul 30, 2009 at 16:10

Please use …[/code[b][/b]] tags when posting code. [code]…[/code**] tags when posting code.