I'm making a space game and so far what I have is a system to generate spheres with noise on them, making them planets. I make a sphere, create noise data, write that data to an image file, and then bind it to the sphere as a texture, and from there, I use that to make terrain. The problem I'm having is there are too many hills and valleys, and just looks like a spikeball instead of a planet [![sphere][1]][1] [![sphere wireframe][2]][2] [1]: https://i.sstatic.net/HMGdf.png [2]: https://i.sstatic.net/UNM3V.png Here's the function I use to generate the noise data void write_noise_2d(int w, int h, int channels_num, const char* bmp_path) { // create random seed for noise srand(time(NULL)); float seed = (float)rand()/RAND_MAX; // initialize noise fnl_state noise = fnlCreateState(); noise.noise_type = FNL_NOISE_OPENSIMPLEX2; noise.octaves = 6; noise.lacunarity = 2.0f; noise.gain = 0.5f; noise.frequency = 0.01f; noise.seed = (int)seed; printf("Seed: %i\n", seed); noise.fractal_type = FNL_FRACTAL_FBM; // create data array for noise float* noise_data = malloc(w * h * channels_num * sizeof(float)); int index = 0; // create noise throughout the entire image for(int x=0; x<w; x++) { for(int y=0; y<h; y++) { noise_data[index++] = fnlGetNoise2D(&noise, x * 0.3f, y * 0.3f); } } stbi_write_bmp(bmp_path, w, h, channels_num, noise_data); free(noise_data); } Here's the function where I bind the noise to the sphere unsigned int load_noise_2d(const char* path, unsigned int shader_program, const char* sampler, bool remove_noise) { unsigned int noise; glGenTextures(1, &noise); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, noise); // from what I heard no need to specify gl_repeat because that is the default // filtering parameters glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_MIPMAP); // image stats int width, height, num_channels; // load image unsigned char* noise_data = stbi_load(path, &width, &height, &num_channels, 0); if(noise_data) { // image options glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_SHORT, noise_data); glGenerateMipmap(GL_TEXTURE_2D); // send to the GPU for processing set_int(shader_program, sampler, 0); printf("Loaded noise map of %i by %i\n", width, height); } else { printf("Failed to load noisemap\n"); } // deallocate data that's no longer needed stbi_image_free(noise_data); if(remove_noise == true) { remove(path); printf("Deleted noise file\n"); } else { printf("Kept noise file\n"); return 0; } return noise; } For reference, this is how the function calls look like // write noise data from FNL to texture write_noise_2d(512, 512, 2, "textures/2dnoise.bmp"); // now we load the noise map back into the program to be used later load_noise_2d("textures/2dnoise.bmp", earthlike, "noisemap", true); And finally, here's the tessellation shader, where I had a problem before with the intensity being too high, but that's solved #version 450 core // determines what type of tessellation to do layout(triangles, equal_spacing, cw) in; // input from control shader in vec3 vertex_coord[]; // output vec out vec3 vert; // simplex noise goes here uniform sampler2D noisemap; // allows for object transformations uniform mat4 model; uniform mat4 view; uniform mat4 projection; out float height; void main() { // gets barycentric coordinates from the triangles vec3 x = gl_TessCoord.x * vertex_coord[0]; vec3 y = gl_TessCoord.y * vertex_coord[1]; vec3 z = gl_TessCoord.z * vertex_coord[2]; vec3 v = x + y + z; // scale noise between an acceptable value float min_noise_value = 0.5f; float max_noise_value = 2.5f; float intensity_scale = 0.015f; float noise_range = max_noise_value - min_noise_value; // use texture for offsetting sphere vertices float noise = texture(noisemap, vec2(v)).r; // sphere offsetting multiplier height = min_noise_value + noise_range * noise * intensity_scale; // makes every triangle an equal distance from the center through normalization (that's how spheres are formed) vec3 pos = normalize(x + y + z); // apply noise pos *= height; // output tessellated shape gl_Position = projection * view * model * vec4(pos, 1.0); }