Adding Galaxy4 wallpaper.

Change-Id: I259cd675f1e28d38be042c35ca1827da2707bac0
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..fa753f9
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,29 @@
+#
+# Copyright (C) 2010 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_SRC_FILES := $(call all-subdir-java-files) $(call all-renderscript-files-under, src)
+
+LOCAL_PACKAGE_NAME := Galaxy4
+LOCAL_CERTIFICATE := shared
+
+LOCAL_PROGUARD_FLAG_FILES := proguard.cfg
+
+include $(BUILD_PACKAGE)
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
new file mode 100644
index 0000000..464bf28
--- /dev/null
+++ b/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+      package="com.android.galaxy4"
+      android:versionCode="1"
+      android:versionName="1.0">
+    <uses-sdk android:minSdkVersion="13" />
+    
+    <uses-feature android:name="android.software.live_wallpaper" />
+
+    <application android:icon="@drawable/icon" android:label="@string/wallpaper_label">
+        <activity android:name=".Galaxy4"
+                  android:theme="@android:style/Theme.NoTitleBar"
+                  android:label="@string/wallpaper_label"
+                  android:launchMode="singleInstance">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+                <category android:name="android.intent.category.LAUNCHER" />
+            </intent-filter>
+        </activity>
+        <service
+                android:name=".Galaxy4Wallpaper"
+                android:label="@string/wallpaper_label"
+                android:permission="android.permission.BIND_WALLPAPER">
+            <intent-filter>
+                <action android:name="android.service.wallpaper.WallpaperService" />
+            </intent-filter>
+            <meta-data android:name="android.service.wallpaper" android:resource="@xml/wallpaper" />
+        </service>
+    </application>
+</manifest>
\ No newline at end of file
diff --git a/default.properties b/default.properties
new file mode 100644
index 0000000..ac9e1a0
--- /dev/null
+++ b/default.properties
@@ -0,0 +1,11 @@
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system use,
+# "build.properties", and override values to adapt the script to your
+# project structure.
+
+# Project target.
+target=android-13
diff --git a/proguard.cfg b/proguard.cfg
new file mode 100644
index 0000000..b1cdf17
--- /dev/null
+++ b/proguard.cfg
@@ -0,0 +1,40 @@
+-optimizationpasses 5
+-dontusemixedcaseclassnames
+-dontskipnonpubliclibraryclasses
+-dontpreverify
+-verbose
+-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
+
+-keep public class * extends android.app.Activity
+-keep public class * extends android.app.Application
+-keep public class * extends android.app.Service
+-keep public class * extends android.content.BroadcastReceiver
+-keep public class * extends android.content.ContentProvider
+-keep public class * extends android.app.backup.BackupAgentHelper
+-keep public class * extends android.preference.Preference
+-keep public class com.android.vending.licensing.ILicensingService
+
+-keepclasseswithmembernames class * {
+    native <methods>;
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet);
+}
+
+-keepclasseswithmembers class * {
+    public <init>(android.content.Context, android.util.AttributeSet, int);
+}
+
+-keepclassmembers class * extends android.app.Activity {
+   public void *(android.view.View);
+}
+
+-keepclassmembers enum * {
+    public static **[] values();
+    public static ** valueOf(java.lang.String);
+}
+
+-keep class * implements android.os.Parcelable {
+  public static final android.os.Parcelable$Creator *;
+}
diff --git a/res/drawable-nodpi/bg.png b/res/drawable-nodpi/bg.png
new file mode 100644
index 0000000..0102d9f
--- /dev/null
+++ b/res/drawable-nodpi/bg.png
Binary files differ
diff --git a/res/drawable-nodpi/bgstar.png b/res/drawable-nodpi/bgstar.png
new file mode 100644
index 0000000..5ab0136
--- /dev/null
+++ b/res/drawable-nodpi/bgstar.png
Binary files differ
diff --git a/res/drawable-nodpi/cloud.png b/res/drawable-nodpi/cloud.png
new file mode 100644
index 0000000..17b9fd4
--- /dev/null
+++ b/res/drawable-nodpi/cloud.png
Binary files differ
diff --git a/res/drawable-nodpi/fgstar.png b/res/drawable-nodpi/fgstar.png
new file mode 100644
index 0000000..100250f
--- /dev/null
+++ b/res/drawable-nodpi/fgstar.png
Binary files differ
diff --git a/res/drawable-nodpi/icon.png b/res/drawable-nodpi/icon.png
new file mode 100644
index 0000000..8074c4c
--- /dev/null
+++ b/res/drawable-nodpi/icon.png
Binary files differ
diff --git a/res/drawable-nodpi/wallpaper_thumb.png b/res/drawable-nodpi/wallpaper_thumb.png
new file mode 100644
index 0000000..41a355c
--- /dev/null
+++ b/res/drawable-nodpi/wallpaper_thumb.png
Binary files differ
diff --git a/res/layout/main.xml b/res/layout/main.xml
new file mode 100644
index 0000000..8eab2f8
--- /dev/null
+++ b/res/layout/main.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    >
+<TextView
+    android:layout_width="fill_parent"
+    android:layout_height="wrap_content"
+    android:text="@string/wallpaper_label"
+    />
+</LinearLayout>
diff --git a/res/raw/bgstar_fs.glsl b/res/raw/bgstar_fs.glsl
new file mode 100644
index 0000000..54edf85
--- /dev/null
+++ b/res/raw/bgstar_fs.glsl
@@ -0,0 +1,5 @@
+varying vec4 varColor;
+
+void main()  {
+    gl_FragColor = varColor;
+}
\ No newline at end of file
diff --git a/res/raw/bgstar_vs.glsl b/res/raw/bgstar_vs.glsl
new file mode 100644
index 0000000..ac35d9f
--- /dev/null
+++ b/res/raw/bgstar_vs.glsl
@@ -0,0 +1,24 @@
+varying vec4 varColor;
+
+void main() {
+    float dist = ATTRIB_position.y;
+    float angle = ATTRIB_position.x;
+
+    float x = dist * sin(angle);
+    float y = dist * cos(angle) * 0.8;
+    float p = dist * 7.5;
+    float s = cos(p);
+    float t = sin(p);
+    vec4 pos;
+    pos.x = t*x + s*y;
+    pos.y = s*x - t*y;
+    pos.z = ATTRIB_position.z;
+    pos.w = 1.0;
+    
+    pos.y = pos.y * 0.5;
+    gl_Position = UNI_MVP * pos;
+    varColor = vec4(1.0, 1.0, 1.0, 0.5);
+    float pointSize = 1.0;
+
+    gl_PointSize = pointSize;
+}
\ No newline at end of file
diff --git a/res/raw/spacecloud_fs.glsl b/res/raw/spacecloud_fs.glsl
new file mode 100644
index 0000000..75adcd2
--- /dev/null
+++ b/res/raw/spacecloud_fs.glsl
@@ -0,0 +1,12 @@
+varying vec4 varColor;
+
+void main()  {
+    lowp vec4 texColor;
+    texColor = texture2D(UNI_Tex0, gl_PointCoord);
+    
+    // texColor = texture2D(UNI_Tex1, gl_PointCoord);
+    
+    gl_FragColor.rgb = texColor.rgb;
+    gl_FragColor.a = 0.1;
+    // gl_FragColor = varColor;
+}
\ No newline at end of file
diff --git a/res/raw/spacecloud_vs.glsl b/res/raw/spacecloud_vs.glsl
new file mode 100644
index 0000000..0056328
--- /dev/null
+++ b/res/raw/spacecloud_vs.glsl
@@ -0,0 +1,26 @@
+varying vec4 varColor;
+varying float pointSize;
+
+void main() {
+    float dist = ATTRIB_position.y / 4.0;
+    float angle = ATTRIB_position.x;
+    
+    float x = dist * sin(angle) * 0.8;
+    float y = dist * cos(angle) * 0.8;
+    float p = dist * 7.5;
+    float s = cos(p);
+    float t = sin(p);
+    vec4 pos;
+    pos.x = t*x + s*y;
+    pos.y = s*x - t*y;
+    pos.z = ATTRIB_position.z;
+    pos.w = 1.0;
+    pos.y = pos.y * 0.5;
+    gl_Position = UNI_MVP * pos;
+    varColor = vec4(1.0, 1.0, 1.0, 1.0);
+    pointSize = 170.0-(pos.y*pos.y*1.2*1.2 + pos.x*pos.x)*400.0;
+    if(pointSize<=30.0){
+        pointSize = 30.0;
+    }
+    gl_PointSize = pointSize;// - snoise(pos.xy)*5.0;
+}
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
new file mode 100644
index 0000000..2dd521b
--- /dev/null
+++ b/res/values/strings.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2010 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <string name="wallpaper_label">Black Hole</string>
+    <string name="wallpaper_author">Google</string>
+    <string name="wallpaper_description">DESC</string>
+</resources>
diff --git a/res/xml/wallpaper.xml b/res/xml/wallpaper.xml
new file mode 100644
index 0000000..71a9574
--- /dev/null
+++ b/res/xml/wallpaper.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/**
+ * Copyright (c) 2010, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+
+<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
+    android:author="@string/wallpaper_author"
+    android:description="@string/wallpaper_description"
+    android:thumbnail="@drawable/wallpaper_thumb" />
diff --git a/src/com/android/galaxy4/Galaxy4.java b/src/com/android/galaxy4/Galaxy4.java
new file mode 100644
index 0000000..6985de3
--- /dev/null
+++ b/src/com/android/galaxy4/Galaxy4.java
@@ -0,0 +1,16 @@
+package com.android.galaxy4;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class Galaxy4 extends Activity {
+
+    private GalaxyView mView;
+
+    @Override
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mView = new GalaxyView(this);
+        setContentView(mView);
+    }
+}
\ No newline at end of file
diff --git a/src/com/android/galaxy4/Galaxy4Wallpaper.java b/src/com/android/galaxy4/Galaxy4Wallpaper.java
new file mode 100644
index 0000000..1192e1c
--- /dev/null
+++ b/src/com/android/galaxy4/Galaxy4Wallpaper.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.galaxy4;
+
+import android.graphics.PixelFormat;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.renderscript.RenderScript;
+import android.renderscript.RenderScriptGL;
+import android.service.wallpaper.WallpaperService;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+
+public class Galaxy4Wallpaper extends WallpaperService {
+
+    @Override
+    public Engine onCreateEngine() {
+        return new RenderScriptEngine();
+    }
+
+    private class RenderScriptEngine extends Engine {
+        private RenderScriptGL mRenderScript = null;
+        private GalaxyRS mWallpaperRS = null;
+
+        @Override
+        public void onCreate(SurfaceHolder surfaceHolder) {
+            super.onCreate(surfaceHolder);
+            setTouchEventsEnabled(true);
+            surfaceHolder.setSizeFromLayout();
+            surfaceHolder.setFormat(PixelFormat.RGBA_8888);
+        }
+
+        @Override
+        public void onDestroy() {
+            super.onDestroy();
+            destroyRenderer();
+        }
+
+        public void destroyRenderer() {
+            if (mWallpaperRS != null) {
+                mWallpaperRS.stop();
+                mWallpaperRS = null;
+            }
+
+            if (mRenderScript != null) {
+                mRenderScript.setSurface(null, 0, 0);
+                mRenderScript.destroy();
+                mRenderScript = null;
+            }
+        }
+
+        @Override
+        public void onSurfaceCreated(SurfaceHolder surfaceHolder) {
+            super.onSurfaceCreated(surfaceHolder);
+
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRenderScript = new RenderScriptGL(Galaxy4Wallpaper.this, sc);
+            mRenderScript.setPriority(RenderScript.Priority.LOW);
+        }
+
+        @Override
+        public void onSurfaceDestroyed(SurfaceHolder surfaceHolder) {
+            super.onSurfaceDestroyed(surfaceHolder);
+            destroyRenderer();
+        }
+
+        @Override
+        public void onSurfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
+            super.onSurfaceChanged(surfaceHolder, format, width, height);
+
+            if (mRenderScript != null) {
+                mRenderScript.setSurface(surfaceHolder, width, height);
+            }
+
+            if (mWallpaperRS == null) {
+                mWallpaperRS = new GalaxyRS();
+                mWallpaperRS.init(mRenderScript, getResources(), width, height);
+                mWallpaperRS.start();
+            }
+
+            // mWallpaperRS.resize(width, height);
+        }
+
+        @Override
+        public Bundle onCommand(String action, int x, int y, int z, Bundle extras,
+                boolean resultRequested) {
+            if (mWallpaperRS != null) {
+                // return mWallpaperRS.onCommand(action, x, y, z, extras, resultRequested);
+            }
+            return null;
+        }
+
+        @Override
+        public void onVisibilityChanged(boolean visible) {
+            super.onVisibilityChanged(visible);
+            if (mWallpaperRS != null) {
+                if (visible) {
+                    mWallpaperRS.start();
+                } else {
+                    mWallpaperRS.stop();
+                }
+            }
+        }
+
+        @Override
+        public void onOffsetsChanged(float xOffset, float yOffset, float xOffsetStep,
+                float yOffsetStep, int xPixelOffset, int yPixelOffset) {
+            // mWallpaperRS.setOffset(xOffset, yOffset, xPixelOffset, yPixelOffset);
+        }
+    }
+}
diff --git a/src/com/android/galaxy4/GalaxyRS.java b/src/com/android/galaxy4/GalaxyRS.java
new file mode 100644
index 0000000..c568296
--- /dev/null
+++ b/src/com/android/galaxy4/GalaxyRS.java
@@ -0,0 +1,277 @@
+package com.android.galaxy4;
+
+import android.content.res.Resources;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.renderscript.Allocation;
+import android.renderscript.Matrix4f;
+import android.renderscript.Mesh;
+import android.renderscript.ProgramFragment;
+import android.renderscript.ProgramFragmentFixedFunction;
+import android.renderscript.ProgramRaster;
+import android.renderscript.ProgramStore;
+import android.renderscript.Sampler;
+import android.renderscript.ProgramStore.BlendDstFunc;
+import android.renderscript.ProgramStore.BlendSrcFunc;
+import android.renderscript.ProgramVertex;
+import android.renderscript.ProgramVertexFixedFunction;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.ProgramVertexFixedFunction.Builder;
+import android.util.Log;
+import android.renderscript.Program;
+import static android.renderscript.Sampler.Value.*;
+
+public class GalaxyRS {
+    public static final int BG_STAR_COUNT = 11000;
+    public static final int SPACE_CLOUDSTAR_COUNT = 25;
+    private Resources mRes;
+    // rendering context
+    private RenderScriptGL mRS;
+    private ScriptC_galaxy mScript;
+
+    // shader constants
+    private ScriptField_VpConsts mPvConsts;
+    private ScriptField_Particle spaceClouds;
+    private ScriptField_Particle bgStars;
+    private Mesh spaceCloudsMesh;
+    private Mesh bgStarsMesh;
+
+    int mHeight;
+    int mWidth;
+    boolean inited = false;
+
+    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
+
+    private Allocation cloudAllocation;
+    private Allocation fgStarAllocation;
+    private Allocation bgAllocation;
+
+    public void init(RenderScriptGL rs, Resources res, int width, int height) {
+        if (!inited) {
+            mRS = rs;
+            mRes = res;
+
+            mWidth = width;
+            mHeight = height;
+
+            mOptionsARGB.inScaled = false;
+            mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
+
+            spaceClouds = new ScriptField_Particle(mRS, SPACE_CLOUDSTAR_COUNT);
+            Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
+            smb.addVertexAllocation(spaceClouds.getAllocation());
+            smb.addIndexSetType(Mesh.Primitive.POINT);
+            spaceCloudsMesh = smb.create();
+
+            bgStars = new ScriptField_Particle(mRS, BG_STAR_COUNT);
+            Mesh.AllocationBuilder smb2 = new Mesh.AllocationBuilder(mRS);
+            smb2.addVertexAllocation(bgStars.getAllocation());
+            smb2.addIndexSetType(Mesh.Primitive.POINT);
+            bgStarsMesh = smb2.create();
+
+            mScript = new ScriptC_galaxy(mRS, mRes, R.raw.galaxy);
+            mScript.set_spaceCloudsMesh(spaceCloudsMesh);
+            mScript.bind_spaceClouds(spaceClouds);
+            mScript.set_bgStarsMesh(bgStarsMesh);
+            mScript.bind_bgStars(bgStars);
+
+            mPvConsts = new ScriptField_VpConsts(mRS, 1);
+
+            createProgramVertex();
+            createProgramRaster();
+            createProgramFragmentStore();
+            createProgramFragment();
+
+            loadTextures();
+
+            mRS.bindRootScript(mScript);
+
+            mScript.invoke_positionParticles();
+
+            inited = true;
+        }
+
+    }
+
+    private Allocation loadTexture(int id) {
+        final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes, id);
+        return allocation;
+    }
+
+    private Allocation loadTextureARGB(int id) {
+        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
+        return Allocation.createFromBitmap(mRS, b,
+                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
+                Allocation.USAGE_GRAPHICS_TEXTURE);
+    }
+
+    private void loadTextures() {
+        fgStarAllocation = loadTexture(R.drawable.fgstar);
+        cloudAllocation = loadTexture(R.drawable.cloud);
+        bgAllocation = loadTexture(R.drawable.bg);
+        mScript.set_textureSpaceCloud(cloudAllocation);
+        mScript.set_textureFGStar(fgStarAllocation);
+        mScript.set_textureBg(bgAllocation);
+    }
+
+    private Matrix4f getProjectionNormalized(int w, int h) {
+        // range -1,1 in the narrow axis at z = 0.
+        Matrix4f m1 = new Matrix4f();
+        Matrix4f m2 = new Matrix4f();
+
+        if (w > h) {
+            float aspect = ((float) w) / h;
+            m1.loadFrustum(-aspect, aspect, -1, 1, 1, 100);
+        } else {
+            float aspect = ((float) h) / w;
+            m1.loadFrustum(-1, 1, -aspect, aspect, 1, 100);
+        }
+
+        m2.loadRotate(180, 0, 1, 0);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadScale(-1, 1, 1);
+        m1.loadMultiply(m1, m2);
+
+        m2.loadTranslate(0, 0, 1);
+        m1.loadMultiply(m1, m2);
+        return m1;
+    }
+
+    private void updateProjectionMatrices() {
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(mWidth, mHeight);
+
+        Log.d("------------------- UPDATE PROJECTION MATRICES", mWidth + "  " + mHeight);
+
+        Matrix4f projNorm = getProjectionNormalized(mWidth, mHeight);
+        ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
+        // i.Proj = projNorm;
+        i.MVP = projNorm;
+        mPvConsts.set(i, 0, true);
+
+    }
+
+    private void createProgramVertex() {
+
+        // /////////////////// fixed function bg
+        ProgramVertexFixedFunction.Constants mPvOrthoAlloc = 
+            new ProgramVertexFixedFunction.Constants(mRS);
+        Matrix4f proj = new Matrix4f();
+        proj.loadOrthoWindow(mWidth, mHeight);
+        mPvOrthoAlloc.setProjection(proj);
+
+        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
+        ProgramVertex pv = pvb.create();
+        ((ProgramVertexFixedFunction) pv).bindConstants(mPvOrthoAlloc);
+        mScript.set_vertBg(pv);
+
+        // ///////////////////////////////////////////////////////////////////////
+        // //////////////////////////////////////////////////////////////////
+
+        updateProjectionMatrices();
+
+        // cloud
+        ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS);
+        builder.setShader(mRes, R.raw.spacecloud_vs);
+        builder.addConstant(mPvConsts.getType());
+        builder.addInput(spaceCloudsMesh.getVertexAllocation(0).getType().getElement());
+        ProgramVertex pvs = builder.create();
+        pvs.bindConstants(mPvConsts.getAllocation(), 0);
+        mRS.bindProgramVertex(pvs);
+
+        mScript.set_vertSpaceClouds(pvs);
+
+        // bg stars
+        builder = new ProgramVertex.Builder(mRS);
+        builder.setShader(mRes, R.raw.bgstar_vs);
+        builder.addConstant(mPvConsts.getType());
+        builder.addInput(bgStarsMesh.getVertexAllocation(0).getType().getElement());
+        pvs = builder.create();
+        pvs.bindConstants(mPvConsts.getAllocation(), 0);
+        mRS.bindProgramVertex(pvs);
+        mScript.set_vertBgStars(pvs);
+    }
+
+    private void createProgramFragment() {
+        // fixed function bg
+
+        Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
+        samplerBuilder.setMinification(NEAREST);
+        samplerBuilder.setMagnification(NEAREST);
+        samplerBuilder.setWrapS(WRAP);
+        samplerBuilder.setWrapT(WRAP);
+        Sampler sn = samplerBuilder.create();
+        ProgramFragmentFixedFunction.Builder builderff = 
+            new ProgramFragmentFixedFunction.Builder(mRS);
+        builderff = new ProgramFragmentFixedFunction.Builder(mRS);
+        builderff.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
+                ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
+        ProgramFragment pfff = builderff.create();
+        mScript.set_fragBg(pfff);
+        pfff.bindSampler(sn, 0);
+
+        ////////////////////////////////////////////////////////////////////
+
+        // cloud fragment
+        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
+
+        builder.setShader(mRes, R.raw.spacecloud_fs);
+        // multiple textures
+        builder.addTexture(Program.TextureType.TEXTURE_2D);
+        builder.addTexture(Program.TextureType.TEXTURE_2D);
+
+        ProgramFragment pf = builder.create();
+        pf.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
+        mScript.set_fragSpaceClouds(pf);
+
+        // bg star fragment
+        builder = new ProgramFragment.Builder(mRS);
+        builder.setShader(mRes, R.raw.bgstar_fs);
+        pf = builder.create();
+        mScript.set_fragBgStars(pf);
+
+    }
+
+    private void createProgramRaster() {
+        // Program raster is primarily used to specify whether point sprites are enabled and
+        // to control the culling mode. By default, back faces are culled.
+        ProgramRaster.Builder builder = new ProgramRaster.Builder(mRS);
+        builder.setPointSpriteEnabled(true);
+        ProgramRaster pr = builder.create();
+        mRS.bindProgramRaster(pr);
+    }
+
+    private void createProgramFragmentStore() {
+        // ProgramStore contains a set of parameters that control how the graphics hardware handles
+        // writes to the framebuffer.
+        // 
+        // It could be used to:
+        //     enable/disable depth testing
+        //     specify wheather depth writes are performed
+        //     setup various blending modes for use in effects like transparency
+        //     define write masks for color components written into the framebuffer
+
+        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
+        // builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA,
+        // BlendDstFunc.ONE_MINUS_SRC_ALPHA );
+        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
+        // why alpha no work with additive blending?
+        // builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
+        mRS.bindProgramStore(builder.create());
+
+    }
+
+    public void start() {
+        mRS.bindRootScript(mScript);
+    }
+
+    public void stop() {
+        mRS.bindRootScript(null);
+    }
+
+    public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
+        mScript.set_xOffset(xOffset);
+    }
+
+}
diff --git a/src/com/android/galaxy4/GalaxyView.java b/src/com/android/galaxy4/GalaxyView.java
new file mode 100644
index 0000000..ce0d33f
--- /dev/null
+++ b/src/com/android/galaxy4/GalaxyView.java
@@ -0,0 +1,45 @@
+package com.android.galaxy4;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.renderscript.RSSurfaceView;
+import android.renderscript.RenderScriptGL;
+import android.renderscript.RenderScriptGL.SurfaceConfig;
+import android.view.SurfaceHolder;
+
+public class GalaxyView extends RSSurfaceView {
+
+    private RenderScriptGL mRS;
+    private GalaxyRS mRender;
+
+    public GalaxyView(Context context) {
+        super(context);
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        // getHolder().setFormat(PixelFormat.TRANSPARENT);
+    }
+
+    public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
+        super.surfaceChanged(holder, format, w, h);
+
+        if (mRS == null) {
+            RenderScriptGL.SurfaceConfig sc = new RenderScriptGL.SurfaceConfig();
+            mRS = createRenderScriptGL(sc);
+            mRS.setSurface(holder, w, h);
+
+            mRender = new GalaxyRS();
+            mRender.init(mRS, getResources(), w, h);
+        }
+
+    }
+
+    @Override
+    protected void onDetachedFromWindow() {
+        if (mRS != null) {
+            mRS.setSurface(null, 0, 0);
+            mRS = null;
+            destroyRenderScriptGL();
+        }
+    }
+
+}
diff --git a/src/com/android/galaxy4/galaxy.rs b/src/com/android/galaxy4/galaxy.rs
new file mode 100644
index 0000000..5117024
--- /dev/null
+++ b/src/com/android/galaxy4/galaxy.rs
@@ -0,0 +1,179 @@
+#pragma version(1)
+
+#pragma rs java_package_name(com.android.galaxy4)
+#include "rs_graphics.rsh"
+#pragma stateVertex(parent);
+#pragma stateStore(parent);
+
+typedef struct __attribute__((packed, aligned(4))) Particle {
+    float3 position;
+    uchar4 color;
+} Particle_t;
+
+typedef struct VpConsts {
+    rs_matrix4x4 MVP;
+} VpConsts_t;
+VpConsts_t *vpConstants;
+
+
+// hold clouds
+Particle_t *spaceClouds;
+
+// hold bg stars
+Particle_t *bgStars;
+
+rs_mesh spaceCloudsMesh;
+rs_mesh bgStarsMesh;
+
+rs_program_vertex vertSpaceClouds;
+rs_program_vertex vertBgStars;
+rs_program_fragment fragSpaceClouds;
+rs_program_fragment fragBgStars;
+rs_program_vertex vertBg;
+rs_program_fragment fragBg;
+
+rs_allocation textureSpaceCloud;
+rs_allocation textureFGStar;
+rs_allocation textureBg;
+
+static int gGalaxyRadius = 250;
+
+float xOffset;
+
+#define PI 3.1415f
+#define TWO_PI 6.283f
+
+/**
+ * Helper function to generate the stars.
+ */
+static float randomGauss() {
+    float x1;
+    float x2;
+    float w = 2.f;
+
+    while (w >= 1.0f) {
+        x1 = rsRand(2.0f) - 1.0f;
+        x2 = rsRand(2.0f) - 1.0f;
+        w = x1 * x1 + x2 * x2;
+    }
+
+    w = sqrt(-2.0f * log(w) / w);
+    return x1 * w;
+}
+
+static float mapf(float minStart, float minStop, float maxStart, float maxStop, float value) {
+    return maxStart + (maxStart - maxStop) * ((value - minStart) / (minStop - minStart));
+}
+
+
+
+void positionParticles(){
+    rsDebug("************************&&&&&&&&&&&&&&& Called positionBGStars", rsUptimeMillis());
+
+    float width = rsgGetWidth();
+    float height = rsgGetHeight();
+    
+    float scale = gGalaxyRadius / (width * 0.5f);
+    
+    // space clouds 
+    Particle_t* particle = spaceClouds;
+    int size = rsAllocationGetDimX(rsGetAllocation(spaceClouds));
+    for(int i=0; i<size; i++){
+    
+        float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
+    
+        d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
+        
+        float id = d / gGalaxyRadius;
+        float z = randomGauss() * 0.4f * (1.0f - id);
+        
+        if (d > gGalaxyRadius * 0.15f) {
+            z *= 0.6f * (1.0f - id);
+        } else {
+            z *= 0.72f;
+        }
+        
+        particle->position.x = rsRand(TWO_PI);
+        particle->position.y = d;
+        particle->position.z = z/5.0f;
+        particle->color = rsPackColorTo8888(1.0f, 0.0f, 1.0f);
+        particle++;
+    }
+    
+    // bg stars
+    size = rsAllocationGetDimX(rsGetAllocation(bgStars));
+    particle = bgStars;
+    for(int i=0; i<size; i++){
+        float d = fabs(randomGauss()) * gGalaxyRadius * 0.5f + rsRand(64.0f);
+    
+        d = mapf(-4.0f, gGalaxyRadius + 4.0f, 0.0f, scale, d);
+        
+        float id = d / gGalaxyRadius;
+        float z = randomGauss() * 0.4f * (1.0f - id);
+        
+        if (d > gGalaxyRadius * 0.15f) {
+            z *= 0.6f * (1.0f - id);
+        } else {
+            z *= 0.72f;
+        }
+        
+        particle->position.x = rsRand(TWO_PI);
+        particle->position.y = d;
+        particle->position.z = z/5.0f;
+        particle->color = rsPackColorTo8888(1.0f, 0.0f, 1.0f);
+        particle++;
+    }
+    
+    
+}
+
+static void drawBg(int width, int height){
+    rsgBindTexture(fragBg, 0, textureBg);
+    rsgDrawRect(0.0f, 0.0f, width, height, 0.0f);
+}
+
+int root(){
+    float width = rsgGetWidth();
+    float height = rsgGetHeight();
+    
+    
+    rsgClearColor(0.0f, 0.f, 0.f, 0.5f);
+    
+    // bg
+    rsgBindProgramVertex(vertBg);
+    rsgBindProgramFragment(fragBg);
+    drawBg(width, height);
+    
+    
+    // space cloud
+    rsgBindProgramVertex(vertSpaceClouds);
+    int size = rsAllocationGetDimX(rsGetAllocation(spaceClouds));
+    Particle_t *particle = spaceClouds;
+    
+    for(int i=0; i<size; i++){
+        particle->position.x -= .065;
+        particle++;
+    }
+    rsgBindProgramFragment(fragSpaceClouds);
+    rsgBindTexture(fragSpaceClouds, 0, textureSpaceCloud);
+    rsgBindTexture(fragSpaceClouds, 1, textureFGStar);
+    rsgDrawMesh(spaceCloudsMesh);
+    
+    
+    
+    // bg stars
+    rsgBindProgramVertex(vertBgStars);
+    size = rsAllocationGetDimX(rsGetAllocation(bgStars));
+    particle = bgStars;
+    
+    for(int i=0; i<size; i++){
+        particle->position.x -= .007;
+        particle++;
+    }
+    rsgBindProgramFragment(fragBgStars);
+    rsgDrawMesh(bgStarsMesh);
+
+
+    return 40;
+}
+