Sphere Seams

Started by
6 comments, last by Enalis 12 years, 8 months ago
I'm having two last problems with my planet generation with dynamic LOD through tessellation shaders.

First and foremost, right at the core is that I'm experiencing seams at the poles of the sphere. I generate a sphere with texture coordinates like a rectangle, and the texture I'm generating is based on sampling 3d perlin noise. I checked the texture coordinates on a simple 8 triangle sphere and along the top they are [(0, 1), (0.25, 1), (0.5, 1), (0.75, 1)] and the texels along the top of the image are all the same value as they should be.

Here is the height map I'm generating:
generated_planet_height_map.png


Here are the seams I am getting
sphere_seams.png


As you can see at the top, things are just not quite lining up. Now I'm using the same algorithm to generate the coordinates to sample the noise as I am the positions of the sphere. If you notice bumpiness in the sphere it's because I am modifying the positions based on the height map also so don't worry about that.

Just to verify, here is some sample code...

Sphere Mesh Generation:


double PI = 3.1415926535897;
std::vector<EG::Base::Math::Vector4f> points, uv;
for (unsigned int stack = 0; stack < (stacks + 1); ++stack){
//float y = -((2.0 * (stack / double(stacks))) - 1.0); // Worse Distribution
float y = -cos(PI * stack / stacks); // Better Distribution
float v = 1.0f - (stack / double(stacks));
float r = sqrt(1 - pow(y, 2));
for (unsigned int slice = 0; slice < (slices + 1); ++slice){
float angle = (slice / double(slices)) * 2.0 * PI;
float x = r * sin(angle);
float z = r * cos(angle);
float u = slice / double(slices);

EG::Base::Math::Vector4f point(x, y, z, 1.0f);
EG::Base::Math::Vector4f tcoord(u, v, 1.0f, 1.0f);
points.push_back(point);
uv.push_back(tcoord);
}
}
// The code goes on later to use this grid to create triangles which seems to be working.


Height Map Generation:


float *GenerateSphereHeightMap(unsigned int width, unsigned int height, Noise *noise_generator, std::string file_path){
double PI = 3.1415926535897;
unsigned int height_count = width * height;
float *heights = new float[height_count];
unsigned int height_index = 0;

bool image_dump = (file_path != "") ? true : false;
unsigned char *pixels;
unsigned int index = 0;
if (image_dump){
pixels = new unsigned char[width * height * 4];
}

for (unsigned int y_index = 0; y_index < height; ++y_index){
//float y = -((2.0 * (y_index / double(height - 1))) - 1.0); // Worse Distribution
float y = -cos(PI * y_index / height); // Better Distribution
float r = sqrt(1 - pow(y, 2));
for (unsigned int x_index = 0; x_index < width; ++x_index){
float angle = (x_index / double(width - 1)) * 2.0 * PI;
float x = r * sin(angle);
float z = r * cos(angle);

float x2 = (x + 1.0f) / 2.0f;
float y2 = (y + 1.0f) / 2.0f;
float z2 = (z + 1.0f) / 2.0f;

float generated_height = noise_generator->Get(x2, y2, z2);
heights[height_index] = generated_height;
height_index += 1;

if (image_dump){
unsigned char pixel_value = (((generated_height + 1.0f) / 2.0f) * 255);
pixels[index] = pixel_value;
pixels[index + 1] = pixel_value;
pixels[index + 2] = pixel_value;
pixels[index + 3] = 255;
index += 4;
}
}
}
if (image_dump){
sf::Image image_out;
bool image_result = image_out.LoadFromPixels(width, height, pixels);
image_result = image_out.SaveToFile(file_path);
delete []pixels;
}
return heights;
}


The last issue I'm having is finding a good function to generate LODs from...
here's the equation I'm using now:
float tessellation_level = 8.0 - clamp((vPosition[gl_InvocationID].w / z_far) * 8.0, 1.0, 8.0);
It's very rudimentary so I'm hoping for some more insight, I haven't seen much about it so far.

Thanks in advance for any insight and help! Cheers!
Douglas Eugene Reisinger II
Projects/Profile Site
Advertisement
Such a sphere is always difficult to texture. The problem is, that at the poles one vertex needs to be shared among many tris. A better "sphere" is a subdivided cube:

[media]http://imageshack.us/photo/my-images/818/spheres.jpg/[/media]

This has been created in blender using the catmull-clark subdivision algorithm on a cube. I've marked the top "cube" face red. Due the cube nature you can easily use a cube-texture map to texture it. Either generate such a sphere from blender or take a look at the catmull-clark algo.
More specifically, the problem with your code is that you are drawing quadrilaterals as two triangles, and when you get a degenerate quadrilateral that involves the pole twice, one of the triangles is degenerate. This means the corresponding part of the texture never gets drawn, and instead the non-degenerate triangles that involve the poles are made to touch each other, although they don't in UV space. That's why you see discontinuities.

I also recommend using a parametrization based on a cube.
you know... I should have drawn the wireframe... I probably would have seen that. It makes a lot of sense now. Thank you everyone! Your answers were a big help! Cheers!

Just to clarify though... this would occur even if I sample the texture out of a sphere in the same manner as I have for the height map?
Douglas Eugene Reisinger II
Projects/Profile Site
Just so you know, you could also use this: http://www.infinity-universe.com/Infinity/index.php?option=com_smf&Itemid=75&topic=2305.0.html Already tried and tested, in fact, I'm using it on my own planet renderer :)
Currently trying to make a planet renderer. After many hours of work, somehow I know It'll never be complete.
Also, If I help you, please give me an ++
Infinity has been blowing my mind for a while! I can't believe I missed this!
Douglas Eugene Reisinger II
Projects/Profile Site
Well, I wrote a sphere mesh generator based on that function... basically generating a cube and running the vertices through that function, and I did the same for the height and decal maps I'm generating with the 3d perlin noise and ended up getting great results! Thanks again for all of your help!

Results: (Note: Rendered on my netbook with no shaders or anything, but wanted to share my good fortune thanks to everyone's help!):
snapshot1.png
Douglas Eugene Reisinger II
Projects/Profile Site
Now that I'm on my main computer, here's with tessellation and per pixel lighting:

snapshot2.png
Douglas Eugene Reisinger II
Projects/Profile Site

This topic is closed to new replies.

Advertisement