2
0

post-processor_water.html 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. <!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]--><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta name="generator" content="Asciidoctor 1.5.4"><title>Rendering Water as Post-Process Effect</title><link rel="stylesheet" href="./asciidoctor.css">
  2. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
  3. <link rel="stylesheet" href="./coderay-asciidoctor.css"><link rel="stylesheet" href="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.css"><link rel="stylesheet" href="/home/travis/build/jMonkeyEngine/wiki/build/asciidoc/html5/jme3/advanced/twemoji-awesome.css"></head><body class="article toc2 toc-left"><div id="header"><div id="toolbar"><a href="https://github.com/jMonkeyEngine/wiki/edit/master/src/docs/asciidoc/jme3/advanced/post-processor_water.adoc"><i class="fa fa-pencil-square" aria-hidden="true"></i></a><a href="https://github.com/jMonkeyEngine/wiki/new/master/src/docs/asciidoc/jme3/advanced/"><i class="fa fa-plus-square" aria-hidden="true"></i></a><input dir="auto" style="position: relative; vertical-align: top;" spellcheck="false" autocomplete="off" class="searchbox__input aa-input" id="doc-search" name="search" placeholder="Search in the doc" required="required" type="search"></div><h1>Rendering Water as Post-Process Effect</h1><div class="details"><span class="author" id="author"></span><br><span id="revnumber">version ,</span> <span id="revdate">2016/03/17 20:48</span></div><div id="toc" class="toc2"><div id="toctitle">Table of Contents</div><ul class="sectlevel1"><li><a href="#the-theory">The Theory</a></li><li><a href="#how-did-we-implement-it-in-jme3">How Did We Implement it in jME3?</a></li><li><a href="#sample-code">Sample Code</a><ul class="sectlevel2"><li><a href="#using-the-water-filter">Using the Water Filter</a></li><li><a href="#optional-waves">Optional: Waves</a></li><li><a href="#optional-water-wave-and-color-effects">Optional: Water Wave and Color Effects</a></li><li><a href="#sound-effects">Sound Effects</a></li></ul></li></ul></div></div><div id="content"><div id="preamble"><div class="sectionbody"><div class="paragraph"><p>The awesome SeaMonkey WaterFilter is highly configurable. It can render any type of water and also simulates the underwater part of the effect, including light effects called caustics. The effect is based on <a href="https://www.gamedev.net/articles/programming/graphics/rendering-water-as-a-post-process-effect-r2642/">Wojciech Toman’s Rendering Water as a Post-process Effect</a>
  4. published on gamedev.net. Here&#8217;s a video:</p></div>
  5. <div style="text-align: center;" class="imageblock"><div class="content"><a class="image" href="https://youtu.be/AWlUzgRN3Pc"><img src="../../jme3/advanced/water-post.png" alt="water-post.png" width="" height=""></a></div></div>
  6. <div class="admonitionblock note"><table><tr><td class="icon"><i class="fa icon-note" title="Note"></i></td><td class="content"><div class="paragraph"><p>The SeaMonkey WaterFilter is ideal for oceans and lakes, and especially for under-water scenes. If you only need a small simple water surface, such as a water trough or a shallow fountain, the <a href="../../jme3/advanced/water.html">SimpleWaterProcessor</a> may already be all you need.</p></div></td></tr></table></div></div></div>
  7. <div class="sect1"><h2 id="the-theory">The Theory</h2><div class="sectionbody"><div class="paragraph"><p>The effect is part of a deferred rendering process, taking advantage of the pre-computed position buffer and back buffer (a texture representing the screen’s pixels position in view space, and a texture of the rendered scene).</p></div>
  8. <div class="paragraph"><p>After some calculation, this allows to reconstruct the position in world space for each pixel on the screen. “If a pixel is under a given water height, let’s render it as a blue pixel! Blue pixel? Not exactly, we want waves, we want ripples, we want foam, we want reflection and refraction.</p></div>
  9. <div class="paragraph"><p>The GameDev.net article describes how those effects are achieved, but the main idea is to generate waves from a height map, create ripples from a normal map, blend in the foam texture when the water depth is below a certain height, compute the refraction color with a clever color extinction algorithm, and then, display the reflection and specular effect by computing a Fresnel term (like in the simple water effect). In addition, this effect allows to blend the water shore with the ground to avoid the hard edges of classic water effects based on grids or quads.</p></div></div></div>
  10. <div class="sect1"><h2 id="how-did-we-implement-it-in-jme3">How Did We Implement it in jME3?</h2><div class="sectionbody"><div class="paragraph"><p>jME3 default behavior is to use a forward rendering process, so there is no position buffer rendered that we can take advantage of. But while rendering the main scene to a frame buffer in the FilterPostPorcessor, we can write the hardware depth buffer to a texture, with nearly no additional cost.</p></div>
  11. <div class="paragraph"><p>There are several ways of reconstructing the world space position of a pixel from the depth buffer. The computational cost is higher than just fetching the position from a position buffer, but the bandwidth and the memory required is a lot lower.</p></div>
  12. <div class="paragraph"><p>Now we have the rendered scene in a texture, and we can reconstruct the position in world space of each pixel. We’re good to go!</p></div>
  13. <div class="paragraph"><p>– Nehon</p></div></div></div>
  14. <div class="sect2"><h3 id="sample-code">Sample Code</h3><div class="paragraph"><p>These are test cases in the jME3 repository:</p></div>
  15. <div class="ulist"><ul><li><p><a href="https://github.com/jMonkeyEngine/jmonkeyengine/tree/master/jme3-examples/src/main/java/jme3test/water/TestPostWater.java">TestPostWater.java</a> (ocean island)</p></li><li><p><a href="https://github.com/jMonkeyEngine/jmonkeyengine/tree/master/jme3-examples/src/main/java/jme3test/water/TestPostWaterLake.java">TestPostWaterLake.java</a> (calm and muddy water pond)</p></li><li><p><a href="https://github.com/jMonkeyEngine/jmonkeyengine/tree/master/jme3-examples/src/main/java/jme3test/water/TestMultiPostWater.java">TestMultiPostWater.java</a> (several ponds of different sizes at different heights etc)</p></li></ul></div>
  16. <div class="sect2"><h3 id="using-the-water-filter">Using the Water Filter</h3><div class="paragraph"><p>In the <code>simpleInitApp()</code> method, you attach your scene to the rootNode, typically a terrain with a sky. Remember to add a directional light, since the water relies on the light direction vector. The WaterFilter constructor expects a node with the scene attached that should be reflected in the water, and vector information from the light source&#8217;s direction.</p></div>
  17. <div class="paragraph"><p>This is how you use the water filter post-processor code in your code:</p></div>
  18. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> FilterPostProcessor fpp;
  19. <span class="directive">private</span> WaterFilter water;
  20. <span class="directive">private</span> Vector3f lightDir = <span class="keyword">new</span> Vector3f(-<span class="float">4.9f</span>, -<span class="float">1.3f</span>, <span class="float">5.9f</span>); <span class="comment">// same as light source</span>
  21. <span class="directive">private</span> <span class="type">float</span> initialWaterHeight = <span class="float">0.8f</span>; <span class="comment">// choose a value for your scene</span>
  22. ...
  23. public <span class="type">void</span> simpleInitApp() {
  24. ...
  25. fpp = <span class="keyword">new</span> FilterPostProcessor(assetManager);
  26. water = <span class="keyword">new</span> WaterFilter(rootNode, lightDir);
  27. water.setWaterHeight(initialWaterHeight);
  28. fpp.addFilter(water);
  29. viewPort.addProcessor(fpp);
  30. ...
  31. }</code></pre></div></div>
  32. <div class="paragraph"><p>Usually you make the water reflect everything attached to the rootNode. But you can also give a custom node (a subnode of the rootNode) to the WaterFilter constructor that has only a subset of scene nodes attached. This would be a relevant optimization if you have lots of nodes that are far away from the water, or covered, and will never be reflected.</p></div></div>
  33. <div class="sect2"><h3 id="optional-waves">Optional: Waves</h3><div class="paragraph"><p>If you want waves, set the water height in the update loop. We reuse the initialWaterHeight variable, and repeatedly reset the waterHeight value according to time. This causes the waves.</p></div>
  34. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java"><span class="directive">private</span> <span class="type">float</span> time = <span class="float">0.0f</span>;
  35. <span class="directive">private</span> <span class="type">float</span> waterHeight = <span class="float">0.0f</span>;
  36. <span class="annotation">@Override</span>
  37. <span class="directive">public</span> <span class="type">void</span> simpleUpdate(<span class="type">float</span> tpf) {
  38. <span class="local-variable">super</span>.simpleUpdate(tpf);
  39. time += tpf;
  40. waterHeight = (<span class="type">float</span>) <span class="predefined-type">Math</span>.cos(((time * <span class="float">0.6f</span>) % FastMath.TWO_PI)) * <span class="float">1.5f</span>;
  41. water.setWaterHeight(initialWaterHeight + waterHeight);
  42. }</code></pre></div></div></div>
  43. <div class="sect2"><h3 id="optional-water-wave-and-color-effects">Optional: Water Wave and Color Effects</h3><div style="text-align: center;" class="imageblock"><div class="content"><img src="../../jme3/advanced/water-post-muddy.png" alt="water-post-muddy.png" width="220" height="172"></div></div>
  44. <div class="paragraph"><p>All these effects are optional. Every setter also has a getter.</p></div>
  45. <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Water method example</th><th class="tableblock halign-left valign-top">Effects: Waves</th><th class="tableblock halign-left valign-top">Default</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setWaterHeight(-6);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Use this waterheight method for causing waves.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.0f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setMaxAmplitude(0.3f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>How high the highest waves are.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>1.0f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setWaveScale(0.008f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the scale factor of the waves height map. The smaller the value, the bigger the waves!</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.005f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setWindDirection(new Vector2f(0,1))</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the wind direction, which is the direction where the waves move</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Vector2f(0.0f, -1.0f)</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setSpeed(0.7f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>How fast the waves move. Set it to 0.0f for still water.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>1.0f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setHeightTexture( (Texture2D)<br>
  46. manager.loadTexture(“Textures/waveheight.png) )</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>This height map describes the shape of the waves</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>“Common/MatDefs/Water/Textures/heightmap.jpg</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setNormalTexture( (Texture2D)<br>
  47. manager.loadTexture(“Textures/wavenormals.png) )</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>This normal map describes the shape of the waves</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>“Common/MatDefs/Water/Textures/gradient_map.jpg</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setUseRipples(false);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Switches the ripples effect on or off.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>true</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setNormalScale(0.5f)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the normal scaling factors to apply to the normal map. The higher the value, the more small ripples will be visible on the waves.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>1.0f</p></div></div></td></tr></tbody></table>
  48. <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Water method example</th><th class="tableblock halign-left valign-top">Effects: Color</th><th class="tableblock halign-left valign-top">Default</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setLightDirection(new Vector3f(-0.37f,-0.50f,-0.78f))</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Usually you set this to the same as the light source&#8217;s direction. Use this to set the light direction if the sun is moving.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Value given to WaterFilter() constructor.</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setLightColor(ColorRGBA.White)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Usually you set this to the same as the light source&#8217;s color.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>RGBA.White</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setWaterColor(ColorRGBA.Brown.mult(2.0f));</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the main water color.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>greenish blue<br>
  49. ColorRGBA(0.0f,0.5f,0.5f,1.0f)</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setDeepWaterColor(ColorRGBA.Brown);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the deep water color.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>dark blue<br>
  50. ColorRGBA(0.0f, 0.0f,0.2f,1.0f)</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setWaterTransparency(0.2f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets how fast colors fade out. use this to control how clear (e.g. 0.05f) or muddy (0.2f) water is.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.1f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setColorExtinction(new Vector3f(10f,20f,30f));</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets At what depth the refraction color extincts. The three values are RGB (red, green, blue) in this order. Play with these parameters to “muddy the water.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Vector3f(5f,20f,30f)</p></div></div></td></tr></tbody></table>
  51. <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Water method example</th><th class="tableblock halign-left valign-top">Effects: Shore</th><th class="tableblock halign-left valign-top">Default</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setCenter(Vector3f.ZERO);<br>
  52. water.setRadius(260);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Limit the water filter to a semisphere with the given center and radius. Use this for lakes and smaller bodies of water. Skip this for oceans.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>unused</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setShoreHardness(1.0f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets how soft the transition between shore and water should be. High values mean a harder transition between shore and water.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.1f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setUseHQShoreline(false);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Renders shoreline with better quality ?</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>true</p></div></div></td></tr></tbody></table>
  53. <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Water method example</th><th class="tableblock halign-left valign-top">Effects: Foam</th><th class="tableblock halign-left valign-top">Default</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setUseFoam(false);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Switches the white foam on or off</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>true</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setFoamHardness(0.5f)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets how much the foam will blend with the shore to avoid a hard edged water plane.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>1.0f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setFoamExistence(new Vector3f(0.5f,5f,1.0f))</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The three values describe what depth foam starts to fade out, at what depth it is completely invisible, at what height foam for waves appears (+ waterHeight).</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Vector3f(0.45f,4.35f,1.0f)</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setFoamTexture( (Texture2D)<br>
  54. manager.loadTexture(“Textures/foam.png) )</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>This foam texture will be used with WrapMode.Repeat</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>“Common/MatDefs/Water/Textures/foam.jpg</p></div></div></td></tr></tbody></table>
  55. <table class="tableblock frame-all grid-all spread"><colgroup><col style="width: 33.3333%;"><col style="width: 33.3333%;"><col style="width: 33.3334%;"></colgroup><thead><tr><th class="tableblock halign-left valign-top">Water method example</th><th class="tableblock halign-left valign-top">Effects: Light</th><th class="tableblock halign-left valign-top">Default</th></tr></thead><tbody><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setSunScale(1f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets how big the sun should appear in the light&#8217;s specular effect on the water.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>3.0f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setUseSpecular(false)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Switches specular effect on or off</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>true</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setShininess(0.8f)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the shininess of the water reflections</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.7f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setUseRefraction(true)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Switches the refraction effect on or off.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>true</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setRefractionConstant(0.2f);</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>The lower the value, the less reflection can be seen on water. This is a constant related to the index of refraction (IOR) used to compute the fresnel term.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.3f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setRefractionStrength(-0.1)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>This value modifies the current Fresnel term. If you want to weaken reflections use bigger value. If you want to empasize them, use a value smaller than 0.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>0.0f</p></div></div></td></tr><tr><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>water.setReflectionMapSize(256)</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>Sets the size of the reflection map. The higher, the better the quality, but the slower the effect.</p></div></div></td><td class="tableblock halign-left valign-top"><div><div class="paragraph"><p>512</p></div></div></td></tr></tbody></table></div>
  56. <div class="sect2"><h3 id="sound-effects">Sound Effects</h3><div class="paragraph"><p>You should also add audio nodes with water sounds to complete the effect.</p></div>
  57. <div class="listingblock"><div class="content"><pre class="CodeRay highlight"><code data-lang="java">AudioNode waves = <span class="keyword">new</span> AudioNode(assetManager, <span class="string"><span class="delimiter">&quot;</span><span class="content">Sounds/Environment/Ocean Waves.ogg</span><span class="delimiter">&quot;</span></span>, <span class="predefined-constant">false</span>);
  58. waves.setLooping(<span class="predefined-constant">true</span>);
  59. audioRenderer.playSource(waves);</code></pre></div></div>
  60. <div class="paragraph"><p>See also: <a href="../../jme3/advanced/audio.html">audio</a>.</p></div>
  61. <hr>
  62. <div class="paragraph"><p>See also:</p></div>
  63. <div class="ulist"><ul><li><p><a href="https://hub.jmonkeyengine.org/t/monkeys-at-the-beach/15000">JME3&#8217;s Water Post-Process Effect</a> by Nehon</p></li><li><p><a href="../../jme3/advanced/water.html">Simple water</a></p></li></ul></div></div></div></div><div id="footer"><div id="footer-text">Version <br>Last updated 2019-12-20 23:30:51 +00:00</div></div><script type="text/javascript" src="https://cdn.jsdelivr.net/docsearch.js/2/docsearch.min.js"></script><script>docsearch({
  64. apiKey: 'a736b6d93de805e26ec2f49b55013fbd',
  65. indexName: 'jmonkeyengine',
  66. inputSelector: '#doc-search',
  67. debug: false // Set debug to true if you want to inspect the dropdown
  68. });</script></body></html>