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(PVBackground)
17 #pragma stateFragment(PFBackground)
18 #pragma stateStore(PFSBackground)
20 #define RSID_BLADES_BUFFER 2
22 #define TESSELATION 0.5f
23 #define HALF_TESSELATION 0.25f
25 #define MAX_BEND 0.09f
27 #define SECONDS_IN_DAY 86400.0f
30 #define HALF_PI 1.570796326f
36 int bladesCount = State->bladesCount;
37 struct Blades_s *bladeStruct = Blades;
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;
49 float time(int isPreview) {
50 if (REAL_TIME && !isPreview) {
51 return (hour() * 3600.0f + minute() * 60.0f + second()) / SECONDS_IN_DAY;
53 float t = uptimeMillis() / 30000.0f;
58 color(1.0f, 1.0f, 1.0f, a);
61 void drawNight(int width, int height) {
62 bindTexture(NAMED_PFBackground, 0, NAMED_TNight);
68 width, 1024.0f - 32.0f, 0.0f,
70 0.0f, 1024.0f - 32.0f, 0.0f,
74 void drawSunrise(int width, int height) {
75 bindTexture(NAMED_PFBackground, 0, NAMED_TSunrise);
76 drawRect(0.0f, 0.0f, width, height, 0.0f);
79 void drawNoon(int width, int height) {
80 bindTexture(NAMED_PFBackground, 0, NAMED_TSky);
81 drawRect(0.0f, 0.0f, width, height, 0.0f);
84 void drawSunset(int width, int height) {
85 bindTexture(NAMED_PFBackground, 0, NAMED_TSunset);
86 drawRect(0.0f, 0.0f, width, height, 0.0f);
89 int drawBlade(struct Blades_s *bladeStruct, float *bladeBuffer, int *bladeColor,
90 float brightness, float xOffset, float now) {
92 float scale = bladeStruct->scale;
93 float angle = bladeStruct->angle;
94 float xpos = bladeStruct->xPos + xOffset;
95 int size = bladeStruct->size;
97 int color = hsbToAbgr(bladeStruct->h, bladeStruct->s,
98 lerpf(0, bladeStruct->b, brightness), 1.0f);
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);
103 float currentAngle = HALF_PI;
105 float bottomX = xpos;
106 float bottomY = bladeStruct->yPos;
108 float d = angle * bladeStruct->hardness;
110 int triangles = size * 2;
112 for ( ; size > 0; size -= 1) {
113 float topX = bottomX - cosf_fast(currentAngle) * bladeStruct->lengthX;
114 float topY = bottomY - sinf_fast(currentAngle) * bladeStruct->lengthY;
116 float si = size * scale;
117 float spi = si - scale;
119 float bottomLeft = bottomX - si;
120 float bottomRight = bottomX + si;
121 float topLeft = topX - spi;
122 float topRight = topX + spi;
123 float bottom = bottomY + HALF_TESSELATION;
126 bladeColor[0] = color; // V1.ABGR
128 bladeBuffer[1] = bottomLeft; // V1.X
129 bladeBuffer[2] = bottom; // V1.Y
131 bladeColor[5] = color; // V1.ABGR
133 bladeBuffer[6] = topLeft; // V2.X
134 bladeBuffer[7] = topY; // V2.Y
136 bladeColor[10] = color; // V3.ABGR
138 bladeBuffer[11] = topRight; // V3.X
139 bladeBuffer[12] = topY; // V3.Y
145 bladeColor[0] = color; // V1.ABGR
147 bladeBuffer[1] = bottomLeft; // V1.X
148 bladeBuffer[2] = bottom; // V1.Y
150 bladeColor[5] = color; // V2.ABGR
152 bladeBuffer[6] = topRight; // V2.X
153 bladeBuffer[7] = topY; // V2.Y
155 bladeColor[10] = color; // V3.ABGR
157 bladeBuffer[11] = bottomRight; // V3.X
158 bladeBuffer[12] = bottom; // V3.Y
169 bladeStruct->angle = angle;
171 // 3 vertices per triangle, 5 properties per vertex (RGBA, X, Y, S, T)
172 return triangles * 15;
175 void drawBlades(float brightness, float xOffset) {
177 bindTexture(NAMED_PFGrass, 0, NAMED_TAa);
179 int bladesCount = State->bladesCount;
180 int trianglesCount = State->trianglesCount;
183 struct Blades_s *bladeStruct = Blades;
184 float *bladeBuffer = loadArrayF(RSID_BLADES_BUFFER, 0);
185 int *bladeColor = loadArrayI32(RSID_BLADES_BUFFER, 0);
187 float now = uptimeMillis() * 0.00004f;
189 for ( ; i < bladesCount; i += 1) {
190 int offset = drawBlade(bladeStruct, bladeBuffer, bladeColor, brightness, xOffset, now);
191 bladeBuffer += offset;
192 bladeColor += offset;
196 uploadToBufferObject(NAMED_BladesBuffer);
197 drawSimpleMeshRange(NAMED_BladesMesh, 0, trianglesCount * 3);
200 int main(int launchID) {
201 int width = State->width;
202 int height = State->height;
204 float x = lerpf(width, 0, State->xOffset);
206 float now = time(State->isPreview);
210 float dawn = State->dawn;
211 float morning = State->morning;
212 float afternoon = State->afternoon;
213 float dusk = State->dusk;
215 if (now >= 0.0f && now < dawn) { // Draw night
216 drawNight(width, height);
218 } else if (now >= dawn && now <= morning) { // Draw sunrise
219 float half = dawn + (morning - dawn) * 0.5f;
220 if (now <= half) { // Draw night->sunrise
221 drawNight(width, height);
222 newB = normf(dawn, half, now);
224 drawSunrise(width, height);
225 } else { // Draw sunrise->day
226 drawSunrise(width, height);
227 alpha(normf(half, morning, now));
228 drawNoon(width, height);
230 } else if (now > morning && now < afternoon) { // Draw day
231 drawNoon(width, height);
232 } else if (now >= afternoon && now <= dusk) { // Draw sunset
233 float half = afternoon + (dusk - afternoon) * 0.5f;
234 if (now <= half) { // Draw day->sunset
235 drawNoon(width, height);
236 newB = normf(afternoon, half, now);
239 drawSunset(width, height);
240 } else { // Draw sunset->night
241 drawSunset(width, height);
242 alpha(normf(half, dusk, now));
243 drawNight(width, height);
246 } else if (now > dusk) { // Draw night
247 drawNight(width, height);
251 bindProgramFragment(NAMED_PFGrass);