Godot and procedural Generation

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By GR00G0
:warning: Old Version Published before Godot 3 was released.

I am planing on making a little procedural generated 3d game in Godot 3.0 when it releases. My problem is that there is no noise function, and implementing it isn’t gonna work for me, because:

  1. The function really confuses me.
  2. I don’t think that a huge function wich I need to call a lot wich is scripted in gdscript would be very good.

So is there any chance a default noise function will get implemented in 3.0? And if not how have other people done it.
Also I don’t wan’t to completly recompile the engine, so editing the source isn’t an option. Thanks for your help!

You can probably do this by binding a noise library (such as OpenSimplex or FastNoise) as a GDNative library, which doesn’t require to recompile the engine in 3.0.

Alternatively, you could write a shader to generate a texture that you can then download from the GPU to GDScript to make up your map, which will be even faster than a C++ generator, but also trickier^^

Zylann | 2017-08-04 17:47

Thank you for your help. I just found a really good tutorial how simplex noise works. I heard about gdnative, but i am not sure what it does. What language is gdnative in and can i create a function like noise(x,y,z,w) and it can be used efficiently and without too much resources in any other gdscript? Thank you for your answer.

GR00G0 | 2017-08-04 21:13

GDNative is a C interface for Godot, so that you can write native libraries (.dll/.so/etc) that Godot will be able to load as if they were scripts.
As such, it gives you access to the same script API, but allowing any language that can bridge to C. There are C++ bindings, but people also work on D, Rust, even Python bindings.
It requires a minimum of knowledge of C/C++ programming though, since it is lower-level than GDScript and the primary language is C. And obviously, it is also a lot faster if you do a C/C++ library.
The doc is a bit sparse at the moment, I gave it a try a few months ago but it has changed and improved since. Devs are working actively on it, and you can get help by asking them on the Discord community or IRC.

Zylann | 2017-08-05 03:53

Ok that sounds good! But just in case I would be to stupid to use it with gdnative, would a funcion like the 4d noise described here: Noise work good in gdscript?

GR00G0 | 2017-08-05 11:36

There is a simplex noise implementation in GDScript: https://github.com/OvermindDL1/Godot-Helpers/blob/master/Simplex/Simplex.gd
It doesn’t have 4d noise though. OpenSimplex and FastNoise have it but they need to be bound with GDNative or a module. You can also find another way, or implement it yourself.

Zylann | 2017-08-05 15:13

:bust_in_silhouette: Reply From: davidoc

I’m using a diamond-square algorithm for my random generated maps. You may want to read this:
Diamond-square algorithm

This is my implementation in GDScript. I’m using a custom class (_mi_arr) to store the result, you should modify it to use an array.

_width = pow(2, map_factor) + 1
_height = _width
	
var passes = 0
var r = rand_range(0, 60)
var dir = -1 if randf() < 0.5 else 1
while(passes<4):
	var step_size = (_width - 1)
	while(step_size > 1):
		var x = 0
		while(x < _width - 1):
			var y = 0
			while(y < _height - 1):
				diamond_step(x, y, step_size, r * dir)
				square_step(x, y, step_size, r * dir)
				y += step_size
			x += step_size
		step_size /= 2
		r -= 4
		r = clamp(r,0,60)
	passes += 1

Diamond

func diamond_step(x, y, step_size, r):
var avg = (_mi_arr.get_value(x,y) + 
		   _mi_arr.get_value(x,y + step_size) + 
		   _mi_arr.get_value(x + step_size, y + step_size) + 
		   _mi_arr.get_value(x + step_size, y)) / 4
_mi_arr.set_value(x + step_size/2, y + step_size/2, avg + r)

Square

func square_step(x, y, step_size, r):
var avg = (_mi_arr.get_value(x,y) + _mi_arr.get_value(x+ step_size,y))/2
_mi_arr.set_value(x + step_size/2, y, avg + r) #up
avg = (_mi_arr.get_value(x,y + step_size) + _mi_arr.get_value(x + step_size,y+ step_size))/2
_mi_arr.set_value(x + step_size/2, y + step_size, avg + r) #down
avg = (_mi_arr.get_value(x,y) + _mi_arr.get_value(x,y+ step_size))/2
_mi_arr.set_value(x, y + step_size/2, avg + r) #left
avg = (_mi_arr.get_value(x + step_size,y) + _mi_arr.get_value(x + step_size,y + step_size))/2
_mi_arr.set_value(x + step_size, y + step_size/2, avg + r) #right

That looks great, but the diamond square algorithm isn’t made for procedural generation.

GR00G0 | 2017-08-04 18:26

Well… it actually does. It can generate random maps. You might have a different definition of procedural generation^^

Zylann | 2017-08-05 03:48

:bust_in_silhouette: Reply From: Cyanux

Hello,

Still needing noise function?

I have found some modules on this blog:

The blog

You need to compile them with the master branch but you don’t need to write it yourself as you don’t want to. I have the module OpenSimplex in my godot and it works very good. Thanks to Zylann.

I know you already have an answer but a compiled module should work faster than one in gdscript.

:bust_in_silhouette: Reply From: PerduGames

if I’m still behind, I did this before long:

I found this recently too: