1 /* 2 * Copyright (c) 2009-2010 jMonkeyEngine 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are 7 * met: 8 * 9 * * Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * * Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors 17 * may be used to endorse or promote products derived from this software 18 * without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 package com.jme3.post.filters; 33 34 import com.jme3.asset.AssetManager; 35 import com.jme3.material.Material; 36 import com.jme3.math.ColorRGBA; 37 import com.jme3.post.Filter; 38 import com.jme3.post.Filter.Pass; 39 import com.jme3.renderer.RenderManager; 40 import com.jme3.renderer.Renderer; 41 import com.jme3.renderer.ViewPort; 42 import com.jme3.texture.Image.Format; 43 44 /** 45 * Applies a cartoon-style edge detection filter to all objects in the scene. 46 * 47 * @author Kirill Vainer 48 */ 49 public class CartoonEdgeFilter extends Filter { 50 51 private Pass normalPass; 52 private float edgeWidth = 1.0f; 53 private float edgeIntensity = 1.0f; 54 private float normalThreshold = 0.5f; 55 private float depthThreshold = 0.1f; 56 private float normalSensitivity = 1.0f; 57 private float depthSensitivity = 10.0f; 58 private ColorRGBA edgeColor = new ColorRGBA(0, 0, 0, 1); 59 60 /** 61 * Creates a CartoonEdgeFilter 62 */ CartoonEdgeFilter()63 public CartoonEdgeFilter() { 64 super("CartoonEdgeFilter"); 65 } 66 67 @Override isRequiresDepthTexture()68 protected boolean isRequiresDepthTexture() { 69 return true; 70 } 71 72 @Override postQueue(RenderManager renderManager, ViewPort viewPort)73 protected void postQueue(RenderManager renderManager, ViewPort viewPort) { 74 Renderer r = renderManager.getRenderer(); 75 r.setFrameBuffer(normalPass.getRenderFrameBuffer()); 76 renderManager.getRenderer().clearBuffers(true, true, true); 77 renderManager.setForcedTechnique("PreNormalPass"); 78 renderManager.renderViewPortQueues(viewPort, false); 79 renderManager.setForcedTechnique(null); 80 renderManager.getRenderer().setFrameBuffer(viewPort.getOutputFrameBuffer()); 81 } 82 83 @Override getMaterial()84 protected Material getMaterial() { 85 material.setTexture("NormalsTexture", normalPass.getRenderedTexture()); 86 return material; 87 } 88 89 @Override initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h)90 protected void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) { 91 normalPass = new Pass(); 92 normalPass.init(renderManager.getRenderer(), w, h, Format.RGBA8, Format.Depth); 93 material = new Material(manager, "Common/MatDefs/Post/CartoonEdge.j3md"); 94 material.setFloat("EdgeWidth", edgeWidth); 95 material.setFloat("EdgeIntensity", edgeIntensity); 96 material.setFloat("NormalThreshold", normalThreshold); 97 material.setFloat("DepthThreshold", depthThreshold); 98 material.setFloat("NormalSensitivity", normalSensitivity); 99 material.setFloat("DepthSensitivity", depthSensitivity); 100 material.setColor("EdgeColor", edgeColor); 101 } 102 103 /** 104 * Return the depth sensitivity<br> 105 * for more details see {@link setDepthSensitivity(float depthSensitivity)} 106 * @return 107 */ getDepthSensitivity()108 public float getDepthSensitivity() { 109 return depthSensitivity; 110 } 111 112 /** 113 * sets the depth sensitivity<br> 114 * defines how much depth will influence edges, default is 10 115 * @param depthSensitivity 116 */ setDepthSensitivity(float depthSensitivity)117 public void setDepthSensitivity(float depthSensitivity) { 118 this.depthSensitivity = depthSensitivity; 119 if (material != null) { 120 material.setFloat("DepthSensitivity", depthSensitivity); 121 } 122 } 123 124 /** 125 * returns the depth threshold<br> 126 * for more details see {@link setDepthThreshold(float depthThreshold)} 127 * @return 128 */ getDepthThreshold()129 public float getDepthThreshold() { 130 return depthThreshold; 131 } 132 133 /** 134 * sets the depth threshold<br> 135 * Defines at what threshold of difference of depth an edge is outlined default is 0.1f 136 * @param depthThreshold 137 */ setDepthThreshold(float depthThreshold)138 public void setDepthThreshold(float depthThreshold) { 139 this.depthThreshold = depthThreshold; 140 if (material != null) { 141 material.setFloat("DepthThreshold", depthThreshold); 142 } 143 } 144 145 /** 146 * returns the edge intensity<br> 147 * for more details see {@link setEdgeIntensity(float edgeIntensity) } 148 * @return 149 */ getEdgeIntensity()150 public float getEdgeIntensity() { 151 return edgeIntensity; 152 } 153 154 /** 155 * sets the edge intensity<br> 156 * Defineshow visilble will be the outlined edges 157 * @param edgeIntensity 158 */ setEdgeIntensity(float edgeIntensity)159 public void setEdgeIntensity(float edgeIntensity) { 160 this.edgeIntensity = edgeIntensity; 161 if (material != null) { 162 material.setFloat("EdgeIntensity", edgeIntensity); 163 } 164 } 165 166 /** 167 * returns the width of the edges 168 * @return 169 */ getEdgeWidth()170 public float getEdgeWidth() { 171 return edgeWidth; 172 } 173 174 /** 175 * sets the witdh of the edge in pixels default is 1 176 * @param edgeWidth 177 */ setEdgeWidth(float edgeWidth)178 public void setEdgeWidth(float edgeWidth) { 179 this.edgeWidth = edgeWidth; 180 if (material != null) { 181 material.setFloat("EdgeWidth", edgeWidth); 182 } 183 184 } 185 186 /** 187 * returns the normals sensitivity<br> 188 * form more details see {@link setNormalSensitivity(float normalSensitivity)} 189 * @return 190 */ getNormalSensitivity()191 public float getNormalSensitivity() { 192 return normalSensitivity; 193 } 194 195 /** 196 * sets the normals sensitivity default is 1 197 * @param normalSensitivity 198 */ setNormalSensitivity(float normalSensitivity)199 public void setNormalSensitivity(float normalSensitivity) { 200 this.normalSensitivity = normalSensitivity; 201 if (material != null) { 202 material.setFloat("NormalSensitivity", normalSensitivity); 203 } 204 } 205 206 /** 207 * returns the normal threshold<br> 208 * for more details see {@link setNormalThreshold(float normalThreshold)} 209 * 210 * @return 211 */ getNormalThreshold()212 public float getNormalThreshold() { 213 return normalThreshold; 214 } 215 216 /** 217 * sets the normal threshold default is 0.5 218 * @param normalThreshold 219 */ setNormalThreshold(float normalThreshold)220 public void setNormalThreshold(float normalThreshold) { 221 this.normalThreshold = normalThreshold; 222 if (material != null) { 223 material.setFloat("NormalThreshold", normalThreshold); 224 } 225 } 226 227 /** 228 * returns the edge color 229 * @return 230 */ getEdgeColor()231 public ColorRGBA getEdgeColor() { 232 return edgeColor; 233 } 234 235 /** 236 * Sets the edge color, default is black 237 * @param edgeColor 238 */ setEdgeColor(ColorRGBA edgeColor)239 public void setEdgeColor(ColorRGBA edgeColor) { 240 this.edgeColor = edgeColor; 241 if (material != null) { 242 material.setColor("EdgeColor", edgeColor); 243 } 244 } 245 } 246