Procedural terrain perlin noise

Hello everyone, i want to generate realistic procedural heightmap, i use perlin noise algo for this.
But i have problem, i have a random terrain, not “realistic” with not river, sea, mountain…

import sys
from noise import pnoise2, snoise2


Xstart=0
Xend=0

for i in range(0,2):
name="./heightmap"+str(i)+".pgm"
print(name)
f = open(name, 'wt')
octaves = 10
freq = 16.0 * octaves
f.write('P2\n')
f.write('256 256\n')
f.write('255\n')
Xend=Xend+256
for y in range(0,256):
    for x in range(Xstart,Xend):
        f.write("%s\n" % int(snoise2(x / freq, y / freq, octaves) * 127.0 + 128.0))
f.close()
Xstart=Xstart+256
print(Xstart)
print(Xend)
print("...")

would you have better to offer me?

You need more then one frequency, noise in different scales and more often then not some manipulations of the noise values.
Try this:


Its a simple random terrain generator, that I once made for a level editor but never integrated it, the noise generation runs on the gpu but the idea is the same. Run it with “main.py -edit” to get a preview and some sliders to edit the shape. You may need to add parentheses to print if you’re on python3

In order to get realistic terrain with valleys, rivers, etc. you’ll need to simulate some form of erosion.

This is an example of an algorithm that isn’t too difficult to implement: codeflow.org/entries/2011/nov/10/webgl-gpu-landscaping-and-erosion/
which is based on this paper:
https://otik.uk.zcu.cz/bitstream/11025/5963/1/F23.pdf

thanks wezu

i have question, in my first code, i generate 2 small terrain that fit together like a puzzle
I’d like to do the same with your code

when define your varaible self.size, i want to define in x axis for fist terrain 0-512 size and for seconde 512-1024

it’s possible to make this with make_buffer to define a zone to draw ?

self.erosion_map=self.make_buffer(Shader.load(Shader.SL_GLSL,'shaders/erode_v.glsl','shaders/erode_f.glsl'), self.size,rgbBits=(16, 0, 0, 0))

like this :

self.erosion_map=self.make_buffer(Shader.load(Shader.SL_GLSL,'shaders/erode_v.glsl','shaders/erode_f.glsl'), [self.size, self.size*2],rgbBits=(16, 0, 0, 0))

You could modify that function, you’d need to pass the size to the base.win.make_texture_buffer() function but wouldn’t it be simpler to cut the image into pieces after making the heightmap?

Or you could change your own code, I posted this to show how one can make use of noise to make different shapes, the core of it is in the shaders/noise_f.glsl:

float h=pow(1.0-abs(snoise((uv*parm1.x)+seed1)), 2.0)*parm1.y;
h+=(1.0-abs(snoise((uv*parm2.x)+seed2)))*parm2.y;   
h+=pow(abs(snoise((uv*parm3.x)+seed3)), 2.0)*parm3.y;
h+=abs(snoise((uv*parm4.x)+seed4))*parm4.y;
h+=noise((uv*parm5.x*50.0)+seed5)*parm5.y;
h+=noise((uv*parm6.x*50.0)+seed6)*parm6.y;

All the shapes are made adding up:

pow(1-abs(noise1),2)*a+abs(noise2)*b+pow(abs(noise3),2)*c+abs(noise4)*d+noise5*e

with different values for a,b,c,d,e and a different seed and frequency for the noise.