这篇主要是关于Android RenderScript 的使用。
RenderScript简介:RenderScript是Android平台的一种类C脚本语言,Google虽然一直在之前的各个Android版本内置的动态墙纸中使用该技术实现3D图形特效,但一直未将其集成在公开发布的SDK中。至Android3.0版本开始,SDK中已将RenderScript技术集成了进来,开发者可在Eclipse下开发基于RenderScript的3D应用,并在Android3.0版本以上的平板电脑中运行。
SDK链接:http://developer.android.com/guide/topics/renderscript/index.html
要使用Renderscript渲染功能,需要实现的功能如下:
fall.rs 实现RenderScript的代码,是水波纹效果实现的关键代码(但关于.rs文件的资料少之又少,希望今后会多起来)
FallRS.java .rs文件的辅助类,用以简化操作fall.rs文件
FallView.java 一个继承于RSSurfaceView的类,用于显示RenderScript的渲染或者用来处理用户的触摸等视图
Fall.java 这是一个Activity,Android 应用程序的界面类。
好了先来看fall.rs文件(中文是我加的注释):
// 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.
//编译指示声明(#pragma version(1)),声明了要使用的Renderscript的版本(目前只能是1)
#pragma version(1)
//编译指示声明(#pragma rs java_package_name(package.name)),它声明了该Renderscript反射所对应的*.java类名
#pragma rs java_package_name(com.harlan.waterscreen)
#include "rs_graphics.rsh"
#define LEAVES_TEXTURES_COUNT 8
#define LEAF_SIZE 0.55f
#define LEAVES_COUNT 14
// Things we need to set from the application
float g_glWidth;
float g_glHeight;
float g_meshWidth;
float g_meshHeight;
float g_xOffset;
float g_rotate;
//着色器处理程序类分为4类:ProgramFragment ProgramFragmentStore ProgramVertext Mesh
//ProgramFragment对应片断处理程序,对光栅化的每一个片断做独立的处理,包括映射纹理点,混合,着色等。
//ProgramFragmentStore主要负责一些跟片断处理相关的辅助功能,如设置混合模式等。
//ProgramVertext对应顶点处理程序,对每一个顶点做独立的处理,包括视景投影变换,法线变换等。
//Mesh又叫网格,是方便对一组顶点的处理的类。
//以上四个类最终都会被调用setupGL或render这样方法,在这些方法中将用户的配置转换为OpenGL的具体操作序列。
rs_program_vertex g_PVWater;
rs_program_vertex g_PVSky;
rs_program_fragment g_PFSky;
rs_program_store g_PFSLeaf;
rs_program_fragment g_PFBackground;
rs_allocation g_TLeaves;
rs_allocation g_TRiverbed;
rs_mesh g_WaterMesh;
//存储类,主要用来进行数据的存储以及和上层java的交换,包括Type,Element,Allocation。Element可以理解为一个结构体。
//下面是一个element;Constants是对这个结构体的类型的命名,Constants_t 就是这个Constants。
typedef struct Constants {
float4 Drop01;
float4 Drop02;
float4 Drop03;
float4 Drop04;
float4 Drop05;
float4 Drop06;
float4 Drop07;
float4 Drop08;
float4 Drop09;
float4 Drop10;
float4 Offset;
float Rotate;
} Constants_t;
//这是一个Constants_t的一个实例,是一个Allocation
//在RenderScript运行之前,必要的Allocation要分配好,它们可能是定点坐标,可能是纹理,也可能是用户的数据
Constants_t *g_Constants;
rs_program_store g_PFSBackground;
//float skyOffsetX;
//float skyOffsetY;
static float g_DT;
static int64_t g_LastTime;
typedef struct Drop {
float ampS;
float ampE;
float spread;
float x;
float y;
} Drop_t;
static Drop_t gDrops[10];
static int gMaxDrops;
typedef struct Leaves {
float x;
float y;
float scale;
float angle;
float spin;
float u1;
float u2;
float altitude;
float rippled;
float deltaX;
float deltaY;
int newLeaf;
} Leaves_t;
static Leaves_t gLeavesStore[LEAVES_COUNT];
static Leaves_t* gLeaves[LEAVES_COUNT];
static Leaves_t* gNextLeaves[LEAVES_COUNT];
void initLeaves() {
Leaves_t *leaf = gLeavesStore;
// globals haven't been set at this point yet. We need to find the correct
// function index to call this, we can wait until reflection works
float width = 2; //g_glWidth;
float height = 3.333; //g_glHeight;
int i;
for (i = 0; i < LEAVES_COUNT; i ++) {
gLeaves[i] = leaf;
int sprite = rsRand(LEAVES_TEXTURES_COUNT);
leaf->x = rsRand(-width, width);
leaf->y = rsRand(-height * 0.5f, height * 0.5f);
leaf->scale = rsRand(0.4f, 0.5f);
leaf->angle = rsRand(0.0f, 360.0f);
leaf->spin = degrees(rsRand(-0.02f, 0.02f)) * 0.25f;
leaf->u1 = (float)sprite / (float) LEAVES_TEXTURES_COUNT;
leaf->u2 = (float)(sprite + 1) / (float) LEAVES_TEXTURES_COUNT;
leaf->altitude = -1.0f;
leaf->rippled = 1.0f;
leaf->deltaX = rsRand(-0.01f, 0.01f);
leaf->deltaY = -rsRand(0.036f, 0.044f);
leaf++;
}
}
//一个可选的init()方法,在root()方法调用之前做一些初始化工作,如初始化变量等。
//这个函数运行一次,并且在Renderscript启动时,Renderscript中其他工作被执行之前,该方法会被自动的调用。
void init() {
int ct;
gMaxDrops = 10;
for (ct=0; ct<gMaxDrops; ct++) {
gDrops[ct].ampS = 0;
gDrops[ct].ampE = 0;
gDrops[ct].spread = 1;
}
initLeaves();
g_LastTime = rsUptimeMillis();
g_DT = 0.1f;
}
static void updateDrop(int ct) {
gDrops[ct].spread += 30.f * g_DT;
gDrops[ct].ampE = gDrops[ct].ampS / gDrops[ct].spread;
}
static void drop(int x, int y, float s) {
int ct;
int iMin = 0;
float minAmp = 10000.f;
for (ct = 0; ct < gMaxDrops; ct++) {
if (gDrops[ct].ampE < minAmp) {
iMin = ct;
minAmp = gDrops[ct].ampE;
}
}
gDrops[iMin].ampS = s;
gDrop