diff --git a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java b/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java index ce85507a1..5c8793ece 100644 --- a/engine/src/android/com/jme3/renderer/android/OGLESShaderRenderer.java +++ b/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){ diff --git a/engine/src/core-data/Common/MatDefs/Post/Post.vert b/engine/src/core-data/Common/MatDefs/Post/Post.vert index e785bf3d3..6d80905cd 100644 --- a/engine/src/core-data/Common/MatDefs/Post/Post.vert +++ b/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; } \ No newline at end of file diff --git a/engine/src/core/com/jme3/post/Filter.java b/engine/src/core/com/jme3/post/Filter.java index 8e7187c8b..382935b51 100644 --- a/engine/src/core/com/jme3/post/Filter.java +++ b/engine/src/core/com/jme3/post/Filter.java @@ -80,12 +80,12 @@ public abstract class Filter implements Savable { Collection 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 getPostRenderPasses() { return postRenderPasses; diff --git a/engine/src/core/com/jme3/post/FilterPostProcessor.java b/engine/src/core/com/jme3/post/FilterPostProcessor.java index 8a08b7a2e..b9be95e60 100644 --- a/engine/src/core/com/jme3/post/FilterPostProcessor.java +++ b/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 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; + } } diff --git a/engine/src/core/com/jme3/renderer/RenderManager.java b/engine/src/core/com/jme3/renderer/RenderManager.java index ba041188c..f9cecbf89 100644 --- a/engine/src/core/com/jme3/renderer/RenderManager.java +++ b/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; + } } diff --git a/engine/src/core/com/jme3/renderer/Renderer.java b/engine/src/core/com/jme3/renderer/Renderer.java index 4ec4eaa7f..88202a034 100644 --- a/engine/src/core/com/jme3/renderer/Renderer.java +++ b/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); - } diff --git a/engine/src/core/com/jme3/renderer/queue/RenderQueue.java b/engine/src/core/com/jme3/renderer/queue/RenderQueue.java index 006ece7df..7f8f209d9 100644 --- a/engine/src/core/com/jme3/renderer/queue/RenderQueue.java +++ b/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. *
  • Bucket.Transparent: {@link com.jme3.renderer.queue.TransparentComparator} which * sorts purely back to front by leading bounding edge with no material sort. + *
  • 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. *
  • Bucket.Sky: {@link com.jme3.renderer.queue.NullComparator} which does no sorting * at all. *
  • 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(); } - } diff --git a/engine/src/core/com/jme3/system/NullRenderer.java b/engine/src/core/com/jme3/system/NullRenderer.java index 8ebfa670f..181d88da9 100644 --- a/engine/src/core/com/jme3/system/NullRenderer.java +++ b/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) { } diff --git a/engine/src/desktop-fx/com/jme3/post/filters/BloomFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/BloomFilter.java index af896e918..b1e4875b6 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/BloomFilter.java +++ b/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); diff --git a/engine/src/desktop-fx/com/jme3/post/filters/CartoonEdgeFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/CartoonEdgeFilter.java index d861530e4..a6c347d42 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/CartoonEdgeFilter.java +++ b/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); diff --git a/engine/src/desktop-fx/com/jme3/post/filters/ColorOverlayFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/ColorOverlayFilter.java index acd9f3e08..5a18346af 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/ColorOverlayFilter.java +++ b/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"); diff --git a/engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java index 6cdf14d11..388e52d1b 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java +++ b/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) { } diff --git a/engine/src/desktop-fx/com/jme3/post/filters/DepthOfFieldFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/DepthOfFieldFilter.java index f82858691..238fe067e 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/DepthOfFieldFilter.java +++ b/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) { diff --git a/engine/src/desktop-fx/com/jme3/post/filters/FadeFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/FadeFilter.java index 958794f7b..9832c833a 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/FadeFilter.java +++ b/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) { diff --git a/engine/src/desktop-fx/com/jme3/post/filters/FogFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/FogFilter.java index d29f8c9eb..1739756d4 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/FogFilter.java +++ b/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 diff --git a/engine/src/desktop-fx/com/jme3/post/filters/LightScatteringFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/LightScatteringFilter.java index 89ccfc4df..1dda176e0 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/LightScatteringFilter.java +++ b/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(); diff --git a/engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java index a7b5a1a46..6a9814367 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java +++ b/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) { diff --git a/engine/src/desktop-fx/com/jme3/post/filters/RadialBlurFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/RadialBlurFilter.java index 3f1f090c9..e52b2398c 100644 --- a/engine/src/desktop-fx/com/jme3/post/filters/RadialBlurFilter.java +++ b/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; diff --git a/engine/src/desktop-fx/com/jme3/post/filters/TranslucentBucketFilter.java b/engine/src/desktop-fx/com/jme3/post/filters/TranslucentBucketFilter.java new file mode 100644 index 000000000..8a16983ea --- /dev/null +++ b/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); + } + } +} diff --git a/engine/src/desktop-fx/com/jme3/post/ssao/SSAOFilter.java b/engine/src/desktop-fx/com/jme3/post/ssao/SSAOFilter.java index 63a323389..a2281ec5a 100644 --- a/engine/src/desktop-fx/com/jme3/post/ssao/SSAOFilter.java +++ b/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(); 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); diff --git a/engine/src/desktop-fx/com/jme3/water/WaterFilter.java b/engine/src/desktop-fx/com/jme3/water/WaterFilter.java index d82a8e1ca..d5a8054a9 100644 --- a/engine/src/desktop-fx/com/jme3/water/WaterFilter.java +++ b/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); } diff --git a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java b/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java index 4ad679e7f..97d16df4d 100644 --- a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglGL1Renderer.java +++ b/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 = 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 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 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 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 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 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) { } - } diff --git a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java b/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java index 7e8e6ed3b..0cbc408b8 100644 --- a/engine/src/lwjgl-ogl/com/jme3/renderer/lwjgl/LwjglRenderer.java +++ b/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: " ); + throw new RendererException("compile error in:" + source + " error: "); } } @@ -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: " ); + throw new RendererException("Shader link failure, shader:" + shader + " info: "); } } @@ -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) { diff --git a/engine/src/test/jme3test/light/TestTransparentShadow.java b/engine/src/test/jme3test/light/TestTransparentShadow.java index 123d05f8c..9deed1df8 100644 --- a/engine/src/test/jme3test/light/TestTransparentShadow.java +++ b/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()); diff --git a/engine/src/test/jme3test/post/TestMultiViewsFilters.java b/engine/src/test/jme3test/post/TestMultiViewsFilters.java index 71aa7ab3c..0c29b987b 100644 --- a/engine/src/test/jme3test/post/TestMultiViewsFilters.java +++ b/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; } diff --git a/engine/src/test/jme3test/water/TestPostWater.java b/engine/src/test/jme3test/water/TestPostWater.java index 46decf95a..cdbb2790f 100644 --- a/engine/src/test/jme3test/water/TestPostWater.java +++ b/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 cameras = new ArrayList(); 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);