Home | History | Annotate | Download | only in raw
      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 #pragma stateVertex(PVBackground)
     17 #pragma stateFragment(PFBackground)
     18 #pragma stateStore(PFSBackground)
     19 
     20 #define RSID_BLADES_BUFFER 2
     21 
     22 #define TESSELATION 0.5f
     23 #define HALF_TESSELATION 0.25f
     24 
     25 #define MAX_BEND 0.09f
     26 
     27 #define SECONDS_IN_DAY 86400.0f
     28 
     29 #define PI 3.1415926f
     30 #define HALF_PI 1.570796326f
     31 
     32 #define REAL_TIME 1
     33 
     34 void updateBlades()
     35 {
     36     int bladesCount = State->bladesCount;
     37     struct Blades_s *bladeStruct = Blades;
     38 
     39     int i;
     40     for (i = 0; i < bladesCount; i ++) {
     41         float xpos = randf2(-State->width, State->width);
     42         bladeStruct->xPos = xpos;
     43         bladeStruct->turbulencex = xpos * 0.006f;
     44         bladeStruct->yPos = State->height;
     45         bladeStruct++;
     46     }
     47 }
     48 
     49 float time(int isPreview) {
     50     if (REAL_TIME && !isPreview) {
     51         return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY;
     52     }
     53     float t = uptimeMillis() / 30000.0f;
     54     return t - (int) t;
     55 }
     56 
     57 void alpha(float a) {
     58     color(1.0f, 1.0f, 1.0f, a);
     59 }
     60 
     61 void drawNight(int width, int height) {
     62     bindTexture(NAMED_PFBackground, 0, NAMED_TNight);
     63     drawQuadTexCoords(
     64             0.0f, -32.0f, 0.0f,
     65             0.0f, 1.0f,
     66             width, -32.0f, 0.0f,
     67             2.0f, 1.0f,
     68             width, 1024.0f - 32.0f, 0.0f,
     69             2.0f, 0.0f,
     70             0.0f, 1024.0f - 32.0f, 0.0f,
     71             0.0f, 0.0f);
     72 }
     73 
     74 void drawSunrise(int width, int height) {
     75     bindTexture(NAMED_PFBackground, 0, NAMED_TSunrise);
     76     drawRect(0.0f, 0.0f, width, height, 0.0f);
     77 }
     78 
     79 void drawNoon(int width, int height) {
     80     bindTexture(NAMED_PFBackground, 0, NAMED_TSky);
     81     drawRect(0.0f, 0.0f, width, height, 0.0f);
     82 }
     83 
     84 void drawSunset(int width, int height) {
     85     bindTexture(NAMED_PFBackground, 0, NAMED_TSunset);
     86     drawRect(0.0f, 0.0f, width, height, 0.0f);
     87 }
     88 
     89 int drawBlade(struct Blades_s *bladeStruct, float *bladeBuffer, int *bladeColor,
     90         float brightness, float xOffset, float now) {
     91 
     92     float scale = bladeStruct->scale;
     93     float angle = bladeStruct->angle;
     94     float xpos = bladeStruct->xPos + xOffset;
     95     int size = bladeStruct->size;
     96 
     97     int color = hsbToAbgr(bladeStruct->h, bladeStruct->s,
     98                           lerpf(0, bladeStruct->b, brightness), 1.0f);
     99 
    100     float newAngle = (turbulencef2(bladeStruct->turbulencex, now, 4.0f) - 0.5f) * 0.5f;
    101     angle = clampf(angle + (newAngle + bladeStruct->offset - angle) * 0.15f, -MAX_BEND, MAX_BEND);
    102 
    103     float currentAngle = HALF_PI;
    104 
    105     float bottomX = xpos;
    106     float bottomY = bladeStruct->yPos;
    107 
    108     float d = angle * bladeStruct->hardness;
    109 
    110 
    111     float si = size * scale;
    112     float bottomLeft = bottomX - si;
    113     float bottomRight = bottomX + si;
    114     float bottom = bottomY + HALF_TESSELATION;
    115 
    116     bladeColor[0] = color;                          // V1.ABGR
    117     bladeBuffer[1] = bottomLeft;                    // V1.X
    118     bladeBuffer[2] = bottom;                        // V1.Y
    119     bladeBuffer[3] = 0.f;                           // V1.s
    120     bladeBuffer[4] = 0.f;                           // V1.t
    121                                                     //
    122     bladeColor[5] = color;                          // V2.ABGR
    123     bladeBuffer[6] = bottomRight;                   // V2.X
    124     bladeBuffer[7] = bottom;                        // V2.Y
    125     bladeBuffer[8] = 1.f;                           // V2.s
    126     bladeBuffer[9] = 0.f;                           // V2.t
    127     bladeBuffer += 10;
    128     bladeColor += 10;
    129 
    130     for ( ; size > 0; size -= 1) {
    131         float topX = bottomX - cosf_fast(currentAngle) * bladeStruct->lengthX;
    132         float topY = bottomY - sinf_fast(currentAngle) * bladeStruct->lengthY;
    133 
    134         si = (float)size * scale;
    135         float spi = si - scale;
    136 
    137         float topLeft = topX - spi;
    138         float topRight = topX + spi;
    139 
    140         bladeColor[0] = color;                          // V1.ABGR
    141         bladeBuffer[1] = topLeft;                       // V1.X
    142         bladeBuffer[2] = topY;                          // V1.Y
    143         bladeBuffer[3] = 0.f;                           // V1.s
    144         bladeBuffer[4] = 0.f;                           // V1.t
    145 
    146         bladeColor[5] = color;                          // V2.ABGR
    147         bladeBuffer[6] = topRight;                      // V2.X
    148         bladeBuffer[7] = topY;                          // V2.Y
    149         bladeBuffer[8] = 1.f;                           // V2.s
    150         bladeBuffer[9] = 0.f;                           // V2.t
    151 
    152         bladeBuffer += 10;
    153         bladeColor += 10;
    154 
    155         bottomX = topX;
    156         bottomY = topY;
    157 
    158         currentAngle += d;
    159     }
    160 
    161     bladeStruct->angle = angle;
    162 
    163     // 2 vertices per triangle, 5 properties per vertex (RGBA, X, Y, S, T)
    164     return bladeStruct->size * 10 + 10;
    165 }
    166 
    167 void drawBlades(float brightness, float xOffset) {
    168     // For anti-aliasing
    169     bindTexture(NAMED_PFGrass, 0, NAMED_TAa);
    170 
    171     int bladesCount = State->bladesCount;
    172 
    173     int i = 0;
    174     struct Blades_s *bladeStruct = Blades;
    175     float *bladeBuffer = loadArrayF(RSID_BLADES_BUFFER, 0);
    176     int *bladeColor = loadArrayI32(RSID_BLADES_BUFFER, 0);
    177 
    178     float now = uptimeMillis() * 0.00004f;
    179 
    180     for ( ; i < bladesCount; i += 1) {
    181         int offset = drawBlade(bladeStruct, bladeBuffer, bladeColor, brightness, xOffset, now);
    182         bladeBuffer += offset;
    183         bladeColor += offset;
    184         bladeStruct ++;
    185     }
    186 
    187     uploadToBufferObject(NAMED_BladesBuffer);
    188     drawSimpleMeshRange(NAMED_BladesMesh, 0, State->indexCount);
    189 }
    190 
    191 int main(int launchID) {
    192     int width = State->width;
    193     int height = State->height;
    194 
    195     float x = lerpf(width, 0, State->xOffset);
    196 
    197     float now = time(State->isPreview);
    198     alpha(1.0f);
    199 
    200     float newB = 1.0f;
    201     float dawn = State->dawn;
    202     float morning = State->morning;
    203     float afternoon = State->afternoon;
    204     float dusk = State->dusk;
    205 
    206     if (now >= 0.0f && now < dawn) {                    // Draw night
    207         drawNight(width, height);
    208         newB = 0.0f;
    209     } else if (now >= dawn && now <= morning) {         // Draw sunrise
    210         float half = dawn + (morning - dawn) * 0.5f;
    211         if (now <= half) {                              // Draw night->sunrise
    212             drawNight(width, height);
    213             newB = normf(dawn, half, now);
    214             alpha(newB);
    215             drawSunrise(width, height);
    216         } else {                                        // Draw sunrise->day
    217             drawSunrise(width, height);
    218             alpha(normf(half, morning, now));
    219             drawNoon(width, height);
    220         }
    221     } else if (now > morning && now < afternoon) {      // Draw day
    222         drawNoon(width, height);
    223     } else if (now >= afternoon && now <= dusk) {       // Draw sunset
    224         float half = afternoon + (dusk - afternoon) * 0.5f;
    225         if (now <= half) {                              // Draw day->sunset
    226             drawNoon(width, height);
    227             newB = normf(afternoon, half, now);
    228             alpha(newB);
    229             newB = 1.0f - newB;
    230             drawSunset(width, height);
    231         } else {                                        // Draw sunset->night
    232             drawSunset(width, height);
    233             alpha(normf(half, dusk, now));
    234             drawNight(width, height);
    235             newB = 0.0f;
    236         }
    237     } else if (now > dusk) {                            // Draw night
    238         drawNight(width, height);
    239         newB = 0.0f;
    240     }
    241 
    242     bindProgramFragment(NAMED_PFGrass);
    243     drawBlades(newB, x);
    244 
    245     return 50;
    246 }
    247