Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Page 3 of 7 FirstFirst 12345 ... LastLast
Results 21 to 30 of 69

Thread: GLSL noise fail? Not necessarily!

  1. #21
    Senior Member OpenGL Guru
    Join Date
    May 2009
    Posts
    4,948

    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."

  2. #22
    Advanced Member Frequent Contributor
    Join Date
    Apr 2009
    Posts
    591

    Re: GLSL noise fail? Not necessarily!

    Lets do an operation count on the posted glsl's simplexNoise2 function, which I quote here with some #ifdef's removed for the way I'd use it:

    Code :
    float taylorInvSqrt(float r)
      {
      return ( 0.83666002653408 + 0.7*0.85373472095314 - 0.85373472095314 * r );
      }
     
    float permute(float x0,vec3 p) { 
      float x1 = mod(x0 * p.y, p.x);
      return floor(  mod( (x1 + p.z) *x0, p.x ));
      }
    vec2 permute(vec2 x0,vec3 p) { 
      vec2 x1 = mod(x0 * p.y, p.x);
      return floor(  mod( (x1 + p.z) *x0, p.x ));
      }
    vec3 permute(vec3 x0,vec3 p) { 
      vec3 x1 = mod(x0 * p.y, p.x);
      return floor(  mod( (x1 + p.z) *x0, p.x ));
      }
    vec4 permute(vec4 x0,vec3 p) { 
      vec4 x1 = mod(x0 * p.y, p.x);
      return floor(  mod( (x1 + p.z) *x0, p.x ));
      }
     
    float simplexNoise2(vec2 v)
      {
       const vec2 C = vec2(0.211324865405187134, // (3.0-sqrt(3.0))/6.;
                          0.366025403784438597); // 0.5*(sqrt(3.0)-1.);
      const vec3 D = vec3( 0., 0.5, 2.0) * 3.14159265358979312;
    // First corner
      vec2 i  = floor(v + dot(v, C.yy) );
      vec2 x0 = v -   i + dot(i, C.xx);
     
    // Other corners
      vec2 i1  =  (x0.x > x0.y) ? vec2(1.,0.) : vec2(0.,1.) ;
     
       //  x0 = x0 - 0. + 0. * C
      vec2 x1 = x0 - i1 + 1. * C.xx ;
      vec2 x2 = x0 - 1. + 2. * C.xx ;
     
    // Permutations
      i = mod(i, pParam.x);
      vec3 p = permute( permute( 
                 i.y + vec3(0., i1.y, 1. ), pParam.xyz)
               + i.x + vec3(0., i1.x, 1. ), pParam.xyz);
     
    // ( N points uniformly over a line, mapped onto a diamond.)
      vec3 x = fract(p / pParam.w) ;
      vec3 h = 0.5 - abs(x) ;
     
      vec3 sx = vec3(lessThan(x,D.xxx)) *2. -1.;
      vec3 sh = vec3(lessThan(h,D.xxx));
     
      vec3 a0 = x + sx*sh;
      vec2 p0 = vec2(a0.x,h.x);
      vec2 p1 = vec2(a0.y,h.y);
      vec2 p2 = vec2(a0.z,h.z);
     
    #ifdef NORMALISE_GRADIENTS
      p0 *= taylorInvSqrt(dot(p0,p0));
      p1 *= taylorInvSqrt(dot(p1,p1));
      p2 *= taylorInvSqrt(dot(p2,p2));
    #endif
     
      vec3 g = 2.0 * vec3( dot(p0, x0), dot(p1, x1), dot(p2, x2) );
     
    // mix
      vec3 m = max(0.5 - vec3(dot(x0,x0), dot(x1,x1), dot(x2,x2)), 0.);
      m = m*m ;
      return 1.66666* 70.*dot(m*m, g);
      }

    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:

    Code :
    vec3 a0 = x + sx*sh;
    vec2 p0 = vec2(a0.x,h.x);
    vec2 p1 = vec2(a0.y,h.y);
    vec2 p2 = vec2(a0.z,h.z);
    vec3 g = 2.0 * vec3( dot(p0, x0), dot(p1, x1), dot(p2, x2) );

    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).

    At any rate, I think this is pretty spiffy and I intend to try it out at work on PowerVR and Mali soon.

  3. #23
    Junior Member Regular Contributor
    Join Date
    Aug 2001
    Location
    Norrkoping, Sweden
    Posts
    112

    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.

  4. #24
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    3

    Re: GLSL noise fail? Not necessarily!

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

    --las/Mercury

    EDIT:
    http://research.mercury-labs.org/noise.glsl (only touched simplexNoise3 so far - search for "LAS_OPT" for the changes)

  5. #25
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    5

    Re: GLSL noise fail? Not necessarily!

    I'm feeling like I need to get some documentation done!

    Quote Originally Posted by kRogue
    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!

    Quote 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.
    I hope not that major! Drop me a PM.

  6. #26
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    3

    Re: GLSL noise fail? Not necessarily!

    Done.
    With the proposed changes I get at least ~4900 fps on my GTS 450 compared to ~4500 fps without the changes.

    EDIT:
    Just for the discussion: A noise provided by the hardware and the GLSL specification would be a really great thing, especially a 4D noise (try to store that as a texture...).

  7. #27
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    5

    Re: GLSL noise fail? Not necessarily!

    Quote Originally Posted by lasHG
    http://research.mercury-labs.org/noise.glsl (only touched simplexNoise3 so far - search for "LAS_OPT" for the changes)
    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 ?

  8. #28
    Junior Member Newbie
    Join Date
    Mar 2011
    Posts
    3

    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.

  9. #29
    Junior Member Regular Contributor
    Join Date
    Aug 2001
    Location
    Norrkoping, Sweden
    Posts
    112

    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.

  10. #30
    Junior Member Regular Contributor
    Join Date
    Jan 2005
    Posts
    182

    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.

    Philipp

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •