/*
* This file is part of the Haven & Hearth game client.
* Copyright (C) 2009 Fredrik Tolf <fredrik@dolda2000.com>, and
* Björn Johannessen <johannessen.bjorn@gmail.com>
*
* Redistribution and/or modification of this file is subject to the
* terms of the GNU Lesser General Public License, version 3, as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* Other parts of this source tree adhere to other copying
* rights. Please see the file `COPYING' in the root directory of the
* source tree for details.
*
* A copy the GNU Lesser General Public License is distributed along
* with the source tree of which this file is a part in the file
* `doc/LPGL-3'. If it is missing for any reason, please see the Free
* Software Foundation's website at <http://www.fsf.org/>, or write
* to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307 USA
*/
package haven;
import java.util.*;
import javax.media.opengl.*;
import haven.glsl.*;
import static haven.glsl.Cons.*;
import static haven.glsl.Function.PDir.*;
import static haven.glsl.Type.*;
public class CloudShadow extends GLState {
public static final Slot<CloudShadow> slot = new Slot<CloudShadow>(Slot.Type.DRAW, CloudShadow.class, Light.lighting);
public final TexGL tex;
public DirLight light;
public Coord3f vel;
public float scale;
public float a = 0.5f, w = 1.0f, t = 0.4f, s = 1.0f;
public CloudShadow(TexGL tex, DirLight light, Coord3f vel, float scale) {
this.tex = tex;
this.light = light;
this.vel = vel;
this.scale = scale;
}
public static final Uniform tsky = new Uniform(SAMPLER2D);
public static final Uniform cdir = new Uniform(VEC2);
public static final Uniform cvel = new Uniform(VEC2);
public static final Uniform cscl = new Uniform(FLOAT);
public static final Uniform cthr = new Uniform(VEC4);
private static final ShaderMacro[] shaders = {
new ShaderMacro() {
public void modify(ProgramContext prog) {
final Phong ph = prog.getmod(Phong.class);
if((ph == null) || !ph.pfrag)
return;
final ValBlock.Value shval = prog.fctx.uniform.new Value(FLOAT) {
public Expression root() {
Expression tc = add(mul(add(pick(MiscLib.fragmapv.ref(), "xy"),
mul(pick(MiscLib.fragmapv.ref(), "z"), cdir.ref())),
cscl.ref()), mul(cvel.ref(), MiscLib.globtime.ref()));
Expression cl = pick(texture2D(tsky.ref(), tc), "r");
Expression th = cthr.ref();
return(add(mul(smoothstep(pick(th, "x"), pick(th, "y"), cl), pick(th, "w")), pick(th, "z")));
}
protected void cons2(Block blk) {
var = new Variable.Global(FLOAT);
blk.add(ass(var, init));
}
};
shval.force();
ph.dolight.mod(new Runnable() {
public void run() {
ph.dolight.dcalc.add(new If(eq(MapView.amblight.ref(), ph.dolight.i),
stmt(amul(ph.dolight.dl.var.ref(), shval.ref()))),
ph.dolight.dcurs);
}
}, 0);
}
}
};
public ShaderMacro[] shaders() {return(shaders);}
public boolean reqshaders() {return(true);}
private TexUnit sampler;
public void reapply(GOut g) {
int u = g.st.prog.cuniform(tsky);
if(u >= 0) {
g.gl.glUniform1i(u, sampler.id);
float zf = 1.0f / (light.dir[2] + 1.1f);
float xd = -light.dir[0] * zf, yd = -light.dir[1] * zf;
g.gl.glUniform2f(g.st.prog.uniform(cdir), xd, yd);
g.gl.glUniform2f(g.st.prog.uniform(cvel), vel.x, vel.y);
g.gl.glUniform1f(g.st.prog.uniform(cscl), scale);
float lthr = a * (1 - w);
g.gl.glUniform4f(g.st.prog.uniform(cthr), lthr, lthr + w, t, s - t);
}
}
public void apply(GOut g) {
sampler = TexGL.lbind(g, tex);
reapply(g);
}
public void unapply(GOut g) {
sampler.act();
g.gl.glBindTexture(GL.GL_TEXTURE_2D, 0);
sampler.free(); sampler = null;
}
public void prep(Buffer buf) {
buf.put(slot, this);
}
}