1 #pragma version(1) 2 3 #pragma rs java_package_name(com.android.noisefield) 4 5 #include "rs_graphics.rsh" 6 #pragma stateVertex(parent); 7 #pragma stateStore(parent); 8 9 10 rs_allocation textureDot; 11 rs_allocation textureVignette; 12 13 rs_program_vertex vertBg; 14 rs_program_fragment fragBg; 15 16 rs_program_vertex vertDots; 17 rs_program_fragment fragDots; 18 19 rs_program_store storeAlpha; 20 rs_program_store storeAdd; 21 22 typedef struct VpConsts { 23 rs_matrix4x4 MVP; 24 float scaleSize; 25 } VpConsts_t; 26 VpConsts_t *vpConstants; 27 28 typedef struct Particle { 29 float3 position; 30 float speed; 31 float wander; 32 float alphaStart; 33 float alpha; 34 int life; 35 int death; 36 } Particle_t; 37 Particle_t *dotParticles; 38 39 40 typedef struct VertexColor_s { 41 float3 position; 42 float4 color; 43 float offsetX; 44 45 } VertexColor; 46 VertexColor* vertexColors; 47 48 rs_mesh dotMesh; 49 rs_mesh gBackgroundMesh; 50 51 float densityDPI; 52 bool touchDown = false; 53 54 #define B 0x100 55 #define BM 0xff 56 #define N 0x1000 57 58 static int p[B + B + 2]; 59 static float g3[B + B + 2][3]; 60 static float g2[B + B + 2][2]; 61 static float g1[B + B + 2]; 62 63 // used for motion easing from touch to non-touch state 64 static float touchInfluence = 0; 65 66 static float touchX = 0; 67 static float touchY = 0; 68 69 static float noise_sCurve(float t) { 70 return t * t * (3.0f - 2.0f * t); 71 } 72 73 static void normalizef2(float v[]) { 74 float s = (float)sqrt(v[0] * v[0] + v[1] * v[1]); 75 v[0] = v[0] / s; 76 v[1] = v[1] / s; 77 } 78 79 static void normalizef3(float v[]) { 80 float s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]); 81 v[0] = v[0] / s; 82 v[1] = v[1] / s; 83 v[2] = v[2] / s; 84 } 85 86 void init() { 87 int i, j, k; 88 for (i = 0; i < B; i++) { 89 p[i] = i; 90 91 g1[i] = (float)(rsRand(B * 2) - B) / B; 92 93 for (j = 0; j < 2; j++) 94 g2[i][j] = (float)(rsRand(B * 2) - B) / B; 95 normalizef2(g2[i]); 96 97 for (j = 0; j < 3; j++) 98 g3[i][j] = (float)(rsRand(B * 2) - B) / B; 99 normalizef3(g3[i]); 100 } 101 102 for (i = B-1; i >= 0; i--) { 103 k = p[i]; 104 p[i] = p[j = rsRand(B)]; 105 p[j] = k; 106 } 107 108 for (i = 0; i < B + 2; i++) { 109 p[B + i] = p[i]; 110 g1[B + i] = g1[i]; 111 for (j = 0; j < 2; j++) 112 g2[B + i][j] = g2[i][j]; 113 for (j = 0; j < 3; j++) 114 g3[B + i][j] = g3[i][j]; 115 } 116 } 117 118 static float noisef2(float x, float y) { 119 int bx0, bx1, by0, by1, b00, b10, b01, b11; 120 float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v; 121 float *q; 122 int i, j; 123 124 t = x + N; 125 bx0 = ((int)t) & BM; 126 bx1 = (bx0+1) & BM; 127 rx0 = t - (int)t; 128 rx1 = rx0 - 1.0f; 129 130 t = y + N; 131 by0 = ((int)t) & BM; 132 by1 = (by0+1) & BM; 133 ry0 = t - (int)t; 134 ry1 = ry0 - 1.0f; 135 136 i = p[bx0]; 137 j = p[bx1]; 138 139 b00 = p[i + by0]; 140 b10 = p[j + by0]; 141 b01 = p[i + by1]; 142 b11 = p[j + by1]; 143 144 sx = noise_sCurve(rx0); 145 sy = noise_sCurve(ry0); 146 147 q = g2[b00]; u = rx0 * q[0] + ry0 * q[1]; 148 q = g2[b10]; v = rx1 * q[0] + ry0 * q[1]; 149 a = mix(u, v, sx); 150 151 q = g2[b01]; u = rx0 * q[0] + ry1 * q[1]; 152 q = g2[b11]; v = rx1 * q[0] + ry1 * q[1]; 153 b = mix(u, v, sx); 154 155 return 1.5f * mix(a, b, sy); 156 } 157 158 void positionParticles() { 159 Particle_t* particle = dotParticles; 160 int size = rsAllocationGetDimX(rsGetAllocation(dotParticles)); 161 for(int i=0; i<size; i++) { 162 particle->position.x = rsRand(-1.0f, 1.0f); 163 particle->position.y = rsRand(-1.0f, 1.0f); 164 particle->speed = rsRand(0.0002f, 0.02f); 165 particle->wander = rsRand(0.50f, 1.5f); 166 particle->death = 0; 167 particle->life = rsRand(300, 800); 168 particle->alphaStart = rsRand(0.01f, 1.0f); 169 particle->alpha = particle->alphaStart; 170 particle++; 171 } 172 } 173 174 void touch(float x, float y) { 175 bool landscape = rsgGetWidth() > rsgGetHeight(); 176 float wRatio; 177 float hRatio; 178 if(!landscape){ 179 wRatio = 1.0; 180 hRatio = rsgGetHeight()/rsgGetWidth(); 181 } else { 182 hRatio = 1.0; 183 wRatio = rsgGetWidth()/rsgGetHeight(); 184 } 185 186 touchInfluence = 1.0; 187 touchX = x/rsgGetWidth() * wRatio * 2 - wRatio; 188 touchY = -(y/rsgGetHeight() * hRatio * 2 - hRatio); 189 } 190 191 int root() { 192 rsgClearColor(0.0, 0.0, 0.0, 1.0f); 193 int size = rsAllocationGetDimX(rsGetAllocation(vertexColors)); 194 rsgBindProgramVertex(vertDots); 195 rsgBindProgramFragment(fragDots); 196 rsgBindTexture(fragDots, 0, textureDot); 197 rsgDrawMesh(dotMesh); 198 199 // bg 200 rsgBindProgramVertex(vertBg); 201 rsgBindProgramFragment(fragBg); 202 rsgDrawMesh(gBackgroundMesh); 203 204 // dots 205 Particle_t* particle = dotParticles; 206 size = rsAllocationGetDimX(rsGetAllocation(dotParticles)); 207 float rads; 208 float speed; 209 210 for(int i=0; i<size; i++) { 211 if(particle->life < 0 || particle->position.x < -1.2 || 212 particle->position.x >1.2 || particle->position.y < -1.7 || 213 particle->position.y >1.7) { 214 particle->position.x = rsRand(-1.0f, 1.0f); 215 particle->position.y = rsRand(-1.0f, 1.0f); 216 particle->speed = rsRand(0.0002f, 0.02f); 217 particle->wander = rsRand(0.50f, 1.5f); 218 particle->death = 0; 219 particle->life = rsRand(300, 800); 220 particle->alphaStart = rsRand(0.01f, 1.0f); 221 particle->alpha = particle->alphaStart; 222 } 223 224 float touchDist = sqrt(pow(touchX - particle->position.x, 2) + 225 pow(touchY - particle->position.y, 2)); 226 227 float noiseval = noisef2(particle->position.x, particle->position.y); 228 if(touchDown || touchInfluence > 0.0) { 229 if(touchDown){ 230 touchInfluence = 1.0; 231 } 232 rads = atan2(touchX - particle->position.x + noiseval, 233 touchY - particle->position.y + noiseval); 234 if(touchDist != 0){ 235 speed = ( (0.25 + (noiseval * particle->speed + 0.01)) / touchDist * 0.3 ); 236 speed = speed * touchInfluence; 237 } else { 238 speed = .3; 239 } 240 particle->position.x += cos(rads) * speed * 0.2; 241 particle->position.y += sin(rads) * speed * 0.2; 242 } 243 244 float angle = 360 * noiseval * particle->wander; 245 speed = noiseval * particle->speed + 0.01; 246 rads = angle * 3.14159265 / 180.0; 247 248 particle->position.x += cos(rads) * speed * 0.33; 249 particle->position.y += sin(rads) * speed * 0.33; 250 251 particle->life--; 252 particle->death++; 253 254 float dist = sqrt(particle->position.x*particle->position.x + 255 particle->position.y*particle->position.y); 256 if(dist < 0.95) { 257 dist = 0; 258 particle->alphaStart *= (1-dist); 259 } else { 260 dist = dist-0.95; 261 if(particle->alphaStart < 1.0f) { 262 particle->alphaStart +=0.01; 263 particle->alphaStart *= (1-dist); 264 } 265 } 266 267 if(particle->death < 101) { 268 particle->alpha = (particle->alphaStart)*(particle->death)/100.0; 269 } else if(particle->life < 101) { 270 particle->alpha = particle->alpha*particle->life/100.0; 271 } else { 272 particle->alpha = particle->alphaStart; 273 } 274 275 particle++; 276 } 277 278 if(touchInfluence > 0) { 279 touchInfluence-=0.01; 280 } 281 return 35; 282 }