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 #pragma stateVertex(PVBkOrtho) 17 #pragma stateRaster(parent) 18 #pragma stateFragment(PFBackground) 19 #pragma stateStore(PFSBackground) 20 21 #define ELLIPSE_RATIO 0.892f 22 23 #define PI 3.1415f 24 #define TWO_PI 6.283f 25 #define ELLIPSE_TWIST 0.023333333f 26 27 float angle; 28 29 /** 30 * Script initialization. Called automatically. 31 */ 32 void init() { 33 angle = 50.0f; 34 } 35 36 /** 37 * Helper function to generate the stars. 38 */ 39 float randomGauss() { 40 float x1; 41 float x2; 42 float w = 2.f; 43 44 while (w >= 1.0f) { 45 x1 = 2.0f * randf2(0.0f, 1.0f) - 1.0f; 46 x2 = 2.0f * randf2(0.0f, 1.0f) - 1.0f; 47 w = x1 * x1 + x2 * x2; 48 } 49 50 w = sqrtf(-2.0 * logf(w) / w); 51 return x1 * w; 52 } 53 54 float gSpeed[12000]; 55 56 /** 57 * Generates the properties for a given star. 58 */ 59 void createParticle(struct Particles_s *part, int idx, float scale) { 60 float d = fabsf(randomGauss()) * State->galaxyRadius * 0.5f + randf(64.0f); 61 float id = d / State->galaxyRadius; 62 float z = randomGauss() * 0.4f * (1.0f - id); 63 float p = -d * ELLIPSE_TWIST; 64 65 int r,g,b,a; 66 if (d < State->galaxyRadius * 0.33f) { 67 r = (int) (220 + id * 35); 68 g = 220; 69 b = 220; 70 } else { 71 r = 180; 72 g = 180; 73 b = (int) clampf(140.f + id * 115.f, 140.f, 255.f); 74 } 75 // Stash point size * 10 in Alpha 76 a = (int) (randf2(1.2f, 2.1f) * 60); 77 part->color = r | g<<8 | b<<16 | a<<24; 78 79 if (d > State->galaxyRadius * 0.15f) { 80 z *= 0.6f * (1.0f - id); 81 } else { 82 z *= 0.72f; 83 } 84 85 // Map to the projection coordinates (viewport.x = -1.0 -> 1.0) 86 d = mapf(-4.0f, State->galaxyRadius + 4.0f, 0.0f, scale, d); 87 88 part->position.x = randf(TWO_PI); 89 part->position.y = d; 90 gSpeed[idx] = randf2(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f; 91 92 part->position.z = z / 5.0f; 93 } 94 95 /** 96 * Initialize all the stars. Called from Java. 97 */ 98 void initParticles() { 99 if (State->isPreview == 1) { 100 angle = 0.0f; 101 } 102 103 struct Particles_s *part = Particles; 104 int particlesCount = State->particlesCount; 105 float scale = State->galaxyRadius / (State->width * 0.5f); 106 107 int i; 108 for (i = 0; i < particlesCount; i ++) { 109 createParticle(part, i, scale); 110 part++; 111 } 112 } 113 114 void drawSpace(float xOffset, int width, int height) { 115 bindTexture(NAMED_PFBackground, 0, NAMED_TSpace); 116 drawQuadTexCoords( 117 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 118 width, 0.0f, 0.0f, 2.0f, 1.0f, 119 width, height, 0.0f, 2.0f, 0.0f, 120 0.0f, height, 0.0f, 0.0f, 0.0f); 121 } 122 123 void drawLights(float xOffset, int width, int height) { 124 bindProgramVertex(NAMED_PVBkProj); 125 bindProgramFragment(NAMED_PFBackground); 126 bindTexture(NAMED_PFBackground, 0, NAMED_TLight1); 127 128 float scale = 512.0f / width; 129 float x = -scale + xOffset - scale * 0.05f; 130 float y = -scale; 131 132 scale *= 2.0f; 133 134 drawQuad(x, y, 0.0f, 135 x + scale * 1.1f, y, 0.0f, 136 x + scale * 1.1f, y + scale, 0.0f, 137 x, y + scale, 0.0f); 138 } 139 140 void drawParticles(float xOffset, float offset, int width, int height) { 141 bindProgramVertex(NAMED_PVStars); 142 bindProgramFragment(NAMED_PFStars); 143 bindProgramFragmentStore(NAMED_PFSLights); 144 bindTexture(NAMED_PFStars, 0, NAMED_TFlares); 145 146 float a = offset * angle; 147 float absoluteAngle = fabsf(a); 148 149 float matrix[16]; 150 matrixLoadTranslate(matrix, 0.0f, 0.0f, 10.0f - 6.0f * absoluteAngle / 50.0f); 151 if (State->scale == 0) { 152 matrixScale(matrix, 6.6f, 6.0f, 1.0f); 153 } else { 154 matrixScale(matrix, 12.6f, 12.0f, 1.0f); 155 } 156 matrixRotate(matrix, absoluteAngle, 1.0f, 0.0f, 0.0f); 157 matrixRotate(matrix, a, 0.0f, 0.4f, 0.1f); 158 vpLoadModelMatrix(matrix); 159 160 // quadratic attenuation 161 //pointAttenuation(0.1f + 0.3f * fabsf(offset), 0.0f, 0.06f + 0.1f * fabsf(offset)); 162 163 int radius = State->galaxyRadius; 164 int particlesCount = State->particlesCount; 165 166 struct Particles_s *vtx = Particles; 167 168 int i = 0; 169 for ( ; i < particlesCount; i++) { 170 vtx->position.x = vtx->position.x + gSpeed[i]; 171 vtx++; 172 } 173 174 uploadToBufferObject(NAMED_ParticlesBuffer); 175 drawSimpleMeshRange(NAMED_ParticlesMesh, 0, particlesCount); 176 } 177 178 int main(int index) { 179 int width = State->width; 180 int height = State->height; 181 182 float x = 0.0f; 183 float offset = lerpf(-1.0f, 1.0f, State->xOffset); 184 185 drawSpace(x, width, height); 186 187 drawParticles(x, offset, width, height); 188 drawLights(x, width, height); 189 190 return 45; 191 } 192