Revision 9420f2fe
Added by Leszek Koltunski over 9 years ago
| src/main/res/raw/main_vertex_shader.glsl | ||
|---|---|---|
| 50 | 50 |
////////////////////////////////////////////////////////////////////////////////////////////// |
| 51 | 51 |
// HELPER FUNCTIONS |
| 52 | 52 |
////////////////////////////////////////////////////////////////////////////////////////////// |
| 53 |
// Let (v.x,v.y) be point P (the current vertex). |
|
| 54 |
// Let vPoint[effect].xy be point S (the center of effect) |
|
| 55 |
// Let vPoint[effect].xy + vRegion[effect].xy be point O (the center of the Region circle) |
|
| 56 |
// Let X be the point where the halfline SP meets a) if region is non-null, the region circle b) otherwise, the edge of the bitmap. |
|
| 57 |
// |
|
| 58 |
// If P is inside the Region, this function returns |PX|/||SX|, aka the 'degree' of point P. Otherwise, it returns 0. |
|
| 59 |
// |
|
| 60 |
// We compute the point where half-line from S to P intersects the edge of the bitmap. If that's inside the circle, end. If not, we solve the |
|
| 61 |
// the triangle with vertices at O, P and the point of intersection with the circle we are looking for X. |
|
| 62 |
// We know the lengths |PO|, |OX| and the angle OPX , because cos(OPX) = cos(180-OPS) = -cos(OPS) = -PS*PO/(|PS|*|PO|) |
|
| 63 |
// then from the law of cosines PX^2 + PO^2 - 2*PX*PO*cos(OPX) = OX^2 so |
|
| 64 |
// PX = -a + sqrt(a^2 + OX^2 - PO^2) where a = PS*PO/|PS| but we are really looking for d = |PX|/(|PX|+|PS|) = 1/(1+ (|PS|/|PX|) ) and |
|
| 65 |
// |PX|/|PS| = -b + sqrt(b^2 + (OX^2-PO^2)/PS^2) where b=PS*PO/|PS|^2 which can be computed with only one sqrt. |
|
| 66 |
// |
|
| 67 |
// the trick below is the if-less version of the |
|
| 53 |
// The trick below is the if-less version of the |
|
| 68 | 54 |
// |
| 69 | 55 |
// t = dx<0.0 ? (u_objD.x-v.x) / (u_objD.x-ux) : (u_objD.x+v.x) / (u_objD.x+ux); |
| 70 | 56 |
// h = dy<0.0 ? (u_objD.y-v.y) / (u_objD.y-uy) : (u_objD.y+v.y) / (u_objD.y+uy); |
| ... | ... | |
| 90 | 76 |
} |
| 91 | 77 |
|
| 92 | 78 |
////////////////////////////////////////////////////////////////////////////////////////////// |
| 93 |
// return degree of the point as defined by the Region |
|
| 94 |
// Currently only supports circles; .xy = vector from center of effect to the center of the circle, .z = radius |
|
| 79 |
// Return degree of the point as defined by the Region. Currently only supports circular regions. |
|
| 80 |
// |
|
| 81 |
// 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 |
// Let region.xy be the vector from point S to point O (the center point of the region circle) |
|
| 84 |
// Let region.z be the radius of the region circle. |
|
| 85 |
// |
|
| 86 |
// 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|, |
|
| 88 |
// aka the 'degree' of point P. |
|
| 89 |
// |
|
| 90 |
// We solve the the triangle OPX. |
|
| 91 |
// We know the lengths |PO|, |OX| and the angle OPX, because cos(OPX) = cos(180-OPS) = -cos(OPS) = -PS*PO/(|PS|*|PO|) |
|
| 92 |
// then from the law of cosines PX^2 + PO^2 - 2*PX*PO*cos(OPX) = OX^2 so PX = -a + sqrt(a^2 + OX^2 - PO^2) |
|
| 93 |
// where a = PS*PO/|PS| but we are really looking for d = |PX|/(|PX|+|PS|) = 1/(1+ (|PS|/|PX|) ) and |
|
| 94 |
// |PX|/|PS| = -b + sqrt(b^2 + (OX^2-PO^2)/PS^2) where b=PS*PO/|PS|^2 which can be computed with only one sqrt. |
|
| 95 | 95 |
|
| 96 | 96 |
float degree_region(in vec3 region, in vec2 PS) |
| 97 | 97 |
{
|
| 98 | 98 |
vec2 PO = PS + region.xy; |
| 99 | 99 |
float D = region.z*region.z-dot(PO,PO); // D = |OX|^2 - |PO|^2 |
| 100 |
|
|
| 101 |
if( D<=0.0 ) return 0.0; |
|
| 102 |
|
|
| 100 | 103 |
float ps_sq = dot(PS,PS); |
| 101 | 104 |
float one_over_ps_sq = 1.0/(ps_sq+1.0-sign(ps_sq)); // return 1.0 if ps_sq = 0.0 |
| 102 | 105 |
float DOT = dot(PS,PO)*one_over_ps_sq; |
| 103 | 106 |
|
| 104 |
return max(sign(D),0.0) / (1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT)); // if D<=0 (i.e p is outside the Region) return 0.
|
|
| 107 |
return 1.0 / (1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT));
|
|
| 105 | 108 |
} |
| 106 | 109 |
|
| 107 | 110 |
////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 111 | 114 |
{
|
| 112 | 115 |
vec2 PO = PS + region.xy; |
| 113 | 116 |
float D = region.z*region.z-dot(PO,PO); // D = |OX|^2 - |PO|^2 |
| 117 |
|
|
| 118 |
if( D<=0.0 ) return 0.0; |
|
| 119 |
|
|
| 114 | 120 |
vec2 A = sign(PS)*u_objD.xy + S; |
| 115 | 121 |
vec2 signA = sign(A); |
| 116 | 122 |
vec2 signA_SQ = signA*signA; |
| ... | ... | |
| 121 | 127 |
float one_over_ps_sq = 1.0/(ps_sq+1.0-sign(ps_sq)); // return 1.0 if ps_sq = 0.0 |
| 122 | 128 |
float DOT = dot(PS,PO)*one_over_ps_sq; |
| 123 | 129 |
|
| 124 |
return max(sign(D),0.0) * min(1.0/(1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT)),E); // if D<=0 (i.e p is outside the Region) return 0.
|
|
| 130 |
return min(1.0/(1.0 + 1.0/(sqrt(DOT*DOT+D*one_over_ps_sq)-DOT)),E);
|
|
| 125 | 131 |
} |
| 126 | 132 |
|
| 127 | 133 |
////////////////////////////////////////////////////////////////////////////////////////////// |
Also available in: Unified diff
Fix for Bug 19: SWIRL effect: mess if Center out of Region.