浏览代码

TranslucentBucket :
- Added a translucent bucket that is rendered after the processors (usefull for shadows)
- For filters, rendering this bucket is a bit particular, so you can use the TranslucentBucketFilter to render the translucent bucket in the middle of the fillter stack (doc is comming up in the wiki)
- renamed Filter's preRender method to postQueue for consistancy with processors
- added translucent objects in TestPostWater, added a fire (particles) in test transparent shadows

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7540 75d07b2b-3a1a-0410-a2c5-0572b91ccdca

rem..om 14 年之前
父节点
当前提交
2d4896942d
共有 26 个文件被更改,包括 574 次插入293 次删除
  1. 3 0
      engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java
  2. 2 3
      engine/src/core-data/Common/MatDefs/Post/Post.vert
  3. 19 3
      engine/src/core/com/jme3/post/Filter.java
  4. 35 13
      engine/src/core/com/jme3/post/FilterPostProcessor.java
  5. 19 2
      engine/src/core/com/jme3/renderer/RenderManager.java
  6. 6 2
      engine/src/core/com/jme3/renderer/Renderer.java
  7. 56 34
      engine/src/core/com/jme3/renderer/queue/RenderQueue.java
  8. 3 0
      engine/src/core/com/jme3/system/NullRenderer.java
  9. 1 1
      engine/src/desktop-fx/com/jme3/post/filters/BloomFilter.java
  10. 1 1
      engine/src/desktop-fx/com/jme3/post/filters/CartoonEdgeFilter.java
  11. 0 4
      engine/src/desktop-fx/com/jme3/post/filters/ColorOverlayFilter.java
  12. 0 4
      engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java
  13. 0 4
      engine/src/desktop-fx/com/jme3/post/filters/DepthOfFieldFilter.java
  14. 0 3
      engine/src/desktop-fx/com/jme3/post/filters/FadeFilter.java
  15. 0 3
      engine/src/desktop-fx/com/jme3/post/filters/FogFilter.java
  16. 1 1
      engine/src/desktop-fx/com/jme3/post/filters/LightScatteringFilter.java
  17. 0 3
      engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java
  18. 0 3
      engine/src/desktop-fx/com/jme3/post/filters/RadialBlurFilter.java
  19. 76 0
      engine/src/desktop-fx/com/jme3/post/filters/TranslucentBucketFilter.java
  20. 6 6
      engine/src/desktop-fx/com/jme3/post/ssao/SSAOFilter.java
  21. 9 1
      engine/src/desktop-fx/com/jme3/water/WaterFilter.java
  22. 89 87
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java
  23. 100 95
      engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java
  24. 26 1
      engine/src/test/jme3test/light/TestTransparentShadow.java
  25. 28 1
      engine/src/test/jme3test/post/TestMultiViewsFilters.java
  26. 94 18
      engine/src/test/jme3test/water/TestPostWater.java

+ 3 - 0
engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java

@@ -1259,6 +1259,9 @@ public class OGLESShaderRenderer implements Renderer {
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
 	logger.warning("copyFrameBuffer is not supported.");
     }
+    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth){
+	logger.warning("copyFrameBuffer is not supported.");
+    }
 /*
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst){
         if (GLContext.getCapabilities().GL_EXT_framebuffer_blit){

+ 2 - 3
engine/src/core-data/Common/MatDefs/Post/Post.vert

@@ -4,8 +4,7 @@ attribute vec4 inPosition;
 attribute vec2 inTexCoord;
 varying vec2 texCoord;
 
-void main() {
-    vec2 pos = (g_WorldViewProjectionMatrix * inPosition).xy;
-    gl_Position = vec4(pos, 0.0, 1.0);
+void main() {  
+    gl_Position = inPosition * 2.0 - 1.0; //vec4(pos, 0.0, 1.0);
     texCoord = inTexCoord;
 }

+ 19 - 3
engine/src/core/com/jme3/post/Filter.java

@@ -80,12 +80,12 @@ public abstract class Filter implements Savable {
             Collection<Caps> caps = renderer.getCaps();
             if (numSamples > 1 && caps.contains(Caps.FrameBufferMultisample) && caps.contains(Caps.OpenGL31)) {
                 renderFrameBuffer = new FrameBuffer(width, height, numSamples);
-                renderedTexture = new Texture2D(width, height, numSamples, textureFormat);
+                renderedTexture = new Texture2D(width, height, numSamples, textureFormat);             
                 //  depthTexture = new Texture2D(width, height, numSamples, depthBufferFormat);
             } else {
                 renderFrameBuffer = new FrameBuffer(width, height, 1);
                 renderedTexture = new Texture2D(width, height, textureFormat);
-//                depthTexture = new Texture2D(width, height,  depthBufferFormat);
+               //                depthTexture = new Texture2D(width, height,  depthBufferFormat);
             }
 
             renderFrameBuffer.setColorTexture(renderedTexture);
@@ -200,7 +200,7 @@ public abstract class Filter implements Savable {
      * @param renderManager
      * @param viewPort
      */
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    public void postQueue(RenderManager renderManager, ViewPort viewPort) {
     }
 
     /**
@@ -211,6 +211,14 @@ public abstract class Filter implements Savable {
     public void preFrame(float tpf) {
     }
 
+    /**
+     * Override this method if you want to make a pass just after the frame has been rendered and just before the filter rendering
+     * @param renderManager
+     * @param viewPort
+     */
+    public void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
+    }
+
     /**
      * Override this method if you want to save extra properties when the filter is saved else only basic properties of the filter will be saved
      * This method should always begin by super.write(ex);
@@ -267,6 +275,14 @@ public abstract class Filter implements Savable {
     public boolean isRequiresDepthTexture() {
         return false;
     }
+    
+     /**
+     * Override this method and return false if your Filter does not need the scene texture
+     * @return
+     */
+    public boolean isRequiresSceneTexture() {
+        return true;
+    }
 
     public List<Pass> getPostRenderPasses() {
         return postRenderPasses;

+ 35 - 13
engine/src/core/com/jme3/post/FilterPostProcessor.java

@@ -40,6 +40,7 @@ import com.jme3.export.InputCapsule;
 import com.jme3.export.OutputCapsule;
 import com.jme3.export.Savable;
 import com.jme3.material.Material;
+import com.jme3.post.filters.TranslucentBucketFilter;
 import com.jme3.renderer.Camera;
 import com.jme3.renderer.Caps;
 import com.jme3.renderer.RenderManager;
@@ -80,6 +81,10 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
     private int originalHeight;
     private int lastFilterIndex = -1;
     private boolean cameraInit = false;
+//    private boolean handleTranslucentBucket = false;
+//    private FrameBuffer transFrameBuffer;
+//    private Material transMaterial;
+//    private boolean isTransparencyRendered=false;
 
     /**
      * Create a FilterProcessor constructor
@@ -159,8 +164,9 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
             filterCam.resize(buff.getWidth(), buff.getHeight(), true);
             fsQuad.setPosition(0, 0);
         }
-
-
+        if (mat.getAdditionalRenderState().isDepthWrite()) {
+            mat.getAdditionalRenderState().setDepthWrite(false);
+        }
         fsQuad.setMaterial(mat);
         fsQuad.updateGeometricState();
 
@@ -179,14 +185,16 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
         for (Iterator<Filter> it = filters.iterator(); it.hasNext();) {
             Filter filter = it.next();
             if (filter.isEnabled()) {
-                filter.preRender(renderManager, viewPort);
+                filter.postQueue(renderManager, viewPort);
             }
         }
 
     }
+    Picture pic = new Picture("debug");
 
-    public void renderFilterChain(Renderer r) {
+    public void renderFilterChain(Renderer r, FrameBuffer sceneFb) {
         Texture2D tex = filterTexture;
+        FrameBuffer buff = null;
         boolean msDepth = depthTexture != null && depthTexture.getImage().getMultiSamples() > 1;
         for (int i = 0; i < filters.size(); i++) {
             Filter filter = filters.get(i);
@@ -216,22 +224,27 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
                     }
                 }
 
+                filter.postFrame(renderManager, viewPort, buff, sceneFb);
+
                 Material mat = filter.getMaterial();
                 if (msDepth && filter.isRequiresDepthTexture()) {
                     mat.setInt("NumSamplesDepth", depthTexture.getImage().getMultiSamples());
                 }
 
-                mat.setTexture("Texture", tex);
-                if (tex.getImage().getMultiSamples() > 1) {
-                    mat.setInt("NumSamples", tex.getImage().getMultiSamples());
-                } else {
-                    mat.clearParam("NumSamples");
+                if (filter.isRequiresSceneTexture()) {
+                    mat.setTexture("Texture", tex);
+                    if (tex.getImage().getMultiSamples() > 1) {
+                        mat.setInt("NumSamples", tex.getImage().getMultiSamples());
+                    } else {
+                        mat.clearParam("NumSamples");
+                    }
                 }
 
-                FrameBuffer buff = outputBuffer;
+                buff = outputBuffer;
                 if (i != lastFilterIndex) {
                     buff = filter.getRenderFrameBuffer();
                     tex = filter.getRenderedTexture();
+
                 }
                 renderProcessing(r, buff, mat);
             }
@@ -240,11 +253,13 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
 
     public void postFrame(FrameBuffer out) {
 
-
+        FrameBuffer sceneBuffer = renderFrameBuffer;
         if (renderFrameBufferMS != null && !renderer.getCaps().contains(Caps.OpenGL31)) {
             renderer.copyFrameBuffer(renderFrameBufferMS, renderFrameBuffer);
+        } else if (renderFrameBufferMS != null) {
+            sceneBuffer = renderFrameBufferMS;
         }
-        renderFilterChain(renderer);
+        renderFilterChain(renderer, sceneBuffer);
 
     }
 
@@ -336,7 +351,6 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
                 renderFrameBufferMS.setColorTexture(msColor);
                 filterTexture = msColor;
                 depthTexture = msDepth;
-                //   samplePositions = ((LwjglRenderer) renderer).getFrameBufferSamplePositions(renderFrameBufferMS);
             } else {
                 renderFrameBufferMS.setDepthBuffer(Format.Depth);
                 renderFrameBufferMS.setColorBuffer(Format.RGBA8);
@@ -420,4 +434,12 @@ public class FilterPostProcessor implements SceneProcessor, Savable {
         numSamples = ic.readInt("numSamples", 0);
         filters = ic.readSavableArrayList("filters", null);
     }
+
+    public Texture2D getDepthTexture() {
+        return depthTexture;
+    }
+
+    public Texture2D getFilterTexture() {
+        return filterTexture;
+    }
 }

+ 19 - 2
engine/src/core/com/jme3/renderer/RenderManager.java

@@ -94,6 +94,7 @@ public class RenderManager {
             camLoc = new Vector3f();
     //temp technique
     private String tmpTech;
+    private boolean handleTranlucentBucket = true;
 
     /**
      * Create a high-level rendering interface over the
@@ -518,7 +519,7 @@ public class RenderManager {
                 //restoring cam state before proceeding children recusively
                 vp.getCamera().setPlaneState(camState);
                 renderScene(children.get(i), vp);
-               
+
             }
         } else if (scene instanceof Geometry) {
 
@@ -607,6 +608,13 @@ public class RenderManager {
         }
     }
 
+    public void renderTranslucentQueue(ViewPort vp) {
+        RenderQueue rq = vp.getQueue();
+        if (!rq.isQueueEmpty(Bucket.Translucent) && handleTranlucentBucket) {
+            rq.renderQueue(Bucket.Translucent, this, vp.getCamera(), true);
+        }
+    }
+
     private void setViewPort(Camera cam) {
         // this will make sure to update viewport only if needed
         if (cam != prevCam || cam.isViewportChanged()) {
@@ -729,7 +737,8 @@ public class RenderManager {
                 proc.postFrame(vp.getOutputFrameBuffer());
             }
         }
-
+        //renders the translucent objects queue after processors have been rendered
+        renderTranslucentQueue(vp);
         // clear any remaining spatials that were not rendered.
         clearQueue(vp);
     }
@@ -768,4 +777,12 @@ public class RenderManager {
     public void setAlphaToCoverage(boolean value) {
         renderer.setAlphaToCoverage(value);
     }
+
+    public boolean isHandleTranslucentBucket() {
+        return handleTranlucentBucket;
+    }
+
+    public void setHandleTranslucentBucket(boolean handleTranslucentBucket) {
+        this.handleTranlucentBucket = handleTranslucentBucket;
+    }
 }

+ 6 - 2
engine/src/core/com/jme3/renderer/Renderer.java

@@ -29,7 +29,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 package com.jme3.renderer;
 
 import com.jme3.light.LightList;
@@ -138,6 +137,12 @@ public interface Renderer {
      */
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst);
 
