• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }