1 /* 2 * Copyright (c) 2009-2012 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.water; 33 34 import com.jme3.asset.AssetManager; 35 import com.jme3.export.InputCapsule; 36 import com.jme3.export.JmeExporter; 37 import com.jme3.export.JmeImporter; 38 import com.jme3.export.OutputCapsule; 39 import com.jme3.light.DirectionalLight; 40 import com.jme3.light.Light; 41 import com.jme3.material.Material; 42 import com.jme3.math.*; 43 import com.jme3.post.Filter; 44 import com.jme3.post.Filter.Pass; 45 import com.jme3.renderer.Camera; 46 import com.jme3.renderer.RenderManager; 47 import com.jme3.renderer.ViewPort; 48 import com.jme3.scene.Node; 49 import com.jme3.scene.Spatial; 50 import com.jme3.texture.Image.Format; 51 import com.jme3.texture.Texture.WrapMode; 52 import com.jme3.texture.Texture2D; 53 import com.jme3.util.TempVars; 54 import java.io.IOException; 55 56 /** 57 * The WaterFilter is a 2D post process that simulate water. 58 * It renders water above and under water. 59 * See this blog post for more info <a href="http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/">http://jmonkeyengine.org/2011/01/15/new-advanced-water-effect-for-jmonkeyengine-3/</a> 60 * 61 * 62 * @author Rmy Bouquet aka Nehon 63 */ 64 public class WaterFilter extends Filter { 65 66 private Pass reflectionPass; 67 protected Spatial reflectionScene; 68 protected ViewPort reflectionView; 69 private Texture2D normalTexture; 70 private Texture2D foamTexture; 71 private Texture2D causticsTexture; 72 private Texture2D heightTexture; 73 private Plane plane; 74 private Camera reflectionCam; 75 protected Ray ray = new Ray(); 76 private Vector3f targetLocation = new Vector3f(); 77 private ReflectionProcessor reflectionProcessor; 78 private Matrix4f biasMatrix = new Matrix4f(0.5f, 0.0f, 0.0f, 0.5f, 79 0.0f, 0.5f, 0.0f, 0.5f, 80 0.0f, 0.0f, 0.0f, 0.5f, 81 0.0f, 0.0f, 0.0f, 1.0f); 82 private Matrix4f textureProjMatrix = new Matrix4f(); 83 private boolean underWater; 84 private RenderManager renderManager; 85 private ViewPort viewPort; 86 private float time = 0; 87 //properties 88 private float speed = 1; 89 private Vector3f lightDirection = new Vector3f(0, -1, 0); 90 private ColorRGBA lightColor = ColorRGBA.White; 91 private float waterHeight = 0.0f; 92 private ColorRGBA waterColor = new ColorRGBA(0.0078f, 0.3176f, 0.5f, 1.0f); 93 private ColorRGBA deepWaterColor = new ColorRGBA(0.0039f, 0.00196f, 0.145f, 1.0f); 94 private Vector3f colorExtinction = new Vector3f(5.0f, 20.0f, 30.0f); 95 private float waterTransparency = 0.1f; 96 private float maxAmplitude = 1.5f; 97 private float shoreHardness = 0.1f; 98 private boolean useFoam = true; 99 private float foamIntensity = 0.5f; 100 private float foamHardness = 1.0f; 101 private Vector3f foamExistence = new Vector3f(0.45f, 4.35f, 1.5f); 102 private float waveScale = 0.005f; 103 private float sunScale = 3.0f; 104 private float shininess = 0.7f; 105 private Vector2f windDirection = new Vector2f(0.0f, -1.0f); 106 private int reflectionMapSize = 512; 107 private boolean useRipples = true; 108 private float normalScale = 3.0f; 109 private boolean useHQShoreline = true; 110 private boolean useSpecular = true; 111 private boolean useRefraction = true; 112 private float refractionStrength = 0.0f; 113 private float refractionConstant = 0.5f; 114 private float reflectionDisplace = 30; 115 private float underWaterFogDistance = 120; 116 private boolean useCaustics = true; 117 private float causticsIntensity = 0.5f; 118 119 /** 120 * Create a Water Filter 121 */ 122 public WaterFilter() { 123 super("WaterFilter"); 124 } 125 126 public WaterFilter(Node reflectionScene, Vector3f lightDirection) { 127 super("WaterFilter"); 128 this.reflectionScene = reflectionScene; 129 this.lightDirection = lightDirection; 130 } 131 132 @Override 133 protected boolean isRequiresDepthTexture() { 134 return true; 135 } 136 137 @Override 138 protected void preFrame(float tpf) { 139 time = time + (tpf * speed); 140 material.setFloat("Time", time); 141 Camera sceneCam = viewPort.getCamera(); 142 biasMatrix.mult(sceneCam.getViewProjectionMatrix(), textureProjMatrix); 143 material.setMatrix4("TextureProjMatrix", textureProjMatrix); 144 material.setVector3("CameraPosition", sceneCam.getLocation()); 145 material.setMatrix4("ViewProjectionMatrixInverse", sceneCam.getViewProjectionMatrix().invert()); 146 147 material.setFloat("WaterHeight", waterHeight); 148 149 //update reflection cam 150 ray.setOrigin(sceneCam.getLocation()); 151 ray.setDirection(sceneCam.getDirection()); 152 plane = new Plane(Vector3f.UNIT_Y, new Vector3f(0, waterHeight, 0).dot(Vector3f.UNIT_Y)); 153 reflectionProcessor.setReflectionClipPlane(plane); 154 boolean inv = false; 155 if (!ray.intersectsWherePlane(plane, targetLocation)) { 156 ray.setDirection(ray.getDirection().negateLocal()); 157 ray.intersectsWherePlane(plane, targetLocation); 158 inv = true; 159 } 160 Vector3f loc = plane.reflect(sceneCam.getLocation(), new Vector3f()); 161 reflectionCam.setLocation(loc); 162 reflectionCam.setFrustum(sceneCam.getFrustumNear(), 163 sceneCam.getFrustumFar(), 164 sceneCam.getFrustumLeft(), 165 sceneCam.getFrustumRight(), 166 sceneCam.getFrustumTop(), 167 sceneCam.getFrustumBottom()); 168 TempVars vars = TempVars.get(); 169 170 171 vars.vect1.set(sceneCam.getLocation()).addLocal(sceneCam.getUp()); 172 float planeDistance = plane.pseudoDistance(vars.vect1); 173 vars.vect2.set(plane.getNormal()).multLocal(planeDistance * 2.0f); 174 vars.vect3.set(vars.vect1.subtractLocal(vars.vect2)).subtractLocal(loc).normalizeLocal().negateLocal(); 175 176 reflectionCam.lookAt(targetLocation, vars.vect3); 177 vars.release(); 178 179 if (inv) { 180 reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal()); 181 } 182 183 //if we're under water no need to compute reflection 184 if (sceneCam.getLocation().y >= waterHeight) { 185 boolean rtb = true; 186 if (!renderManager.isHandleTranslucentBucket()) { 187 renderManager.setHandleTranslucentBucket(true); 188 rtb = false; 189 } 190 renderManager.renderViewPort(reflectionView, tpf); 191 if (!rtb) { 192 renderManager.setHandleTranslucentBucket(false); 193 } 194 renderManager.setCamera(sceneCam, false); 195 renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); 196 197 198 underWater = false; 199 } else { 200 underWater = true; 201 } 202 } 203 204 @Override 205 protected Material getMaterial() { 206 return material; 207 } 208 209 private DirectionalLight findLight(Node node) { 210 for (Light light : node.getWorldLightList()) { 211 if (light instanceof DirectionalLight) { 212 return (DirectionalLight) light; 213 } 214 } 215 for (Spatial child : node.getChildren()) { 216 if (child instanceof Node) { 217 return findLight((Node) child); 218 } 219 } 220 221 return null; 222 } 223 224 @Override 225 protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { 226 227 if (reflectionScene == null) { 228 reflectionScene = vp.getScenes().get(0); 229 DirectionalLight l = findLight((Node) reflectionScene); 230 if (l != null) { 231 lightDirection = l.getDirection(); 232 } 233 234 } 235 236 this.renderManager = renderManager; 237 this.viewPort = vp; 238 reflectionPass = new Pass(); 239 reflectionPass.init(renderManager.getRenderer(), reflectionMapSize, reflectionMapSize, Format.RGBA8, Format.Depth); 240 reflectionCam = new Camera(reflectionMapSize, reflectionMapSize); 241 reflectionView = new ViewPort("reflectionView", reflectionCam); 242 reflectionView.setClearFlags(true, true, true); 243 reflectionView.attachScene(reflectionScene); 244 reflectionView.setOutputFrameBuffer(reflectionPass.getRenderFrameBuffer()); 245 plane = new Plane(Vector3f.UNIT_Y, new Vector3f(0, waterHeight, 0).dot(Vector3f.UNIT_Y)); 246 reflectionProcessor = new ReflectionProcessor(reflectionCam, reflectionPass.getRenderFrameBuffer(), plane); 247 reflectionView.addProcessor(reflectionProcessor); 248 249 normalTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/water_normalmap.dds"); 250 if (foamTexture == null) { 251 foamTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"); 252 } 253 if (causticsTexture == null) { 254 causticsTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/caustics.jpg"); 255 } 256 heightTexture = (Texture2D) manager.loadTexture("Common/MatDefs/Water/Textures/heightmap.jpg"); 257 258 normalTexture.setWrap(WrapMode.Repeat); 259 foamTexture.setWrap(WrapMode.Repeat); 260 causticsTexture.setWrap(WrapMode.Repeat); 261 heightTexture.setWrap(WrapMode.Repeat); 262 263 material = new Material(manager, "Common/MatDefs/Water/Water.j3md"); 264 material.setTexture("HeightMap", heightTexture); 265 material.setTexture("CausticsMap", causticsTexture); 266 material.setTexture("FoamMap", foamTexture); 267 material.setTexture("NormalMap", normalTexture); 268 material.setTexture("ReflectionMap", reflectionPass.getRenderedTexture()); 269 270 material.setFloat("WaterTransparency", waterTransparency); 271 material.setFloat("NormalScale", normalScale); 272 material.setFloat("R0", refractionConstant); 273 material.setFloat("MaxAmplitude", maxAmplitude); 274 material.setVector3("LightDir", lightDirection); 275 material.setColor("LightColor", lightColor); 276 material.setFloat("ShoreHardness", shoreHardness); 277 material.setFloat("RefractionStrength", refractionStrength); 278 material.setFloat("WaveScale", waveScale); 279 material.setVector3("FoamExistence", foamExistence); 280 material.setFloat("SunScale", sunScale); 281 material.setVector3("ColorExtinction", colorExtinction); 282 material.setFloat("Shininess", shininess); 283 material.setColor("WaterColor", waterColor); 284 material.setColor("DeepWaterColor", deepWaterColor); 285 material.setVector2("WindDirection", windDirection); 286 material.setFloat("FoamHardness", foamHardness); 287 material.setBoolean("UseRipples", useRipples); 288 material.setBoolean("UseHQShoreline", useHQShoreline); 289 material.setBoolean("UseSpecular", useSpecular); 290 material.setBoolean("UseFoam", useFoam); 291 material.setBoolean("UseCaustics", useCaustics); 292 material.setBoolean("UseRefraction", useRefraction); 293 material.setFloat("ReflectionDisplace", reflectionDisplace); 294 material.setFloat("FoamIntensity", foamIntensity); 295 material.setFloat("UnderWaterFogDistance", underWaterFogDistance); 296 material.setFloat("CausticsIntensity", causticsIntensity); 297 298 299 } 300 301 @Override 302 public void write(JmeExporter ex) throws IOException { 303 super.write(ex); 304 OutputCapsule oc = ex.getCapsule(this); 305 306 oc.write(speed, "speed", 1f); 307 oc.write(lightDirection, "lightDirection", new Vector3f(0, -1, 0)); 308 oc.write(lightColor, "lightColor", ColorRGBA.White); 309 oc.write(waterHeight, "waterHeight", 0.0f); 310 oc.write(waterColor, "waterColor", new ColorRGBA(0.0078f, 0.3176f, 0.5f, 1.0f)); 311 oc.write(deepWaterColor, "deepWaterColor", new ColorRGBA(0.0039f, 0.00196f, 0.145f, 1.0f)); 312 313 oc.write(colorExtinction, "colorExtinction", new Vector3f(5.0f, 20.0f, 30.0f)); 314 oc.write(waterTransparency, "waterTransparency", 0.1f); 315 oc.write(maxAmplitude, "maxAmplitude", 1.5f); 316 oc.write(shoreHardness, "shoreHardness", 0.1f); 317 oc.write(useFoam, "useFoam", true); 318 319 oc.write(foamIntensity, "foamIntensity", 0.5f); 320 oc.write(foamHardness, "foamHardness", 1.0f); 321 322 oc.write(foamExistence, "foamExistence", new Vector3f(0.45f, 4.35f, 1.5f)); 323 oc.write(waveScale, "waveScale", 0.005f); 324 325 oc.write(sunScale, "sunScale", 3.0f); 326 oc.write(shininess, "shininess", 0.7f); 327 oc.write(windDirection, "windDirection", new Vector2f(0.0f, -1.0f)); 328 oc.write(reflectionMapSize, "reflectionMapSize", 512); 329 oc.write(useRipples, "useRipples", true); 330 331 oc.write(normalScale, "normalScale", 3.0f); 332 oc.write(useHQShoreline, "useHQShoreline", true); 333 334 oc.write(useSpecular, "useSpecular", true); 335 336 oc.write(useRefraction, "useRefraction", true); 337 oc.write(refractionStrength, "refractionStrength", 0.0f); 338 oc.write(refractionConstant, "refractionConstant", 0.5f); 339 oc.write(reflectionDisplace, "reflectionDisplace", 30f); 340 oc.write(underWaterFogDistance, "underWaterFogDistance", 120f); 341 oc.write(causticsIntensity, "causticsIntensity", 0.5f); 342 343 oc.write(useCaustics, "useCaustics", true); 344 } 345 346 @Override 347 public void read(JmeImporter im) throws IOException { 348 super.read(im); 349 InputCapsule ic = im.getCapsule(this); 350 speed = ic.readFloat("speed", 1f); 351 lightDirection = (Vector3f) ic.readSavable("lightDirection", new Vector3f(0, -1, 0)); 352 lightColor = (ColorRGBA) ic.readSavable("lightColor", ColorRGBA.White); 353 waterHeight = ic.readFloat("waterHeight", 0.0f); 354 waterColor = (ColorRGBA) ic.readSavable("waterColor", new ColorRGBA(0.0078f, 0.3176f, 0.5f, 1.0f)); 355 deepWaterColor = (ColorRGBA) ic.readSavable("deepWaterColor", new ColorRGBA(0.0039f, 0.00196f, 0.145f, 1.0f)); 356 357 colorExtinction = (Vector3f) ic.readSavable("colorExtinction", new Vector3f(5.0f, 20.0f, 30.0f)); 358 waterTransparency = ic.readFloat("waterTransparency", 0.1f); 359 maxAmplitude = ic.readFloat("maxAmplitude", 1.5f); 360 shoreHardness = ic.readFloat("shoreHardness", 0.1f); 361 useFoam = ic.readBoolean("useFoam", true); 362 363 foamIntensity = ic.readFloat("foamIntensity", 0.5f); 364 foamHardness = ic.readFloat("foamHardness", 1.0f); 365 366 foamExistence = (Vector3f) ic.readSavable("foamExistence", new Vector3f(0.45f, 4.35f, 1.5f)); 367 waveScale = ic.readFloat("waveScale", 0.005f); 368 369 sunScale = ic.readFloat("sunScale", 3.0f); 370 shininess = ic.readFloat("shininess", 0.7f); 371 windDirection = (Vector2f) ic.readSavable("windDirection", new Vector2f(0.0f, -1.0f)); 372 reflectionMapSize = ic.readInt("reflectionMapSize", 512); 373 useRipples = ic.readBoolean("useRipples", true); 374 375 normalScale = ic.readFloat("normalScale", 3.0f); 376 useHQShoreline = ic.readBoolean("useHQShoreline", true); 377 378 useSpecular = ic.readBoolean("useSpecular", true); 379 380 useRefraction = ic.readBoolean("useRefraction", true); 381 refractionStrength = ic.readFloat("refractionStrength", 0.0f); 382 refractionConstant = ic.readFloat("refractionConstant", 0.5f); 383 reflectionDisplace = ic.readFloat("reflectionDisplace", 30f); 384 underWaterFogDistance = ic.readFloat("underWaterFogDistance", 120f); 385 causticsIntensity = ic.readFloat("causticsIntensity", 0.5f); 386 387 useCaustics = ic.readBoolean("useCaustics", true); 388 389 } 390 391 /** 392 * gets the height of the water plane 393 * @return 394 */ 395 public float getWaterHeight() { 396 return waterHeight; 397 } 398 399 /** 400 * Sets the height of the water plane 401 * default is 0.0 402 * @param waterHeight 403 */ 404 public void setWaterHeight(float waterHeight) { 405 this.waterHeight = waterHeight; 406 } 407 408 /** 409 * sets the scene to render in the reflection map 410 * @param reflectionScene 411 */ 412 public void setReflectionScene(Spatial reflectionScene) { 413 this.reflectionScene = reflectionScene; 414 } 415 416 /** 417 * returns the waterTransparency value 418 * @return 419 */ 420 public float getWaterTransparency() { 421 return waterTransparency; 422 } 423 424 /** 425 * Sets how fast will colours fade out. You can also think about this 426 * values as how clear water is. Therefore use smaller values (eg. 0.05) 427 * to have crystal clear water and bigger to achieve "muddy" water. 428 * default is 0.1f 429 * @param waterTransparency 430 */ 431 public void setWaterTransparency(float waterTransparency) { 432 this.waterTransparency = waterTransparency; 433 if (material != null) { 434 material.setFloat("WaterTransparency", waterTransparency); 435 } 436 } 437 438 /** 439 * Returns the normal scales applied to the normal map 440 * @return 441 */ 442 public float getNormalScale() { 443 return normalScale; 444 } 445 446 /** 447 * Sets the normal scaling factors to apply to the normal map. 448 * the higher the value the more small ripples will be visible on the waves. 449 * default is 1.0 450 * @param normalScale 451 */ 452 public void setNormalScale(float normalScale) { 453 this.normalScale = normalScale; 454 if (material != null) { 455 material.setFloat("NormalScale", normalScale); 456 } 457 } 458 459 /** 460 * returns the refractoin constant 461 * @return 462 */ 463 public float getRefractionConstant() { 464 return refractionConstant; 465 } 466 467 /** 468 * This is a constant related to the index of refraction (IOR) used to compute the fresnel term. 469 * F = R0 + (1-R0)( 1 - N.V)^5 470 * where F is the fresnel term, R0 the constant, N the normal vector and V tne view vector. 471 * It usually depend on the material you are lookinh through (here water). 472 * Default value is 0.3f 473 * In practice, the lowest the value and the less the reflection can be seen on water 474 * @param refractionConstant 475 */ 476 public void setRefractionConstant(float refractionConstant) { 477 this.refractionConstant = refractionConstant; 478 if (material != null) { 479 material.setFloat("R0", refractionConstant); 480 } 481 } 482 483 /** 484 * return the maximum wave amplitude 485 * @return 486 */ 487 public float getMaxAmplitude() { 488 return maxAmplitude; 489 } 490 491 /** 492 * Sets the maximum waves amplitude 493 * default is 1.0 494 * @param maxAmplitude 495 */ 496 public void setMaxAmplitude(float maxAmplitude) { 497 this.maxAmplitude = maxAmplitude; 498 if (material != null) { 499 material.setFloat("MaxAmplitude", maxAmplitude); 500 } 501 } 502 503 /** 504 * gets the light direction 505 * @return 506 */ 507 public Vector3f getLightDirection() { 508 return lightDirection; 509 } 510 511 /** 512 * Sets the light direction 513 * @param lightDirection 514 */ 515 public void setLightDirection(Vector3f lightDirection) { 516 this.lightDirection = lightDirection; 517 if (material != null) { 518 material.setVector3("LightDir", lightDirection); 519 } 520 } 521 522 /** 523 * returns the light color 524 * @return 525 */ 526 public ColorRGBA getLightColor() { 527 return lightColor; 528 } 529 530 /** 531 * Sets the light color to use 532 * default is white 533 * @param lightColor 534 */ 535 public void setLightColor(ColorRGBA lightColor) { 536 this.lightColor = lightColor; 537 if (material != null) { 538 material.setColor("LightColor", lightColor); 539 } 540 } 541 542 /** 543 * Return the shoreHardeness 544 * @return 545 */ 546 public float getShoreHardness() { 547 return shoreHardness; 548 } 549 550 /** 551 * The smaller this value is, the softer the transition between 552 * shore and water. If you want hard edges use very big value. 553 * Default is 0.1f. 554 * @param shoreHardness 555 */ 556 public void setShoreHardness(float shoreHardness) { 557 this.shoreHardness = shoreHardness; 558 if (material != null) { 559 material.setFloat("ShoreHardness", shoreHardness); 560 } 561 } 562 563 /** 564 * returns the foam hardness 565 * @return 566 */ 567 public float getFoamHardness() { 568 return foamHardness; 569 } 570 571 /** 572 * Sets the foam hardness : How much the foam will blend with the shore to avoid hard edged water plane. 573 * Default is 1.0 574 * @param foamHardness 575 */ 576 public void setFoamHardness(float foamHardness) { 577 this.foamHardness = foamHardness; 578 if (material != null) { 579 material.setFloat("FoamHardness", foamHardness); 580 } 581 } 582 583 /** 584 * returns the refractionStrenght 585 * @return 586 */ 587 public float getRefractionStrength() { 588 return refractionStrength; 589 } 590 591 /** 592 * This value modifies current fresnel term. If you want to weaken 593 * reflections use bigger value. If you want to empasize them use 594 * value smaller then 0. Default is 0.0f. 595 * @param refractionStrength 596 */ 597 public void setRefractionStrength(float refractionStrength) { 598 this.refractionStrength = refractionStrength; 599 if (material != null) { 600 material.setFloat("RefractionStrength", refractionStrength); 601 } 602 } 603 604 /** 605 * returns the scale factor of the waves height map 606 * @return 607 */ 608 public float getWaveScale() { 609 return waveScale; 610 } 611 612 /** 613 * Sets the scale factor of the waves height map 614 * the smaller the value the bigger the waves 615 * default is 0.005f 616 * @param waveScale 617 */ 618 public void setWaveScale(float waveScale) { 619 this.waveScale = waveScale; 620 if (material != null) { 621 material.setFloat("WaveScale", waveScale); 622 } 623 } 624 625 /** 626 * returns the foam existance vector 627 * @return 628 */ 629 public Vector3f getFoamExistence() { 630 return foamExistence; 631 } 632 633 /** 634 * Describes at what depth foam starts to fade out and 635 * at what it is completely invisible. The third value is at 636 * what height foam for waves appear (+ waterHeight). 637 * default is (0.45, 4.35, 1.0); 638 * @param foamExistence 639 */ 640 public void setFoamExistence(Vector3f foamExistence) { 641 this.foamExistence = foamExistence; 642 if (material != null) { 643 material.setVector3("FoamExistence", foamExistence); 644 } 645 } 646 647 /** 648 * gets the scale of the sun 649 * @return 650 */ 651 public float getSunScale() { 652 return sunScale; 653 } 654 655 /** 656 * Sets the scale of the sun for specular effect 657 * @param sunScale 658 */ 659 public void setSunScale(float sunScale) { 660 this.sunScale = sunScale; 661 if (material != null) { 662 material.setFloat("SunScale", sunScale); 663 } 664 } 665 666 /** 667 * Returns the color exctinction vector of the water 668 * @return 669 */ 670 public Vector3f getColorExtinction() { 671 return colorExtinction; 672 } 673 674 /** 675 * Return at what depth the refraction color extinct 676 * the first value is for red 677 * the second is for green 678 * the third is for blue 679 * Play with thos parameters to "trouble" the water 680 * default is (5.0, 20.0, 30.0f); 681 * @param colorExtinction 682 */ 683 public void setColorExtinction(Vector3f colorExtinction) { 684 this.colorExtinction = colorExtinction; 685 if (material != null) { 686 material.setVector3("ColorExtinction", colorExtinction); 687 } 688 } 689 690 /** 691 * Sets the foam texture 692 * @param foamTexture 693 */ 694 public void setFoamTexture(Texture2D foamTexture) { 695 this.foamTexture = foamTexture; 696 foamTexture.setWrap(WrapMode.Repeat); 697 if (material != null) { 698 material.setTexture("FoamMap", foamTexture); 699 } 700 } 701 702 /** 703 * Sets the height texture 704 * @param heightTexture 705 */ 706 public void setHeightTexture(Texture2D heightTexture) { 707 this.heightTexture = heightTexture; 708 heightTexture.setWrap(WrapMode.Repeat); 709 } 710 711 /** 712 * Sets the normal Texture 713 * @param normalTexture 714 */ 715 public void setNormalTexture(Texture2D normalTexture) { 716 this.normalTexture = normalTexture; 717 normalTexture.setWrap(WrapMode.Repeat); 718 } 719 720 /** 721 * return the shininess factor of the water 722 * @return 723 */ 724 public float getShininess() { 725 return shininess; 726 } 727 728 /** 729 * Sets the shinines factor of the water 730 * default is 0.7f 731 * @param shininess 732 */ 733 public void setShininess(float shininess) { 734 this.shininess = shininess; 735 if (material != null) { 736 material.setFloat("Shininess", shininess); 737 } 738 } 739 740 /** 741 * retruns the speed of the waves 742 * @return 743 */ 744 public float getSpeed() { 745 return speed; 746 } 747 748 /** 749 * Set the speed of the waves (0.0 is still) default is 1.0 750 * @param speed 751 */ 752 public void setSpeed(float speed) { 753 this.speed = speed; 754 } 755 756 /** 757 * returns the color of the water 758 * 759 * @return 760 */ 761 public ColorRGBA getWaterColor() { 762 return waterColor; 763 } 764 765 /** 766 * Sets the color of the water 767 * see setDeepWaterColor for deep water color 768 * default is (0.0078f, 0.5176f, 0.5f,1.0f) (greenish blue) 769 * @param waterColor 770 */ 771 public void setWaterColor(ColorRGBA waterColor) { 772 this.waterColor = waterColor; 773 if (material != null) { 774 material.setColor("WaterColor", waterColor); 775 } 776 } 777 778 /** 779 * returns the deep water color 780 * @return 781 */ 782 public ColorRGBA getDeepWaterColor() { 783 return deepWaterColor; 784 } 785 786 /** 787 * sets the deep water color 788 * see setWaterColor for general color 789 * default is (0.0039f, 0.00196f, 0.145f,1.0f) (very dark blue) 790 * @param deepWaterColor 791 */ 792 public void setDeepWaterColor(ColorRGBA deepWaterColor) { 793 this.deepWaterColor = deepWaterColor; 794 if (material != null) { 795 material.setColor("DeepWaterColor", deepWaterColor); 796 } 797 } 798 799 /** 800 * returns the wind direction 801 * @return 802 */ 803 public Vector2f getWindDirection() { 804 return windDirection; 805 } 806 807 /** 808 * sets the wind direction 809 * the direction where the waves move 810 * default is (0.0f, -1.0f) 811 * @param windDirection 812 */ 813 public void setWindDirection(Vector2f windDirection) { 814 this.windDirection = windDirection; 815 if (material != null) { 816 material.setVector2("WindDirection", windDirection); 817 } 818 } 819 820 /** 821 * returns the size of the reflection map 822 * @return 823 */ 824 public int getReflectionMapSize() { 825 return reflectionMapSize; 826 } 827 828 /** 829 * Sets the size of the reflection map 830 * default is 512, the higher, the better quality, but the slower the effect. 831 * @param reflectionMapSize 832 */ 833 public void setReflectionMapSize(int reflectionMapSize) { 834 this.reflectionMapSize = reflectionMapSize; 835 } 836 837 /** 838 * returns true if the water uses foam 839 * @return 840 */ 841 public boolean isUseFoam() { 842 return useFoam; 843 } 844 845 /** 846 * set to true to use foam with water 847 * default true 848 * @param useFoam 849 */ 850 public void setUseFoam(boolean useFoam) { 851 this.useFoam = useFoam; 852 if (material != null) { 853 material.setBoolean("UseFoam", useFoam); 854 } 855 856 } 857 858 /** 859 * sets the texture to use to render caustics on the ground underwater 860 * @param causticsTexture 861 */ 862 public void setCausticsTexture(Texture2D causticsTexture) { 863 this.causticsTexture = causticsTexture; 864 if (material != null) { 865 material.setTexture("causticsMap", causticsTexture); 866 } 867 } 868 869 /** 870 * returns true if caustics are rendered 871 * @return 872 */ 873 public boolean isUseCaustics() { 874 return useCaustics; 875 } 876 877 /** 878 * set to true if you want caustics to be rendered on the ground underwater, false otherwise 879 * @param useCaustics 880 */ 881 public void setUseCaustics(boolean useCaustics) { 882 this.useCaustics = useCaustics; 883 if (material != null) { 884 material.setBoolean("UseCaustics", useCaustics); 885 } 886 } 887 888 /** 889 * return true 890 * @return 891 */ 892 public boolean isUseHQShoreline() { 893 return useHQShoreline; 894 } 895 896 public void setUseHQShoreline(boolean useHQShoreline) { 897 this.useHQShoreline = useHQShoreline; 898 if (material != null) { 899 material.setBoolean("UseHQShoreline", useHQShoreline); 900 } 901 902 } 903 904 /** 905 * returns true if the water use the refraction 906 * @return 907 */ 908 public boolean isUseRefraction() { 909 return useRefraction; 910 } 911 912 /** 913 * set to true to use refraction (default is true) 914 * @param useRefraction 915 */ 916 public void setUseRefraction(boolean useRefraction) { 917 this.useRefraction = useRefraction; 918 if (material != null) { 919 material.setBoolean("UseRefraction", useRefraction); 920 } 921 922 } 923 924 /** 925 * returns true if the ater use ripples 926 * @return 927 */ 928 public boolean isUseRipples() { 929 return useRipples; 930 } 931 932 /** 933 * 934 * Set to true tu use ripples 935 * @param useRipples 936 */ 937 public void setUseRipples(boolean useRipples) { 938 this.useRipples = useRipples; 939 if (material != null) { 940 material.setBoolean("UseRipples", useRipples); 941 } 942 943 } 944 945 /** 946 * returns true if the water use specular 947 * @return 948 */ 949 public boolean isUseSpecular() { 950 return useSpecular; 951 } 952 953 /** 954 * Set to true to use specular lightings on the water 955 * @param useSpecular 956 */ 957 public void setUseSpecular(boolean useSpecular) { 958 this.useSpecular = useSpecular; 959 if (material != null) { 960 material.setBoolean("UseSpecular", useSpecular); 961 } 962 } 963 964 /** 965 * returns the foam intensity 966 * @return 967 */ 968 public float getFoamIntensity() { 969 return foamIntensity; 970 } 971 972 /** 973 * sets the foam intensity default is 0.5f 974 * @param foamIntensity 975 */ 976 public void setFoamIntensity(float foamIntensity) { 977 this.foamIntensity = foamIntensity; 978 if (material != null) { 979 material.setFloat("FoamIntensity", foamIntensity); 980 981 } 982 } 983 984 /** 985 * returns the reflection displace 986 * see {@link setReflectionDisplace(float reflectionDisplace)} 987 * @return 988 */ 989 public float getReflectionDisplace() { 990 return reflectionDisplace; 991 } 992 993 /** 994 * Sets the reflection displace. define how troubled will look the reflection in the water. default is 30 995 * @param reflectionDisplace 996 */ 997 public void setReflectionDisplace(float reflectionDisplace) { 998 this.reflectionDisplace = reflectionDisplace; 999 if (material != null) { 1000 material.setFloat("m_ReflectionDisplace", reflectionDisplace); 1001 } 1002 } 1003 1004 /** 1005 * returns true if the camera is under the water level 1006 * @return 1007 */ 1008 public boolean isUnderWater() { 1009 return underWater; 1010 } 1011 1012 /** 1013 * returns the distance of the fog when under water 1014 * @return 1015 */ 1016 public float getUnderWaterFogDistance() { 1017 return underWaterFogDistance; 1018 } 1019 1020 /** 1021 * sets the distance of the fog when under water. 1022 * default is 120 (120 world units) use a high value to raise the view range under water 1023 * @param underWaterFogDistance 1024 */ 1025 public void setUnderWaterFogDistance(float underWaterFogDistance) { 1026 this.underWaterFogDistance = underWaterFogDistance; 1027 if (material != null) { 1028 material.setFloat("UnderWaterFogDistance", underWaterFogDistance); 1029 } 1030 } 1031 1032 /** 1033 * get the intensity of caustics under water 1034 * @return 1035 */ 1036 public float getCausticsIntensity() { 1037 return causticsIntensity; 1038 } 1039 1040 /** 1041 * sets the intensity of caustics under water. goes from 0 to 1, default is 0.5f 1042 * @param causticsIntensity 1043 */ 1044 public void setCausticsIntensity(float causticsIntensity) { 1045 this.causticsIntensity = causticsIntensity; 1046 if (material != null) { 1047 material.setFloat("CausticsIntensity", causticsIntensity); 1048 } 1049 } 1050 } 1051