Home | History | Annotate | Download | only in filters
      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      */
     63     public CartoonEdgeFilter() {
     64         super("CartoonEdgeFilter");
     65     }
     66 
     67     @Override
     68     protected boolean isRequiresDepthTexture() {
     69         return true;
     70     }
     71 
     72     @Override
     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
     84     protected Material getMaterial() {
     85         material.setTexture("NormalsTexture", normalPass.getRenderedTexture());
     86         return material;
     87     }
     88 
     89     @Override
     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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    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      */
    191     public float getNormalSensitivity() {
    192         return normalSensitivity;
    193     }
    194 
    195     /**
    196      * sets the normals sensitivity default is 1
    197      * @param normalSensitivity
    198      */
    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      */
    212     public float getNormalThreshold() {
    213         return normalThreshold;
    214     }
    215 
    216     /**
    217      * sets the normal threshold default is 0.5
    218      * @param normalThreshold
    219      */
    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      */
    231     public ColorRGBA getEdgeColor() {
    232         return edgeColor;
    233     }
    234 
    235     /**
    236      * Sets the edge color, default is black
    237      * @param edgeColor
    238      */
    239     public void setEdgeColor(ColorRGBA edgeColor) {
    240         this.edgeColor = edgeColor;
    241         if (material != null) {
    242             material.setColor("EdgeColor", edgeColor);
    243         }
    244     }
    245 }
    246