• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.galaxy)
18 
19 #include "rs_graphics.rsh"
20 
21 #pragma stateVertex(parent);
22 #pragma stateStore(parent);
23 
24 #define ELLIPSE_RATIO 0.892f
25 #define PI 3.1415f
26 #define TWO_PI 6.283f
27 #define ELLIPSE_TWIST 0.023333333f
28 
29 static float angle = 50.f;
30 static int gOldWidth;
31 static int gOldHeight;
32 static int gWidth;
33 static int gHeight;
34 static float gSpeed[12000];
35 static int gGalaxyRadius = 300;
36 static rs_allocation gParticlesBuffer;
37 
38 float gXOffset;
39 int gIsPreview;
40 
41 rs_program_fragment gPFBackground;
42 rs_program_fragment gPFStars;
43 rs_program_vertex gPVStars;
44 rs_program_vertex gPVBkProj;
45 rs_program_store gPSLights;
46 
47 rs_allocation gTSpace;
48 rs_allocation gTFlares;
49 rs_allocation gTLight1;
50 rs_mesh gParticlesMesh;
51 
52 typedef struct __attribute__((packed, aligned(4))) Particle {
53     uchar4 color;
54     float3 position;
55 } Particle_t;
56 Particle_t *Particles;
57 
58 typedef struct VpConsts {
59     rs_matrix4x4 Proj;
60     rs_matrix4x4 MVP;
61 } VpConsts_t;
62 VpConsts_t *vpConstants;
63 
64 static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
65     return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
66 }
67 
68 /**
69  * Helper function to generate the stars.
70  */
71 static float randomGauss() {
72     float x1;
73     float x2;
74     float w = 2.f;
75 
76     while (w >= 1.0f) {
77         x1 = rsRand(2.0f) - 1.0f;
78         x2 = rsRand(2.0f) - 1.0f;
79         w = x1 * x1 + x2 * x2;
80     }
81 
82     w = sqrt(-2.0f * log(w) / w);
83     return x1 * w;
84 }
85 
86 /**
87  * Generates the properties for a given star.
88  */
89 static void createParticle(Particle_t *part, int idx, float scale) {
90     float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
91     float id = d / gGalaxyRadius;
92     float z = randomGauss() * 0.4f * (1.0f - id);
93     float p = -d * ELLIPSE_TWIST;
94 
95     if (d < gGalaxyRadius * 0.33f) {
96         part->color.x = (uchar) (220 + id * 35);
97         part->color.y = 220;
98         part->color.z = 220;
99     } else {
100         part->color.x = 180;
101         part->color.y = 180;
102         part->color.z = (uchar) clamp(140.f + id * 115.f, 140.f, 255.f);
103     }
104     // Stash point size * 10 in Alpha
105     part->color.w = (uchar) (rsRand(1.2f, 2.1f) * 60);
106 
107     if (d > gGalaxyRadius * 0.15f) {
108         z *= 0.6f * (1.0f - id);
109     } else {
110         z *= 0.72f;
111     }
112 
113     // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
114     d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
115 
116     part->position.x = rsRand(TWO_PI);
117     part->position.y = d;
118     gSpeed[idx] = rsRand(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
119 
120     part->position.z = z / 5.0f;
121 }
122 
123 /**
124  * Initialize all the stars. Called from Java.
125  */
126 void initParticles() {
127     if (gIsPreview == 1) {
128         angle = 0.0f;
129     }
130 
131     Particle_t *part = Particles;
132     float scale = gGalaxyRadius / (gWidth * 0.5f);
133     int count = rsAllocationGetDimX(gParticlesBuffer);
134     for (int i = 0; i < count; i ++) {
135         createParticle(part, i, scale);
136         part++;
137     }
138 }
139 
140 static void drawSpace() {
141     rsgBindProgramFragment(gPFBackground);
142     rsgBindTexture(gPFBackground, 0, gTSpace);
143     rsgDrawQuadTexCoords(
144             0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
145             gWidth, 0.0f, 0.0f, 2.0f, 1.0f,
146             gWidth, gHeight, 0.0f, 2.0f, 0.0f,
147             0.0f, gHeight, 0.0f, 0.0f, 0.0f);
148 }
149 
150 static void calcMatrix(rs_matrix4x4 *out, float offset) {
151     float a = offset * angle;
152     float absoluteAngle = fabs(a);
153 
154     rsMatrixLoadTranslate(out, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f);
155     if (gHeight > gWidth) {
156         rsMatrixScale(out, 6.6f, 6.0f, 1.0f);
157     } else {
158         rsMatrixScale(out, 12.6f, 12.0f, 1.0f);
159     }
160     rsMatrixRotate(out, absoluteAngle, 1.0f, 0.0f, 0.0f);
161     rsMatrixRotate(out, a, 0.0f, 0.4f, 0.1f);
162 }
163 
164 static void drawLights(const rs_matrix4x4 *m) {
165     rsgBindProgramVertex(gPVBkProj);
166     rsgBindProgramFragment(gPFBackground);
167     rsgBindTexture(gPFBackground, 0, gTLight1);
168     rsgProgramVertexLoadModelMatrix(m);
169 
170     float sx = (512.0f / gWidth) * 1.1f;
171     float sy = (512.0f / gWidth) * 1.2f;
172     rsgDrawQuad(-sx, -sy, 0.0f,
173                  sx, -sy, 0.0f,
174                  sx,  sy, 0.0f,
175                 -sx,  sy, 0.0f);
176 }
177 
178 static void drawParticles(const rs_matrix4x4 *m) {
179     rsMatrixLoad(&vpConstants->MVP, &vpConstants->Proj);
180     rsMatrixMultiply(&vpConstants->MVP, m);
181     rsgAllocationSyncAll(rsGetAllocation(vpConstants));
182 
183     rsgBindProgramVertex(gPVStars);
184     rsgBindProgramFragment(gPFStars);
185     rsgBindProgramStore(gPSLights);
186     rsgBindTexture(gPFStars, 0, gTFlares);
187 
188     Particle_t *vtx = Particles;
189     int count = rsAllocationGetDimX(gParticlesBuffer);
190     for (int i = 0; i < count; i++) {
191         vtx->position.x = vtx->position.x + gSpeed[i];
192         vtx++;
193     }
194 
195     rsgDrawMesh(gParticlesMesh);
196 }
197 
198 int root() {
199     rsgClearColor(0.f, 0.f, 0.f, 1.f);
200 
201     gParticlesBuffer = rsGetAllocation(Particles);
202     rsgBindProgramFragment(gPFBackground);
203 
204     gWidth = rsgGetWidth();
205     gHeight = rsgGetHeight();
206     if ((gWidth != gOldWidth) || (gHeight != gOldHeight)) {
207         initParticles();
208         gOldWidth = gWidth;
209         gOldHeight = gHeight;
210     }
211 
212     drawSpace();
213 
214     rs_matrix4x4 matrix;
215     calcMatrix(&matrix, mix(-0.5f, 0.5f, gXOffset));
216     drawParticles(&matrix);
217     drawLights(&matrix);
218 
219     return 45;
220 }
221