0

I have just encountered this issues and I do not know how to look at it. I guess that I have an intuition of how it might work but I want to know if some of you can give me an answer.

So, i have a function wave that returns a float. Now, with this code:

vec2 p = ( gl_FragCoord.xy / resolution.xy );
float a;
int steps = 6;
for(int i = 1; i < steps; i++)
{
  a = wave(p, i, steps, 0.125, float(steps/2), .7, time / 2., touch);
}
gl_FragColor = vec4(vec3(a*p.x, a*p.y, a * (1. - p.x) ), 1. );

Will render well, drawing a wave behind another, starting with the farthest to the closest and brightest correct.

But, if I do this:

vec2 p = ( gl_FragCoord.xy / resolution.xy );
float a;
int steps = 6;
 a = wave(p, 1, steps, 0.125, float(steps/2), .7, time / 2., touch);
 a = wave(p, 2, steps, 0.125, float(steps/2), .7, time / 2., touch);
 a = wave(p, 3, steps, 0.125, float(steps/2), .7, time / 2., touch);
 a = wave(p, 4, steps, 0.125, float(steps/2), .7, time / 2., touch);
 a = wave(p, 5, steps, 0.125, float(steps/2), .7, time / 2., touch);
 gl_FragColor = vec4(vec3(a*p.x, a*p.y, a * (1. - p.x) ), 1. );

It will draw only the closest and also the last wave this one, ignoring the others. My experience tells me that in most circumstances and programming languages the above two are somewhat equivalent. Can you tell me what is the difference here?

And the wave function:

float wave(vec2 p, int depth, int scale, 
           float amp, float freq, float wh, 
           float move, vec2 modif)
{
  float a;
  float fi            = float(depth);
  float div_height    = 35.;
  float m_div         = 200./fi;    
  float m_order_h     = fi * .09; 
  float m_height      = wh - m_order_h; 
  float m_paralax     = fi / float(scale);
  float m_scale       = fi / div_height;
  float m_m_var       = 50.*fi;
  float m_wave        = amp*cos(move + m_paralax + p.x*freq);
  float s             = floor(m_div*(p.x) + m_m_var + move);
  float ns            = noise2(vec2(s) + modif);

  if (p.y < ns*m_scale + m_height + m_wave)
  {
      a = fi/float(scale);
  }

  return a;
}
khael
  • 2,600
  • 1
  • 15
  • 36
  • I don't know the solution, but maybe try the second one backwards? – Evan Carslake Feb 27 '15 at 17:46
  • @EvanCarslake I just renders the first wave, discarding the others. I think it is some kind of optimization but I wonder if someone can point me to a reference to this since it seems counterintuitive. – khael Feb 27 '15 at 23:03
  • This seems similar to [GLSL Sandbox #23044](http://glslsandbox.com/e#23044.0), except there `a` is only assigned conditionally (not each pass through the loop, as both of your examples do). Are you sure your first code block is really producing the correct result? Assigning `a` conditionally appears the key to making this work. – emackey Mar 02 '15 at 01:22
  • @emackey Yes, it is the same code. The function wave contains that if condition you spoke of and returns `a`. I still wonder what makes that `for` loop special. And yes, it does produce the right result in the first example. – khael Mar 26 '15 at 12:25
  • Can you post your version of `wave`? – emackey Mar 26 '15 at 21:02
  • @emackey I just edited the question to include the function code as well. As you can see I was trying to split it so I can understand what it does. But it still doesn't explain the problem. Maybe I should mention what machine is executing it though, But I didn't thought it matters that much, all being a standard and such. – khael Mar 26 '15 at 22:59
  • 1
    @khael I copied your for loop to [GLSL Sandbox #23978](http://glslsandbox.com/e#23978.0). It's not showing multiple rows for me in FF or Chrome on Win7 nVidia. And there's no reason it should, your `for` loop is stepping on the contents of `a` with each pass. I don't see any way your loop can work like that, it needs to skip writing to `a` on some passes if you want to see the results of other passes. – emackey Mar 27 '15 at 02:20

1 Answers1

0

You need to pass a as a paremeter to your wave function, so the previous value is preserved with each pass through the loop (or each call to the un-rolled loop). If you found a case where a was being preserved without explicitly being passed in (such as your for loop), that's a bug, you're returning a's uninitialized value, with the bad assumption that the uninitialized value will be the answer from the previous pass.

Here are the diffs in GLSL Sandbox where I got this working. The key difference is that a is initialized to 0.0 and then passed into wave with each iteration.

http://glslsandbox.com/diff#23978.0-vs-24192.0

emackey
  • 11,818
  • 2
  • 38
  • 58