Home | History | Annotate | Download | only in grass
      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