Revision 73af5285
Added by Leszek Koltunski about 8 years ago
src/main/res/raw/main_vertex_shader.glsl | ||
---|---|---|
78 | 78 |
////////////////////////////////////////////////////////////////////////////////////////////// |
79 | 79 |
// Return degree of the point as defined by the Region. Currently only supports circular regions. |
80 | 80 |
// |
81 |
// Let us first introduce some notation. |
|
81 | 82 |
// Let 'PS' be the vector from point P (the current vertex) to point S (the center of the effect). |
82 |
// Should work regardless if S is inside or outside of the circle. |
|
83 | 83 |
// Let region.xy be the vector from point S to point O (the center point of the region circle) |
84 | 84 |
// Let region.z be the radius of the region circle. |
85 |
// (This all should work regardless if S is inside or outside of the circle). |
|
86 |
// |
|
87 |
// Then, the degree of a point with respect to a given (circular!) Region is defined by: |
|
85 | 88 |
// |
86 | 89 |
// If P is outside the circle, return 0. |
87 |
// Otherwise, let X be the point where the halfline SP meets the region circle - return |PX|/||SX|, |
|
90 |
// Otherwise, let X be the point where the halfline SP meets the region circle - then return |PX|/||SX|,
|
|
88 | 91 |
// aka the 'degree' of point P. |
89 | 92 |
// |
90 | 93 |
// We solve the triangle OPX. |
... | ... | |
267 | 270 |
// so finally -|PS|/f'(|PX|) = -ps_sq/ (6uz*d*(1-d)^2) |
268 | 271 |
// |
269 | 272 |
// Case 3: |
270 |
// f(t) = 3t^4-8t^3+6t^2 would be better as this safisfies f(0)=0, f'(0)=0, f'(1)=0, f(1)=1,
|
|
273 |
// f(t) = 3t^4-8t^3+6t^2 would be better as this satisfies f(0)=0, f'(0)=0, f'(1)=0, f(1)=1,
|
|
271 | 274 |
// f(0.5)=0.7 and f'(t)= t(t-1)^2 >=0 for t>=0 so this produces a fuller, thicker bubble! |
272 | 275 |
// then -|PS|/f'(|PX|) = (-|PS|*|SX)) / (12uz*d*(d-1)^2) but |PS|*|SX| = ps_sq/(1-d) (see above!) |
273 | 276 |
// so finally -|PS|/f'(|PX|) = -ps_sq/ (12uz*d*(1-d)^3) |
274 | 277 |
// |
275 | 278 |
// Now, new requirement: we have to be able to add up normal vectors, i.e. distort already distorted surfaces. |
276 |
// If a surface is given by z = f(x,y), then the normal vector at (x0,y0) is given by (df/dx (x0,y0), df/dy (x0,y0), 1 ).
|
|
279 |
// If a surface is given by z = f(x,y), then the normal vector at (x0,y0) is given by (-df/dx (x0,y0), -df/dy (x0,y0), 1 ).
|
|
277 | 280 |
// so if we have two surfaces defined by f1(x,y) and f2(x,y) with their normals expressed as (f1x,f1y,1) and (f2x,f2y,1) |
278 |
// then the normal to g = f1+f2 is simply given by (f1x+f2x,f1y+f2y,1), i.e. if the third component is 1, then we can simply
|
|
279 |
// add up the first and second components. |
|
281 |
// then the normal to g = f1+f2 is simply given by (f1x+f2x,f1y+f2y,1), i.e. if the third components are equal, then we
|
|
282 |
// can simply add up the first and second components.
|
|
280 | 283 |
// |
281 | 284 |
// Thus we actually want to compute N(v.x,v.y) = a*(-(dx/|PS|)*f'(|PX|), -(dy/|PS|)*f'(|PX|), 1) and keep adding |
282 | 285 |
// the first two components. (a is the horizontal part) |
... | ... | |
346 | 349 |
// WAVE EFFECT |
347 | 350 |
// |
348 | 351 |
// Directional sinusoidal wave effect. |
352 |
// |
|
353 |
// This is an effect from a (hopefully!) generic family of effects of the form (vec3 V: |V|=1 , f(x,y) ) (*) |
|
354 |
// i.e. effects defined by a unit vector and an arbitrary function. Those effects are defined to move each |
|
355 |
// point (x,y,0) of the XY plane to the point (x,y,0) + V*f(x,y). |
|
356 |
// |
|
357 |
// In this case V is defined by angles A and B (sines and cosines of which are precomputed in |
|
358 |
// EffectQueueVertex and passed in the uniforms). |
|
359 |
// Let's move V to start at the origin O, let point C be the endpoint of V, and let C' be C's projection |
|
360 |
// to the XY plane. Then A is defined to be the angle C0C' and angle B is the angle C'O(axisY). |
|
361 |
// |
|
362 |
// Also, in this case f(x,y) = amplitude*sin(x/length), with those 2 parameters passed in uniforms. |
|
363 |
// |
|
364 |
//////////////////////////////////////////////////////// |
|
365 |
// How to compute any generic effect of type (*) |
|
366 |
//////////////////////////////////////////////////////// |
|
367 |
// |
|
368 |
// By definition, the vertices move by f(x,y)*V. |
|
369 |
// |
|
370 |
// Normals are much more complicated. |
|
371 |
// Let angle X be the angle (0,Vy,Vz)((0,Vy,0)(Vx,Vy,Vz). |
|
372 |
// Let angle Y be the angle (Vx,0,Vz)((Vx,0,0)(Vx,Vy,Vz). |
|
373 |
// |
|
374 |
// Then it can be shown that the resulting surface, at point to which point (x0,y0,0) got moved to, |
|
375 |
// has 2 tangent vectors given by |
|
376 |
// |
|
377 |
// SX = (1.0+cosX*fx , cosY*sinX*fx , sinY*sinX*fx); (**) |
|
378 |
// SY = (cosX*sinY*fy , 1.0+cosY*fy , sinX*sinY*fy); (***) |
|
379 |
// |
|
380 |
// and then obviously the normal N is given by N= SX x SY . |
|
381 |
// |
|
382 |
// We still need to remember the note from the distort function about adding up normals: |
|
383 |
// we first need to 'normalize' the normals to make their third components equal, and then we |
|
384 |
// simply add up the first and the second component while leaving the third unchanged. |
|
385 |
// |
|
386 |
// How to see facts (**) and (***) ? Briefly: |
|
387 |
// a) compute the 2D analogon and conclude that in this case the tangent SX is given by |
|
388 |
// SX = ( cosA*f'(x) +1, sinA*f'(x) ) (where A is the angle vector V makes with X axis ) |
|
389 |
// b) cut the resulting surface with plane P which |
|
390 |
// - includes vector V |
|
391 |
// - crosses plane XY along line parallel to X axis |
|
392 |
// c) apply the 2D analogon and notice that the tangent vector to the curve that is the common part of P |
|
393 |
// and our surface (I am talking about the tangent vector which belongs to P) is given by |
|
394 |
// (1+cosX*fx,0,sinX*fx) rotated by angle Y (where angles X,Y are defined above) along vector (1,0,0). |
|
395 |
// d) compute the above and see that this is equal precisely to SX from (**). |
|
396 |
// e) repeat points b,c,d in direction Y and come up with (***). |
|
349 | 397 |
|
350 | 398 |
void wave(in int effect, inout vec4 v, inout vec4 n) |
351 | 399 |
{ |
... | ... | |
363 | 411 |
float sinB = vUniforms[effect ].w; |
364 | 412 |
float cosB = vUniforms[effect+1].y; |
365 | 413 |
|
366 |
float angle= 1.578*(-ps.x*cosB-ps.y*sinB) / length; // -ps.x and -ps.y becuase the 'ps=center-v.xy' inverts the XY axis!
|
|
414 |
float angle= 1.578*(-ps.x*cosB-ps.y*sinB) / length; // -ps.x and -ps.y because the 'ps=center-v.xy' inverts the XY axis!
|
|
367 | 415 |
vec3 dir = vec3(sinB*cosA,cosB*cosA,sinA); |
368 | 416 |
|
369 | 417 |
v.xyz += sin(angle)*deg*dir; |
370 | 418 |
|
371 |
float sqrtX = sqrt(dir.y*dir.y + dir.z*dir.z); |
|
372 |
float sqrtY = sqrt(dir.x*dir.x + dir.z*dir.z); |
|
419 |
if( n.z != 0.0 ) |
|
420 |
{ |
|
421 |
float sqrtX = sqrt(dir.y*dir.y + dir.z*dir.z); |
|
422 |
float sqrtY = sqrt(dir.x*dir.x + dir.z*dir.z); |
|
373 | 423 |
|
374 |
float sinX = ( sqrtY==0.0 ? 0.0 : dir.z / sqrtY); |
|
375 |
float cosX = ( sqrtY==0.0 ? 1.0 : dir.x / sqrtY); |
|
376 |
float sinY = ( sqrtX==0.0 ? 0.0 : dir.z / sqrtX); |
|
377 |
float cosY = ( sqrtX==0.0 ? 1.0 : dir.y / sqrtX); |
|
424 |
float sinX = ( sqrtY==0.0 ? 0.0 : dir.z / sqrtY);
|
|
425 |
float cosX = ( sqrtY==0.0 ? 1.0 : dir.x / sqrtY);
|
|
426 |
float sinY = ( sqrtX==0.0 ? 0.0 : dir.z / sqrtX);
|
|
427 |
float cosY = ( sqrtX==0.0 ? 1.0 : dir.y / sqrtX);
|
|
378 | 428 |
|
379 |
float tmp = 1.578*cos(angle)*deg/length; |
|
429 |
float tmp = 1.578*cos(angle)*deg/length;
|
|
380 | 430 |
|
381 |
float fx = cosB*tmp; |
|
382 |
float fy = sinB*tmp; |
|
431 |
float fx = cosB*tmp;
|
|
432 |
float fy = sinB*tmp;
|
|
383 | 433 |
|
384 |
vec3 sx = vec3 (1.0+cosX*fx,cosY*sinX*fx,sinY*sinX*fx); |
|
385 |
vec3 sy = vec3 (cosX*sinY*fy,1.0+cosY*fy,sinX*sinY*fy); |
|
434 |
vec3 sx = vec3 (1.0+cosX*fx,cosY*sinX*fx,sinY*sinX*fx);
|
|
435 |
vec3 sy = vec3 (cosX*sinY*fy,1.0+cosY*fy,sinX*sinY*fy);
|
|
386 | 436 |
|
387 |
vec3 normal = cross(sx,sy); |
|
437 |
vec3 normal = cross(sx,sy);
|
|
388 | 438 |
|
389 |
if( n.z != 0.0 ) |
|
390 |
{ |
|
391 |
n.xyz = n.z*normal; |
|
439 |
if( normal.z > 0.0 ) |
|
440 |
{ |
|
441 |
n.xy += (n.z/normal.z)*vec2(normal.x,normal.y); |
|
442 |
} |
|
392 | 443 |
} |
393 | 444 |
} |
394 | 445 |
} |
Also available in: Unified diff
Now we can add up the WAVE effect to others with smooth shading! Remaining issues:
- when angle A < 0, the shades are wrong
- sometimes (check with the 3D vertex & Fragment effects' app) we get black spots at seemingly random points. Looks like computational instability again.