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.wallpaper.galaxy; 18 19 import android.renderscript.*; 20 import android.renderscript.Mesh.Primitive; 21 import static android.renderscript.ProgramStore.DepthFunc.*; 22 import static android.renderscript.ProgramStore.BlendDstFunc; 23 import static android.renderscript.ProgramStore.BlendSrcFunc; 24 import static android.renderscript.Element.*; 25 import android.graphics.Bitmap; 26 import android.graphics.BitmapFactory; 27 28 import java.util.TimeZone; 29 30 import com.android.wallpaper.R; 31 import com.android.wallpaper.RenderScriptScene; 32 33 class 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 Allocation.MipmapControl.MIPMAP_NONE, 140 Allocation.USAGE_GRAPHICS_TEXTURE); 141 return allocation; 142 } 143 144 // TODO: Fix Allocation.createFromBitmapResource() to do this when RGBA_8888 is specified 145 private Allocation loadTextureARGB(int id) { 146 Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB); 147 final Allocation allocation = Allocation.createFromBitmap(mRS, b, 148 Allocation.MipmapControl.MIPMAP_NONE, 149 Allocation.USAGE_GRAPHICS_TEXTURE); 150 return allocation; 151 } 152 153 private void createProgramFragment() { 154 ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS); 155 builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE, 156 ProgramFragmentFixedFunction.Builder.Format.RGB, 0); 157 ProgramFragment pfb = builder.create(); 158 pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0); 159 mScript.set_gPFBackground(pfb); 160 161 builder = new ProgramFragmentFixedFunction.Builder(mRS); 162 builder.setPointSpriteTexCoordinateReplacement(true); 163 builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE, 164 ProgramFragmentFixedFunction.Builder.Format.RGBA, 0); 165 builder.setVaryingColor(true); 166 ProgramFragment pfs = builder.create(); 167 pfs.bindSampler(Sampler.WRAP_LINEAR(mRS), 0); 168 mScript.set_gPFStars(pfs); 169 } 170 171 private void createProgramFragmentStore() { 172 ProgramStore.Builder builder = new ProgramStore.Builder(mRS); 173 builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO); 174 mRS.bindProgramStore(builder.create()); 175 176 builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE); 177 mScript.set_gPSLights(builder.create()); 178 } 179 180 private void createProgramVertex() { 181 mPvOrthoAlloc = new ProgramVertexFixedFunction.Constants(mRS); 182 183 ProgramVertexFixedFunction.Builder builder = new ProgramVertexFixedFunction.Builder(mRS); 184 ProgramVertex pvbo = builder.create(); 185 ((ProgramVertexFixedFunction)pvbo).bindConstants(mPvOrthoAlloc); 186 mRS.bindProgramVertex(pvbo); 187 188 mPvStarAlloc = new ScriptField_VpConsts(mRS, 1); 189 mScript.bind_vpConstants(mPvStarAlloc); 190 mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS); 191 updateProjectionMatrices(); 192 193 builder = new ProgramVertexFixedFunction.Builder(mRS); 194 ProgramVertex pvbp = builder.create(); 195 ((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc); 196 mScript.set_gPVBkProj(pvbp); 197 198 ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS); 199 String t = "varying vec4 varColor;\n" + 200 "varying vec2 varTex0;\n" + 201 "void main() {\n" + 202 " float dist = ATTRIB_position.y;\n" + 203 " float angle = ATTRIB_position.x;\n" + 204 " float x = dist * sin(angle);\n" + 205 " float y = dist * cos(angle) * 0.892;\n" + 206 " float p = dist * 5.5;\n" + 207 " float s = cos(p);\n" + 208 " float t = sin(p);\n" + 209 " vec4 pos;\n" + 210 " pos.x = t * x + s * y;\n" + 211 " pos.y = s * x - t * y;\n" + 212 " pos.z = ATTRIB_position.z;\n" + 213 " pos.w = 1.0;\n" + 214 " gl_Position = UNI_MVP * pos;\n" + 215 " gl_PointSize = ATTRIB_color.a * 10.0;\n" + 216 " varColor.rgb = ATTRIB_color.rgb;\n" + 217 " varColor.a = 1.0;\n" + 218 "}\n"; 219 sb.setShader(t); 220 sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement()); 221 sb.addConstant(mPvStarAlloc.getType()); 222 ProgramVertex pvs = sb.create(); 223 pvs.bindConstants(mPvStarAlloc.getAllocation(), 0); 224 mScript.set_gPVStars(pvs); 225 } 226 227 private void createProgramRaster() { 228 ProgramRaster.Builder b = new ProgramRaster.Builder(mRS); 229 b.setPointSpriteEnabled(true); 230 ProgramRaster pr = b.create(); 231 mRS.bindProgramRaster(pr); 232 } 233 234 } 235