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 17package com.android.wallpaper.galaxy; 18 19import android.renderscript.*; 20import android.renderscript.Mesh.Primitive; 21import static android.renderscript.ProgramStore.DepthFunc.*; 22import static android.renderscript.ProgramStore.BlendDstFunc; 23import static android.renderscript.ProgramStore.BlendSrcFunc; 24import static android.renderscript.Element.*; 25import android.graphics.Bitmap; 26import android.graphics.BitmapFactory; 27 28import java.util.TimeZone; 29 30import com.android.wallpaper.R; 31import com.android.wallpaper.RenderScriptScene; 32 33class GalaxyRS extends RenderScriptScene { 34 private static final int PARTICLES_COUNT = 12000; 35 private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options(); 36 private ProgramVertexFixedFunction.Constants mPvOrthoAlloc; 37 private ProgramVertexFixedFunction.Constants mPvProjectionAlloc; 38 private ScriptField_VpConsts mPvStarAlloc; 39 private Mesh mParticlesMesh; 40 private ScriptC_galaxy mScript; 41 42 GalaxyRS(int width, int height) { 43 super(width, height); 44 45 mOptionsARGB.inScaled = false; 46 mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888; 47 } 48 49 @Override 50 protected ScriptC createScript() { 51 mScript = new ScriptC_galaxy(mRS, mResources, R.raw.galaxy); 52 mScript.set_gIsPreview(isPreview() ? 1 : 0); 53 if (isPreview()) { 54 mScript.set_gXOffset(0.5f); 55 } 56 57 58 createParticlesMesh(); 59 createProgramVertex(); 60 createProgramRaster(); 61 createProgramFragmentStore(); 62 createProgramFragment(); 63 loadTextures(); 64 65 mScript.setTimeZone(TimeZone.getDefault().getID()); 66 return mScript; 67 } 68 69 private void createParticlesMesh() { 70 ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT); 71 72 final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS); 73 meshBuilder.addVertexAllocation(p.getAllocation()); 74 final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex(); 75 meshBuilder.addIndexSetType(Primitive.POINT); 76 mParticlesMesh = meshBuilder.create(); 77 78 mScript.set_gParticlesMesh(mParticlesMesh); 79 mScript.bind_Particles(p); 80 } 81 82 private Matrix4f getProjectionNormalized(int w, int h) { 83 // range -1,1 in the narrow axis at z = 0. 84 Matrix4f m1 = new Matrix4f(); 85 Matrix4f m2 = new Matrix4f(); 86 87 if(w > h) { 88 float aspect = ((float)w) / h; 89 m1.loadFrustum(-aspect,aspect, -1,1, 1,100); 90 } else { 91 float aspect = ((float)h) / w; 92 m1.loadFrustum(-1,1, -aspect,aspect, 1,100); 93 } 94 95 m2.loadRotate(180, 0, 1, 0); 96 m1.loadMultiply(m1, m2); 97 98 m2.loadScale(-2, 2, 1); 99 m1.loadMultiply(m1, m2); 100 101 m2.loadTranslate(0, 0, 2); 102 m1.loadMultiply(m1, m2); 103 return m1; 104 } 105 106 private void updateProjectionMatrices() { 107 Matrix4f proj = new Matrix4f(); 108 proj.loadOrthoWindow(mWidth, mHeight); 109 mPvOrthoAlloc.setProjection(proj); 110 111 Matrix4f projNorm = getProjectionNormalized(mWidth, mHeight); 112 ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item(); 113 i.Proj = projNorm; 114 i.MVP = projNorm; 115 mPvStarAlloc.set(i, 0, true); 116 mPvProjectionAlloc.setProjection(projNorm); 117 } 118 119 @Override 120 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { 121 mScript.set_gXOffset(xOffset); 122 } 123 124 @Override 125 public void resize(int width, int height) { 126 super.resize(width, height); 127 128 updateProjectionMatrices(); 129 } 130 131 private void loadTextures() { 132 mScript.set_gTSpace(loadTexture(R.drawable.space)); 133 mScript.set_gTLight1(loadTexture(R.drawable.light1)); 134 mScript.set_gTFlares(loadTextureARGB(R.drawable.flares)); 135 } 136 137 private Allocation loadTexture(int id) { 138 final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources, id); 139 return allocation; 140 } 141 142 // TODO: Fix Allocation.createFromBitmapResource() to do this when RGBA_8888 is specified 143 private Allocation loadTextureARGB(int id) { 144 Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB); 145 final Allocation allocation = Allocation.createFromBitmap(mRS, b); 146 return allocation; 147 } 148 149 private void createProgramFragment() { 150 ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS); 151 builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, 152 ProgramFragmentFixedFunction.Builder.Format.RGB, 0); 153 ProgramFragment pfb = builder.create(); 154 pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0); 155 mScript.set_gPFBackground(pfb); 156 157 builder = new ProgramFragmentFixedFunction.Builder(mRS); 158 builder.setPointSpriteTexCoordinateReplacement(true); 159 builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE, 160 ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); 161 builder.setVaryingColor(true); 162 ProgramFragment pfs = builder.create(); 163 pfs.bindSampler(Sampler.WRAP_LINEAR(mRS), 0); 164 mScript.set_gPFStars(pfs); 165 } 166 167 private void createProgramFragmentStore() { 168 ProgramStore.Builder builder = new ProgramStore.Builder(mRS); 169 builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO); 170 mRS.bindProgramStore(builder.create()); 171 172 builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE); 173 mScript.set_gPSLights(builder.create()); 174 } 175 176 private void createProgramVertex() { 177 mPvOrthoAlloc = new ProgramVertexFixedFunction.Constants(mRS); 178 179 ProgramVertexFixedFunction.Builder builder = new ProgramVertexFixedFunction.Builder(mRS); 180 ProgramVertex pvbo = builder.create(); 181 ((ProgramVertexFixedFunction)pvbo).bindConstants(mPvOrthoAlloc); 182 mRS.bindProgramVertex(pvbo); 183 184 mPvStarAlloc = new ScriptField_VpConsts(mRS, 1); 185 mScript.bind_vpConstants(mPvStarAlloc); 186 mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS); 187 updateProjectionMatrices(); 188 189 builder = new ProgramVertexFixedFunction.Builder(mRS); 190 ProgramVertex pvbp = builder.create(); 191 ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc); 192 mScript.set_gPVBkProj(pvbp); 193 194 ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS); 195 String t = "varying vec4 varColor;\n" + 196 "varying vec2 varTex0;\n" + 197 "void main() {\n" + 198 " float dist = ATTRIB_position.y;\n" + 199 " float angle = ATTRIB_position.x;\n" + 200 " float x = dist * sin(angle);\n" + 201 " float y = dist * cos(angle) * 0.892;\n" + 202 " float p = dist * 5.5;\n" + 203 " float s = cos(p);\n" + 204 " float t = sin(p);\n" + 205 " vec4 pos;\n" + 206 " pos.x = t * x + s * y;\n" + 207 " pos.y = s * x - t * y;\n" + 208 " pos.z = ATTRIB_position.z;\n" + 209 " pos.w = 1.0;\n" + 210 " gl_Position = UNI_MVP * pos;\n" + 211 " gl_PointSize = ATTRIB_color.a * 10.0;\n" + 212 " varColor.rgb = ATTRIB_color.rgb;\n" + 213 " varColor.a = 1.0;\n" + 214 "}\n"; 215 sb.setShader(t); 216 sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement()); 217 sb.addConstant(mPvStarAlloc.getType()); 218 ProgramVertex pvs = sb.create(); 219 pvs.bindConstants(mPvStarAlloc.getAllocation(), 0); 220 mScript.set_gPVStars(pvs); 221 } 222 223 private void createProgramRaster() { 224 ProgramRaster.Builder b = new ProgramRaster.Builder(mRS); 225 b.setPointSpriteEnabled(true); 226 ProgramRaster pr = b.create(); 227 mRS.bindProgramRaster(pr); 228 } 229 230} 231