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