/* * 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.effect.ParticleEmitter; 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.scene.Node; import com.jme3.scene.Spatial; import com.jme3.texture.FrameBuffer; import com.jme3.texture.Texture; import com.jme3.texture.Texture2D; import java.util.logging.Level; import java.util.logging.Logger; /** * A filter to handle translucent objects when rendering a scene with filters that uses depth like WaterFilter and SSAOFilter * just create a TranslucentBucketFilter and add it to the Filter list of a FilterPostPorcessor * @author Nehon */ public final class TranslucentBucketFilter extends Filter { private final static Logger logger = Logger.getLogger(TranslucentBucketFilter.class.getName()); private RenderManager renderManager; private boolean enabledSoftParticles = false; private Texture depthTexture; private ViewPort viewPort; public TranslucentBucketFilter() { super("TranslucentBucketFilter"); } public TranslucentBucketFilter(boolean enabledSoftParticles) { this(); this.enabledSoftParticles = enabledSoftParticles; } @Override protected void initFilter(AssetManager manager, RenderManager rm, ViewPort vp, int w, int h) { this.renderManager = rm; this.viewPort = vp; 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); if (enabledSoftParticles && depthTexture != null) { initSoftParticles(vp, true); } } private void initSoftParticles(ViewPort vp, boolean enabledSP) { if (depthTexture != null) { for (Spatial scene : vp.getScenes()) { makeSoftParticleEmitter(scene, enabledSP && enabled); } } } @Override protected void setDepthTexture(Texture depthTexture) { this.depthTexture = depthTexture; if (enabledSoftParticles && depthTexture != null) { initSoftParticles(viewPort, true); } } /** * Override this method and return false if your Filter does not need the scene texture * @return */ @Override protected boolean isRequiresSceneTexture() { return false; } @Override protected boolean isRequiresDepthTexture() { return enabledSoftParticles; } @Override protected void postFrame(RenderManager renderManager, ViewPort viewPort, FrameBuffer prevFilterBuffer, FrameBuffer sceneBuffer) { renderManager.setCamera(viewPort.getCamera(), false); if (prevFilterBuffer != sceneBuffer) { renderManager.getRenderer().copyFrameBuffer(prevFilterBuffer, sceneBuffer, false); } renderManager.getRenderer().setFrameBuffer(sceneBuffer); viewPort.getQueue().renderQueue(RenderQueue.Bucket.Translucent, renderManager, viewPort.getCamera()); } @Override protected void cleanUpFilter(Renderer r) { if (renderManager != null) { renderManager.setHandleTranslucentBucket(true); } initSoftParticles(viewPort, false); } @Override protected Material getMaterial() { return material; } @Override public void setEnabled(boolean enabled) { super.setEnabled(enabled); if (renderManager != null) { renderManager.setHandleTranslucentBucket(!enabled); } initSoftParticles(viewPort, enabledSoftParticles); } private void makeSoftParticleEmitter(Spatial scene, boolean enabled) { if (scene instanceof Node) { Node n = (Node) scene; for (Spatial child : n.getChildren()) { makeSoftParticleEmitter(child, enabled); } } if (scene instanceof ParticleEmitter) { ParticleEmitter emitter = (ParticleEmitter) scene; if (enabled) { enabledSoftParticles = enabled; emitter.getMaterial().selectTechnique("SoftParticles", renderManager); emitter.getMaterial().setTexture("DepthTexture", processor.getDepthTexture()); emitter.setQueueBucket(RenderQueue.Bucket.Translucent); logger.log(Level.INFO, "Made particle Emitter {0} soft.", emitter.getName()); } else { emitter.getMaterial().clearParam("DepthTexture"); emitter.getMaterial().selectTechnique("Default", renderManager); // emitter.setQueueBucket(RenderQueue.Bucket.Transparent); logger.log(Level.INFO, "Particle Emitter {0} is not soft anymore.", emitter.getName()); } } } }