Project

General

Profile

« Previous | Next » 

Revision 20af7b69

Added by Leszek Koltunski over 7 years ago

Correct an important bug in the vertex shader.

b = 1/a if a!=0, 1 otherwise was incorrectly computed as b = 1.0 / (a+1.0-sign(a)). This, when 0<a<2^-24, suffers from 'round-off error': then a+1.0 = 1.0 (sic!) thus b = 1/0 !.

Correct way: b = 1.0 / ( a - (sign(a)-1.0) )

View differences:

src/main/res/raw/main_vertex_shader.glsl
70 70

  
71 71
  vec2 signA = sign(A);                           //
72 72
  vec2 signA_SQ = signA*signA;                    // div = PS/A if A!=0, 0 otherwise.
73
  vec2 div = signA_SQ*PS/(A+signA_SQ-vec2(1,1));  //
73
  vec2 div = signA_SQ*PS/(A-(vec2(1,1)-signA_SQ));//
74 74

  
75 75
  return 1.0-max(div.x,div.y);
76 76
  }
......
101 101
  if( D<=0.0 ) return 0.0;
102 102

  
103 103
  float ps_sq = dot(PS,PS);
104
  float one_over_ps_sq = 1.0/(ps_sq+1.0-sign(ps_sq));  // return 1.0 if ps_sq = 0.0
104
  float one_over_ps_sq = 1.0/(ps_sq-(sign(ps_sq)-1.0));  // return 1.0 if ps_sq = 0.0
105
                                                         // Important: if we want to write
106
                                                         // b = 1/a if a!=0, b=1 otherwise
107
                                                         // we need to write that as
108
                                                         // b = 1 / ( a-(sign(a)-1) )
109
                                                         // [ and NOT 1 / ( a + 1 - sign(a) ) ]
110
                                                         // because the latter, if 0<a<2^-24,
111
                                                         // will suffer from round-off error and in this case
112
                                                         // a + 1.0 = 1.0 !! so 1 / (a+1-sign(a)) = 1/0 !
105 113
  float DOT  = dot(PS,PO)*one_over_ps_sq;
106 114

  
107 115
  return 1.0 / (1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT));
......
120 128
  vec2 A = sign(PS)*u_objD.xy + S;
121 129
  vec2 signA = sign(A);
122 130
  vec2 signA_SQ = signA*signA;
123
  vec2 div = signA_SQ*PS/(A+signA_SQ-vec2(1,1));
131
  vec2 div = signA_SQ*PS/(A-(vec2(1,1)-signA_SQ));
124 132
  float E = 1.0-max(div.x,div.y);
125 133

  
126 134
  float ps_sq = dot(PS,PS);
127
  float one_over_ps_sq = 1.0/(ps_sq+1.0-sign(ps_sq));  // return 1.0 if ps_sq = 0.0
135
  float one_over_ps_sq = 1.0/(ps_sq-(sign(ps_sq)-1.0));  // return 1.0 if ps_sq = 0.0
128 136
  float DOT  = dot(PS,PO)*one_over_ps_sq;
129 137

  
130 138
  return min(1.0/(1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT)),E);
......
281 289
  vec2 w = vec2(vUniforms[effect].x, -vUniforms[effect].y);
282 290
  float uz = vUniforms[effect].z;                                         // height of the bubble
283 291
  float denominator = dot(ps+(1.0-d)*w,ps);
284
  float one_over_denom = 1.0/(denominator+0.001*(1.0-sign(denominator))); // = denominator==0 ? 1000:1/denominator;
292
  float one_over_denom = 1.0/(denominator-0.001*(sign(denominator)-1.0)); // = denominator==0 ? 1000:1/denominator;
285 293

  
286 294
  //v.z += uz*d;                                                          // cone
287 295
  //b = -(uz*(1.0-d))*one_over_denom;                                     //
......
326 334
  vec3 SO = vUniforms[effect+1];
327 335
  float d1_circle = degree_region(SO,PS);
328 336
  float d1_bitmap = degree_bitmap(S,PS);
329
  float sinA = vUniforms[effect].y;                            // sin(A) precomputed in EffectListVertex.postprocess                                         
330
  float cosA = vUniforms[effect].z;                            // cos(A) precomputed in EffectListVertex.postprocess  
331
  vec2 PS2 = vec2( PS.x*cosA+PS.y*sinA,-PS.x*sinA+PS.y*cosA ); // vector PS rotated by A radians clockwise around S.                               
337
  float sinA = vUniforms[effect].y;                            // sin(A) precomputed in EffectListVertex.postprocess
338
  float cosA = vUniforms[effect].z;                            // cos(A) precomputed in EffectListVertex.postprocess
339
  vec2 PS2 = vec2( PS.x*cosA+PS.y*sinA,-PS.x*sinA+PS.y*cosA ); // vector PS rotated by A radians clockwise around S.
332 340
  vec3 SG = (1.0-d1_circle)*SO;                                // coordinates of the dilated circle P is going to get rotated around
333
  float d2 = max(0.0,degree(SG,S,PS2));                        // make it a max(0,deg) because when S=left edge of the bitmap, otherwise
334
                                                               // some points end up with d2<0 and they disappear off view.
341
  float d2 = max(0.0,degree(SG,S,PS2));                        // make it a max(0,deg) because otherwise when S=left edge of the
342
                                                               // bitmap some points end up with d2<0 and they disappear off view.
335 343
  v.xy += min(d1_circle,d1_bitmap)*(PS - PS2/(1.0-d2));        // if d2=1 (i.e P=S) we should have P unchanged. How to do it?
336 344
  }
337 345

  

Also available in: Unified diff