• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (C) 2009 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #pragma version(1)
16 
17 #pragma rs java_package_name(com.android.wallpaper.grass)
18 
19 #include "rs_graphics.rsh"
20 
21 #define RSID_BLADES_BUFFER 2
22 
23 #define TESSELATION 0.5f
24 #define HALF_TESSELATION 0.25f
25 #define MAX_BEND 0.09f
26 #define SECONDS_IN_DAY 86400.0f
27 #define PI 3.1415926f
28 #define HALF_PI 1.570796326f
29 #define REAL_TIME 1
30 
31 int gBladesCount;
32 int gIndexCount;
33 int gWidth;
34 int gHeight;
35 float gXOffset;
36 float gDawn;
37 float gMorning;
38 float gAfternoon;
39 float gDusk;
40 int gIsPreview;
41 rs_program_vertex gPVBackground;
42 rs_program_fragment gPFBackground;
43 rs_program_fragment gPFGrass;
44 rs_program_store gPSBackground;
45 rs_allocation gTNight;
46 rs_allocation gTSunset;
47 rs_allocation gTSunrise;
48 rs_allocation gTSky;
49 rs_allocation gTAa;
50 rs_mesh gBladesMesh;
51 
52 
53 typedef struct Blade {
54     float angle;
55     int size;
56     float xPos;
57     float yPos;
58     float offset;
59     float scale;
60     float lengthX;
61     float lengthY;
62     float hardness;
63     float h;
64     float s;
65     float b;
66     float turbulencex;
67 } Blade_t;
68 Blade_t *Blades;
69 
70 typedef struct RS_PACKED Vertex {
71     uchar4 color;
72     float2 position;
73     float2 texture0;
74 } __attribute__((packed,aligned(4))) Vertex_t;
75 Vertex_t *Verticies;
76 
77 #define B 0x100
78 #define BM 0xff
79 #define N 0x1000
80 
81 static int p[B + B + 2];
82 static float g3[B + B + 2][3];
83 static float g2[B + B + 2][2];
84 static float g1[B + B + 2];
85 
86 static float noise_sCurve(float t)
87 {
88     return t * t * (3.0f - 2.0f * t);
89 }
90 
91 static void normalizef2(float v[])
92 {
93     float s = (float)sqrt(v[0] * v[0] + v[1] * v[1]);
94     v[0] = v[0] / s;
95     v[1] = v[1] / s;
96 }
97 
98 static void normalizef3(float v[])
99 {
100     float s = (float)sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
101     v[0] = v[0] / s;
102     v[1] = v[1] / s;
103     v[2] = v[2] / s;
104 }
105 
106 void init()
107 {
108     int i, j, k;
109 
110     for (i = 0; i < B; i++) {
111         p[i] = i;
112 
113         g1[i] = (float)(rsRand(B * 2) - B) / B;
114 
115         for (j = 0; j < 2; j++)
116             g2[i][j] = (float)(rsRand(B * 2) - B) / B;
117         normalizef2(g2[i]);
118 
119         for (j = 0; j < 3; j++)
120             g3[i][j] = (float)(rsRand(B * 2) - B) / B;
121         normalizef3(g3[i]);
122     }
123 
124     for (i = B-1; i >= 0; i--) {
125         k = p[i];
126         p[i] = p[j = rsRand(B)];
127         p[j] = k;
128     }
129 
130     for (i = 0; i < B + 2; i++) {
131         p[B + i] = p[i];
132         g1[B + i] = g1[i];
133         for (j = 0; j < 2; j++)
134             g2[B + i][j] = g2[i][j];
135         for (j = 0; j < 3; j++)
136             g3[B + i][j] = g3[i][j];
137     }
138 }
139 
140 static float noisef(float x)
141 {
142     int bx0, bx1;
143     float rx0, rx1, sx, t, u, v;
144 
145     t = x + N;
146     bx0 = ((int)t) & BM;
147     bx1 = (bx0+1) & BM;
148     rx0 = t - (int)t;
149     rx1 = rx0 - 1.0f;
150 
151     sx = noise_sCurve(rx0);
152 
153     u = rx0 * g1[p[bx0]];
154     v = rx1 * g1[p[bx1]];
155     return 2.3f * mix(u, v, sx);
156 }
157 
158 static float noisef2(float x, float y)
159 {
160     int bx0, bx1, by0, by1, b00, b10, b01, b11;
161     float rx0, rx1, ry0, ry1, sx, sy, a, b, t, u, v;
162     float *q;
163     int i, j;
164 
165     t = x + N;
166     bx0 = ((int)t) & BM;
167     bx1 = (bx0+1) & BM;
168     rx0 = t - (int)t;
169     rx1 = rx0 - 1.0f;
170 
171     t = y + N;
172     by0 = ((int)t) & BM;
173     by1 = (by0+1) & BM;
174     ry0 = t - (int)t;
175     ry1 = ry0 - 1.0f;
176 
177     i = p[bx0];
178     j = p[bx1];
179 
180     b00 = p[i + by0];
181     b10 = p[j + by0];
182     b01 = p[i + by1];
183     b11 = p[j + by1];
184 
185     sx = noise_sCurve(rx0);
186     sy = noise_sCurve(ry0);
187 
188     q = g2[b00]; u = rx0 * q[0] + ry0 * q[1];
189     q = g2[b10]; v = rx1 * q[0] + ry0 * q[1];
190     a = mix(u, v, sx);
191 
192     q = g2[b01]; u = rx0 * q[0] + ry1 * q[1];
193     q = g2[b11]; v = rx1 * q[0] + ry1 * q[1];
194     b = mix(u, v, sx);
195 
196     return 1.5f * mix(a, b, sy);
197 }
198 
199 static float turbulencef2(float x, float y, float octaves)
200 {
201     float t = 0.0f;
202 
203     for (float f = 1.0f; f <= octaves; f *= 2)
204         t += fabs(noisef2(f * x, f * y)) / f;
205     return t;
206 }
207 
208 void updateBlades()
209 {
210     Blade_t *bladeStruct = Blades;
211     for (int i = 0; i < gBladesCount; i ++) {
212         float xpos = rsRand(-gWidth, gWidth);
213         bladeStruct->xPos = xpos;
214         bladeStruct->turbulencex = xpos * 0.006f;
215         bladeStruct->yPos = gHeight;
216         bladeStruct++;
217     }
218 }
219 
220 static float time(int isPreview) {
221     if (REAL_TIME && !isPreview) {
222         rs_time_t currentTime = rsTime(0);
223         rs_tm localTime;
224         rsLocaltime(&localTime, &currentTime);
225         return (localTime.tm_hour * 3600.0f +
226                 localTime.tm_min * 60.0f +
227                 localTime.tm_sec) / SECONDS_IN_DAY;
228     }
229     float t = rsUptimeMillis() / 30000.0f;
230     return t - (int) t;
231 }
232 
233 static void alpha(float a) {
234     rsgProgramFragmentConstantColor(gPFBackground, 1.0f, 1.0f, 1.0f, a);
235 }
236 
237 static float normf(float start, float stop, float value) {
238     return (value - start) / (stop - start);
239 }
240 
241 static void drawNight(int width, int height) {
242     rsgBindTexture(gPFBackground, 0, gTNight);
243     rsgDrawQuadTexCoords(
244             0.0f, -32.0f, 0.0f,
245             0.0f, 1.0f,
246             0.0f, height, 0.0f,
247             0.0f, 0.0f,
248             width, height, 0.0f,
249             2.0f, 0.0f,
250             width, -32.0f, 0.0f,
251             2.0f, 1.0f);
252 }
253 
254 static void drawSunrise(int width, int height) {
255     rsgBindTexture(gPFBackground, 0, gTSunrise);
256     rsgDrawRect(0.0f, 0.0f, width, height, 0.0f);
257 }
258 
259 static void drawNoon(int width, int height) {
260     rsgBindTexture(gPFBackground, 0, gTSky);
261     rsgDrawRect(0.0f, 0.0f, width, height, 0.0f);
262 }
263 
264 static void drawSunset(int width, int height) {
265     rsgBindTexture(gPFBackground, 0, gTSunset);
266     rsgDrawRect(0.0f, 0.0f, width, height, 0.0f);
267 }
268 
269 
270 static uchar4 hsbToRgb(float h, float s, float b)
271 {
272     float red = 0.0f;
273     float green = 0.0f;
274     float blue = 0.0f;
275 
276     float x = h;
277     float y = s;
278     float z = b;
279 
280     float hf = (x - (int) x) * 6.0f;
281     int ihf = (int) hf;
282     float f = hf - ihf;
283     float pv = z * (1.0f - y);
284     float qv = z * (1.0f - y * f);
285     float tv = z * (1.0f - y * (1.0f - f));
286 
287     switch (ihf) {
288         case 0:         // Red is the dominant color
289             red = z;
290             green = tv;
291             blue = pv;
292             break;
293         case 1:         // Green is the dominant color
294             red = qv;
295             green = z;
296             blue = pv;
297             break;
298         case 2:
299             red = pv;
300             green = z;
301             blue = tv;
302             break;
303         case 3:         // Blue is the dominant color
304             red = pv;
305             green = qv;
306             blue = z;
307             break;
308         case 4:
309             red = tv;
310             green = pv;
311             blue = z;
312             break;
313         case 5:         // Red is the dominant color
314             red = z;
315             green = pv;
316             blue = qv;
317             break;
318     }
319 
320     return rsPackColorTo8888(red, green, blue);
321 }
322 
323 static int drawBlade(Blade_t *bladeStruct, Vertex_t *v,
324         float brightness, float xOffset, float now) {
325 
326     float scale = bladeStruct->scale;
327     float angle = bladeStruct->angle;
328     float xpos = bladeStruct->xPos + xOffset;
329     int size = bladeStruct->size;
330 
331     uchar4 color = hsbToRgb(bladeStruct->h, bladeStruct->s,
332                             mix(0.f, bladeStruct->b, brightness));
333 
334     float newAngle = (turbulencef2(bladeStruct->turbulencex, now, 4.0f) - 0.5f) * 0.5f;
335     angle = clamp(angle + (newAngle + bladeStruct->offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);
336 
337     float currentAngle = HALF_PI;
338 
339     float bottomX = xpos;
340     float bottomY = bladeStruct->yPos;
341 
342     float d = angle * bladeStruct->hardness;
343 
344 
345     float si = size * scale;
346     float bottomLeft = bottomX - si;
347     float bottomRight = bottomX + si;
348     float bottom = bottomY + HALF_TESSELATION;
349 
350     v[0].color = color;                          // V1.ABGR
351     v[0].position.x = bottomLeft;                    // V1.X
352     v[0].position.y = bottom;                        // V1.Y
353     v[0].texture0.x = 0.f;                           // V1.s
354     v[0].texture0.y = 0.f;                           // V1.t
355                                                     //
356     v[1].color = color;                          // V2.ABGR
357     v[1].position.x = bottomRight;                   // V2.X
358     v[1].position.y = bottom;                        // V2.Y
359     v[1].texture0.x = 1.f;                           // V2.s
360     v[1].texture0.y = 0.f;                           // V2.t
361     v += 2;
362 
363     for ( ; size > 0; size -= 1) {
364         float topX = bottomX - cos(currentAngle) * bladeStruct->lengthX;
365         float topY = bottomY - sin(currentAngle) * bladeStruct->lengthY;
366 
367         si = (float)size * scale;
368         float spi = si - scale;
369 
370         float topLeft = topX - spi;
371         float topRight = topX + spi;
372 
373         v[0].color = color;                          // V1.ABGR
374         v[0].position.x = topLeft;                       // V1.X
375         v[0].position.y = topY;                          // V1.Y
376         v[0].texture0.x = 0.f;                           // V1.s
377         v[0].texture0.y = 0.f;                           // V1.t
378 
379         v[1].color = color;                          // V2.ABGR
380         v[1].position.x = topRight;                      // V2.X
381         v[1].position.y = topY;                          // V2.Y
382         v[1].texture0.x = 1.f;                           // V2.s
383         v[1].texture0.y = 0.f;                           // V2.t
384 
385         v += 2;
386         bottomX = topX;
387         bottomY = topY;
388         currentAngle += d;
389     }
390 
391     bladeStruct->angle = angle;
392 
393     // 2 vertices per triangle, 5 properties per vertex (RGBA, X, Y, S, T)
394     return bladeStruct->size * 2 + 2;
395 }
396 
397 static void drawBlades(float brightness, float xOffset) {
398     // For anti-aliasing
399     rsgBindTexture(gPFGrass, 0, gTAa);
400 
401     Blade_t *bladeStruct = Blades;
402     Vertex_t *vtx = Verticies;
403     float now = rsUptimeMillis() * 0.00004f;
404 
405     for (int i = 0; i < gBladesCount; i += 1) {
406         int offset = drawBlade(bladeStruct, vtx, brightness, xOffset, now);
407         vtx += offset;
408         bladeStruct ++;
409     }
410 
411     rsgDrawMesh(gBladesMesh, 0, 0, gIndexCount);
412 }
413 
414 int root(void) {
415     float x = mix((float)gWidth, 0.f, gXOffset);
416 
417     float now = time(gIsPreview);
418 
419     rsgBindProgramVertex(gPVBackground);
420     rsgBindProgramFragment(gPFBackground);
421     rsgBindProgramStore(gPSBackground);
422     alpha(1.0f);
423 
424     float newB = 1.0f;
425     if (now >= 0.0f && now < gDawn) {                    // Draw night
426         drawNight(gWidth, gHeight);
427         newB = 0.0f;
428     } else if (now >= gDawn && now <= gMorning) {         // Draw sunrise
429         float half = gDawn + (gMorning - gDawn) * 0.5f;
430         if (now <= half) {                              // Draw night->sunrise
431             drawNight(gWidth, gHeight);
432             newB = normf(gDawn, half, now);
433             alpha(newB);
434             drawSunrise(gWidth, gHeight);
435         } else {                                        // Draw sunrise->day
436             drawSunrise(gWidth, gHeight);
437             alpha(normf(half, gMorning, now));
438             drawNoon(gWidth, gHeight);
439         }
440     } else if (now > gMorning && now < gAfternoon) {      // Draw day
441         drawNoon(gWidth, gHeight);
442     } else if (now >= gAfternoon && now <= gDusk) {       // Draw sunset
443         float half = gAfternoon + (gDusk - gAfternoon) * 0.5f;
444         if (now <= half) {                              // Draw day->sunset
445             drawNoon(gWidth, gHeight);
446             newB = normf(gAfternoon, half, now);
447             alpha(newB);
448             newB = 1.0f - newB;
449             drawSunset(gWidth, gHeight);
450         } else {                                        // Draw sunset->night
451             drawSunset(gWidth, gHeight);
452             alpha(normf(half, gDusk, now));
453             drawNight(gWidth, gHeight);
454             newB = 0.0f;
455         }
456     } else if (now > gDusk) {                            // Draw night
457         drawNight(gWidth, gHeight);
458         newB = 0.0f;
459     }
460 
461     rsgBindProgramFragment(gPFGrass);
462     drawBlades(newB, x);
463 
464     return 50;
465 }
466