Here's a direct question: how do we make your CheapWater into a glsl shader? Or to start with a smaller question: is that in the vertex shader (I would think so) or in the fragment one?
class CheapWater {
private World world;
private FrameBuffer buffer;
protected Object3D water;
private WaterController wc = null;
private Time waterTime;
public CheapWater(World world, FrameBuffer buffer) throws Exception {
Config.glForceEnvMapToSecondStage = true;
Config.glUseVBO = true;
this.world = world;
this.buffer = buffer;
waterTime = new Time();
TextureManager tm = TextureManager.getInstance();
tm.addTexture("water", new Texture("water3.jpg"));
tm.addTexture("envmap", new Texture("environment.jpg"));
water = Primitives.getPlane(40, 1000);
TextureInfo ti = new TextureInfo(tm.getTextureID("water"));
ti.add(tm.getTextureID("envmap"), TextureInfo.MODE_MODULATE);
wc = new WaterController(water, 15, 5, false);
water.setTexture(ti);
water.setEnvmapped(Object3D.ENVMAP_ENABLED);
water.rotateX((float) Math.PI / -2f);
water.rotateMesh();
water.clearRotation();
water.build();
water.compile(true);
water.setTransparency(2);
water.getMesh().setVertexController(wc, false);
water.setTextureMatrix(new Matrix());
water.translate(0, -56f, 0);//WHY IS -18 DOWN INSTEAD OF UP?
}
public void perform() throws Exception {
wc.update((float)waterTime.deltaTime());
water.getMesh().applyVertexController();
}
private static class WaterController extends GenericVertexController {
private float scale = 0;
private float damping = 0;
private SimpleVector[] preCalcNormals = null;
private SimpleVector[] preCalcNormalsNeg = null;
private float[] lastHeight = null;
private static final long serialVersionUID = 1L;
private float degreeAdd = 0;
private Object3D water = null;
private float lastUpdate = 0;
private boolean realNormals = false;
public WaterController(Object3D water, float waveScale, float damping, boolean realNormals) {
this.scale = waveScale;
this.water = water;
this.realNormals = realNormals;
this.damping = damping;
water.setTextureMatrix(new Matrix());
}
/**
* This calculates some normals...these are rather fake and in no way
* comparable to real surface normals. But they should do the trick...
*/
public boolean setup() {
SimpleVector ax = new SimpleVector(-1, 0, 1).normalize();
preCalcNormals = new SimpleVector[(int) (100f * scale)];
preCalcNormalsNeg = new SimpleVector[(int) (100f * scale)];
int end = preCalcNormals.length;
for (int i = 0; i < end; i++) {
float height = -1f + (((float) i) / (end / 2f));
SimpleVector n = new SimpleVector(0, -1, 0);
SimpleVector n2 = new SimpleVector(0, -1, 0);
Matrix m = new Matrix();
Matrix m2 = new Matrix();
if (height <= 0) {
float val = (float) Math.sqrt((height + 1) * (Math.PI / 7f));
m.rotateAxis(ax, val);
m2.rotateAxis(ax, -val);
} else {
float val = (float) Math.sqrt((1 - height) * (Math.PI / 7f));
m.rotateAxis(ax, val);
m2.rotateAxis(ax, -val);
}
n.rotate(m);
n2.rotate(m);
preCalcNormals[i] = n;
preCalcNormalsNeg[i] = n2;
}
SimpleVector[] source = this.getSourceMesh();
lastHeight = new float[source.length];
for (int i = 0; i < source.length; i++)
lastHeight[i] = 0;
return true;
}
public void update(float inc) {
degreeAdd += inc;
lastUpdate = inc;
}
public void apply() {
SimpleVector[] source = this.getSourceMesh();
SimpleVector[] destination = this.getDestinationMesh();
SimpleVector[] destNormals = this.getDestinationNormals();
int end = source.length;
int nEnd = preCalcNormals.length;
for (int i = 0; i < end; i++) {
SimpleVector sourceVector = source[i];
SimpleVector destinationVector = destination[i];
float sin = (float) Math.sin((degreeAdd + sourceVector.x + sourceVector.z) / damping);
destinationVector.set(sourceVector.x, sourceVector.y + sin * scale, sourceVector.z);
int iHeight = (int) ((sin + 1) * (nEnd / 2));
if (lastHeight[i] > sin) {
destNormals[i].set(preCalcNormalsNeg[iHeight]);
}
else destNormals[i].set(preCalcNormals[iHeight]);
lastHeight[i] = sin;
}
water.touch();
if (realNormals)
water.calcNormals();
float tr = lastUpdate / 333f;
water.getTextureMatrix().translate(tr, -tr, 0);
}
}
}