1package com.android.galaxy4;
2
3import android.content.res.Resources;
4import android.graphics.Bitmap;
5import android.graphics.BitmapFactory;
6import android.renderscript.Allocation;
7import android.renderscript.Matrix4f;
8import android.renderscript.Mesh;
9import android.renderscript.ProgramFragment;
10import android.renderscript.ProgramFragmentFixedFunction;
11import android.renderscript.ProgramRaster;
12import android.renderscript.ProgramStore;
13import android.renderscript.Sampler;
14import android.renderscript.ProgramStore.BlendDstFunc;
15import android.renderscript.ProgramStore.BlendSrcFunc;
16import android.renderscript.ProgramVertex;
17import android.renderscript.ProgramVertexFixedFunction;
18import android.renderscript.RenderScriptGL;
19import android.renderscript.ProgramVertexFixedFunction.Builder;
20import android.util.Log;
21import android.renderscript.Program;
22import static android.renderscript.Sampler.Value.*;
23
24public class GalaxyRS {
25    public static final int BG_STAR_COUNT = 11000;
26    public static final int SPACE_CLOUDSTAR_COUNT = 25;
27    public static final int STATIC_STAR_COUNT = 50;
28    private Resources mRes;
29
30    private RenderScriptGL mRS;
31    private ScriptC_galaxy mScript;
32
33    private ScriptField_VpConsts mPvConsts;
34    private ScriptField_Particle mSpaceClouds;
35    private ScriptField_Particle mBgStars;
36    private ScriptField_Particle mStaticStars;
37    private Mesh mSpaceCloudsMesh;
38    private Mesh mBgStarsMesh;
39    private Mesh mStaticStarsMesh;
40
41    private int mHeight;
42    private int mWidth;
43    private boolean mInited = false;
44    private int mDensityDPI;
45
46    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
47
48    private Allocation mCloudAllocation;
49    private Allocation mStaticStarAllocation;
50    private Allocation mStaticStar2Allocation;
51    private Allocation mBgAllocation;
52
53    public void init(int dpi, RenderScriptGL rs, Resources res, int width, int height) {
54        if (!mInited) {
55            mDensityDPI = dpi;
56
57            mRS = rs;
58            mRes = res;
59
60            mWidth = width;
61            mHeight = height;
62
63            mOptionsARGB.inScaled = false;
64            mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
65
66            mSpaceClouds = new ScriptField_Particle(mRS, SPACE_CLOUDSTAR_COUNT);
67            Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
68            smb.addVertexAllocation(mSpaceClouds.getAllocation());
69            smb.addIndexSetType(Mesh.Primitive.POINT);
70            mSpaceCloudsMesh = smb.create();
71
72            mBgStars = new ScriptField_Particle(mRS, BG_STAR_COUNT);
73            Mesh.AllocationBuilder smb2 = new Mesh.AllocationBuilder(mRS);
74            smb2.addVertexAllocation(mBgStars.getAllocation());
75            smb2.addIndexSetType(Mesh.Primitive.POINT);
76            mBgStarsMesh = smb2.create();
77
78            mStaticStars = new ScriptField_Particle(mRS, STATIC_STAR_COUNT);
79            Mesh.AllocationBuilder smb3 = new Mesh.AllocationBuilder(mRS);
80            smb3.addVertexAllocation(mStaticStars.getAllocation());
81            smb3.addIndexSetType(Mesh.Primitive.POINT);
82            mStaticStarsMesh = smb3.create();
83
84            mScript = new ScriptC_galaxy(mRS, mRes, R.raw.galaxy);
85            mScript.set_spaceCloudsMesh(mSpaceCloudsMesh);
86            mScript.bind_spaceClouds(mSpaceClouds);
87            mScript.set_bgStarsMesh(mBgStarsMesh);
88            mScript.bind_bgStars(mBgStars);
89            mScript.set_staticStarsMesh(mStaticStarsMesh);
90            mScript.bind_staticStars(mStaticStars);
91
92            mPvConsts = new ScriptField_VpConsts(mRS, 1);
93
94            createProgramVertex();
95            createProgramRaster();
96            createProgramFragmentStore();
97            createProgramFragment();
98
99            loadTextures();
100
101            mScript.set_densityDPI(mDensityDPI);
102            mRS.bindRootScript(mScript);
103            mScript.invoke_positionParticles();
104            mInited = true;
105        }
106    }
107
108    private Allocation loadTexture(int id) {
109        final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes, id);
110        return allocation;
111    }
112
113    private void loadTextures() {
114        mStaticStarAllocation = loadTexture(R.drawable.staticstar);
115        mStaticStar2Allocation = loadTexture(R.drawable.staticstar2);
116        mCloudAllocation = loadTexture(R.drawable.cloud);
117        mBgAllocation = loadTexture(R.drawable.bg);
118        mScript.set_textureSpaceCloud(mCloudAllocation);
119        mScript.set_textureStaticStar(mStaticStarAllocation);
120        mScript.set_textureStaticStar2(mStaticStar2Allocation);
121        mScript.set_textureBg(mBgAllocation);
122    }
123
124    private Matrix4f getProjectionNormalized(int w, int h) {
125        Matrix4f m1 = new Matrix4f();
126        Matrix4f m2 = new Matrix4f();
127
128        if (w > h) {
129            float aspect = ((float) w) / h;
130            m1.loadFrustum(-aspect, aspect, -1, 1, 1, 100);
131        } else {
132            float aspect = ((float) h) / w;
133            m1.loadFrustum(-1, 1, -aspect, aspect, 1, 100);
134        }
135
136        m2.loadRotate(180, 0, 1, 0);
137        m1.loadMultiply(m1, m2);
138        m2.loadScale(-1, 1, 1);
139        m1.loadMultiply(m1, m2);
140        m2.loadTranslate(0, 0, 1);
141        m1.loadMultiply(m1, m2);
142        return m1;
143    }
144
145    private void updateProjectionMatrices(int w, int h) {
146        mWidth = w;
147        mHeight = h;
148        Matrix4f proj = new Matrix4f();
149        proj.loadOrthoWindow(mWidth, mHeight);
150        Matrix4f projNorm = getProjectionNormalized(mWidth, mHeight);
151        ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
152        i.MVP = projNorm;
153        i.scaleSize = mDensityDPI / 240.0f;
154        mPvConsts.set(i, 0, true);
155        mScript.invoke_positionParticles();
156    }
157
158    public void createProgramVertex() {
159        ProgramVertexFixedFunction.Constants mPvOrthoAlloc =
160            new ProgramVertexFixedFunction.Constants(mRS);
161        Matrix4f proj = new Matrix4f();
162        proj.loadOrthoWindow(mWidth, mHeight);
163        mPvOrthoAlloc.setProjection(proj);
164
165        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
166        ProgramVertex pv = pvb.create();
167        ((ProgramVertexFixedFunction) pv).bindConstants(mPvOrthoAlloc);
168        mScript.set_vertBg(pv);
169        updateProjectionMatrices(mWidth, mHeight);
170
171        // cloud
172        ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS);
173        builder.setShader(mRes, R.raw.spacecloud_vs);
174        builder.addConstant(mPvConsts.getType());
175        builder.addInput(mSpaceCloudsMesh.getVertexAllocation(0).getType().getElement());
176        ProgramVertex pvs = builder.create();
177        pvs.bindConstants(mPvConsts.getAllocation(), 0);
178        mRS.bindProgramVertex(pvs);
179
180        mScript.set_vertSpaceClouds(pvs);
181
182        // bg stars
183        builder = new ProgramVertex.Builder(mRS);
184        builder.setShader(mRes, R.raw.bgstar_vs);
185        builder.addConstant(mPvConsts.getType());
186        builder.addInput(mBgStarsMesh.getVertexAllocation(0).getType().getElement());
187        pvs = builder.create();
188        pvs.bindConstants(mPvConsts.getAllocation(), 0);
189        mRS.bindProgramVertex(pvs);
190        mScript.set_vertBgStars(pvs);
191
192        // static stars
193        builder = new ProgramVertex.Builder(mRS);
194        builder.setShader(mRes, R.raw.staticstar_vs);
195        builder.addConstant(mPvConsts.getType());
196        builder.addInput(mBgStarsMesh.getVertexAllocation(0).getType().getElement());
197        pvs = builder.create();
198        pvs.bindConstants(mPvConsts.getAllocation(), 0);
199        mRS.bindProgramVertex(pvs);
200        mScript.set_vertStaticStars(pvs);
201    }
202
203    private void createProgramFragment() {
204        // bg
205        Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
206        samplerBuilder.setMinification(LINEAR);
207        samplerBuilder.setMagnification(LINEAR);
208        samplerBuilder.setWrapS(WRAP);
209        samplerBuilder.setWrapT(WRAP);
210        Sampler sn = samplerBuilder.create();
211        ProgramFragmentFixedFunction.Builder builderff =
212                new ProgramFragmentFixedFunction.Builder(mRS);
213        builderff = new ProgramFragmentFixedFunction.Builder(mRS);
214        builderff.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
215                ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
216        ProgramFragment pfff = builderff.create();
217        mScript.set_fragBg(pfff);
218        pfff.bindSampler(sn, 0);
219
220        // cloud
221        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
222
223        builder.setShader(mRes, R.raw.spacecloud_fs);
224        builder.addTexture(Program.TextureType.TEXTURE_2D);
225
226        ProgramFragment pf = builder.create();
227        pf.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
228        mScript.set_fragSpaceClouds(pf);
229
230        // bg stars
231        builder = new ProgramFragment.Builder(mRS);
232        builder.setShader(mRes, R.raw.bgstar_fs);
233        pf = builder.create();
234        mScript.set_fragBgStars(pf);
235
236        // static stars
237        builder = new ProgramFragment.Builder(mRS);
238        builder.setShader(mRes, R.raw.staticstar_fs);
239        builder.addTexture(Program.TextureType.TEXTURE_2D);
240        builder.addTexture(Program.TextureType.TEXTURE_2D);
241        pf = builder.create();
242        mScript.set_fragStaticStars(pf);
243    }
244
245    private void createProgramRaster() {
246        ProgramRaster.Builder builder = new ProgramRaster.Builder(mRS);
247        builder.setPointSpriteEnabled(true);
248        ProgramRaster pr = builder.create();
249        mRS.bindProgramRaster(pr);
250    }
251
252    private void createProgramFragmentStore() {
253        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
254        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
255        mRS.bindProgramStore(builder.create());
256    }
257
258    public void start() {
259        mRS.bindRootScript(mScript);
260    }
261
262    public void stop() {
263        mRS.bindRootScript(null);
264    }
265
266    public void resize(int width, int height) {
267        mWidth = width;
268        mHeight = height;
269        createProgramVertex();
270    }
271}