Re: GLSL noise fail? Not necessarily!

First and foremost, this version is a lot more convenient to use, as it is a pure computation without lookup tables. You just include a piece of code in your shader and call a function - no textures to create and load, no uniform arrays to initialize. This is a big improvement over previous versions.

If you're making a high-performance application, it's going to be inconvenient to you in many ways. The overhead of setting up a texture or uniform array will be negligible compared to the general issues of managing a high-performance rendering engine.

Or, to put it another way, the inconvenience of using textures or uniform arrays or whatever is not the reason why noise functions have not gained widespread use in shaders. Performance is the reason.

Please be reasonable in your demands on a noise algorithm. Noise can be very useful even if it competes for resources with other rendering tasks. It simply makes some things look better, and it can be worth the effort. Hardware rendering is mostly a tradeoff between quality and speed, and procedural shading is not a magic exception. Noise is available as one possible tool when building a shader, but of course it requires some resources.

All I'm saying that the resources/performance it requires is not paid for by the quality improvements as of yet. Not for applications that need every GPU cycle they can get.

Before you criticize the algorithm for requiring too much ALU resources to be useful, please look at the code. The number of computations required is not as huge as you may think. Benchmarking this particular implementation on a GeForce GTX560, I clocked it to around 500 million 3D noise samples per second, with no texture resources being used. That gives plenty of headroom for other more traditional shading tasks as well, don't you think?

Let's take your 500 million samples per second number. Divide that by 60 frames per second; you get 8.3 million samples per frame. Divide that by a quite common 1920x1080 resolution, and you get 4 samples per image pixel. It's even worse if you go up to 2560x1600, where you drop to two samples per pixel.

That pretty much requires deferred rendering now, since you can't afford to have more than 4x overdraw. It also means that you don't have the resources to do much anisotropic filtering, so you're going to get quite a bit of aliasing in your texture.

And this doesn't even take into account processor resources dedicated to other things, like lighting, vertex processing, and so forth. So in order to use even 1 noise sample per image pixel, you have to sacrifice 25% of the hardware's shader resources.

The GTX 560 is upper-midgrade hardware; most graphics hardware is considerably slower. Obviously, graphics hardware gets faster all the time, but the performance from noise simply isn't there yet. Not unless you focus solely on the high end.

So I stand by my statement: "you'd need a fairly beefy GPU to be able to use it freely without dropping performance."

Lets add up to operation counts, and then see how worthy it is (without having NORMALISE_GRADIENTS defined)

9 dot's

5 mod's

4 floor's

1 fract

quite a few vec2 +'s and *'s (counting them is too much)

Notice that there are no "nasty expensive transcendental operations". Thing is... this is likely fast enough to run on embedded hardware such as ARM Mali, NVIDIA Tegra and PowerVR.. not the bottom line of those, but the "high end for each". I am not talking 60Hz kind of performance, but bearable nevertheless. For these gizmos, bandwidth is at times horribly limited.. much less bandwidth in them than on desktop. Almost all of them have a unified memory model and the caches are not insanely huge, so a texture look up has a lot of latency. On these gizmos just enabling mipmap filtering has a huge dramatic improvement in performance. Really freaking huge. To get this to be happier on some of those GPU's some massaging to use mediump's (and even lowp's) will help as well (actually Mali does not even support highp in fragment shader anyways).

I think some of it can be optimized a touch more in the case where NORMALISE_GRADIENTS is not defined... it looks like, but I have not taken the time to do it that:

Re: GLSL noise fail? Not necessarily!

When you qualify your arguments like that, I agree with you. Thanks for the patience and constructive thought you put into discussing this. Given the other recent comment on low end hardware with bad memory bandwidth, I think we can conclude that noise is sometimes useful, but of course it depends on the situation at hand. My opinion is that procedural shading for real time rendering is finally a real possibility, and my bet it that it is likely to become more interesting in the near future.

BTW, your numbers become less depressing if you consider that a typical scene need not use noise for every surface on the screen. It's a special effect, not a universal tool. Yet.

Re: GLSL noise fail? Not necessarily!

to calculate g can be jazzed up to look like a MAD's rather than dot's (which for some hardware gives a significant performance increases when one drops to mediump).

I've re-factored noise2D to do this, and the opcode count is the same for the non-normalised version, and a few % smaller for the normalized one. I'll push an LESS_DOTS version to the repository as soon as I have made sure I didn't break something else in the process!

Originally Posted by lasHG

I would like to discuss some major speed improvements with the original author but I can't find any contact information.

Re: GLSL noise fail? Not necessarily!

Ah! the step() function. I could use some general advice on this: When I did my initial comparison of built in functions, step() always produced worse code (via nvida's Cg compiler, and ANGLE to hlsl) - so I didn't use it. Should I ignore this and believe/hope/trust that real drivers do some magic optimization that will always make intrinsics better?

I like the use of floor() instead of lessThan(). neat.

The third optimization you do isn't an optimization because it changed the behavior of the code: By removing one of the mod() operations per permutation, the maximum size of a permutation ring before precision aberrations occur drops from 2896 to 203 (and the number of suitable finite rings inside these sizes from 1138 to just 78). This is might be acceptable from the 2D case, but probably isn't for the 3D case, and doesn't work for the 4D case. I can send you a more detailed explanation if you like ?
Is it worth adding an option to enable this anyway ?

Re: GLSL noise fail? Not necessarily!

The third optimization you do isn't an optimization because it changed the behavior of the code: By removing one of the mod() operations per permutation, the maximum size of a permutation ring before precision aberrations occur drops from 2896 to 203 (and the number of suitable finite rings inside these sizes from 1138 to just 78). This is might be acceptable from the 2D case, but probably isn't for the 3D case, and doesn't work for the 4D case. I can send you a more detailed explanation if you like ?
Is it worth adding an option to enable this anyway ?

I was not really sure whether it would change the behavior, a more detailed explanation would be greatly appreciated.
Even if it changes the behavior it comes with a great speed up, especially if you call the function more than just once in your shader - for some things I am currently working on it will be called even more than 100 times per shader call.
Maybe a "DIRTY_TRICKS" define wouldn't be that bad at all.

Re: GLSL noise fail? Not necessarily!

Maybe a "DIRTY_TRICKS" define wouldn't be that bad at all.

Or just make it a separate function altogether. This is software, and versions of noise focusing on different problems (performance, support domain, statistical properties) should probably be allowed to differ quite significantly, even have different names and different maintainers. There's no real use writing an "uber-shader" that tries to do it all by configuration options. With too many #ifdefs you lose readability and maintainability of the code, and that would be counterproductive.

Re: GLSL noise fail? Not necessarily!

If this was under a more permissive license, it could make it's way into Mesa, and thus into virtually all free drivers, resulting e.g. in a good noise implementation being available to most GNU/Linux users. And once it's there the non-free drivers probably would want to catch up.