Home | History | Annotate | Download | only in galaxy
      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