ashima / webgl-noise

Procedural Noise Shader Routines compatible with WebGL
MIT License
2.79k stars 302 forks source link

Gradient to 3D Simplex Noise #12

Closed JcBernack closed 8 years ago

JcBernack commented 9 years ago

I tried to add the calculation of the noise gradient to the 3D Simplex Noise, but I have no idea how to check if my results are correct. Can somebody comment on this with a better understanding of the Simplex Noise algorithm?

float snoise(vec3 v, out vec3 grad)
{
    ......

    // Mix final noise value
    vec4 m = max(0.6 - vec4(dot(x0,x0), dot(x1,x1), dot(x2,x2), dot(x3,x3)), 0.0);
    vec4 m2 = m * m;
    vec4 m4 = m2 * m2;

    vec4 pdotx = vec4(dot(p0,x0), dot(p1,x1), dot(p2,x2), dot(p3,x3));

    vec4 temp = m2 * m * pdotx;
    grad = -8.0 * (temp.x * x0 + temp.y * x1 + temp.z * x2 + temp.w * x3);
    grad += m4.x * p0 + m4.y * p1 + m4.z * p2 + m4.w * p3;
    grad *= 42.0;

    return 42.0 * dot(m4, pdotx);
}

The implementation is based on code I found which either was not in GLSL or not in 3D, like this one: srdnoise2.glsl

JcBernack commented 9 years ago

I think the calculation is almost right, only the scaling seems to be off.

I use the gradient to calculate the surface normal to a sphere displaced with the Simplex Noise, described here. I am fairly confident that I got the math right and after playing around with the scaling factor things seem to work quite well (grad *= 0.21), but finding a proper scaling factor by trial and error does not feel very good. ;-)

Could someone please shine a light on the scaling involved with Simplex Noise?

stegu commented 9 years ago

I have no GLSL implementation to contribute, but I have some C code to compute simplex noise with analytic derivatives in 1D to 4D that I thought would be useful to share here:

http://webstaff.itn.liu.se/~stegu/aqsis/aqsis-newnoise/

The files you want are "sdnoise1234.c" and "sdnoise1234.h".

The GLSL version in 2D I wrote that was linked above (srdnoise2.glsl) has rotating gradients to also make the "flow noise" effect, but afaik, it computes the correct derivative. I have not validated and double-checked it, though.

JcBernack commented 9 years ago

Thanks for your reply @stegu.

Turns out my implementation from above is totally correct and my scaling problem had nothing to do with the calculation of the gradient itself, but how I used it. I posted what I wanted to do including the solution here: http://math.stackexchange.com/questions/1071662/surface-normal-to-point-on-displaced-sphere

stegu commented 9 years ago

Good job doing that, and nice that you described it so well. I have saved the link and may refer my students to it as an example of the useful and rewarding attitude I encourage them to have when faced with mathematical problems, an attitude I often summarize as "How hard can it be? Let's try it!" (OK, sometimes it's pretty hard, but it's very seldom impossible.)

What you describe is basically the original bump mapping algorithm as presented by Jim Blinn in 1978 (http://dl.acm.org/citation.cfm?id=507101), but presented more briefly and easily accessible. Blinn's paper is locked down in an age-old and blurry PDF behind the ACM paywall. Thanks!

/Stefan

JcBernack commented 9 years ago

Awesome, very motivating, thanks! :)

stegu commented 8 years ago

Yesterday, I posted versions of 2-D simplex noise in GLSL that are tileable, have analytical derivative and an option for rotating the gradients to create "flow noise". It's in "psrdnoise2D.glsl". Separate functions for different purposes, because of how GLSL works. (My C/C++ version of this is one function with conditionals that takes slightly different paths dependng on what you ask it to compute.)

I still didn't make a 3D version with analytic derivative, so I'm keeping this issue open for visibility. The solution above from JcBernack is correct, and extends to 4-D with only minor changes. The gradient of simplex noise in higher dimensions is just a sum of more terms, the terms themselves are basically the same. The polynomials are of the same degree, there are only 5 4-D expressions instead of 4 3-D ones.

stegu commented 8 years ago

Finally saw your pull request, and merged it. I thought I was not supposed to be the maintainer here, but it seems I am the only one still in attendance. Closing issue. Thank you, @JcBernack!