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, ¤tTime); 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