Parcourir la source

Merge pull request #220 from zzuegg/master

Geometry shader and Tessellation shader support
Kirill Vainer il y a 10 ans
Parent
commit
273f3a6e62
28 fichiers modifiés avec 560 ajouts et 119 suppressions
  1. 1 1
      gradle.properties
  2. 3 8
      jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java
  3. 1 5
      jme3-core/src/main/java/com/jme3/material/Technique.java
  4. 92 34
      jme3-core/src/main/java/com/jme3/material/TechniqueDef.java
  5. 16 3
      jme3-core/src/main/java/com/jme3/renderer/Caps.java
  6. 1 1
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
  7. 46 0
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java
  8. 22 2
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  9. 24 2
      jme3-core/src/main/java/com/jme3/scene/Mesh.java
  10. 9 1
      jme3-core/src/main/java/com/jme3/shader/Shader.java
  11. 59 22
      jme3-core/src/main/java/com/jme3/shader/ShaderKey.java
  12. 23 1
      jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg
  13. 31 25
      jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java
  14. 3 6
      jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java
  15. 42 0
      jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java
  16. 68 0
      jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java
  17. 10 8
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  18. 3 0
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.frag
  19. 19 0
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.geom
  20. 4 0
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m
  21. 17 0
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3md
  22. 5 0
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert
  23. 3 0
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.frag
  24. 4 0
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m
  25. 19 0
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3md
  26. 13 0
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tsctrl
  27. 17 0
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval
  28. 5 0
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert

+ 1 - 1
gradle.properties

@@ -22,4 +22,4 @@ bulletFolder = bullet-2.82-r2704
 bulletZipFile = bullet.zip
 
 # Path for downloading NetBeans Base
-netbeansUrl = http://download.netbeans.org/netbeans/8.0.2/final/zip/netbeans-8.0.2-201411181905-javase.zip
+netbeansUrl = http://download.netbeans.org/netbeans/8.0.2/final/zip/netbeans-8.0.2-201411181905-javase.zip

+ 3 - 8
jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java

@@ -450,16 +450,11 @@ public class DesktopAssetManager implements AssetManager {
                 }
                 shader = shaderGenerator.generateShader();
             } else {
-                String vertName = key.getVertName();
-                String fragName = key.getFragName();
-
-                String vertSource = (String) loadAsset(new AssetKey(vertName));
-                String fragSource = (String) loadAsset(new AssetKey(fragName));
-
                 shader = new Shader();
                 shader.initialize();
-                shader.addSource(Shader.ShaderType.Vertex, vertName, vertSource, key.getDefines().getCompiled(), key.getVertexShaderLanguage());
-                shader.addSource(Shader.ShaderType.Fragment, fragName, fragSource, key.getDefines().getCompiled(), key.getFragmentShaderLanguage());
+                for (Shader.ShaderType shaderType : key.getUsedShaderPrograms()) {
+                    shader.addSource(shaderType,key.getShaderProgramName(shaderType),(String) loadAsset(new AssetKey(key.getShaderProgramName(shaderType))),key.getDefines().getCompiled(),key.getShaderProgramLanguage(shaderType));
+                }
             }
 
             cache.addToCache(key, shader);

+ 1 - 5
jme3-core/src/main/java/com/jme3/material/Technique.java

