Merge pull request #220 from zzuegg/master

Geometry shader and Tessellation shader support
experimental
Kirill Vainer 10 years ago
commit 273f3a6e62
  1. 2
      gradle.properties
  2. 11
      jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java
  3. 6
      jme3-core/src/main/java/com/jme3/material/Technique.java
  4. 126
      jme3-core/src/main/java/com/jme3/material/TechniqueDef.java
  5. 19
      jme3-core/src/main/java/com/jme3/renderer/Caps.java
  6. 2
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java
  7. 46
      jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java
  8. 24
      jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java
  9. 26
      jme3-core/src/main/java/com/jme3/scene/Mesh.java
  10. 10
      jme3-core/src/main/java/com/jme3/shader/Shader.java
  11. 81
      jme3-core/src/main/java/com/jme3/shader/ShaderKey.java
  12. 24
      jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg
  13. 56
      jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java
  14. 9
      jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java
  15. 42
      jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java
  16. 68
      jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java
  17. 18
      jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java
  18. 3
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.frag
  19. 19
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.geom
  20. 4
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m
  21. 17
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3md
  22. 5
      jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert
  23. 3
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.frag
  24. 4
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m
  25. 19
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3md
  26. 13
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tsctrl
  27. 17
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval
  28. 5
      jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert

@ -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

@ -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);

@ -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);

@ -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 + '}';
}
}

@ -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
*/

@ -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+

@ -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);
}

@ -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);

@ -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);

@ -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;
}
/**

@ -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));
}
}

@ -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

@ -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();

@ -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){

@ -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();
}
}

@ -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();
}
}

@ -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);
}
}

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

@ -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();
}

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

@ -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
}
}
}

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

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

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

@ -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
}
}
}

@ -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);
}

@ -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;
}

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