Sign in to follow this  
Enalis

Sphere Seams

Recommended Posts

Enalis    333
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:
[img]http://www.palodequeso.net/site_redesign/images/gallery_images/2/generated_planet_height_map.png[/img]


Here are the seams I am getting
[img]http://www.palodequeso.net/sphere_seams.png[/img]


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:
[code]

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.
[/code]

Height Map Generation:
[code]

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;
}
[/code]

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!

Share this post


Link to post
Share on other sites
Ashaman73    13715
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 [url="http://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface"]catmull-clark algo[/url].

Share this post


Link to post
Share on other sites
alvaro    21266
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.

Share this post


Link to post
Share on other sites
Enalis    333
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?

Share this post


Link to post
Share on other sites
Magmatwister    109
Just so you know, you could also use this: [url="http://www.infinity-universe.com/Infinity/index.php?option=com_smf&Itemid=75&topic=2305.0.html"]http://www.infinity-universe.com/Infinity/index.php?option=com_smf&Itemid=75&topic=2305.0.html[/url] Already tried and tested, in fact, I'm using it on my own planet renderer :)

Share this post


Link to post
Share on other sites
Enalis    333
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!):
[img]http://www.palodequeso.net/snapshot1.png[/img]

Share this post


Link to post
Share on other sites
Enalis    333
Now that I'm on my main computer, here's with tessellation and per pixel lighting:

[img]http://www.palodequeso.net/snapshot2.png[/img]

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this