Update water with new wave physics.
[xdandroid:packages_wallpapers_basic.git] / res / raw / fall.rs
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(PVSky)
17 #pragma stateFragment(PFBackground)
18 #pragma stateStore(PFSBackground)
19
20 #define LEAVES_TEXTURES_COUNT 4
21 #define LEAF_SIZE 0.55f
22
23 float skyOffsetX;
24 float skyOffsetY;
25
26 struct vert_s {
27     float x;
28     float y;
29     float z;
30     float s;
31     float t;
32     float nx;
33     float ny;
34     float nz;
35 };
36
37 struct drop_s {
38     float amp;
39     float spread;
40     float invSpread;
41     float x;
42     float y;
43 };
44 struct drop_s gDrops[10];
45 int gNextDrop;
46 int gMaxDrops;
47
48 void init() {
49     int ct;
50     gMaxDrops = 10;
51     for (ct=0; ct<gMaxDrops; ct++) {
52         gDrops[ct].amp = 0;
53         gDrops[ct].spread = 1;
54         gDrops[ct].invSpread = 1 / gDrops[ct].spread;
55     }
56     gNextDrop = 0;
57 }
58
59 void initLeaves() {
60     struct Leaves_s *leaf = Leaves;
61     int leavesCount = State->leavesCount;
62     float width = State->glWidth;
63     float height = State->glHeight;
64
65     int i;
66     for (i = 0; i < leavesCount; i ++) {
67         int sprite = randf(LEAVES_TEXTURES_COUNT);
68         leaf->x = randf2(-width * 0.5f, width * 0.5f);
69         leaf->y = randf2(-height * 0.5f, height * 0.5f);
70         leaf->scale = randf2(0.4f, 0.5f);
71         leaf->angle = randf2(0.0f, 360.0f);
72         leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
73         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
74         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
75         leaf->altitude = -1.0f;
76         leaf->rippled = 1.0f;
77         leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
78         leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
79         leaf++;
80     }
81 }
82
83 void drop(int x, int y, float s) {
84     gDrops[gNextDrop].amp = s;
85     gDrops[gNextDrop].spread = 0.5f;
86     gDrops[gNextDrop].x = x;
87     gDrops[gNextDrop].y = State->meshHeight - y - 1;
88     gNextDrop++;
89     if (gNextDrop >= gMaxDrops)
90         gNextDrop = 0;
91 }
92
93 void generateRipples() {
94     int rippleMapSize = State->rippleMapSize;
95     int width = State->meshWidth;
96     int height = State->meshHeight;
97     int index = State->rippleIndex;
98
99     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
100     struct vert_s *vert = (struct vert_s *)vertices;
101
102     float fw = 1.0f / width;
103     float fh = 1.0f / height;
104     {
105         int x, y, ct;
106         struct vert_s *vtx = vert;
107         for (y=0; y < height; y++) {
108             for (x=0; x < width; x++) {
109                 struct drop_s * d = &gDrops[0];
110                 float z = 0;
111
112                 for (ct = 0; ct < gMaxDrops; ct++) {
113                     float dx = d->x - x;
114                     float dy = d->y - y;
115                     float dist = sqrtf(dx*dx + dy*dy);
116                     if (dist < d->spread && d->amp) {
117                         float a = d->amp * d->invSpread;
118                         a *= dist * d->invSpread;
119                         z += sinf(d->spread - dist) * a;
120                     }
121                     d++;
122                 }
123                 vtx->s = (float)x * fw;
124                 vtx->t = (float)y * fh;
125                 vtx->z = z;
126                 vtx ++;
127             }
128         }
129         for (ct = 0; ct < gMaxDrops; ct++) {
130             gDrops[ct].spread += 1;
131             gDrops[ct].invSpread = 1 / gDrops[ct].spread;
132             gDrops[ct].amp = maxf(gDrops[ct].amp - 0.01f, 0);
133         }
134     }
135
136     // Compute the normals for lighting
137     int y = 0;
138     for ( ; y < (height-1); y += 1) {
139         int x = 0;
140         int yOffset = y * width;
141         struct vert_s *v = vert;
142         v += y * width;
143
144         for ( ; x < (width-1); x += 1) {
145             struct vec3_s n1, n2, n3;
146             vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
147             vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
148             vec3Cross(&n3, &n1, &n2);
149             vec3Norm(&n3);
150
151             // Average of previous normal and N1 x N2
152             vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
153             vec3Cross(&n2, &n1, &n2);
154             vec3Add(&n3, &n3, &n2);
155             vec3Norm(&n3);
156
157             v->nx = n3.x;
158             v->ny = n3.y;
159             v->nz = -n3.z;
160             v->s += v->nx * 0.005;
161             v->t += v->ny * 0.005;
162             v += 1;
163
164             // reset Z
165             //vertices[(yOffset + x) << 3 + 7] = 0.0f;
166         }
167     }
168 }
169
170 void drawLeaf(struct Leaves_s *leaf, int meshWidth, int meshHeight, float glWidth, float glHeight,
171         int rotate) {
172
173     float x = leaf->x;
174     float x1 = x - LEAF_SIZE;
175     float x2 = x + LEAF_SIZE;
176
177     float y = leaf->y;
178     float y1 = y - LEAF_SIZE;
179     float y2 = y + LEAF_SIZE;
180
181     float u1 = leaf->u1;
182     float u2 = leaf->u2;
183
184     float z1 = 0.0f;
185     float z2 = 0.0f;
186     float z3 = 0.0f;
187     float z4 = 0.0f;
188
189     float a = leaf->altitude;
190     float s = leaf->scale;
191     float r = leaf->angle;
192
193     float tz = 0.0f;
194     if (a > 0.0f) {
195         tz = -a;
196     }
197
198     x1 -= x;
199     x2 -= x;
200     y1 -= y;
201     y2 -= y;
202
203     float matrix[16];
204
205     if (a > 0.0f) {
206         color(0.0f, 0.0f, 0.0f, 0.15f);
207
208         if (rotate) {
209             matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
210         } else {
211             matrixLoadIdentity(matrix);
212         }
213         matrixTranslate(matrix, x, y, 0.0f);
214         matrixScale(matrix, s, s, 1.0f);
215         matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
216         vpLoadModelMatrix(matrix);
217
218         drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
219                           x2, y1, z2, u2, 1.0f,
220                           x2, y2, z3, u2, 0.0f,
221                           x1, y2, z4, u1, 0.0f);
222
223         float alpha = 1.0f;
224         if (a >= 0.4f) alpha = 1.0f - (a - 0.5f) / 0.1f;
225         color(1.0f, 1.0f, 1.0f, alpha);
226     } else {
227         color(1.0f, 1.0f, 1.0f, 1.0f);
228     }
229
230     if (rotate) {
231         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
232     } else {
233         matrixLoadIdentity(matrix);
234     }
235     matrixTranslate(matrix, x, y, tz);
236     matrixScale(matrix, s, s, 1.0f);
237     matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
238     vpLoadModelMatrix(matrix);
239
240     drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
241                       x2, y1, z2, u2, 1.0f,
242                       x2, y2, z3, u2, 0.0f,
243                       x1, y2, z4, u1, 0.0f);
244
245     float spin = leaf->spin;
246     if (a <= 0.0f) {
247         float rippled = leaf->rippled;
248         if (rippled < 0.0f) {
249             drop(((x + glWidth * 0.5f) / glWidth) * meshWidth,
250                  meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight, 1);
251             spin /= 4.0f;
252             leaf->spin = spin;
253             leaf->rippled = 1.0f;
254         }
255         leaf->x = x + leaf->deltaX;
256         leaf->y = y + leaf->deltaY;
257         r += spin;
258         leaf->angle = r;
259     } else {
260         a -= 0.005f;
261         leaf->altitude = a;
262         r += spin * 2.0f;
263         leaf->angle = r;
264     }
265
266     if (-LEAF_SIZE * s + x > glWidth / 2.0f || LEAF_SIZE * s + x < -glWidth / 2.0f ||
267             LEAF_SIZE * s + y < -glHeight / 2.0f) {
268
269         int sprite = randf(LEAVES_TEXTURES_COUNT);
270         leaf->x = randf2(-glWidth * 0.5f, glWidth * 0.5f);
271         leaf->y = randf2(-glHeight * 0.5f, glHeight * 0.5f);
272         leaf->scale = randf2(0.4f, 0.5f);
273         leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
274         leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
275         leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
276         leaf->altitude = 0.6f;
277         leaf->rippled = -1.0f;
278         leaf->deltaX = randf2(-0.02f, 0.02f) / 60.0f;
279         leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
280     }
281 }
282
283 void drawLeaves() {
284     bindProgramFragment(NAMED_PFSky);
285     bindProgramFragmentStore(NAMED_PFSLeaf);
286     bindProgramVertex(NAMED_PVSky);
287     bindTexture(NAMED_PFSky, 0, NAMED_TLeaves);
288
289     color(1.0f, 1.0f, 1.0f, 1.0f);
290
291     int leavesCount = State->leavesCount;
292     int width = State->meshWidth;
293     int height = State->meshHeight;
294     float glWidth = State->glWidth;
295     float glHeight = State->glHeight;
296     int rotate = State->rotate;
297
298     struct Leaves_s *leaf = Leaves;
299
300     int i = 0;
301     for ( ; i < leavesCount; i += 1) {
302         drawLeaf(leaf, width, height, glWidth, glHeight, rotate);
303         leaf += 1;
304     }
305
306     float matrix[16];
307     matrixLoadIdentity(matrix);
308     vpLoadModelMatrix(matrix);
309 }
310
311 void drawRiverbed() {
312     bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
313
314     drawSimpleMesh(NAMED_WaterMesh);
315 }
316
317 void drawSky() {
318     color(1.0f, 1.0f, 1.0f, 0.5f);
319
320     bindProgramFragment(NAMED_PFSky);
321     bindProgramFragmentStore(NAMED_PFSLeaf);
322     bindTexture(NAMED_PFSky, 0, NAMED_TSky);
323
324     float x = skyOffsetX + State->skySpeedX;
325     float y = skyOffsetY + State->skySpeedY;
326
327     if (x > 1.0f) x = 0.0f;
328     if (x < -1.0f) x = 0.0f;
329     if (y > 1.0f) y = 0.0f;
330
331     skyOffsetX = x;
332     skyOffsetY = y;
333
334     float matrix[16];
335     matrixLoadTranslate(matrix, x, y, 0.0f);
336     vpLoadTextureMatrix(matrix);
337
338     drawSimpleMesh(NAMED_WaterMesh);
339
340     matrixLoadIdentity(matrix);
341     vpLoadTextureMatrix(matrix);
342 }
343
344 void drawLighting() {
345     ambient(0.0f, 0.0f, 0.0f, 1.0f);
346     diffuse(0.0f, 0.0f, 0.0f, 1.0f);
347     specular(0.44f, 0.44f, 0.44f, 1.0f);
348     shininess(40.0f);
349
350     bindProgramFragmentStore(NAMED_PFSBackground);
351     bindProgramFragment(NAMED_PFLighting);
352     bindProgramVertex(NAMED_PVLight);
353
354     drawSimpleMesh(NAMED_WaterMesh);
355 }
356
357 void drawNormals() {
358     int width = State->meshWidth;
359     int height = State->meshHeight;
360
361     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
362
363     bindProgramVertex(NAMED_PVSky);
364     bindProgramFragment(NAMED_PFLighting);
365
366     color(1.0f, 0.0f, 0.0f, 1.0f);
367
368     float scale = 1.0f / 10.0f;
369     int y = 0;
370     for ( ; y < height; y += 1) {
371         int yOffset = y * width;
372         int x = 0;
373         for ( ; x < width; x += 1) {
374             int offset = (yOffset + x) << 3;
375             float vx = vertices[offset + 5];
376             float vy = vertices[offset + 6];
377             float vz = vertices[offset + 7];
378             float nx = vertices[offset + 0];
379             float ny = vertices[offset + 1];
380             float nz = vertices[offset + 2];
381             drawLine(vx, vy, vz, vx + nx * scale, vy + ny * scale, vz + nz * scale);
382         }
383     }
384 }
385
386 int main(int index) {
387     if (Drop->dropX != -1) {
388         drop(Drop->dropX, Drop->dropY, 1);
389         Drop->dropX = -1;
390         Drop->dropY = -1;
391     }
392
393     int ct;
394     float amp = 0;
395     for (ct = 0; ct < gMaxDrops; ct++) {
396         amp += gDrops[ct].amp;
397     }
398
399     if (State->isPreview || (amp < 0.2f)) {
400         float x = randf(State->meshWidth);
401         float y = randf(State->meshHeight);
402
403         if (State->isPreview) {
404             drop(x, y, 1.f);
405         } else {
406             drop(x, y, 0.2f);
407         }
408     }
409
410     generateRipples();
411     updateSimpleMesh(NAMED_WaterMesh);
412
413     if (State->rotate) {
414         float matrix[16];
415         matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
416         vpLoadModelMatrix(matrix);
417     }
418
419     drawRiverbed();
420     drawSky();
421     drawLighting();
422     drawLeaves();
423     //drawNormals();
424
425     return 1;
426 }