1 // Copyright (C) 2009 The Android Open Source Project
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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.
16 #pragma stateVertex(PVSky)
17 #pragma stateFragment(PFBackground)
18 #pragma stateStore(PFSBackground)
20 #define LEAVES_TEXTURES_COUNT 8
21 #define LEAF_SIZE 0.55f
22 #define LEAVES_COUNT 14
47 struct drop_s gDrops[10];
65 struct Leaves_s gLeavesStore[LEAVES_COUNT];
67 struct Leaves_s* gLeaves[LEAVES_COUNT];
69 struct Leaves_s* gNextLeaves[LEAVES_COUNT];
74 for (ct=0; ct<gMaxDrops; ct++) {
77 gDrops[ct].spread = 1;
78 gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
79 gDrops[ct].invSpread = 1 / gDrops[ct].spread;
80 gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
85 struct Leaves_s *leaf = gLeavesStore;
86 float width = State->glWidth * 2;
87 float height = State->glHeight;
90 for (i = 0; i < LEAVES_COUNT; i ++) {
92 int sprite = randf(LEAVES_TEXTURES_COUNT);
93 leaf->x = randf2(-width * 0.5f, width * 0.5f);
94 leaf->y = randf2(-height * 0.5f, height * 0.5f);
95 leaf->scale = randf2(0.4f, 0.5f);
96 leaf->angle = randf2(0.0f, 360.0f);
97 leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.25f;
98 leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
99 leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
100 leaf->altitude = -1.0f;
101 leaf->rippled = 1.0f;
102 leaf->deltaX = randf2(-0.02f, 0.02f) / 2.0f;
103 leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 2.0f;
108 void updateDrop(int ct) {
109 gDrops[ct].spread += 30.f * g_DT;
110 gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
111 gDrops[ct].invSpread = 1 / gDrops[ct].spread;
112 gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
113 gDrops[ct].ampE = gDrops[ct].ampS * gDrops[ct].invSpread;
116 void drop(int x, int y, float s) {
119 float minAmp = 10000.f;
120 for (ct = 0; ct < gMaxDrops; ct++) {
121 if (gDrops[ct].ampE < minAmp) {
123 minAmp = gDrops[ct].ampE;
126 gDrops[iMin].ampS = s;
127 gDrops[iMin].spread = 0;
129 gDrops[iMin].y = State->meshHeight - y - 1;
133 void generateRipples() {
134 int rippleMapSize = State->rippleMapSize;
135 int width = State->meshWidth;
136 int height = State->meshHeight;
137 int index = State->rippleIndex;
138 float ratio = (float)State->meshWidth / State->glWidth;
139 float xShift = State->xOffset * ratio * 2;
141 float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
142 struct vert_s *vert = (struct vert_s *)vertices;
144 float fw = 1.0f / width;
145 float fh = 1.0f / height;
147 struct vert_s *v = vert;
148 for (y=0; y < height; y++) {
149 for (x=0; x < width; x++) {
150 struct drop_s * d = &gDrops[0];
153 for (ct = 0; ct < gMaxDrops; ct++) {
154 if (d->ampE > 0.01f) {
155 float dx = (d->x - xShift) - x;
157 float dist2 = dx*dx + dy*dy;
158 if (dist2 < d->spread2) {
159 float dist = sqrtf(dist2);
160 float a = d->ampE * (dist * d->invSpread);
161 z += sinf(d->spread - dist) * a;
170 for (ct = 0; ct < gMaxDrops; ct++) {
175 for (y = 0; y < height; y += 1) {
176 for (x = 0; x < width; x += 1) {
177 struct vec3_s n1, n2, n3;
178 vec3Sub(&n1, (struct vec3_s *)&(v+1)->x, (struct vec3_s *)&v->x);
179 vec3Sub(&n2, (struct vec3_s *)&(v+width)->x, (struct vec3_s *)&v->x);
180 vec3Cross(&n3, &n1, &n2);
182 // Average of previous normal and N1 x N2
183 vec3Sub(&n1, (struct vec3_s *)&(v+width+1)->x, (struct vec3_s *)&v->x);
184 vec3Cross(&n2, &n1, &n2);
185 vec3Add(&n3, &n3, &n2);
186 //vec3Norm(&n3); // Not necessary for our constrained mesh.
188 v->s = (float)x * fw + n3.x;// * 0.2;
189 v->t = (float)y * fh + n3.y;// * 0.2;
196 void genLeafDrop(struct Leaves_s *leaf, float amp) {
197 float nx = (leaf->x + State->glWidth * 0.5f) / State->glWidth;
198 float ny = (leaf->y + State->glHeight * 0.5f) / State->glHeight;
199 drop(nx * State->meshWidth, State->meshHeight - ny * State->meshHeight, amp);
203 int drawLeaf(struct Leaves_s *leaf) {
211 float a = leaf->altitude;
212 float s = leaf->scale;
213 float r = leaf->angle;
224 if (a >= 0.4f) alpha = 1.0f - (a - 0.4f) / 0.1f;
226 color(0.0f, 0.0f, 0.0f, alpha * 0.15f);
229 matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
231 matrixLoadIdentity(matrix);
234 float shadowOffet = a / 5;
236 matrixTranslate(matrix, (x - State->xOffset * 2) + (shadowOffet / 2), y - shadowOffet, tz);
237 matrixScale(matrix, s, s, 1.0f);
238 matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
239 vpLoadModelMatrix(matrix);
241 drawQuadTexCoords(-LEAF_SIZE, -LEAF_SIZE, 0, u1, 1.0f,
242 LEAF_SIZE, -LEAF_SIZE, 0, u2, 1.0f,
243 LEAF_SIZE, LEAF_SIZE, 0, u2, 0.0f,
244 -LEAF_SIZE, LEAF_SIZE, 0, u1, 0.0f);
246 color(1.0f, 1.0f, 1.0f, alpha);
248 color(1.0f, 1.0f, 1.0f, 1.0f);
252 matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
254 matrixLoadIdentity(matrix);
256 matrixTranslate(matrix, x - State->xOffset * 2, y, tz);
257 matrixScale(matrix, s, s, 1.0f);
258 matrixRotate(matrix, r, 0.0f, 0.0f, 1.0f);
259 vpLoadModelMatrix(matrix);
261 drawQuadTexCoords(-LEAF_SIZE, -LEAF_SIZE, 0, u1, 1.0f,
262 LEAF_SIZE, -LEAF_SIZE, 0, u2, 1.0f,
263 LEAF_SIZE, LEAF_SIZE, 0, u2, 0.0f,
264 -LEAF_SIZE, LEAF_SIZE, 0, u1, 0.0f);
266 float spin = leaf->spin;
268 float rippled = leaf->rippled;
269 if (rippled < 0.0f) {
270 genLeafDrop(leaf, 1.5f);
271 //drop(((x + State->glWidth * 0.5f) / State->glWidth) * meshWidth,
272 // meshHeight - ((y + State->glHeight * 0.5f) / State->glHeight) * meshHeight, 1);
275 leaf->rippled = 1.0f;
277 leaf->x = x + leaf->deltaX * g_DT;
278 leaf->y = y + leaf->deltaY * g_DT;
289 if (-LEAF_SIZE * s + x > State->glWidth || LEAF_SIZE * s + x < -State->glWidth ||
290 LEAF_SIZE * s + y < -State->glHeight / 2.0f) {
292 int sprite = randf(LEAVES_TEXTURES_COUNT);
293 leaf->x = randf2(-State->glWidth, State->glWidth);
294 leaf->y = randf2(-State->glHeight * 0.5f, State->glHeight * 0.5f);
296 leaf->scale = randf2(0.4f, 0.5f);
297 leaf->spin = degf(randf2(-0.02f, 0.02f)) * 0.35f;
298 leaf->u1 = sprite / (float) LEAVES_TEXTURES_COUNT;
299 leaf->u2 = (sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
300 leaf->altitude = 0.7f;
301 leaf->rippled = -1.0f;
302 leaf->deltaX = randf2(-0.02f, 0.02f) / 2.0f;
303 leaf->deltaY = -0.08f * randf2(0.9f, 1.1f) / 2.0f;
311 bindProgramFragment(NAMED_PFSky);
312 bindProgramFragmentStore(NAMED_PFSLeaf);
313 bindProgramVertex(NAMED_PVSky);
314 bindTexture(NAMED_PFSky, 0, NAMED_TLeaves);
316 color(1.0f, 1.0f, 1.0f, 1.0f);
320 for ( ; i < LEAVES_COUNT; i += 1) {
321 if (drawLeaf(gLeaves[i])) {
330 // Copy all the old leaves to the beginning of gNextLeaves
331 for (i=0; i < LEAVES_COUNT; i++) {
332 if (gLeaves[i]->newLeaf == 0) {
333 gNextLeaves[index] = gLeaves[i];
338 // Now copy all the newly falling leaves to the end of gNextLeaves
339 for (i=0; i < LEAVES_COUNT; i++) {
340 if (gLeaves[i]->newLeaf > 0) {
341 gNextLeaves[index] = gLeaves[i];
342 gNextLeaves[index]->newLeaf = 0;
347 // And move everything in gNextLeaves back to gLeaves
348 for (i=0; i < LEAVES_COUNT; i++) {
349 gLeaves[i] = gNextLeaves[i];
354 matrixLoadIdentity(matrix);
355 vpLoadModelMatrix(matrix);
358 void drawRiverbed() {
359 bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
362 matrixLoadScale(matrix, 0.5f * 960.0f / 1024.0f, -1.0f * 800.0f / 1024.0f, 1.0f);
363 matrixTranslate(matrix, State->xOffset, 0.0f, 0.0f);
364 vpLoadTextureMatrix(matrix);
366 drawSimpleMesh(NAMED_WaterMesh);
368 matrixLoadIdentity(matrix);
369 vpLoadTextureMatrix(matrix);
374 color(1.0f, 1.0f, 1.0f, 0.5f);
376 bindProgramFragment(NAMED_PFSky);
377 bindProgramFragmentStore(NAMED_PFSLeaf);
378 bindTexture(NAMED_PFSky, 0, NAMED_TSky);
380 float x = skyOffsetX + State->skySpeedX;
381 float y = skyOffsetY + State->skySpeedY;
383 if (x > 1.0f) x = 0.0f;
384 if (x < -1.0f) x = 0.0f;
385 if (y > 1.0f) y = 0.0f;
391 matrixLoadTranslate(matrix, x + State->xOffset, y, 0.0f);
392 vpLoadTextureMatrix(matrix);
394 drawSimpleMesh(NAMED_WaterMesh);
396 matrixLoadIdentity(matrix);
397 vpLoadTextureMatrix(matrix);
401 int main(int index) {
402 // Compute dt in seconds.
403 int newTime = uptimeMillis();
404 g_DT = (newTime - g_LastTime) / 1000.f;
405 g_LastTime = newTime;
406 g_DT = minf(g_DT, 0.2f);
409 if (Drop->dropX != -1) {
410 drop(Drop->dropX, Drop->dropY, 2);
417 for (ct = 0; ct < gMaxDrops; ct++) {
418 if (gDrops[ct].ampE < 0.005f) {
424 int i = (int)randf(LEAVES_COUNT);
425 genLeafDrop(gLeaves[i], randf(0.3f) + 0.1f);
429 updateSimpleMesh(NAMED_WaterMesh);
433 matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
434 vpLoadModelMatrix(matrix);