I have made an update to the code mainly to improve the below sea level view. The idea is to use the refraction camera below sea level instead of the reflection camera (caused weird effects when there were objects above sea level).
It also fixes a small issue with the refraction when objects are partially submerged in water for the surface view (could see some black colored refractions close to the object when waves move the water above the xz-plane).
I’ll just post the necessary changes here since i have not taught myself how to update github etc.
[java]
public class TestProjectedGridWithProjectedWater extends SimpleApplication {
…
// new object declarations
private WaterHeightGenerator waterHeightGenerator;
private Material gridMaterial;
// Modification to simpleInitApp()
@Override
public void simpleInitApp() {
...
waterHeightGenerator = new WaterHeightGenerator();
grid = new MyProjectedGrid(timer, cam, 100, 70, 0.02f, waterHeightGenerator);
projectedGridGeometry = new Geometry("Projected Grid", grid); // create cube geometry from the shape
projectedGridGeometry.setCullHint(CullHint.Never);
gridMaterial = setWaterProcessor();
projectedGridGeometry.setMaterial(gridMaterial);
projectedGridGeometry.setLocalTranslation(0, 0, 0);
rootNode.attachChild(projectedGridGeometry);
@Override
public void simpleUpdate(float tpf) {
//Determine if camera is above or below sea level
if (cam.getLocation().y > waterHeightGenerator.getHeight(cam.getLocation().x, cam.getLocation().z, timer.getTimeInSeconds())) {
gridMaterial.setBoolean("abovewater", true);
} else {
gridMaterial.setBoolean("abovewater", false);
}[/java]
[java]
public class ProjectedWaterProcessorWithRefraction implements SceneProcessor {
…
public class RefractionProcessor implements SceneProcessor {
…
public void preFrame(float tpf) {
// Commented line to be able to look up from the water using refractionCam.
// Line also caused some weird artifacts in surface view on objects partially submerged in water.
//refractionCam.setClipPlane(refractionClipPlane, Plane.Side.Negative);//,-1
}[/java]
projectedwatershader_refraction.frag:
[java]
void main()
{
…
projCoordDepth += (vnormal + dudvColor.xy * 0.5 + normalVector.xy * 0.2);
projCoordDepth = clamp(projCoordDepth, 0.001, 0.999);
//Calculation of refractionColor moved here to be able to use it both above and below water
vec4 refractionColor = texture2D(m_refraction, projCoordDepth);
float depth = texture2D(m_depthMap, projCoordDepth).r;
depth = pow(depth,15.0);
float invDepth = 1.0-depth;
vec4 reflectionColor = texture2D(m_reflection, projCoord);
if ( m_abovewater == false ) {
//Use refractionColor instead of reflectionColor below water
vec4 endColor = mix(refractionColor,m_waterColor,fresnelTerm);
gl_FragColor = mix(endColor,m_waterColor,fogDist);
}
else {
vec4 waterColorNew = mix(m_waterColor,m_waterColorEnd,fresnelTerm);
vec4 endColor = mix(waterColorNew,reflectionColor,fresnelTerm);
float foamVal = (vVertex.y-vVertex.w) / (m_amplitude * 2.0);
foamVal = clamp(foamVal,0.0,1.0);
vec4 foamTex = texture2D(m_foamMap, foamCoords + vnormal * 0.6 + normalVector.xy * 0.05 );
float normLength = length(vnormal*5.0);
foamVal *= 1.0-normLength;
foamVal *= foamTex.a;
endColor = mix(endColor,foamTex,clamp(foamVal,0.0,0.95));
//Code moved before the if statement
//vec4 refractionColor = texture2D(m_refraction, projCoordDepth);
//float depth = texture2D(m_depthMap, projCoordDepth).r;
//depth = pow(depth,15.0);
//float invDepth = 1.0-depth;
endColor = refractionColor*vec4(invDepth*fresnel) + endColor*vec4(depth*fresnel);
if( m_useFadeToFogColor == false) {
gl_FragColor = endColor + reflectionColor * vec4(fresnelTerm);
} else {
gl_FragColor = (endColor + reflectionColor * vec4(fresnelTerm)) * (1.0-fogDist) + gl_Fog.color * fogDist;
}
}[/java]