Update fall to new RS API
[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 stateFragmentStore(PFSBackground)
19
20 #define RSID_STATE 0
21 #define RSID_RIPPLE_MAP 1
22 #define RSID_REFRACTION_MAP 2
23 #define RSID_LEAVES 3
24 #define RSID_DROP 4
25
26 #define LEAF_STRUCT_FIELDS_COUNT 11
27 #define LEAF_STRUCT_X 0
28 #define LEAF_STRUCT_Y 1
29 #define LEAF_STRUCT_SCALE 2
30 #define LEAF_STRUCT_ANGLE 3
31 #define LEAF_STRUCT_SPIN 4
32 #define LEAF_STRUCT_U1 5
33 #define LEAF_STRUCT_U2 6
34 #define LEAF_STRUCT_ALTITUDE 7
35 #define LEAF_STRUCT_RIPPLED 8
36 #define LEAF_STRUCT_DELTAX 9
37 #define LEAF_STRUCT_DELTAY 10
38
39 #define LEAVES_TEXTURES_COUNT 4
40
41 #define LEAF_SIZE 0.55f
42
43 #define REFRACTION 1.333f
44 #define DAMP 3
45
46 #define DROP_RADIUS 2
47 // The higher, the smaller the ripple
48 #define RIPPLE_HEIGHT 10.0f
49
50 float g_SkyOffsetX;
51 float g_SkyOffsetY;
52
53 struct vert_s {
54     float nx;
55     float ny;
56     float nz;
57     float s;
58     float t;
59     float x;
60     float y;
61     float z;
62 };
63
64 int offset(int x, int y, int width) {
65     return x + 1 + (y + 1) * (width + 2);
66 }
67
68 void dropWithStrength(int x, int y, int r, int s) {
69     int width = State->meshWidth;
70     int height = State->meshHeight;
71
72     if (x < r) x = r;
73     if (y < r) y = r;
74     if (x >= width - r) x = width - r - 1;
75     if (y >= height - r) y = height - r - 1;
76
77     x = width - x;
78
79     int rippleMapSize = State->rippleMapSize;
80     int index = State->rippleIndex;
81     int origin = offset(0, 0, width);
82
83     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
84     int sqr = r * r;
85     float invs = 1.0f / s;
86
87     int h = 0;
88     for ( ; h < r; h += 1) {
89         int sqv = h * h;
90         int yn = origin + (y - h) * (width + 2);
91         int yp = origin + (y + h) * (width + 2);
92         int w = 0;
93         for ( ; w < r; w += 1) {
94             int squ = w * w;
95             if (squ + sqv < sqr) {
96                 int v = -sqrtf((sqr - (squ + sqv)) << 16) * invs;
97                 current[yn + x + w] = v;
98                 current[yp + x + w] = v;
99                 current[yn + x - w] = v;
100                 current[yp + x - w] = v;
101             }
102         }
103     }
104 }
105
106 void drop(int x, int y, int r) {
107     dropWithStrength(x, y, r, 1);
108 }
109
110 void updateRipples() {
111     int rippleMapSize = State->rippleMapSize;
112     int width = State->meshWidth;
113     int height = State->meshHeight;
114     int index = State->rippleIndex;
115     int origin = offset(0, 0, width);
116
117     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
118     int* next = loadArrayI32(RSID_RIPPLE_MAP, (1 - index) * rippleMapSize + origin);
119
120     storeI32(RSID_STATE, OFFSETOF_WorldState_rippleIndex, 1 - index);
121
122     int a = 1;
123     int b = width + 2;
124     int h = height;
125     while (h) {
126         int w = width;
127         while (w) {
128             int droplet = ((current[-b] + current[b] + current[-a] + current[a]) >> 1) - *next;
129             droplet -= (droplet >> DAMP);
130             *next = droplet;
131             current += 1;
132             next += 1;
133             w -= 1;
134         }
135         current += 2;
136         next += 2;
137         h -= 1;
138     }
139 }
140
141 int refraction(int d, int wave, int *map) {
142     int i = d;
143     if (i < 0) i = -i;
144     if (i > 512) i = 512;
145     int w = (wave + 0x10000) >> 8;
146     w &= ~(w >> 31);
147     int r = (map[i] * w) >> 3;
148     if (d < 0) {
149         return -r;
150     }
151     return r;
152 }
153
154 void generateRipples() {
155     int rippleMapSize = loadI32(RSID_STATE, OFFSETOF_WorldState_rippleMapSize);
156     int width = State->meshWidth;
157     int height = State->meshHeight;
158     int index = State->rippleIndex;
159     int origin = offset(0, 0, width);
160
161     int b = width + 2;
162
163     int* current = loadArrayI32(RSID_RIPPLE_MAP, index * rippleMapSize + origin);
164     int *map = loadArrayI32(RSID_REFRACTION_MAP, 0);
165     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
166     struct vert_s *vert = (struct vert_s *)vertices;
167
168     float fw = 1.f / width;
169     float fh = 1.f / height;
170     float fy = (1.0f / 512.0f) * (1.0f / RIPPLE_HEIGHT);
171
172     int h = height - 1;
173     while (h >= 0) {
174         int w = width - 1;
175         int wave = *current;
176         int offset = h * width;
177         struct vert_s *vtx = vert + offset + w;
178
179         while (w >= 0) {
180             int nextWave = current[1];
181             int dx = nextWave - wave;
182             int dy = current[b] - wave;
183
184             int offsetx = refraction(dx, wave, map) >> 16;
185             int u = (width - w) + offsetx;
186             u &= ~(u >> 31);
187             if (u >= width) u = width - 1;
188
189             int offsety = refraction(dy, wave, map) >> 16;
190             int v = (height - h) + offsety;
191             v &= ~(v >> 31);
192             if (v >= height) v = height - 1;
193
194             vtx->s = u * fw;
195             vtx->t = v * fh;
196             vtx->z = dy * fy;
197             vtx --;
198
199             w -= 1;
200             current += 1;
201             wave = nextWave;
202         }
203         h -= 1;
204         current += 2;
205     }
206
207     // Compute the normals for lighting
208     int y = 0;
209     for ( ; y < height; y += 1) {
210         int x = 0;
211         int yOffset = y * width;
212         struct vert_s *v = vert;
213
214         for ( ; x < width; x += 1) {
215             struct vec3_s n1, n2, n3;
216             vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
217             vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
218             vec3Cross(&n3, &n1, &n2);
219             vec3Norm(&n3);
220
221             // Average of previous normal and N1 x N2
222             vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
223             vec3Cross(&n2, &n1, &n2);
224             vec3Add(&n3, &n3, &n2);
225             vec3Norm(&n3);
226
227             v->nx = n3.x;
228             v->ny = n3.y;
229             v->nz = -n3.z;
230             v += 1;
231
232             // reset Z
233             //vertices[(yOffset + x) << 3 + 7] = 0.0f;
234         }
235     }
236 }
237
238 float averageZ(float x1, float x2, float y1, float y2, float* vertices,
239         int meshWidth, int meshHeight, float glWidth, float glHeight) {
240
241     x1 = ((x1 + glWidth * 0.5f) / glWidth) * meshWidth;
242     x2 = ((x2 + glWidth * 0.5f) / glWidth) * meshWidth;
243     y1 = ((y1 + glHeight * 0.5f) / glHeight) * meshHeight;
244     y2 = ((y2 + glHeight * 0.5f) / glHeight) * meshHeight;
245
246     int quadX1 = clamp(x1, 0, meshWidth);
247     int quadX2 = clamp(x2, 0, meshWidth);
248     int quadY1 = clamp(y1, 0, meshHeight);
249     int quadY2 = clamp(y2, 0, meshHeight);
250
251     float z = 0.0f;
252     int vertexCount = 0;
253
254     int y = quadY1;
255     for ( ; y < quadY2; y += 1) {
256         int x = quadX1;
257         int yOffset = y * meshWidth;
258         for ( ; x < quadX2; x += 1) {
259             z += vertices[(yOffset + x) << 3 + 7];
260             vertexCount += 1;
261         }
262     }
263
264     return 55.0f * z / vertexCount;
265 }
266
267 void drawLeaf(int index, float* vertices, int meshWidth, int meshHeight,
268         float glWidth, float glHeight) {
269
270     float *leafStruct = loadArrayF(RSID_LEAVES, index);
271
272     float x = leafStruct[LEAF_STRUCT_X];
273     float x1 = x - LEAF_SIZE;
274     float x2 = x + LEAF_SIZE;
275
276     float y = leafStruct[LEAF_STRUCT_Y];
277     float y1 = y - LEAF_SIZE;
278     float y2 = y + LEAF_SIZE;
279
280     float u1 = leafStruct[LEAF_STRUCT_U1];
281     float u2 = leafStruct[LEAF_STRUCT_U2];
282
283     float z1 = 0.0f;
284     float z2 = 0.0f;
285     float z3 = 0.0f;
286     float z4 = 0.0f;
287
288     float a = leafStruct[LEAF_STRUCT_ALTITUDE];
289     float s = leafStruct[LEAF_STRUCT_SCALE];
290     float r = leafStruct[LEAF_STRUCT_ANGLE];
291
292     float tz = 0.0f;
293     if (a > 0.0f) {
294         tz = -a;
295     } else {
296 //        z1 = averageZ(x1, x, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
297 //        z2 = averageZ(x, x2, y1, y, vertices, meshWidth, meshHeight, glWidth, glHeight);
298 //        z3 = averageZ(x, x2, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
299 //        z4 = averageZ(x1, x, y, y2, vertices, meshWidth, meshHeight, glWidth, glHeight);
300     }
301
302     x1 -= x;
303     x2 -= x;
304     y1 -= y;
305     y2 -= y;
306
307     float matrix[16];
308     matrixLoadIdentity(matrix);
309     matrixTranslate(matrix, x, y, tz);
310     matrixScale(matrix, s, s, 1.0f);
311     matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
312     vpLoadModelMatrix(matrix);
313
314     drawQuadTexCoords(x1, y1, z1, u1, 1.0f,
315                       x2, y1, z2, u2, 1.0f,
316                       x2, y2, z3, u2, 0.0f,
317                       x1, y2, z4, u1, 0.0f);
318
319     float spin = leafStruct[LEAF_STRUCT_SPIN];
320     if (a <= 0.0f) {
321         float rippled = leafStruct[LEAF_STRUCT_RIPPLED];
322         if (rippled < 0.0f) {
323             drop(((x + glWidth * 0.5f) / glWidth) * meshWidth,
324                  meshHeight - ((y + glHeight * 0.5f) / glHeight) * meshHeight,
325                  DROP_RADIUS);
326             spin /= 4.0f;
327             leafStruct[LEAF_STRUCT_SPIN] = spin;
328             leafStruct[LEAF_STRUCT_RIPPLED] = 1.0f;
329         } else {
330 //            dropWithStrength(((x + glWidth / 2.0f) / glWidth) * meshWidth,
331 //                meshHeight - ((y + glHeight / 2.0f) / glHeight) * meshHeight,
332 //                2, 5);
333         }
334         leafStruct[LEAF_STRUCT_X] = x + leafStruct[LEAF_STRUCT_DELTAX];
335         leafStruct[LEAF_STRUCT_Y] = y + leafStruct[LEAF_STRUCT_DELTAY];
336         r += spin;
337         leafStruct[LEAF_STRUCT_ANGLE] = r;
338     } else {
339         a -= 0.005f;
340         leafStruct[LEAF_STRUCT_ALTITUDE] = a;
341         r += spin * 2.0f;
342         leafStruct[LEAF_STRUCT_ANGLE] = r;
343     }
344
345     if (-LEAF_SIZE * s + x > glWidth / 2.0f || LEAF_SIZE * s + x < -glWidth / 2.0f ||
346         LEAF_SIZE * s + y < -glHeight / 2.0f) {
347
348         int sprite = randf(LEAVES_TEXTURES_COUNT);
349         leafStruct[LEAF_STRUCT_X] = randf2(-1.0f, 1.0f);
350         leafStruct[LEAF_STRUCT_Y] = glHeight / 2.0f + LEAF_SIZE * 2 * randf(1.0f);
351         leafStruct[LEAF_STRUCT_SCALE] = randf2(0.4f, 0.5f);
352         leafStruct[LEAF_STRUCT_SPIN] = degf(randf2(-0.02f, 0.02f)) / 4.0f;
353         leafStruct[LEAF_STRUCT_U1] = sprite / (float) LEAVES_TEXTURES_COUNT;
354         leafStruct[LEAF_STRUCT_U2] = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
355         leafStruct[LEAF_STRUCT_DELTAX] = randf2(-0.02f, 0.02f) / 60.0f;
356         leafStruct[LEAF_STRUCT_DELTAY] = -0.08f * randf2(0.9f, 1.1f) / 60.0f;
357     }
358 }
359
360 void drawLeaves() {
361     bindProgramFragment(NAMED_PFBackground);
362     bindProgramFragmentStore(NAMED_PFSLeaf);
363     bindProgramVertex(NAMED_PVSky);
364     bindTexture(NAMED_PFBackground, 0, NAMED_TLeaves);
365
366     int leavesCount = State->leavesCount;
367     int count = leavesCount * LEAF_STRUCT_FIELDS_COUNT;
368     int width = State->meshWidth;
369     int height = State->meshHeight;
370     float glWidth = State->glWidth;
371     float glHeight = State->glHeight;
372
373     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
374
375     int i = 0;
376     for ( ; i < count; i += LEAF_STRUCT_FIELDS_COUNT) {
377         drawLeaf(i, vertices, width, height, glWidth, glHeight);
378     }
379
380     float matrix[16];
381     matrixLoadIdentity(matrix);
382     vpLoadModelMatrix(matrix);
383 }
384
385 void drawRiverbed() {
386     bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
387
388     drawSimpleMesh(NAMED_WaterMesh);
389 }
390
391 void drawSky() {
392     color(1.0f, 1.0f, 1.0f, 0.8f);
393
394     bindProgramFragment(NAMED_PFSky);
395     bindProgramFragmentStore(NAMED_PFSLeaf);
396     bindTexture(NAMED_PFSky, 0, NAMED_TSky);
397
398     float x = g_SkyOffsetX + State->skySpeedX;
399     float y = g_SkyOffsetY + State->skySpeedY;
400
401     if (x > 1.0f) x = 0.0f;
402     if (x < -1.0f) x = 0.0f;
403     if (y > 1.0f) y = 0.0f;
404
405     g_SkyOffsetX = x;
406     g_SkyOffsetY = y;
407
408     float matrix[16];
409     matrixLoadTranslate(matrix, x, y, 0.0f);
410     vpLoadTextureMatrix(matrix);
411
412     drawSimpleMesh(NAMED_WaterMesh);
413
414     matrixLoadIdentity(matrix);
415     vpLoadTextureMatrix(matrix);
416 }
417
418 void drawLighting() {
419     ambient(0.0f, 0.0f, 0.0f, 1.0f);
420     diffuse(0.0f, 0.0f, 0.0f, 1.0f);
421     specular(0.44f, 0.44f, 0.44f, 1.0f);
422     shininess(40.0f);
423
424     bindProgramFragmentStore(NAMED_PFSBackground);
425     bindProgramFragment(NAMED_PFLighting);
426     bindProgramVertex(NAMED_PVLight);
427
428     drawSimpleMesh(NAMED_WaterMesh);
429 }
430
431 void drawNormals() {
432     int width = State->meshWidth;
433     int height = State->meshHeight;
434
435     float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
436
437     bindProgramVertex(NAMED_PVSky);
438     bindProgramFragment(NAMED_PFLighting);
439
440     color(1.0f, 0.0f, 0.0f, 1.0f);
441
442     float scale = 1.0f / 10.0f;
443     int y = 0;
444     for ( ; y < height; y += 1) {
445         int yOffset = y * width;
446         int x = 0;
447         for ( ; x < width; x += 1) {
448             int offset = (yOffset + x) << 3;
449             float vx = vertices[offset + 5];
450             float vy = vertices[offset + 6];
451             float vz = vertices[offset + 7];
452             float nx = vertices[offset + 0];
453             float ny = vertices[offset + 1];
454             float nz = vertices[offset + 2];
455             drawLine(vx, vy, vz, vx + nx * scale, vy + ny * scale, vz + nz * scale);
456         }
457     }
458 }
459
460 int main(int index) {
461     if (Drop->dropX != -1) {
462         drop(Drop->dropX, Drop->dropY, DROP_RADIUS);
463         Drop->dropX = -1;
464         Drop->dropY = -1;
465     }
466
467     updateRipples();
468     generateRipples();
469     updateSimpleMesh(NAMED_WaterMesh);
470
471     drawRiverbed();
472     drawSky();
473     drawLighting();
474     drawLeaves();
475     //drawNormals();
476
477     return 1;
478 }