1 /* 2 * Copyright (C) 2010 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.holospiral; 18 19 import com.android.wallpaper.holospiral.ScriptC_holo_spiral; 20 import com.android.wallpaper.holospiral.ScriptField_VertexColor_s; 21 import com.android.wallpaper.holospiral.ScriptField_VertexShaderConstants_s; 22 23 import android.content.res.Resources; 24 import android.graphics.Bitmap; 25 import android.graphics.BitmapFactory; 26 import android.graphics.Color; 27 import android.os.Bundle; 28 import android.renderscript.Allocation; 29 import android.renderscript.Element; 30 import android.renderscript.Float3; 31 import android.renderscript.Float4; 32 import android.renderscript.Mesh; 33 import android.renderscript.Mesh.Primitive; 34 import android.renderscript.Program; 35 import android.renderscript.ProgramFragment; 36 import android.renderscript.ProgramStore; 37 import android.renderscript.ProgramVertex; 38 import android.renderscript.RenderScriptGL; 39 import android.renderscript.Sampler; 40 41 public class HoloSpiralRS { 42 private static final String LOG_TAG = "HoloSpiralRS"; 43 private static final float MAX_POINT_SIZE = 75.0f; 44 private static final float NEAR_PLANE = 1.0f; 45 private static final float FAR_PLANE = 55.0f; 46 47 private static final int NUM_INNER_POINTS = 100; 48 private static final float INNER_SPIRAL_DEPTH = 50.0f; 49 private static final float INNER_RADIUS = 5.0f; 50 private static final float INNER_SEPARATION_DEG = 23.0f; 51 52 private static final int NUM_OUTER_POINTS = 50; 53 private static final float OUTER_SPIRAL_DEPTH = 30.0f; 54 private static final float OUTER_RADIUS = 10.0f; 55 private static final float OUTER_SEPARATION_DEG = 23.0f; 56 57 /* Colors */ 58 private static final int POINTS_COLOR_BLUE = Color.argb(179, 0, 0, 255); 59 private static final int POINTS_COLOR_GREEN = Color.argb(210, 166, 51, 255); 60 private static final int POINTS_COLOR_AQUA = Color.argb(220, 38, 120, 148); 61 private static final int BG_COLOR_BLACK = Color.argb(255, 26, 26, 83); 62 private static final int BG_COLOR_BLUE = Color.argb(255, 8, 0, 26); 63 64 private ScriptC_holo_spiral mScript; 65 private RenderScriptGL mRS = null; 66 private Resources mResources = null; 67 68 public HoloSpiralRS(RenderScriptGL renderer, Resources resources) { 69 init(renderer, resources); 70 } 71 72 public void init(RenderScriptGL renderer, Resources resources) { 73 mRS = renderer; 74 mResources = resources; 75 createScript(); 76 } 77 78 public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) { 79 mScript.set_gXOffset(xOffset); 80 } 81 82 public Bundle onCommand(String action, int x, int y, int z, Bundle extras, 83 boolean resultRequested) { 84 return null; 85 } 86 87 public void start() { 88 mRS.bindRootScript(mScript); 89 } 90 91 public void stop() { 92 mRS.bindRootScript(null); 93 } 94 95 public void resize(int width, int height) { 96 mScript.invoke_resize(width, height); 97 } 98 99 private void createScript() { 100 mScript = new ScriptC_holo_spiral(mRS, mResources, R.raw.holo_spiral); 101 mScript.set_gNearPlane(NEAR_PLANE); 102 mScript.set_gFarPlane(FAR_PLANE); 103 104 createVertexPrograms(); 105 createFragmentPrograms(); 106 createStorePrograms(); 107 108 createPointGeometry(); 109 createBackgroundMesh(); 110 createTextures(); 111 } 112 113 private void createVertexPrograms() { 114 ScriptField_VertexShaderConstants_s vertexShaderConstants = 115 new ScriptField_VertexShaderConstants_s(mRS, 1); 116 mScript.bind_gVSConstants(vertexShaderConstants); 117 vertexShaderConstants.set_maxPointSize(0, MAX_POINT_SIZE, false); 118 vertexShaderConstants.copyAll(); 119 120 ProgramVertex.Builder backgroundBuilder = new ProgramVertex.Builder(mRS); 121 backgroundBuilder.setShader(mResources, R.raw.vertex_background); 122 backgroundBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS)); 123 ProgramVertex programVertexBackground = backgroundBuilder.create(); 124 mScript.set_gPVBackground(programVertexBackground); 125 126 ProgramVertex.Builder geometryBuilder = new ProgramVertex.Builder(mRS); 127 geometryBuilder.setShader(mResources, R.raw.vertex_geometry); 128 geometryBuilder.addConstant(vertexShaderConstants.getAllocation().getType()); 129 geometryBuilder.addInput(ScriptField_VertexColor_s.createElement(mRS)); 130 ProgramVertex programVertexGeometry = geometryBuilder.create(); 131 programVertexGeometry.bindConstants(vertexShaderConstants.getAllocation(), 0); 132 mScript.set_gPVGeometry(programVertexGeometry); 133 } 134 135 private void createFragmentPrograms() { 136 ProgramFragment.Builder backgroundBuilder = new ProgramFragment.Builder(mRS); 137 backgroundBuilder.setShader(mResources, R.raw.fragment_background); 138 ProgramFragment programFragmentBackground = backgroundBuilder.create(); 139 mScript.set_gPFBackground(programFragmentBackground); 140 141 ProgramFragment.Builder geometryBuilder = new ProgramFragment.Builder(mRS); 142 geometryBuilder.setShader(mResources, R.raw.fragment_geometry); 143 geometryBuilder.addTexture(Program.TextureType.TEXTURE_2D); 144 ProgramFragment programFragmentGeometry = geometryBuilder.create(); 145 programFragmentGeometry.bindSampler(Sampler.CLAMP_LINEAR(mRS), 0); 146 mScript.set_gPFGeometry(programFragmentGeometry); 147 } 148 149 private void createStorePrograms() { 150 ProgramStore.Builder builder = new ProgramStore.Builder(mRS); 151 builder.setBlendFunc(ProgramStore.BlendSrcFunc.SRC_ALPHA, 152 ProgramStore.BlendDstFunc.ONE_MINUS_SRC_ALPHA); 153 mScript.set_gPSGeometry(builder.create()); 154 builder.setBlendFunc(ProgramStore.BlendSrcFunc.ONE, ProgramStore.BlendDstFunc.ZERO); 155 builder.setDitherEnabled(true); 156 mScript.set_gPSBackground(builder.create()); 157 } 158 159 private void createPointGeometry() { 160 ScriptField_VertexColor_s innerPoints = 161 new ScriptField_VertexColor_s(mRS, NUM_INNER_POINTS); 162 generateSpiral(innerPoints, INNER_SPIRAL_DEPTH, INNER_RADIUS, INNER_SEPARATION_DEG, 163 POINTS_COLOR_BLUE, POINTS_COLOR_GREEN); 164 165 Mesh.AllocationBuilder innerPointBuilder = new Mesh.AllocationBuilder(mRS); 166 innerPointBuilder.addIndexSetType(Primitive.POINT); 167 innerPointBuilder.addVertexAllocation(innerPoints.getAllocation()); 168 mScript.set_gInnerGeometry(innerPointBuilder.create()); 169 170 ScriptField_VertexColor_s outerPoints = 171 new ScriptField_VertexColor_s(mRS, NUM_OUTER_POINTS); 172 generateSpiral(outerPoints, OUTER_SPIRAL_DEPTH, OUTER_RADIUS, OUTER_SEPARATION_DEG, 173 POINTS_COLOR_AQUA, POINTS_COLOR_AQUA); 174 175 Mesh.AllocationBuilder outerPointBuilder = new Mesh.AllocationBuilder(mRS); 176 outerPointBuilder.addIndexSetType(Primitive.POINT); 177 outerPointBuilder.addVertexAllocation(outerPoints.getAllocation()); 178 mScript.set_gOuterGeometry(outerPointBuilder.create()); 179 } 180 181 private void createTextures() { 182 Bitmap bmp = BitmapFactory.decodeResource( 183 mResources, R.drawable.points_red_green, null); 184 Allocation pointTexture = Allocation.createFromBitmap(mRS, bmp); 185 mScript.set_gPointTexture(pointTexture); 186 } 187 188 private void createBackgroundMesh() { 189 ScriptField_VertexColor_s fullQuad = new ScriptField_VertexColor_s(mRS, 4); 190 191 Float3 topLeft = new Float3(-1.0f, 1.0f, 0.0f); 192 Float3 bottomLeft = new Float3(-1.0f, -1.0f, 0.0f); 193 Float3 topRight = new Float3(1.0f, 1.0f, 0.0f); 194 Float3 bottomRight = new Float3(1.0f, -1.0f, 0.0f); 195 196 fullQuad.set_position(0, topLeft, false); 197 fullQuad.set_color(0, convertColor(BG_COLOR_BLUE), false); 198 199 fullQuad.set_position(1, bottomLeft, false); 200 fullQuad.set_color(1, convertColor(BG_COLOR_BLACK), false); 201 202 fullQuad.set_position(2, topRight, false); 203 fullQuad.set_color(2, convertColor(BG_COLOR_BLUE), false); 204 205 fullQuad.set_position(3, bottomRight, false); 206 fullQuad.set_color(3, convertColor(BG_COLOR_BLACK), false); 207 208 fullQuad.copyAll(); 209 210 Mesh.AllocationBuilder backgroundBuilder = new Mesh.AllocationBuilder(mRS); 211 backgroundBuilder.addIndexSetType(Primitive.TRIANGLE_STRIP); 212 backgroundBuilder.addVertexAllocation(fullQuad.getAllocation()); 213 mScript.set_gBackgroundMesh(backgroundBuilder.create()); 214 } 215 216 private void generateSpiral(ScriptField_VertexColor_s points, float depth, float radius, 217 float separationDegrees, int primaryColor, int secondaryColor) { 218 219 float separationRads = (separationDegrees / 360.0f) * 2 * (float) Math.PI; 220 int size = points.getAllocation().getType().getX(); 221 222 float halfDepth = depth / 2.0f; 223 float radians = 0.0f; 224 225 Float4 primary = convertColor(primaryColor); 226 Float4 secondary = convertColor(secondaryColor); 227 228 for (int i = 0; i < size; i++) { 229 float percentage = (float) i / (float) size; 230 Float3 position = new Float3(radius * (float) Math.cos(radians), 231 radius * (float) Math.sin(radians), (percentage * depth) - halfDepth); 232 233 float r = (float) Math.sin(radians / 2.0f); 234 235 Float4 color = new Float4(); 236 color.x = primary.x + ((secondary.x - primary.x) * r); 237 color.y = primary.y + ((secondary.y - primary.y) * r); 238 color.z = primary.z + ((secondary.z - primary.z) * r); 239 color.w = primary.w + ((secondary.w - primary.w) * r); 240 241 points.set_position(i, position, false); 242 points.set_color(i, color, false); 243 244 radians += separationRads; 245 int multiplier = (int) (radians / (2.0f * (float) Math.PI)); 246 radians -= multiplier * 2.0f * (float) Math.PI; 247 } 248 249 points.copyAll(); 250 } 251 252 private static Float4 convertColor(int color) { 253 float red = Color.red(color) / 255.0f; 254 float green = Color.green(color) / 255.0f; 255 float blue = Color.blue(color) / 255.0f; 256 float alpha = Color.alpha(color) / 255.0f; 257 return new Float4(red, green, blue, alpha); 258 } 259 } 260