0

I'm currently working on a terrain engine and I'm experimenting a little bit with noise. It's so fascinating to see what different structures, functions and pure imagination can create with just a few lines of code. Recently I saw this post: http://squall-digital.com/ProceduralGeneration.html, I was definitely intrigued by all of these techniques, but especially the first one caught my attention. The programmer made the gain (or persistence) of the noise to be proportional to the slope of the noise on that point. I'm currently trying to achieve this but I don't think I'm on the right track.

I'm currently using simplex noise. I know the author of the article uses Perlin Noise and yes, I have seen how to calculate the derivative of Perlin Noise, but obviously this implementation wouldn't work because of the fundamental differences in how Perlin and Simplex noise are generated. I thus set out on my own way to try and approximate the slope of noise on a given position.

I came up with the following "algorithm":

  • Calculate neighboring points of noise [(x + 1, z), (x - 1, z), (x, z + 1), (x, z - 1)].
  • Calculate their respective noise value
  • Calculate differenceX and differenceZ in noise values on the x-axis and the z-axis respectively
  • Create vectors from origin: (2, differenceX, 0) and (0, differenceZ, 2)
  • Scale to vectors of length 1
  • Add y-components of the resulting unit vectors
  • use this y-component as the "slope" approximated at the given point.

Now I have implemented this in code (I added "3D" vectors for the purpose of ease of understanding)

private static float slope(OpenSimplex2F simplex, float x, float z, float noise) {
    float[] neighbours = getStraightNeighbours(simplex, x, z);

    float xSlope = (neighbours[1] - neighbours[0]) / (2.0f * x);
    float zSlope = (neighbours[3] - neighbours[2]) / (2.0f * z);

    float[] vecX = new float[] { 1, xSlope, 0 };
    float[] vecZ = new float[] { 0, zSlope, 1 };

    float scaleX = Maths.sqrt(1.0f + xSlope * xSlope);
    float scaleZ = Maths.sqrt(1.0f + zSlope * zSlope);

    for (int i = 0; i < 3; i++) {
        vecX[i] /= scaleX;
        vecZ[i] /= scaleZ;
    }

    float[] grad = new float[] {
            vecX[0] + vecZ[0],
            vecX[1] + vecZ[1],
            vecX[2] + vecZ[2]
    };

    return grad[1];
}

Now this gives me extremely underwhelming and rest assured, wrong results: Result

Is there anyone that can explain me if this is a good technique to approximate the slope of if this is completely wrong. I'm not the biggest math genius so I was already happy I could figure this out and that it produced a result in the first place. If anyone has a resource linked to the derivative of simplex noise (which would be a life saver, obviously), it'd be really appreciated!

Matthias K.
  • 43
  • 11
  • These algorithms are cool but look like ultimately dead ends for anything besides quick-and-dirty terrain generation. For better effects, look up hydraulic terrain erosion. Here's a quick sample: https://www.cs.rpi.edu/~cutler/classes/advancedgraphics/S09/final_projects/odhner_fleming.pdf – markspace Feb 21 '21 at 00:11
  • I know about Hydraulic Erosion, and I successfully implemented it into my terrain engine. The thing is I still generate my maps using a combination of different noise maps and thus different techniques to combine these result in more realistic looking terrain (if combined right, this takes hours to get right). – Matthias K. Feb 21 '21 at 01:03
  • I initially mis-understood the question (didn't realize you were attempting to come up with a new mapping based on the rate of change at the given location), but I am really pleased to see this link and article with the alternative mapping functions. I am going to add them to a visualizer I wrote (https://github.com/philfrei/SiVi). FWIW, the tool is limited to 2D but is useful for quickly viewing noise mixes with the simple or turbulent mappings. For your derivatives, maybe calculating rate changes in a given direction, and a transform being changing the directionality? Much to explore. – Phil Freihofner Feb 21 '21 at 01:32

0 Answers0