+    /**
+     * Copies contents from src to dst, scaling if neccessary.
+     * set copyDepth to false ton ly copy the color
+     */
+    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth);
+
     /**
      * Sets the framebuffer that will be drawn to.
      */
@@ -212,5 +217,4 @@ public interface Renderer {
      * @param value
      */
     public void setAlphaToCoverage(boolean value);
-    
 }

+ 56 - 34
engine/src/core/com/jme3/renderer/queue/RenderQueue.java

@@ -29,7 +29,6 @@
  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-
 package com.jme3.renderer.queue;
 
 import com.jme3.renderer.Camera;
@@ -42,28 +41,33 @@ public class RenderQueue {
     private GeometryList opaqueList;
     private GeometryList guiList;
     private GeometryList transparentList;
+    private GeometryList translucentList;
     private GeometryList skyList;
     private GeometryList shadowRecv;
     private GeometryList shadowCast;
 
-    public RenderQueue(){
-        this.opaqueList =  new GeometryList(new OpaqueComparator());
+    public RenderQueue() {
+        this.opaqueList = new GeometryList(new OpaqueComparator());
         this.guiList = new GeometryList(new GuiComparator());
         this.transparentList = new GeometryList(new TransparentComparator());
+        this.translucentList = new GeometryList(new TransparentComparator());
         this.skyList = new GeometryList(new NullComparator());
         this.shadowRecv = new GeometryList(new OpaqueComparator());
         this.shadowCast = new GeometryList(new OpaqueComparator());
     }
 
     public enum Bucket {
+
         Gui,
         Opaque,
         Sky,
         Transparent,
+        Translucent,
         Inherit,
     }
 
     public enum ShadowMode {
+
         Off,
         Cast,
         Receive,
@@ -89,6 +93,8 @@ public class RenderQueue {
      *                     by material first and front to back within the same material.
      *  <li>Bucket.Transparent: {@link com.jme3.renderer.queue.TransparentComparator} which
      *                     sorts purely back to front by leading bounding edge with no material sort.
+     *  <li>Bucket.Translucent: {@link com.jme3.renderer.queue.TransparentComparator} which
+     *                     sorts purely back to front by leading bounding edge with no material sort. this bucket is rendered after post processors.
      *  <li>Bucket.Sky: {@link com.jme3.renderer.queue.NullComparator} which does no sorting
      *                     at all.
      *  <li>Bucket.Gui: {@link com.jme3.renderer.queue.GuiComparator} sorts geometries back to
@@ -108,15 +114,20 @@ public class RenderQueue {
             case Transparent:
                 transparentList = new GeometryList(c);
                 break;
+            case Translucent:
+                translucentList = new GeometryList(c);
+                break;
             default:
-                throw new UnsupportedOperationException("Unknown bucket type: "+bucket);
+                throw new UnsupportedOperationException("Unknown bucket type: " + bucket);
         }
     }
 
-    public void addToShadowQueue(Geometry g, ShadowMode shadBucket){
-        switch (shadBucket){
-            case Inherit: break;
-            case Off: break;
+    public void addToShadowQueue(Geometry g, ShadowMode shadBucket) {
+        switch (shadBucket) {
+            case Inherit:
+                break;
+            case Off:
+                break;
             case Cast:
                 shadowCast.add(g);
                 break;
@@ -128,7 +139,7 @@ public class RenderQueue {
                 shadowRecv.add(g);
                 break;
             default:
-                throw new UnsupportedOperationException("Unrecognized shadow bucket type: "+shadBucket);
+                throw new UnsupportedOperationException("Unrecognized shadow bucket type: " + shadBucket);
         }
     }
 
@@ -146,13 +157,16 @@ public class RenderQueue {
             case Transparent:
                 transparentList.add(g);
                 break;
+            case Translucent:
+                translucentList.add(g);
+                break;
             default:
-                throw new UnsupportedOperationException("Unknown bucket type: "+bucket);
+                throw new UnsupportedOperationException("Unknown bucket type: " + bucket);
         }
     }
 
-    public GeometryList getShadowQueueContent(ShadowMode shadBucket){
-        switch (shadBucket){
+    public GeometryList getShadowQueueContent(ShadowMode shadBucket) {
+        switch (shadBucket) {
             case Cast:
                 return shadowCast;
             case Receive:
@@ -162,30 +176,32 @@ public class RenderQueue {
         }
     }
 
-    private void renderGeometryList(GeometryList list, RenderManager rm, Camera cam, boolean clear){
+    private void renderGeometryList(GeometryList list, RenderManager rm, Camera cam, boolean clear) {
         list.setCamera(cam); // select camera for sorting
         list.sort();
-        for (int i = 0; i < list.size(); i++){
+        for (int i = 0; i < list.size(); i++) {
             Spatial obj = list.get(i);
             assert obj != null;
-                if (obj instanceof Geometry){
-                    Geometry g = (Geometry) obj;
-                    rm.renderGeometry(g);
-                    // make sure to reset queue distance
-                }
-            if (obj != null)
+            if (obj instanceof Geometry) {
+                Geometry g = (Geometry) obj;
+                rm.renderGeometry(g);
+                // make sure to reset queue distance
+            }
+            if (obj != null) {
                 obj.queueDistance = Float.NEGATIVE_INFINITY;
+            }
         }
-        if (clear)
+        if (clear) {
             list.clear();
+        }
     }
 
-    public void renderShadowQueue(GeometryList list, RenderManager rm, Camera cam, boolean clear){
-          renderGeometryList(list, rm, cam, clear);
+    public void renderShadowQueue(GeometryList list, RenderManager rm, Camera cam, boolean clear) {
+        renderGeometryList(list, rm, cam, clear);
     }
 
-    public void renderShadowQueue(ShadowMode shadBucket, RenderManager rm, Camera cam, boolean clear){
-        switch (shadBucket){
+    public void renderShadowQueue(ShadowMode shadBucket, RenderManager rm, Camera cam, boolean clear) {
+        switch (shadBucket) {
             case Cast:
                 renderGeometryList(shadowCast, rm, cam, clear);
                 break;
@@ -197,8 +213,8 @@ public class RenderQueue {
         }
     }
 
-    public boolean isQueueEmpty(Bucket bucket){
-        switch (bucket){
+    public boolean isQueueEmpty(Bucket bucket) {
+        switch (bucket) {
             case Gui:
                 return guiList.size() == 0;
             case Opaque:
@@ -207,17 +223,19 @@ public class RenderQueue {
                 return skyList.size() == 0;
             case Transparent:
                 return transparentList.size() == 0;
+            case Translucent:
+                return translucentList.size() == 0;
             default:
-                throw new UnsupportedOperationException("Unsupported bucket type: "+bucket);
+                throw new UnsupportedOperationException("Unsupported bucket type: " + bucket);
         }
     }
 
-    public void renderQueue(Bucket bucket, RenderManager rm, Camera cam){
+    public void renderQueue(Bucket bucket, RenderManager rm, Camera cam) {
         renderQueue(bucket, rm, cam, true);
     }
 
-    public void renderQueue(Bucket bucket, RenderManager rm, Camera cam, boolean clear){
-        switch (bucket){
+    public void renderQueue(Bucket bucket, RenderManager rm, Camera cam, boolean clear) {
+        switch (bucket) {
             case Gui:
                 renderGeometryList(guiList, rm, cam, clear);
                 break;
@@ -230,18 +248,22 @@ public class RenderQueue {
             case Transparent:
                 renderGeometryList(transparentList, rm, cam, clear);
                 break;
+            case Translucent:
+                renderGeometryList(translucentList, rm, cam, clear);
+                break;
+
             default:
-                throw new UnsupportedOperationException("Unsupported bucket type: "+bucket);
+                throw new UnsupportedOperationException("Unsupported bucket type: " + bucket);
         }
     }
 
-    public void clear(){
+    public void clear() {
         opaqueList.clear();
         guiList.clear();
         transparentList.clear();
+        translucentList.clear();
         skyList.clear();
         shadowCast.clear();
         shadowRecv.clear();
     }
-
 }

+ 3 - 0
engine/src/core/com/jme3/system/NullRenderer.java

@@ -110,6 +110,9 @@ public class NullRenderer implements Renderer {
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
     }
 
+    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
+    }
+    
     public void setFrameBuffer(FrameBuffer fb) {
     }
 

+ 1 - 1
engine/src/desktop-fx/com/jme3/post/filters/BloomFilter.java

@@ -202,7 +202,7 @@ public class BloomFilter extends Filter {
     }
 
     @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    public void postQueue(RenderManager renderManager, ViewPort viewPort) {
         if (glowMode != GlowMode.Scene) {
             backupColor = viewPort.getBackgroundColor();
             viewPort.setBackgroundColor(ColorRGBA.Black);

+ 1 - 1
engine/src/desktop-fx/com/jme3/post/filters/CartoonEdgeFilter.java

@@ -67,7 +67,7 @@ public class CartoonEdgeFilter extends Filter {
     }
 
     @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    public void postQueue(RenderManager renderManager, ViewPort viewPort) {
         Renderer r = renderManager.getRenderer();
         r.setFrameBuffer(normalPass.getRenderFrameBuffer());
         renderManager.getRenderer().clearBuffers(true, true, true);

+ 0 - 4
engine/src/desktop-fx/com/jme3/post/filters/ColorOverlayFilter.java

@@ -76,10 +76,6 @@ public class ColorOverlayFilter extends Filter {
         this.color = color;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
-
     @Override
     public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
         material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md");

+ 0 - 4
engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java

@@ -105,10 +105,6 @@ public class CrossHatchFilter extends Filter {
         return material;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
-
     @Override
     public void cleanUpFilter(Renderer r) {
     }

+ 0 - 4
engine/src/desktop-fx/com/jme3/post/filters/DepthOfFieldFilter.java

@@ -70,10 +70,6 @@ public class DepthOfFieldFilter extends Filter {
         return material;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
-
     @Override
     public void initFilter(AssetManager assets, RenderManager renderManager,
             ViewPort vp, int w, int h) {

+ 0 - 3
engine/src/desktop-fx/com/jme3/post/filters/FadeFilter.java

@@ -71,9 +71,6 @@ public class FadeFilter extends Filter {
         return material;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
 
     @Override
     public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {

+ 0 - 3
engine/src/desktop-fx/com/jme3/post/filters/FogFilter.java

@@ -84,9 +84,6 @@ public class FogFilter extends Filter {
         return material;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
 
     /**
      * returns the fog color

+ 1 - 1
engine/src/desktop-fx/com/jme3/post/filters/LightScatteringFilter.java

@@ -88,7 +88,7 @@ public class LightScatteringFilter extends Filter {
     }
 
     @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    public void postQueue(RenderManager renderManager, ViewPort viewPort) {
         getClipCoordinates(lightPosition, screenLightPos, viewPort.getCamera());
         //  screenLightPos.x = screenLightPos.x / viewPort.getCamera().getWidth();
         //  screenLightPos.y = screenLightPos.y / viewPort.getCamera().getHeight();

+ 0 - 3
engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java

@@ -88,9 +88,6 @@ public class PosterizationFilter extends Filter {
         return material;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
 
     @Override
     public void cleanUpFilter(Renderer r) {

+ 0 - 3
engine/src/desktop-fx/com/jme3/post/filters/RadialBlurFilter.java

@@ -74,9 +74,6 @@ public class RadialBlurFilter extends Filter {
         return material;
     }
 
-    @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
-    }
 
     public float getSampleDist() {
         return sampleDist;

+ 76 - 0
engine/src/desktop-fx/com/jme3/post/filters/TranslucentBucketFilter.java

@@ -0,0 +1,76 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package com.jme3.post.filters;
+
+import com.jme3.asset.AssetManager;
+import com.jme3.material.Material;
+import com.jme3.math.ColorRGBA;
+import com.jme3.post.Filter;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.Renderer;
+import com.jme3.renderer.ViewPort;
+import com.jme3.renderer.queue.RenderQueue;
+import com.jme3.texture.FrameBuffer;
+import com.jme3.texture.Texture2D;
+
+/**
+ *
+ * @author Nehon
+ */
+public final class TranslucentBucketFilter extends Filter {
+
+    private RenderManager renderManager;
+
+    @Override
+    public void initFilter(AssetManager manager, RenderManager rm, ViewPort vp, int w, int h) {
+        this.renderManager = rm;
+        material = new Material(manager, "Common/MatDefs/Post/Overlay.j3md");
+        material.setColor("Color", ColorRGBA.White);
+        Texture2D tex = processor.getFilterTexture();
+        material.setTexture("Texture", tex);
+        if (tex.getImage().getMultiSamples() > 1) {
+            material.setInt("NumSamples", tex.getImage().getMultiSamples());
+        } else {
+            material.clearParam("NumSamples");
+        }
+        renderManager.setHandleTranslucentBucket(false);
+    }
+    
+     /**
+     * Override this method and return false if your Filter does not need the scene texture
+     * @return
+     */
+    public boolean isRequiresSceneTexture() {
+        return false;
+    }
+
+    @Override
+    public void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) {
+        renderManager.setCamera(viewPort.getCamera(), false);
+        renderManager.getRenderer().copyFrameBuffer(prevFilterBuffer, sceneBuffer, false);
+        renderManager.getRenderer().setFrameBuffer(sceneBuffer);
+        viewPort.getQueue().renderQueue(RenderQueue.Bucket.Translucent, renderManager, viewPort.getCamera());
+    }
+
+    @Override
+    public void cleanUpFilter(Renderer r) {
+        if (renderManager != null) {
+            renderManager.setHandleTranslucentBucket(true);
+        }
+    }
+
+    @Override
+    public Material getMaterial() {
+        return material;
+    }
+
+    @Override
+    public void setEnabled(boolean enabled) {
+        super.setEnabled(enabled);
+        if (renderManager != null) {
+            renderManager.setHandleTranslucentBucket(!enabled);
+        }
+    }
+}

+ 6 - 6
engine/src/desktop-fx/com/jme3/post/ssao/SSAOFilter.java

@@ -70,7 +70,7 @@ public class SSAOFilter extends Filter {
     private Pass ssaoPass;
     private Material downSampleMat;
     private Pass downSamplePass;
-    private int downSampleFactor = 1;
+    private float downSampleFactor = 1f;
 
     /**
      * Create a Screen Space Ambiant Occlusion Filter
@@ -101,7 +101,7 @@ public class SSAOFilter extends Filter {
     }
 
     @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    public void postQueue(RenderManager renderManager, ViewPort viewPort) {
         Renderer r = renderManager.getRenderer();
         r.setFrameBuffer(normalPass.getRenderFrameBuffer());
         renderManager.getRenderer().clearBuffers(true, true, true);
@@ -123,7 +123,7 @@ public class SSAOFilter extends Filter {
         postRenderPasses = new ArrayList<Pass>();
 
         normalPass = new Pass();
-        normalPass.init(renderManager.getRenderer(), screenWidth / downSampleFactor, screenHeight / downSampleFactor, Format.RGBA8, Format.Depth);
+        normalPass.init(renderManager.getRenderer(), (int)(screenWidth / downSampleFactor), (int)(screenHeight / downSampleFactor), Format.RGBA8, Format.Depth);
 
 
         frustumNearFar = new Vector2f();
@@ -149,11 +149,11 @@ public class SSAOFilter extends Filter {
 
             @Override
             public boolean requiresDepthAsTexture() {
-                return downSampleFactor == 1;
+                return true;
             }
         };
 
-        ssaoPass.init(renderManager.getRenderer(), screenWidth / downSampleFactor, screenHeight / downSampleFactor, Format.RGBA8, Format.Depth, 1, ssaoMat);
+        ssaoPass.init(renderManager.getRenderer(), (int)(screenWidth / downSampleFactor), (int)(screenHeight / downSampleFactor), Format.RGBA8, Format.Depth, 1, ssaoMat);
         ssaoPass.getRenderedTexture().setMinFilter(Texture.MinFilter.Trilinear);
         ssaoPass.getRenderedTexture().setMagFilter(Texture.MagFilter.Bilinear);
         postRenderPasses.add(ssaoPass);
@@ -174,7 +174,7 @@ public class SSAOFilter extends Filter {
         float xScale = 1.0f / w;
         float yScale = 1.0f / h;
 
-        float blurScale = 2.0f;
+        float blurScale = 2f;
         material.setFloat("XScale", blurScale * xScale);
         material.setFloat("YScale", blurScale * yScale);
 

+ 9 - 1
engine/src/desktop-fx/com/jme3/water/WaterFilter.java

@@ -138,7 +138,7 @@ public class WaterFilter extends Filter {
     }
 
     @Override
-    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    public void postQueue(RenderManager renderManager, ViewPort viewPort) {
         Camera sceneCam = viewPort.getCamera();
         biasMatrix.mult(sceneCam.getViewProjectionMatrix(), textureProjMatrix);
         material.setMatrix4("TextureProjMatrix", textureProjMatrix);
@@ -171,7 +171,15 @@ public class WaterFilter extends Filter {
             reflectionCam.setAxes(reflectionCam.getLeft().negateLocal(), reflectionCam.getUp(), reflectionCam.getDirection().negateLocal());
         }
 
+        boolean rtb = true;
+        if (!renderManager.isHandleTranslucentBucket()) {
+            renderManager.setHandleTranslucentBucket(true);
+            rtb = false;
+        }
         renderManager.renderViewPort(reflectionView, savedTpf);
+        if (!rtb) {
+            renderManager.setHandleTranslucentBucket(false);
+        }
         renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer());
         renderManager.setCamera(sceneCam, false);
     }

+ 89 - 87
engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java

@@ -42,7 +42,6 @@ import static org.lwjgl.opengl.GL11.*;
 public class LwjglGL1Renderer implements GL1Renderer {
 
     private static final Logger logger = Logger.getLogger(LwjglRenderer.class.getName());
-
     private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250);
     private final StringBuilder stringBuf = new StringBuilder(250);
     private final IntBuffer ib1 = BufferUtils.createIntBuffer(1);
@@ -51,20 +50,16 @@ public class LwjglGL1Renderer implements GL1Renderer {
     private final RenderContext context = new RenderContext();
     private final GLObjectManager objManager = new GLObjectManager();
     private final EnumSet<Caps> caps = EnumSet.noneOf(Caps.class);
-
     private int maxTexSize;
     private int maxCubeTexSize;
     private int maxVertCount;
     private int maxTriCount;
-
     private final Statistics statistics = new Statistics();
     private int vpX, vpY, vpW, vpH;
     private int clipX, clipY, clipW, clipH;
-
 //    private Matrix4f worldMatrix = new Matrix4f();
     private Matrix4f viewMatrix = new Matrix4f();
 //    private Matrix4f projMatrix = new Matrix4f();
-
     private boolean colorSet = false;
     private boolean materialSet = false;
 
@@ -93,16 +88,16 @@ public class LwjglGL1Renderer implements GL1Renderer {
         glShadeModel(GL_SMOOTH);
         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
 
-        if (GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){
+        if (GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
             caps.add(Caps.NonPowerOfTwoTextures);
-        }else{
+        } else {
             logger.log(Level.WARNING, "Your graphics card does not "
-                                    + "support non-power-of-2 textures. "
-                                    + "Some features might not work.");
+                    + "support non-power-of-2 textures. "
+                    + "Some features might not work.");
         }
     }
 
-    public void invalidateState(){
+    public void invalidateState() {
         context.reset();
     }
 
@@ -143,8 +138,8 @@ public class LwjglGL1Renderer implements GL1Renderer {
         glClearColor(color.r, color.g, color.b, color.a);
     }
 
-    private void setMaterialColor(int type, ColorRGBA color){
-        if (!materialSet){
+    private void setMaterialColor(int type, ColorRGBA color) {
+        if (!materialSet) {
             materialSet = true;
             glEnable(GL_COLOR_MATERIAL);
         }
@@ -155,8 +150,8 @@ public class LwjglGL1Renderer implements GL1Renderer {
         glMaterial(GL_FRONT_AND_BACK, type, fb16);
     }
 
-    public void setFixedFuncBinding(FixedFuncBinding ffBinding, Object val){
-        switch (ffBinding){
+    public void setFixedFuncBinding(FixedFuncBinding ffBinding, Object val) {
+        switch (ffBinding) {
             case Color:
                 ColorRGBA color = (ColorRGBA) val;
                 glColor4f(color.r, color.g, color.b, color.a);
@@ -177,12 +172,12 @@ public class LwjglGL1Renderer implements GL1Renderer {
         }
     }
 
-    public void clearSetFixedFuncBindings(){
-        if (colorSet){
-            glColor4f(1,1,1,1);
+    public void clearSetFixedFuncBindings() {
+        if (colorSet) {
+            glColor4f(1, 1, 1, 1);
             colorSet = false;
         }
-        if (materialSet){
+        if (materialSet) {
             glDisable(GL_COLOR_MATERIAL);
             materialSet = false; // TODO: not efficient
         }
@@ -231,7 +226,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
             context.colorWriteEnabled = false;
         }
 
-        if (state.isPointSprite()){
+        if (state.isPointSprite()) {
             logger.log(Level.WARNING, "Point Sprite unsupported!");
         }
 
@@ -325,8 +320,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
             context.blendMode = state.getBlendMode();
         }
 
-        if(state.isStencilTest())
+        if (state.isStencilTest()) {
             throw new UnsupportedOperationException("OpenGL 1.1 doesn't support two sided stencil operations.");
+        }
 
     }
 
@@ -519,11 +515,11 @@ public class LwjglGL1Renderer implements GL1Renderer {
         }
 
         // Check sizes if graphics card doesn't support NPOT
-        if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){
-            if (img.getWidth() != 0 && img.getHeight() != 0){
+        if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
+            if (img.getWidth() != 0 && img.getHeight() != 0) {
                 if (!FastMath.isPowerOfTwo(img.getWidth())
-                    || !FastMath.isPowerOfTwo(img.getHeight())
-                    || img.getWidth() != img.getHeight()){
+                        || !FastMath.isPowerOfTwo(img.getHeight())
+                        || img.getWidth() != img.getHeight()) {
 
                     // Resize texture to Power-of-2 size
                     MipMapGenerator.resizeToPowerOf2(img);
@@ -537,9 +533,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
             // generate from base level if required
 
             // Check if hardware mips are supported
-            if (GLContext.getCapabilities().OpenGL14){
+            if (GLContext.getCapabilities().OpenGL14) {
                 glTexParameteri(target, GL14.GL_GENERATE_MIPMAP, GL_TRUE);
-            }else{
+            } else {
                 MipMapGenerator.generateMipMaps(img);
             }
         } else {
@@ -547,33 +543,33 @@ public class LwjglGL1Renderer implements GL1Renderer {
 
         /*
         if (target == GL_TEXTURE_CUBE_MAP) {
-            List<ByteBuffer> data = img.getData();
-            if (data.size() != 6) {
-                logger.log(Level.WARNING, "Invalid texture: {0}\n"
-                        + "Cubemap textures must contain 6 data units.", img);
-                return;
-            }
-            for (int i = 0; i < 6; i++) {
-                TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc);
-            }
+        List<ByteBuffer> data = img.getData();
+        if (data.size() != 6) {
+        logger.log(Level.WARNING, "Invalid texture: {0}\n"
+        + "Cubemap textures must contain 6 data units.", img);
+        return;
+        }
+        for (int i = 0; i < 6; i++) {
+        TextureUtil.uploadTexture(img, GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, i, 0, tdc);
+        }
         } else if (target == EXTTextureArray.GL_TEXTURE_2D_ARRAY_EXT) {
-            List<ByteBuffer> data = img.getData();
-            // -1 index specifies prepare data for 2D Array
-            TextureUtil.uploadTexture(img, target, -1, 0, tdc);
-            for (int i = 0; i < data.size(); i++) {
-                // upload each slice of 2D array in turn
-                // this time with the appropriate index
-                TextureUtil.uploadTexture(img, target, i, 0, tdc);
-            }
+        List<ByteBuffer> data = img.getData();
+        // -1 index specifies prepare data for 2D Array
+        TextureUtil.uploadTexture(img, target, -1, 0, tdc);
+        for (int i = 0; i < data.size(); i++) {
+        // upload each slice of 2D array in turn
+        // this time with the appropriate index
+        TextureUtil.uploadTexture(img, target, i, 0, tdc);
+        }
         } else {*/
-            TextureUtil.uploadTexture(img, target, 0, 0, false);
+        TextureUtil.uploadTexture(img, target, 0, 0, false);
         //}
 
         img.clearUpdateNeeded();
     }
 
     public void setTexture(int unit, Texture tex) {
-        if (unit != 0 || tex.getType() != Texture.Type.TwoDimensional){
+        if (unit != 0 || tex.getType() != Texture.Type.TwoDimensional) {
             //throw new UnsupportedOperationException();
             return;
         }
@@ -617,7 +613,7 @@ public class LwjglGL1Renderer implements GL1Renderer {
 
     private void checkTexturingUsed() {
         Image[] textures = context.boundTextures;
-        if (textures[0] != null){
+        if (textures[0] != null) {
             glDisable(GL_TEXTURE_2D);
             textures[0] = null;
         }
@@ -691,8 +687,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
     }
 
     public void drawTriangleArray(Mesh.Mode mode, int count, int vertCount) {
-        if (count > 1)
+        if (count > 1) {
             throw new UnsupportedOperationException();
+        }
 
         glDrawArrays(convertElementMode(mode), 0, vertCount);
     }
@@ -725,31 +722,34 @@ public class LwjglGL1Renderer implements GL1Renderer {
 
         switch (vb.getBufferType()) {
             case Position:
-                if (!(data instanceof FloatBuffer))
+                if (!(data instanceof FloatBuffer)) {
                     throw new UnsupportedOperationException();
+                }
 
                 glVertexPointer(comps, vb.getStride(), (FloatBuffer) data);
                 break;
             case Normal:
-                if (!(data instanceof FloatBuffer))
+                if (!(data instanceof FloatBuffer)) {
                     throw new UnsupportedOperationException();
+                }
 
-                glNormalPointer(vb.getStride(), (FloatBuffer)data);
+                glNormalPointer(vb.getStride(), (FloatBuffer) data);
                 break;
             case Color:
-                if (data instanceof FloatBuffer){
-                    glColorPointer(comps, vb.getStride(), (FloatBuffer)data);
-                }else if (data instanceof ByteBuffer){
-                    glColorPointer(comps, true, vb.getStride(), (ByteBuffer)data);
-                }else{
+                if (data instanceof FloatBuffer) {
+                    glColorPointer(comps, vb.getStride(), (FloatBuffer) data);
+                } else if (data instanceof ByteBuffer) {
+                    glColorPointer(comps, true, vb.getStride(), (ByteBuffer) data);
+                } else {
                     throw new UnsupportedOperationException();
                 }
                 break;
             case TexCoord:
-                if (!(data instanceof FloatBuffer))
+                if (!(data instanceof FloatBuffer)) {
                     throw new UnsupportedOperationException();
+                }
 
-                glTexCoordPointer(comps, vb.getStride(), (FloatBuffer)data);
+                glTexCoordPointer(comps, vb.getStride(), (FloatBuffer) data);
                 break;
             default:
                 // Ignore, this is an unsupported attribute for OpenGL1.
@@ -761,16 +761,16 @@ public class LwjglGL1Renderer implements GL1Renderer {
         setVertexAttrib(vb, null);
     }
 
-    private void drawElements(int mode, int format, Buffer data){
-        switch (format){
+    private void drawElements(int mode, int format, Buffer data) {
+        switch (format) {
             case GL_UNSIGNED_BYTE:
-                glDrawElements(mode, (ByteBuffer)data);
+                glDrawElements(mode, (ByteBuffer) data);
                 break;
             case GL_UNSIGNED_SHORT:
-                glDrawElements(mode, (ShortBuffer)data);
+                glDrawElements(mode, (ShortBuffer) data);
                 break;
             case GL_UNSIGNED_INT:
-                glDrawElements(mode, (IntBuffer)data);
+                glDrawElements(mode, (IntBuffer) data);
                 break;
             default:
                 throw new UnsupportedOperationException();
@@ -788,38 +788,36 @@ public class LwjglGL1Renderer implements GL1Renderer {
             /*
             int[] modeStart = mesh.getModeStart();
             int[] elementLengths = mesh.getElementLengths();
-
+            
             int elMode = convertElementMode(Mode.Triangles);
             int fmt = convertVertexFormat(indexBuf.getFormat());
-//            int elSize = indexBuf.getFormat().getComponentSize();
-//            int listStart = modeStart[0];
+            //            int elSize = indexBuf.getFormat().getComponentSize();
+            //            int listStart = modeStart[0];
             int stripStart = modeStart[1];
             int fanStart = modeStart[2];
             int curOffset = 0;
             for (int i = 0; i < elementLengths.length; i++) {
-                if (i == stripStart) {
-                    elMode = convertElementMode(Mode.TriangleStrip);
-                } else if (i == fanStart) {
-                    elMode = convertElementMode(Mode.TriangleStrip);
-                }
-                int elementLength = elementLengths[i];
-                indexData.position(curOffset);
-
-                drawElements(elMode,
-                             fmt,
-                             indexData);
-
-                curOffset += elementLength;
+            if (i == stripStart) {
+            elMode = convertElementMode(Mode.TriangleStrip);
+            } else if (i == fanStart) {
+            elMode = convertElementMode(Mode.TriangleStrip);
+            }
+            int elementLength = elementLengths[i];
+            indexData.position(curOffset);
+            
+            drawElements(elMode,
+            fmt,
+            indexData);
+            
+            curOffset += elementLength;
             }*/
         } else {
             drawElements(convertElementMode(mode),
-                         convertVertexFormat(indexBuf.getFormat()),
-                         indexData);
+                    convertVertexFormat(indexBuf.getFormat()),
+                    indexData);
         }
     }
 
-
-
     public void clearVertexAttribs() {
         for (int i = 0; i < 16; i++) {
             VertexBuffer vb = context.boundAttribs[i];
@@ -874,8 +872,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
     }
 
     public void renderMesh(Mesh mesh, int lod, int count) {
-    	if (mesh.getVertexCount() == 0)
+        if (mesh.getVertexCount() == 0) {
             return;
+        }
 
         if (context.pointSize != mesh.getPointSize()) {
             glPointSize(mesh.getPointSize());
@@ -887,8 +886,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
         }
 
         boolean dynamic = false;
-        if (mesh.getBuffer(Type.InterleavedData) != null)
+        if (mesh.getBuffer(Type.InterleavedData) != null) {
             throw new UnsupportedOperationException();
+        }
 
         if (mesh.getNumLodLevels() == 0) {
             IntMap<VertexBuffer> bufs = mesh.getBuffers();
@@ -905,10 +905,10 @@ public class LwjglGL1Renderer implements GL1Renderer {
         statistics.onMeshDrawn(mesh, lod);
 
 //        if (!dynamic) {
-            // dealing with a static object, generate display list
+        // dealing with a static object, generate display list
 //            renderMeshDisplayList(mesh);
 //        } else {
-            renderMeshDefault(mesh, lod, count);
+        renderMeshDefault(mesh, lod, count);
 //        }
 
 
@@ -929,6 +929,9 @@ public class LwjglGL1Renderer implements GL1Renderer {
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
     }
 
+    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
+    }
+
     public void setFrameBuffer(FrameBuffer fb) {
     }
 
@@ -943,5 +946,4 @@ public class LwjglGL1Renderer implements GL1Renderer {
 
     public void deleteBuffer(VertexBuffer vb) {
     }
-
 }

+ 100 - 95
engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java

@@ -204,7 +204,7 @@ public class LwjglRenderer implements Renderer {
         // buffer being used.
         initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
         initialReadBuf = glGetInteger(GL_READ_BUFFER);
-        
+
         // XXX: This has to be GL_BACK for canvas on Mac
         // Since initialDrawBuf is GL_FRONT for pbuffer, gotta
         // change this value later on ...
@@ -326,12 +326,12 @@ public class LwjglRenderer implements Renderer {
             caps.add(Caps.VertexBufferArray);
         }
 
-        if (ctxCaps.GL_ARB_texture_non_power_of_two){
+        if (ctxCaps.GL_ARB_texture_non_power_of_two) {
             caps.add(Caps.NonPowerOfTwoTextures);
-        }else{
+        } else {
             logger.log(Level.WARNING, "Your graphics card does not "
-                                    + "support non-power-of-2 textures. "
-                                    + "Some features might not work.");
+                    + "support non-power-of-2 textures. "
+                    + "Some features might not work.");
         }
 
         boolean latc = ctxCaps.GL_EXT_texture_compression_latc;
@@ -414,11 +414,11 @@ public class LwjglRenderer implements Renderer {
         logger.log(Level.INFO, "Caps: {0}", caps);
     }
 
-    public void invalidateState(){
+    public void invalidateState() {
         context.reset();
         boundShader = null;
         lastFb = null;
-        
+
         initialDrawBuf = glGetInteger(GL_DRAW_BUFFER);
         initialReadBuf = glGetInteger(GL_READ_BUFFER);
     }
@@ -610,96 +610,91 @@ public class LwjglRenderer implements Renderer {
             context.blendMode = state.getBlendMode();
         }
 
-        if(context.stencilTest!=state.isStencilTest()
-                || context.frontStencilStencilFailOperation!=state.getFrontStencilStencilFailOperation()
-                || context.frontStencilDepthFailOperation!=state.getFrontStencilDepthFailOperation()
-                || context.frontStencilDepthPassOperation!=state.getFrontStencilDepthPassOperation()
-                || context.backStencilStencilFailOperation!=state.getBackStencilStencilFailOperation()
-                || context.backStencilDepthFailOperation!=state.getBackStencilDepthFailOperation()
-                || context.backStencilDepthPassOperation!=state.getBackStencilDepthPassOperation()
-                || context.frontStencilFunction!=state.getFrontStencilFunction()
-                || context.backStencilFunction!=state.getBackStencilFunction()
-                ){
-
-            context.frontStencilStencilFailOperation=state.getFrontStencilStencilFailOperation();   //terrible looking, I know
-            context.frontStencilDepthFailOperation=state.getFrontStencilDepthFailOperation();
-            context.frontStencilDepthPassOperation=state.getFrontStencilDepthPassOperation();
-            context.backStencilStencilFailOperation=state.getBackStencilStencilFailOperation();
-            context.backStencilDepthFailOperation=state.getBackStencilDepthFailOperation();
-            context.backStencilDepthPassOperation=state.getBackStencilDepthPassOperation();
-            context.frontStencilFunction=state.getFrontStencilFunction();
-            context.backStencilFunction=state.getBackStencilFunction();
-
-            if(state.isStencilTest()){
+        if (context.stencilTest != state.isStencilTest()
+                || context.frontStencilStencilFailOperation != state.getFrontStencilStencilFailOperation()
+                || context.frontStencilDepthFailOperation != state.getFrontStencilDepthFailOperation()
+                || context.frontStencilDepthPassOperation != state.getFrontStencilDepthPassOperation()
+                || context.backStencilStencilFailOperation != state.getBackStencilStencilFailOperation()
+                || context.backStencilDepthFailOperation != state.getBackStencilDepthFailOperation()
+                || context.backStencilDepthPassOperation != state.getBackStencilDepthPassOperation()
+                || context.frontStencilFunction != state.getFrontStencilFunction()
+                || context.backStencilFunction != state.getBackStencilFunction()) {
+
+            context.frontStencilStencilFailOperation = state.getFrontStencilStencilFailOperation();   //terrible looking, I know
+            context.frontStencilDepthFailOperation = state.getFrontStencilDepthFailOperation();
+            context.frontStencilDepthPassOperation = state.getFrontStencilDepthPassOperation();
+            context.backStencilStencilFailOperation = state.getBackStencilStencilFailOperation();
+            context.backStencilDepthFailOperation = state.getBackStencilDepthFailOperation();
+            context.backStencilDepthPassOperation = state.getBackStencilDepthPassOperation();
+            context.frontStencilFunction = state.getFrontStencilFunction();
+            context.backStencilFunction = state.getBackStencilFunction();
+
+            if (state.isStencilTest()) {
                 glEnable(GL_STENCIL_TEST);
                 glStencilOpSeparate(GL_FRONT,
                         glStencilOpFromStencilOp(state.getFrontStencilStencilFailOperation()),
                         glStencilOpFromStencilOp(state.getFrontStencilDepthFailOperation()),
-                        glStencilOpFromStencilOp(state.getFrontStencilDepthPassOperation())
-                        );
+                        glStencilOpFromStencilOp(state.getFrontStencilDepthPassOperation()));
                 glStencilOpSeparate(GL_BACK,
                         glStencilOpFromStencilOp(state.getBackStencilStencilFailOperation()),
                         glStencilOpFromStencilOp(state.getBackStencilDepthFailOperation()),
-                        glStencilOpFromStencilOp(state.getBackStencilDepthPassOperation())
-                        );
+                        glStencilOpFromStencilOp(state.getBackStencilDepthPassOperation()));
                 glStencilFuncSeparate(GL_FRONT,
                         glStencilFuncFromStencilFunc(state.getFrontStencilFunction()),
-                        0,Integer.MAX_VALUE
-                        );
+                        0, Integer.MAX_VALUE);
                 glStencilFuncSeparate(GL_BACK,
                         glStencilFuncFromStencilFunc(state.getBackStencilFunction()),
-                        0,Integer.MAX_VALUE
-                        );
-            }else{
+                        0, Integer.MAX_VALUE);
+            } else {
                 glDisable(GL_STENCIL_TEST);
             }
         }
 
     }
 
-    private int glStencilOpFromStencilOp(RenderState.StencilOperation s){
-        switch(s){
-        case Keep:
-            return GL_KEEP;
-        case Zero:
-            return GL_ZERO;
-        case Replace:
-            return GL_REPLACE;
-        case Increment:
-            return GL_INCR;
-        case IncrementWrap:
-            return GL_INCR_WRAP;
-        case Decrement:
-            return GL_DECR;
-        case DecrementWrap:
-            return GL_DECR_WRAP;
-        case Invert:
-            return GL_INVERT;
-        default:
-            throw new UnsupportedOperationException("Unrecognized front stencil operation: " + s);
+    private int glStencilOpFromStencilOp(RenderState.StencilOperation s) {
+        switch (s) {
+            case Keep:
+                return GL_KEEP;
+            case Zero:
+                return GL_ZERO;
+            case Replace:
+                return GL_REPLACE;
+            case Increment:
+                return GL_INCR;
+            case IncrementWrap:
+                return GL_INCR_WRAP;
+            case Decrement:
+                return GL_DECR;
+            case DecrementWrap:
+                return GL_DECR_WRAP;
+            case Invert:
+                return GL_INVERT;
+            default:
+                throw new UnsupportedOperationException("Unrecognized front stencil operation: " + s);
         }  //end switch
     }
 
-    private int glStencilFuncFromStencilFunc(RenderState.StencilFunction s){
-        switch(s){
-        case Never:
-            return GL_NEVER;
-        case Less:
-            return GL_LESS;
-        case LessEqual:
-            return GL_LEQUAL;
-        case Greater:
-            return GL_GREATER;
-        case GreaterEqual:
-            return GL_GEQUAL;
-        case Equal:
-            return GL_EQUAL;
-        case NotEqual:
-            return GL_NOTEQUAL;
-        case Always:
-            return GL_ALWAYS;
-        default:
-            throw new UnsupportedOperationException("Unrecognized front stencil functin: " + s);
+    private int glStencilFuncFromStencilFunc(RenderState.StencilFunction s) {
+        switch (s) {
+            case Never:
+                return GL_NEVER;
+            case Less:
+                return GL_LESS;
+            case LessEqual:
+                return GL_LEQUAL;
+            case Greater:
+                return GL_GREATER;
+            case GreaterEqual:
+                return GL_GEQUAL;
+            case Equal:
+                return GL_EQUAL;
+            case NotEqual:
+                return GL_NOTEQUAL;
+            case Always:
+                return GL_ALWAYS;
+            default:
+                throw new UnsupportedOperationException("Unrecognized front stencil functin: " + s);
         }  //end switch
     }
 
@@ -826,7 +821,7 @@ public class LwjglRenderer implements Renderer {
                 if (val instanceof ColorRGBA) {
                     ColorRGBA c = (ColorRGBA) val;
                     glUniform4f(loc, c.r, c.g, c.b, c.a);
-                }else if (val instanceof Vector4f) {
+                } else if (val instanceof Vector4f) {
                     Vector4f c = (Vector4f) val;
                     glUniform4f(loc, c.x, c.y, c.z, c.w);
                 } else {
@@ -991,9 +986,9 @@ public class LwjglRenderer implements Renderer {
             logger.log(Level.WARNING, "Bad compile of:\n{0}{1}",
                     new Object[]{source.getDefines(), source.getSource()});
             if (infoLog != null) {
-                throw new RendererException( "compile error in:" + source + " error:" + infoLog );
+                throw new RendererException("compile error in:" + source + " error:" + infoLog);
             } else {
-                throw new RendererException( "compile error in:" + source + " error: <not provided>" );
+                throw new RendererException("compile error in:" + source + " error: <not provided>");
             }
         }
 
@@ -1072,9 +1067,9 @@ public class LwjglRenderer implements Renderer {
             }
         } else {
             if (infoLog != null) {
-                throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog );
+                throw new RendererException("Shader link failure, shader:" + shader + " info:" + infoLog);
             } else {
-                throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>" );
+                throw new RendererException("Shader link failure, shader:" + shader + " info: <not provided>");
             }
         }
 
@@ -1179,6 +1174,10 @@ public class LwjglRenderer implements Renderer {
     |* Framebuffers                                                      *|
     \*********************************************************************/
     public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst) {
+        copyFrameBuffer(src, dst, true);
+    }
+
+    public void copyFrameBuffer(FrameBuffer src, FrameBuffer dst, boolean copyDepth) {
         if (GLContext.getCapabilities().GL_EXT_framebuffer_blit) {
             int srcW = 0;
             int srcH = 0;
@@ -1212,11 +1211,15 @@ public class LwjglRenderer implements Renderer {
                 dstW = dst.getWidth();
                 dstH = dst.getHeight();
             }
+            int mask = GL_COLOR_BUFFER_BIT;
+            if (copyDepth) {
+                mask |= GL_DEPTH_BUFFER_BIT;
+            }
             glBlitFramebufferEXT(0, 0, srcW, srcH,
-                    0, 0, dstW, dstH,
-                    GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT,
+                    0, 0, dstW, dstH, mask,
                     GL_NEAREST);
 
+
             glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, prevFBO);
             try {
                 checkFrameBufferError();
@@ -1402,7 +1405,7 @@ public class LwjglRenderer implements Renderer {
         if (lastFb == fb) {
             return;
         }
-        
+
         // generate mipmaps for last FB if needed
         if (lastFb != null) {
             for (int i = 0; i < lastFb.getNumColorBuffers(); i++) {
@@ -1643,9 +1646,9 @@ public class LwjglRenderer implements Renderer {
             }
         }
 
-        if (context.pointSprite)
+        if (context.pointSprite) {
             return; // Attempt to fix glTexParameter crash for some ATI GPUs
-
+        }
         // repeat modes
         switch (tex.getType()) {
             case ThreeDimensional:
@@ -1722,14 +1725,15 @@ public class LwjglRenderer implements Renderer {
         }
 
         // Yes, some OpenGL2 cards (GeForce 5) still dont support NPOT.
-          if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two){
-            if (img.getData(0) == null)
+        if (!GLContext.getCapabilities().GL_ARB_texture_non_power_of_two) {
+            if (img.getData(0) == null) {
                 throw new RendererException("non-power-of-2 framebuffer textures are not supported by the video hardware");
-            
-            if (img.getWidth() != 0 && img.getHeight() != 0){ 
+            }
+
+            if (img.getWidth() != 0 && img.getHeight() != 0) {
                 if (!FastMath.isPowerOfTwo(img.getWidth())
-                    || !FastMath.isPowerOfTwo(img.getHeight())
-                    || img.getWidth() != img.getHeight()){
+                        || !FastMath.isPowerOfTwo(img.getHeight())
+                        || img.getWidth() != img.getHeight()) {
 //                    logger.log(Level.WARNING, "Encountered NPOT texture {0}, "
 //                                            + "it might not display correctly.", img);
 
@@ -1739,9 +1743,10 @@ public class LwjglRenderer implements Renderer {
         }
 
         // Check if graphics card doesn't support multisample textures
-        if (!GLContext.getCapabilities().GL_ARB_texture_multisample){
-            if (img.getMultiSamples() > 1)
+        if (!GLContext.getCapabilities().GL_ARB_texture_multisample) {
+            if (img.getMultiSamples() > 1) {
                 throw new RendererException("Multisample textures not supported by graphics hardware");
+            }
         }
 
         if (target == GL_TEXTURE_CUBE_MAP) {

+ 26 - 1
engine/src/test/jme3test/light/TestTransparentShadow.java

@@ -33,6 +33,8 @@
 package jme3test.light;
 
 import com.jme3.app.SimpleApplication;
+import com.jme3.effect.ParticleEmitter;
+import com.jme3.effect.ParticleMesh;
 import com.jme3.light.AmbientLight;
 import com.jme3.light.DirectionalLight;
 import com.jme3.material.Material;
@@ -105,7 +107,30 @@ public class TestTransparentShadow extends SimpleApplication {
         dl.setColor(new ColorRGBA(0.965f, 0.949f, 0.772f, 1f).mult(0.7f));
         rootNode.addLight(dl);
 
-        rootNode.attachChild(teaGeom);
+        rootNode.attachChild(teaGeom);    
+        
+        /** Uses Texture from jme3-test-data library! */
+        ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
+        Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+        mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
+        //mat_red.getAdditionalRenderState().setDepthTest(true);
+        //mat_red.getAdditionalRenderState().setDepthWrite(true);
+        fire.setMaterial(mat_red);
+        fire.setImagesX(2); fire.setImagesY(2); // 2x2 texture animation
+        fire.setEndColor(  new ColorRGBA(1f, 0f, 0f, 1f));   // red
+        fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
+        fire.setInitialVelocity(new Vector3f(0, 2, 0));
+        fire.setStartSize(0.6f);
+        fire.setEndSize(0.1f);
+        fire.setGravity(0);
+        fire.setLowLife(0.5f);
+        fire.setHighLife(1.5f);
+        fire.setVelocityVariation(0.3f);
+        fire.setLocalTranslation(1.0f, 0, 1.0f);
+        fire.setLocalScale(0.3f);
+        fire.setQueueBucket(Bucket.Translucent);
+        rootNode.attachChild(fire);
+
         
         PssmShadowRenderer pssmRenderer = new PssmShadowRenderer(assetManager, 1024, 1);
         pssmRenderer.setDirection(new Vector3f(0.01f, -1f, 0.01f).normalizeLocal());

+ 28 - 1
engine/src/test/jme3test/post/TestMultiViewsFilters.java

@@ -42,6 +42,7 @@ import com.jme3.math.Vector3f;
 import com.jme3.post.FilterPostProcessor;
 import com.jme3.post.filters.BloomFilter;
 import com.jme3.post.filters.CartoonEdgeFilter;
+import com.jme3.post.filters.CrossHatchFilter;
 import com.jme3.post.filters.FogFilter;
 import com.jme3.post.filters.RadialBlurFilter;
 import com.jme3.post.ssao.SSAOFilter;
@@ -62,6 +63,7 @@ public class TestMultiViewsFilters extends SimpleApplication {
         // create the geometry and attach it
         Geometry teaGeom = (Geometry) assetManager.loadModel("Models/Teapot/Teapot.obj");
         teaGeom.scale(3);
+        teaGeom.getMaterial().setColor("GlowColor", ColorRGBA.Green);
 
         DirectionalLight dl = new DirectionalLight();
         dl.setColor(ColorRGBA.White);
@@ -109,18 +111,38 @@ public class TestMultiViewsFilters extends SimpleApplication {
         view4.setClearFlags(true, true, true);
         view4.attachScene(rootNode);
 
+//        Camera cam5 = new Camera(200, 200);
+//        cam5.setFrustumPerspective(45f, (float)cam.getWidth() / cam.getHeight(), 1f, 1000f);
+//        cam5.setName("cam5");
+//        cam5.setViewPort(5.23f, 6.33f, 0.56f, 1.66f);
+//          this.setViewPortAreas(5.23f, 6.33f, 0.56f, 1.66f);
+//          this.setViewPortCamSize(200, 200);
+//          1046,1266,112,332
+        Camera cam5 = cam.clone();
+        cam5.setName("cam5");
+        cam5.setViewPort(1046f/settings.getWidth(), 1266f/settings.getWidth(), 112f/settings.getHeight(), 332f/settings.getHeight());
+        cam5.setLocation(new Vector3f(0.2846221f, 6.4271426f, 0.23380789f));
+        cam5.setRotation(new Quaternion(0.004381671f, 0.72363687f, -0.69015175f, 0.0045953835f));
+
+        final ViewPort view5 = renderManager.createMainView("center", cam5);
+        view5.setClearFlags(true, true, true);
+        view5.attachScene(rootNode);
+
+        
+        
         rootNode.attachChild(SkyFactory.createSky(assetManager, "Textures/Sky/Bright/BrightSky.dds", false));
 
         final FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
         final FilterPostProcessor fpp2 = new FilterPostProcessor(assetManager);
         final FilterPostProcessor fpp3 = new FilterPostProcessor(assetManager);
         final FilterPostProcessor fpp4 = new FilterPostProcessor(assetManager);
+        final FilterPostProcessor fpp5 = new FilterPostProcessor(assetManager);
 
 
         //  fpp.addFilter(new WaterFilter(rootNode, Vector3f.UNIT_Y.mult(-1)));
         fpp3.addFilter(new CartoonEdgeFilter());
 
-        fpp2.addFilter(new BloomFilter());
+        fpp2.addFilter(new CrossHatchFilter());
         final FogFilter ff = new FogFilter(ColorRGBA.Yellow, 0.7f, 2);
         fpp.addFilter(ff);
 
@@ -132,11 +154,14 @@ public class TestMultiViewsFilters extends SimpleApplication {
         SSAOFilter f = new SSAOFilter(1.8899765f, 20.490374f, 0.4699998f, 0.1f);;
         fpp4.addFilter(f);
         SSAOUI ui = new SSAOUI(inputManager, f);
+        
+        fpp5.addFilter(new BloomFilter(BloomFilter.GlowMode.Objects));
 
         viewPort.addProcessor(fpp);
         view2.addProcessor(fpp2);
         view3.addProcessor(fpp3);
         view4.addProcessor(fpp4);
+        view5.addProcessor(fpp5);
 
 
 
@@ -149,11 +174,13 @@ public class TestMultiViewsFilters extends SimpleApplication {
                         view2.removeProcessor(fpp2);
                         view3.removeProcessor(fpp3);
                         view4.removeProcessor(fpp4);
+                        view5.removeProcessor(fpp5);
                     } else {
                         viewPort.addProcessor(fpp);
                         view2.addProcessor(fpp2);
                         view3.addProcessor(fpp3);
                         view4.addProcessor(fpp4);
+                        view5.addProcessor(fpp5);
                     }
                     filterEnabled = !filterEnabled;
                 }

+ 94 - 18
engine/src/test/jme3test/water/TestPostWater.java

@@ -3,20 +3,29 @@ package jme3test.water;
 import com.jme3.app.SimpleApplication;
 import com.jme3.audio.AudioNode;
 import com.jme3.bounding.BoundingBox;
+import com.jme3.effect.ParticleEmitter;
+import com.jme3.effect.ParticleMesh;
 import com.jme3.input.controls.ActionListener;
 import com.jme3.input.controls.KeyTrigger;
 import com.jme3.light.DirectionalLight;
 import com.jme3.material.Material;
+import com.jme3.material.RenderState.BlendMode;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.FastMath;
 import com.jme3.math.Quaternion;
 import com.jme3.math.Vector3f;
 
 import com.jme3.post.FilterPostProcessor;
+import com.jme3.post.filters.DepthOfFieldFilter;
+import com.jme3.post.filters.LightScatteringFilter;
+import com.jme3.post.filters.TranslucentBucketFilter;
 import com.jme3.renderer.Camera;
+import com.jme3.renderer.queue.RenderQueue.Bucket;
 import com.jme3.renderer.queue.RenderQueue.ShadowMode;
+import com.jme3.scene.Geometry;
 import com.jme3.scene.Node;
 import com.jme3.scene.Spatial;
+import com.jme3.scene.shape.Box;
 import com.jme3.terrain.geomipmap.TerrainQuad;
 import com.jme3.terrain.heightmap.AbstractHeightMap;
 import com.jme3.terrain.heightmap.ImageBasedHeightMap;
@@ -35,7 +44,6 @@ import jme3tools.converters.ImageToAwt;
  */
 public class TestPostWater extends SimpleApplication {
 
-    private FilterPostProcessor fpp;
     private Vector3f lightDir = new Vector3f(-4.9236743f, -1.27054665f, 5.896916f);
     private WaterFilter water;
     TerrainQuad terrain;
@@ -65,10 +73,10 @@ public class TestPostWater extends SimpleApplication {
         l.setColor(ColorRGBA.White.clone().multLocal(0.3f));
         mainScene.addLight(l);
 
-        flyCam.setMoveSpeed(50);
+        flyCam.setMoveSpeed(100);
 
         cam.setLocation(new Vector3f(-700, 100, 300));
-        cam.setRotation(new Quaternion().fromAngles(new float[]{FastMath.PI*0.06f,FastMath.PI*0.65f,0}));
+        cam.setRotation(new Quaternion().fromAngles(new float[]{FastMath.PI * 0.06f, FastMath.PI * 0.65f, 0}));
 
 
         Spatial sky = SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false);
@@ -80,44 +88,112 @@ public class TestPostWater extends SimpleApplication {
         waves.setLooping(true);
         audioRenderer.playSource(waves);
 
+        //private FilterPostProcessor fpp;
 
-        fpp = new FilterPostProcessor(assetManager);
-    //    fpp.setNumSamples(4);
 
         water = new WaterFilter(rootNode, lightDir);
+
+        FilterPostProcessor fpp = new FilterPostProcessor(assetManager);
+        fpp.addFilter(water);
+        
+        DepthOfFieldFilter dof=new DepthOfFieldFilter();
+        dof.setFocusDistance(0);
+        dof.setFocusRange(100);        
+        fpp.addFilter(new TranslucentBucketFilter());
+        fpp.addFilter(dof);
+        
+        
+        //     fpp.setNumSamples(4);
+
+
         water.setWaveScale(0.003f);
         water.setMaxAmplitude(2f);
         water.setFoamExistence(new Vector3f(1f, 4, 0.5f));
         water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
         //water.setNormalScale(0.5f);
-        
+
         //water.setRefractionConstant(0.25f);
-        water.setRefractionStrength(0.2f);        
+        water.setRefractionStrength(0.2f);
         //water.setFoamHardness(0.6f);
 
         water.setWaterHeight(initialWaterHeight);
-        fpp.addFilter(water);
+       
+      
+        //  
         viewPort.addProcessor(fpp);
 
         inputManager.addListener(new ActionListener() {
 
             public void onAction(String name, boolean isPressed, float tpf) {
-                if(isPressed){
-                    if(name.equals("foam1")){
-                        water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"));                      
+                if (isPressed) {
+                    if (name.equals("foam1")) {
+                        water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam.jpg"));
                     }
-                    if(name.equals("foam2")){
+                    if (name.equals("foam2")) {
                         water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam2.jpg"));
                     }
-                    if(name.equals("foam3")){
+                    if (name.equals("foam3")) {
                         water.setFoamTexture((Texture2D) assetManager.loadTexture("Common/MatDefs/Water/Textures/foam3.jpg"));
                     }
                 }
             }
-        }, "foam1","foam2","foam3");
+        }, "foam1", "foam2", "foam3");
         inputManager.addMapping("foam1", new KeyTrigger(keyInput.KEY_1));
         inputManager.addMapping("foam2", new KeyTrigger(keyInput.KEY_2));
         inputManager.addMapping("foam3", new KeyTrigger(keyInput.KEY_3));
+        createBox();
+        createFire();
+    }
+    Geometry box;
+
+    private void createBox() {
+        //creating a transluscent box
+        box = new Geometry("box", new Box(new Vector3f(0, 0, 0), 50, 50, 50));
+        Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
+        mat.setColor("Color", new ColorRGBA(1.0f, 0, 0, 0.3f));
+        mat.getAdditionalRenderState().setBlendMode(BlendMode.Alpha);
+        //mat.getAdditionalRenderState().setDepthWrite(false);
+        //mat.getAdditionalRenderState().setDepthTest(false);
+        box.setMaterial(mat);
+        box.setQueueBucket(Bucket.Translucent);
+
+
+        //creating a post view port
+//        ViewPort post=renderManager.createPostView("transpPost", cam);
+//        post.setClearFlags(false, true, true);
+
+
+        box.setLocalTranslation(-600, 0, 300);
+
+        //attaching the box to the post viewport
+        //Don't forget to updateGeometricState() the box in the simpleUpdate
+        //  post.attachScene(box);
+
+        rootNode.attachChild(box);
+    }
+
+    private void createFire() {
+        /** Uses Texture from jme3-test-data library! */
+        ParticleEmitter fire = new ParticleEmitter("Emitter", ParticleMesh.Type.Triangle, 30);
+        Material mat_red = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
+        mat_red.setTexture("Texture", assetManager.loadTexture("Effects/Explosion/flame.png"));
+
+        fire.setMaterial(mat_red);
+        fire.setImagesX(2);
+        fire.setImagesY(2); // 2x2 texture animation
+        fire.setEndColor(new ColorRGBA(1f, 0f, 0f, 1f));   // red
+        fire.setStartColor(new ColorRGBA(1f, 1f, 0f, 0.5f)); // yellow
+        fire.setInitialVelocity(new Vector3f(0, 2, 0));
+        fire.setStartSize(10f);
+        fire.setEndSize(1f);
+        fire.setGravity(0);
+        fire.setLowLife(0.5f);
+        fire.setHighLife(1.5f);
+        fire.setVelocityVariation(0.3f);
+        fire.setLocalTranslation(-500, 30, 300);
+
+        fire.setQueueBucket(Bucket.Translucent);
+        rootNode.attachChild(fire);
     }
 
     private void createTerrain(Node rootNode) {
@@ -138,7 +214,7 @@ public class TestPostWater extends SimpleApplication {
         rock.setWrap(WrapMode.Repeat);
         matRock.setTexture("DiffuseMap_2", rock);
         matRock.setFloat("DiffuseMap_2_scale", 128);
-        Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.png");
+        Texture normalMap0 = assetManager.loadTexture("Textures/Terrain/splat/grass_normal.jpg");
         normalMap0.setWrap(WrapMode.Repeat);
         Texture normalMap1 = assetManager.loadTexture("Textures/Terrain/splat/dirt_normal.png");
         normalMap1.setWrap(WrapMode.Repeat);
@@ -161,8 +237,8 @@ public class TestPostWater extends SimpleApplication {
         List<Camera> cameras = new ArrayList<Camera>();
         cameras.add(getCamera());
         terrain.setMaterial(matRock);
-        terrain.setLocalScale(new Vector3f(5,5,5));
-        terrain.setLocalTranslation(new Vector3f(0,-30,0));
+        terrain.setLocalScale(new Vector3f(5, 5, 5));
+        terrain.setLocalTranslation(new Vector3f(0, -30, 0));
         terrain.setModelBound(new BoundingBox());
         terrain.updateModelBound();
         terrain.setLocked(false); // unlock it so we can edit the height
@@ -171,7 +247,6 @@ public class TestPostWater extends SimpleApplication {
         rootNode.attachChild(terrain);
 
     }
-
     //This part is to emulate tides, slightly varrying the height of the water plane
     private float time = 0.0f;
     private float waterHeight = 0.0f;
@@ -180,6 +255,7 @@ public class TestPostWater extends SimpleApplication {
     @Override
     public void simpleUpdate(float tpf) {
         super.simpleUpdate(tpf);
+        //     box.updateGeometricState();
         time += tpf;
         waterHeight = (float) Math.cos(((time * 0.6f) % FastMath.TWO_PI)) * 1.5f;
         water.setWaterHeight(initialWaterHeight + waterHeight);