Reputeless / PerlinNoise

Header-only Perlin noise library for modern C++ (C++17/C++20)
MIT License
690 stars 76 forks source link

slow grad functions #14

Closed SollyBunny closed 1 month ago

SollyBunny commented 3 months ago

Your grad functions use switch statements which are bad for branch prediction

Here are their alternatives (in c, because I converted this to c)


static const perlinfloat_t dot_grad3_gradients[8][2] = {
    { 1,  1},
    { 1,  0},
    { 1, -1},
    { 0, -1},
    {-1, -1},
    {-1,  0},
    {-1,  1},
    { 0,  1}
};
static inline perlinfloat_t dot_grad3(int hash, perlinfloat_t xf, perlinfloat_t yf) {
    // In 2D case, the gradient may be any of 8 direction vectors pointing to the
    // edges of a unit-square. The distance vector is the input offset (relative to
    // the smallest bound).
    int index = hash & 0x7;
    perlinfloat_t gx = dot_grad3_gradients[index][0];
    perlinfloat_t gy = dot_grad3_gradients[index][1];
    return gx * xf + gy * yf;
}

static const perlinfloat_t dot_grad4_gradients[16][3] = {
    { 1.0,  1.0, 0.0}, {-1.0,  1.0, 0.0}, { 1.0, -1.0, 0.0}, {-1.0, -1.0, 0.0},
    { 1.0,  0.0, 1.0}, {-1.0,  0.0, 1.0}, { 1.0,  0.0, -1.0}, {-1.0,  0.0, -1.0},
    { 0.0,  1.0, 1.0}, { 0.0, -1.0, 1.0}, { 0.0,  1.0, -1.0}, { 0.0, -1.0, -1.0},
    { 1.0,  1.0, 0.0}, {-1.0,  0.0, 1.0}, { 0.0,  1.0, -1.0}, { 0.0, -1.0, -1.0}
};
static inline perlinfloat_t dot_grad4(int hash, perlinfloat_t xf, perlinfloat_t yf, perlinfloat_t zf) {
    // In 3D case, the gradient may be any of 12 direction vectors pointing to the edges
    // of a unit-cube (rounded to 16 with duplications). The distance vector is the input
    // offset (relative to the smallest bound).
    const perlinfloat_t *g = dot_grad4_gradients[hash & 0xF];
    return g[0] * xf + g[1] * yf + g[2] * zf;
}
Reputeless commented 3 months ago

Thank you for your suggestion! I'll test it when I have some time.

SollyBunny commented 1 month ago

wrong repo, oops!