0
\$\begingroup\$

I'm trying to code a game in Unity with a procedurally generated terrain that is divided into chunks. Is it faster to use multithreading or compute shaders to generate the terrain and mesh? If it helps; for the generation I use the following:

public static float StackedNoise(int x, int z, int seed, float scale, int octaves, float persistance, float lacunarity, Vector2 offset) {

    System.Random prng = new System.Random(seed);
    Vector2[] octaveOffset = new Vector2[octaves];
    for (int i = 0; i < octaves; i++) {
        float offsetX = prng.Next(-100000, 100000) + offset.x;
        float offsetY = prng.Next(-100000, 100000) + offset.y;
        octaveOffset[i] = new Vector2(offsetX, offsetY);
    }

    if (scale <= 0) scale = 0.0001f;

    float amplitude = 1;
    float frequency = 1;
    float noiseHeight = 0;
    float ampSum = 0;

    for (int i = 0; i < octaves; i++) {
        float _x = x / scale * frequency + octaveOffset[i].x;
        float _y = z / scale * frequency + octaveOffset[i].y;

        float perlinValue = Mathf.PerlinNoise(_x, _y) * 2 - 1;
        noiseHeight += perlinValue * amplitude;
        ampSum += amplitude;

        amplitude *= persistance;
        frequency *= lacunarity;
    }

    noiseHeight = Mathf.InverseLerp(-ampSum, ampSum, noiseHeight);

    return noiseHeight;
}

public static float Perlin3D(float x, float y, float z) {
    float xy = Mathf.PerlinNoise(x, y);
    float yz = Mathf.PerlinNoise(y, z);
    float zx = Mathf.PerlinNoise(z, x);

    float xz = Mathf.PerlinNoise(x, z);
    float zy = Mathf.PerlinNoise(z, y);
    float yx = Mathf.PerlinNoise(y, x);

    float xyz = xy + yz + zx + xz + zy + yx;
    return xyz / 6f;
}

, which are used for the following terrain functions:

float SurfaceFunction(int x, int z) => amplitude * StackedNoise(x, z, seed, terrainScale, octaves, persistance, lacunarity, offset) + terrainSurface;

bool Surface3D(int x, int y, int z) => TerrainFunction(x, z) > y;

bool CaveFunction(int x, int y, int z) => Perlin3D(x * scale, y * scale, z * scale) > threshold;

bool Terrain(int x, int y, int z) => Surface3D(x, y, z) && CaveFunction(x, y, z);

Until now I am using multithreading as seen here, but it is lagging a bit. For rendering a chunk, I use a Marching Cubes algorithm which just connects the centers of the cube.

\$\endgroup\$
  • 2
    \$\begingroup\$ This sounds like a question that you can answer for yourself by profiling the two options. That's the only way that anyone will be able to give you a confirmed answer, so you might as well be the one to do it. As a bonus, then you'll have concrete evidence rather than just an Internet stranger's claim to go by, you know it's accurate to your specific generation method and target hardware, and you can even do finer-grain experiments to determine exactly which aspects of each alternative are the bottlenecks, and maybe find ways to make one or both faster. Lots of benefits to doing this test! \$\endgroup\$ – DMGregory Jan 8 at 15:28
  • \$\begingroup\$ I would add that also there is an article on youtube explaining Zero Dawn Horizon and how it approached procedural terrain generation. It answers alot that might inspire you one way or the other. Links I know can break, but cant link a video in here -> youtube.com/watch?v=ToCozpl1sYY&t=350s \$\endgroup\$ – ErnieDingo Jan 15 at 4:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.