blob: 3f32d092731f2b29d86cf16efbb37c3d9ecf1684 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.wallpaper.galaxy;
import android.renderscript.*;
import android.renderscript.Mesh.Primitive;
import static android.renderscript.ProgramStore.DepthFunc.*;
import static android.renderscript.ProgramStore.BlendDstFunc;
import static android.renderscript.ProgramStore.BlendSrcFunc;
import static android.renderscript.Element.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import java.util.TimeZone;
import com.android.wallpaper.R;
import com.android.wallpaper.RenderScriptScene;
class GalaxyRS extends RenderScriptScene {
private static final int PARTICLES_COUNT = 12000;
private final BitmapFactory.Options mOptionsARGB = new BitmapFactory.Options();
private ProgramVertexFixedFunction.Constants mPvOrthoAlloc;
private ProgramVertexFixedFunction.Constants mPvProjectionAlloc;
private ScriptField_VpConsts mPvStarAlloc;
private Mesh mParticlesMesh;
private ScriptC_galaxy mScript;
GalaxyRS(int width, int height) {
super(width, height);
mOptionsARGB.inScaled = false;
mOptionsARGB.inPreferredConfig = Bitmap.Config.ARGB_8888;
}
@Override
protected ScriptC createScript() {
mScript = new ScriptC_galaxy(mRS, mResources, R.raw.galaxy);
mScript.set_gIsPreview(isPreview() ? 1 : 0);
if (isPreview()) {
mScript.set_gXOffset(0.5f);
}
createParticlesMesh();
createProgramVertex();
createProgramRaster();
createProgramFragmentStore();
createProgramFragment();
loadTextures();
mScript.setTimeZone(TimeZone.getDefault().getID());
return mScript;
}
private void createParticlesMesh() {
ScriptField_Particle p = new ScriptField_Particle(mRS, PARTICLES_COUNT);
final Mesh.AllocationBuilder meshBuilder = new Mesh.AllocationBuilder(mRS);
meshBuilder.addVertexAllocation(p.getAllocation());
final int vertexSlot = meshBuilder.getCurrentVertexTypeIndex();
meshBuilder.addIndexSetType(Primitive.POINT);
mParticlesMesh = meshBuilder.create();
mScript.set_gParticlesMesh(mParticlesMesh);
mScript.bind_Particles(p);
}
private Matrix4f getProjectionNormalized(int w, int h) {
// range -1,1 in the narrow axis at z = 0.
Matrix4f m1 = new Matrix4f();
Matrix4f m2 = new Matrix4f();
if(w > h) {
float aspect = ((float)w) / h;
m1.loadFrustum(-aspect,aspect, -1,1, 1,100);
} else {
float aspect = ((float)h) / w;
m1.loadFrustum(-1,1, -aspect,aspect, 1,100);
}
m2.loadRotate(180, 0, 1, 0);
m1.loadMultiply(m1, m2);
m2.loadScale(-2, 2, 1);
m1.loadMultiply(m1, m2);
m2.loadTranslate(0, 0, 2);
m1.loadMultiply(m1, m2);
return m1;
}
private void updateProjectionMatrices() {
Matrix4f proj = new Matrix4f();
proj.loadOrthoWindow(mWidth, mHeight);
mPvOrthoAlloc.setProjection(proj);
Matrix4f projNorm = getProjectionNormalized(mWidth, mHeight);
ScriptField_VpConsts.Item i = new ScriptField_VpConsts.Item();
i.Proj = projNorm;
i.MVP = projNorm;
mPvStarAlloc.set(i, 0, true);
mPvProjectionAlloc.setProjection(projNorm);
}
@Override
public void setOffset(float xOffset, float yOffset, int xPixels, int yPixels) {
mScript.set_gXOffset(xOffset);
}
@Override
public void resize(int width, int height) {
super.resize(width, height);
updateProjectionMatrices();
}
private void loadTextures() {
mScript.set_gTSpace(loadTexture(R.drawable.space));
mScript.set_gTLight1(loadTexture(R.drawable.light1));
mScript.set_gTFlares(loadTextureARGB(R.drawable.flares));
}
private Allocation loadTexture(int id) {
final Allocation allocation = Allocation.createFromBitmapResource(mRS, mResources, id);
return allocation;
}
// TODO: Fix Allocation.createFromBitmapResource() to do this when RGBA_8888 is specified
private Allocation loadTextureARGB(int id) {
Bitmap b = BitmapFactory.decodeResource(mResources, id, mOptionsARGB);
final Allocation allocation = Allocation.createFromBitmap(mRS, b);
return allocation;
}
private void createProgramFragment() {
ProgramFragmentFixedFunction.Builder builder = new ProgramFragmentFixedFunction.Builder(mRS);
builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.REPLACE,
ProgramFragmentFixedFunction.Builder.Format.RGB, 0);
ProgramFragment pfb = builder.create();
pfb.bindSampler(Sampler.WRAP_NEAREST(mRS), 0);
mScript.set_gPFBackground(pfb);
builder = new ProgramFragmentFixedFunction.Builder(mRS);
builder.setPointSpriteTexCoordinateReplacement(true);
builder.setTexture(ProgramFragmentFixedFunction.Builder.EnvMode.MODULATE,
ProgramFragmentFixedFunction.Builder.Format.RGBA, 0);
builder.setVaryingColor(true);
ProgramFragment pfs = builder.create();
pfs.bindSampler(Sampler.WRAP_LINEAR(mRS), 0);
mScript.set_gPFStars(pfs);
}
private void createProgramFragmentStore() {
ProgramStore.Builder builder = new ProgramStore.Builder(mRS);
builder.setBlendFunc(BlendSrcFunc.ONE, BlendDstFunc.ZERO);
mRS.bindProgramStore(builder.create());
builder.setBlendFunc(BlendSrcFunc.SRC_ALPHA, BlendDstFunc.ONE);
mScript.set_gPSLights(builder.create());
}
private void createProgramVertex() {
mPvOrthoAlloc = new ProgramVertexFixedFunction.Constants(mRS);
ProgramVertexFixedFunction.Builder builder = new ProgramVertexFixedFunction.Builder(mRS);
ProgramVertex pvbo = builder.create();
((ProgramVertexFixedFunction)pvbo).bindConstants(mPvOrthoAlloc);
mRS.bindProgramVertex(pvbo);
mPvStarAlloc = new ScriptField_VpConsts(mRS, 1);
mScript.bind_vpConstants(mPvStarAlloc);
mPvProjectionAlloc = new ProgramVertexFixedFunction.Constants(mRS);
updateProjectionMatrices();
builder = new ProgramVertexFixedFunction.Builder(mRS);
ProgramVertex pvbp = builder.create();
((ProgramVertexFixedFunction)pvbp).bindConstants(mPvProjectionAlloc);
mScript.set_gPVBkProj(pvbp);
ProgramVertex.Builder sb = new ProgramVertex.Builder(mRS);
String t = "varying vec4 varColor;\n" +
"varying vec2 varTex0;\n" +
"void main() {\n" +
" float dist = ATTRIB_position.y;\n" +
" float angle = ATTRIB_position.x;\n" +
" float x = dist * sin(angle);\n" +
" float y = dist * cos(angle) * 0.892;\n" +
" float p = dist * 5.5;\n" +
" float s = cos(p);\n" +
" float t = sin(p);\n" +
" vec4 pos;\n" +
" pos.x = t * x + s * y;\n" +
" pos.y = s * x - t * y;\n" +
" pos.z = ATTRIB_position.z;\n" +
" pos.w = 1.0;\n" +
" gl_Position = UNI_MVP * pos;\n" +
" gl_PointSize = ATTRIB_color.a * 10.0;\n" +
" varColor.rgb = ATTRIB_color.rgb;\n" +
" varColor.a = 1.0;\n" +
"}\n";
sb.setShader(t);
sb.addInput(mParticlesMesh.getVertexAllocation(0).getType().getElement());
sb.addConstant(mPvStarAlloc.getType());
ProgramVertex pvs = sb.create();
pvs.bindConstants(mPvStarAlloc.getAllocation(), 0);
mScript.set_gPVStars(pvs);
}
private void createProgramRaster() {
ProgramRaster.Builder b = new ProgramRaster.Builder(mRS);
b.setPointSpriteEnabled(true);
ProgramRaster pr = b.create();
mRS.bindProgramRaster(pr);
}
}