1 /* 2 * Copyright (C) 2009 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.magicsmoke; 18 19 import static android.renderscript.ProgramFragment.EnvMode.REPLACE; 20 import static android.renderscript.Sampler.Value.LINEAR; 21 import static android.renderscript.Sampler.Value.WRAP; 22 23 import com.android.magicsmoke.R; 24 25 import android.content.Context; 26 import android.content.SharedPreferences; 27 import android.content.SharedPreferences.Editor; 28 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 29 import android.graphics.Bitmap; 30 import android.graphics.BitmapFactory; 31 import android.media.MediaPlayer; 32 import android.os.Handler; 33 import android.renderscript.Allocation; 34 import android.renderscript.Dimension; 35 import android.renderscript.Element; 36 import android.renderscript.Primitive; 37 import android.renderscript.ProgramFragment; 38 import android.renderscript.ProgramStore; 39 import android.renderscript.ProgramVertex; 40 import android.renderscript.Sampler; 41 import android.renderscript.ScriptC; 42 import android.renderscript.SimpleMesh; 43 import android.renderscript.Type; 44 import android.renderscript.Element.Builder; 45 import android.renderscript.ProgramStore.BlendDstFunc; 46 import android.renderscript.ProgramStore.BlendSrcFunc; 47 import android.util.Log; 48 import android.view.MotionEvent; 49 50 import java.util.TimeZone; 51 52 class MagicSmokeRS extends RenderScriptScene implements OnSharedPreferenceChangeListener { 53 54 static class WorldState { 55 public float mXOffset; 56 public float mTilt; 57 public int mPreset; 58 public int mTextureMask; 59 public int mRotate; 60 public int mTextureSwap; 61 public int mProcessTextureMode; 62 public int mBackCol; 63 public int mLowCol; 64 public int mHighCol; 65 public float mAlphaMul; 66 public int mPreMul; 67 public int mBlendFunc; 68 } 69 WorldState mWorldState = new WorldState(); 70 private Type mStateType; 71 private Allocation mState; 72 73 private ProgramStore mPfsBackgroundOne; 74 private ProgramStore mPfsBackgroundSrc; 75 private ProgramFragment mPfBackground; 76 private Sampler mSampler; 77 private Allocation[] mSourceTextures; 78 private Allocation[] mRealTextures; 79 80 private ProgramVertex mPVBackground; 81 private ProgramVertex.MatrixAllocation mPVAlloc; 82 83 private static final int RSID_STATE = 0; 84 //private static final int RSID_PROGRAMVERTEX = 3; 85 private static final int RSID_NOISESRC1 = 1; 86 private static final int RSID_NOISESRC2 = 2; 87 private static final int RSID_NOISESRC3 = 3; 88 private static final int RSID_NOISESRC4 = 4; 89 private static final int RSID_NOISESRC5 = 5; 90 private static final int RSID_NOISEDST1 = 6; 91 private static final int RSID_NOISEDST2 = 7; 92 private static final int RSID_NOISEDST3 = 8; 93 private static final int RSID_NOISEDST4 = 9; 94 private static final int RSID_NOISEDST5 = 10; 95 96 private Context mContext; 97 private SharedPreferences mSharedPref; 98 99 static class Preset { Preset(int processmode, int backcol, int locol, int hicol, float mul, int mask, boolean rot, int blend, boolean texswap, boolean premul)100 Preset(int processmode, int backcol, int locol, int hicol, float mul, int mask, 101 boolean rot, int blend, boolean texswap, boolean premul) { 102 mProcessTextureMode = processmode; 103 mBackColor = backcol; 104 mLowColor = locol; 105 mHighColor = hicol; 106 mAlphaMul = mul; 107 mTextureMask = mask; 108 mRotate = rot; 109 mBlendFunc = blend; 110 mTextureSwap = texswap; 111 mPreMul = premul; 112 } 113 public int mProcessTextureMode; 114 public int mBackColor; 115 public int mLowColor; 116 public int mHighColor; 117 public float mAlphaMul; 118 public int mTextureMask; 119 public boolean mRotate; 120 public int mBlendFunc; 121 public boolean mTextureSwap; 122 public boolean mPreMul; 123 } 124 125 public static final int DEFAULT_PRESET = 4; 126 public static final Preset [] mPreset = new Preset[] { 127 // proc back low high alph mask rot blend swap premul 128 new Preset(1, 0x000000, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, false), 129 new Preset(1, 0x0000ff, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, false), 130 new Preset(1, 0x00ff00, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, false), 131 new Preset(1, 0x00ff00, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, true), 132 new Preset(1, 0x00ff00, 0x00ff00, 0xffffff, 2.5f, 0x1f, true, 0, true, true), 133 new Preset(1, 0x800000, 0xff0000, 0xffffff, 2.5f, 0x1f, true, 0, true, false), 134 new Preset(0, 0x000000, 0x000000, 0xffffff, 0.0f, 0x1f, true, 0, false, false), 135 new Preset(1, 0x0000ff, 0x00ff00, 0xffff00, 2.0f, 0x1f, true, 0, true, false), 136 new Preset(1, 0x008000, 0x00ff00, 0xffffff, 2.5f, 0x1f, true, 0, true, false), 137 new Preset(1, 0x800000, 0xff0000, 0xffffff, 2.5f, 0x1f, true, 0, true, true), 138 new Preset(1, 0x808080, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, true), 139 new Preset(1, 0x0000ff, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, true), 140 new Preset(1, 0x0000ff, 0x00ff00, 0xffff00, 1.5f, 0x1f, false, 0, false, true), 141 new Preset(1, 0x0000ff, 0x00ff00, 0xffff00, 2.0f, 0x1f, true, 0, true, true), 142 new Preset(1, 0x0000ff, 0x00ff00, 0xffff00, 1.5f, 0x1f, true, 0, true, true), 143 new Preset(1, 0x808080, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, false, false), 144 new Preset(1, 0x000000, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, true, false), 145 new Preset(2, 0x000000, 0x000070, 0xff2020, 2.5f, 0x1f, true, 0, false, false), 146 new Preset(2, 0x6060ff, 0x000070, 0xffffff, 2.5f, 0x1f, true, 0, false, false), 147 new Preset(3, 0x0000f0, 0x000000, 0xffffff, 2.0f, 0x0f, true, 0, true, false), 148 }; 149 150 private float mTouchY; 151 MagicSmokeRS(Context context, int width, int height)152 MagicSmokeRS(Context context, int width, int height) { 153 super(width, height); 154 mWidth = width; 155 mHeight = height; 156 mWorldState.mTilt = 0; 157 mContext = context; 158 mSharedPref = mContext.getSharedPreferences("magicsmoke", Context.MODE_PRIVATE); 159 makeNewState(); 160 } 161 onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key)162 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { 163 164 makeNewState(); 165 mState.data(mWorldState); 166 } 167 makeNewState()168 void makeNewState() { 169 int p = mSharedPref.getInt("preset", DEFAULT_PRESET); 170 if (p >= mPreset.length) { 171 p = 0; 172 } 173 mWorldState.mPreset = p; 174 mWorldState.mTextureMask = mPreset[p].mTextureMask; 175 mWorldState.mRotate = mPreset[p].mRotate ? 1 : 0; 176 mWorldState.mTextureSwap = mPreset[p].mTextureSwap ? 1 : 0; 177 mWorldState.mProcessTextureMode = mPreset[p].mProcessTextureMode; 178 mWorldState.mBackCol = mPreset[p].mBackColor; 179 mWorldState.mLowCol = mPreset[p].mLowColor; 180 mWorldState.mHighCol = mPreset[p].mHighColor; 181 mWorldState.mAlphaMul = mPreset[p].mAlphaMul; 182 mWorldState.mPreMul = mPreset[p].mPreMul ? 1 : 0; 183 mWorldState.mBlendFunc = mPreset[p].mBlendFunc; 184 } 185 186 @Override resize(int width, int height)187 public void resize(int width, int height) { 188 super.resize(width, height); 189 if (mPVAlloc != null) { 190 mPVAlloc.setupProjectionNormalized(width, height); 191 } 192 } 193 194 @Override onTouchEvent(MotionEvent event)195 public void onTouchEvent(MotionEvent event) { 196 switch(event.getAction()) { 197 case MotionEvent.ACTION_DOWN: 198 mTouchY = event.getY(); 199 break; 200 case MotionEvent.ACTION_MOVE: 201 float dy = event.getY() - mTouchY; 202 mTouchY += dy; 203 dy /= 20; 204 dy += mWorldState.mTilt; 205 if (dy > 4) { 206 dy = 4; 207 } else if (dy < -4) { 208 dy = -4; 209 } 210 mWorldState.mTilt = dy; 211 mState.data(mWorldState); 212 } 213 } 214 215 @Override setOffset(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels)216 public void setOffset(float xOffset, float yOffset, float xStep, float yStep, 217 int xPixels, int yPixels) { 218 // update our state, then push it to the renderscript 219 mWorldState.mXOffset = xOffset; 220 mState.data(mWorldState); 221 } 222 223 @Override stop()224 public void stop() { 225 mSharedPref.unregisterOnSharedPreferenceChangeListener(this); 226 super.stop(); 227 } 228 229 @Override start()230 public void start() { 231 super.start(); 232 mSharedPref.registerOnSharedPreferenceChangeListener(this); 233 makeNewState(); 234 mState.data(mWorldState); 235 } 236 237 float alphafactor; 238 Type mTextureType; 239 loadBitmap(int id, int index, String name, float alphamul, int lowcol, int highcol)240 void loadBitmap(int id, int index, String name, float alphamul, int lowcol, int highcol) { 241 BitmapFactory.Options opts = new BitmapFactory.Options(); 242 opts.inPreferredConfig = Bitmap.Config.ARGB_8888; 243 Bitmap in = BitmapFactory.decodeResource(mResources, id, opts); 244 245 int pixels[] = new int[65536]; 246 in.getPixels(pixels, 0, 256, 0, 0, 256, 256); 247 mRealTextures[index] = Allocation.createTyped(mRS, mTextureType); 248 mSourceTextures[index] = Allocation.createTyped(mRS, mTextureType); 249 mSourceTextures[index].setName(name+"_src"); 250 mSourceTextures[index].data(pixels); 251 mRealTextures[index].setName(name); 252 in.recycle(); 253 } 254 loadBitmaps()255 void loadBitmaps() { 256 alphafactor = 1f; 257 float alphamul = mPreset[mWorldState.mPreset].mAlphaMul; 258 int lowcol = mPreset[mWorldState.mPreset].mLowColor; 259 int highcol = mPreset[mWorldState.mPreset].mHighColor; 260 //Log.i("@@@@", "preset " + mWorldState.mPreset + ", mul: " + alphamul + 261 // ", colors: " + Integer.toHexString(lowcol) + "/" + Integer.toHexString(highcol)); 262 263 // TODO: using different high and low colors for each layer offers some cool effects too 264 loadBitmap(R.drawable.noise1, 0, "Tnoise1", alphamul, lowcol, highcol); 265 loadBitmap(R.drawable.noise2, 1, "Tnoise2", alphamul, lowcol, highcol); 266 loadBitmap(R.drawable.noise3, 2, "Tnoise3", alphamul, lowcol, highcol); 267 loadBitmap(R.drawable.noise4, 3, "Tnoise4", alphamul, lowcol, highcol); 268 loadBitmap(R.drawable.noise5, 4, "Tnoise5", alphamul, lowcol, highcol); 269 } 270 271 @Override createScript()272 protected ScriptC createScript() { 273 274 // Create a renderscript type from a java class. The specified name doesn't 275 // really matter; the name by which we refer to the object in RenderScript 276 // will be specified later. 277 mStateType = Type.createFromClass(mRS, WorldState.class, 1, "WorldState"); 278 // Create an allocation from the type we just created. 279 mState = Allocation.createTyped(mRS, mStateType); 280 mState.data(mWorldState); 281 282 // First set up the coordinate system and such 283 ProgramVertex.Builder pvb = new ProgramVertex.Builder(mRS, null, null); 284 mPVBackground = pvb.create(); 285 mPVBackground.setName("PVBackground"); 286 mPVAlloc = new ProgramVertex.MatrixAllocation(mRS); 287 mPVBackground.bindAllocation(mPVAlloc); 288 mPVAlloc.setupProjectionNormalized(mWidth, mHeight); 289 290 mSourceTextures = new Allocation[5]; 291 mRealTextures = new Allocation[5]; 292 293 Type.Builder tb = new Type.Builder(mRS, Element.RGBA_8888(mRS)); 294 tb.add(Dimension.X, 256); 295 tb.add(Dimension.Y, 256); 296 mTextureType = tb.create(); 297 loadBitmaps(); 298 299 Sampler.Builder samplerBuilder = new Sampler.Builder(mRS); 300 samplerBuilder.setMin(LINEAR); 301 samplerBuilder.setMag(LINEAR); 302 samplerBuilder.setWrapS(WRAP); 303 samplerBuilder.setWrapT(WRAP); 304 mSampler = samplerBuilder.create(); 305 306 { 307 ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS, null, null); 308 builder.setTexEnable(true, 0); 309 builder.setTexEnvMode(ProgramFragment.EnvMode.MODULATE, 0); 310 mPfBackground = builder.create(); 311 mPfBackground.setName("PFBackground"); 312 mPfBackground.bindSampler(mSampler, 0); 313 } 314 315 { 316 ProgramStore.Builder builder = new ProgramStore.Builder(mRS, null, null); 317 builder.setDepthFunc(ProgramStore.DepthFunc.EQUAL); 318 builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ONE_MINUS_SRC_ALPHA); 319 builder.setDitherEnable(true); // without dithering there is severe banding 320 builder.setDepthMask(false); 321 mPfsBackgroundOne = builder.create(); 322 mPfsBackgroundOne.setName("PFSBackgroundOne"); 323 builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE_MINUS_SRC_ALPHA); 324 mPfsBackgroundSrc = builder.create(); 325 mPfsBackgroundSrc.setName("PFSBackgroundSrc"); 326 } 327 328 // Time to create the script 329 ScriptC.Builder sb = new ScriptC.Builder(mRS); 330 // Specify the name by which to refer to the WorldState object in the 331 // renderscript. 332 sb.setType(mStateType, "State", RSID_STATE); 333 sb.setType(mTextureType, "noisesrc1", RSID_NOISESRC1); 334 sb.setType(mTextureType, "noisedst1", RSID_NOISEDST1); 335 sb.setType(mTextureType, "noisesrc2", RSID_NOISESRC2); 336 sb.setType(mTextureType, "noisedst2", RSID_NOISEDST2); 337 sb.setType(mTextureType, "noisesrc3", RSID_NOISESRC3); 338 sb.setType(mTextureType, "noisedst3", RSID_NOISEDST3); 339 sb.setType(mTextureType, "noisesrc4", RSID_NOISESRC4); 340 sb.setType(mTextureType, "noisedst4", RSID_NOISEDST4); 341 sb.setType(mTextureType, "noisesrc5", RSID_NOISESRC5); 342 sb.setType(mTextureType, "noisedst5", RSID_NOISEDST5); 343 sb.setScript(mResources, R.raw.clouds); 344 sb.setRoot(true); 345 346 ScriptC script = sb.create(); 347 script.setClearColor(1.0f, 0.0f, 0.0f, 1.0f); 348 script.setTimeZone(TimeZone.getDefault().getID()); 349 350 script.bindAllocation(mState, RSID_STATE); 351 script.bindAllocation(mSourceTextures[0], RSID_NOISESRC1); 352 script.bindAllocation(mRealTextures[0], RSID_NOISEDST1); 353 script.bindAllocation(mSourceTextures[1], RSID_NOISESRC2); 354 script.bindAllocation(mRealTextures[1], RSID_NOISEDST2); 355 script.bindAllocation(mSourceTextures[2], RSID_NOISESRC3); 356 script.bindAllocation(mRealTextures[2], RSID_NOISEDST3); 357 script.bindAllocation(mSourceTextures[3], RSID_NOISESRC4); 358 script.bindAllocation(mRealTextures[3], RSID_NOISEDST4); 359 script.bindAllocation(mSourceTextures[4], RSID_NOISESRC5); 360 script.bindAllocation(mRealTextures[4], RSID_NOISEDST5); 361 //script.bindAllocation(mPVAlloc.mAlloc, RSID_PROGRAMVERTEX); 362 363 364 return script; 365 } 366 } 367