1 package jme3test.water; 2 3 import com.jme3.app.SimpleApplication; 4 import com.jme3.audio.AudioNode; 5 import com.jme3.audio.LowPassFilter; 6 import com.jme3.effect.ParticleEmitter; 7 import com.jme3.effect.ParticleMesh; 8 import com.jme3.input.controls.ActionListener; 9 import com.jme3.input.controls.KeyTrigger; 10 import com.jme3.light.DirectionalLight; 11 import com.jme3.material.Material; 12 import com.jme3.material.RenderState.BlendMode; 13 import com.jme3.math.ColorRGBA; 14 import com.jme3.math.FastMath; 15 import com.jme3.math.Quaternion; 16 import com.jme3.math.Vector3f; 17 import com.jme3.post.FilterPostProcessor; 18 import com.jme3.post.filters.BloomFilter; 19 import com.jme3.post.filters.DepthOfFieldFilter; 20 import com.jme3.post.filters.LightScatteringFilter; 21 import com.jme3.renderer.Camera; 22 import com.jme3.renderer.queue.RenderQueue.Bucket; 23 import com.jme3.renderer.queue.RenderQueue.ShadowMode; 24 import com.jme3.scene.Geometry; 25 import com.jme3.scene.Node; 26 import com.jme3.scene.Spatial; 27 import com.jme3.scene.shape.Box; 28 import com.jme3.terrain.geomipmap.TerrainQuad; 29 import com.jme3.terrain.heightmap.AbstractHeightMap; 30 import com.jme3.terrain.heightmap.ImageBasedHeightMap; 31 import com.jme3.texture.Texture; 32 import com.jme3.texture.Texture.WrapMode; 33 import com.jme3.texture.Texture2D; 34 import com.jme3.util.SkyFactory; 35 import com.jme3.water.WaterFilter; 36 import java.util.ArrayList; 37 import java.util.List; 38 39 /** 40 * test 41 * @author normenhansen 42 */ 43 public class TestPostWater extends SimpleApplication { 44 45 private Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f); 46 private WaterFilter water; 47 TerrainQuad terrain; 48 Material matRock; 49 AudioNode waves; 50 LowPassFilter underWaterAudioFilter = new LowPassFilter(0.5f, 0.1f); 51 LowPassFilter underWaterReverbFilter = new LowPassFilter(0.5f, 0.1f); 52 LowPassFilter aboveWaterAudioFilter = new LowPassFilter(1, 1); 53 main(String[] args)54 public static void main(String[] args) { 55 TestPostWater app = new TestPostWater(); 56 app.start(); 57 } 58 59 @Override simpleInitApp()60 public void simpleInitApp() { 61 62 setDisplayFps(false); 63 setDisplayStatView(false); 64 65 Node mainScene = new Node("Main Scene"); 66 rootNode.attachChild(mainScene); 67 68 createTerrain(mainScene); 69 DirectionalLight sun = new DirectionalLight(); 70 sun.setDirection(lightDir); 71 sun.setColor(ColorRGBA.White.clone().multLocal(1.7f)); 72 mainScene.addLight(sun); 73 74 DirectionalLight l = new DirectionalLight(); 75 l.setDirection(Vector3f.UNIT_Y.mult(-1)); 76 l.setColor(ColorRGBA.White.clone().multLocal(0.3f)); 77 // mainScene.addLight(l); 78 79 flyCam.setMoveSpeed(50); 80 81 //cam.setLocation(new Vector3f(-700, 100, 300)); 82 //cam.setRotation(new Quaternion().fromAngleAxis(0.5f, Vector3f.UNIT_Z)); 83 cam.setLocation(new Vector3f(-327.21957f, 61.6459f, 126.884346f)); 84 cam.setRotation(new Quaternion(0.052168474f, 0.9443102f, -0.18395276f, 0.2678024f)); 85 86 87 cam.setRotation(new Quaternion().fromAngles(new float[]{FastMath.PI * 0.06f, FastMath.PI * 0.65f, 0})); 88 89 90 Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false); 91 sky.setLocalScale(350); 92 93 mainScene.attachChild(sky); 94 cam.setFrustumFar(4000); 95 //cam.setFrustumNear(100); 96 97 98 99 //private FilterPostProcessor fpp; 100 101 102 water = new WaterFilter(rootNode, lightDir); 103 104 FilterPostProcessor fpp = new FilterPostProcessor(assetManager); 105 106 fpp.addFilter(water); 107 BloomFilter bloom=new BloomFilter(); 108 //bloom.getE 109 bloom.setExposurePower(55); 110 bloom.setBloomIntensity(1.0f); 111 fpp.addFilter(bloom); 112 LightScatteringFilter lsf = new LightScatteringFilter(lightDir.mult(-300)); 113 lsf.setLightDensity(1.0f); 114 fpp.addFilter(lsf); 115 DepthOfFieldFilter dof=new DepthOfFieldFilter(); 116 dof.setFocusDistance(0); 117 dof.setFocusRange(100); 118 fpp.addFilter(dof); 119 // 120 121 // fpp.addFilter(new TranslucentBucketFilter()); 122 // 123 124 // fpp.setNumSamples(4); 125 126 127 water.setWaveScale(0.003f); 128 water.setMaxAmplitude(2f); 129 water.setFoamExistence(new Vector3f(1f, 4, 0.5f)); 130 water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg")); 131 //water.setNormalScale(0.5f); 132 133 //water.setRefractionConstant(0.25f); 134 water.setRefractionStrength(0.2f); 135 //water.setFoamHardness(0.6f); 136 137 water.setWaterHeight(initialWaterHeight); 138 uw=cam.getLocation().y<waterHeight; 139 140 waves = new AudioNode(audioRenderer, assetManager, "Sound/Environment/Ocean Waves.ogg", false); 141 waves.setLooping(true); 142 waves.setReverbEnabled(true); 143 if(uw){ 144 waves.setDryFilter(new LowPassFilter(0.5f, 0.1f)); 145 }else{ 146 waves.setDryFilter(aboveWaterAudioFilter); 147 } 148 audioRenderer.playSource(waves); 149 // 150 viewPort.addProcessor(fpp); 151 152 inputManager.addListener(new ActionListener() { 153 154 public void onAction(String name, boolean isPressed, float tpf) { 155 if (isPressed) { 156 if (name.equals("foam1")) { 157 water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg")); 158 } 159 if (name.equals("foam2")) { 160 water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg")); 161 } 162 if (name.equals("foam3")) { 163 water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam3.jpg")); 164 } 165 } 166 } 167 }, "foam1", "foam2", "foam3"); 168 inputManager.addMapping("foam1", new KeyTrigger(keyInput.KEY_1)); 169 inputManager.addMapping("foam2", new KeyTrigger(keyInput.KEY_2)); 170 inputManager.addMapping("foam3", new KeyTrigger(keyInput.KEY_3)); 171 // createBox(); 172 // createFire(); 173 } 174 Geometry box; 175 176 private void createBox() { 177 //creating a transluscent box 178 box = new Geometry("box", new Box(new Vector3f(0, 0, 0), 50, 50, 50)); 179 Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"); 180 mat.setColor("Color", new ColorRGBA(1.0f, 0, 0, 0.3f)); 181 mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha); 182 //mat.getAdditionalRenderState().setDepthWrite(false); 183 //mat.getAdditionalRenderState().setDepthTest(false); 184 box.setMaterial(mat); 185 box.setQueueBucket(Bucket.Translucent); 186 187 188 //creating a post view port 189 // ViewPort post=renderManager.createPostView("transpPost", cam); 190 // post.setClearFlags(false, true, true); 191 192 193 box.setLocalTranslation(-600, 0, 300); 194 195 //attaching the box to the post viewport 196 //Don't forget to updateGeometricState() the box in the simpleUpdate 197 // post.attachScene(box); 198 199 rootNode.attachChild(box); 200 } 201 202 private void createFire() { 203 /** Uses Texture from jme3-test-data library! */ 204 ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30); 205 Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"); 206 mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png")); 207 208 fire.setMaterial(mat_red); 209 fire.setImagesX(2); 210 fire.setImagesY(2); // 2x2 texture animation 211 fire.setEndColor(new ColorRGBA(1f, 0f, 0f, 1f)); // red 212 fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow 213 fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 2, 0)); 214 fire.setStartSize(10f); 215 fire.setEndSize(1f); 216 fire.setGravity(0, 0, 0); 217 fire.setLowLife(0.5f); 218 fire.setHighLife(1.5f); 219 fire.getParticleInfluencer().setVelocityVariation(0.3f); 220 fire.setLocalTranslation(-350, 40, 430); 221 222 fire.setQueueBucket(Bucket.Transparent); 223 rootNode.attachChild(fire); 224 } 225 226 private void createTerrain(Node rootNode) { 227 matRock = new Material(assetManager, "Common/MatDefs/Terrain/TerrainLighting.j3md"); 228 matRock.setBoolean("useTriPlanarMapping", false); 229 matRock.setBoolean("WardIso", true); 230 matRock.setTexture("AlphaMap", assetManager.loadTexture("Textures/Terrain/splat/alphamap.png")); 231 Texture heightMapImage = assetManager.loadTexture("Textures/Terrain/splat/mountains512.png"); 232 Texture grass = assetManager.loadTexture("Textures/Terrain/splat/grass.jpg"); 233 grass.setWrap(WrapMode.Repeat); 234 matRock.setTexture("DiffuseMap", grass); 235 matRock.setFloat("DiffuseMap_0_scale", 64); 236 Texture dirt = assetManager.loadTexture("Textures/Terrain/splat/dirt.jpg"); 237 dirt.setWrap(WrapMode.Repeat); 238 matRock.setTexture("DiffuseMap_1", dirt); 239 matRock.setFloat("DiffuseMap_1_scale", 16); 240 Texture rock = assetManager.loadTexture("Textures/Terrain/splat/road.jpg"); 241 rock.setWrap(WrapMode.Repeat); 242 matRock.setTexture("DiffuseMap_2", rock); 243 matRock.setFloat("DiffuseMap_2_scale", 128); 244 Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg"); 245 normalMap0.setWrap(WrapMode.Repeat); 246 Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png"); 247 normalMap1.setWrap(WrapMode.Repeat); 248 Texture normalMap2 = assetManager.loadTexture("Textures/Terrain/splat/road_normal.png"); 249 normalMap2.setWrap(WrapMode.Repeat); 250 matRock.setTexture("NormalMap", normalMap0); 251 matRock.setTexture("NormalMap_1", normalMap2); 252 matRock.setTexture("NormalMap_2", normalMap2); 253 254 AbstractHeightMap heightmap = null; 255 try { 256 heightmap = new ImageBasedHeightMap(heightMapImage.getImage(), 0.25f); 257 heightmap.load(); 258 } catch (Exception e) { 259 e.printStackTrace(); 260 } 261 terrain = new TerrainQuad("terrain", 65, 513, heightmap.getHeightMap()); 262 List<Camera> cameras = new ArrayList<Camera>(); 263 cameras.add(getCamera()); 264 terrain.setMaterial(matRock); 265 terrain.setLocalScale(new Vector3f(5, 5, 5)); 266 terrain.setLocalTranslation(new Vector3f(0, -30, 0)); 267 terrain.setLocked(false); // unlock it so we can edit the height 268 269 terrain.setShadowMode(ShadowMode.Receive); 270 rootNode.attachChild(terrain); 271 272 } 273 //This part is to emulate tides, slightly varrying the height of the water plane 274 private float time = 0.0f; 275 private float waterHeight = 0.0f; 276 private float initialWaterHeight = 0.8f; 277 private boolean uw=false; 278 @Override 279 public void simpleUpdate(float tpf) { 280 super.simpleUpdate(tpf); 281 // box.updateGeometricState(); 282 time += tpf; 283 waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f; 284 water.setWaterHeight(initialWaterHeight + waterHeight); 285 if(water.isUnderWater() && !uw){ 286 287 waves.setDryFilter(new LowPassFilter(0.5f, 0.1f)); 288 uw=true; 289 } 290 if(!water.isUnderWater() && uw){ 291 uw=false; 292 //waves.setReverbEnabled(false); 293 waves.setDryFilter(new LowPassFilter(1, 1f)); 294 //waves.setDryFilter(new LowPassFilter(1,1f)); 295 296 } 297 } 298 } 299