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