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:
Here are the seams I am getting
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!