Open tavurth opened 10 months ago
Random sampling based on the placement of other existing random samples is expensive, and not always suited for real-time usage due to its performance cost.
You can already greatly improve the uniformity of randomness by dividing your area into grid cells and using rand_range()
with a small range within this grid cell. This isn't as uniform as methods like Poisson disk sampling, but it essentially has no performance cost.
You can already greatly improve the uniformity of randomness by dividing your area into grid cells and using
rand_range()
with a small range within this grid cell. This isn't as uniform as methods like Poisson disk sampling, but it essentially has no performance cost.
Yes I completely agree!
However, my thoughts on using something like this in a game jam or regular production game are:
I feel like these options could be available with a note about the performance hit.
Just relying on the built in randomness sometimes leads to less than the desired result.
This is especially true to new entrants to gamedev. It would be really nice to have the official tools pointing out that there are many ways to do random.
I've worked with a similar issue in a graphics stippling generation tool and I think for a game engine like Godot a good option could be to provide some sort of pre-generated "blue noise" arrays with different densities. Basically fixed pre-generated arrays of points that are placed at random with similar distance between them. The engine could then provide access to these points using similar syntax as a rand_range(min, max)
like blue_noise_point_range(min, max, density)
and blue_noise_value_range(min, max, density)
by then picking a suitable (approx) density array from the pregenerated set based on the density parameter, return a point scaled to fit the desired range and advance an index so the next request returns the next point in the array. I think this could be useful since these types of points are very useful for placing things, but difficult to generate.
Technically this would of course make it repeat the same patterns, but due to the "patternless" like nature of blue noise this will be difficult to see in any real use case, and randomize() could shuffle the array making the points appear in a different order, which will give different placement patterns as long as you don't use all points in an array. Another drawback is of course that the number of points are finite, so if you have an array to 100 points and get 101, the last one will loop around to the same as the first one. But this can be documented, and the solution is just that if you want 101 unique points you need to use a higher density (=more points) array. An option could be to have the interface be a request for an array of points instead like blue_noise_points_range(min, max, density, count)
which could give an opportunity to warn if the number of requested points is too many for the density and use a higher density one.
A simpler but similar option that you can more easily implement yourself @tavurth is to make a distributed_points_in_area(point_min,point_max,count) that takes a two-step approach: First based on the area and count find a number of grid rows/columns to distribute roughly count points in a same spacing grid. Make an array of all the points in this grid. Then add a random offset +/- these array points, up to 2/5 (or something less than 1/2) of the grid spacing. Finally return the points, culling at random a couple to return the desired number of points. This will give you a nicely distributed "random" point set, but it won't be as nicely even as blue noise generated with more expensive methods.
A simpler but similar option that you can more easily implement yourself @tavurth
I don't actually find this to be a current issue for myself, I just use random until I find the need to do it differently. Then I can easily throw together something specific for the required task.
However they aren't open source, and they are not community tested etc as they have pretty much always been built for clients.
I guess I am using this proposal as a personal note to add this to Godot later, and get community feedback on it, rather than a current need or difficulty I have implementing this myself. 😅
Would be awesome if Godot could actually provide this types of common game dev tooling out of the box.
Describe the project you are working on
Any project that has procedural generation.
Describe the problem or limitation you are having in your project
Please see the blogpost: When Random Numbers Are Too Random
Sometimes randomness is too random, it would be nice to be able to sample in a grid from
0..1
instead of sampling randomly in that number space.Here's another blog post on the subject of placing vegetation
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Images borrowed from the blog link
Common random number generation:
Ideally more uniformly distributed random number generation:
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
Perhaps
RandomNumberGenerator
could have a new function:randf_grid
I see that we already have
randfn
which is a good step in this direction.If this enhancement will not be used often, can it be worked around with a few lines of script?
It could not, but perhaps it could be a module or addon
Is there a reason why this should be core and not an add-on in the asset library?
This would be really nice to have as part of the Godot
RandomNumberGenerator
module. There is C++ source code in the above blog post, although I'm not sure of the licensing thereof.