OSDN Git Service

Improve the rendering of the galaxy.
authorRomain Guy <romainguy@android.com>
Sat, 5 Sep 2009 00:54:17 +0000 (17:54 -0700)
committerRomain Guy <romainguy@android.com>
Sat, 5 Sep 2009 00:54:17 +0000 (17:54 -0700)
Change-Id: If6bdf21bc187425fcf036842746d1ba10689d239

res/raw/galaxy.rs
src/com/android/wallpaper/galaxy/GalaxyRS.java

index deac8ab..a78133b 100644 (file)
 
 #define ELLIPSE_RATIO 0.892f
 
+float angle;
+float distance;
+
+void init() {
+    angle = 0.0f;
+    distance = 0.0f;
+}
+
 void drawSpace(float xOffset, int width, int height) {
     bindTexture(NAMED_PFBackground, 0, NAMED_TSpace);
     drawQuadTexCoords(
@@ -29,43 +37,56 @@ void drawSpace(float xOffset, int width, int height) {
 }
 
 void drawLights(float xOffset, int width, int height) {
-    float x = (width - 512.0f) * 0.5f + xOffset;
-    float y = (height - 512.0f) * 0.5f;
-
-    // increase the size of the texture by 5% on each side
-    x -= 512.0f * 0.05f;
-
+    bindProgramVertex(NAMED_PVStars);
     bindProgramFragment(NAMED_PFBackground);
     bindTexture(NAMED_PFBackground, 0, NAMED_TLight1);
-    drawQuad(x + 512.0f * 1.1f, y         , 0.0f,
-             x                , y         , 0.0f,
-             x                , y + 512.0f, 0.0f,
-             x + 512.0f * 1.1f, y + 512.0f, 0.0f);
+
+    float scale = 512.0f / width;
+    float x = -scale + xOffset - scale * 0.05f;
+    float y = -scale;
+
+    scale *= 2.0f;
+
+    drawQuad(x, y, 0.0f,
+             x + scale * 1.1f, y, 0.0f,
+             x + scale * 1.1f, y + scale, 0.0f,
+             x, y + scale, 0.0f);
 }
 
 void drawParticles(float xOffset, int width, int height) {
-    bindProgramFragment(NAMED_PFBasic);
+    bindProgramVertex(NAMED_PVStars);
+    bindProgramFragment(NAMED_PFStars);
     bindProgramFragmentStore(NAMED_PFSLights);
+    bindTexture(NAMED_PFStars, 0, NAMED_TFlares);
+
+    float matrix[16];
+    matrixLoadTranslate(matrix, 0.0f, 0.0f, 10.0f - 6.0f * distance);
+    matrixScale(matrix, 6.15f, 6.0f, 1.0f);
+    matrixRotate(matrix, angle, 1.0f, 0.5f, 0.0f);
+    vpLoadModelMatrix(matrix);
+
+    // quadratic attenuation
+    pointAttenuation(0.1f, 0.0f, 0.06f);
 
     int radius = State->galaxyRadius;
     int particlesCount = State->particlesCount;
 
-    float w = width * 0.5f + xOffset;
-    float h = height * 0.5f;
+    float w = xOffset;
 
-    int i = 0;
     struct Stars_s *star = Stars;
-    struct Parts_s *vtx = Parts;
+    struct Particles_s *vtx = Particles;
+
+    int i = 0;
     for ( ; i < particlesCount; i++) {
         float a = star->angle + star->speed;
         float x = star->distance * sinf(a);
         float y = star->distance * cosf(a) * ELLIPSE_RATIO;
 
         vtx->x = star->t * x + star->s * y + w;
-        vtx->y = star->s * x - star->t * y + h;
+        vtx->y = star->s * x - star->t * y;
         star->angle = a;
-        star ++;
-        vtx ++;
+        star++;
+        vtx++;
     }
 
     uploadToBufferObject(NAMED_ParticlesBuffer);
@@ -76,11 +97,16 @@ int main(int index) {
     int width = State->width;
     int height = State->height;
 
-    float w = width * 0.5f;
-    float x = lerpf(w, -w, State->xOffset);
+    float x = lerpf(1.0f, -1.0f, State->xOffset);
 
     drawSpace(x, width, height);
     drawParticles(x, width, height);
     drawLights(x, width, height);
+
+//    if (angle < 68.0f) {
+//        angle += 0.4f;
+//        distance = angle / 68.0f;
+//    }
+
     return 1;
 }
index 760014c..e38e004 100644 (file)
@@ -26,6 +26,7 @@ import android.renderscript.Element;
 import android.renderscript.SimpleMesh;
 import android.renderscript.Primitive;
 import android.renderscript.Type;
+import static android.renderscript.Sampler.Value.LINEAR;
 import static android.renderscript.Sampler.Value.NEAREST;
 import static android.renderscript.Sampler.Value.WRAP;
 import static android.renderscript.ProgramStore.DepthFunc.*;
@@ -33,8 +34,6 @@ import static android.renderscript.ProgramStore.BlendDstFunc;
 import static android.renderscript.ProgramStore.BlendSrcFunc;
 import static android.renderscript.ProgramFragment.EnvMode.*;
 import static android.renderscript.Element.*;
-import android.graphics.BitmapFactory;
-import android.graphics.Bitmap;
 import static android.util.MathUtils.*;
 
 import java.util.TimeZone;
@@ -51,17 +50,15 @@ class GalaxyRS extends RenderScriptScene {
     private static final int RSID_PARTICLES = 1;
     private static final int RSID_PARTICLES_BUFFER = 2;
 
-    private static final int TEXTURES_COUNT = 2;
+    private static final int TEXTURES_COUNT = 3;
     private static final int RSID_TEXTURE_SPACE = 0;
     private static final int RSID_TEXTURE_LIGHT1 = 1;
-
-
-    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+    private static final int RSID_TEXTURE_FLARES = 2;
 
     @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramFragment mPfBackground;
     @SuppressWarnings({"FieldCanBeLocal"})
-    private ProgramFragment mPfBasic;
+    private ProgramFragment mPfStars;
     @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramStore mPfsBackground;
     @SuppressWarnings({"FieldCanBeLocal"})
@@ -69,10 +66,16 @@ class GalaxyRS extends RenderScriptScene {
     @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramVertex mPvBackground;
     @SuppressWarnings({"FieldCanBeLocal"})
+    private ProgramVertex mPvStars;
+    @SuppressWarnings({"FieldCanBeLocal"})
     private Sampler mSampler;
     @SuppressWarnings({"FieldCanBeLocal"})
+    private Sampler mStarSampler;
+    @SuppressWarnings({"FieldCanBeLocal"})
     private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
     @SuppressWarnings({"FieldCanBeLocal"})
+    private ProgramVertex.MatrixAllocation mPvProjectionAlloc;
+    @SuppressWarnings({"FieldCanBeLocal"})
     private Allocation[] mTextures;
 
     private GalaxyState mGalaxyState;
@@ -84,12 +87,10 @@ class GalaxyRS extends RenderScriptScene {
     @SuppressWarnings({"FieldCanBeLocal"})
     private SimpleMesh mParticlesMesh;
 
-    private final float[] mFloatData3 = new float[4];
+    private final float[] mFloatData = new float[5];
 
     GalaxyRS(int width, int height) {
         super(width, height);
-        mOptionsARGB.inScaled = false;
-        mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
     }
 
     @Override
@@ -102,13 +103,13 @@ class GalaxyRS extends RenderScriptScene {
 
         ScriptC.Builder sb = new ScriptC.Builder(mRS);
         sb.setType(mStateType, "State", RSID_STATE);
-        sb.setType(mParticlesMesh.getVertexType(0), "Parts", RSID_PARTICLES_BUFFER);
+        sb.setType(mParticlesMesh.getVertexType(0), "Particles", RSID_PARTICLES_BUFFER);
         sb.setType(mParticlesType, "Stars", RSID_PARTICLES);
         sb.setScript(mResources, R.raw.galaxy);
         sb.setRoot(true);
 
         ScriptC script = sb.create();
-        script.setClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+        script.setClearColor(1.0f, 0.0f, 0.0f, 1.0f);
         script.setTimeZone(TimeZone.getDefault().getID());
 
         script.bindAllocation(mState, RSID_STATE);
@@ -127,8 +128,8 @@ class GalaxyRS extends RenderScriptScene {
     private void createParticlesMesh() {
         final Builder elementBuilder = new Builder(mRS);
         elementBuilder.addUNorm8RGBA("");
-        elementBuilder.addFloatXY("");
-        elementBuilder.addFloatPointSize("PS");
+        elementBuilder.addFloatXYZ("");
+        elementBuilder.addFloatPointSize("");
         final Element vertexElement = elementBuilder.create();
 
         final SimpleMesh.Builder meshBuilder = new SimpleMesh.Builder(mRS);
@@ -192,41 +193,48 @@ class GalaxyRS extends RenderScriptScene {
         mParticlesType = Type.createFromClass(mRS, GalaxyParticle.class, PARTICLES_COUNT, "Particle");
         mParticles = Allocation.createTyped(mRS, mParticlesType);
 
+        final float scale = GALAXY_RADIUS / (mWidth * 0.5f);
+
         for (int i = 0; i < PARTICLES_COUNT; i ++) {
-            createParticle(gp, i);
+            createParticle(gp, i, scale);
         }
     }
 
     @SuppressWarnings({"PointlessArithmeticExpression"})
-    private void createParticle(GalaxyParticle gp, int index) {
+    private void createParticle(GalaxyParticle gp, int index, float scale) {
         float d = abs(randomGauss()) * GALAXY_RADIUS / 2.0f + random(-4.0f, 4.0f);
-        //float z = randomGauss() * 0.5f * 0.8f * ((GALAXY_RADIUS - d) / (float) GALAXY_RADIUS);
-        //z += 1.0f;
-        float p = d * ELLIPSE_TWIST;
+        float z = randomGauss() * 0.5f * 0.8f * ((GALAXY_RADIUS - d) / (float) GALAXY_RADIUS);
+        float p = -d * ELLIPSE_TWIST;
 
-        gp.angle = random(0.0f, (float) (Math.PI * 2.0));
-        gp.distance = d;
-        gp.speed = random(0.0015f, 0.0025f) * (0.5f + (0.5f * (float) GALAXY_RADIUS / d)) * 0.7f;
-        gp.s = (float) Math.cos(p);
-        gp.t = (float) Math.sin(p);
+        final float nd = d / (float) GALAXY_RADIUS;
 
-        int red, green, blue;
+        int red, green, blue, alpha;
         if (d < GALAXY_RADIUS / 3.0f) {
-            red = (int) (220 + (d / (float) GALAXY_RADIUS) * 35);
+            red = (int) (220 + nd * 35);
             green = 220;
             blue = 220;
         } else {
             red = 180;
             green = 180;
-            blue = (int) constrain(140 + (d / (float) GALAXY_RADIUS) * 115, 140, 255);
+            blue = (int) constrain(140 + nd * 115, 140, 255);
         }
+        alpha = (int) (40 + nd * 215);
+        int color = red | green << 8 | blue << 16 | alpha << 24;
 
-        final int color = red | green << 8 | blue << 16 | 0xff000000;
+        // Map to the projection coordinates (viewport.x = -1.0 -> 1.0)
+        d = map(-4.0f, GALAXY_RADIUS + 4.0f, 0.0f, scale, d);
 
-        final float[] floatData = mFloatData3;
+        gp.angle = random(0.0f, (float) (Math.PI * 2.0));
+        gp.distance = d;
+        gp.speed = random(0.0015f, 0.0025f) * (0.5f + (scale / d)) * 0.8f;
+        gp.s = (float) Math.cos(p);
+        gp.t = (float) Math.sin(p);
 
+        final float[] floatData = mFloatData;
         floatData[0] = Float.intBitsToFloat(color);
-        floatData[3] = random(0.5f, 1.5f);
+        floatData[3] = z / 5.0f;
+        floatData[4] = random(1.2f, 2.1f) * 6f;
+
         mParticlesBuffer.subData1D(index, 1, floatData);
         mParticles.subData(index, gp);
     }
@@ -243,6 +251,7 @@ class GalaxyRS extends RenderScriptScene {
         } while (w >= 1.0f);
 
         w = (float) Math.sqrt(-2.0 * log(w) / w);
+
         return x1 * w;
     }
 
@@ -251,7 +260,8 @@ class GalaxyRS extends RenderScriptScene {
 
         final Allocation[] textures = mTextures;
         textures[RSID_TEXTURE_SPACE] = loadTexture(R.drawable.space, "TSpace");
-        textures[RSID_TEXTURE_LIGHT1] = loadTextureARGB(R.drawable.light1, "TLight1");
+        textures[RSID_TEXTURE_LIGHT1] = loadTexture(R.drawable.light1, "TLight1");
+        textures[RSID_TEXTURE_FLARES] = loadTexture(R.drawable.flares, "TFlares");
 
         final int count = textures.length;
         for (int i = 0; i < count; i++) {
@@ -266,20 +276,13 @@ class GalaxyRS extends RenderScriptScene {
         return allocation;
     }
 
-    private Allocation loadTextureARGB(int id, String name) {
-        Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
-        final Allocation allocation = Allocation.createFromBitmap(mRS, b, RGBA_8888, false);
-        allocation.setName(name);
-        return allocation;
-    }
-
     private void createProgramFragment() {
-        Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
-        sampleBuilder.setMin(NEAREST);
-        sampleBuilder.setMag(NEAREST);
-        sampleBuilder.setWrapS(WRAP);
-        sampleBuilder.setWrapT(WRAP);
-        mSampler = sampleBuilder.create();
+        Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
+        samplerBuilder.setMin(NEAREST);
+        samplerBuilder.setMag(NEAREST);
+        samplerBuilder.setWrapS(WRAP);
+        samplerBuilder.setWrapT(WRAP);
+        mSampler = samplerBuilder.create();
 
         ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null);
         builder.setTexEnable(true, 0);
@@ -288,9 +291,20 @@ class GalaxyRS extends RenderScriptScene {
         mPfBackground.setName("PFBackground");
         mPfBackground.bindSampler(mSampler, 0);
 
+        samplerBuilder = new Sampler.Builder(mRS);
+        samplerBuilder.setMin(LINEAR);
+        samplerBuilder.setMag(LINEAR);
+        samplerBuilder.setWrapS(WRAP);
+        samplerBuilder.setWrapT(WRAP);
+        mStarSampler = samplerBuilder.create();
+
         builder = new ProgramFragment.Builder(mRS, null, null);
-        mPfBasic = builder.create();
-        mPfBasic.setName("PFBasic");
+        builder.setPointSpriteTexCoordinateReplacement(true);
+        builder.setTexEnable(true, 0);
+        builder.setTexEnvMode(MODULATE, 0);
+        mPfStars = builder.create();
+        mPfStars.setName("PFStars");
+        mPfBackground.bindSampler(mStarSampler, 0);        
     }
 
     private void createProgramFragmentStore() {
@@ -298,12 +312,13 @@ class GalaxyRS extends RenderScriptScene {
         builder.setDepthFunc(ALWAYS);
         builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
         builder.setDitherEnable(false);
+        builder.setDepthMask(false);
         mPfsBackground = builder.create();
         mPfsBackground.setName("PFSBackground");
 
         builder = new ProgramStore.Builder(mRS, null, null);
         builder.setDepthFunc(ALWAYS);
-        builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
         builder.setDitherEnable(false);
         mPfsLights = builder.create();
         mPfsLights.setName("PFSLights");
@@ -317,5 +332,13 @@ class GalaxyRS extends RenderScriptScene {
         mPvBackground = builder.create();
         mPvBackground.bindAllocation(mPvOrthoAlloc);
         mPvBackground.setName("PVBackground");
+        
+        mPvProjectionAlloc = new ProgramVertex.MatrixAllocation(mRS);
+        mPvProjectionAlloc.setupProjectionNormalized(mWidth, mHeight);
+
+        builder = new ProgramVertex.Builder(mRS, null, null);
+        mPvStars = builder.create();
+        mPvStars.bindAllocation(mPvProjectionAlloc);
+        mPvStars.setName("PVStars");
     }
-}
\ No newline at end of file
+}