water.adoc 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. = Simple Water
  2. :author:
  3. :revnumber:
  4. :revdate: 2016/03/17 20:48
  5. :relfileprefix: ../../
  6. :imagesdir: ../..
  7. ifdef::env-github,env-browser[:outfilesuffix: .adoc]
  8. jMonkeyEngine offers a SimpleWaterProcessor that turns any quad (flat rectangle) into a reflective water surface with waves. You can use this quad for simple limited water surfaces such as water troughs, shallow fountains, puddles, shallow water in channels. The SimpleWaterProcessor has less performance impact on your game than the full featured <<jme3/advanced/post-processor_water#,SeaMonkey WaterFilter>>; the main difference is that the SimpleWaterProcessor does not include under-water effects.
  9. Here is some background info for JME3's basic water implementation:
  10. // * link:http://www.jmonkeyengine.com/forum/index.php?topic=14740.0[http://www.jmonkeyengine.com/forum/index.php?topic=14740.0]
  11. * link:https://www.bonzaisoftware.com/tnp/gl-water-tutorial/[https://www.bonzaisoftware.com/tnp/gl-water-tutorial/]
  12. // * link:http://www.gametutorials.com/Articles/RealisticWater.pdf[http://www.gametutorials.com/Articles/RealisticWater.pdf]
  13. // image::http://www.jmonkeyengine.com/wp-content/uploads/2010/10/simplewaterdemo.jpg[simplewaterdemo.jpg,width="277",height="180",align="center"]
  14. == SimpleWaterProcessor
  15. A JME3 scene with water can use a `com.jme3.water.SimpleWaterProcessor` (which implements the SceneProcessor interface).
  16. To achieve a water effect, JME3 uses shaders and a special material, `Common/MatDefs/Water/SimpleWater.j3md`. The water surface is a quad, and we use normal map and dU/dV map texturing to simulate the waves.
  17. . Every frame, we render to three texture maps:
  18. ** For the water surface (reflection), we take a snapshot of the environment, flip it upside down, and clip it to the visible water surface. Note that we do not actually use a "`water`" texture color map: The "`texture`" of the water is solely a distorted reflection.
  19. ** For the "`wavy`" distortion (refraction), we use the derivative of a normal map, a dU/dV map.
  20. ** For the fogginess of water (depth) we use a depth map from the terrains z-buffer.
  21. . In the shaders, we add all of the texture maps together.
  22. ** For the "`bumpy`" displacement of the waves, we use a normal map and a du/dv map that are shifted against each other over time to create the wave effect.
  23. ** For the light reflection vectors on the water surface, we use the Fresnel formula, together with normal vectors.
  24. ** We add specular lighting.
  25. . (For the underwater caustics effect, we use splatted textures. – WIP/TODO)
  26. == Usage
  27. [.right.text-left]
  28. image::jme3/advanced/simplewater.png[simplewater.png,width="384",height="288",align="right"]
  29. . Create a `mainScene` Node
  30. .. Attach the `mainScene` Node to the `rootNode`
  31. . Load your `scene` Spatial
  32. .. Add a light source to the `scene` Spatial
  33. .. Attach the `scene` Spatial to the `mainScene` Node
  34. . Load your <<jme3/advanced/sky#,sky>> Geometry
  35. .. Attach the sky Geometry to the `mainScene` Node
  36. . Create the SimpleWaterProcessor `waterProcessor`
  37. .. Set the processor's ReflectionScene to the `mainScene` Spatial (!)
  38. .. Set the processor's Plane to where you want your water surface to be
  39. .. Set the processor's WaterDepth, DistortionScale, and WaveSpeed
  40. .. Attach the processor to the `viewPort`
  41. . Create a Quad `quad`
  42. .. Set the quad's TextureCoordinates to specify the size of the waves
  43. . Create a `water` Geometry from the Quad
  44. .. Set the water's translation and rotation (same Y value as Plane above!)
  45. .. Set the water's material to the processor's output material
  46. .. Attach the `water` Geometry to the `rootNode`. (Not to the mainScene!)
  47. == Sample Code
  48. The sample code can be found in `link:https://github.com/jMonkeyEngine/jmonkeyengine/blob/445f7ed010199d30c484fe75bacef4b87f2eb38e/jme3-examples/src/main/java/jme3test/water/TestSimpleWater.java[TestSimpleWater.java]` and `link:https://github.com/jMonkeyEngine/jmonkeyengine/blob/445f7ed010199d30c484fe75bacef4b87f2eb38e/jme3-examples/src/main/java/jme3test/water/TestSceneWater.java[TestSceneWater.java]`.
  49. Here is the most important part of the code:
  50. [source,java]
  51. ----
  52. // we create a water processor
  53. SimpleWaterProcessor waterProcessor = new SimpleWaterProcessor(assetManager);
  54. waterProcessor.setReflectionScene(mainScene);
  55. // we set the water plane
  56. Vector3f waterLocation=new Vector3f(0,-6,0);
  57. waterProcessor.setPlane(new Plane(Vector3f.UNIT_Y, waterLocation.dot(Vector3f.UNIT_Y)));
  58. viewPort.addProcessor(waterProcessor);
  59. // we set wave properties
  60. waterProcessor.setWaterDepth(40); // transparency of water
  61. waterProcessor.setDistortionScale(0.05f); // strength of waves
  62. waterProcessor.setWaveSpeed(0.05f); // speed of waves
  63. // we define the wave size by setting the size of the texture coordinates
  64. Quad quad = new Quad(400,400);
  65. quad.scaleTextureCoordinates(new Vector2f(6f,6f));
  66. // we create the water geometry from the quad
  67. Geometry water=new Geometry("water", quad);
  68. water.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
  69. water.setLocalTranslation(-200, -6, 250);
  70. water.setShadowMode(ShadowMode.Receive);
  71. water.setMaterial(waterProcessor.getMaterial());
  72. rootNode.attachChild(water);
  73. ----
  74. == Settings
  75. You can lower the render size to gain higher performance:
  76. [source,java]
  77. ----
  78. waterProcessor.setRenderSize(128,128);
  79. ----
  80. The deeper the water, the more transparent. (?)
  81. [source,java]
  82. ----
  83. waterProcessor.setWaterDepth(40);
  84. ----
  85. A higher distortion scale makes bigger waves.
  86. [source,java]
  87. ----
  88. waterProcessor.setDistortionScale(0.05f);
  89. ----
  90. A lower wave speed makes calmer water.
  91. [source,java]
  92. ----
  93. waterProcessor.setWaveSpeed(0.05f);
  94. ----
  95. If your scene does not have a lightsource, you can set the light direction for the water:
  96. [source,java]
  97. ----
  98. waterProcessor.setLightDirection( new Vector3f(0.55f, -0.82f, 0.15f));
  99. ----
  100. Instead of creating a quad and specifying a plane, you can get a default waterplane from the processor:
  101. [source,java]
  102. ----
  103. Geometry waterPlane = waterProcessor.createWaterGeometry(10, 10);
  104. waterPlane.setLocalTranslation(-5, 0, 5);
  105. waterPlane.setMaterial(waterProcessor.getMaterial());
  106. ----
  107. You can offer a switch to set the water Material to a static texture – for users with slow PCs.