@@ -190,11 +190,7 @@ public class Technique /* implements Savable */ {
 
     private void loadShader(AssetManager manager,EnumSet<Caps> rendererCaps) {
         
-        ShaderKey key = new ShaderKey(def.getVertexShaderName(),
-                    def.getFragmentShaderName(),
-                    getAllDefines(),
-                    def.getVertexShaderLanguage(),
-                    def.getFragmentShaderLanguage());
+        ShaderKey key = new ShaderKey(getAllDefines(),def.getShaderProgramLanguages(),def.getShaderProgramNames());
         
         if (getDef().isUsingShaderNodes()) {                 
            manager.getShaderGenerator(rendererCaps).initialize(this);           

+ 92 - 34
jme3-core/src/main/java/com/jme3/material/TechniqueDef.java

@@ -33,16 +33,10 @@ package com.jme3.material;
 
 import com.jme3.export.*;
 import com.jme3.renderer.Caps;
-import com.jme3.renderer.Renderer;
-import com.jme3.shader.DefineList;
-import com.jme3.shader.ShaderNode;
-import com.jme3.shader.UniformBinding;
-import com.jme3.shader.VarType;
+import com.jme3.shader.*;
+
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 /**
  * Describes a technique definition.
@@ -100,10 +94,8 @@ public class TechniqueDef implements Savable {
     private EnumSet<Caps> requiredCaps = EnumSet.noneOf(Caps.class);
     private String name;
 
-    private String vertName;
-    private String fragName;
-    private String vertLanguage;
-    private String fragLanguage;
+    private EnumMap<Shader.ShaderType,String> shaderLanguage;
+    private EnumMap<Shader.ShaderType,String> shaderName;
     
     private DefineList presetDefines;
     private boolean usesShaders;
@@ -129,6 +121,7 @@ public class TechniqueDef implements Savable {
      * for default techniques.
      */
     public TechniqueDef(String name){
+        this();
         this.name = name == null ? "Default" : name;
     }
 
@@ -136,6 +129,8 @@ public class TechniqueDef implements Savable {
      * Serialization only. Do not use.
      */
     public TechniqueDef(){
+        shaderLanguage=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
+        shaderName=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
     }
 
     /**
@@ -244,11 +239,10 @@ public class TechniqueDef implements Savable {
      * @param fragLanguage The fragment shader language
      */
     public void setShaderFile(String vertexShader, String fragmentShader, String vertLanguage, String fragLanguage){
-        this.vertName = vertexShader;
-        this.fragName = fragmentShader;
-        this.vertLanguage = vertLanguage;
-        this.fragLanguage = fragLanguage;
-
+        this.shaderLanguage.put(Shader.ShaderType.Vertex,shaderLanguage.get(vertLanguage));
+        this.shaderName.put(Shader.ShaderType.Vertex,shaderName.get(vertexShader));
+        this.shaderLanguage.put(Shader.ShaderType.Fragment,shaderLanguage.get(fragLanguage));
+        this.shaderName.put(Shader.ShaderType.Fragment,shaderName.get(fragmentShader));
         Caps vertCap = Caps.valueOf(vertLanguage);
         requiredCaps.add(vertCap);
         Caps fragCap = Caps.valueOf(fragLanguage);
@@ -257,6 +251,26 @@ public class TechniqueDef implements Savable {
         usesShaders = true;
     }
 
+
+    /**
+     * Sets the shaders that this technique definition will use.
+     *
+     * @param shaderName EnumMap containing all shader names for this stage
+     * @param shaderLanguage EnumMap containing all shader languages for this stage
+     */
+    public void setShaderFile(EnumMap<Shader.ShaderType, String> shaderName, EnumMap<Shader.ShaderType, String> shaderLanguage) {
+        for (Shader.ShaderType shaderType : shaderName.keySet()) {
+            this.shaderLanguage.put(shaderType,shaderLanguage.get(shaderType));
+            this.shaderName.put(shaderType,shaderName.get(shaderType));
+            if(shaderType.equals(Shader.ShaderType.Geometry)){
+                requiredCaps.add(Caps.GeometryShader);
+            }else if(shaderType.equals(Shader.ShaderType.TessellationControl)){
+                requiredCaps.add(Caps.TesselationShader);
+            }
+        }
+        usesShaders=true;
+    }
+
     /**
      * Returns the define name which the given material parameter influences.
      * 
@@ -329,7 +343,7 @@ public class TechniqueDef implements Savable {
      * @return the name of the fragment shader to be used.
      */
     public String getFragmentShaderName() {
-        return fragName;
+        return shaderName.get(Shader.ShaderType.Fragment);
     }
 
     
@@ -340,7 +354,7 @@ public class TechniqueDef implements Savable {
      * @return the name of the vertex shader to be used.
      */
     public String getVertexShaderName() {
-        return vertName;
+        return shaderName.get(Shader.ShaderType.Vertex);
     }
 
     /**
@@ -348,21 +362,34 @@ public class TechniqueDef implements Savable {
      */
     @Deprecated
     public String getShaderLanguage() {
-        return vertLanguage;
+        return shaderLanguage.get(Shader.ShaderType.Vertex);
     }
 
     /**
      * Returns the language of the fragment shader used in this technique.
      */
     public String getFragmentShaderLanguage() {
-        return fragLanguage;
+        return shaderLanguage.get(Shader.ShaderType.Fragment);
     }
     
     /**
      * Returns the language of the vertex shader used in this technique.
      */
     public String getVertexShaderLanguage() {
-        return vertLanguage;
+        return shaderLanguage.get(Shader.ShaderType.Vertex);
+    }
+
+    /**Returns the language for each shader program
+     * @param shaderType
+     */
+    public String getShaderProgramLanguage(Shader.ShaderType shaderType){
+        return shaderLanguage.get(shaderType);
+    }
+    /**Returns the name for each shader program
+     * @param shaderType
+     */
+    public String getShaderProgramName(Shader.ShaderType shaderType){
+        return shaderName.get(shaderType);
     }
     
     /**
@@ -406,10 +433,18 @@ public class TechniqueDef implements Savable {
     public void write(JmeExporter ex) throws IOException{
         OutputCapsule oc = ex.getCapsule(this);
         oc.write(name, "name", null);
-        oc.write(vertName, "vertName", null);
-        oc.write(fragName, "fragName", null);
-        oc.write(vertLanguage, "vertLanguage", null);
-        oc.write(vertLanguage, "fragLanguage", null);
+
+        oc.write(shaderName.get(Shader.ShaderType.Vertex), "vertName", null);
+        oc.write(shaderName.get(Shader.ShaderType.Fragment), "fragName", null);
+        oc.write(shaderName.get(Shader.ShaderType.Geometry), "geomName", null);
+        oc.write(shaderName.get(Shader.ShaderType.TessellationControl), "tsctrlName", null);
+        oc.write(shaderName.get(Shader.ShaderType.TessellationEvaluation), "tsevalName", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.Vertex), "vertLanguage", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.Fragment), "fragLanguage", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.Geometry), "geomLanguage", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.TessellationControl), "tsctrlLanguage", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.TessellationEvaluation), "tsevalLanguage", null);
+
         oc.write(presetDefines, "presetDefines", null);
         oc.write(lightMode, "lightMode", LightMode.Disable);
         oc.write(shadowMode, "shadowMode", ShadowMode.Disable);
@@ -428,8 +463,11 @@ public class TechniqueDef implements Savable {
     public void read(JmeImporter im) throws IOException{
         InputCapsule ic = im.getCapsule(this);
         name = ic.readString("name", null);
-        vertName = ic.readString("vertName", null);
-        fragName = ic.readString("fragName", null);
+        shaderName.put(Shader.ShaderType.Vertex,ic.readString("vertName", null));
+        shaderName.put(Shader.ShaderType.Fragment,ic.readString("fragName", null));
+        shaderName.put(Shader.ShaderType.Geometry,ic.readString("geomName", null));
+        shaderName.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrlName", null));
+        shaderName.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tsevalName", null));
         presetDefines = (DefineList) ic.readSavable("presetDefines", null);
         lightMode = ic.readEnum("lightMode", LightMode.class, LightMode.Disable);
         shadowMode = ic.readEnum("shadowMode", ShadowMode.class, ShadowMode.Disable);
@@ -438,12 +476,15 @@ public class TechniqueDef implements Savable {
         
         if (ic.getSavableVersion(TechniqueDef.class) == 0) {
             // Old version
-            vertLanguage = ic.readString("shaderLang", null);
-            fragLanguage = vertLanguage;
+            shaderLanguage.put(Shader.ShaderType.Vertex,ic.readString("shaderLang", null));
+            shaderLanguage.put(Shader.ShaderType.Fragment,shaderLanguage.get(Shader.ShaderType.Vertex));
         } else {
             // New version
-            vertLanguage = ic.readString("vertLanguage", null);
-            fragLanguage = ic.readString("fragLanguage", null);;
+            shaderLanguage.put(Shader.ShaderType.Vertex,ic.readString("vertLanguage", null));
+            shaderLanguage.put(Shader.ShaderType.Fragment,ic.readString("fragLanguage", null));
+            shaderLanguage.put(Shader.ShaderType.Geometry,ic.readString("geomLanguage", null));
+            shaderLanguage.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrlLanguage", null));
+            shaderLanguage.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tsevalLanguage", null));
         }
         
         usesNodes = ic.readBoolean("usesNodes", false);
@@ -461,6 +502,22 @@ public class TechniqueDef implements Savable {
         usesShaders = true;
     }
 
+    /**
+     * Returns the Enum containing the ShaderProgramNames;
+     * @return
+     */
+    public EnumMap<Shader.ShaderType, String> getShaderProgramNames() {
+        return shaderName;
+    }
+
+    /**
+     * Returns the Enum containing the ShaderProgramLanguages;
+     * @return
+     */
+    public EnumMap<Shader.ShaderType, String> getShaderProgramLanguages() {
+        return shaderLanguage;
+    }
+
     public ShaderGenerationInfo getShaderGenerationInfo() {
         return shaderGenerationInfo;
     }
@@ -469,8 +526,9 @@ public class TechniqueDef implements Savable {
         this.shaderGenerationInfo = shaderGenerationInfo;
     }
 
+    //todo: make toString return something usefull
     @Override
     public String toString() {
-        return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name + ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage + ", presetDefines=" + presetDefines + ", usesShaders=" + usesShaders + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}';
+        return "TechniqueDef{" + "requiredCaps=" + requiredCaps + ", name=" + name /*+ ", vertName=" + vertName + ", fragName=" + fragName + ", vertLanguage=" + vertLanguage + ", fragLanguage=" + fragLanguage */+ ", presetDefines=" + presetDefines + ", usesShaders=" + usesShaders + ", usesNodes=" + usesNodes + ", shaderNodes=" + shaderNodes + ", shaderGenerationInfo=" + shaderGenerationInfo + ", renderState=" + renderState + ", forcedRenderState=" + forcedRenderState + ", lightMode=" + lightMode + ", shadowMode=" + shadowMode + ", defineParams=" + defineParams + ", worldBinds=" + worldBinds + '}';
     }    
 }

+ 16 - 3
jme3-core/src/main/java/com/jme3/renderer/Caps.java

@@ -120,7 +120,14 @@ public enum Caps {
      * Supports OpenGL 3.2
      */
     OpenGL32,
-
+    /**
+     * Supports OpenGL 3.3
+     */
+    OpenGL33,
+    /**
+     * Supports OpenGL 4.0
+     */
+    OpenGL40,
     /**
      * Do not use.
      * 
@@ -163,7 +170,10 @@ public enum Caps {
      * Supports GLSL 3.3
      */
     GLSL330,
-
+    /**
+     * Supports GLSL 4.0
+     */
+    GLSL400,
     /**
      * Supports reading from textures inside the vertex shader.
      */
@@ -173,7 +183,10 @@ public enum Caps {
      * Supports geometry shader.
      */
     GeometryShader,
-
+    /**
+     * Supports Tesselation shader
+     */
+    TesselationShader,
     /**
      * Supports texture arrays
      */

+ 1 - 1
jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java

@@ -41,7 +41,7 @@ import java.nio.IntBuffer;
 public interface GL3 extends GL2 {
     
     public static final int GL_DEPTH_STENCIL_ATTACHMENT = 0x821A;
-    
+    public static final int GL_GEOMETRY_SHADER=0x8DD9;
     public void glBindFragDataLocation(int param1, int param2, String param3); /// GL3+
     public void glBindVertexArray(int param1); /// GL3+
     public void glGenVertexArrays(IntBuffer param1); /// GL3+

+ 46 - 0
jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java

@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2009-2014 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.renderer.opengl;
+
+import java.nio.IntBuffer;
+
+/**
+ * GL functions only available on vanilla desktop OpenGL 3.0.
+ * 
+ * @author Kirill Vainer
+ */
+public interface GL4 extends GL3 {
+    public static final int GL_TESS_CONTROL_SHADER=0x8E87;
+    public static final int GL_TESS_EVALUATION_SHADER=0x8E88;
+    public static final int GL_PATCHES=0xE;
+    public void glPatchParameter(int count);
+}

+ 22 - 2
jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java

@@ -107,6 +107,7 @@ public class GLRenderer implements Renderer {
     private final GL gl;
     private final GL2 gl2;
     private final GL3 gl3;
+    private final GL4 gl4;
     private final GLExt glext;
     private final GLFbo glfbo;
     private final TextureUtil texUtil;
@@ -115,6 +116,7 @@ public class GLRenderer implements Renderer {
         this.gl = gl;
         this.gl2 = gl instanceof GL2 ? (GL2)gl : null;
         this.gl3 = gl instanceof GL3 ? (GL3)gl : null;
+        this.gl4 = gl instanceof GL4 ? (GL4)gl : null;
         this.glfbo = glfbo;
         this.glext = glfbo instanceof GLExt ? (GLExt)glfbo : null;
         this.texUtil = new TextureUtil(gl, gl2, glext, context);
@@ -183,6 +185,12 @@ public class GLRenderer implements Renderer {
                         caps.add(Caps.OpenGL31);
                         if (oglVer >= 320) {
                             caps.add(Caps.OpenGL32);
+                        }if(oglVer>=330){
+                            caps.add(Caps.OpenGL33);
+                            caps.add(Caps.GeometryShader);
+                        }if(oglVer>=400){
+                            caps.add(Caps.OpenGL40);
+                            caps.add(Caps.TesselationShader);
                         }
                     }
                 }
@@ -199,7 +207,9 @@ public class GLRenderer implements Renderer {
                 // so that future OpenGL revisions wont break jme3
                 // fall through intentional
             case 400:
+                caps.add(Caps.GLSL400);
             case 330:
+                caps.add(Caps.GLSL330);
             case 150:
                 caps.add(Caps.GLSL150);
             case 140:
@@ -271,7 +281,7 @@ public class GLRenderer implements Renderer {
         
         boolean hasFloatTexture = false;
 
-        hasFloatTexture = hasExtension("GL_OES_texture_half_float") && 
+        hasFloatTexture = hasExtension("GL_OES_texture_half_float") &&
                           hasExtension("GL_OES_texture_float");
         
         if (!hasFloatTexture) {
@@ -1009,6 +1019,12 @@ public class GLRenderer implements Renderer {
                 return GL.GL_FRAGMENT_SHADER;
             case Vertex:
                 return GL.GL_VERTEX_SHADER;
+            case Geometry:
+                return GL3.GL_GEOMETRY_SHADER;
+            case TessellationControl:
+                return GL4.GL_TESS_CONTROL_SHADER;
+            case TessellationEvaluation:
+                return GL4.GL_TESS_EVALUATION_SHADER;
             default:
                 throw new UnsupportedOperationException("Unrecognized shader type.");
         }
@@ -2520,6 +2536,8 @@ public class GLRenderer implements Renderer {
                 return GL.GL_TRIANGLE_FAN;
             case TriangleStrip:
                 return GL.GL_TRIANGLE_STRIP;
+            case Patch:
+                return GL4.GL_PATCHES;
             default:
                 throw new UnsupportedOperationException("Unrecognized mesh mode: " + mode);
         }
@@ -2670,7 +2688,9 @@ public class GLRenderer implements Renderer {
             gl.glLineWidth(mesh.getLineWidth());
             context.lineWidth = mesh.getLineWidth();
         }
-
+        if(gl4!=null && mesh.getMode().equals(Mode.Patch)){
+            gl4.glPatchParameter(mesh.getPatchVertexCount());
+        }
         statistics.onMeshDrawn(mesh, lod, count);
 //        if (ctxCaps.GL_ARB_vertex_array_object){
 //            renderMeshVertexArray(mesh, lod, count);

+ 24 - 2
jme3-core/src/main/java/com/jme3/scene/Mesh.java

@@ -134,8 +134,12 @@ public class Mesh implements Savable, Cloneable {
          * {@link Mesh#setElementLengths(int[]) element lengths} must 
          * be specified for this mode.
          */
-        Hybrid(false);
-        
+        Hybrid(false),
+        /**
+         * Used for Tesselation only. Requires to set the number of vertices
+         * for each patch (default is 3 for triangle tesselation)
+         */
+        Patch(true);
         private boolean listMode = false;
         
         private Mode(boolean listMode){
@@ -175,6 +179,7 @@ public class Mesh implements Savable, Cloneable {
     private int vertCount = -1;
     private int elementCount = -1;
     private int instanceCount = -1;
+    private int patchVertexCount=3; //only used for tesselation
     private int maxNumWeights = -1; // only if using skeletal animation
 
     private int[] elementLengths;
@@ -728,6 +733,8 @@ public class Mesh implements Savable, Cloneable {
                 return bufSize;
             case LineStrip:
                 return bufSize - 1;
+            case Patch:
+                return bufSize/patchVertexCount;
             default:
                 throw new UnsupportedOperationException();
         }
@@ -1362,6 +1369,21 @@ public class Mesh implements Savable, Cloneable {
                getBuffer(Type.HWBoneIndex) != null;
     }
 
+    /**
+     * Sets the count of vertices used for each tessellation patch
+     * @param patchVertexCount
+     */
+    public void setPatchVertexCount(int patchVertexCount) {
+        this.patchVertexCount = patchVertexCount;
+    }
+
+    /**
+     * Gets the amout of vertices used for each patch;
+     * @return
+     */
+    public int getPatchVertexCount() {
+        return patchVertexCount;
+    }
 
     public void write(JmeExporter ex) throws IOException {
         OutputCapsule out = ex.getCapsule(this);

+ 9 - 1
jme3-core/src/main/java/com/jme3/shader/Shader.java

@@ -74,7 +74,15 @@ public final class Shader extends NativeObject {
         /**
          * Control geometry assembly. (e.g compile a triangle list from input data)
          */
-        Geometry;
+        Geometry,
+        /**
+         * Controls tesselation factor (e.g how often a input patch should be subdivided)
+         */
+        TessellationControl,
+        /**
+         * Controls tesselation transform (e.g similar to the vertex shader, but required to mix inputs manual)
+         */
+        TessellationEvaluation;
     }
 
     /**

+ 59 - 22
jme3-core/src/main/java/com/jme3/shader/ShaderKey.java

@@ -37,25 +37,31 @@ import com.jme3.export.JmeExporter;
 import com.jme3.export.JmeImporter;
 import com.jme3.export.OutputCapsule;
 import java.io.IOException;
+import java.util.EnumMap;
+import java.util.Set;
 
 public class ShaderKey extends AssetKey<Shader> {
 
-    protected String fragName;
+    protected EnumMap<Shader.ShaderType,String> shaderLanguage;
+    protected EnumMap<Shader.ShaderType,String> shaderName;
     protected DefineList defines;
-    protected String vertLanguage;
-    protected String fragLanguage;
     protected int cachedHashedCode = 0;
     protected boolean usesShaderNodes = false;
 
     public ShaderKey(){
+        shaderLanguage=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
+        shaderName=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
     }
 
-    public ShaderKey(String vertName, String fragName, DefineList defines, String vertLanguage, String fragLanguage){
-        super(vertName);
-        this.fragName = fragName;
+    public ShaderKey(DefineList defines, EnumMap<Shader.ShaderType,String> shaderLanguage,EnumMap<Shader.ShaderType,String> shaderName){
+        super(shaderName.get(Shader.ShaderType.Vertex));
+        this.shaderLanguage=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
+        this.shaderName=new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
         this.defines = defines;
-        this.vertLanguage = vertLanguage;
-        this.fragLanguage = fragLanguage;
+        for (Shader.ShaderType shaderType : shaderName.keySet()) {
+            this.shaderName.put(shaderType,shaderName.get(shaderType));
+            this.shaderLanguage.put(shaderType,shaderLanguage.get(shaderType));
+        }
     }
     
     @Override
@@ -68,13 +74,15 @@ public class ShaderKey extends AssetKey<Shader> {
     
     @Override
     public String toString(){
-        return "V="+name + " F=" + fragName + (defines != null ? defines : "");
+        //todo:
+        return "V="+name+";";
     }
 
+    //todo: make equals and hashCode work
     @Override
     public boolean equals(Object obj) {
         final ShaderKey other = (ShaderKey) obj;
-        if (name.equals(other.name) && fragName.equals(other.fragName)){
+        if (name.equals(other.name) && shaderName.get(Shader.ShaderType.Fragment).equals(other.shaderName.get(Shader.ShaderType.Fragment))){
             if (defines != null && other.defines != null) {
                 return defines.equals(other.defines);
             } else if (defines != null || other.defines != null) {
@@ -91,7 +99,10 @@ public class ShaderKey extends AssetKey<Shader> {
         if (cachedHashedCode == 0) {
             int hash = 7;
             hash = 41 * hash + name.hashCode();
-            hash = 41 * hash + fragName.hashCode();
+            hash = 41 * hash + shaderName.get(Shader.ShaderType.Fragment).hashCode();
+            hash = shaderName.get(Shader.ShaderType.Geometry) == null ? hash : 41 * hash + shaderName.get(Shader.ShaderType.Geometry).hashCode();
+            hash = shaderName.get(Shader.ShaderType.TessellationControl) == null ? hash : 41 * hash + shaderName.get(Shader.ShaderType.TessellationControl).hashCode();
+            hash = shaderName.get(Shader.ShaderType.TessellationEvaluation) == null ? hash : 41 * hash + shaderName.get(Shader.ShaderType.TessellationEvaluation).hashCode();
             hash = 41 * hash + (defines != null ? defines.hashCode() : 0);
             cachedHashedCode = hash;
         }
@@ -103,11 +114,11 @@ public class ShaderKey extends AssetKey<Shader> {
     }
 
     public String getVertName(){
-        return name;
+        return shaderName.get(Shader.ShaderType.Vertex);
     }
 
     public String getFragName() {
-        return fragName;
+        return shaderName.get(Shader.ShaderType.Fragment);
     }
 
     /**
@@ -115,15 +126,15 @@ public class ShaderKey extends AssetKey<Shader> {
      */
     @Deprecated
     public String getLanguage() {
-        return vertLanguage;
+        return shaderLanguage.get(Shader.ShaderType.Vertex);
     }
     
     public String getVertexShaderLanguage() { 
-        return vertLanguage;
+        return shaderLanguage.get(Shader.ShaderType.Vertex);
     }
     
     public String getFragmentShaderLanguage() {
-        return fragLanguage;
+        return shaderLanguage.get(Shader.ShaderType.Vertex);
     }
 
     public boolean isUsesShaderNodes() {
@@ -134,22 +145,48 @@ public class ShaderKey extends AssetKey<Shader> {
         this.usesShaderNodes = usesShaderNodes;
     }
 
+    public Set<Shader.ShaderType> getUsedShaderPrograms(){
+        return shaderName.keySet();
+    }
+
+    public String getShaderProgramLanguage(Shader.ShaderType shaderType){
+        return shaderLanguage.get(shaderType);
+    }
+
+    public String getShaderProgramName(Shader.ShaderType shaderType){
+        return shaderName.get(shaderType);
+    }
+
     @Override
     public void write(JmeExporter ex) throws IOException{
         super.write(ex);
         OutputCapsule oc = ex.getCapsule(this);
-        oc.write(fragName, "fragment_name", null);
-        oc.write(vertLanguage, "language", null);
-        oc.write(fragLanguage, "frag_language", null);
+        oc.write(shaderName.get(Shader.ShaderType.Fragment), "fragment_name", null);
+        oc.write(shaderName.get(Shader.ShaderType.Geometry), "geometry_name", null);
+        oc.write(shaderName.get(Shader.ShaderType.TessellationControl), "tessControl_name", null);
+        oc.write(shaderName.get(Shader.ShaderType.TessellationEvaluation), "tessEval_name", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.Vertex), "language", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.Fragment), "frag_language", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.Geometry), "geom_language", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.TessellationControl), "tsctrl_language", null);
+        oc.write(shaderLanguage.get(Shader.ShaderType.TessellationEvaluation), "tseval_language", null);
+
     }
 
     @Override
     public void read(JmeImporter im) throws IOException{
         super.read(im);
         InputCapsule ic = im.getCapsule(this);
-        fragName = ic.readString("fragment_name", null);
-        vertLanguage = ic.readString("language", null);
-        fragLanguage = ic.readString("frag_language", null);
+        shaderName.put(Shader.ShaderType.Vertex,name);
+        shaderName.put(Shader.ShaderType.Fragment,ic.readString("fragment_name", null));
+        shaderName.put(Shader.ShaderType.Geometry,ic.readString("geometry_name", null));
+        shaderName.put(Shader.ShaderType.TessellationControl,ic.readString("tessControl_name", null));
+        shaderName.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tessEval_name", null));
+        shaderLanguage.put(Shader.ShaderType.Vertex,ic.readString("language", null));
+        shaderLanguage.put(Shader.ShaderType.Fragment,ic.readString("frag_language", null));
+        shaderLanguage.put(Shader.ShaderType.Geometry,ic.readString("geom_language", null));
+        shaderLanguage.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrl_language", null));
+        shaderLanguage.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tseval_language", null));
     }
 
 }

+ 23 - 1
jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg

@@ -2,4 +2,26 @@ INCLUDE com/jme3/asset/General.cfg
 
 # Desktop-specific loaders
 LOADER com.jme3.texture.plugins.AWTLoader : jpg, bmp, gif, png, jpeg
-LOADER com.jme3.audio.plugins.OGGLoader : ogg
+LOADER com.jme3.audio.plugins.OGGLoader : oggLOADER com.jme3.audio.plugins.WAVLoader : wav
+LOADER com.jme3.audio.plugins.OGGLoader : ogg
+LOADER com.jme3.cursors.plugins.CursorLoader : ani, cur, ico
+LOADER com.jme3.material.plugins.J3MLoader : j3m
+LOADER com.jme3.material.plugins.J3MLoader : j3md
+LOADER com.jme3.material.plugins.ShaderNodeDefinitionLoader : j3sn
+LOADER com.jme3.font.plugins.BitmapFontLoader : fnt
+LOADER com.jme3.texture.plugins.DDSLoader : dds
+LOADER com.jme3.texture.plugins.PFMLoader : pfm
+LOADER com.jme3.texture.plugins.HDRLoader : hdr
+LOADER com.jme3.texture.plugins.TGALoader : tga
+LOADER com.jme3.export.binary.BinaryImporter : j3o
+LOADER com.jme3.export.binary.BinaryImporter : j3f
+LOADER com.jme3.scene.plugins.OBJLoader : obj
+LOADER com.jme3.scene.plugins.MTLLoader : mtl
+LOADER com.jme3.scene.plugins.ogre.MeshLoader : meshxml, mesh.xml
+LOADER com.jme3.scene.plugins.ogre.SkeletonLoader : skeletonxml, skeleton.xml
+LOADER com.jme3.scene.plugins.ogre.MaterialLoader : material
+LOADER com.jme3.scene.plugins.ogre.SceneLoader : scene
+LOADER com.jme3.scene.plugins.blender.BlenderModelLoader : blend
+LOADER com.jme3.shader.plugins.GLSLLoader : vert, frag,geom,tsctrl,tseval, glsl, glsllib
+LOADER com.jme3.scene.plugins.fbx.SceneLoader : fbx
+LOADER com.jme3.scene.plugins.fbx.SceneWithAnimationLoader : fba

+ 31 - 25
jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java

@@ -40,6 +40,7 @@ import com.jme3.material.TechniqueDef.ShadowMode;
 import com.jme3.math.ColorRGBA;
 import com.jme3.math.Vector2f;
 import com.jme3.math.Vector3f;
+import com.jme3.shader.Shader;
 import com.jme3.shader.VarType;
 import com.jme3.texture.Texture;
 import com.jme3.texture.Texture.WrapMode;
@@ -48,8 +49,10 @@ import com.jme3.texture.image.ColorSpace;
 import com.jme3.util.PlaceholderAssets;
 import com.jme3.util.blockparser.BlockLanguageParser;
 import com.jme3.util.blockparser.Statement;
+
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.EnumMap;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -68,16 +71,15 @@ public class J3MLoader implements AssetLoader {
     private Material material;
     private TechniqueDef technique;
     private RenderState renderState;
-    
-    private String vertLanguage;
-    private String fragLanguage;
-    
-    private String vertName;
-    private String fragName;
-    
+
+    private EnumMap<Shader.ShaderType, String> shaderLanguage;
+    private EnumMap<Shader.ShaderType, String> shaderName;
+
     private static final String whitespacePattern = "\\p{javaWhitespace}+";
 
-    public J3MLoader(){
+    public J3MLoader() {
+        shaderLanguage = new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
+        shaderName = new EnumMap<Shader.ShaderType, String>(Shader.ShaderType.class);
     }
 
 
@@ -91,16 +93,19 @@ public class J3MLoader implements AssetLoader {
         if (typeAndLang.length != 2) {
             throw new IOException("Shader statement syntax incorrect: " + statement);
         }
-        
-        if (typeAndLang[0].equals("VertexShader")) {
-            vertName = split[1].trim();
-            vertLanguage = typeAndLang[1];
-        } else if (typeAndLang[0].equals("FragmentShader")) {
-            fragName = split[1].trim();
-            fragLanguage = typeAndLang[1];
+
+        for (Shader.ShaderType shaderType : Shader.ShaderType.values()) {
+            if (typeAndLang[0].equals(shaderType.toString() + "Shader")) {
+                readShaderDefinition(shaderType, split[1].trim(), typeAndLang[1]);
+            }
         }
     }
 
+    private void readShaderDefinition(Shader.ShaderType shaderType, String name, String language) {
+        shaderName.put(shaderType, name);
+        shaderLanguage.put(shaderType, language);
+    }
+
     // LightMode <MODE>
     private void readLightMode(String statement) throws IOException{
         String[] split = statement.split(whitespacePattern);
@@ -403,7 +408,10 @@ public class J3MLoader implements AssetLoader {
     private void readTechniqueStatement(Statement statement) throws IOException{
         String[] split = statement.getLine().split("[ \\{]");       
         if (split[0].equals("VertexShader") ||
-            split[0].equals("FragmentShader")){
+                split[0].equals("FragmentShader") ||
+                split[0].equals("GeometryShader") ||
+                split[0].equals("TessellationControlShader") ||
+                split[0].equals("TessellationEvaluationShader")) {
             readShaderStatement(statement.getLine());
         }else if (split[0].equals("LightMode")){
             readLightMode(statement.getLine());
@@ -467,16 +475,14 @@ public class J3MLoader implements AssetLoader {
             technique.setShaderFile(technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100");
         }
 
-        if (vertName != null && fragName != null){
-            technique.setShaderFile(vertName, fragName, vertLanguage, fragLanguage);
+        if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) {
+            technique.setShaderFile(shaderName, shaderLanguage);
         }
         
         materialDef.addTechniqueDef(technique);
         technique = null;
-        vertName = null;
-        fragName = null;
-        vertLanguage = null;
-        fragLanguage = null;
+        shaderLanguage.clear();
+        shaderName.clear();
     }
 
     private void loadFromRoot(List<Statement> roots) throws IOException{       
@@ -594,9 +600,9 @@ public class J3MLoader implements AssetLoader {
 
     protected void initNodesLoader() {
         if (!isUseNodes) {
-            isUseNodes = fragName == null && vertName == null;
-            if (isUseNodes) { 
-                if(nodesLoaderDelegate == null){
+            isUseNodes = shaderName.get(Shader.ShaderType.Vertex) == null && shaderName.get(Shader.ShaderType.Fragment) == null;
+            if (isUseNodes) {
+                if (nodesLoaderDelegate == null) {
                     nodesLoaderDelegate = new ShaderNodeLoaderDelegate();
                 }else{
                     nodesLoaderDelegate.clear();

+ 3 - 6
jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java

@@ -30,7 +30,7 @@ public class ShaderCheck {
         assetManager.registerLocator("/", ClasspathLocator.class);
         assetManager.registerLoader(J3MLoader.class, "j3m");
         assetManager.registerLoader(J3MLoader.class, "j3md");
-        assetManager.registerLoader(GLSLLoader.class, "vert", "frag", "glsllib");
+        assetManager.registerLoader(GLSLLoader.class, "vert", "frag","geom","tsctrl","tseval","glsllib");
     }
     
     private static void checkMatDef(String matdefName){
@@ -38,11 +38,8 @@ public class ShaderCheck {
         for (TechniqueDef techDef : def.getDefaultTechniques()){
             DefineList dl = new DefineList();
             dl.addFrom(techDef.getShaderPresetDefines());
-            ShaderKey shaderKey = new ShaderKey(techDef.getVertexShaderName(),
-                                                techDef.getFragmentShaderName(),
-                                                dl,
-                                                techDef.getVertexShaderLanguage(),
-                                                techDef.getFragmentShaderLanguage());
+            ShaderKey shaderKey = new ShaderKey(dl,techDef.getShaderProgramLanguages(),techDef.getShaderProgramNames());
+
             Shader shader = assetManager.loadShader(shaderKey);
 
             for (Validator validator : validators){

+ 42 - 0
jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java

@@ -0,0 +1,42 @@
+package jme3test.material;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.bounding.BoundingBox;
+import com.jme3.material.Material;
+import com.jme3.math.Vector3f;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer;
+import com.jme3.scene.shape.Sphere;
+import com.jme3.util.BufferUtils;
+
+/**
+ * Created by michael on 23.02.15.
+ */
+public class TestGeometryShader extends SimpleApplication {
+    @Override
+    public void simpleInitApp() {
+        Mesh mesh = new Mesh();
+        mesh.setBuffer(VertexBuffer.Type.Index, 1, BufferUtils.createIntBuffer(new int[]{1}));
+        mesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(new float[]{0, 0, 0}));
+        mesh.setMode(Mesh.Mode.Points);
+        mesh.setBound(new BoundingBox(new Vector3f(0, 0, 0), 10, 10, 10));
+        mesh.updateCounts();
+        Geometry geometry = new Geometry("Test", mesh);
+        geometry.updateGeometricState();
+        geometry.setMaterial(new Material(assetManager, "Materials/Geom/SimpleGeom.j3md"));
+        //geometry.getMaterial().getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off);
+        //geometry.setMaterial(assetManager.loadMaterial("Materials/Geom/SimpleTess.j3md"));
+        rootNode.attachChild(geometry);
+
+        Geometry geometry1 = new Geometry("T1", new Sphere(10, 10, 1));
+        geometry1.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md"));
+        rootNode.attachChild(geometry1);
+
+    }
+
+    public static void main(String[] args) {
+        TestGeometryShader app = new TestGeometryShader();
+        app.start();
+    }
+}

+ 68 - 0
jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java

@@ -0,0 +1,68 @@
+package jme3test.material;
+
+import com.jme3.app.SimpleApplication;
+import com.jme3.input.KeyInput;
+import com.jme3.input.controls.AnalogListener;
+import com.jme3.input.controls.KeyTrigger;
+import com.jme3.material.Material;
+import com.jme3.scene.Geometry;
+import com.jme3.scene.Mesh;
+import com.jme3.scene.VertexBuffer;
+import com.jme3.scene.shape.Quad;
+import com.jme3.util.BufferUtils;
+
+import java.util.concurrent.Callable;
+
+/**
+ * Created by michael on 28.02.15.
+ */
+public class TestTessellationShader extends SimpleApplication {
+    Material tessellationMaterial;
+    int tessFactor=5;
+    @Override
+    public void simpleInitApp() {
+        tessellationMaterial = new Material(getAssetManager(), "Materials/Tess/SimpleTess.j3md");
+        tessellationMaterial.setInt("TessellationFactor", tessFactor);
+        tessellationMaterial.getAdditionalRenderState().setWireframe(true);
+        Quad quad = new Quad(10, 10);
+        quad.clearBuffer(VertexBuffer.Type.Index);
+        quad.setBuffer(VertexBuffer.Type.Index, 4, BufferUtils.createIntBuffer(0, 1, 2, 3));
+        quad.setMode(Mesh.Mode.Patch);
+        quad.setPatchVertexCount(4);
+        Geometry geometry = new Geometry("tessTest", quad);
+        geometry.setMaterial(tessellationMaterial);
+        rootNode.attachChild(geometry);
+
+        getInputManager().addMapping("TessUp", new KeyTrigger(KeyInput.KEY_A));
+        getInputManager().addMapping("TessDo", new KeyTrigger(KeyInput.KEY_Y));
+        getInputManager().addListener(new AnalogListener() {
+            @Override
+            public void onAnalog(String name, float value, float tpf) {
+                if(name.equals("TessUp")){
+                    tessFactor++;
+                    enqueue(new Callable<Boolean>() {
+                        @Override
+                        public Boolean call() throws Exception {
+                            tessellationMaterial.setInt("TessellationFactor",tessFactor);
+                            return true;
+                        }
+                    });
+                }
+                if(name.equals("TessDo")){
+                    tessFactor--;
+                    enqueue(new Callable<Boolean>() {
+                        @Override
+                        public Boolean call() throws Exception {
+                            tessellationMaterial.setInt("TessellationFactor",tessFactor);
+                            return true;
+                        }
+                    });
+                }
+            }
+        },"TessUp","TessDo");
+    }
+
+    public static void main(String[] args) {
+        new TestTessellationShader().start();
+    }
+}

+ 10 - 8
jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java

@@ -9,14 +9,11 @@ import java.nio.ByteBuffer;
 import java.nio.FloatBuffer;
 import java.nio.IntBuffer;
 import java.nio.ShortBuffer;
-import org.lwjgl.opengl.GL11;
-import org.lwjgl.opengl.GL12;
-import org.lwjgl.opengl.GL13;
-import org.lwjgl.opengl.GL15;
-import org.lwjgl.opengl.GL20;
-import org.lwjgl.opengl.GL30;
-
-public class LwjglGL implements GL, GL2, GL3 {
+
+import com.jme3.renderer.opengl.GL4;
+import org.lwjgl.opengl.*;
+
+public class LwjglGL implements GL, GL2, GL3,GL4 {
     
     private static void checkLimit(Buffer buffer) {
         if (buffer == null) {
@@ -442,4 +439,9 @@ public class LwjglGL implements GL, GL2, GL3 {
         checkLimit(param1);
         GL30.glGenVertexArrays(param1);
     }
+
+    @Override
+    public void glPatchParameter(int count) {
+        GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count);
+    }
 }

+ 3 - 0
jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.frag

@@ -0,0 +1,3 @@
+void main(){
+ gl_FragColor=vec4(1.0,0.0,1.0,0.5);
+}

+ 19 - 0
jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.geom

@@ -0,0 +1,19 @@
+layout (points) in;
+layout (line_strip) out;
+layout (max_vertices = 11) out;
+
+uniform mat4 g_WorldViewProjectionMatrix;
+const float PI = 3.1415926;
+void main(){
+    for (int i = 0; i <= 10; i++) {
+
+            float ang = PI * 2.0 / 10.0 * i;
+            vec4 offset = vec4(cos(ang) * 5, -sin(ang) * 5, 0.0, 0.0);
+            gl_Position = g_WorldViewProjectionMatrix*vec4(gl_in[0].gl_Position.xyz + offset.xyz,1.0);
+
+            EmitVertex();
+        }
+
+    EndPrimitive();
+}
+

+ 4 - 0
jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m

@@ -0,0 +1,4 @@
+Material Pong Rock : Materials/Geom/SimpleGeom.j3md {
+     MaterialParameters {
+     }
+}

+ 17 - 0
jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3md

@@ -0,0 +1,17 @@
+MaterialDef SimpleGeom {
+
+    MaterialParameters {
+
+    }
+
+     Technique {
+        VertexShader GLSL330:   Materials/Geom/SimpleGeom.vert
+        GeometryShader GLSL330:   Materials/Geom/SimpleGeom.geom
+        FragmentShader GLSL330: Materials/Geom/SimpleGeom.frag
+
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+
+}

+ 5 - 0
jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert

@@ -0,0 +1,5 @@
+attribute vec3 inPosition;
+
+void main(){
+ gl_Position=vec4(inPosition,1);
+}

+ 3 - 0
jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.frag

@@ -0,0 +1,3 @@
+void main(){
+ gl_FragColor=vec4(1.0,0.0,1.0,0.5);
+}

+ 4 - 0
jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m

@@ -0,0 +1,4 @@
+Material Pong Rock : Materials/Tess/SimpleTess.j3md {
+     MaterialParameters {
+     }
+}

+ 19 - 0
jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3md

@@ -0,0 +1,19 @@
+MaterialDef SimpleGeom {
+
+    MaterialParameters {
+        Texture2D NormalDisplacementMap
+        Int TessellationFactor
+    }
+
+     Technique {
+        VertexShader GLSL400:   Materials/Tess/SimpleTess.vert
+        TessellationEvaluationShader GLSL400:   Materials/Tess/SimpleTess.tseval
+        TessellationControlShader GLSL400:   Materials/Tess/SimpleTess.tsctrl
+        FragmentShader GLSL400: Materials/Tess/SimpleTess.frag
+
+        WorldParameters {
+            WorldViewProjectionMatrix
+        }
+    }
+
+}

+ 13 - 0
jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tsctrl

@@ -0,0 +1,13 @@
+layout (quads,equal_spacing,cw) in;
+
+uniform mat4 g_WorldViewProjectionMatrix;
+
+void main(){
+        vec3 p0 = mix(gl_in[0].gl_Position.xyz, gl_in[3].gl_Position.xyz, gl_TessCoord.x);
+        // interpolate in horizontal direction between vert. 1 and 2
+        vec3 p1 = mix(gl_in[1].gl_Position.xyz, gl_in[2].gl_Position.xyz, gl_TessCoord.x);
+        // interpolate in vert direction
+        vec3 tePosition = mix(p0, p1, gl_TessCoord.y);
+        gl_Position = g_WorldViewProjectionMatrix * vec4(tePosition, 1);
+}
+

+ 17 - 0
jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval

@@ -0,0 +1,17 @@
+layout(vertices=4) out;
+out gl_PerVertex{
+  vec4 gl_Position;
+}gl_out[];
+uniform int m_TessellationFactor;
+void main(){
+    if (gl_InvocationID == 0){
+        gl_TessLevelOuter[0]=m_TessellationFactor;
+        gl_TessLevelOuter[1]=m_TessellationFactor;
+        gl_TessLevelOuter[2]=m_TessellationFactor;
+        gl_TessLevelOuter[3]=m_TessellationFactor;
+
+        gl_TessLevelInner[0]=m_TessellationFactor;
+        gl_TessLevelInner[1]=m_TessellationFactor;
+    }
+    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;
+}

+ 5 - 0
jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert

@@ -0,0 +1,5 @@
+attribute vec3 inPosition;
+
+void main(){
+ gl_Position=vec4(inPosition,1);
+}