فهرست منبع

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

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@7000 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om 14 سال پیش
والد
کامیت
f58ca40979

+ 51 - 0
engine/src/core-data/Common/MatDefs/Post/CrossHatch.frag

@@ -0,0 +1,51 @@
+uniform sampler2D m_Texture;
+varying vec2 texCoord;
+ 
+uniform vec4 m_LineColor;
+uniform vec4 m_PaperColor;
+uniform float m_ColorInfluenceLine;
+uniform float m_ColorInfluencePaper;
+ 
+uniform float m_FillValue;
+uniform float m_Luminance1;
+uniform float m_Luminance2;
+uniform float m_Luminance3;
+uniform float m_Luminance4;
+uniform float m_Luminance5;
+ 
+uniform int m_LineDistance;
+uniform int m_LineThickness;
+ 
+void main() {
+    vec4 texVal = texture2D(m_Texture, texCoord);
+    float linePixel = 0;
+ 
+    float lum = texVal.r*0.2126 + texVal.g*0.7152 + texVal.b*0.0722;
+ 
+    if (lum < m_Luminance1){
+        if (mod(gl_FragCoord.x + gl_FragCoord.y, m_LineDistance * 2) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance2){
+        if (mod(gl_FragCoord.x - gl_FragCoord.y, m_LineDistance * 2) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance3){
+        if (mod(gl_FragCoord.x + gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance4){
+        if (mod(gl_FragCoord.x - gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance5){ // No line, make a blob instead
+        linePixel = m_FillValue;
+    }
+ 
+    // Mix line color with existing color information
+    vec4 lineColor = mix(m_LineColor, texVal, m_ColorInfluenceLine);
+    // Mix paper color with existing color information
+    vec4 paperColor = mix(m_PaperColor, texVal, m_ColorInfluencePaper);
+ 
+    gl_FragColor = mix(paperColor, lineColor, linePixel);
+}

+ 41 - 0
engine/src/core-data/Common/MatDefs/Post/CrossHatch.j3md

@@ -0,0 +1,41 @@
+MaterialDef CrossHatch {
+ 
+    MaterialParameters {
+        Int NumSamples
+        Texture2D Texture;
+        Vector4 LineColor;
+        Vector4 PaperColor;
+        Float ColorInfluenceLine;
+        Float ColorInfluencePaper;
+        Float FillValue;
+        Float Luminance1;
+        Float Luminance2;
+        Float Luminance3;
+        Float Luminance4;
+        Float Luminance5;
+        Int LineThickness;
+        Int LineDistance;
+    }
+ 
+    Technique {
+        VertexShader GLSL150:   Common/MatDefs/Post/Post15.vert
+        FragmentShader GLSL150: Common/MatDefs/Post/CrossHatch15.frag
+ 
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+ 
+    Technique {
+        VertexShader GLSL100:   Common/MatDefs/Post/Post.vert
+        FragmentShader GLSL100: Common/MatDefs/Post/CrossHatch.frag
+ 
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+ 
+    Technique FixedFunc {
+    }
+ 
+}

+ 53 - 0
engine/src/core-data/Common/MatDefs/Post/CrossHatch15.frag

@@ -0,0 +1,53 @@
+#import "Common/ShaderLib/MultiSample.glsllib"
+ 
+uniform COLORTEXTURE m_Texture;
+in vec2 texCoord;
+ 
+uniform vec4 m_LineColor;
+uniform vec4 m_PaperColor;
+uniform float m_ColorInfluenceLine;
+uniform float m_ColorInfluencePaper;
+ 
+uniform float m_FillValue;
+uniform float m_Luminance1;
+uniform float m_Luminance2;
+uniform float m_Luminance3;
+uniform float m_Luminance4;
+uniform float m_Luminance5;
+ 
+uniform int m_LineDistance;
+uniform int m_LineThickness;
+ 
+void main() {
+    vec4 texVal = getColor(m_Texture, texCoord);
+    float linePixel = 0;
+ 
+    float lum = texVal.r*0.2126 + texVal.g*0.7152 + texVal.b*0.0722;
+ 
+    if (lum < m_Luminance1){
+        if (mod(gl_FragCoord.x + gl_FragCoord.y, m_LineDistance * 2) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance2){
+        if (mod(gl_FragCoord.x - gl_FragCoord.y, m_LineDistance * 2) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance3){
+        if (mod(gl_FragCoord.x + gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance4){
+        if (mod(gl_FragCoord.x - gl_FragCoord.y - m_LineDistance, m_LineDistance) < m_LineThickness)
+            linePixel = 1;
+    }
+    if (lum < m_Luminance5){ // No line, make a blob instead
+        linePixel = m_FillValue;
+    }
+ 
+    // Mix line color with existing color information
+    vec4 lineColor = mix(m_LineColor, texVal, m_ColorInfluenceLine);
+    // Mix paper color with existing color information
+    vec4 paperColor = mix(m_PaperColor, texVal, m_ColorInfluencePaper);
+ 
+    gl_FragColor = mix(paperColor, lineColor, linePixel);
+}

+ 296 - 0
engine/src/desktop-fx/com/jme3/post/filters/CrossHatchFilter.java

@@ -0,0 +1,296 @@
+/*
+ * 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.math.ColorRGBA;
+import com.jme3.post.Filter;
+import com.jme3.renderer.RenderManager;
+import com.jme3.renderer.Renderer;
+import com.jme3.renderer.ViewPort;
+
+/*
+ * A Post Processing filter that makes the screen look like it was drawn as
+ * diagonal lines with a pen.
+ * Try combining this with a cartoon edge filter to obtain manga style visuals.
+ *
+ * Based on an article from Geeks3D:
+ *    <a href="http://www.geeks3d.com/20110219/shader-library-crosshatching-glsl-filter/" rel="nofollow">http://www.geeks3d.com/20110219/shader-library-crosshatching-glsl-filter/</a>
+ *
+ * @author: Roy Straver a.k.a. Baal Garnaal
+ */
+public class CrossHatchFilter extends Filter {
+
+    private ColorRGBA lineColor = ColorRGBA.Black.clone();
+    private ColorRGBA paperColor = ColorRGBA.White.clone();
+    private float colorInfluenceLine = 0.8f;
+    private float colorInfluencePaper = 0.1f;
+    private float fillValue = 0.9f;
+    private float luminance1 = 0.9f;
+    private float luminance2 = 0.7f;
+    private float luminance3 = 0.5f;
+    private float luminance4 = 0.3f;
+    private float luminance5 = 0.0f;
+    private int lineThickness = 1;
+    private int lineDistance = 4;
+
+    public CrossHatchFilter() {
+        super("CrossHatchFilter");
+    }
+
+    public CrossHatchFilter(ColorRGBA lineColor, ColorRGBA paperColor) {
+        this();
+        this.lineColor = lineColor;
+        this.paperColor = paperColor;
+    }
+
+    @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/CrossHatch.j3md");
+        material.setColor("LineColor", lineColor);
+        material.setColor("PaperColor", paperColor);
+
+        material.setFloat("ColorInfluenceLine", colorInfluenceLine);
+        material.setFloat("ColorInfluencePaper", colorInfluencePaper);
+
+        material.setFloat("FillValue", fillValue);
+
+        material.setFloat("Luminance1", luminance1);
+        material.setFloat("Luminance2", luminance2);
+        material.setFloat("Luminance3", luminance3);
+        material.setFloat("Luminance4", luminance4);
+        material.setFloat("Luminance5", luminance5);
+
+        material.setInt("LineThickness", lineThickness);
+        material.setInt("LineDistance", lineDistance);
+    }
+
+    @Override
+    public Material getMaterial() {
+        return material;
+    }
+
+    @Override
+    public void preRender(RenderManager renderManager, ViewPort viewPort) {
+    }
+
+    @Override
+    public void cleanUpFilter(Renderer r) {
+    }
+
+    /*
+     * Sets color used to draw lines
+     */
+    public void setLineColor(ColorRGBA lineColor) {
+        this.lineColor = lineColor;
+        if (material != null) {
+            material.setColor("LineColor", lineColor);
+        }
+    }
+
+    /*
+     * Sets color used as background
+     */
+    public void setPaperColor(ColorRGBA paperColor) {
+        this.paperColor = paperColor;
+        if (material != null) {
+            material.setColor("PaperColor", paperColor);
+        }
+    }
+    /*
+     * Sets color influence of original image on lines drawn
+     */
+
+    public void setColorInfluenceLine(float colorInfluenceLine) {
+        this.colorInfluenceLine = colorInfluenceLine;
+        if (material != null) {
+            material.setFloat("ColorInfluenceLine", colorInfluenceLine);
+        }
+    }
+
+    /*
+     * Sets color influence of original image on non-line areas
+     */
+    public void setColorInfluencePaper(float colorInfluencePaper) {
+        this.colorInfluencePaper = colorInfluencePaper;
+        if (material != null) {
+            material.setFloat("ColorInfluencePaper", colorInfluencePaper);
+        }
+    }
+
+    /*
+     * Sets line/paper color ratio for areas with values < luminance5,
+     * really dark areas get no lines but a filled blob instead
+     */
+    public void setFillValue(float fillValue) {
+        this.fillValue = fillValue;
+        if (material != null) {
+            material.setFloat("FillValue", fillValue);
+        }
+    }
+
+    /*
+     * Sets minimum luminance levels for lines drawn
+     * Luminance1: Top-left to down right 1
+     * Luminance2: Top-right to bottom left 1
+     * Luminance3: Top-left to down right 2
+     * Luminance4: Top-right to bottom left 2
+     * Luminance5: Blobs
+     */
+    public void setLuminanceLevels(float luminance1, float luminance2, float luminance3, float luminance4, float luminance5) {
+        this.luminance1 = luminance1;
+        this.luminance2 = luminance2;
+        this.luminance3 = luminance3;
+        this.luminance4 = luminance4;
+        this.luminance5 = luminance5;
+
+        if (material != null) {
+            material.setFloat("Luminance1", luminance1);
+            material.setFloat("Luminance2", luminance2);
+            material.setFloat("Luminance3", luminance3);
+            material.setFloat("Luminance4", luminance4);
+            material.setFloat("Luminance5", luminance5);
+        }
+    }
+
+    /*
+     * Sets the thickness of lines drawn
+     */
+    public void setLineThickness(int lineThickness) {
+        this.lineThickness = lineThickness;
+        if (material != null) {
+            material.setInt("LineThickness", lineThickness);
+        }
+    }
+
+    /*
+     * Sets minimum distance between lines drawn
+     * Primary lines are drawn at 2*lineDistance
+     * Secondary lines are drawn at lineDistance
+     */
+    public void setLineDistance(int lineDistance) {
+        this.lineDistance = lineDistance;
+        if (material != null) {
+            material.setInt("LineDistance", lineDistance);
+        }
+    }
+
+    /*
+     * Returns line color
+     */
+    public ColorRGBA getLineColor() {
+        return lineColor;
+    }
+
+    /*
+     * Returns paper background color
+     */
+    public ColorRGBA getPaperColor() {
+        return paperColor;
+    }
+
+    /*
+     * Returns current influence of image colors on lines
+     */
+    public float getColorInfluenceLine() {
+        return colorInfluenceLine;
+    }
+
+    /*
+     * Returns current influence of image colors on paper background
+     */
+    public float getColorInfluencePaper() {
+        return colorInfluencePaper;
+    }
+
+    /*
+     * Returns line/paper color ratio for blobs
+     */
+    public float getFillValue() {
+        return fillValue;
+    }
+
+    /*
+     * Returns the thickness of the lines drawn
+     */
+    public int getLineThickness() {
+        return lineThickness;
+    }
+
+    /*
+     * Returns minimum distance between lines
+     */
+    public int getLineDistance() {
+        return lineDistance;
+    }
+
+    /*
+     * Returns treshold for lines 1
+     */
+    public float getLuminance1() {
+        return luminance1;
+    }
+
+    /*
+     * Returns treshold for lines 2
+     */
+    public float getLuminance2() {
+        return luminance2;
+    }
+
+    /*
+     * Returns treshold for lines 3
+     */
+    public float getLuminance3() {
+        return luminance3;
+    }
+
+    /*
+     * Returns treshold for lines 4
+     */
+    public float getLuminance4() {
+        return luminance4;
+    }
+
+    /*
+     * Returns treshold for blobs
+     */
+    public float getLuminance5() {
+        return luminance5;
+    }
+}

+ 156 - 0
engine/src/test/jme3test/post/TestCrossHatch.java

@@ -0,0 +1,156 @@
+/*
+ * 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.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 TestCrossHatch extends SimpleApplication {
+
+    float angle;
+    Spatial lightMdl;
+    Spatial teapot;
+    Geometry frustumMdl;
+    WireFrustum frustum;
+    boolean active=true;
+    FilterPostProcessor fpp;
+    
+    public static void main(String[] args){
+        TestCrossHatch app = new TestCrossHatch();
+        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);
+        CrossHatchFilter chf=new CrossHatchFilter();
+        
+   
+
+        viewPort.addProcessor(fpp);
+        fpp.addFilter(chf);
+        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");
+
+    }
+
+ 
+
+}