From e45d5c093d2a5bff4447365065284cef337bfe20 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 18:33:40 +0100 Subject: [PATCH 01/34] *Added Caps: GL3.3 GL4.0 GLSL400 TesselationShader --- .../src/main/java/com/jme3/renderer/Caps.java | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/Caps.java b/jme3-core/src/main/java/com/jme3/renderer/Caps.java index b43e38bd6..613a031f6 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Caps.java +++ b/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 */ @@ -302,7 +315,6 @@ public enum Caps { * Supports 32-bit index buffers. */ IntegerIndexBuffer, - /** * Partial support for non-power-of-2 textures, typically found * on OpenGL ES 2 devices. From 0c35b20412072e9d720c5fa0a51cfee615d73ad8 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 18:38:11 +0100 Subject: [PATCH 02/34] Added Patch as MeshMode Added private variable patchVertexCount --- jme3-core/src/main/java/com/jme3/scene/Mesh.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index 5d0e8dcec..357cee438 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/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; From a1146f7676bb1379a0c244952f47e85987f71f04 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 18:41:14 +0100 Subject: [PATCH 03/34] Added TesselationEvaluation and TesselationControl enums --- jme3-core/src/main/java/com/jme3/shader/Shader.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/shader/Shader.java b/jme3-core/src/main/java/com/jme3/shader/Shader.java index d0efe81b7..24eca7199 100644 --- a/jme3-core/src/main/java/com/jme3/shader/Shader.java +++ b/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) + */ + TesselationControl, + /** + * Controls tesselation transform (e.g similar to the vertex shader, but required to mix inputs manual) + */ + TesselationEvaluation; } /** From 3ced941c537cff678ce859f7a194c505dac9017a Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 18:45:56 +0100 Subject: [PATCH 04/34] Added geom,tsctrl and tseval to the GLSLLoader --- jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg b/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg index 60b86fbc1..aa177d23f 100644 --- a/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg +++ b/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg @@ -21,6 +21,6 @@ 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, glsl, glsllib +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 From ab4d665b3e7a605896db3fa319d7c912ba70719b Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 18:46:16 +0100 Subject: [PATCH 05/34] Fixed typo --- jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg b/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg index aa177d23f..08e6492f5 100644 --- a/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg +++ b/jme3-core/src/main/resources/com/jme3/asset/Desktop.cfg @@ -21,6 +21,6 @@ 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.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 From 0d3292c83a300aecbde4e8ea187da90d9854ffb9 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 19:59:11 +0100 Subject: [PATCH 06/34] Refactoring of the shader system to allow addition of new shaderstages --- .../com/jme3/asset/DesktopAssetManager.java | 1 + .../java/com/jme3/material/Technique.java | 6 +- .../java/com/jme3/material/TechniqueDef.java | 123 +++++++++++----- .../main/java/com/jme3/shader/ShaderKey.java | 65 ++++++--- .../com/jme3/material/plugins/J3MLoader.java | 136 +++++++++--------- .../jme3tools/shadercheck/ShaderCheck.java | 7 +- 6 files changed, 205 insertions(+), 133 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java index 090538b60..bf0d145d8 100644 --- a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java +++ b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java @@ -402,6 +402,7 @@ public class DesktopAssetManager implements AssetManager { } shader = shaderGenerator.generateShader(); } else { + String vertName = key.getVertName(); String fragName = key.getFragName(); diff --git a/jme3-core/src/main/java/com/jme3/material/Technique.java b/jme3-core/src/main/java/com/jme3/material/Technique.java index ba2bc72f9..8321991bf 100644 --- a/jme3-core/src/main/java/com/jme3/material/Technique.java +++ b/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 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); diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index 1336442fa..768590725 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -34,15 +34,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. @@ -55,7 +50,9 @@ public class TechniqueDef implements Savable { * Version #1: Separate shader language for each shader source. */ public static final int SAVABLE_VERSION = 1; - + + + /** * Describes light rendering mode. */ @@ -100,10 +97,8 @@ public class TechniqueDef implements Savable { private EnumSet requiredCaps = EnumSet.noneOf(Caps.class); private String name; - private String vertName; - private String fragName; - private String vertLanguage; - private String fragLanguage; + private EnumMap shaderLanguage; + private EnumMap shaderName; private DefineList presetDefines; private boolean usesShaders; @@ -129,6 +124,7 @@ public class TechniqueDef implements Savable { * for default techniques. */ public TechniqueDef(String name){ + this(); this.name = name == null ? "Default" : name; } @@ -136,6 +132,8 @@ public class TechniqueDef implements Savable { * Serialization only. Do not use. */ public TechniqueDef(){ + shaderLanguage=new EnumMap(Shader.ShaderType.class); + shaderName=new EnumMap(Shader.ShaderType.class); } /** @@ -244,11 +242,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 +254,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 shaderName, EnumMap 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.TesselationControl)){ + requiredCaps.add(Caps.TesselationShader); + } + } + usesShaders=true; + } + /** * Returns the define name which the given material parameter influences. * @@ -329,7 +346,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 +357,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 +365,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 +436,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.TesselationControl), "tsctrlName", null); + oc.write(shaderName.get(Shader.ShaderType.TesselationEvaluation), "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.TesselationControl), "tsctrlLanguage", null); + oc.write(shaderLanguage.get(Shader.ShaderType.TesselationEvaluation), "tsevalLanguage", null); + oc.write(presetDefines, "presetDefines", null); oc.write(lightMode, "lightMode", LightMode.Disable); oc.write(shadowMode, "shadowMode", ShadowMode.Disable); @@ -428,8 +466,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.TesselationControl,ic.readString("tsctrlName", null)); + shaderName.put(Shader.ShaderType.TesselationEvaluation,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 +479,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.TesselationControl,ic.readString("tsctrlLanguage", null)); + shaderLanguage.put(Shader.ShaderType.TesselationEvaluation,ic.readString("tsevalLanguage", null)); } usesNodes = ic.readBoolean("usesNodes", false); @@ -461,6 +505,16 @@ public class TechniqueDef implements Savable { usesShaders = true; } + //todo: add javadoc + public EnumMap getShaderProgramNames() { + return shaderName; + } + + //todo: add javadoc + public EnumMap getShaderProgramLanguages() { + return shaderLanguage; + } + public ShaderGenerationInfo getShaderGenerationInfo() { return shaderGenerationInfo; } @@ -469,8 +523,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 + '}'; } } diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java index f6cb81508..9207c56aa 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java @@ -37,25 +37,30 @@ import com.jme3.export.JmeExporter; import com.jme3.export.JmeImporter; import com.jme3.export.OutputCapsule; import java.io.IOException; +import java.util.EnumMap; public class ShaderKey extends AssetKey { - protected String fragName; + protected EnumMap shaderLanguage; + protected EnumMap 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.class); + shaderName=new EnumMap(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 shaderLanguage,EnumMap shaderName){ + super(shaderName.get(Shader.ShaderType.Vertex)); + this.shaderLanguage=new EnumMap(Shader.ShaderType.class); + this.shaderName=new EnumMap(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 +73,15 @@ public class ShaderKey extends AssetKey { @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 +98,7 @@ public class ShaderKey extends AssetKey { 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 = 41 * hash + (defines != null ? defines.hashCode() : 0); cachedHashedCode = hash; } @@ -103,11 +110,11 @@ public class ShaderKey extends AssetKey { } public String getVertName(){ - return name; + return shaderName.get(Shader.ShaderType.Vertex); } public String getFragName() { - return fragName; + return shaderName.get(Shader.ShaderType.Fragment); } /** @@ -115,15 +122,15 @@ public class ShaderKey extends AssetKey { */ @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() { @@ -138,18 +145,32 @@ public class ShaderKey extends AssetKey { 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.TesselationControl), "tessControl_name", null); + oc.write(shaderName.get(Shader.ShaderType.TesselationEvaluation), "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.TesselationControl), "tsctrl_language", null); + oc.write(shaderLanguage.get(Shader.ShaderType.TesselationEvaluation), "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.TesselationControl,ic.readString("tessControl_name", null)); + shaderName.put(Shader.ShaderType.TesselationEvaluation,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.TesselationControl,ic.readString("tsctrl_language", null)); + shaderLanguage.put(Shader.ShaderType.TesselationEvaluation,ic.readString("tseval_language", null)); } } diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 23310f12f..727072e86 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/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; @@ -50,6 +51,7 @@ 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; @@ -60,7 +62,7 @@ public class J3MLoader implements AssetLoader { // private ErrorLogger errors; private ShaderNodeLoaderDelegate nodesLoaderDelegate; boolean isUseNodes = false; - + private AssetManager assetManager; private AssetKey key; @@ -68,16 +70,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 shaderLanguage; + private EnumMap shaderName; + private static final String whitespacePattern = "\\p{javaWhitespace}+"; public J3MLoader(){ + shaderLanguage=new EnumMap(Shader.ShaderType.class); + shaderName=new EnumMap(Shader.ShaderType.class); } @@ -91,16 +92,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 private void readLightMode(String statement) throws IOException{ String[] split = statement.split(whitespacePattern); @@ -163,14 +167,14 @@ public class J3MLoader implements AssetLoader { if (tex != null){ if (repeat){ tex.setWrap(WrapMode.Repeat); - } + } }else{ tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); if (repeat){ tex.setWrap(WrapMode.Repeat); } tex.setKey(texKey); - } + } return tex; }else{ String[] split = value.trim().split(whitespacePattern); @@ -216,13 +220,13 @@ public class J3MLoader implements AssetLoader { } } } - + // [ "(" ")" ] [ ":" ] [-LINEAR] private void readParam(String statement) throws IOException{ String name; String defaultVal = null; ColorSpace colorSpace = null; - + String[] split = statement.split("-"); if(split.length>1){ if(split[1].equalsIgnoreCase("LINEAR")){ @@ -230,9 +234,9 @@ public class J3MLoader implements AssetLoader { } statement = split[0].trim(); } - + split = statement.split(":"); - + // Parse default val if (split.length == 1){ // Doesn't contain default value @@ -241,9 +245,9 @@ public class J3MLoader implements AssetLoader { throw new IOException("Parameter statement syntax incorrect"); } statement = split[0].trim(); - defaultVal = split[1].trim(); + defaultVal = split[1].trim(); } - + // Parse ffbinding int startParen = statement.indexOf("("); if (startParen != -1){ @@ -253,32 +257,32 @@ public class J3MLoader implements AssetLoader { // don't care about bindingStr statement = statement.substring(0, startParen); } - + // Parse type + name split = statement.split(whitespacePattern); if (split.length != 2){ throw new IOException("Parameter statement syntax incorrect"); } - + VarType type; if (split[0].equals("Color")){ type = VarType.Vector4; }else{ type = VarType.valueOf(split[0]); } - + name = split[1]; - + Object defaultValObj = null; - if (defaultVal != null){ + if (defaultVal != null){ defaultValObj = readValue(type, defaultVal); } if(type.isTextureType()){ - materialDef.addMaterialParamTexture(type, name, colorSpace); + materialDef.addMaterialParamTexture(type, name, colorSpace); }else{ materialDef.addMaterialParam(type, name, defaultValObj); } - + } private void readValueParam(String statement) throws IOException{ @@ -373,7 +377,7 @@ public class J3MLoader implements AssetLoader { technique.setRenderState(renderState); renderState = null; } - + private void readForcedRenderState(List renderStates) throws IOException{ renderState = new RenderState(); for (Statement statement : renderStates){ @@ -382,7 +386,7 @@ public class J3MLoader implements AssetLoader { technique.setForcedRenderState(renderState); renderState = null; } - + // [ ":" ] private void readDefine(String statement) throws IOException{ String[] split = statement.split(":"); @@ -402,9 +406,9 @@ public class J3MLoader implements AssetLoader { } } - + private void readTechniqueStatement(Statement statement) throws IOException{ - String[] split = statement.getLine().split("[ \\{]"); + String[] split = statement.getLine().split("[ \\{]"); if (split[0].equals("VertexShader") || split[0].equals("FragmentShader")){ readShaderStatement(statement.getLine()); @@ -414,12 +418,12 @@ public class J3MLoader implements AssetLoader { readShadowMode(statement.getLine()); }else if (split[0].equals("WorldParameters")){ readWorldParams(statement.getContents()); - }else if (split[0].equals("RenderState")){ + }else if (split[0].equals("RenderState")){ readRenderState(statement.getContents()); - }else if (split[0].equals("ForcedRenderState")){ + }else if (split[0].equals("ForcedRenderState")){ readForcedRenderState(statement.getContents()); - }else if (split[0].equals("Defines")){ - readDefines(statement.getContents()); + }else if (split[0].equals("Defines")){ + readDefines(statement.getContents()); } else if (split[0].equals("ShaderNodesDefinitions")) { initNodesLoader(); if (isUseNodes) { @@ -432,14 +436,14 @@ public class J3MLoader implements AssetLoader { } } else if (split[0].equals("FragmentShaderNodes")) { initNodesLoader(); - if (isUseNodes) { + if (isUseNodes) { nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents()); } } else { throw new MatParseException(null, split[0], statement); } } - + private void readTransparentStatement(String statement) throws IOException{ String[] split = statement.split(whitespacePattern); if (split.length != 2){ @@ -459,30 +463,28 @@ public class J3MLoader implements AssetLoader { } else { throw new IOException("Technique statement syntax incorrect"); } - + for (Statement statement : techStat.getContents()){ readTechniqueStatement(statement); } - + if(isUseNodes){ nodesLoaderDelegate.computeConditions(); //used for caching later, the shader here is not a file. 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 roots) throws IOException{ + private void loadFromRoot(List roots) throws IOException{ if (roots.size() == 2){ Statement exception = roots.get(0); String line = exception.getLine(); @@ -494,7 +496,7 @@ public class J3MLoader implements AssetLoader { }else if (roots.size() != 1){ throw new IOException("Too many roots in J3M/J3MD file"); } - + boolean extending = false; Statement materialStat = roots.get(0); String materialName = materialStat.getLine(); @@ -507,16 +509,16 @@ public class J3MLoader implements AssetLoader { }else{ throw new IOException("Specified file is not a Material file"); } - + String[] split = materialName.split(":", 2); - + if (materialName.equals("")){ - throw new MatParseException("Material name cannot be empty", materialStat); + throw new MatParseException("Material name cannot be empty", materialStat); } if (split.length == 2){ if (!extending){ - throw new MatParseException("Must use 'Material' when extending.", materialStat); + throw new MatParseException("Must use 'Material' when extending.", materialStat); } String extendedMat = split[1].trim(); @@ -531,15 +533,15 @@ public class J3MLoader implements AssetLoader { // material.setAssetName(fileName); }else if (split.length == 1){ if (extending){ - throw new MatParseException("Expected ':', got '{'", materialStat); + throw new MatParseException("Expected ':', got '{'", materialStat); } materialDef = new MaterialDef(assetManager, materialName); // NOTE: pass file name for defs so they can be loaded later materialDef.setAssetName(key.getName()); }else{ - throw new MatParseException("Cannot use colon in material name/path", materialStat); + throw new MatParseException("Cannot use colon in material name/path", materialStat); } - + for (Statement statement : materialStat.getContents()){ split = statement.getLine().split("[ \\{]"); String statType = split[0]; @@ -557,25 +559,25 @@ public class J3MLoader implements AssetLoader { }else if (statType.equals("MaterialParameters")){ readMaterialParams(statement.getContents()); }else{ - throw new MatParseException("Expected material statement, got '"+statType+"'", statement); + throw new MatParseException("Expected material statement, got '"+statType+"'", statement); } } } } - public Object load(AssetInfo info) throws IOException { + public Object load(AssetInfo info) throws IOException { this.assetManager = info.getManager(); - InputStream in = info.openStream(); + InputStream in = info.openStream(); try { - key = info.getKey(); + key = info.getKey(); loadFromRoot(BlockLanguageParser.parse(in)); } finally { if (in != null){ in.close(); } } - + if (material != null){ if (!(info.getKey() instanceof MaterialKey)){ throw new IOException("Material instances must be loaded via MaterialKey"); @@ -587,7 +589,7 @@ public class J3MLoader implements AssetLoader { return materialDef; } } - + public MaterialDef loadMaterialDef(List roots, AssetManager manager, AssetKey key) throws IOException { this.key = key; this.assetManager = manager; @@ -597,8 +599,8 @@ public class J3MLoader implements AssetLoader { protected void initNodesLoader() { if (!isUseNodes) { - isUseNodes = fragName == null && vertName == null; - if (isUseNodes) { + isUseNodes = shaderName.get(Shader.ShaderType.Vertex) == null && shaderName.get(Shader.ShaderType.Fragment) == null; + if (isUseNodes) { if(nodesLoaderDelegate == null){ nodesLoaderDelegate = new ShaderNodeLoaderDelegate(); }else{ @@ -609,6 +611,6 @@ public class J3MLoader implements AssetLoader { nodesLoaderDelegate.setAssetManager(assetManager); } } - } + } } diff --git a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java index ddd2993e8..8e73f0e6f 100644 --- a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java +++ b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java @@ -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){ From 1949a7d831be36c7d4d9117d3ae2ffbc717f221b Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 20:23:18 +0100 Subject: [PATCH 07/34] Added GL4 Interface, Added GL_*_SHADER constants Added Caps to the Renderer Added required converters --- .../java/com/jme3/renderer/opengl/GL3.java | 2 +- .../java/com/jme3/renderer/opengl/GL4.java | 44 +++++++++++++++++++ .../com/jme3/renderer/opengl/GLRenderer.java | 14 ++++++ .../java/com/jme3/renderer/lwjgl/LwjglGL.java | 4 +- 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java index 91b14488f..50eb065ab 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL3.java +++ b/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+ diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java new file mode 100644 index 000000000..81adf4bfc --- /dev/null +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java @@ -0,0 +1,44 @@ +/* + * 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; +} diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index da5392b5c..f6640a049 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -183,6 +183,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 +205,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: @@ -1008,6 +1016,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 TesselationControl: + return GL4.GL_TESS_CONTROL_SHADER; + case TesselationEvaluation: + return GL4.GL_TESS_EVALUATION_SHADER; default: throw new UnsupportedOperationException("Unrecognized shader type."); } diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index b213fdded..ee2581f9a 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -9,6 +9,8 @@ import java.nio.ByteBuffer; import java.nio.FloatBuffer; import java.nio.IntBuffer; import java.nio.ShortBuffer; + +import com.jme3.renderer.opengl.GL4; import org.lwjgl.opengl.GL11; import org.lwjgl.opengl.GL12; import org.lwjgl.opengl.GL13; @@ -16,7 +18,7 @@ import org.lwjgl.opengl.GL15; import org.lwjgl.opengl.GL20; import org.lwjgl.opengl.GL30; -public class LwjglGL implements GL, GL2, GL3 { +public class LwjglGL implements GL, GL2, GL3,GL4 { private static void checkLimit(Buffer buffer) { if (buffer == null) { From 46a48f466dcb03845963cab9ee297dd0390d0320 Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 20:27:08 +0100 Subject: [PATCH 08/34] Added loaders to ShaderCheck --- jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java b/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java index 8e73f0e6f..c77fa2b2e 100644 --- a/jme3-core/src/tools/java/jme3tools/shadercheck/ShaderCheck.java +++ b/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){ From 1ad8ff154c24b256bdd430963027bdb09c100f9a Mon Sep 17 00:00:00 2001 From: michael Date: Mon, 23 Feb 2015 22:39:46 +0100 Subject: [PATCH 09/34] Fixed uploading of all shader stages --- .../com/jme3/asset/DesktopAssetManager.java | 61 ++-- .../asset/cache/WeakRefCloneAssetCache.java | 84 +++--- .../com/jme3/renderer/opengl/GLRenderer.java | 204 ++++++------- .../main/java/com/jme3/shader/ShaderKey.java | 13 + .../com/jme3/material/plugins/J3MLoader.java | 278 +++++++++--------- .../resources/Materials/Geom/SimpleGeom.frag | 3 + .../resources/Materials/Geom/SimpleGeom.geom | 19 ++ .../resources/Materials/Geom/SimpleGeom.j3m | 4 + .../resources/Materials/Geom/SimpleGeom.j3md | 17 ++ .../resources/Materials/Geom/SimpleGeom.vert | 5 + 10 files changed, 374 insertions(+), 314 deletions(-) create mode 100644 jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.frag create mode 100644 jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.geom create mode 100644 jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m create mode 100644 jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3md create mode 100644 jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert diff --git a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java index bf0d145d8..109ebed36 100644 --- a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java +++ b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java @@ -68,12 +68,12 @@ public class DesktopAssetManager implements AssetManager { private static final Logger logger = Logger.getLogger(AssetManager.class.getName()); private ShaderGenerator shaderGenerator; - + private final ImplHandler handler = new ImplHandler(this); - private CopyOnWriteArrayList eventListeners = + private CopyOnWriteArrayList eventListeners = new CopyOnWriteArrayList(); - + private List classLoaders = Collections.synchronizedList(new ArrayList()); @@ -89,7 +89,7 @@ public class DesktopAssetManager implements AssetManager { public DesktopAssetManager(URL configFile){ if (configFile != null){ loadConfigFile(configFile); - } + } logger.fine("DesktopAssetManager created."); } @@ -109,11 +109,11 @@ public class DesktopAssetManager implements AssetManager { } } } - + public void addClassLoader(ClassLoader loader) { classLoaders.add(loader); } - + public void removeClassLoader(ClassLoader loader) { classLoaders.remove(loader); } @@ -121,7 +121,7 @@ public class DesktopAssetManager implements AssetManager { public List getClassLoaders(){ return Collections.unmodifiableList(classLoaders); } - + public void addAssetEventListener(AssetEventListener listener) { eventListeners.add(listener); } @@ -133,7 +133,7 @@ public class DesktopAssetManager implements AssetManager { public void clearAssetEventListeners() { eventListeners.clear(); } - + public void setAssetEventListener(AssetEventListener listener){ eventListeners.clear(); eventListeners.add(listener); @@ -160,7 +160,7 @@ public class DesktopAssetManager implements AssetManager { registerLoader(clazz, extensions); } } - + public void unregisterLoader(Class loaderClass) { handler.removeLoader(loaderClass); if (logger.isLoggable(Level.FINER)){ @@ -190,7 +190,7 @@ public class DesktopAssetManager implements AssetManager { registerLocator(rootPath, clazz); } } - + public void unregisterLocator(String rootPath, Class clazz){ handler.removeLocator(clazz, rootPath); if (logger.isLoggable(Level.FINER)){ @@ -198,7 +198,7 @@ public class DesktopAssetManager implements AssetManager { clazz.getSimpleName()); } } - + public AssetInfo locateAsset(AssetKey key){ AssetInfo info = handler.tryLocate(key); if (info == null){ @@ -206,7 +206,7 @@ public class DesktopAssetManager implements AssetManager { } return info; } - + public T getFromCache(AssetKey key) { AssetCache cache = handler.getCache(key.getCacheType()); if (cache != null) { @@ -220,7 +220,7 @@ public class DesktopAssetManager implements AssetManager { throw new IllegalArgumentException("Key " + key + " specifies no cache."); } } - + public void addToCache(AssetKey key, T asset) { AssetCache cache = handler.getCache(key.getCacheType()); if (cache != null) { @@ -230,7 +230,7 @@ public class DesktopAssetManager implements AssetManager { throw new IllegalArgumentException("Key " + key + " specifies no cache."); } } - + public boolean deleteFromCache(AssetKey key) { AssetCache cache = handler.getCache(key.getCacheType()); if (cache != null) { @@ -239,7 +239,7 @@ public class DesktopAssetManager implements AssetManager { throw new IllegalArgumentException("Key " + key + " specifies no cache."); } } - + public void clearCache(){ handler.clearCache(); if (logger.isLoggable(Level.FINER)){ @@ -257,14 +257,14 @@ public class DesktopAssetManager implements AssetManager { public T loadAsset(AssetKey key){ if (key == null) throw new IllegalArgumentException("key cannot be null"); - + for (AssetEventListener listener : eventListeners){ listener.assetRequested(key); } - + AssetCache cache = handler.getCache(key.getCacheType()); AssetProcessor proc = handler.getProcessor(key.getProcessorType()); - + Object obj = cache != null ? cache.getFromCache(key) : null; if (obj == null){ // Asset not in cache, load it from file system. @@ -298,17 +298,17 @@ public class DesktopAssetManager implements AssetManager { logger.log(Level.FINER, "Loaded {0} with {1}", new Object[]{key, loader.getClass().getSimpleName()}); } - + if (proc != null){ // do processing on asset before caching obj = proc.postProcess(key, obj); } - + if (cache != null){ // At this point, obj should be of type T cache.addToCache(key, (T) obj); } - + for (AssetEventListener listener : eventListeners){ listener.assetLoaded(key); } @@ -334,7 +334,7 @@ public class DesktopAssetManager implements AssetManager { } } } - + return clone; } @@ -342,7 +342,7 @@ public class DesktopAssetManager implements AssetManager { return loadAsset(new AssetKey(name)); } - public Texture loadTexture(TextureKey key){ + public Texture loadTexture(TextureKey key){ return (Texture) loadAsset(key); } @@ -393,6 +393,7 @@ public class DesktopAssetManager implements AssetManager { public Shader loadShader(ShaderKey key){ // cache abuse in method // that doesn't use loaders/locators + System.out.println(); AssetCache cache = handler.getCache(SimpleAssetCache.class); Shader shader = (Shader) cache.getFromCache(key); if (shader == null){ @@ -402,17 +403,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); @@ -443,5 +438,5 @@ public class DesktopAssetManager implements AssetManager { this.shaderGenerator = shaderGenerator; } - + } diff --git a/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java b/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java index 46ddfd199..15c453dcc 100644 --- a/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java +++ b/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java @@ -33,6 +33,7 @@ package com.jme3.asset.cache; import com.jme3.asset.AssetKey; import com.jme3.asset.CloneableSmartAsset; + import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -45,43 +46,43 @@ import java.util.logging.Logger; * caches cloneable assets in a weak-key * cache, allowing them to be collected when memory is low. * The cache stores weak references to the asset keys, so that - * when all clones of the original asset are collected, will cause the + * when all clones of the original asset are collected, will cause the * asset to be automatically removed from the cache. - * -* @author Kirill Vainer + * + * @author Kirill Vainer */ public class WeakRefCloneAssetCache implements AssetCache { private static final Logger logger = Logger.getLogger(WeakRefAssetCache.class.getName()); - + private final ReferenceQueue refQueue = new ReferenceQueue(); - + /** - * Maps cloned key to AssetRef which has a weak ref to the original + * Maps cloned key to AssetRef which has a weak ref to the original * key and a strong ref to the original asset. */ - private final ConcurrentHashMap smartCache + private final ConcurrentHashMap smartCache = new ConcurrentHashMap(); - + /** * Stored in the ReferenceQueue to find out when originalKey is collected * by GC. Once collected, the clonedKey is used to remove the asset * from the cache. */ private static final class KeyRef extends PhantomReference { - + AssetKey clonedKey; - + public KeyRef(AssetKey originalKey, ReferenceQueue refQueue) { super(originalKey, refQueue); clonedKey = originalKey.clone(); } } - + /** * Stores the original key and original asset. * The asset info contains a cloneable asset (e.g. the original, from - * which all clones are made). Also a weak reference to the + * which all clones are made). Also a weak reference to the * original key which is used when the clones are produced. */ private static final class AssetRef extends WeakReference { @@ -94,24 +95,24 @@ public class WeakRefCloneAssetCache implements AssetCache { } } - private final ThreadLocal> assetLoadStack + private final ThreadLocal> assetLoadStack = new ThreadLocal>() { @Override protected ArrayList initialValue() { return new ArrayList(); } }; - - private void removeCollectedAssets(){ + + private void removeCollectedAssets() { int removedAssets = 0; - for (KeyRef ref; (ref = (KeyRef)refQueue.poll()) != null;){ + for (KeyRef ref; (ref = (KeyRef) refQueue.poll()) != null; ) { // (Cannot use ref.get() since it was just collected by GC!) AssetKey key = ref.clonedKey; - + // Asset was collected, note that at this point the asset cache // might not even have this asset anymore, it is OK. - if (smartCache.remove(key) != null){ - removedAssets ++; + if (smartCache.remove(key) != null) { + removedAssets++; //System.out.println("WeakRefAssetCache: The asset " + ref.assetKey + " was purged from the cache"); } } @@ -119,25 +120,24 @@ public class WeakRefCloneAssetCache implements AssetCache { logger.log(Level.FINE, "WeakRefAssetCache: {0} assets were purged from the cache.", removedAssets); } } - + public void addToCache(AssetKey originalKey, T obj) { // Make room for new asset removeCollectedAssets(); - CloneableSmartAsset asset = (CloneableSmartAsset) obj; - + // No circular references, since the original asset is // strongly referenced, we don't want the key strongly referenced. - asset.setKey(null); - + asset.setKey(null); + // Start tracking the collection of originalKey // (this adds the KeyRef to the ReferenceQueue) KeyRef ref = new KeyRef(originalKey, refQueue); - + // Place the asset in the cache, but use a clone of // the original key. smartCache.put(ref.clonedKey, new AssetRef(asset, originalKey)); - + // Push the original key used to load the asset // so that it can be set on the clone later ArrayList loadStack = assetLoadStack.get(); @@ -146,9 +146,9 @@ public class WeakRefCloneAssetCache implements AssetCache { public void registerAssetClone(AssetKey key, T clone) { ArrayList loadStack = assetLoadStack.get(); - ((CloneableSmartAsset)clone).setKey(loadStack.remove(loadStack.size() - 1)); + ((CloneableSmartAsset) clone).setKey(loadStack.remove(loadStack.size() - 1)); } - + public void notifyNoAssetClone() { ArrayList loadStack = assetLoadStack.get(); loadStack.remove(loadStack.size() - 1); @@ -156,10 +156,10 @@ public class WeakRefCloneAssetCache implements AssetCache { public T getFromCache(AssetKey key) { AssetRef smartInfo; - synchronized (smartCache){ + synchronized (smartCache) { smartInfo = smartCache.get(key); } - + if (smartInfo == null) { return null; } else { @@ -167,40 +167,40 @@ public class WeakRefCloneAssetCache implements AssetCache { // can check this and determine that the asset clone // belongs to the asset retrieved here. AssetKey keyForTheClone = smartInfo.get(); - if (keyForTheClone == null){ + if (keyForTheClone == null) { // The asset was JUST collected by GC // (between here and smartCache.get) return null; } - + // Prevent original key from getting collected // while an asset is loaded for it. ArrayList loadStack = assetLoadStack.get(); loadStack.add(keyForTheClone); - + return (T) smartInfo.asset; } } public boolean deleteFromCache(AssetKey key) { ArrayList loadStack = assetLoadStack.get(); - - if (!loadStack.isEmpty()){ + + if (!loadStack.isEmpty()) { throw new UnsupportedOperationException("Cache cannot be modified" - + "while assets are being loaded"); + + "while assets are being loaded"); } - + return smartCache.remove(key) != null; } - + public void clearCache() { ArrayList loadStack = assetLoadStack.get(); - - if (!loadStack.isEmpty()){ + + if (!loadStack.isEmpty()) { throw new UnsupportedOperationException("Cache cannot be modified" - + "while assets are being loaded"); + + "while assets are being loaded"); } - + smartCache.clear(); } } diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index f6640a049..03f06f5a4 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -71,7 +71,7 @@ public class GLRenderer implements Renderer { private static final Logger logger = Logger.getLogger(GLRenderer.class.getName()); private static final boolean VALIDATE_SHADER = false; private static final Pattern GLVERSION_PATTERN = Pattern.compile(".*?(\\d+)\\.(\\d+).*"); - + private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); private final StringBuilder stringBuf = new StringBuilder(250); private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); @@ -81,7 +81,7 @@ public class GLRenderer implements Renderer { private final NativeObjectManager objManager = new NativeObjectManager(); private final EnumSet caps = EnumSet.noneOf(Caps.class); private final EnumMap limits = new EnumMap(Limits.class); - + // private int vertexTextureUnits; // private int fragTextureUnits; // private int vertexUniforms; @@ -110,7 +110,7 @@ public class GLRenderer implements Renderer { private final GLExt glext; private final GLFbo glfbo; private final TextureUtil texUtil; - + public GLRenderer(GL gl, GLFbo glfbo) { this.gl = gl; this.gl2 = gl instanceof GL2 ? (GL2)gl : null; @@ -129,7 +129,7 @@ public class GLRenderer implements Renderer { public EnumSet getCaps() { return caps; } - + // Not making public yet ... public EnumMap getLimits() { return limits; @@ -142,7 +142,7 @@ public class GLRenderer implements Renderer { } return extensionSet; } - + public static int extractVersion(String version) { Matcher m = GLVERSION_PATTERN.matcher(version); if (m.matches()) { @@ -162,17 +162,17 @@ public class GLRenderer implements Renderer { private boolean hasExtension(String extensionName) { return extensions.contains(extensionName); } - + private void loadCapabilitiesES() { caps.add(Caps.GLSL100); caps.add(Caps.OpenGLES20); - + // Important: Do not add OpenGL20 - that's the desktop capability! } - + private void loadCapabilitiesGL2() { int oglVer = extractVersion(gl.glGetString(GL.GL_VERSION)); - + if (oglVer >= 200) { caps.add(Caps.OpenGL20); if (oglVer >= 210) { @@ -194,9 +194,9 @@ public class GLRenderer implements Renderer { } } } - + int glslVer = extractVersion(gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)); - + switch (glslVer) { default: if (glslVer < 400) { @@ -222,27 +222,27 @@ public class GLRenderer implements Renderer { caps.add(Caps.GLSL100); break; } - + // Workaround, always assume we support GLSL100 & GLSL110 // Supporting OpenGL 2.0 means supporting GLSL 1.10. caps.add(Caps.GLSL110); caps.add(Caps.GLSL100); - + // Fix issue in TestRenderToMemory when GL.GL_FRONT is the main // buffer being used. context.initialDrawBuf = getInteger(GL2.GL_DRAW_BUFFER); context.initialReadBuf = getInteger(GL2.GL_READ_BUFFER); - + // XXX: This has to be GL.GL_BACK for canvas on Mac // Since initialDrawBuf is GL.GL_FRONT for pbuffer, gotta // change this value later on ... // initialDrawBuf = GL.GL_BACK; // initialReadBuf = GL.GL_BACK; } - + private void loadCapabilitiesCommon() { extensions = loadExtensions(gl.glGetString(GL.GL_EXTENSIONS)); - + limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); if (limits.get(Limits.VertexTextureUnits) > 0) { caps.add(Caps.VertexTextureFetch); @@ -262,7 +262,7 @@ public class GLRenderer implements Renderer { limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE)); - if (hasExtension("GL_ARB_draw_instanced") && + if (hasExtension("GL_ARB_draw_instanced") && hasExtension("GL_ARB_instanced_arrays")) { caps.add(Caps.MeshInstancing); } @@ -270,43 +270,43 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_OES_element_index_uint") || gl2 != null) { caps.add(Caps.IntegerIndexBuffer); } - + if (hasExtension("GL_ARB_texture_buffer_object")) { caps.add(Caps.TextureBuffer); } - + // == texture format extensions == - + boolean hasFloatTexture = false; - hasFloatTexture = hasExtension("GL_OES_texture_half_float") && + hasFloatTexture = hasExtension("GL_OES_texture_half_float") && hasExtension("GL_OES_texture_float"); - + if (!hasFloatTexture) { hasFloatTexture = hasExtension("GL_ARB_texture_float") && hasExtension("GL_ARB_half_float_pixel"); - + if (!hasFloatTexture) { hasFloatTexture = caps.contains(Caps.OpenGL30); } } - + if (hasFloatTexture) { caps.add(Caps.FloatTexture); } - + if (hasExtension("GL_OES_depth_texture") || gl2 != null) { caps.add(Caps.DepthTexture); - + // TODO: GL_OES_depth24 } - - if (hasExtension("GL_OES_rgb8_rgba8") || - hasExtension("GL_ARM_rgba8") || + + if (hasExtension("GL_OES_rgb8_rgba8") || + hasExtension("GL_ARM_rgba8") || hasExtension("GL_EXT_texture_format_BGRA8888")) { caps.add(Caps.Rgba8); } - + if (caps.contains(Caps.OpenGL30) || hasExtension("GL_OES_packed_depth_stencil")) { caps.add(Caps.PackedDepthStencilBuffer); } @@ -321,35 +321,35 @@ public class GLRenderer implements Renderer { caps.add(Caps.FloatDepthBuffer); } - if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || + if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || caps.contains(Caps.OpenGL30)) { // Either OpenGL3 is available or both packed_float & half_float_pixel. caps.add(Caps.PackedFloatColorBuffer); caps.add(Caps.PackedFloatTexture); } - + if (hasExtension("GL_EXT_texture_shared_exponent") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.SharedExponentTexture); } - + if (hasExtension("GL_EXT_texture_compression_s3tc")) { caps.add(Caps.TextureCompressionS3TC); } - + if (hasExtension("GL_ARB_ES3_compatibility")) { caps.add(Caps.TextureCompressionETC2); caps.add(Caps.TextureCompressionETC1); } else if (hasExtension("GL_OES_compressed_ETC1_RGB8_texture")) { caps.add(Caps.TextureCompressionETC1); } - + // == end texture format extensions == - + if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.VertexBufferArray); } - if (hasExtension("GL_ARB_texture_non_power_of_two") || + if (hasExtension("GL_ARB_texture_non_power_of_two") || hasExtension("GL_OES_texture_npot") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.NonPowerOfTwoTextures); @@ -358,7 +358,7 @@ public class GLRenderer implements Renderer { + "support non-power-of-2 textures. " + "Some features might not work."); } - + if (caps.contains(Caps.OpenGLES20)) { // OpenGL ES 2 has some limited support for NPOT textures caps.add(Caps.PartialNonPowerOfTwoTextures); @@ -374,14 +374,14 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_EXT_framebuffer_object")) { caps.add(Caps.FrameBuffer); - + limits.put(Limits.RenderBufferSize, getInteger(GLExt.GL_MAX_RENDERBUFFER_SIZE_EXT)); limits.put(Limits.FrameBufferAttachments, getInteger(GLExt.GL_MAX_COLOR_ATTACHMENTS_EXT)); - + if (hasExtension("GL_EXT_framebuffer_blit")) { caps.add(Caps.FrameBufferBlit); } - + if (hasExtension("GL_EXT_framebuffer_multisample")) { caps.add(Caps.FrameBufferMultisample); limits.put(Limits.FrameBufferSamples, getInteger(GLExt.GL_MAX_SAMPLES_EXT)); @@ -419,9 +419,9 @@ public class GLRenderer implements Renderer { } caps.add(Caps.Multisample); } - + // Supports sRGB pipeline. - if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) + if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) || caps.contains(Caps.OpenGL30) ) { caps.add(Caps.Srgb); } @@ -430,24 +430,24 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_ARB_seamless_cube_map") || caps.contains(Caps.OpenGL32)) { caps.add(Caps.SeamlessCubemap); } - + // if (hasExtension("GL_ARB_get_program_binary")) { // int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); // } - + // Print context information logger.log(Level.INFO, "OpenGL Renderer Information\n" + " * Vendor: {0}\n" + " * Renderer: {1}\n" + " * OpenGL Version: {2}\n" + " * GLSL Version: {3}", - new Object[]{ - gl.glGetString(GL.GL_VENDOR), + new Object[]{ + gl.glGetString(GL.GL_VENDOR), gl.glGetString(GL.GL_RENDERER), gl.glGetString(GL.GL_VERSION), gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION) }); - + // Print capabilities (if fine logging is enabled) if (logger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(); @@ -458,10 +458,10 @@ public class GLRenderer implements Renderer { } logger.log(Level.FINE, sb.toString()); } - + texUtil.initialize(caps); } - + private void loadCapabilities() { if (gl2 != null) { loadCapabilitiesGL2(); @@ -470,22 +470,22 @@ public class GLRenderer implements Renderer { } loadCapabilitiesCommon(); } - + private int getInteger(int en) { intBuf16.clear(); gl.glGetInteger(en, intBuf16); return intBuf16.get(0); } - + private boolean getBoolean(int en) { gl.glGetBoolean(en, nameBuf); return nameBuf.get(0) != (byte)0; } - + @SuppressWarnings("fallthrough") public void initialize() { loadCapabilities(); - + // Initialize default state.. gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); } @@ -579,7 +579,7 @@ public class GLRenderer implements Renderer { } if (state.isDepthTest() && !context.depthTestEnabled) { - gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(convertTestFunction(context.depthFunc)); context.depthTestEnabled = true; } else if (!state.isDepthTest() && context.depthTestEnabled) { @@ -718,7 +718,7 @@ public class GLRenderer implements Renderer { break; case Screen: gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; + break; case Exclusion: gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR); break; @@ -1043,12 +1043,12 @@ public class GLRenderer implements Renderer { boolean gles2 = caps.contains(Caps.OpenGLES20); String language = source.getLanguage(); - + if (gles2 && !language.equals("GLSL100")) { throw new RendererException("This shader cannot run in OpenGL ES 2. " + "Only GLSL 1.00 shaders are supported."); } - + // Upload shader source. // Merge the defines and source code. stringBuf.setLength(0); @@ -1075,14 +1075,14 @@ public class GLRenderer implements Renderer { } } } - + if (linearizeSrgbImages) { stringBuf.append("#define SRGB 1\n"); } - + stringBuf.append(source.getDefines()); stringBuf.append(source.getSource()); - + intBuf1.clear(); intBuf1.put(0, stringBuf.length()); gl.glShaderSource(id, new String[]{ stringBuf.toString() }, intBuf1); @@ -1140,7 +1140,7 @@ public class GLRenderer implements Renderer { // If using GLSL 1.5, we bind the outputs for the user // For versions 3.3 and up, user should use layout qualifiers instead. boolean bindFragDataRequired = false; - + for (ShaderSource source : shader.getSources()) { if (source.isUpdateNeeded()) { updateShaderSourceData(source); @@ -1412,7 +1412,7 @@ public class GLRenderer implements Renderer { } else if (attachmentSlot < 0 || attachmentSlot >= 16) { throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); } - + return GLExt.GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; } @@ -1422,7 +1422,7 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded()) { // Check NPOT requirements checkNonPowerOfTwo(tex); - + updateTexImageData(image, tex.getType(), 0); // NOTE: For depth textures, sets nearest/no-mips mode @@ -1583,7 +1583,7 @@ public class GLRenderer implements Renderer { // update viewport to reflect framebuffer's resolution setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - + if (context.boundFBO != fb.getId()) { glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, fb.getId()); statistics.onFrameBufferUse(fb, true); @@ -1656,7 +1656,7 @@ public class GLRenderer implements Renderer { public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { readFrameBufferWithGLFormat(fb, byteBuf, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); } - + private void readFrameBufferWithGLFormat(FrameBuffer fb, ByteBuffer byteBuf, int glFormat, int dataType) { if (fb != null) { RenderBuffer rb = fb.getColorBuffer(); @@ -1678,8 +1678,8 @@ public class GLRenderer implements Renderer { gl.glReadPixels(vpX, vpY, vpW, vpH, glFormat, dataType, byteBuf); } - - public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { + + public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { GLImageFormat glFormat = texUtil.getImageFormatWithError(format, false); readFrameBufferWithGLFormat(fb, byteBuf, glFormat.format, glFormat.dataType); } @@ -1716,10 +1716,10 @@ public class GLRenderer implements Renderer { \*********************************************************************/ private int convertTextureType(Texture.Type type, int samples, int face) { if (samples > 1 && !caps.contains(Caps.TextureMultisample)) { - throw new RendererException("Multisample textures are not supported" + + throw new RendererException("Multisample textures are not supported" + " by the video hardware."); } - + switch (type) { case TwoDimensional: if (samples > 1) { @@ -1739,7 +1739,7 @@ public class GLRenderer implements Renderer { } case ThreeDimensional: if (!caps.contains(Caps.OpenGL20)) { - throw new RendererException("3D textures are not supported" + + throw new RendererException("3D textures are not supported" + " by the video hardware."); } return GL2.GL_TEXTURE_3D; @@ -1823,11 +1823,11 @@ public class GLRenderer implements Renderer { int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); boolean haveMips = true; - + if (image != null) { haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps(); } - + // filter things if (image.getLastTextureState().magFilter != tex.getMagFilter()) { int magFilter = convertMagFilter(tex.getMagFilter()); @@ -1850,7 +1850,7 @@ public class GLRenderer implements Renderer { context.seamlessCubemap = false; } } - + if (tex.getAnisotropicFilter() > 1) { if (caps.contains(Caps.TextureFilterAnisotropic)) { gl.glTexParameterf(target, @@ -1862,7 +1862,7 @@ public class GLRenderer implements Renderer { if (context.pointSprite) { return; // Attempt to fix glTexParameter crash for some ATI GPUs } - + // repeat modes switch (tex.getType()) { case ThreeDimensional: @@ -1891,7 +1891,7 @@ public class GLRenderer implements Renderer { // R to Texture compare mode if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); - gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); + gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL); } else { @@ -1899,7 +1899,7 @@ public class GLRenderer implements Renderer { } }else{ //restoring default value - gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); + gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); } tex.compareModeUpdated(); } @@ -1908,10 +1908,10 @@ public class GLRenderer implements Renderer { /** * Validates if a potentially NPOT texture is supported by the hardware. *

- * Textures with power-of-2 dimensions are supported on all hardware, however + * Textures with power-of-2 dimensions are supported on all hardware, however * non-power-of-2 textures may or may not be supported depending on which * texturing features are used. - * + * * @param tex The texture to validate. * @throws RendererException If the texture is not supported by the hardware */ @@ -1920,19 +1920,19 @@ public class GLRenderer implements Renderer { // Texture is power-of-2, safe to use. return; } - + if (caps.contains(Caps.NonPowerOfTwoTextures)) { // Texture is NPOT but it is supported by video hardware. return; } - + // Maybe we have some / partial support for NPOT? if (!caps.contains(Caps.PartialNonPowerOfTwoTextures)) { // Cannot use any type of NPOT texture (uncommon) throw new RendererException("non-power-of-2 textures are not " + "supported by the video hardware"); } - + // Partial NPOT supported.. if (tex.getMinFilter().usesMipMapLevels()) { throw new RendererException("non-power-of-2 textures with mip-maps " @@ -1959,10 +1959,10 @@ public class GLRenderer implements Renderer { throw new UnsupportedOperationException("unrecongized texture type"); } } - + /** * Uploads the given image to the GL driver. - * + * * @param img The image to upload * @param type How the data in the image argument should be interpreted. * @param unit The texture slot to be used to upload the image, not important @@ -1986,7 +1986,7 @@ public class GLRenderer implements Renderer { gl.glActiveTexture(GL.GL_TEXTURE0 + unit); context.boundTextureUnit = unit; } - + gl.glBindTexture(target, texId); context.boundTextures[unit] = img; @@ -2029,12 +2029,12 @@ public class GLRenderer implements Renderer { throw new RendererException("Multisample textures are not supported by the video hardware"); } } - + // Check if graphics card doesn't support depth textures if (img.getFormat().isDepthFormat() && !caps.contains(Caps.DepthTexture)) { throw new RendererException("Depth textures are not supported by the video hardware"); } - + if (target == GL.GL_TEXTURE_CUBE_MAP) { // Check max texture size before upload int cubeSize = limits.get(Limits.CubemapSize); @@ -2065,12 +2065,12 @@ public class GLRenderer implements Renderer { if (!caps.contains(Caps.TextureArray)) { throw new RendererException("Texture arrays not supported by graphics hardware"); } - + List data = img.getData(); - + // -1 index specifies prepare data for 2D Array texUtil.uploadTexture(img, target, -1, linearizeSrgbImages); - + for (int i = 0; i < data.size(); i++) { // upload each slice of 2D array in turn // this time with the appropriate index @@ -2101,7 +2101,7 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) { // Check NPOT requirements checkNonPowerOfTwo(tex); - + updateTexImageData(image, tex.getType(), unit); } @@ -2222,7 +2222,7 @@ public class GLRenderer implements Renderer { //statistics.onVertexBufferUse(vb, false); } } - + int usage = convertUsage(vb.getUsage()); vb.getData().rewind(); @@ -2311,7 +2311,7 @@ public class GLRenderer implements Renderer { if (context.boundShaderProgram <= 0) { throw new IllegalStateException("Cannot render mesh without shader bound"); } - + Attribute attrib = context.boundShader.getAttribute(vb.getBufferType()); int loc = attrib.getLocation(); if (loc == -1) { @@ -2441,7 +2441,7 @@ public class GLRenderer implements Renderer { // What is this? throw new RendererException("Unexpected format for index buffer: " + indexBuf.getFormat()); } - + if (indexBuf.isUpdateNeeded()) { updateBufferData(indexBuf); } @@ -2556,7 +2556,7 @@ public class GLRenderer implements Renderer { if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); } - + if (instanceData != null) { setVertexAttrib(instanceData, null); } @@ -2606,11 +2606,11 @@ public class GLRenderer implements Renderer { } private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - + // Here while count is still passed in. Can be removed when/if // the method is collapsed again. -pspeed count = Math.max(mesh.getInstanceCount(), count); - + VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); @@ -2628,7 +2628,7 @@ public class GLRenderer implements Renderer { setVertexAttrib(vb, null); } } - + for (VertexBuffer vb : mesh.getBufferList().getArray()) { if (vb.getBufferType() == Type.InterleavedData || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers @@ -2696,12 +2696,12 @@ public class GLRenderer implements Renderer { // Gamma correction if (!caps.contains(Caps.Srgb)) { // Not supported, sorry. - logger.warning("sRGB framebuffer is not supported " + - "by video hardware, but was requested."); - + logger.warning("sRGB framebuffer is not supported " + + "by video hardware, but was requested."); + return; } - + setFrameBuffer(null); if (enableSrgb) { diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java index 9207c56aa..222c57af4 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java @@ -38,6 +38,7 @@ 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 { @@ -141,6 +142,18 @@ public class ShaderKey extends AssetKey { this.usesShaderNodes = usesShaderNodes; } + public Set 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); diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 727072e86..7ac4dd69f 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -49,6 +49,7 @@ 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; @@ -59,7 +60,7 @@ import java.util.logging.Logger; public class J3MLoader implements AssetLoader { private static final Logger logger = Logger.getLogger(J3MLoader.class.getName()); - // private ErrorLogger errors; + // private ErrorLogger errors; private ShaderNodeLoaderDelegate nodesLoaderDelegate; boolean isUseNodes = false; @@ -71,14 +72,14 @@ public class J3MLoader implements AssetLoader { private TechniqueDef technique; private RenderState renderState; - private EnumMap shaderLanguage; - private EnumMap shaderName; + private EnumMap shaderLanguage; + private EnumMap shaderName; private static final String whitespacePattern = "\\p{javaWhitespace}+"; - public J3MLoader(){ - shaderLanguage=new EnumMap(Shader.ShaderType.class); - shaderName=new EnumMap(Shader.ShaderType.class); + public J3MLoader() { + shaderLanguage = new EnumMap(Shader.ShaderType.class); + shaderName = new EnumMap(Shader.ShaderType.class); } @@ -94,21 +95,21 @@ public class J3MLoader implements AssetLoader { } for (Shader.ShaderType shaderType : Shader.ShaderType.values()) { - if(typeAndLang[0].equals(shaderType.toString()+"Shader")){ - readShaderDefinition(shaderType,split[1].trim(),typeAndLang[1]); + 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); + private void readShaderDefinition(Shader.ShaderType shaderType, String name, String language) { + shaderName.put(shaderType, name); + shaderLanguage.put(shaderType, language); } // LightMode - private void readLightMode(String statement) throws IOException{ + private void readLightMode(String statement) throws IOException { String[] split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("LightMode statement syntax incorrect"); } LightMode lm = LightMode.valueOf(split[1]); @@ -116,29 +117,29 @@ public class J3MLoader implements AssetLoader { } // ShadowMode - private void readShadowMode(String statement) throws IOException{ + private void readShadowMode(String statement) throws IOException { String[] split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("ShadowMode statement syntax incorrect"); } ShadowMode sm = ShadowMode.valueOf(split[1]); technique.setShadowMode(sm); } - private Object readValue(VarType type, String value) throws IOException{ - if (type.isTextureType()){ + private Object readValue(VarType type, String value) throws IOException { + if (type.isTextureType()) { // String texturePath = readString("[\n;(//)(\\})]"); String texturePath = value.trim(); boolean flipY = false; boolean repeat = false; - if (texturePath.startsWith("Flip Repeat ")){ + if (texturePath.startsWith("Flip Repeat ")) { texturePath = texturePath.substring(12).trim(); flipY = true; repeat = true; - }else if (texturePath.startsWith("Flip ")){ + } else if (texturePath.startsWith("Flip ")) { texturePath = texturePath.substring(5).trim(); flipY = true; - }else if (texturePath.startsWith("Repeat ")){ + } else if (texturePath.startsWith("Repeat ")) { texturePath = texturePath.substring(7).trim(); repeat = true; } @@ -160,76 +161,76 @@ public class J3MLoader implements AssetLoader { Texture tex; try { tex = assetManager.loadTexture(texKey); - } catch (AssetNotFoundException ex){ + } catch (AssetNotFoundException ex) { logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[]{texKey, key}); tex = null; } - if (tex != null){ - if (repeat){ + if (tex != null) { + if (repeat) { tex.setWrap(WrapMode.Repeat); } - }else{ + } else { tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); - if (repeat){ + if (repeat) { tex.setWrap(WrapMode.Repeat); } tex.setKey(texKey); } return tex; - }else{ + } else { String[] split = value.trim().split(whitespacePattern); - switch (type){ + switch (type) { case Float: - if (split.length != 1){ + if (split.length != 1) { throw new IOException("Float value parameter must have 1 entry: " + value); } - return Float.parseFloat(split[0]); + return Float.parseFloat(split[0]); case Vector2: - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Vector2 value parameter must have 2 entries: " + value); } return new Vector2f(Float.parseFloat(split[0]), - Float.parseFloat(split[1])); + Float.parseFloat(split[1])); case Vector3: - if (split.length != 3){ + if (split.length != 3) { throw new IOException("Vector3 value parameter must have 3 entries: " + value); } return new Vector3f(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2])); + Float.parseFloat(split[1]), + Float.parseFloat(split[2])); case Vector4: - if (split.length != 4){ + if (split.length != 4) { throw new IOException("Vector4 value parameter must have 4 entries: " + value); } return new ColorRGBA(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2]), - Float.parseFloat(split[3])); + Float.parseFloat(split[1]), + Float.parseFloat(split[2]), + Float.parseFloat(split[3])); case Int: - if (split.length != 1){ + if (split.length != 1) { throw new IOException("Int value parameter must have 1 entry: " + value); } return Integer.parseInt(split[0]); case Boolean: - if (split.length != 1){ + if (split.length != 1) { throw new IOException("Boolean value parameter must have 1 entry: " + value); } return Boolean.parseBoolean(split[0]); default: - throw new UnsupportedOperationException("Unknown type: "+type); + throw new UnsupportedOperationException("Unknown type: " + type); } } } // [ "(" ")" ] [ ":" ] [-LINEAR] - private void readParam(String statement) throws IOException{ + private void readParam(String statement) throws IOException { String name; String defaultVal = null; ColorSpace colorSpace = null; String[] split = statement.split("-"); - if(split.length>1){ - if(split[1].equalsIgnoreCase("LINEAR")){ + if (split.length > 1) { + if (split[1].equalsIgnoreCase("LINEAR")) { colorSpace = ColorSpace.Linear; } statement = split[0].trim(); @@ -238,10 +239,10 @@ public class J3MLoader implements AssetLoader { split = statement.split(":"); // Parse default val - if (split.length == 1){ + if (split.length == 1) { // Doesn't contain default value - }else{ - if (split.length != 2){ + } else { + if (split.length != 2) { throw new IOException("Parameter statement syntax incorrect"); } statement = split[0].trim(); @@ -250,137 +251,137 @@ public class J3MLoader implements AssetLoader { // Parse ffbinding int startParen = statement.indexOf("("); - if (startParen != -1){ + if (startParen != -1) { // get content inside parentheses int endParen = statement.indexOf(")", startParen); - String bindingStr = statement.substring(startParen+1, endParen).trim(); + String bindingStr = statement.substring(startParen + 1, endParen).trim(); // don't care about bindingStr statement = statement.substring(0, startParen); } // Parse type + name split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Parameter statement syntax incorrect"); } VarType type; - if (split[0].equals("Color")){ + if (split[0].equals("Color")) { type = VarType.Vector4; - }else{ + } else { type = VarType.valueOf(split[0]); } name = split[1]; Object defaultValObj = null; - if (defaultVal != null){ + if (defaultVal != null) { defaultValObj = readValue(type, defaultVal); } - if(type.isTextureType()){ + if (type.isTextureType()) { materialDef.addMaterialParamTexture(type, name, colorSpace); - }else{ + } else { materialDef.addMaterialParam(type, name, defaultValObj); } } - private void readValueParam(String statement) throws IOException{ + private void readValueParam(String statement) throws IOException { // Use limit=1 incase filename contains colons String[] split = statement.split(":", 2); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Value parameter statement syntax incorrect"); } String name = split[0].trim(); // parse value MatParam p = material.getMaterialDef().getMaterialParam(name); - if (p == null){ - throw new IOException("The material parameter: "+name+" is undefined."); + if (p == null) { + throw new IOException("The material parameter: " + name + " is undefined."); } Object valueObj = readValue(p.getVarType(), split[1]); - if (p.getVarType().isTextureType()){ + if (p.getVarType().isTextureType()) { material.setTextureParam(name, p.getVarType(), (Texture) valueObj); - }else{ + } else { material.setParam(name, p.getVarType(), valueObj); } } - private void readMaterialParams(List paramsList) throws IOException{ - for (Statement statement : paramsList){ + private void readMaterialParams(List paramsList) throws IOException { + for (Statement statement : paramsList) { readParam(statement.getLine()); } } - private void readExtendingMaterialParams(List paramsList) throws IOException{ - for (Statement statement : paramsList){ + private void readExtendingMaterialParams(List paramsList) throws IOException { + for (Statement statement : paramsList) { readValueParam(statement.getLine()); } } - private void readWorldParams(List worldParams) throws IOException{ - for (Statement statement : worldParams){ + private void readWorldParams(List worldParams) throws IOException { + for (Statement statement : worldParams) { technique.addWorldParam(statement.getLine()); } } - private boolean parseBoolean(String word){ + private boolean parseBoolean(String word) { return word != null && word.equals("On"); } - private void readRenderStateStatement(Statement statement) throws IOException{ + private void readRenderStateStatement(Statement statement) throws IOException { String[] split = statement.getLine().split(whitespacePattern); - if (split[0].equals("Wireframe")){ + if (split[0].equals("Wireframe")) { renderState.setWireframe(parseBoolean(split[1])); - }else if (split[0].equals("FaceCull")){ + } else if (split[0].equals("FaceCull")) { renderState.setFaceCullMode(FaceCullMode.valueOf(split[1])); - }else if (split[0].equals("DepthWrite")){ + } else if (split[0].equals("DepthWrite")) { renderState.setDepthWrite(parseBoolean(split[1])); - }else if (split[0].equals("DepthTest")){ + } else if (split[0].equals("DepthTest")) { renderState.setDepthTest(parseBoolean(split[1])); - }else if (split[0].equals("Blend")){ + } else if (split[0].equals("Blend")) { renderState.setBlendMode(BlendMode.valueOf(split[1])); - }else if (split[0].equals("AlphaTestFalloff")){ + } else if (split[0].equals("AlphaTestFalloff")) { renderState.setAlphaTest(true); renderState.setAlphaFallOff(Float.parseFloat(split[1])); - }else if (split[0].equals("PolyOffset")){ + } else if (split[0].equals("PolyOffset")) { float factor = Float.parseFloat(split[1]); float units = Float.parseFloat(split[2]); renderState.setPolyOffset(factor, units); - }else if (split[0].equals("ColorWrite")){ + } else if (split[0].equals("ColorWrite")) { renderState.setColorWrite(parseBoolean(split[1])); - }else if (split[0].equals("PointSprite")){ + } else if (split[0].equals("PointSprite")) { renderState.setPointSprite(parseBoolean(split[1])); - }else if (split[0].equals("DepthFunc")){ + } else if (split[0].equals("DepthFunc")) { renderState.setDepthFunc(RenderState.TestFunction.valueOf(split[1])); - }else if (split[0].equals("AlphaFunc")){ + } else if (split[0].equals("AlphaFunc")) { renderState.setAlphaFunc(RenderState.TestFunction.valueOf(split[1])); } else { throw new MatParseException(null, split[0], statement); } } - private void readAdditionalRenderState(List renderStates) throws IOException{ + private void readAdditionalRenderState(List renderStates) throws IOException { renderState = material.getAdditionalRenderState(); - for (Statement statement : renderStates){ + for (Statement statement : renderStates) { readRenderStateStatement(statement); } renderState = null; } - private void readRenderState(List renderStates) throws IOException{ + private void readRenderState(List renderStates) throws IOException { renderState = new RenderState(); - for (Statement statement : renderStates){ + for (Statement statement : renderStates) { readRenderStateStatement(statement); } technique.setRenderState(renderState); renderState = null; } - private void readForcedRenderState(List renderStates) throws IOException{ + private void readForcedRenderState(List renderStates) throws IOException { renderState = new RenderState(); - for (Statement statement : renderStates){ + for (Statement statement : renderStates) { readRenderStateStatement(statement); } technique.setForcedRenderState(renderState); @@ -388,41 +389,44 @@ public class J3MLoader implements AssetLoader { } // [ ":" ] - private void readDefine(String statement) throws IOException{ + private void readDefine(String statement) throws IOException { String[] split = statement.split(":"); - if (split.length == 1){ + if (split.length == 1) { // add preset define technique.addShaderPresetDefine(split[0].trim(), VarType.Boolean, true); - }else if (split.length == 2){ + } else if (split.length == 2) { technique.addShaderParamDefine(split[1].trim(), split[0].trim()); - }else{ + } else { throw new IOException("Define syntax incorrect"); } } - private void readDefines(List defineList) throws IOException{ - for (Statement statement : defineList){ + private void readDefines(List defineList) throws IOException { + for (Statement statement : defineList) { readDefine(statement.getLine()); } } - private void readTechniqueStatement(Statement statement) throws IOException{ + 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("TesselationControlShader") || + split[0].equals("TesselationEvaluationShader")) { readShaderStatement(statement.getLine()); - }else if (split[0].equals("LightMode")){ + } else if (split[0].equals("LightMode")) { readLightMode(statement.getLine()); - }else if (split[0].equals("ShadowMode")){ + } else if (split[0].equals("ShadowMode")) { readShadowMode(statement.getLine()); - }else if (split[0].equals("WorldParameters")){ + } else if (split[0].equals("WorldParameters")) { readWorldParams(statement.getContents()); - }else if (split[0].equals("RenderState")){ + } else if (split[0].equals("RenderState")) { readRenderState(statement.getContents()); - }else if (split[0].equals("ForcedRenderState")){ + } else if (split[0].equals("ForcedRenderState")) { readForcedRenderState(statement.getContents()); - }else if (split[0].equals("Defines")){ + } else if (split[0].equals("Defines")) { readDefines(statement.getContents()); } else if (split[0].equals("ShaderNodesDefinitions")) { initNodesLoader(); @@ -444,15 +448,15 @@ public class J3MLoader implements AssetLoader { } } - private void readTransparentStatement(String statement) throws IOException{ + private void readTransparentStatement(String statement) throws IOException { String[] split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Transparent statement syntax incorrect"); } material.setTransparent(parseBoolean(split[1])); } - private void readTechnique(Statement techStat) throws IOException{ + private void readTechnique(Statement techStat) throws IOException { isUseNodes = false; String[] split = techStat.getLine().split(whitespacePattern); if (split.length == 1) { @@ -464,18 +468,18 @@ public class J3MLoader implements AssetLoader { throw new IOException("Technique statement syntax incorrect"); } - for (Statement statement : techStat.getContents()){ + for (Statement statement : techStat.getContents()) { readTechniqueStatement(statement); } - if(isUseNodes){ + if (isUseNodes) { nodesLoaderDelegate.computeConditions(); //used for caching later, the shader here is not a file. technique.setShaderFile(technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100"); } - if(shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)){ - technique.setShaderFile(shaderName,shaderLanguage); + if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) { + technique.setShaderFile(shaderName, shaderLanguage); } materialDef.addTechniqueDef(technique); @@ -484,40 +488,40 @@ public class J3MLoader implements AssetLoader { shaderName.clear(); } - private void loadFromRoot(List roots) throws IOException{ - if (roots.size() == 2){ + private void loadFromRoot(List roots) throws IOException { + if (roots.size() == 2) { Statement exception = roots.get(0); String line = exception.getLine(); - if (line.startsWith("Exception")){ + if (line.startsWith("Exception")) { throw new AssetLoadException(line.substring("Exception ".length())); - }else{ + } else { throw new IOException("In multiroot material, expected first statement to be 'Exception'"); } - }else if (roots.size() != 1){ + } else if (roots.size() != 1) { throw new IOException("Too many roots in J3M/J3MD file"); } boolean extending = false; Statement materialStat = roots.get(0); String materialName = materialStat.getLine(); - if (materialName.startsWith("MaterialDef")){ + if (materialName.startsWith("MaterialDef")) { materialName = materialName.substring("MaterialDef ".length()).trim(); extending = false; - }else if (materialName.startsWith("Material")){ + } else if (materialName.startsWith("Material")) { materialName = materialName.substring("Material ".length()).trim(); extending = true; - }else{ + } else { throw new IOException("Specified file is not a Material file"); } String[] split = materialName.split(":", 2); - if (materialName.equals("")){ + if (materialName.equals("")) { throw new MatParseException("Material name cannot be empty", materialStat); } - if (split.length == 2){ - if (!extending){ + if (split.length == 2) { + if (!extending) { throw new MatParseException("Must use 'Material' when extending.", materialStat); } @@ -531,35 +535,35 @@ public class J3MLoader implements AssetLoader { material = new Material(def); material.setKey(key); // material.setAssetName(fileName); - }else if (split.length == 1){ - if (extending){ + } else if (split.length == 1) { + if (extending) { throw new MatParseException("Expected ':', got '{'", materialStat); } materialDef = new MaterialDef(assetManager, materialName); // NOTE: pass file name for defs so they can be loaded later materialDef.setAssetName(key.getName()); - }else{ + } else { throw new MatParseException("Cannot use colon in material name/path", materialStat); } - for (Statement statement : materialStat.getContents()){ + for (Statement statement : materialStat.getContents()) { split = statement.getLine().split("[ \\{]"); String statType = split[0]; - if (extending){ - if (statType.equals("MaterialParameters")){ + if (extending) { + if (statType.equals("MaterialParameters")) { readExtendingMaterialParams(statement.getContents()); - }else if (statType.equals("AdditionalRenderState")){ + } else if (statType.equals("AdditionalRenderState")) { readAdditionalRenderState(statement.getContents()); - }else if (statType.equals("Transparent")){ + } else if (statType.equals("Transparent")) { readTransparentStatement(statement.getLine()); } - }else{ - if (statType.equals("Technique")){ + } else { + if (statType.equals("Technique")) { readTechnique(statement); - }else if (statType.equals("MaterialParameters")){ + } else if (statType.equals("MaterialParameters")) { readMaterialParams(statement.getContents()); - }else{ - throw new MatParseException("Expected material statement, got '"+statType+"'", statement); + } else { + throw new MatParseException("Expected material statement, got '" + statType + "'", statement); } } } @@ -573,18 +577,18 @@ public class J3MLoader implements AssetLoader { key = info.getKey(); loadFromRoot(BlockLanguageParser.parse(in)); } finally { - if (in != null){ + if (in != null) { in.close(); } } - if (material != null){ - if (!(info.getKey() instanceof MaterialKey)){ + if (material != null) { + if (!(info.getKey() instanceof MaterialKey)) { throw new IOException("Material instances must be loaded via MaterialKey"); } // material implementation return material; - }else{ + } else { // material definition return materialDef; } @@ -601,9 +605,9 @@ public class J3MLoader implements AssetLoader { if (!isUseNodes) { isUseNodes = shaderName.get(Shader.ShaderType.Vertex) == null && shaderName.get(Shader.ShaderType.Fragment) == null; if (isUseNodes) { - if(nodesLoaderDelegate == null){ + if (nodesLoaderDelegate == null) { nodesLoaderDelegate = new ShaderNodeLoaderDelegate(); - }else{ + } else { nodesLoaderDelegate.clear(); } nodesLoaderDelegate.setTechniqueDef(technique); diff --git a/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.frag b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.frag new file mode 100644 index 000000000..636af0c7e --- /dev/null +++ b/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); +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.geom b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.geom new file mode 100644 index 000000000..e0c5d7b9e --- /dev/null +++ b/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(); +} + diff --git a/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m new file mode 100644 index 000000000..25ac6a523 --- /dev/null +++ b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3m @@ -0,0 +1,4 @@ +Material Pong Rock : Materials/Geom/SimpleGeom.j3md { + MaterialParameters { + } +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3md b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.j3md new file mode 100644 index 000000000..4ae79e3ed --- /dev/null +++ b/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 + } + } + +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert new file mode 100644 index 000000000..f82ebb79b --- /dev/null +++ b/jme3-testdata/src/main/resources/Materials/Geom/SimpleGeom.vert @@ -0,0 +1,5 @@ +attribute vec3 inPosition; + +void main(){ + gl_Position=vec4(inPosition,1); +} \ No newline at end of file From cae4e1996aeb29c8975874a4ce16cfcbeaef7f1e Mon Sep 17 00:00:00 2001 From: michael Date: Tue, 24 Feb 2015 21:53:08 +0100 Subject: [PATCH 10/34] GL4ShaderSupport --- .../jme3test/material/TestGeometryShader.java | 43 +++++++++++ .../jme3test/material/TestTesselation.java | 73 +++++++++++++++++++ 2 files changed, 116 insertions(+) create mode 100644 jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java create mode 100644 jme3-examples/src/main/java/jme3test/material/TestTesselation.java diff --git a/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java b/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java new file mode 100644 index 000000000..6ccedd1c3 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java @@ -0,0 +1,43 @@ +package jme3test.material; + +import com.jme3.app.SimpleApplication; +import com.jme3.bounding.BoundingBox; +import com.jme3.material.Material; +import com.jme3.material.RenderState; +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/SimpleGeom.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(); + } +} diff --git a/jme3-examples/src/main/java/jme3test/material/TestTesselation.java b/jme3-examples/src/main/java/jme3test/material/TestTesselation.java new file mode 100644 index 000000000..231eb5c41 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/material/TestTesselation.java @@ -0,0 +1,73 @@ +package jme3test.material; + +import com.jme3.app.SimpleApplication; +import com.jme3.light.DirectionalLight; +import com.jme3.material.Material; +import com.jme3.math.*; +import com.jme3.scene.Geometry; +import com.jme3.scene.Node; +import com.jme3.scene.shape.Quad; +import com.jme3.texture.Texture; +import com.jme3.util.SkyFactory; +import com.jme3.util.TangentBinormalGenerator; + + +/** + * Created by michael on 23.02.15. + */ +public class TestTesselation extends SimpleApplication { + private Vector3f lightDir = new Vector3f(-1, -1, .5f).normalizeLocal(); + DirectionalLight dl; + + public void setupSkyBox() { + rootNode.attachChild(SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false)); + } + + + public void setupLighting() { + + dl = new DirectionalLight(); + dl.setDirection(lightDir); + dl.setColor(new ColorRGBA(.9f, .9f, .9f, 1)); + rootNode.addLight(dl); + } + + void setupParallax() { + Material mat; + mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall2.j3m"); + mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(Texture.WrapMode.Repeat); + mat.getTextureParam("NormalMap").getTextureValue().setWrap(Texture.WrapMode.Repeat); + + // Node floorGeom = (Node) assetManager.loadAsset("Models/WaterTest/WaterTest.mesh.xml"); + //Geometry g = ((Geometry) floorGeom.getChild(0)); + //g.getMesh().scaleTextureCoordinates(new Vector2f(10, 10)); + + Node floorGeom = new Node("floorGeom"); + Quad q = new Quad(100, 100); + q.scaleTextureCoordinates(new Vector2f(1, 1)); + Geometry g = new Geometry("geom", q); + g.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X)); + floorGeom.attachChild(g); + + + TangentBinormalGenerator.generate(floorGeom); + floorGeom.setLocalTranslation(-50, 22, 60); + //floorGeom.setLocalScale(100); + + floorGeom.setMaterial(mat); + rootNode.attachChild(floorGeom); + } + + @Override + public void simpleInitApp() { + setupLighting(); + setupParallax(); + cam.setLocation(new Vector3f(-15.445636f, 30.162927f, 60.252777f)); + cam.setRotation(new Quaternion(0.05173137f, 0.92363626f, -0.13454558f, 0.35513034f)); + } + + public static void main(String[] args){ + TestTesselation app = new TestTesselation(); + app.start(); + } +} From ea4ff8bbf87810872d71a3b0314ca478a44ac42f Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 10:26:21 +0100 Subject: [PATCH 11/34] GL4ShaderSupport --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 09d505187..b41ba3b64 100644 --- a/.gitignore +++ b/.gitignore @@ -131,3 +131,5 @@ !/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib !/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so !/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so +*.iml +/.idea/* From 9e74c4e2bb33e554012a305d1bf062d3bc863fa1 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 10:38:17 +0100 Subject: [PATCH 12/34] *reverted J3MLoader --- .../com/jme3/material/plugins/J3MLoader.java | 382 +++++++++--------- 1 file changed, 195 insertions(+), 187 deletions(-) diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 23310f12f..609245e8d 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/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; @@ -57,10 +60,10 @@ import java.util.logging.Logger; public class J3MLoader implements AssetLoader { private static final Logger logger = Logger.getLogger(J3MLoader.class.getName()); - // private ErrorLogger errors; + // private ErrorLogger errors; private ShaderNodeLoaderDelegate nodesLoaderDelegate; boolean isUseNodes = false; - + private AssetManager assetManager; private AssetKey key; @@ -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 shaderLanguage; + private EnumMap shaderName; + private static final String whitespacePattern = "\\p{javaWhitespace}+"; - public J3MLoader(){ + public J3MLoader() { + shaderLanguage = new EnumMap(Shader.ShaderType.class); + shaderName = new EnumMap(Shader.ShaderType.class); } @@ -91,20 +93,25 @@ 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) { + System.out.println(shaderType); + System.out.println(name); + shaderName.put(shaderType, name); + shaderLanguage.put(shaderType, language); + } + // LightMode - private void readLightMode(String statement) throws IOException{ + private void readLightMode(String statement) throws IOException { String[] split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("LightMode statement syntax incorrect"); } LightMode lm = LightMode.valueOf(split[1]); @@ -112,29 +119,29 @@ public class J3MLoader implements AssetLoader { } // ShadowMode - private void readShadowMode(String statement) throws IOException{ + private void readShadowMode(String statement) throws IOException { String[] split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("ShadowMode statement syntax incorrect"); } ShadowMode sm = ShadowMode.valueOf(split[1]); technique.setShadowMode(sm); } - private Object readValue(VarType type, String value) throws IOException{ - if (type.isTextureType()){ + private Object readValue(VarType type, String value) throws IOException { + if (type.isTextureType()) { // String texturePath = readString("[\n;(//)(\\})]"); String texturePath = value.trim(); boolean flipY = false; boolean repeat = false; - if (texturePath.startsWith("Flip Repeat ")){ + if (texturePath.startsWith("Flip Repeat ")) { texturePath = texturePath.substring(12).trim(); flipY = true; repeat = true; - }else if (texturePath.startsWith("Flip ")){ + } else if (texturePath.startsWith("Flip ")) { texturePath = texturePath.substring(5).trim(); flipY = true; - }else if (texturePath.startsWith("Repeat ")){ + } else if (texturePath.startsWith("Repeat ")) { texturePath = texturePath.substring(7).trim(); repeat = true; } @@ -156,270 +163,273 @@ public class J3MLoader implements AssetLoader { Texture tex; try { tex = assetManager.loadTexture(texKey); - } catch (AssetNotFoundException ex){ + } catch (AssetNotFoundException ex) { logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[]{texKey, key}); tex = null; } - if (tex != null){ - if (repeat){ + if (tex != null) { + if (repeat) { tex.setWrap(WrapMode.Repeat); - } - }else{ + } + } else { tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); - if (repeat){ + if (repeat) { tex.setWrap(WrapMode.Repeat); } tex.setKey(texKey); - } + } return tex; - }else{ + } else { String[] split = value.trim().split(whitespacePattern); - switch (type){ + switch (type) { case Float: - if (split.length != 1){ + if (split.length != 1) { throw new IOException("Float value parameter must have 1 entry: " + value); } - return Float.parseFloat(split[0]); + return Float.parseFloat(split[0]); case Vector2: - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Vector2 value parameter must have 2 entries: " + value); } return new Vector2f(Float.parseFloat(split[0]), - Float.parseFloat(split[1])); + Float.parseFloat(split[1])); case Vector3: - if (split.length != 3){ + if (split.length != 3) { throw new IOException("Vector3 value parameter must have 3 entries: " + value); } return new Vector3f(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2])); + Float.parseFloat(split[1]), + Float.parseFloat(split[2])); case Vector4: - if (split.length != 4){ + if (split.length != 4) { throw new IOException("Vector4 value parameter must have 4 entries: " + value); } return new ColorRGBA(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2]), - Float.parseFloat(split[3])); + Float.parseFloat(split[1]), + Float.parseFloat(split[2]), + Float.parseFloat(split[3])); case Int: - if (split.length != 1){ + if (split.length != 1) { throw new IOException("Int value parameter must have 1 entry: " + value); } return Integer.parseInt(split[0]); case Boolean: - if (split.length != 1){ + if (split.length != 1) { throw new IOException("Boolean value parameter must have 1 entry: " + value); } return Boolean.parseBoolean(split[0]); default: - throw new UnsupportedOperationException("Unknown type: "+type); + throw new UnsupportedOperationException("Unknown type: " + type); } } } - + // [ "(" ")" ] [ ":" ] [-LINEAR] - private void readParam(String statement) throws IOException{ + private void readParam(String statement) throws IOException { String name; String defaultVal = null; ColorSpace colorSpace = null; - + String[] split = statement.split("-"); - if(split.length>1){ - if(split[1].equalsIgnoreCase("LINEAR")){ + if (split.length > 1) { + if (split[1].equalsIgnoreCase("LINEAR")) { colorSpace = ColorSpace.Linear; } statement = split[0].trim(); } - + split = statement.split(":"); - + // Parse default val - if (split.length == 1){ + if (split.length == 1) { // Doesn't contain default value - }else{ - if (split.length != 2){ + } else { + if (split.length != 2) { throw new IOException("Parameter statement syntax incorrect"); } statement = split[0].trim(); - defaultVal = split[1].trim(); + defaultVal = split[1].trim(); } - + // Parse ffbinding int startParen = statement.indexOf("("); - if (startParen != -1){ + if (startParen != -1) { // get content inside parentheses int endParen = statement.indexOf(")", startParen); - String bindingStr = statement.substring(startParen+1, endParen).trim(); + String bindingStr = statement.substring(startParen + 1, endParen).trim(); // don't care about bindingStr statement = statement.substring(0, startParen); } - + // Parse type + name split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Parameter statement syntax incorrect"); } - + VarType type; - if (split[0].equals("Color")){ + if (split[0].equals("Color")) { type = VarType.Vector4; - }else{ + } else { type = VarType.valueOf(split[0]); } - + name = split[1]; - + Object defaultValObj = null; - if (defaultVal != null){ + if (defaultVal != null) { defaultValObj = readValue(type, defaultVal); } - if(type.isTextureType()){ - materialDef.addMaterialParamTexture(type, name, colorSpace); - }else{ + if (type.isTextureType()) { + materialDef.addMaterialParamTexture(type, name, colorSpace); + } else { materialDef.addMaterialParam(type, name, defaultValObj); } - + } - private void readValueParam(String statement) throws IOException{ + private void readValueParam(String statement) throws IOException { // Use limit=1 incase filename contains colons String[] split = statement.split(":", 2); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Value parameter statement syntax incorrect"); } String name = split[0].trim(); // parse value MatParam p = material.getMaterialDef().getMaterialParam(name); - if (p == null){ - throw new IOException("The material parameter: "+name+" is undefined."); + if (p == null) { + throw new IOException("The material parameter: " + name + " is undefined."); } Object valueObj = readValue(p.getVarType(), split[1]); - if (p.getVarType().isTextureType()){ + if (p.getVarType().isTextureType()) { material.setTextureParam(name, p.getVarType(), (Texture) valueObj); - }else{ + } else { material.setParam(name, p.getVarType(), valueObj); } } - private void readMaterialParams(List paramsList) throws IOException{ - for (Statement statement : paramsList){ + private void readMaterialParams(List paramsList) throws IOException { + for (Statement statement : paramsList) { readParam(statement.getLine()); } } - private void readExtendingMaterialParams(List paramsList) throws IOException{ - for (Statement statement : paramsList){ + private void readExtendingMaterialParams(List paramsList) throws IOException { + for (Statement statement : paramsList) { readValueParam(statement.getLine()); } } - private void readWorldParams(List worldParams) throws IOException{ - for (Statement statement : worldParams){ + private void readWorldParams(List worldParams) throws IOException { + for (Statement statement : worldParams) { technique.addWorldParam(statement.getLine()); } } - private boolean parseBoolean(String word){ + private boolean parseBoolean(String word) { return word != null && word.equals("On"); } - private void readRenderStateStatement(Statement statement) throws IOException{ + private void readRenderStateStatement(Statement statement) throws IOException { String[] split = statement.getLine().split(whitespacePattern); - if (split[0].equals("Wireframe")){ + if (split[0].equals("Wireframe")) { renderState.setWireframe(parseBoolean(split[1])); - }else if (split[0].equals("FaceCull")){ + } else if (split[0].equals("FaceCull")) { renderState.setFaceCullMode(FaceCullMode.valueOf(split[1])); - }else if (split[0].equals("DepthWrite")){ + } else if (split[0].equals("DepthWrite")) { renderState.setDepthWrite(parseBoolean(split[1])); - }else if (split[0].equals("DepthTest")){ + } else if (split[0].equals("DepthTest")) { renderState.setDepthTest(parseBoolean(split[1])); - }else if (split[0].equals("Blend")){ + } else if (split[0].equals("Blend")) { renderState.setBlendMode(BlendMode.valueOf(split[1])); - }else if (split[0].equals("AlphaTestFalloff")){ + } else if (split[0].equals("AlphaTestFalloff")) { renderState.setAlphaTest(true); renderState.setAlphaFallOff(Float.parseFloat(split[1])); - }else if (split[0].equals("PolyOffset")){ + } else if (split[0].equals("PolyOffset")) { float factor = Float.parseFloat(split[1]); float units = Float.parseFloat(split[2]); renderState.setPolyOffset(factor, units); - }else if (split[0].equals("ColorWrite")){ + } else if (split[0].equals("ColorWrite")) { renderState.setColorWrite(parseBoolean(split[1])); - }else if (split[0].equals("PointSprite")){ + } else if (split[0].equals("PointSprite")) { renderState.setPointSprite(parseBoolean(split[1])); - }else if (split[0].equals("DepthFunc")){ + } else if (split[0].equals("DepthFunc")) { renderState.setDepthFunc(RenderState.TestFunction.valueOf(split[1])); - }else if (split[0].equals("AlphaFunc")){ + } else if (split[0].equals("AlphaFunc")) { renderState.setAlphaFunc(RenderState.TestFunction.valueOf(split[1])); } else { throw new MatParseException(null, split[0], statement); } } - private void readAdditionalRenderState(List renderStates) throws IOException{ + private void readAdditionalRenderState(List renderStates) throws IOException { renderState = material.getAdditionalRenderState(); - for (Statement statement : renderStates){ + for (Statement statement : renderStates) { readRenderStateStatement(statement); } renderState = null; } - private void readRenderState(List renderStates) throws IOException{ + private void readRenderState(List renderStates) throws IOException { renderState = new RenderState(); - for (Statement statement : renderStates){ + for (Statement statement : renderStates) { readRenderStateStatement(statement); } technique.setRenderState(renderState); renderState = null; } - - private void readForcedRenderState(List renderStates) throws IOException{ + + private void readForcedRenderState(List renderStates) throws IOException { renderState = new RenderState(); - for (Statement statement : renderStates){ + for (Statement statement : renderStates) { readRenderStateStatement(statement); } technique.setForcedRenderState(renderState); renderState = null; } - + // [ ":" ] - private void readDefine(String statement) throws IOException{ + private void readDefine(String statement) throws IOException { String[] split = statement.split(":"); - if (split.length == 1){ + if (split.length == 1) { // add preset define technique.addShaderPresetDefine(split[0].trim(), VarType.Boolean, true); - }else if (split.length == 2){ + } else if (split.length == 2) { technique.addShaderParamDefine(split[1].trim(), split[0].trim()); - }else{ + } else { throw new IOException("Define syntax incorrect"); } } - private void readDefines(List defineList) throws IOException{ - for (Statement statement : defineList){ + private void readDefines(List defineList) throws IOException { + for (Statement statement : defineList) { readDefine(statement.getLine()); } } - - private void readTechniqueStatement(Statement statement) throws IOException{ - String[] split = statement.getLine().split("[ \\{]"); + + 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("TesselationControlShader") || + split[0].equals("TesselationEvaluationShader")) { readShaderStatement(statement.getLine()); - }else if (split[0].equals("LightMode")){ + } else if (split[0].equals("LightMode")) { readLightMode(statement.getLine()); - }else if (split[0].equals("ShadowMode")){ + } else if (split[0].equals("ShadowMode")) { readShadowMode(statement.getLine()); - }else if (split[0].equals("WorldParameters")){ + } else if (split[0].equals("WorldParameters")) { readWorldParams(statement.getContents()); - }else if (split[0].equals("RenderState")){ + } else if (split[0].equals("RenderState")) { readRenderState(statement.getContents()); - }else if (split[0].equals("ForcedRenderState")){ + } else if (split[0].equals("ForcedRenderState")) { readForcedRenderState(statement.getContents()); - }else if (split[0].equals("Defines")){ - readDefines(statement.getContents()); + } else if (split[0].equals("Defines")) { + readDefines(statement.getContents()); } else if (split[0].equals("ShaderNodesDefinitions")) { initNodesLoader(); if (isUseNodes) { @@ -432,23 +442,23 @@ public class J3MLoader implements AssetLoader { } } else if (split[0].equals("FragmentShaderNodes")) { initNodesLoader(); - if (isUseNodes) { + if (isUseNodes) { nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents()); } } else { throw new MatParseException(null, split[0], statement); } } - - private void readTransparentStatement(String statement) throws IOException{ + + private void readTransparentStatement(String statement) throws IOException { String[] split = statement.split(whitespacePattern); - if (split.length != 2){ + if (split.length != 2) { throw new IOException("Transparent statement syntax incorrect"); } material.setTransparent(parseBoolean(split[1])); } - private void readTechnique(Statement techStat) throws IOException{ + private void readTechnique(Statement techStat) throws IOException { isUseNodes = false; String[] split = techStat.getLine().split(whitespacePattern); if (split.length == 1) { @@ -459,64 +469,62 @@ public class J3MLoader implements AssetLoader { } else { throw new IOException("Technique statement syntax incorrect"); } - - for (Statement statement : techStat.getContents()){ + + for (Statement statement : techStat.getContents()) { readTechniqueStatement(statement); } - - if(isUseNodes){ + + if (isUseNodes) { nodesLoaderDelegate.computeConditions(); //used for caching later, the shader here is not a file. 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 roots) throws IOException{ - if (roots.size() == 2){ + private void loadFromRoot(List roots) throws IOException { + if (roots.size() == 2) { Statement exception = roots.get(0); String line = exception.getLine(); - if (line.startsWith("Exception")){ + if (line.startsWith("Exception")) { throw new AssetLoadException(line.substring("Exception ".length())); - }else{ + } else { throw new IOException("In multiroot material, expected first statement to be 'Exception'"); } - }else if (roots.size() != 1){ + } else if (roots.size() != 1) { throw new IOException("Too many roots in J3M/J3MD file"); } - + boolean extending = false; Statement materialStat = roots.get(0); String materialName = materialStat.getLine(); - if (materialName.startsWith("MaterialDef")){ + if (materialName.startsWith("MaterialDef")) { materialName = materialName.substring("MaterialDef ".length()).trim(); extending = false; - }else if (materialName.startsWith("Material")){ + } else if (materialName.startsWith("Material")) { materialName = materialName.substring("Material ".length()).trim(); extending = true; - }else{ + } else { throw new IOException("Specified file is not a Material file"); } - + String[] split = materialName.split(":", 2); - - if (materialName.equals("")){ - throw new MatParseException("Material name cannot be empty", materialStat); + + if (materialName.equals("")) { + throw new MatParseException("Material name cannot be empty", materialStat); } - if (split.length == 2){ - if (!extending){ - throw new MatParseException("Must use 'Material' when extending.", materialStat); + if (split.length == 2) { + if (!extending) { + throw new MatParseException("Must use 'Material' when extending.", materialStat); } String extendedMat = split[1].trim(); @@ -529,65 +537,65 @@ public class J3MLoader implements AssetLoader { material = new Material(def); material.setKey(key); // material.setAssetName(fileName); - }else if (split.length == 1){ - if (extending){ - throw new MatParseException("Expected ':', got '{'", materialStat); + } else if (split.length == 1) { + if (extending) { + throw new MatParseException("Expected ':', got '{'", materialStat); } materialDef = new MaterialDef(assetManager, materialName); // NOTE: pass file name for defs so they can be loaded later materialDef.setAssetName(key.getName()); - }else{ - throw new MatParseException("Cannot use colon in material name/path", materialStat); + } else { + throw new MatParseException("Cannot use colon in material name/path", materialStat); } - - for (Statement statement : materialStat.getContents()){ + + for (Statement statement : materialStat.getContents()) { split = statement.getLine().split("[ \\{]"); String statType = split[0]; - if (extending){ - if (statType.equals("MaterialParameters")){ + if (extending) { + if (statType.equals("MaterialParameters")) { readExtendingMaterialParams(statement.getContents()); - }else if (statType.equals("AdditionalRenderState")){ + } else if (statType.equals("AdditionalRenderState")) { readAdditionalRenderState(statement.getContents()); - }else if (statType.equals("Transparent")){ + } else if (statType.equals("Transparent")) { readTransparentStatement(statement.getLine()); } - }else{ - if (statType.equals("Technique")){ + } else { + if (statType.equals("Technique")) { readTechnique(statement); - }else if (statType.equals("MaterialParameters")){ + } else if (statType.equals("MaterialParameters")) { readMaterialParams(statement.getContents()); - }else{ - throw new MatParseException("Expected material statement, got '"+statType+"'", statement); + } else { + throw new MatParseException("Expected material statement, got '" + statType + "'", statement); } } } } - public Object load(AssetInfo info) throws IOException { + public Object load(AssetInfo info) throws IOException { this.assetManager = info.getManager(); - InputStream in = info.openStream(); + InputStream in = info.openStream(); try { - key = info.getKey(); + key = info.getKey(); loadFromRoot(BlockLanguageParser.parse(in)); } finally { - if (in != null){ + if (in != null) { in.close(); } } - - if (material != null){ - if (!(info.getKey() instanceof MaterialKey)){ + + if (material != null) { + if (!(info.getKey() instanceof MaterialKey)) { throw new IOException("Material instances must be loaded via MaterialKey"); } // material implementation return material; - }else{ + } else { // material definition return materialDef; } } - + public MaterialDef loadMaterialDef(List roots, AssetManager manager, AssetKey key) throws IOException { this.key = key; this.assetManager = manager; @@ -597,11 +605,11 @@ 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{ + } else { nodesLoaderDelegate.clear(); } nodesLoaderDelegate.setTechniqueDef(technique); @@ -609,6 +617,6 @@ public class J3MLoader implements AssetLoader { nodesLoaderDelegate.setAssetManager(assetManager); } } - } + } } From 6983aff1f3dc4ad4221f953e2730d566090dfe4e Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 10:55:40 +0100 Subject: [PATCH 13/34] *Reapplied -LINEAR fix from https://github.com/jMonkeyEngine/jmonkeyengine/commit/02322d04ccab5c1279e8634b76f520f4bb835aca --- .../java/com/jme3/material/plugins/J3MLoader.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 609245e8d..746a30aa8 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -230,15 +230,7 @@ public class J3MLoader implements AssetLoader { String defaultVal = null; ColorSpace colorSpace = null; - String[] split = statement.split("-"); - if (split.length > 1) { - if (split[1].equalsIgnoreCase("LINEAR")) { - colorSpace = ColorSpace.Linear; - } - statement = split[0].trim(); - } - - split = statement.split(":"); + String[] split = statement.split(":"); // Parse default val if (split.length == 1) { @@ -250,6 +242,10 @@ public class J3MLoader implements AssetLoader { statement = split[0].trim(); defaultVal = split[1].trim(); } + if (statement.endsWith("-LINEAR")) { + colorSpace = ColorSpace.Linear; + statement = statement.substring(0, statement.length() - "-LINEAR".length()); + } // Parse ffbinding int startParen = statement.indexOf("("); From 19143def9b478822b70f2edae9bc0c9c48af6aa1 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 12:54:38 +0100 Subject: [PATCH 14/34] *Modified computeNumElements to support n-Patches --- jme3-core/src/main/java/com/jme3/scene/Mesh.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index 357cee438..3f074f091 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -733,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(); } @@ -1367,6 +1369,13 @@ public class Mesh implements Savable, Cloneable { getBuffer(Type.HWBoneIndex) != null; } + /** + * Sets the count of vertics used for each tessellation patch + * @param patchVertexCount + */ + public void setPatchVertexCount(int patchVertexCount) { + this.patchVertexCount = patchVertexCount; + } public void write(JmeExporter ex) throws IOException { OutputCapsule out = ex.getCapsule(this); From dfca3d5ca0d7a3e11482381e409d992bc25c5a31 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:11:59 +0100 Subject: [PATCH 15/34] Added GL_PATCHES to convertElementMode --- .../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 4a55486f6..5a8641b7a 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -1019,9 +1019,9 @@ public class GLRenderer implements Renderer { return GL.GL_VERTEX_SHADER; case Geometry: return GL3.GL_GEOMETRY_SHADER; - case TesselationControl: + case TessellationControl: return GL4.GL_TESS_CONTROL_SHADER; - case TesselationEvaluation: + case TessellationEvaluation: return GL4.GL_TESS_EVALUATION_SHADER; default: throw new UnsupportedOperationException("Unrecognized shader type."); @@ -2534,6 +2534,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); } From 555d73b8517c98542ab63d156345e6682360993b Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:12:19 +0100 Subject: [PATCH 16/34] Added GL_PATCHES as new constant --- jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java | 1 + 1 file changed, 1 insertion(+) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java index 81adf4bfc..0539f2262 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java @@ -41,4 +41,5 @@ import java.nio.IntBuffer; 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; } From 5c70938ccfc43fbd4b6b3db6b258a23914920eb7 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:32:16 +0100 Subject: [PATCH 17/34] Added GL_PATCHES as new constant --- .../src/main/java/com/jme3/renderer/opengl/GL4.java | 1 + .../main/java/com/jme3/renderer/lwjgl/LwjglGL.java | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java index 0539f2262..9ce4e835f 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GL4.java @@ -42,4 +42,5 @@ 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); } diff --git a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java index ee2581f9a..82b8ee72b 100644 --- a/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java +++ b/jme3-lwjgl/src/main/java/com/jme3/renderer/lwjgl/LwjglGL.java @@ -11,12 +11,7 @@ import java.nio.IntBuffer; import java.nio.ShortBuffer; import com.jme3.renderer.opengl.GL4; -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; +import org.lwjgl.opengl.*; public class LwjglGL implements GL, GL2, GL3,GL4 { @@ -444,4 +439,9 @@ public class LwjglGL implements GL, GL2, GL3,GL4 { checkLimit(param1); GL30.glGenVertexArrays(param1); } + + @Override + public void glPatchParameter(int count) { + GL40.glPatchParameteri(GL40.GL_PATCH_VERTICES,count); + } } From fd78f4d896fc473de4cc04d68b0ce260be2550c1 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:38:34 +0100 Subject: [PATCH 18/34] Added renderer support for glPatchParameter --- .../src/main/java/com/jme3/renderer/opengl/GLRenderer.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 5a8641b7a..1dcd8b659 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/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); @@ -2686,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); From 58bcb39a2db31b767e32c6b17ff563e1677b6326 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:38:52 +0100 Subject: [PATCH 19/34] Added getter for patchVertexCount --- jme3-core/src/main/java/com/jme3/scene/Mesh.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/scene/Mesh.java b/jme3-core/src/main/java/com/jme3/scene/Mesh.java index 3f074f091..a0f8e1fe6 100644 --- a/jme3-core/src/main/java/com/jme3/scene/Mesh.java +++ b/jme3-core/src/main/java/com/jme3/scene/Mesh.java @@ -1370,13 +1370,21 @@ public class Mesh implements Savable, Cloneable { } /** - * Sets the count of vertics used for each tessellation patch + * 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); From 690dd7bf2803bb212c4973a10f6660c5e0464407 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:40:10 +0100 Subject: [PATCH 20/34] Added Geometry and Tessellation Shader Tests --- gradle.properties | 4 +- .../jme3test/material/TestGeometryShader.java | 3 +- .../jme3test/material/TestTesselation.java | 73 ------------------- .../material/TestTessellationShader.java | 37 ++++++++++ .../resources/Materials/Tess/SimpleTess.frag | 3 + .../resources/Materials/Tess/SimpleTess.j3m | 4 + .../resources/Materials/Tess/SimpleTess.j3md | 19 +++++ .../Materials/Tess/SimpleTess.tsctrl | 13 ++++ .../Materials/Tess/SimpleTess.tseval | 17 +++++ .../resources/Materials/Tess/SimpleTess.vert | 5 ++ 10 files changed, 101 insertions(+), 77 deletions(-) delete mode 100644 jme3-examples/src/main/java/jme3test/material/TestTesselation.java create mode 100644 jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java create mode 100644 jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.frag create mode 100644 jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m create mode 100644 jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3md create mode 100644 jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tsctrl create mode 100644 jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval create mode 100644 jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert diff --git a/gradle.properties b/gradle.properties index 4d8b56aa7..739101b20 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,10 +6,10 @@ jmeMainVersion = 3.1 jmeVersionTag = snapshot-github # specify if JavaDoc should be built -buildJavaDoc = true +buildJavaDoc = false # specify if SDK and Native libraries get built -buildSdkProject = true +buildSdkProject = false buildNativeProjects = false # Path to android NDK for building native libraries diff --git a/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java b/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java index 6ccedd1c3..04c8223f1 100644 --- a/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java +++ b/jme3-examples/src/main/java/jme3test/material/TestGeometryShader.java @@ -3,7 +3,6 @@ package jme3test.material; import com.jme3.app.SimpleApplication; import com.jme3.bounding.BoundingBox; import com.jme3.material.Material; -import com.jme3.material.RenderState; import com.jme3.math.Vector3f; import com.jme3.scene.Geometry; import com.jme3.scene.Mesh; @@ -27,7 +26,7 @@ public class TestGeometryShader extends SimpleApplication { geometry.updateGeometricState(); geometry.setMaterial(new Material(assetManager, "Materials/Geom/SimpleGeom.j3md")); //geometry.getMaterial().getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off); - //geometry.setMaterial(assetManager.loadMaterial("Materials/Geom/SimpleGeom.j3md")); + //geometry.setMaterial(assetManager.loadMaterial("Materials/Geom/SimpleTess.j3md")); rootNode.attachChild(geometry); Geometry geometry1 = new Geometry("T1", new Sphere(10, 10, 1)); diff --git a/jme3-examples/src/main/java/jme3test/material/TestTesselation.java b/jme3-examples/src/main/java/jme3test/material/TestTesselation.java deleted file mode 100644 index 231eb5c41..000000000 --- a/jme3-examples/src/main/java/jme3test/material/TestTesselation.java +++ /dev/null @@ -1,73 +0,0 @@ -package jme3test.material; - -import com.jme3.app.SimpleApplication; -import com.jme3.light.DirectionalLight; -import com.jme3.material.Material; -import com.jme3.math.*; -import com.jme3.scene.Geometry; -import com.jme3.scene.Node; -import com.jme3.scene.shape.Quad; -import com.jme3.texture.Texture; -import com.jme3.util.SkyFactory; -import com.jme3.util.TangentBinormalGenerator; - - -/** - * Created by michael on 23.02.15. - */ -public class TestTesselation extends SimpleApplication { - private Vector3f lightDir = new Vector3f(-1, -1, .5f).normalizeLocal(); - DirectionalLight dl; - - public void setupSkyBox() { - rootNode.attachChild(SkyFactory.createSky(assetManager, "Scenes/Beach/FullskiesSunset0068.dds", false)); - } - - - public void setupLighting() { - - dl = new DirectionalLight(); - dl.setDirection(lightDir); - dl.setColor(new ColorRGBA(.9f, .9f, .9f, 1)); - rootNode.addLight(dl); - } - - void setupParallax() { - Material mat; - mat = assetManager.loadMaterial("Textures/Terrain/BrickWall/BrickWall2.j3m"); - mat.getTextureParam("DiffuseMap").getTextureValue().setWrap(Texture.WrapMode.Repeat); - mat.getTextureParam("NormalMap").getTextureValue().setWrap(Texture.WrapMode.Repeat); - - // Node floorGeom = (Node) assetManager.loadAsset("Models/WaterTest/WaterTest.mesh.xml"); - //Geometry g = ((Geometry) floorGeom.getChild(0)); - //g.getMesh().scaleTextureCoordinates(new Vector2f(10, 10)); - - Node floorGeom = new Node("floorGeom"); - Quad q = new Quad(100, 100); - q.scaleTextureCoordinates(new Vector2f(1, 1)); - Geometry g = new Geometry("geom", q); - g.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X)); - floorGeom.attachChild(g); - - - TangentBinormalGenerator.generate(floorGeom); - floorGeom.setLocalTranslation(-50, 22, 60); - //floorGeom.setLocalScale(100); - - floorGeom.setMaterial(mat); - rootNode.attachChild(floorGeom); - } - - @Override - public void simpleInitApp() { - setupLighting(); - setupParallax(); - cam.setLocation(new Vector3f(-15.445636f, 30.162927f, 60.252777f)); - cam.setRotation(new Quaternion(0.05173137f, 0.92363626f, -0.13454558f, 0.35513034f)); - } - - public static void main(String[] args){ - TestTesselation app = new TestTesselation(); - app.start(); - } -} diff --git a/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java b/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java new file mode 100644 index 000000000..9d6762333 --- /dev/null +++ b/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java @@ -0,0 +1,37 @@ +package jme3test.material; + +import com.jme3.app.SimpleApplication; +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; + +/** + * Created by michael on 28.02.15. + */ +public class TestTessellationShader extends SimpleApplication { + @Override + public void simpleInitApp() { + Material material = new Material(getAssetManager(), "Materials/Tess/SimpleTess.j3md"); + material.setInt("TessellationFactor", 5); + material.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(material); + rootNode.attachChild(geometry); + + Geometry geometry1 = new Geometry("Demo", new Quad(2, 2)); + geometry1.setMaterial(new Material(getAssetManager(),"Common/MatDefs/Misc/Unshaded.j3md")); + rootNode.attachChild(geometry1); + } + + public static void main(String[] args) { + new TestTessellationShader().start(); + } +} diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.frag b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.frag new file mode 100644 index 000000000..636af0c7e --- /dev/null +++ b/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); +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m new file mode 100644 index 000000000..599a8c61c --- /dev/null +++ b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3m @@ -0,0 +1,4 @@ +Material Pong Rock : Materials/Tess/SimpleTess.j3md { + MaterialParameters { + } +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3md b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.j3md new file mode 100644 index 000000000..81813493d --- /dev/null +++ b/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 + } + } + +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tsctrl b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tsctrl new file mode 100644 index 000000000..445276e42 --- /dev/null +++ b/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); +} + diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval new file mode 100644 index 000000000..32600c6f2 --- /dev/null +++ b/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 mTessellationFactor; +void main(){ + if (gl_InvocationID == 0){ + gl_TessLevelOuter[0]=5; + gl_TessLevelOuter[1]=5; + gl_TessLevelOuter[2]=5; + gl_TessLevelOuter[3]=5; + + gl_TessLevelInner[0]=5; + gl_TessLevelInner[1]=5; + } + gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; +} \ No newline at end of file diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert new file mode 100644 index 000000000..f82ebb79b --- /dev/null +++ b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.vert @@ -0,0 +1,5 @@ +attribute vec3 inPosition; + +void main(){ + gl_Position=vec4(inPosition,1); +} \ No newline at end of file From 515b48153c5129fd0b2bc19634039545d8615c3b Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:41:52 +0100 Subject: [PATCH 21/34] Fixed Typo --- jme3-core/src/main/java/com/jme3/shader/Shader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/shader/Shader.java b/jme3-core/src/main/java/com/jme3/shader/Shader.java index 746733e78..eb084f178 100644 --- a/jme3-core/src/main/java/com/jme3/shader/Shader.java +++ b/jme3-core/src/main/java/com/jme3/shader/Shader.java @@ -78,11 +78,11 @@ public final class Shader extends NativeObject { /** * Controls tesselation factor (e.g how often a input patch should be subdivided) */ - TesselationControl, + TessellationControl, /** * Controls tesselation transform (e.g similar to the vertex shader, but required to mix inputs manual) */ - TesselationEvaluation; + TessellationEvaluation; } /** From 5c4519b4c9b833dd4fc3e80c7a5461c9c26a0577 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:42:16 +0100 Subject: [PATCH 22/34] Fixed Typo --- .../src/main/java/com/jme3/shader/ShaderKey.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java index 222c57af4..5e45985ef 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java @@ -160,13 +160,13 @@ public class ShaderKey extends AssetKey { OutputCapsule oc = ex.getCapsule(this); 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.TesselationControl), "tessControl_name", null); - oc.write(shaderName.get(Shader.ShaderType.TesselationEvaluation), "tessEval_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.TesselationControl), "tsctrl_language", null); - oc.write(shaderLanguage.get(Shader.ShaderType.TesselationEvaluation), "tseval_language", null); + oc.write(shaderLanguage.get(Shader.ShaderType.TessellationControl), "tsctrl_language", null); + oc.write(shaderLanguage.get(Shader.ShaderType.TessellationEvaluation), "tseval_language", null); } @@ -177,13 +177,13 @@ public class ShaderKey extends AssetKey { 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.TesselationControl,ic.readString("tessControl_name", null)); - shaderName.put(Shader.ShaderType.TesselationEvaluation,ic.readString("tessEval_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.TesselationControl,ic.readString("tsctrl_language", null)); - shaderLanguage.put(Shader.ShaderType.TesselationEvaluation,ic.readString("tseval_language", null)); + shaderLanguage.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrl_language", null)); + shaderLanguage.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tseval_language", null)); } } From 2c2187f3d75a229e0e26b436d67c503fabad66fc Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:42:40 +0100 Subject: [PATCH 23/34] Fixed Typo --- .../java/com/jme3/material/TechniqueDef.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index 768590725..24b789f51 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -33,7 +33,6 @@ package com.jme3.material; import com.jme3.export.*; import com.jme3.renderer.Caps; -import com.jme3.renderer.Renderer; import com.jme3.shader.*; import java.io.IOException; @@ -267,7 +266,7 @@ public class TechniqueDef implements Savable { this.shaderName.put(shaderType,shaderName.get(shaderType)); if(shaderType.equals(Shader.ShaderType.Geometry)){ requiredCaps.add(Caps.GeometryShader); - }else if(shaderType.equals(Shader.ShaderType.TesselationControl)){ + }else if(shaderType.equals(Shader.ShaderType.TessellationControl)){ requiredCaps.add(Caps.TesselationShader); } } @@ -440,13 +439,13 @@ public class TechniqueDef implements Savable { 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.TesselationControl), "tsctrlName", null); - oc.write(shaderName.get(Shader.ShaderType.TesselationEvaluation), "tsevalName", 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.TesselationControl), "tsctrlLanguage", null); - oc.write(shaderLanguage.get(Shader.ShaderType.TesselationEvaluation), "tsevalLanguage", 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); @@ -469,8 +468,8 @@ public class TechniqueDef implements Savable { 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.TesselationControl,ic.readString("tsctrlName", null)); - shaderName.put(Shader.ShaderType.TesselationEvaluation,ic.readString("tsevalName", 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); @@ -486,8 +485,8 @@ public class TechniqueDef implements Savable { 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.TesselationControl,ic.readString("tsctrlLanguage", null)); - shaderLanguage.put(Shader.ShaderType.TesselationEvaluation,ic.readString("tsevalLanguage", null)); + shaderLanguage.put(Shader.ShaderType.TessellationControl,ic.readString("tsctrlLanguage", null)); + shaderLanguage.put(Shader.ShaderType.TessellationEvaluation,ic.readString("tsevalLanguage", null)); } usesNodes = ic.readBoolean("usesNodes", false); From 273ad711bfacec3a390bfd2f87f9b857ce0aa984 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:43:07 +0100 Subject: [PATCH 24/34] Fixed Typo --- .../src/plugins/java/com/jme3/material/plugins/J3MLoader.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 746a30aa8..063151a57 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -411,8 +411,8 @@ public class J3MLoader implements AssetLoader { if (split[0].equals("VertexShader") || split[0].equals("FragmentShader") || split[0].equals("GeometryShader") || - split[0].equals("TesselationControlShader") || - split[0].equals("TesselationEvaluationShader")) { + split[0].equals("TessellationControlShader") || + split[0].equals("TessellationEvaluationShader")) { readShaderStatement(statement.getLine()); } else if (split[0].equals("LightMode")) { readLightMode(statement.getLine()); From 1cce72cd0a92d82cd289a94271a63ab8c087f67e Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:53:36 +0100 Subject: [PATCH 25/34] Allow modifing of the tess factor with keys a and y --- .../material/TestTessellationShader.java | 45 ++++++++++++++++--- .../Materials/Tess/SimpleTess.tseval | 14 +++--- 2 files changed, 45 insertions(+), 14 deletions(-) diff --git a/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java b/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java index 9d6762333..f7557ca83 100644 --- a/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java +++ b/jme3-examples/src/main/java/jme3test/material/TestTessellationShader.java @@ -1,6 +1,9 @@ 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; @@ -8,27 +11,55 @@ 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() { - Material material = new Material(getAssetManager(), "Materials/Tess/SimpleTess.j3md"); - material.setInt("TessellationFactor", 5); - material.getAdditionalRenderState().setWireframe(true); + 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(material); + geometry.setMaterial(tessellationMaterial); rootNode.attachChild(geometry); - Geometry geometry1 = new Geometry("Demo", new Quad(2, 2)); - geometry1.setMaterial(new Material(getAssetManager(),"Common/MatDefs/Misc/Unshaded.j3md")); - rootNode.attachChild(geometry1); + 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() { + @Override + public Boolean call() throws Exception { + tessellationMaterial.setInt("TessellationFactor",tessFactor); + return true; + } + }); + } + if(name.equals("TessDo")){ + tessFactor--; + enqueue(new Callable() { + @Override + public Boolean call() throws Exception { + tessellationMaterial.setInt("TessellationFactor",tessFactor); + return true; + } + }); + } + } + },"TessUp","TessDo"); } public static void main(String[] args) { diff --git a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval index 32600c6f2..3f7074642 100644 --- a/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval +++ b/jme3-testdata/src/main/resources/Materials/Tess/SimpleTess.tseval @@ -2,16 +2,16 @@ layout(vertices=4) out; out gl_PerVertex{ vec4 gl_Position; }gl_out[]; -uniform int mTessellationFactor; +uniform int m_TessellationFactor; void main(){ if (gl_InvocationID == 0){ - gl_TessLevelOuter[0]=5; - gl_TessLevelOuter[1]=5; - gl_TessLevelOuter[2]=5; - gl_TessLevelOuter[3]=5; + gl_TessLevelOuter[0]=m_TessellationFactor; + gl_TessLevelOuter[1]=m_TessellationFactor; + gl_TessLevelOuter[2]=m_TessellationFactor; + gl_TessLevelOuter[3]=m_TessellationFactor; - gl_TessLevelInner[0]=5; - gl_TessLevelInner[1]=5; + gl_TessLevelInner[0]=m_TessellationFactor; + gl_TessLevelInner[1]=m_TessellationFactor; } gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position; } \ No newline at end of file From 951a623930444e94e2978a1083eebbcee1f7593e Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:58:09 +0100 Subject: [PATCH 26/34] Fixed hashCode --- jme3-core/src/main/java/com/jme3/shader/ShaderKey.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java index 5e45985ef..721d6cdb4 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderKey.java @@ -100,6 +100,9 @@ public class ShaderKey extends AssetKey { int hash = 7; hash = 41 * hash + name.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; } From 4e8d6cc498820de6b7399c3910bc76659cec65eb Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 13:58:30 +0100 Subject: [PATCH 27/34] Added some javadoc --- .../src/main/java/com/jme3/material/TechniqueDef.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index 24b789f51..6331fb28d 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -504,12 +504,18 @@ public class TechniqueDef implements Savable { usesShaders = true; } - //todo: add javadoc + /** + * Returns the Enum containing the ShaderProgramNames; + * @return + */ public EnumMap getShaderProgramNames() { return shaderName; } - //todo: add javadoc + /** + * Returns the Enum containing the ShaderProgramLanguages; + * @return + */ public EnumMap getShaderProgramLanguages() { return shaderLanguage; } From a59f0177103249d8bf14c8223336a0f157d5b799 Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 14:02:50 +0100 Subject: [PATCH 28/34] Removed two sysouts --- .../src/plugins/java/com/jme3/material/plugins/J3MLoader.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index 063151a57..a4bf9fe9a 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -102,8 +102,6 @@ public class J3MLoader implements AssetLoader { } private void readShaderDefinition(Shader.ShaderType shaderType, String name, String language) { - System.out.println(shaderType); - System.out.println(name); shaderName.put(shaderType, name); shaderLanguage.put(shaderType, language); } From 5c1fe73530fef5701dee5aafe1acadcacce77fb2 Mon Sep 17 00:00:00 2001 From: Michael Zuegg Date: Sat, 28 Feb 2015 16:06:42 +0100 Subject: [PATCH 29/34] Update gradle.properties --- gradle.properties | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gradle.properties b/gradle.properties index 739101b20..00429d65a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,10 +6,10 @@ jmeMainVersion = 3.1 jmeVersionTag = snapshot-github # specify if JavaDoc should be built -buildJavaDoc = false +buildJavaDoc = true # specify if SDK and Native libraries get built -buildSdkProject = false +buildSdkProject = true buildNativeProjects = false # Path to android NDK for building native libraries @@ -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 \ No newline at end of file +netbeansUrl = http://download.netbeans.org/netbeans/8.0.2/final/zip/netbeans-8.0.2-201411181905-javase.zip From 4fa271582d291817af5b3d3b60277c0da7087278 Mon Sep 17 00:00:00 2001 From: Michael Zuegg Date: Sat, 28 Feb 2015 16:10:22 +0100 Subject: [PATCH 31/34] Update .gitignore --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index b41ba3b64..09d505187 100644 --- a/.gitignore +++ b/.gitignore @@ -131,5 +131,3 @@ !/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib !/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so !/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so -*.iml -/.idea/* From 99d69d1d01da9a7e99e137a9648521d3951cfaaa Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 16:45:18 +0100 Subject: [PATCH 33/34] Fixed formatting thanks to EmpirePhoenix --- .gitignore | 2 - .../com/jme3/asset/DesktopAssetManager.java | 48 +-- .../asset/cache/WeakRefCloneAssetCache.java | 84 ++--- .../java/com/jme3/material/TechniqueDef.java | 4 +- .../src/main/java/com/jme3/renderer/Caps.java | 1 + .../com/jme3/renderer/opengl/GLRenderer.java | 202 +++++------ .../com/jme3/material/plugins/J3MLoader.java | 321 +++++++++--------- 7 files changed, 330 insertions(+), 332 deletions(-) diff --git a/.gitignore b/.gitignore index b41ba3b64..09d505187 100644 --- a/.gitignore +++ b/.gitignore @@ -131,5 +131,3 @@ !/jme3-bullet-native/libs/native/osx/x86_64/libbulletjme.dylib !/jme3-bullet-native/libs/native/linux/x86/libbulletjme.so !/jme3-bullet-native/libs/native/linux/x86_64/libbulletjme.so -*.iml -/.idea/* diff --git a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java index 109ebed36..077b13a5a 100644 --- a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java +++ b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java @@ -68,12 +68,12 @@ public class DesktopAssetManager implements AssetManager { private static final Logger logger = Logger.getLogger(AssetManager.class.getName()); private ShaderGenerator shaderGenerator; - + private final ImplHandler handler = new ImplHandler(this); - private CopyOnWriteArrayList eventListeners = + private CopyOnWriteArrayList eventListeners = new CopyOnWriteArrayList(); - + private List classLoaders = Collections.synchronizedList(new ArrayList()); @@ -89,7 +89,7 @@ public class DesktopAssetManager implements AssetManager { public DesktopAssetManager(URL configFile){ if (configFile != null){ loadConfigFile(configFile); - } + } logger.fine("DesktopAssetManager created."); } @@ -109,11 +109,11 @@ public class DesktopAssetManager implements AssetManager { } } } - + public void addClassLoader(ClassLoader loader) { classLoaders.add(loader); } - + public void removeClassLoader(ClassLoader loader) { classLoaders.remove(loader); } @@ -121,7 +121,7 @@ public class DesktopAssetManager implements AssetManager { public List getClassLoaders(){ return Collections.unmodifiableList(classLoaders); } - + public void addAssetEventListener(AssetEventListener listener) { eventListeners.add(listener); } @@ -133,7 +133,7 @@ public class DesktopAssetManager implements AssetManager { public void clearAssetEventListeners() { eventListeners.clear(); } - + public void setAssetEventListener(AssetEventListener listener){ eventListeners.clear(); eventListeners.add(listener); @@ -160,7 +160,7 @@ public class DesktopAssetManager implements AssetManager { registerLoader(clazz, extensions); } } - + public void unregisterLoader(Class loaderClass) { handler.removeLoader(loaderClass); if (logger.isLoggable(Level.FINER)){ @@ -190,7 +190,7 @@ public class DesktopAssetManager implements AssetManager { registerLocator(rootPath, clazz); } } - + public void unregisterLocator(String rootPath, Class clazz){ handler.removeLocator(clazz, rootPath); if (logger.isLoggable(Level.FINER)){ @@ -198,7 +198,7 @@ public class DesktopAssetManager implements AssetManager { clazz.getSimpleName()); } } - + public AssetInfo locateAsset(AssetKey key){ AssetInfo info = handler.tryLocate(key); if (info == null){ @@ -206,7 +206,7 @@ public class DesktopAssetManager implements AssetManager { } return info; } - + public T getFromCache(AssetKey key) { AssetCache cache = handler.getCache(key.getCacheType()); if (cache != null) { @@ -220,7 +220,7 @@ public class DesktopAssetManager implements AssetManager { throw new IllegalArgumentException("Key " + key + " specifies no cache."); } } - + public void addToCache(AssetKey key, T asset) { AssetCache cache = handler.getCache(key.getCacheType()); if (cache != null) { @@ -230,7 +230,7 @@ public class DesktopAssetManager implements AssetManager { throw new IllegalArgumentException("Key " + key + " specifies no cache."); } } - + public boolean deleteFromCache(AssetKey key) { AssetCache cache = handler.getCache(key.getCacheType()); if (cache != null) { @@ -239,7 +239,7 @@ public class DesktopAssetManager implements AssetManager { throw new IllegalArgumentException("Key " + key + " specifies no cache."); } } - + public void clearCache(){ handler.clearCache(); if (logger.isLoggable(Level.FINER)){ @@ -257,14 +257,14 @@ public class DesktopAssetManager implements AssetManager { public T loadAsset(AssetKey key){ if (key == null) throw new IllegalArgumentException("key cannot be null"); - + for (AssetEventListener listener : eventListeners){ listener.assetRequested(key); } - + AssetCache cache = handler.getCache(key.getCacheType()); AssetProcessor proc = handler.getProcessor(key.getProcessorType()); - + Object obj = cache != null ? cache.getFromCache(key) : null; if (obj == null){ // Asset not in cache, load it from file system. @@ -298,17 +298,17 @@ public class DesktopAssetManager implements AssetManager { logger.log(Level.FINER, "Loaded {0} with {1}", new Object[]{key, loader.getClass().getSimpleName()}); } - + if (proc != null){ // do processing on asset before caching obj = proc.postProcess(key, obj); } - + if (cache != null){ // At this point, obj should be of type T cache.addToCache(key, (T) obj); } - + for (AssetEventListener listener : eventListeners){ listener.assetLoaded(key); } @@ -334,7 +334,7 @@ public class DesktopAssetManager implements AssetManager { } } } - + return clone; } @@ -342,7 +342,7 @@ public class DesktopAssetManager implements AssetManager { return loadAsset(new AssetKey(name)); } - public Texture loadTexture(TextureKey key){ + public Texture loadTexture(TextureKey key){ return (Texture) loadAsset(key); } @@ -438,5 +438,5 @@ public class DesktopAssetManager implements AssetManager { this.shaderGenerator = shaderGenerator; } - + } diff --git a/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java b/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java index 15c453dcc..46ddfd199 100644 --- a/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java +++ b/jme3-core/src/main/java/com/jme3/asset/cache/WeakRefCloneAssetCache.java @@ -33,7 +33,6 @@ package com.jme3.asset.cache; import com.jme3.asset.AssetKey; import com.jme3.asset.CloneableSmartAsset; - import java.lang.ref.PhantomReference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -46,43 +45,43 @@ import java.util.logging.Logger; * caches cloneable assets in a weak-key * cache, allowing them to be collected when memory is low. * The cache stores weak references to the asset keys, so that - * when all clones of the original asset are collected, will cause the + * when all clones of the original asset are collected, will cause the * asset to be automatically removed from the cache. - * - * @author Kirill Vainer + * +* @author Kirill Vainer */ public class WeakRefCloneAssetCache implements AssetCache { private static final Logger logger = Logger.getLogger(WeakRefAssetCache.class.getName()); - + private final ReferenceQueue refQueue = new ReferenceQueue(); - + /** - * Maps cloned key to AssetRef which has a weak ref to the original + * Maps cloned key to AssetRef which has a weak ref to the original * key and a strong ref to the original asset. */ - private final ConcurrentHashMap smartCache + private final ConcurrentHashMap smartCache = new ConcurrentHashMap(); - + /** * Stored in the ReferenceQueue to find out when originalKey is collected * by GC. Once collected, the clonedKey is used to remove the asset * from the cache. */ private static final class KeyRef extends PhantomReference { - + AssetKey clonedKey; - + public KeyRef(AssetKey originalKey, ReferenceQueue refQueue) { super(originalKey, refQueue); clonedKey = originalKey.clone(); } } - + /** * Stores the original key and original asset. * The asset info contains a cloneable asset (e.g. the original, from - * which all clones are made). Also a weak reference to the + * which all clones are made). Also a weak reference to the * original key which is used when the clones are produced. */ private static final class AssetRef extends WeakReference { @@ -95,24 +94,24 @@ public class WeakRefCloneAssetCache implements AssetCache { } } - private final ThreadLocal> assetLoadStack + private final ThreadLocal> assetLoadStack = new ThreadLocal>() { @Override protected ArrayList initialValue() { return new ArrayList(); } }; - - private void removeCollectedAssets() { + + private void removeCollectedAssets(){ int removedAssets = 0; - for (KeyRef ref; (ref = (KeyRef) refQueue.poll()) != null; ) { + for (KeyRef ref; (ref = (KeyRef)refQueue.poll()) != null;){ // (Cannot use ref.get() since it was just collected by GC!) AssetKey key = ref.clonedKey; - + // Asset was collected, note that at this point the asset cache // might not even have this asset anymore, it is OK. - if (smartCache.remove(key) != null) { - removedAssets++; + if (smartCache.remove(key) != null){ + removedAssets ++; //System.out.println("WeakRefAssetCache: The asset " + ref.assetKey + " was purged from the cache"); } } @@ -120,24 +119,25 @@ public class WeakRefCloneAssetCache implements AssetCache { logger.log(Level.FINE, "WeakRefAssetCache: {0} assets were purged from the cache.", removedAssets); } } - + public void addToCache(AssetKey originalKey, T obj) { // Make room for new asset removeCollectedAssets(); + CloneableSmartAsset asset = (CloneableSmartAsset) obj; - + // No circular references, since the original asset is // strongly referenced, we don't want the key strongly referenced. - asset.setKey(null); - + asset.setKey(null); + // Start tracking the collection of originalKey // (this adds the KeyRef to the ReferenceQueue) KeyRef ref = new KeyRef(originalKey, refQueue); - + // Place the asset in the cache, but use a clone of // the original key. smartCache.put(ref.clonedKey, new AssetRef(asset, originalKey)); - + // Push the original key used to load the asset // so that it can be set on the clone later ArrayList loadStack = assetLoadStack.get(); @@ -146,9 +146,9 @@ public class WeakRefCloneAssetCache implements AssetCache { public void registerAssetClone(AssetKey key, T clone) { ArrayList loadStack = assetLoadStack.get(); - ((CloneableSmartAsset) clone).setKey(loadStack.remove(loadStack.size() - 1)); + ((CloneableSmartAsset)clone).setKey(loadStack.remove(loadStack.size() - 1)); } - + public void notifyNoAssetClone() { ArrayList loadStack = assetLoadStack.get(); loadStack.remove(loadStack.size() - 1); @@ -156,10 +156,10 @@ public class WeakRefCloneAssetCache implements AssetCache { public T getFromCache(AssetKey key) { AssetRef smartInfo; - synchronized (smartCache) { + synchronized (smartCache){ smartInfo = smartCache.get(key); } - + if (smartInfo == null) { return null; } else { @@ -167,40 +167,40 @@ public class WeakRefCloneAssetCache implements AssetCache { // can check this and determine that the asset clone // belongs to the asset retrieved here. AssetKey keyForTheClone = smartInfo.get(); - if (keyForTheClone == null) { + if (keyForTheClone == null){ // The asset was JUST collected by GC // (between here and smartCache.get) return null; } - + // Prevent original key from getting collected // while an asset is loaded for it. ArrayList loadStack = assetLoadStack.get(); loadStack.add(keyForTheClone); - + return (T) smartInfo.asset; } } public boolean deleteFromCache(AssetKey key) { ArrayList loadStack = assetLoadStack.get(); - - if (!loadStack.isEmpty()) { + + if (!loadStack.isEmpty()){ throw new UnsupportedOperationException("Cache cannot be modified" - + "while assets are being loaded"); + + "while assets are being loaded"); } - + return smartCache.remove(key) != null; } - + public void clearCache() { ArrayList loadStack = assetLoadStack.get(); - - if (!loadStack.isEmpty()) { + + if (!loadStack.isEmpty()){ throw new UnsupportedOperationException("Cache cannot be modified" - + "while assets are being loaded"); + + "while assets are being loaded"); } - + smartCache.clear(); } } diff --git a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java index 6331fb28d..07bcd930e 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -49,9 +49,7 @@ public class TechniqueDef implements Savable { * Version #1: Separate shader language for each shader source. */ public static final int SAVABLE_VERSION = 1; - - - + /** * Describes light rendering mode. */ diff --git a/jme3-core/src/main/java/com/jme3/renderer/Caps.java b/jme3-core/src/main/java/com/jme3/renderer/Caps.java index 613a031f6..f0d42c8f2 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/Caps.java +++ b/jme3-core/src/main/java/com/jme3/renderer/Caps.java @@ -315,6 +315,7 @@ public enum Caps { * Supports 32-bit index buffers. */ IntegerIndexBuffer, + /** * Partial support for non-power-of-2 textures, typically found * on OpenGL ES 2 devices. diff --git a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java index 1dcd8b659..395b7e485 100644 --- a/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java +++ b/jme3-core/src/main/java/com/jme3/renderer/opengl/GLRenderer.java @@ -71,7 +71,7 @@ public class GLRenderer implements Renderer { private static final Logger logger = Logger.getLogger(GLRenderer.class.getName()); private static final boolean VALIDATE_SHADER = false; private static final Pattern GLVERSION_PATTERN = Pattern.compile(".*?(\\d+)\\.(\\d+).*"); - + private final ByteBuffer nameBuf = BufferUtils.createByteBuffer(250); private final StringBuilder stringBuf = new StringBuilder(250); private final IntBuffer intBuf1 = BufferUtils.createIntBuffer(1); @@ -81,7 +81,7 @@ public class GLRenderer implements Renderer { private final NativeObjectManager objManager = new NativeObjectManager(); private final EnumSet caps = EnumSet.noneOf(Caps.class); private final EnumMap limits = new EnumMap(Limits.class); - + // private int vertexTextureUnits; // private int fragTextureUnits; // private int vertexUniforms; @@ -111,7 +111,7 @@ public class GLRenderer implements Renderer { private final GLExt glext; private final GLFbo glfbo; private final TextureUtil texUtil; - + public GLRenderer(GL gl, GLFbo glfbo) { this.gl = gl; this.gl2 = gl instanceof GL2 ? (GL2)gl : null; @@ -131,7 +131,7 @@ public class GLRenderer implements Renderer { public EnumSet getCaps() { return caps; } - + // Not making public yet ... public EnumMap getLimits() { return limits; @@ -144,7 +144,7 @@ public class GLRenderer implements Renderer { } return extensionSet; } - + public static int extractVersion(String version) { Matcher m = GLVERSION_PATTERN.matcher(version); if (m.matches()) { @@ -164,17 +164,17 @@ public class GLRenderer implements Renderer { private boolean hasExtension(String extensionName) { return extensions.contains(extensionName); } - + private void loadCapabilitiesES() { caps.add(Caps.GLSL100); caps.add(Caps.OpenGLES20); - + // Important: Do not add OpenGL20 - that's the desktop capability! } - + private void loadCapabilitiesGL2() { int oglVer = extractVersion(gl.glGetString(GL.GL_VERSION)); - + if (oglVer >= 200) { caps.add(Caps.OpenGL20); if (oglVer >= 210) { @@ -196,9 +196,9 @@ public class GLRenderer implements Renderer { } } } - + int glslVer = extractVersion(gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION)); - + switch (glslVer) { default: if (glslVer < 400) { @@ -224,27 +224,27 @@ public class GLRenderer implements Renderer { caps.add(Caps.GLSL100); break; } - + // Workaround, always assume we support GLSL100 & GLSL110 // Supporting OpenGL 2.0 means supporting GLSL 1.10. caps.add(Caps.GLSL110); caps.add(Caps.GLSL100); - + // Fix issue in TestRenderToMemory when GL.GL_FRONT is the main // buffer being used. context.initialDrawBuf = getInteger(GL2.GL_DRAW_BUFFER); context.initialReadBuf = getInteger(GL2.GL_READ_BUFFER); - + // XXX: This has to be GL.GL_BACK for canvas on Mac // Since initialDrawBuf is GL.GL_FRONT for pbuffer, gotta // change this value later on ... // initialDrawBuf = GL.GL_BACK; // initialReadBuf = GL.GL_BACK; } - + private void loadCapabilitiesCommon() { extensions = loadExtensions(gl.glGetString(GL.GL_EXTENSIONS)); - + limits.put(Limits.VertexTextureUnits, getInteger(GL.GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS)); if (limits.get(Limits.VertexTextureUnits) > 0) { caps.add(Caps.VertexTextureFetch); @@ -264,7 +264,7 @@ public class GLRenderer implements Renderer { limits.put(Limits.TextureSize, getInteger(GL.GL_MAX_TEXTURE_SIZE)); limits.put(Limits.CubemapSize, getInteger(GL.GL_MAX_CUBE_MAP_TEXTURE_SIZE)); - if (hasExtension("GL_ARB_draw_instanced") && + if (hasExtension("GL_ARB_draw_instanced") && hasExtension("GL_ARB_instanced_arrays")) { caps.add(Caps.MeshInstancing); } @@ -272,43 +272,43 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_OES_element_index_uint") || gl2 != null) { caps.add(Caps.IntegerIndexBuffer); } - + if (hasExtension("GL_ARB_texture_buffer_object")) { caps.add(Caps.TextureBuffer); } - + // == texture format extensions == - + boolean hasFloatTexture = false; hasFloatTexture = hasExtension("GL_OES_texture_half_float") && hasExtension("GL_OES_texture_float"); - + if (!hasFloatTexture) { hasFloatTexture = hasExtension("GL_ARB_texture_float") && hasExtension("GL_ARB_half_float_pixel"); - + if (!hasFloatTexture) { hasFloatTexture = caps.contains(Caps.OpenGL30); } } - + if (hasFloatTexture) { caps.add(Caps.FloatTexture); } - + if (hasExtension("GL_OES_depth_texture") || gl2 != null) { caps.add(Caps.DepthTexture); - + // TODO: GL_OES_depth24 } - - if (hasExtension("GL_OES_rgb8_rgba8") || - hasExtension("GL_ARM_rgba8") || + + if (hasExtension("GL_OES_rgb8_rgba8") || + hasExtension("GL_ARM_rgba8") || hasExtension("GL_EXT_texture_format_BGRA8888")) { caps.add(Caps.Rgba8); } - + if (caps.contains(Caps.OpenGL30) || hasExtension("GL_OES_packed_depth_stencil")) { caps.add(Caps.PackedDepthStencilBuffer); } @@ -323,35 +323,35 @@ public class GLRenderer implements Renderer { caps.add(Caps.FloatDepthBuffer); } - if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || + if ((hasExtension("GL_EXT_packed_float") && hasFloatTexture) || caps.contains(Caps.OpenGL30)) { // Either OpenGL3 is available or both packed_float & half_float_pixel. caps.add(Caps.PackedFloatColorBuffer); caps.add(Caps.PackedFloatTexture); } - + if (hasExtension("GL_EXT_texture_shared_exponent") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.SharedExponentTexture); } - + if (hasExtension("GL_EXT_texture_compression_s3tc")) { caps.add(Caps.TextureCompressionS3TC); } - + if (hasExtension("GL_ARB_ES3_compatibility")) { caps.add(Caps.TextureCompressionETC2); caps.add(Caps.TextureCompressionETC1); } else if (hasExtension("GL_OES_compressed_ETC1_RGB8_texture")) { caps.add(Caps.TextureCompressionETC1); } - + // == end texture format extensions == - + if (hasExtension("GL_ARB_vertex_array_object") || caps.contains(Caps.OpenGL30)) { caps.add(Caps.VertexBufferArray); } - if (hasExtension("GL_ARB_texture_non_power_of_two") || + if (hasExtension("GL_ARB_texture_non_power_of_two") || hasExtension("GL_OES_texture_npot") || hasExtension("GL_APPLE_texture_2D_limited_npot") || caps.contains(Caps.OpenGL30)) { @@ -361,7 +361,7 @@ public class GLRenderer implements Renderer { + "support non-power-of-2 textures. " + "Some features might not work."); } - + if (caps.contains(Caps.OpenGLES20)) { // OpenGL ES 2 has some limited support for NPOT textures caps.add(Caps.PartialNonPowerOfTwoTextures); @@ -377,14 +377,14 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_EXT_framebuffer_object")) { caps.add(Caps.FrameBuffer); - + limits.put(Limits.RenderBufferSize, getInteger(GLExt.GL_MAX_RENDERBUFFER_SIZE_EXT)); limits.put(Limits.FrameBufferAttachments, getInteger(GLExt.GL_MAX_COLOR_ATTACHMENTS_EXT)); - + if (hasExtension("GL_EXT_framebuffer_blit")) { caps.add(Caps.FrameBufferBlit); } - + if (hasExtension("GL_EXT_framebuffer_multisample")) { caps.add(Caps.FrameBufferMultisample); limits.put(Limits.FrameBufferSamples, getInteger(GLExt.GL_MAX_SAMPLES_EXT)); @@ -422,9 +422,9 @@ public class GLRenderer implements Renderer { } caps.add(Caps.Multisample); } - + // Supports sRGB pipeline. - if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) + if ( (hasExtension("GL_ARB_framebuffer_sRGB") && hasExtension("GL_EXT_texture_sRGB")) || caps.contains(Caps.OpenGL30) ) { caps.add(Caps.Srgb); } @@ -433,24 +433,24 @@ public class GLRenderer implements Renderer { if (hasExtension("GL_ARB_seamless_cube_map") || caps.contains(Caps.OpenGL32)) { caps.add(Caps.SeamlessCubemap); } - + // if (hasExtension("GL_ARB_get_program_binary")) { // int binaryFormats = getInteger(GLExt.GL_NUM_PROGRAM_BINARY_FORMATS); // } - + // Print context information logger.log(Level.INFO, "OpenGL Renderer Information\n" + " * Vendor: {0}\n" + " * Renderer: {1}\n" + " * OpenGL Version: {2}\n" + " * GLSL Version: {3}", - new Object[]{ - gl.glGetString(GL.GL_VENDOR), + new Object[]{ + gl.glGetString(GL.GL_VENDOR), gl.glGetString(GL.GL_RENDERER), gl.glGetString(GL.GL_VERSION), gl.glGetString(GL.GL_SHADING_LANGUAGE_VERSION) }); - + // Print capabilities (if fine logging is enabled) if (logger.isLoggable(Level.FINE)) { StringBuilder sb = new StringBuilder(); @@ -461,10 +461,10 @@ public class GLRenderer implements Renderer { } logger.log(Level.FINE, sb.toString()); } - + texUtil.initialize(caps); } - + private void loadCapabilities() { if (gl2 != null) { loadCapabilitiesGL2(); @@ -473,22 +473,22 @@ public class GLRenderer implements Renderer { } loadCapabilitiesCommon(); } - + private int getInteger(int en) { intBuf16.clear(); gl.glGetInteger(en, intBuf16); return intBuf16.get(0); } - + private boolean getBoolean(int en) { gl.glGetBoolean(en, nameBuf); return nameBuf.get(0) != (byte)0; } - + @SuppressWarnings("fallthrough") public void initialize() { loadCapabilities(); - + // Initialize default state.. gl.glPixelStorei(GL.GL_UNPACK_ALIGNMENT, 1); } @@ -582,7 +582,7 @@ public class GLRenderer implements Renderer { } if (state.isDepthTest() && !context.depthTestEnabled) { - gl.glEnable(GL.GL_DEPTH_TEST); + gl.glEnable(GL.GL_DEPTH_TEST); gl.glDepthFunc(convertTestFunction(context.depthFunc)); context.depthTestEnabled = true; } else if (!state.isDepthTest() && context.depthTestEnabled) { @@ -721,7 +721,7 @@ public class GLRenderer implements Renderer { break; case Screen: gl.glBlendFunc(GL.GL_ONE, GL.GL_ONE_MINUS_SRC_COLOR); - break; + break; case Exclusion: gl.glBlendFunc(GL.GL_ONE_MINUS_DST_COLOR, GL.GL_ONE_MINUS_SRC_COLOR); break; @@ -1046,12 +1046,12 @@ public class GLRenderer implements Renderer { boolean gles2 = caps.contains(Caps.OpenGLES20); String language = source.getLanguage(); - + if (gles2 && !language.equals("GLSL100")) { throw new RendererException("This shader cannot run in OpenGL ES 2. " + "Only GLSL 1.00 shaders are supported."); } - + // Upload shader source. // Merge the defines and source code. stringBuf.setLength(0); @@ -1078,14 +1078,14 @@ public class GLRenderer implements Renderer { } } } - + if (linearizeSrgbImages) { stringBuf.append("#define SRGB 1\n"); } - + stringBuf.append(source.getDefines()); stringBuf.append(source.getSource()); - + intBuf1.clear(); intBuf1.put(0, stringBuf.length()); gl.glShaderSource(id, new String[]{ stringBuf.toString() }, intBuf1); @@ -1143,7 +1143,7 @@ public class GLRenderer implements Renderer { // If using GLSL 1.5, we bind the outputs for the user // For versions 3.3 and up, user should use layout qualifiers instead. boolean bindFragDataRequired = false; - + for (ShaderSource source : shader.getSources()) { if (source.isUpdateNeeded()) { updateShaderSourceData(source); @@ -1415,7 +1415,7 @@ public class GLRenderer implements Renderer { } else if (attachmentSlot < 0 || attachmentSlot >= 16) { throw new UnsupportedOperationException("Invalid FBO attachment slot: " + attachmentSlot); } - + return GLExt.GL_COLOR_ATTACHMENT0_EXT + attachmentSlot; } @@ -1425,7 +1425,7 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded()) { // Check NPOT requirements checkNonPowerOfTwo(tex); - + updateTexImageData(image, tex.getType(), 0); // NOTE: For depth textures, sets nearest/no-mips mode @@ -1586,7 +1586,7 @@ public class GLRenderer implements Renderer { // update viewport to reflect framebuffer's resolution setViewPort(0, 0, fb.getWidth(), fb.getHeight()); - + if (context.boundFBO != fb.getId()) { glfbo.glBindFramebufferEXT(GLExt.GL_FRAMEBUFFER_EXT, fb.getId()); statistics.onFrameBufferUse(fb, true); @@ -1659,7 +1659,7 @@ public class GLRenderer implements Renderer { public void readFrameBuffer(FrameBuffer fb, ByteBuffer byteBuf) { readFrameBufferWithGLFormat(fb, byteBuf, GL.GL_RGBA, GL.GL_UNSIGNED_BYTE); } - + private void readFrameBufferWithGLFormat(FrameBuffer fb, ByteBuffer byteBuf, int glFormat, int dataType) { if (fb != null) { RenderBuffer rb = fb.getColorBuffer(); @@ -1681,8 +1681,8 @@ public class GLRenderer implements Renderer { gl.glReadPixels(vpX, vpY, vpW, vpH, glFormat, dataType, byteBuf); } - - public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { + + public void readFrameBufferWithFormat(FrameBuffer fb, ByteBuffer byteBuf, Image.Format format) { GLImageFormat glFormat = texUtil.getImageFormatWithError(format, false); readFrameBufferWithGLFormat(fb, byteBuf, glFormat.format, glFormat.dataType); } @@ -1719,10 +1719,10 @@ public class GLRenderer implements Renderer { \*********************************************************************/ private int convertTextureType(Texture.Type type, int samples, int face) { if (samples > 1 && !caps.contains(Caps.TextureMultisample)) { - throw new RendererException("Multisample textures are not supported" + + throw new RendererException("Multisample textures are not supported" + " by the video hardware."); } - + switch (type) { case TwoDimensional: if (samples > 1) { @@ -1742,7 +1742,7 @@ public class GLRenderer implements Renderer { } case ThreeDimensional: if (!caps.contains(Caps.OpenGL20)) { - throw new RendererException("3D textures are not supported" + + throw new RendererException("3D textures are not supported" + " by the video hardware."); } return GL2.GL_TEXTURE_3D; @@ -1826,11 +1826,11 @@ public class GLRenderer implements Renderer { int target = convertTextureType(tex.getType(), image != null ? image.getMultiSamples() : 1, -1); boolean haveMips = true; - + if (image != null) { haveMips = image.isGeneratedMipmapsRequired() || image.hasMipmaps(); } - + // filter things if (image.getLastTextureState().magFilter != tex.getMagFilter()) { int magFilter = convertMagFilter(tex.getMagFilter()); @@ -1853,7 +1853,7 @@ public class GLRenderer implements Renderer { context.seamlessCubemap = false; } } - + if (tex.getAnisotropicFilter() > 1) { if (caps.contains(Caps.TextureFilterAnisotropic)) { gl.glTexParameterf(target, @@ -1865,7 +1865,7 @@ public class GLRenderer implements Renderer { if (context.pointSprite) { return; // Attempt to fix glTexParameter crash for some ATI GPUs } - + // repeat modes switch (tex.getType()) { case ThreeDimensional: @@ -1894,7 +1894,7 @@ public class GLRenderer implements Renderer { // R to Texture compare mode if (tex.getShadowCompareMode() != Texture.ShadowCompareMode.Off) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL2.GL_COMPARE_R_TO_TEXTURE); - gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); + gl2.glTexParameteri(target, GL2.GL_DEPTH_TEXTURE_MODE, GL2.GL_INTENSITY); if (tex.getShadowCompareMode() == Texture.ShadowCompareMode.GreaterOrEqual) { gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_FUNC, GL.GL_GEQUAL); } else { @@ -1902,7 +1902,7 @@ public class GLRenderer implements Renderer { } }else{ //restoring default value - gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); + gl2.glTexParameteri(target, GL2.GL_TEXTURE_COMPARE_MODE, GL.GL_NONE); } tex.compareModeUpdated(); } @@ -1911,10 +1911,10 @@ public class GLRenderer implements Renderer { /** * Validates if a potentially NPOT texture is supported by the hardware. *

- * Textures with power-of-2 dimensions are supported on all hardware, however + * Textures with power-of-2 dimensions are supported on all hardware, however * non-power-of-2 textures may or may not be supported depending on which * texturing features are used. - * + * * @param tex The texture to validate. * @throws RendererException If the texture is not supported by the hardware */ @@ -1923,19 +1923,19 @@ public class GLRenderer implements Renderer { // Texture is power-of-2, safe to use. return; } - + if (caps.contains(Caps.NonPowerOfTwoTextures)) { // Texture is NPOT but it is supported by video hardware. return; } - + // Maybe we have some / partial support for NPOT? if (!caps.contains(Caps.PartialNonPowerOfTwoTextures)) { // Cannot use any type of NPOT texture (uncommon) throw new RendererException("non-power-of-2 textures are not " + "supported by the video hardware"); } - + // Partial NPOT supported.. if (tex.getMinFilter().usesMipMapLevels()) { throw new RendererException("non-power-of-2 textures with mip-maps " @@ -1962,10 +1962,10 @@ public class GLRenderer implements Renderer { throw new UnsupportedOperationException("unrecongized texture type"); } } - + /** * Uploads the given image to the GL driver. - * + * * @param img The image to upload * @param type How the data in the image argument should be interpreted. * @param unit The texture slot to be used to upload the image, not important @@ -1989,7 +1989,7 @@ public class GLRenderer implements Renderer { gl.glActiveTexture(GL.GL_TEXTURE0 + unit); context.boundTextureUnit = unit; } - + gl.glBindTexture(target, texId); context.boundTextures[unit] = img; @@ -2032,12 +2032,12 @@ public class GLRenderer implements Renderer { throw new RendererException("Multisample textures are not supported by the video hardware"); } } - + // Check if graphics card doesn't support depth textures if (img.getFormat().isDepthFormat() && !caps.contains(Caps.DepthTexture)) { throw new RendererException("Depth textures are not supported by the video hardware"); } - + if (target == GL.GL_TEXTURE_CUBE_MAP) { // Check max texture size before upload int cubeSize = limits.get(Limits.CubemapSize); @@ -2068,12 +2068,12 @@ public class GLRenderer implements Renderer { if (!caps.contains(Caps.TextureArray)) { throw new RendererException("Texture arrays not supported by graphics hardware"); } - + List data = img.getData(); - + // -1 index specifies prepare data for 2D Array texUtil.uploadTexture(img, target, -1, linearizeSrgbImages); - + for (int i = 0; i < data.size(); i++) { // upload each slice of 2D array in turn // this time with the appropriate index @@ -2104,7 +2104,7 @@ public class GLRenderer implements Renderer { if (image.isUpdateNeeded() || (image.isGeneratedMipmapsRequired() && !image.isMipmapsGenerated())) { // Check NPOT requirements checkNonPowerOfTwo(tex); - + updateTexImageData(image, tex.getType(), unit); } @@ -2225,7 +2225,7 @@ public class GLRenderer implements Renderer { //statistics.onVertexBufferUse(vb, false); } } - + int usage = convertUsage(vb.getUsage()); vb.getData().rewind(); @@ -2314,7 +2314,7 @@ public class GLRenderer implements Renderer { if (context.boundShaderProgram <= 0) { throw new IllegalStateException("Cannot render mesh without shader bound"); } - + Attribute attrib = context.boundShader.getAttribute(vb.getBufferType()); int loc = attrib.getLocation(); if (loc == -1) { @@ -2444,7 +2444,7 @@ public class GLRenderer implements Renderer { // What is this? throw new RendererException("Unexpected format for index buffer: " + indexBuf.getFormat()); } - + if (indexBuf.isUpdateNeeded()) { updateBufferData(indexBuf); } @@ -2561,7 +2561,7 @@ public class GLRenderer implements Renderer { if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); } - + if (instanceData != null) { setVertexAttrib(instanceData, null); } @@ -2611,11 +2611,11 @@ public class GLRenderer implements Renderer { } private void renderMeshDefault(Mesh mesh, int lod, int count, VertexBuffer[] instanceData) { - + // Here while count is still passed in. Can be removed when/if // the method is collapsed again. -pspeed count = Math.max(mesh.getInstanceCount(), count); - + VertexBuffer interleavedData = mesh.getBuffer(Type.InterleavedData); if (interleavedData != null && interleavedData.isUpdateNeeded()) { updateBufferData(interleavedData); @@ -2633,7 +2633,7 @@ public class GLRenderer implements Renderer { setVertexAttrib(vb, null); } } - + for (VertexBuffer vb : mesh.getBufferList().getArray()) { if (vb.getBufferType() == Type.InterleavedData || vb.getUsage() == Usage.CpuOnly // ignore cpu-only buffers @@ -2703,12 +2703,12 @@ public class GLRenderer implements Renderer { // Gamma correction if (!caps.contains(Caps.Srgb)) { // Not supported, sorry. - logger.warning("sRGB framebuffer is not supported " + - "by video hardware, but was requested."); - + logger.warning("sRGB framebuffer is not supported " + + "by video hardware, but was requested."); + return; } - + setFrameBuffer(null); if (enableSrgb) { diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java index a4bf9fe9a..449802161 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/J3MLoader.java @@ -60,10 +60,10 @@ import java.util.logging.Logger; public class J3MLoader implements AssetLoader { private static final Logger logger = Logger.getLogger(J3MLoader.class.getName()); - // private ErrorLogger errors; + // private ErrorLogger errors; private ShaderNodeLoaderDelegate nodesLoaderDelegate; boolean isUseNodes = false; - + private AssetManager assetManager; private AssetKey key; @@ -107,9 +107,9 @@ public class J3MLoader implements AssetLoader { } // LightMode - private void readLightMode(String statement) throws IOException { + private void readLightMode(String statement) throws IOException{ String[] split = statement.split(whitespacePattern); - if (split.length != 2) { + if (split.length != 2){ throw new IOException("LightMode statement syntax incorrect"); } LightMode lm = LightMode.valueOf(split[1]); @@ -117,29 +117,29 @@ public class J3MLoader implements AssetLoader { } // ShadowMode - private void readShadowMode(String statement) throws IOException { + private void readShadowMode(String statement) throws IOException{ String[] split = statement.split(whitespacePattern); - if (split.length != 2) { + if (split.length != 2){ throw new IOException("ShadowMode statement syntax incorrect"); } ShadowMode sm = ShadowMode.valueOf(split[1]); technique.setShadowMode(sm); } - private Object readValue(VarType type, String value) throws IOException { - if (type.isTextureType()) { + private Object readValue(VarType type, String value) throws IOException{ + if (type.isTextureType()){ // String texturePath = readString("[\n;(//)(\\})]"); String texturePath = value.trim(); boolean flipY = false; boolean repeat = false; - if (texturePath.startsWith("Flip Repeat ")) { + if (texturePath.startsWith("Flip Repeat ")){ texturePath = texturePath.substring(12).trim(); flipY = true; repeat = true; - } else if (texturePath.startsWith("Flip ")) { + }else if (texturePath.startsWith("Flip ")){ texturePath = texturePath.substring(5).trim(); flipY = true; - } else if (texturePath.startsWith("Repeat ")) { + }else if (texturePath.startsWith("Repeat ")){ texturePath = texturePath.substring(7).trim(); repeat = true; } @@ -161,269 +161,270 @@ public class J3MLoader implements AssetLoader { Texture tex; try { tex = assetManager.loadTexture(texKey); - } catch (AssetNotFoundException ex) { + } catch (AssetNotFoundException ex){ logger.log(Level.WARNING, "Cannot locate {0} for material {1}", new Object[]{texKey, key}); tex = null; } - if (tex != null) { - if (repeat) { + if (tex != null){ + if (repeat){ tex.setWrap(WrapMode.Repeat); - } - } else { + } + }else{ tex = new Texture2D(PlaceholderAssets.getPlaceholderImage(assetManager)); - if (repeat) { + if (repeat){ tex.setWrap(WrapMode.Repeat); } tex.setKey(texKey); - } + } return tex; - } else { + }else{ String[] split = value.trim().split(whitespacePattern); - switch (type) { + switch (type){ case Float: - if (split.length != 1) { + if (split.length != 1){ throw new IOException("Float value parameter must have 1 entry: " + value); } - return Float.parseFloat(split[0]); + return Float.parseFloat(split[0]); case Vector2: - if (split.length != 2) { + if (split.length != 2){ throw new IOException("Vector2 value parameter must have 2 entries: " + value); } return new Vector2f(Float.parseFloat(split[0]), - Float.parseFloat(split[1])); + Float.parseFloat(split[1])); case Vector3: - if (split.length != 3) { + if (split.length != 3){ throw new IOException("Vector3 value parameter must have 3 entries: " + value); } return new Vector3f(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2])); + Float.parseFloat(split[1]), + Float.parseFloat(split[2])); case Vector4: - if (split.length != 4) { + if (split.length != 4){ throw new IOException("Vector4 value parameter must have 4 entries: " + value); } return new ColorRGBA(Float.parseFloat(split[0]), - Float.parseFloat(split[1]), - Float.parseFloat(split[2]), - Float.parseFloat(split[3])); + Float.parseFloat(split[1]), + Float.parseFloat(split[2]), + Float.parseFloat(split[3])); case Int: - if (split.length != 1) { + if (split.length != 1){ throw new IOException("Int value parameter must have 1 entry: " + value); } return Integer.parseInt(split[0]); case Boolean: - if (split.length != 1) { + if (split.length != 1){ throw new IOException("Boolean value parameter must have 1 entry: " + value); } return Boolean.parseBoolean(split[0]); default: - throw new UnsupportedOperationException("Unknown type: " + type); + throw new UnsupportedOperationException("Unknown type: "+type); } } } - - // [ "(" ")" ] [ ":" ] [-LINEAR] - private void readParam(String statement) throws IOException { + + // [ "(" ")" ] [-LINEAR] [ ":" ] + private void readParam(String statement) throws IOException{ String name; String defaultVal = null; ColorSpace colorSpace = null; - + String[] split = statement.split(":"); - + // Parse default val - if (split.length == 1) { + if (split.length == 1){ // Doesn't contain default value - } else { - if (split.length != 2) { + }else{ + if (split.length != 2){ throw new IOException("Parameter statement syntax incorrect"); } statement = split[0].trim(); - defaultVal = split[1].trim(); + defaultVal = split[1].trim(); } + if (statement.endsWith("-LINEAR")) { colorSpace = ColorSpace.Linear; statement = statement.substring(0, statement.length() - "-LINEAR".length()); } - + // Parse ffbinding int startParen = statement.indexOf("("); - if (startParen != -1) { + if (startParen != -1){ // get content inside parentheses int endParen = statement.indexOf(")", startParen); - String bindingStr = statement.substring(startParen + 1, endParen).trim(); + String bindingStr = statement.substring(startParen+1, endParen).trim(); // don't care about bindingStr statement = statement.substring(0, startParen); } - + // Parse type + name split = statement.split(whitespacePattern); - if (split.length != 2) { + if (split.length != 2){ throw new IOException("Parameter statement syntax incorrect"); } - + VarType type; - if (split[0].equals("Color")) { + if (split[0].equals("Color")){ type = VarType.Vector4; - } else { + }else{ type = VarType.valueOf(split[0]); } - + name = split[1]; - + Object defaultValObj = null; - if (defaultVal != null) { + if (defaultVal != null){ defaultValObj = readValue(type, defaultVal); } - if (type.isTextureType()) { - materialDef.addMaterialParamTexture(type, name, colorSpace); - } else { + if(type.isTextureType()){ + materialDef.addMaterialParamTexture(type, name, colorSpace); + }else{ materialDef.addMaterialParam(type, name, defaultValObj); } - + } - private void readValueParam(String statement) throws IOException { + private void readValueParam(String statement) throws IOException{ // Use limit=1 incase filename contains colons String[] split = statement.split(":", 2); - if (split.length != 2) { + if (split.length != 2){ throw new IOException("Value parameter statement syntax incorrect"); } String name = split[0].trim(); // parse value MatParam p = material.getMaterialDef().getMaterialParam(name); - if (p == null) { - throw new IOException("The material parameter: " + name + " is undefined."); + if (p == null){ + throw new IOException("The material parameter: "+name+" is undefined."); } Object valueObj = readValue(p.getVarType(), split[1]); - if (p.getVarType().isTextureType()) { + if (p.getVarType().isTextureType()){ material.setTextureParam(name, p.getVarType(), (Texture) valueObj); - } else { + }else{ material.setParam(name, p.getVarType(), valueObj); } } - private void readMaterialParams(List paramsList) throws IOException { - for (Statement statement : paramsList) { + private void readMaterialParams(List paramsList) throws IOException{ + for (Statement statement : paramsList){ readParam(statement.getLine()); } } - private void readExtendingMaterialParams(List paramsList) throws IOException { - for (Statement statement : paramsList) { + private void readExtendingMaterialParams(List paramsList) throws IOException{ + for (Statement statement : paramsList){ readValueParam(statement.getLine()); } } - private void readWorldParams(List worldParams) throws IOException { - for (Statement statement : worldParams) { + private void readWorldParams(List worldParams) throws IOException{ + for (Statement statement : worldParams){ technique.addWorldParam(statement.getLine()); } } - private boolean parseBoolean(String word) { + private boolean parseBoolean(String word){ return word != null && word.equals("On"); } - private void readRenderStateStatement(Statement statement) throws IOException { + private void readRenderStateStatement(Statement statement) throws IOException{ String[] split = statement.getLine().split(whitespacePattern); - if (split[0].equals("Wireframe")) { + if (split[0].equals("Wireframe")){ renderState.setWireframe(parseBoolean(split[1])); - } else if (split[0].equals("FaceCull")) { + }else if (split[0].equals("FaceCull")){ renderState.setFaceCullMode(FaceCullMode.valueOf(split[1])); - } else if (split[0].equals("DepthWrite")) { + }else if (split[0].equals("DepthWrite")){ renderState.setDepthWrite(parseBoolean(split[1])); - } else if (split[0].equals("DepthTest")) { + }else if (split[0].equals("DepthTest")){ renderState.setDepthTest(parseBoolean(split[1])); - } else if (split[0].equals("Blend")) { + }else if (split[0].equals("Blend")){ renderState.setBlendMode(BlendMode.valueOf(split[1])); - } else if (split[0].equals("AlphaTestFalloff")) { + }else if (split[0].equals("AlphaTestFalloff")){ renderState.setAlphaTest(true); renderState.setAlphaFallOff(Float.parseFloat(split[1])); - } else if (split[0].equals("PolyOffset")) { + }else if (split[0].equals("PolyOffset")){ float factor = Float.parseFloat(split[1]); float units = Float.parseFloat(split[2]); renderState.setPolyOffset(factor, units); - } else if (split[0].equals("ColorWrite")) { + }else if (split[0].equals("ColorWrite")){ renderState.setColorWrite(parseBoolean(split[1])); - } else if (split[0].equals("PointSprite")) { + }else if (split[0].equals("PointSprite")){ renderState.setPointSprite(parseBoolean(split[1])); - } else if (split[0].equals("DepthFunc")) { + }else if (split[0].equals("DepthFunc")){ renderState.setDepthFunc(RenderState.TestFunction.valueOf(split[1])); - } else if (split[0].equals("AlphaFunc")) { + }else if (split[0].equals("AlphaFunc")){ renderState.setAlphaFunc(RenderState.TestFunction.valueOf(split[1])); } else { throw new MatParseException(null, split[0], statement); } } - private void readAdditionalRenderState(List renderStates) throws IOException { + private void readAdditionalRenderState(List renderStates) throws IOException{ renderState = material.getAdditionalRenderState(); - for (Statement statement : renderStates) { + for (Statement statement : renderStates){ readRenderStateStatement(statement); } renderState = null; } - private void readRenderState(List renderStates) throws IOException { + private void readRenderState(List renderStates) throws IOException{ renderState = new RenderState(); - for (Statement statement : renderStates) { + for (Statement statement : renderStates){ readRenderStateStatement(statement); } technique.setRenderState(renderState); renderState = null; } - - private void readForcedRenderState(List renderStates) throws IOException { + + private void readForcedRenderState(List renderStates) throws IOException{ renderState = new RenderState(); - for (Statement statement : renderStates) { + for (Statement statement : renderStates){ readRenderStateStatement(statement); } technique.setForcedRenderState(renderState); renderState = null; } - + // [ ":" ] - private void readDefine(String statement) throws IOException { + private void readDefine(String statement) throws IOException{ String[] split = statement.split(":"); - if (split.length == 1) { + if (split.length == 1){ // add preset define technique.addShaderPresetDefine(split[0].trim(), VarType.Boolean, true); - } else if (split.length == 2) { + }else if (split.length == 2){ technique.addShaderParamDefine(split[1].trim(), split[0].trim()); - } else { + }else{ throw new IOException("Define syntax incorrect"); } } - private void readDefines(List defineList) throws IOException { - for (Statement statement : defineList) { + private void readDefines(List defineList) throws IOException{ + for (Statement statement : defineList){ readDefine(statement.getLine()); } } - - private void readTechniqueStatement(Statement statement) throws IOException { - String[] split = statement.getLine().split("[ \\{]"); + + private void readTechniqueStatement(Statement statement) throws IOException{ + String[] split = statement.getLine().split("[ \\{]"); if (split[0].equals("VertexShader") || 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")) { + }else if (split[0].equals("LightMode")){ readLightMode(statement.getLine()); - } else if (split[0].equals("ShadowMode")) { + }else if (split[0].equals("ShadowMode")){ readShadowMode(statement.getLine()); - } else if (split[0].equals("WorldParameters")) { + }else if (split[0].equals("WorldParameters")){ readWorldParams(statement.getContents()); - } else if (split[0].equals("RenderState")) { + }else if (split[0].equals("RenderState")){ readRenderState(statement.getContents()); - } else if (split[0].equals("ForcedRenderState")) { + }else if (split[0].equals("ForcedRenderState")){ readForcedRenderState(statement.getContents()); - } else if (split[0].equals("Defines")) { - readDefines(statement.getContents()); + }else if (split[0].equals("Defines")){ + readDefines(statement.getContents()); } else if (split[0].equals("ShaderNodesDefinitions")) { initNodesLoader(); if (isUseNodes) { @@ -436,23 +437,23 @@ public class J3MLoader implements AssetLoader { } } else if (split[0].equals("FragmentShaderNodes")) { initNodesLoader(); - if (isUseNodes) { + if (isUseNodes) { nodesLoaderDelegate.readFragmentShaderNodes(statement.getContents()); } } else { throw new MatParseException(null, split[0], statement); } } - - private void readTransparentStatement(String statement) throws IOException { + + private void readTransparentStatement(String statement) throws IOException{ String[] split = statement.split(whitespacePattern); - if (split.length != 2) { + if (split.length != 2){ throw new IOException("Transparent statement syntax incorrect"); } material.setTransparent(parseBoolean(split[1])); } - private void readTechnique(Statement techStat) throws IOException { + private void readTechnique(Statement techStat) throws IOException{ isUseNodes = false; String[] split = techStat.getLine().split(whitespacePattern); if (split.length == 1) { @@ -463,12 +464,12 @@ public class J3MLoader implements AssetLoader { } else { throw new IOException("Technique statement syntax incorrect"); } - - for (Statement statement : techStat.getContents()) { + + for (Statement statement : techStat.getContents()){ readTechniqueStatement(statement); } - - if (isUseNodes) { + + if(isUseNodes){ nodesLoaderDelegate.computeConditions(); //used for caching later, the shader here is not a file. technique.setShaderFile(technique.hashCode() + "", technique.hashCode() + "", "GLSL100", "GLSL100"); @@ -477,48 +478,48 @@ public class J3MLoader implements AssetLoader { if (shaderName.containsKey(Shader.ShaderType.Vertex) && shaderName.containsKey(Shader.ShaderType.Fragment)) { technique.setShaderFile(shaderName, shaderLanguage); } - + materialDef.addTechniqueDef(technique); technique = null; shaderLanguage.clear(); shaderName.clear(); } - private void loadFromRoot(List roots) throws IOException { - if (roots.size() == 2) { + private void loadFromRoot(List roots) throws IOException{ + if (roots.size() == 2){ Statement exception = roots.get(0); String line = exception.getLine(); - if (line.startsWith("Exception")) { + if (line.startsWith("Exception")){ throw new AssetLoadException(line.substring("Exception ".length())); - } else { + }else{ throw new IOException("In multiroot material, expected first statement to be 'Exception'"); } - } else if (roots.size() != 1) { + }else if (roots.size() != 1){ throw new IOException("Too many roots in J3M/J3MD file"); } - + boolean extending = false; Statement materialStat = roots.get(0); String materialName = materialStat.getLine(); - if (materialName.startsWith("MaterialDef")) { + if (materialName.startsWith("MaterialDef")){ materialName = materialName.substring("MaterialDef ".length()).trim(); extending = false; - } else if (materialName.startsWith("Material")) { + }else if (materialName.startsWith("Material")){ materialName = materialName.substring("Material ".length()).trim(); extending = true; - } else { + }else{ throw new IOException("Specified file is not a Material file"); } - + String[] split = materialName.split(":", 2); - - if (materialName.equals("")) { - throw new MatParseException("Material name cannot be empty", materialStat); + + if (materialName.equals("")){ + throw new MatParseException("Material name cannot be empty", materialStat); } - if (split.length == 2) { - if (!extending) { - throw new MatParseException("Must use 'Material' when extending.", materialStat); + if (split.length == 2){ + if (!extending){ + throw new MatParseException("Must use 'Material' when extending.", materialStat); } String extendedMat = split[1].trim(); @@ -531,65 +532,65 @@ public class J3MLoader implements AssetLoader { material = new Material(def); material.setKey(key); // material.setAssetName(fileName); - } else if (split.length == 1) { - if (extending) { - throw new MatParseException("Expected ':', got '{'", materialStat); + }else if (split.length == 1){ + if (extending){ + throw new MatParseException("Expected ':', got '{'", materialStat); } materialDef = new MaterialDef(assetManager, materialName); // NOTE: pass file name for defs so they can be loaded later materialDef.setAssetName(key.getName()); - } else { - throw new MatParseException("Cannot use colon in material name/path", materialStat); + }else{ + throw new MatParseException("Cannot use colon in material name/path", materialStat); } - - for (Statement statement : materialStat.getContents()) { + + for (Statement statement : materialStat.getContents()){ split = statement.getLine().split("[ \\{]"); String statType = split[0]; - if (extending) { - if (statType.equals("MaterialParameters")) { + if (extending){ + if (statType.equals("MaterialParameters")){ readExtendingMaterialParams(statement.getContents()); - } else if (statType.equals("AdditionalRenderState")) { + }else if (statType.equals("AdditionalRenderState")){ readAdditionalRenderState(statement.getContents()); - } else if (statType.equals("Transparent")) { + }else if (statType.equals("Transparent")){ readTransparentStatement(statement.getLine()); } - } else { - if (statType.equals("Technique")) { + }else{ + if (statType.equals("Technique")){ readTechnique(statement); - } else if (statType.equals("MaterialParameters")) { + }else if (statType.equals("MaterialParameters")){ readMaterialParams(statement.getContents()); - } else { - throw new MatParseException("Expected material statement, got '" + statType + "'", statement); + }else{ + throw new MatParseException("Expected material statement, got '"+statType+"'", statement); } } } } - public Object load(AssetInfo info) throws IOException { + public Object load(AssetInfo info) throws IOException { this.assetManager = info.getManager(); - InputStream in = info.openStream(); + InputStream in = info.openStream(); try { - key = info.getKey(); + key = info.getKey(); loadFromRoot(BlockLanguageParser.parse(in)); } finally { - if (in != null) { + if (in != null){ in.close(); } } - - if (material != null) { - if (!(info.getKey() instanceof MaterialKey)) { + + if (material != null){ + if (!(info.getKey() instanceof MaterialKey)){ throw new IOException("Material instances must be loaded via MaterialKey"); } // material implementation return material; - } else { + }else{ // material definition return materialDef; } } - + public MaterialDef loadMaterialDef(List roots, AssetManager manager, AssetKey key) throws IOException { this.key = key; this.assetManager = manager; @@ -603,7 +604,7 @@ public class J3MLoader implements AssetLoader { if (isUseNodes) { if (nodesLoaderDelegate == null) { nodesLoaderDelegate = new ShaderNodeLoaderDelegate(); - } else { + }else{ nodesLoaderDelegate.clear(); } nodesLoaderDelegate.setTechniqueDef(technique); @@ -611,6 +612,6 @@ public class J3MLoader implements AssetLoader { nodesLoaderDelegate.setAssetManager(assetManager); } } - } + } } From 1233fcf727f039da4f3736317706786ddf01357a Mon Sep 17 00:00:00 2001 From: michael Date: Sat, 28 Feb 2015 17:03:10 +0100 Subject: [PATCH 34/34] Removed a Sysout --- jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java | 1 - 1 file changed, 1 deletion(-) diff --git a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java index 077b13a5a..65d8d9a7b 100644 --- a/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java +++ b/jme3-core/src/main/java/com/jme3/asset/DesktopAssetManager.java @@ -393,7 +393,6 @@ public class DesktopAssetManager implements AssetManager { public Shader loadShader(ShaderKey key){ // cache abuse in method // that doesn't use loaders/locators - System.out.println(); AssetCache cache = handler.getCache(SimpleAssetCache.class); Shader shader = (Shader) cache.getFromCache(key); if (shader == null){