Procházet zdrojové kódy

Added PosterizationFilter contribution by Roy Straver a.k.a. Baal Garnaal

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7001 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om před 14 roky
rodič
revize
7c9d4f19e5

+ 18 - 0
engine/src/core-data/Common/MatDefs/Post/Posterization.frag

@@ -0,0 +1,18 @@
+uniform sampler2D m_Texture;
+varying vec2 texCoord;
+ 
+uniform int m_NumColors;
+uniform float m_Gamma;
+uniform float m_Strength;
+ 
+void main() {
+    vec4 texVal = texture2D(m_Texture, texCoord);
+ 
+    texVal = pow(texVal, vec4(m_Gamma));
+    texVal = texVal * m_NumColors;
+    texVal = floor(texVal);
+    texVal = texVal / m_NumColors;
+    texVal = pow(texVal, vec4(1.0/m_Gamma));
+ 
+    gl_FragColor = mix(texture2D(m_Texture, texCoord), texVal, m_Strength);
+}

+ 32 - 0
engine/src/core-data/Common/MatDefs/Post/Posterization.j3md

@@ -0,0 +1,32 @@
+MaterialDef Posterization {
+ 
+    MaterialParameters {
+        Int NumSamples
+        Texture2D Texture;
+        Int NumColors;
+        Float Gamma;
+        Float Strength;
+    }
+ 
+    Technique {
+        VertexShader GLSL150:   Common/MatDefs/Post/Post15.vert
+        FragmentShader GLSL150: Common/MatDefs/Post/Posterization15.frag
+ 
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+ 
+    Technique {
+        VertexShader GLSL100:   Common/MatDefs/Post/Post.vert
+        FragmentShader GLSL100: Common/MatDefs/Post/Posterization.frag
+ 
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+ 
+    Technique FixedFunc {
+    }
+ 
+}

+ 20 - 0
engine/src/core-data/Common/MatDefs/Post/Posterization15.frag

@@ -0,0 +1,20 @@
+#import "Common/ShaderLib/MultiSample.glsllib"
+ 
+uniform COLORTEXTURE m_Texture;
+in vec2 texCoord;
+ 
+uniform int m_NumColors;
+uniform float m_Gamma;
+uniform float m_Strength;
+ 
+void main() {
+    vec4 texVal = getColor(m_Texture, texCoord);
+ 
+    texVal = pow(texVal, vec4(m_Gamma));
+    texVal = texVal * m_NumColors;
+    texVal = floor(texVal);
+    texVal = texVal / m_NumColors;
+    texVal = pow(texVal, vec4(1.0/m_Gamma));
+ 
+    gl_FragColor = mix(getColor(m_Texture, texCoord), texVal, m_Strength);
+}

+ 149 - 0
engine/src/desktop-fx/com/jme3/post/filters/PosterizationFilter.java

@@ -0,0 +1,149 @@
+/*
+ * 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.material.Material;
+import com.jme3.post.Filter;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.Renderer;
+import com.jme3.renderer.ViewPort;
+
+/**
+ * A Post Processing filter to change colors appear with sharp edges as if the
+ * available amount of colors available was not enough to draw the true image.
+ * Possibly useful in cartoon styled games. Use the strength variable to lessen
+ * influence of this filter on the total result. Values from 0.2 to 0.7 appear
+ * to give nice results.
+ *
+ * Based on an article from Geeks3D:
+ *    <a href="http://www.geeks3d.com/20091027/shader-library-posterization-post-processing-effect-glsl/" rel="nofollow">http://www.geeks3d.com/20091027/shader-library-posterization-post-processing-effect-glsl/</a>
+ *
+ * @author: Roy Straver a.k.a. Baal Garnaal
+ */
+public class PosterizationFilter extends Filter {
+
+    private int numColors = 8;
+    private float gamma = 0.6f;
+    private float strength = 1.0f;
+
+    public PosterizationFilter() {
+        super("PosterizationFilter");
+    }
+
+    public PosterizationFilter(int numColors) {
+        this();
+        this.numColors = numColors;
+    }
+
+    public PosterizationFilter(int numColors, float gamma) {
+        this(numColors);
+        this.gamma = gamma;
+    }
+
+    @Override
+    public boolean isRequiresDepthTexture() {
+        return false;
+    }
+
+    @Override
+    public void initFilter(AssetManager manager, RenderManager renderManager, ViewPort vp, int w, int h) {
+        material = new Material(manager, "Common/MatDefs/Post/Posterization.j3md");
+        material.setInt("NumColors", numColors);
+        material.setFloat("Gamma", gamma);
+        material.setFloat("Strength", strength);
+    }
+
+    @Override
+    public Material getMaterial() {
+        return material;
+    }
+
+    @Override
+    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    }
+
+    @Override
+    public void cleanUpFilter(Renderer r) {
+    }
+
+    /*
+     * Sets number of color levels used to draw the screen
+     */
+    public void setNumColors(int numColors) {
+        this.numColors = numColors;
+        if (material != null) {
+            material.setInt("NumColors", numColors);
+        }
+    }
+
+    /*
+     * Sets gamma level used to enhange visual quality
+     */
+    public void setGamma(float gamma) {
+        this.gamma = gamma;
+        if (material != null) {
+            material.setFloat("Gamma", gamma);
+        }
+    }
+
+    /*
+     * Sets urrent strength value, i.e. influence on final image
+     */
+    public void setStrength(float strength) {
+        this.strength = strength;
+        if (material != null) {
+            material.setFloat("Strength", strength);
+        }
+    }
+
+    /*
+     * Returns number of color levels used
+     */
+    public int getNumColors() {
+        return numColors;
+    }
+
+    /*
+     * Returns current gamma value
+     */
+    public float getGamma() {
+        return gamma;
+    }
+
+    /*
+     * Returns current strength value, i.e. influence on final image
+     */
+    public float getStrength() {
+        return strength;
+    }
+}

+ 157 - 0
engine/src/test/jme3test/post/TestPosterization.java

@@ -0,0 +1,157 @@
+/*
+ * 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 jme3test.post;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.KeyInput;
+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.math.ColorRGBA;
+import com.jme3.math.Quaternion;
+import com.jme3.math.Vector3f;
+import com.jme3.post.FilterPostProcessor;
+import com.jme3.post.filters.BloomFilter;
+import com.jme3.post.filters.CrossHatchFilter;
+import com.jme3.post.filters.PosterizationFilter;
+import com.jme3.renderer.queue.RenderQueue.ShadowMode;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Spatial;
+import com.jme3.scene.debug.WireFrustum;
+import com.jme3.scene.shape.Box;
+import com.jme3.util.SkyFactory;
+
+public class TestPosterization extends SimpleApplication {
+
+    float angle;
+    Spatial lightMdl;
+    Spatial teapot;
+    Geometry frustumMdl;
+    WireFrustum frustum;
+    boolean active=true;
+    FilterPostProcessor fpp;
+    
+    public static void main(String[] args){
+        TestPosterization app = new TestPosterization();
+        app.start();
+    }
+
+    @Override
+    public void simpleInitApp() {
+        // put the camera in a bad position
+        cam.setLocation(new Vector3f(-2.336393f, 11.91392f, -7.139601f));
+        cam.setRotation(new Quaternion(0.23602544f, 0.11321983f, -0.027698677f, 0.96473104f));
+        //cam.setFrustumFar(1000);
+
+
+        Material mat = new Material(assetManager,"Common/MatDefs/Light/Lighting.j3md");
+        mat.setFloat("Shininess", 15f);
+        mat.setBoolean("UseMaterialColors", true);
+        mat.setColor("Ambient", ColorRGBA.Yellow.mult(0.2f));
+        mat.setColor("Diffuse", ColorRGBA.Yellow.mult(0.2f));
+        mat.setColor("Specular", ColorRGBA.Yellow.mult(0.8f));
+
+    
+
+
+        Material matSoil = new Material(assetManager,"Common/MatDefs/Light/Lighting.j3md");
+        matSoil.setFloat("Shininess", 15f);
+        matSoil.setBoolean("UseMaterialColors", true);
+        matSoil.setColor("Ambient", ColorRGBA.Gray);
+        matSoil.setColor("Diffuse", ColorRGBA.Black);
+        matSoil.setColor("Specular", ColorRGBA.Gray);
+       
+
+
+        teapot = assetManager.loadModel("Models/Teapot/Teapot.obj");
+        teapot.setLocalTranslation(0,0,10);
+
+        teapot.setMaterial(mat);
+        teapot.setShadowMode(ShadowMode.CastAndReceive);
+        teapot.setLocalScale(10.0f);
+        rootNode.attachChild(teapot);
+
+  
+
+        Geometry soil=new Geometry("soil", new Box(new Vector3f(0, -13, 550), 800, 10, 700));
+        soil.setMaterial(matSoil);
+        soil.setShadowMode(ShadowMode.CastAndReceive);
+        rootNode.attachChild(soil);
+
+        DirectionalLight light=new DirectionalLight();
+        light.setDirection(new Vector3f(-1, -1, -1).normalizeLocal());
+        light.setColor(ColorRGBA.White.mult(1.5f));
+        rootNode.addLight(light);
+
+        // load sky
+        Spatial sky = SkyFactory.createSky(assetManager, "Textures/Sky/Bright/FullskiesBlueClear03.dds", false);
+        sky.setCullHint(Spatial.CullHint.Never);
+        rootNode.attachChild(sky);
+
+        fpp=new FilterPostProcessor(assetManager);
+        PosterizationFilter pf=new PosterizationFilter();
+        
+   
+
+        viewPort.addProcessor(fpp);
+        fpp.addFilter(pf);
+        initInputs();
+
+    }
+    
+         private void initInputs() {
+        inputManager.addMapping("toggle", new KeyTrigger(KeyInput.KEY_SPACE));
+     
+        ActionListener acl = new ActionListener() {
+
+            public void onAction(String name, boolean keyPressed, float tpf) {
+                if (name.equals("toggle") && keyPressed) {
+                    if(active){
+                        active=false;
+                        viewPort.removeProcessor(fpp);
+                    }else{
+                        active=true;
+                        viewPort.addProcessor(fpp);
+                    }
+                }
+            }
+        };
+             
+        inputManager.addListener(acl, "toggle");
+
+    }
+
+ 
+
+}