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    private Resources mRes;
28    // rendering context
29    private RenderScriptGL mRS;
30    private ScriptC_galaxy mScript;
31
32    // shader constants
33    private ScriptField_VpConsts mPvConsts;
34    private ScriptField_Particle spaceClouds;
35    private ScriptField_Particle bgStars;
36    private Mesh spaceCloudsMesh;
37    private Mesh bgStarsMesh;
38
39    int mHeight;
40    int mWidth;
41    boolean inited = false;
42
43    private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
44
45    private Allocation cloudAllocation;
46    private Allocation fgStarAllocation;
47    private Allocation bgAllocation;
48
49    public void init(RenderScriptGL rs, Resources res, int width, int height) {
50        if (!inited) {
51            mRS = rs;
52            mRes = res;
53
54            mWidth = width;
55            mHeight = height;
56
57            mOptionsARGB.inScaled = false;
58            mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
59
60            spaceClouds = new ScriptField_Particle(mRS, SPACE_CLOUDSTAR_COUNT);
61            Mesh.AllocationBuilder smb = new Mesh.AllocationBuilder(mRS);
62            smb.addVertexAllocation(spaceClouds.getAllocation());
63            smb.addIndexSetType(Mesh.Primitive.POINT);
64            spaceCloudsMesh = smb.create();
65
66            bgStars = new ScriptField_Particle(mRS, BG_STAR_COUNT);
67            Mesh.AllocationBuilder smb2 = new Mesh.AllocationBuilder(mRS);
68            smb2.addVertexAllocation(bgStars.getAllocation());
69            smb2.addIndexSetType(Mesh.Primitive.POINT);
70            bgStarsMesh = smb2.create();
71
72            mScript = new ScriptC_galaxy(mRS, mRes, R.raw.galaxy);
73            mScript.set_spaceCloudsMesh(spaceCloudsMesh);
74            mScript.bind_spaceClouds(spaceClouds);
75            mScript.set_bgStarsMesh(bgStarsMesh);
76            mScript.bind_bgStars(bgStars);
77
78            mPvConsts = new ScriptField_VpConsts(mRS, 1);
79
80            createProgramVertex();
81            createProgramRaster();
82            createProgramFragmentStore();
83            createProgramFragment();
84
85            loadTextures();
86
87            mRS.bindRootScript(mScript);
88
89            mScript.invoke_positionParticles();
90
91            inited = true;
92        }
93
94    }
95
96    private Allocation loadTexture(int id) {
97        final Allocation allocation = Allocation.createFromBitmapResource(mRS, mRes, id);
98        return allocation;
99    }
100
101    private Allocation loadTextureARGB(int id) {
102        Bitmap b = BitmapFactory.decodeResource(mRes, id, mOptionsARGB);
103        return Allocation.createFromBitmap(mRS, b,
104                Allocation.MipmapControl.MIPMAP_ON_SYNC_TO_TEXTURE,
105                Allocation.USAGE_GRAPHICS_TEXTURE);
106    }
107
108    private void loadTextures() {
109        fgStarAllocation = loadTexture(R.drawable.fgstar);
110        cloudAllocation = loadTexture(R.drawable.cloud);
111        bgAllocation = loadTexture(R.drawable.bg);
112        mScript.set_textureSpaceCloud(cloudAllocation);
113        mScript.set_textureFGStar(fgStarAllocation);
114        mScript.set_textureBg(bgAllocation);
115    }
116
117    private Matrix4f getProjectionNormalized(int w, int h) {
118        // range -1,1 in the narrow axis at z = 0.
119        Matrix4f m1 = new Matrix4f();
120        Matrix4f m2 = new Matrix4f();
121
122        if (w > h) {
123            float aspect = ((float) w) / h;
124            m1.loadFrustum(-aspect, aspect, -1, 1, 1, 100);
125        } else {
126            float aspect = ((float) h) / w;
127            m1.loadFrustum(-1, 1, -aspect, aspect, 1, 100);
128        }
129
130        m2.loadRotate(180, 0, 1, 0);
131        m1.loadMultiply(m1, m2);
132
133        m2.loadScale(-1, 1, 1);
134        m1.loadMultiply(m1, m2);
135
136        m2.loadTranslate(0, 0, 1);
137        m1.loadMultiply(m1, m2);
138        return m1;
139    }
140
141    private void updateProjectionMatrices() {
142        Matrix4f proj = new Matrix4f();
143        proj.loadOrthoWindow(mWidth, mHeight);
144
145        Log.d("------------------- UPDATE PROJECTION MATRICES", mWidth + "  " + mHeight);
146
147        Matrix4f projNorm = getProjectionNormalized(mWidth, mHeight);
148        ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
149        // i.Proj = projNorm;
150        i.MVP = projNorm;
151        mPvConsts.set(i, 0, true);
152
153    }
154
155    private void createProgramVertex() {
156
157        // /////////////////// fixed function bg
158        ProgramVertexFixedFunction.Constants mPvOrthoAlloc =
159            new ProgramVertexFixedFunction.Constants(mRS);
160        Matrix4f proj = new Matrix4f();
161        proj.loadOrthoWindow(mWidth, mHeight);
162        mPvOrthoAlloc.setProjection(proj);
163
164        ProgramVertexFixedFunction.Builder pvb = new ProgramVertexFixedFunction.Builder(mRS);
165        ProgramVertex pv = pvb.create();
166        ((ProgramVertexFixedFunction) pv).bindConstants(mPvOrthoAlloc);
167        mScript.set_vertBg(pv);
168
169        // ///////////////////////////////////////////////////////////////////////
170        // //////////////////////////////////////////////////////////////////
171
172        updateProjectionMatrices();
173
174        // cloud
175        ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS);
176        builder.setShader(mRes, R.raw.spacecloud_vs);
177        builder.addConstant(mPvConsts.getType());
178        builder.addInput(spaceCloudsMesh.getVertexAllocation(0).getType().getElement());
179        ProgramVertex pvs = builder.create();
180        pvs.bindConstants(mPvConsts.getAllocation(), 0);
181        mRS.bindProgramVertex(pvs);
182
183        mScript.set_vertSpaceClouds(pvs);
184
185        // bg stars
186        builder = new ProgramVertex.Builder(mRS);
187        builder.setShader(mRes, R.raw.bgstar_vs);
188        builder.addConstant(mPvConsts.getType());
189        builder.addInput(bgStarsMesh.getVertexAllocation(0).getType().getElement());
190        pvs = builder.create();
191        pvs.bindConstants(mPvConsts.getAllocation(), 0);
192        mRS.bindProgramVertex(pvs);
193        mScript.set_vertBgStars(pvs);
194    }
195
196    private void createProgramFragment() {
197        // fixed function bg
198
199        Sampler.Builder samplerBuilder = new Sampler.Builder(mRS);
200        samplerBuilder.setMinification(NEAREST);
201        samplerBuilder.setMagnification(NEAREST);
202        samplerBuilder.setWrapS(WRAP);
203        samplerBuilder.setWrapT(WRAP);
204        Sampler sn = samplerBuilder.create();
205        ProgramFragmentFixedFunction.Builder builderff =
206            new ProgramFragmentFixedFunction.Builder(mRS);
207        builderff = new ProgramFragmentFixedFunction.Builder(mRS);
208        builderff.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
209                ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
210        ProgramFragment pfff = builderff.create();
211        mScript.set_fragBg(pfff);
212        pfff.bindSampler(sn, 0);
213
214        ////////////////////////////////////////////////////////////////////
215
216        // cloud fragment
217        ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
218
219        builder.setShader(mRes, R.raw.spacecloud_fs);
220        // multiple textures
221        builder.addTexture(Program.TextureType.TEXTURE_2D);
222        builder.addTexture(Program.TextureType.TEXTURE_2D);
223
224        ProgramFragment pf = builder.create();
225        pf.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0);
226        mScript.set_fragSpaceClouds(pf);
227
228        // bg star fragment
229        builder = new ProgramFragment.Builder(mRS);
230        builder.setShader(mRes, R.raw.bgstar_fs);
231        pf = builder.create();
232        mScript.set_fragBgStars(pf);
233
234    }
235
236    private void createProgramRaster() {
237        // Program raster is primarily used to specify whether point sprites are enabled and
238        // to control the culling mode. By default, back faces are culled.
239        ProgramRaster.Builder builder = new ProgramRaster.Builder(mRS);
240        builder.setPointSpriteEnabled(true);
241        ProgramRaster pr = builder.create();
242        mRS.bindProgramRaster(pr);
243    }
244
245    private void createProgramFragmentStore() {
246        // ProgramStore contains a set of parameters that control how the graphics hardware handles
247        // writes to the framebuffer.
248        //
249        // It could be used to:
250        //     enable/disable depth testing
251        //     specify wheather depth writes are performed
252        //     setup various blending modes for use in effects like transparency
253        //     define write masks for color components written into the framebuffer
254
255        ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
256        // builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA,
257        // BlendDstFunc.ONE_MINUS_SRC_ALPHA );
258        builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
259        // why alpha no work with additive blending?
260        // builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE);
261        mRS.bindProgramStore(builder.create());
262
263    }
264
265    public void start() {
266        mRS.bindRootScript(mScript);
267    }
268
269    public void stop() {
270        mRS.bindRootScript(null);
271    }
272
273    public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
274        mScript.set_xOffset(xOffset);
275    }
276
277}
278