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