Move Fall waveform calculation to vertex shader.
diff --git a/res/raw/fall.rs b/res/raw/fall.rs
index f27e156..e183178 100644
--- a/res/raw/fall.rs
+++ b/res/raw/fall.rs
@@ -26,20 +26,10 @@
float g_DT;
int g_LastTime;
-struct vert_s {
- float x;
- float y;
- float s;
- float t;
-};
-
struct drop_s {
float ampS;
float ampE;
float spread;
- float spread2;
- float invSpread;
- float invSpread2;
float x;
float y;
};
@@ -62,9 +52,7 @@
};
struct Leaves_s gLeavesStore[LEAVES_COUNT];
-
struct Leaves_s* gLeaves[LEAVES_COUNT];
-
struct Leaves_s* gNextLeaves[LEAVES_COUNT];
void init() {
@@ -74,9 +62,6 @@
gDrops[ct].ampS = 0;
gDrops[ct].ampE = 0;
gDrops[ct].spread = 1;
- gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
- gDrops[ct].invSpread = 1 / gDrops[ct].spread;
- gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
}
}
@@ -106,10 +91,7 @@
void updateDrop(int ct) {
gDrops[ct].spread += 30.f * g_DT;
- gDrops[ct].spread2 = gDrops[ct].spread * gDrops[ct].spread;
- gDrops[ct].invSpread = 1 / gDrops[ct].spread;
- gDrops[ct].invSpread2 = gDrops[ct].invSpread * gDrops[ct].invSpread;
- gDrops[ct].ampE = gDrops[ct].ampS * gDrops[ct].invSpread;
+ gDrops[ct].ampE = gDrops[ct].ampS / gDrops[ct].spread;
}
void drop(int x, int y, float s) {
@@ -130,43 +112,18 @@
}
void generateRipples() {
- int width = State->meshWidth;
- int height = State->meshHeight;
- int index = State->rippleIndex;
- float ratio = (float)State->meshWidth / State->glWidth;
- float xShift = State->xOffset * ratio * 2;
-
- float *vertices = loadSimpleMeshVerticesF(NAMED_WaterMesh, 0);
- struct vert_s *v = (struct vert_s *)vertices;
-
- float fw = 1.0f / width;
- float fh = 1.0f / height;
- int x, y, ct;
- for (y=0; y < height; y++) {
- for (x=0; x < width; x++) {
- struct drop_s * d = &gDrops[0];
- float z = 0;
-
- v->s = (float)x * fw;
- v->t = (float)y * fh;
- for (ct = 0; ct < gMaxDrops; ct++) {
- if (d->ampE > 0.01f) {
- float dx = (d->x - xShift) - x;
- float dy = d->y - y;
- float dist2 = dx*dx + dy*dy;
- if (dist2 < d->spread2) {
- float dist = sqrtf(dist2);
- float a = d->ampE * (dist * d->invSpread2);
- a *= sinf(d->spread - dist) * 0.15f;
- v->s += dx * a;
- v->t += dy * a;
- }
- }
- d++;
- }
- v ++;
- }
+ int ct;
+ for (ct = 0; ct < gMaxDrops; ct++) {
+ struct drop_s * d = &gDrops[ct];
+ vecF32_4_t *v = &Constants->Drop01;
+ v += ct;
+ v->x = d->x;
+ v->y = d->y;
+ v->z = d->ampE * 0.12f;
+ v->w = d->spread;
}
+ Constants->Offset.x = State->xOffset;
+
for (ct = 0; ct < gMaxDrops; ct++) {
updateDrop(ct);
}
@@ -336,47 +293,9 @@
void drawRiverbed() {
bindTexture(NAMED_PFBackground, 0, NAMED_TRiverbed);
-
- float matrix[16];
- matrixLoadScale(matrix, 0.5f * 960.0f / 1024.0f, -1.0f * 800.0f / 1024.0f, 1.0f);
- matrixTranslate(matrix, State->xOffset, 0.0f, 0.0f);
- vpLoadTextureMatrix(matrix);
-
drawSimpleMesh(NAMED_WaterMesh);
-
- matrixLoadIdentity(matrix);
- vpLoadTextureMatrix(matrix);
}
-/*
-void drawSky() {
- color(1.0f, 1.0f, 1.0f, 0.5f);
-
- bindProgramFragment(NAMED_PFSky);
- bindProgramFragmentStore(NAMED_PFSLeaf);
- bindTexture(NAMED_PFSky, 0, NAMED_TSky);
-
- float x = skyOffsetX + State->skySpeedX;
- float y = skyOffsetY + State->skySpeedY;
-
- if (x > 1.0f) x = 0.0f;
- if (x < -1.0f) x = 0.0f;
- if (y > 1.0f) y = 0.0f;
-
- skyOffsetX = x;
- skyOffsetY = y;
-
- float matrix[16];
- matrixLoadTranslate(matrix, x + State->xOffset, y, 0.0f);
- vpLoadTextureMatrix(matrix);
-
- drawSimpleMesh(NAMED_WaterMesh);
-
- matrixLoadIdentity(matrix);
- vpLoadTextureMatrix(matrix);
-}
-*/
-
int main(int index) {
// Compute dt in seconds.
int newTime = uptimeMillis();
@@ -404,17 +323,17 @@
genLeafDrop(gLeaves[i], randf(0.3f) + 0.1f);
}
- generateRipples();
- updateSimpleMesh(NAMED_WaterMesh);
-
if (State->rotate) {
float matrix[16];
matrixLoadRotate(matrix, 90.0f, 0.0f, 0.0f, 1.0f);
vpLoadModelMatrix(matrix);
}
+ bindProgramVertex(NAMED_PVWater);
+ generateRipples();
drawRiverbed();
- // drawSky();
+
+ bindProgramVertex(NAMED_PVSky);
drawLeaves();
return 30;
diff --git a/src/com/android/wallpaper/fall/FallRS.java b/src/com/android/wallpaper/fall/FallRS.java
index a10adea..dc86cfb 100644
--- a/src/com/android/wallpaper/fall/FallRS.java
+++ b/src/com/android/wallpaper/fall/FallRS.java
@@ -17,6 +17,7 @@
package com.android.wallpaper.fall;
import android.os.Bundle;
+import android.renderscript.Element;
import android.renderscript.ScriptC;
import android.renderscript.ProgramFragment;
import android.renderscript.ProgramStore;
@@ -28,7 +29,7 @@
import android.renderscript.SimpleMesh;
import android.renderscript.Script;
import static android.renderscript.Sampler.Value.LINEAR;
-import static android.renderscript.Sampler.Value.WRAP;
+import static android.renderscript.Sampler.Value.CLAMP;
import static android.renderscript.ProgramStore.DepthFunc.*;
import static android.renderscript.ProgramStore.BlendDstFunc;
import static android.renderscript.ProgramStore.BlendSrcFunc;
@@ -48,13 +49,14 @@
private static final int MESH_RESOLUTION = 48;
private static final int RSID_STATE = 0;
+ private static final int RSID_CONSTANTS = 1;
+ private static final int RSID_DROP = 2;
private static final int TEXTURES_COUNT = 2;
private static final int RSID_TEXTURE_RIVERBED = 0;
private static final int RSID_TEXTURE_LEAVES = 1;
private static final int RSID_TEXTURE_SKY = 2;
- private static final int RSID_DROP = 2;
static class Defines {
@@ -73,6 +75,7 @@
private ProgramStore mPfsLeaf;
@SuppressWarnings({"FieldCanBeLocal"})
private ProgramVertex mPvSky;
+ private ProgramVertex mPvWater;
private ProgramVertex.MatrixAllocation mPvOrthoAlloc;
@SuppressWarnings({"FieldCanBeLocal"})
private Sampler mSampler;
@@ -83,6 +86,7 @@
private Type mStateType;
private Type mDropType;
private int mMeshWidth;
+ private Allocation mUniformAlloc;
private int mMeshHeight;
@SuppressWarnings({"FieldCanBeLocal"})
@@ -139,16 +143,19 @@
@Override
protected ScriptC createScript() {
+ createMesh();
+ createState();
createProgramVertex();
createProgramFragmentStore();
createProgramFragment();
- createMesh();
- createState();
loadTextures();
+
+
ScriptC.Builder sb = new ScriptC.Builder(mRS);
sb.setType(mStateType, "State", RSID_STATE);
sb.setType(mDropType, "Drop", RSID_DROP);
+ sb.setType(mUniformAlloc.getType(), "Constants", RSID_CONSTANTS);
sb.setScript(mResources, R.raw.fall);
Script.Invokable invokable = sb.addInvokable("initLeaves");
sb.setRoot(true);
@@ -158,6 +165,7 @@
script.setTimeZone(TimeZone.getDefault().getID());
script.bindAllocation(mState, RSID_STATE);
+ script.bindAllocation(mUniformAlloc, RSID_CONSTANTS);
script.bindAllocation(mDropState, RSID_DROP);
invokable.execute();
@@ -166,8 +174,7 @@
}
private void createMesh() {
- SimpleMesh.TriangleMeshBuilder tmb = new SimpleMesh.TriangleMeshBuilder(mRS, 2,
- SimpleMesh.TriangleMeshBuilder.TEXTURE_0);
+ SimpleMesh.TriangleMeshBuilder tmb = new SimpleMesh.TriangleMeshBuilder(mRS, 2, 0);
final int width = mWidth > mHeight ? mHeight : mWidth;
final int height = mWidth > mHeight ? mWidth : mHeight;
@@ -185,11 +192,9 @@
hResolution += 2;
for (int y = 0; y <= hResolution; y++) {
- final float yOffset = y * quadHeight - glHeight / 2.0f - quadHeight;
- final float t = 1.0f - y / (float) hResolution;
+ final float yOffset = (((float)y / hResolution) * 2.f - 1.f) * height / width;
for (int x = 0; x <= wResolution; x++) {
- tmb.setTexture(x / (float) wResolution, t);
- tmb.addVertex(-1.0f + x * quadWidth - quadWidth, yOffset);
+ tmb.addVertex(((float)x / wResolution) * 2.f - 1.f, yOffset);
}
}
@@ -295,8 +300,8 @@
Sampler.Builder sampleBuilder = new Sampler.Builder(mRS);
sampleBuilder.setMin(LINEAR);
sampleBuilder.setMag(LINEAR);
- sampleBuilder.setWrapS(WRAP);
- sampleBuilder.setWrapT(WRAP);
+ sampleBuilder.setWrapS(CLAMP);
+ sampleBuilder.setWrapT(CLAMP);
mSampler = sampleBuilder.create();
ProgramFragment.Builder builder = new ProgramFragment.Builder(mRS);
@@ -337,10 +342,157 @@
mPvOrthoAlloc.setupProjectionNormalized(mWidth, mHeight);
ProgramVertex.Builder builder = new ProgramVertex.Builder(mRS, null, null);
- builder.setTextureMatrixEnable(true);
mPvSky = builder.create();
mPvSky.bindAllocation(mPvOrthoAlloc);
mPvSky.setName("PVSky");
+
+ float dw = 480.f / mMeshWidth;
+ float dh = 800.f / mMeshHeight;
+
+ Element.Builder eb = new Element.Builder(mRS);
+ // Make this an array when we can.
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop01");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop02");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop03");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop04");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop05");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop06");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop07");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop08");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop09");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Drop10");
+ eb.add(Element.createVector(mRS, Element.DataType.FLOAT_32, 4), "Offset");
+ Element e = eb.create();
+
+ mUniformAlloc = Allocation.createSized(mRS, e, 1);
+
+
+ ProgramVertex.ShaderBuilder sb = new ProgramVertex.ShaderBuilder(mRS);
+ String t = new String("void main() {\n" +
+ " vec4 pos;\n" +
+ " pos.x = ATTRIB_position.x;\n" +
+ " pos.y = ATTRIB_position.y;\n" +
+ " pos.z = 0.0;\n" +
+ " pos.w = 1.0;\n" +
+ " gl_Position = pos;\n" +
+
+ // When we resize the texture we will need to tweak this.
+ " varTex0.x = (pos.x + 1.0) * 0.25;\n" +
+ " varTex0.x += UNI_Offset.x * 0.5 * 0.85;\n" +
+ " varTex0.y = (pos.y + 1.6666) * 0.33;\n" +
+ " varTex0.w = 0.0;\n" +
+ " varColor = vec4(1.0, 1.0, 1.0, 1.0);\n" +
+
+ " pos.x += UNI_Offset.x * 2.0;\n" +
+ " pos.x += 1.0;\n" +
+ " pos.y += 1.0;\n" +
+ " pos.x *= 25.0;\n" +
+ " pos.y *= 42.0;\n" +
+
+ " vec2 delta;\n" +
+ " float dist;\n" +
+ " float amp;\n" +
+
+ " delta = UNI_Drop01.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop01.w) { \n" +
+ " amp = UNI_Drop01.z * dist;\n" +
+ " amp /= UNI_Drop01.w * UNI_Drop01.w;\n" +
+ " amp *= sin(UNI_Drop01.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop02.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop02.w) { \n" +
+ " amp = UNI_Drop02.z * dist;\n" +
+ " amp /= UNI_Drop02.w * UNI_Drop02.w;\n" +
+ " amp *= sin(UNI_Drop02.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop03.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop03.w) { \n" +
+ " amp = UNI_Drop03.z * dist;\n" +
+ " amp /= UNI_Drop03.w * UNI_Drop03.w;\n" +
+ " amp *= sin(UNI_Drop03.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop04.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop04.w) { \n" +
+ " amp = UNI_Drop04.z * dist;\n" +
+ " amp /= UNI_Drop04.w * UNI_Drop04.w;\n" +
+ " amp *= sin(UNI_Drop04.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop05.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop05.w) { \n" +
+ " amp = UNI_Drop05.z * dist;\n" +
+ " amp /= UNI_Drop05.w * UNI_Drop05.w;\n" +
+ " amp *= sin(UNI_Drop05.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop06.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop06.w) { \n" +
+ " amp = UNI_Drop06.z * dist;\n" +
+ " amp /= UNI_Drop06.w * UNI_Drop06.w;\n" +
+ " amp *= sin(UNI_Drop06.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop07.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop07.w) { \n" +
+ " amp = UNI_Drop07.z * dist;\n" +
+ " amp /= UNI_Drop07.w * UNI_Drop07.w;\n" +
+ " amp *= sin(UNI_Drop07.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop08.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop08.w) { \n" +
+ " amp = UNI_Drop08.z * dist;\n" +
+ " amp /= UNI_Drop08.w * UNI_Drop08.w;\n" +
+ " amp *= sin(UNI_Drop08.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop09.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop09.w) { \n" +
+ " amp = UNI_Drop09.z * dist;\n" +
+ " amp /= UNI_Drop09.w * UNI_Drop09.w;\n" +
+ " amp *= sin(UNI_Drop09.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+ " delta = UNI_Drop10.xy - pos.xy;\n" +
+ " dist = length(delta);\n" +
+ " if (dist < UNI_Drop10.w) { \n" +
+ " amp = UNI_Drop10.z * dist;\n" +
+ " amp /= UNI_Drop10.w * UNI_Drop10.w;\n" +
+ " amp *= sin(UNI_Drop10.w - dist);\n" +
+ " varTex0.xy += delta * amp;\n" +
+ " }\n" +
+
+
+ "}\n");
+ sb.setShader(t);
+ sb.addConstant(mUniformAlloc.getType());
+ sb.addInput(mMesh.getVertexType(0).getElement());
+ mPvWater = sb.create();
+ mPvWater.bindAllocation(mPvOrthoAlloc);
+ mPvWater.setName("PVWater");
+ mPvWater.bindConstants(mUniformAlloc, 1);
+
}
void addDrop(float x, float y) {