diff options
Diffstat (limited to 'engine/src/core-effects/com/jme3/post/filters/BloomFilter.java')
-rw-r--r-- | engine/src/core-effects/com/jme3/post/filters/BloomFilter.java | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/engine/src/core-effects/com/jme3/post/filters/BloomFilter.java b/engine/src/core-effects/com/jme3/post/filters/BloomFilter.java new file mode 100644 index 0000000..770e7f4 --- /dev/null +++ b/engine/src/core-effects/com/jme3/post/filters/BloomFilter.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2009-2010 jMonkeyEngine + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of 'jMonkeyEngine' nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * 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.post.filters; + +import com.jme3.asset.AssetManager; +import com.jme3.export.InputCapsule; +import com.jme3.export.JmeExporter; +import com.jme3.export.JmeImporter; +import com.jme3.export.OutputCapsule; +import com.jme3.material.Material; +import com.jme3.math.ColorRGBA; +import com.jme3.post.Filter; +import com.jme3.renderer.RenderManager; +import com.jme3.renderer.ViewPort; +import com.jme3.texture.Image.Format; +import java.io.IOException; +import java.util.ArrayList; + +/** + * BloomFilter is used to make objects in the scene have a glow effect.<br> + * There are 2 mode : Scene and Objects.<br> + * Scene mode extracts the bright parts of the scene to make them glow<br> + * Object mode make objects glow according to their material's glowMap or their GlowColor<br> + * @see <a href="http://jmonkeyengine.org/wiki/doku.php/jme3:advanced:bloom_and_glow">advanced:bloom_and_glow</a> for more details + * + * @author Rémy Bouquet aka Nehon + */ +public class BloomFilter extends Filter { + + /** + * GlowMode specifies if the glow will be applied to the whole scene,or to objects that have aglow color or a glow map + */ + public enum GlowMode { + + /** + * Apply bloom filter to bright areas in the scene. + */ + Scene, + /** + * Apply bloom only to objects that have a glow map or a glow color. + */ + Objects, + /** + * Apply bloom to both bright parts of the scene and objects with glow map. + */ + SceneAndObjects; + } + + private GlowMode glowMode = GlowMode.Scene; + //Bloom parameters + private float blurScale = 1.5f; + private float exposurePower = 5.0f; + private float exposureCutOff = 0.0f; + private float bloomIntensity = 2.0f; + private float downSamplingFactor = 1; + private Pass preGlowPass; + private Pass extractPass; + private Pass horizontalBlur = new Pass(); + private Pass verticalalBlur = new Pass(); + private Material extractMat; + private Material vBlurMat; + private Material hBlurMat; + private int screenWidth; + private int screenHeight; + + /** + * Creates a Bloom filter + */ + public BloomFilter() { + super("BloomFilter"); + } + + /** + * Creates the bloom filter with the specific glow mode + * @param glowMode + */ + public BloomFilter(GlowMode glowMode) { + this(); + this.glowMode = glowMode; + } + + @Override + protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { + screenWidth = (int) Math.max(1, (w / downSamplingFactor)); + screenHeight = (int) Math.max(1, (h / downSamplingFactor)); + // System.out.println(screenWidth + " " + screenHeight); + if (glowMode != GlowMode.Scene) { + preGlowPass = new Pass(); + preGlowPass.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth); + } + + postRenderPasses = new ArrayList<Pass>(); + //configuring extractPass + extractMat = new Material(manager, "Common/MatDefs/Post/BloomExtract.j3md"); + extractPass = new Pass() { + + @Override + public boolean requiresSceneAsTexture() { + return true; + } + + @Override + public void beforeRender() { + extractMat.setFloat("ExposurePow", exposurePower); + extractMat.setFloat("ExposureCutoff", exposureCutOff); + if (glowMode != GlowMode.Scene) { + extractMat.setTexture("GlowMap", preGlowPass.getRenderedTexture()); + } + extractMat.setBoolean("Extract", glowMode != GlowMode.Objects); + } + }; + + extractPass.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth, 1, extractMat); + postRenderPasses.add(extractPass); + + //configuring horizontal blur pass + hBlurMat = new Material(manager, "Common/MatDefs/Blur/HGaussianBlur.j3md"); + horizontalBlur = new Pass() { + + @Override + public void beforeRender() { + hBlurMat.setTexture("Texture", extractPass.getRenderedTexture()); + hBlurMat.setFloat("Size", screenWidth); + hBlurMat.setFloat("Scale", blurScale); + } + }; + + horizontalBlur.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth, 1, hBlurMat); + postRenderPasses.add(horizontalBlur); + + //configuring vertical blur pass + vBlurMat = new Material(manager, "Common/MatDefs/Blur/VGaussianBlur.j3md"); + verticalalBlur = new Pass() { + + @Override + public void beforeRender() { + vBlurMat.setTexture("Texture", horizontalBlur.getRenderedTexture()); + vBlurMat.setFloat("Size", screenHeight); + vBlurMat.setFloat("Scale", blurScale); + } + }; + + verticalalBlur.init(renderManager.getRenderer(), screenWidth, screenHeight, Format.RGBA8, Format.Depth, 1, vBlurMat); + postRenderPasses.add(verticalalBlur); + + + //final material + material = new Material(manager, "Common/MatDefs/Post/BloomFinal.j3md"); + material.setTexture("BloomTex", verticalalBlur.getRenderedTexture()); + } + + + @Override + protected Material getMaterial() { + material.setFloat("BloomIntensity", bloomIntensity); + return material; + } + + @Override + protected void postQueue(RenderManager renderManager, ViewPort viewPort) { + if (glowMode != GlowMode.Scene) { + renderManager.getRenderer().setBackgroundColor(ColorRGBA.BlackNoAlpha); + renderManager.getRenderer().setFrameBuffer(preGlowPass.getRenderFrameBuffer()); + renderManager.getRenderer().clearBuffers(true, true, true); + renderManager.setForcedTechnique("Glow"); + renderManager.renderViewPortQueues(viewPort, false); + renderManager.setForcedTechnique(null); + renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); + } + } + + /** + * returns the bloom intensity + * @return + */ + public float getBloomIntensity() { + return bloomIntensity; + } + + /** + * intensity of the bloom effect default is 2.0 + * @param bloomIntensity + */ + public void setBloomIntensity(float bloomIntensity) { + this.bloomIntensity = bloomIntensity; + } + + /** + * returns the blur scale + * @return + */ + public float getBlurScale() { + return blurScale; + } + + /** + * sets The spread of the bloom default is 1.5f + * @param blurScale + */ + public void setBlurScale(float blurScale) { + this.blurScale = blurScale; + } + + /** + * returns the exposure cutoff<br> + * for more details see {@link setExposureCutOff(float exposureCutOff)} + * @return + */ + public float getExposureCutOff() { + return exposureCutOff; + } + + /** + * Define the color threshold on which the bloom will be applied (0.0 to 1.0) + * @param exposureCutOff + */ + public void setExposureCutOff(float exposureCutOff) { + this.exposureCutOff = exposureCutOff; + } + + /** + * returns the exposure power<br> + * form more details see {@link setExposurePower(float exposurePower)} + * @return + */ + public float getExposurePower() { + return exposurePower; + } + + /** + * defines how many time the bloom extracted color will be multiplied by itself. default id 5.0<br> + * a high value will reduce rough edges in the bloom and somhow the range of the bloom area * + * @param exposurePower + */ + public void setExposurePower(float exposurePower) { + this.exposurePower = exposurePower; + } + + /** + * returns the downSampling factor<br> + * form more details see {@link setDownSamplingFactor(float downSamplingFactor)} + * @return + */ + public float getDownSamplingFactor() { + return downSamplingFactor; + } + + /** + * Sets the downSampling factor : the size of the computed texture will be divided by this factor. default is 1 for no downsampling + * A 2 value is a good way of widening the blur + * @param downSamplingFactor + */ + public void setDownSamplingFactor(float downSamplingFactor) { + this.downSamplingFactor = downSamplingFactor; + } + + @Override + public void write(JmeExporter ex) throws IOException { + super.write(ex); + OutputCapsule oc = ex.getCapsule(this); + oc.write(glowMode, "glowMode", GlowMode.Scene); + oc.write(blurScale, "blurScale", 1.5f); + oc.write(exposurePower, "exposurePower", 5.0f); + oc.write(exposureCutOff, "exposureCutOff", 0.0f); + oc.write(bloomIntensity, "bloomIntensity", 2.0f); + oc.write(downSamplingFactor, "downSamplingFactor", 1); + } + + @Override + public void read(JmeImporter im) throws IOException { + super.read(im); + InputCapsule ic = im.getCapsule(this); + glowMode = ic.readEnum("glowMode", GlowMode.class, GlowMode.Scene); + blurScale = ic.readFloat("blurScale", 1.5f); + exposurePower = ic.readFloat("exposurePower", 5.0f); + exposureCutOff = ic.readFloat("exposureCutOff", 0.0f); + bloomIntensity = ic.readFloat("bloomIntensity", 2.0f); + downSamplingFactor = ic.readFloat("downSamplingFactor", 1); + } +} |