diff --git a/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java b/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java index d7a201909..81f579bd6 100644 --- a/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java +++ b/engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java @@ -272,12 +272,23 @@ public class ShaderNodeLoaderDelegate { * @throws IOException */ protected ShaderNodeVariable readVariable(Statement statement) throws IOException { - String[] splitVar = statement.getLine().trim().split("\\s"); - if (varNames.contains(splitVar[1] + ";")) { - throw new MatParseException("Duplicate variable name " + splitVar[1], statement); + String line = statement.getLine().trim().replaceAll("\\s*\\[", "["); + String[] splitVar = line.split("\\s"); + String varName = splitVar[1]; + String varType = splitVar[0]; + String multiplicity = null; + + if (varName.contains("[")) { + //we have an array + String[] arr = splitVar[1].split("\\["); + varName = arr[0].trim(); + multiplicity = arr[1].replaceAll("\\]", "").trim(); } - varNames += splitVar[1] + ";"; - return new ShaderNodeVariable(splitVar[0], splitVar[1]); + if (varNames.contains(varName + ";")) { + throw new MatParseException("Duplicate variable name " + varName, statement); + } + varNames += varName + ";"; + return new ShaderNodeVariable(varType, "", varName, multiplicity); } /** @@ -437,6 +448,7 @@ public class ShaderNodeLoaderDelegate { for (ShaderNodeVariable shaderNodeVariable : list) { if (shaderNodeVariable.getName().equals(var.getName())) { var.setType(shaderNodeVariable.getType()); + var.setMultiplicity(shaderNodeVariable.getMultiplicity()); var.setNameSpace(shaderNode.getName()); return true; } @@ -545,18 +557,37 @@ public class ShaderNodeLoaderDelegate { * @param map the map of uniforms to search into * @return true if the param was added to the map */ - public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map map) { + public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map map, Statement statement) throws MatParseException { ShaderNodeVariable right = mapping.getRightVariable(); DeclaredVariable dv = map.get(param.getPrefixedName()); if (dv == null) { right.setType(param.getVarType().getGlslType()); - right.setName(param.getPrefixedName()); + right.setName(param.getPrefixedName()); + if(mapping.getLeftVariable().getMultiplicity() != null){ + if(!param.getVarType().name().endsWith("Array")){ + throw new MatParseException(param.getName() + " is not of Array type", statement); + } + String multiplicity = mapping.getLeftVariable().getMultiplicity(); + try { + Integer.parseInt(multiplicity); + } catch (NumberFormatException nfe) { + //multiplicity is not an int attempting to find for a material parameter. + MatParam mp = findMatParam(multiplicity); + if (mp != null) { + addDefine(multiplicity); + multiplicity = multiplicity.toUpperCase(); + } else { + throw new MatParseException("Wrong multiplicity for variable" + mapping.getLeftVariable().getName() + ". " + multiplicity + " should be an int or a declared material parameter.", statement); + } + } + right.setMultiplicity(multiplicity); + } dv = new DeclaredVariable(right); map.put(right.getName(), dv); - dv.addNode(shaderNode); + dv.addNode(shaderNode); mapping.setRightVariable(right); return true; - } + } dv.addNode(shaderNode); mapping.setRightVariable(dv.var); return false; @@ -669,12 +700,11 @@ public class ShaderNodeLoaderDelegate { throw new MatParseException("Could not find a Material Parameter named " + right.getName(), statement1); } if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) { - if (updateRightFromUniforms(param, mapping, vertexDeclaredUniforms)) { - // updateCondition(mapping.getRightVariable(), mapping); + if (updateRightFromUniforms(param, mapping, vertexDeclaredUniforms, statement1)) { storeVertexUniform(mapping.getRightVariable()); } } else { - if (updateRightFromUniforms(param, mapping, fragmentDeclaredUniforms)) { + if (updateRightFromUniforms(param, mapping, fragmentDeclaredUniforms, statement1)) { if (mapping.getRightVariable().getType().contains("|")) { String type = fixSamplerType(left.getType(), mapping.getRightVariable().getType()); if (type != null) { @@ -682,8 +712,7 @@ public class ShaderNodeLoaderDelegate { } else { throw new MatParseException(param.getVarType().toString() + " can only be matched to one of " + param.getVarType().getGlslType().replaceAll("\\|", ",") + " found " + left.getType(), statement1); } - } - // updateCondition(mapping.getRightVariable(), mapping); + } storeFragmentUniform(mapping.getRightVariable()); } } @@ -694,13 +723,11 @@ public class ShaderNodeLoaderDelegate { throw new MatParseException("Could not find a World Parameter named " + right.getName(), statement1); } if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) { - if (updateRightFromUniforms(worldParam, mapping, vertexDeclaredUniforms)) { - // updateCondition(mapping.getRightVariable(), mapping); + if (updateRightFromUniforms(worldParam, mapping, vertexDeclaredUniforms)) { storeVertexUniform(mapping.getRightVariable()); } } else { - if (updateRightFromUniforms(worldParam, mapping, fragmentDeclaredUniforms)) { - // updateCondition(mapping.getRightVariable(), mapping); + if (updateRightFromUniforms(worldParam, mapping, fragmentDeclaredUniforms)) { storeFragmentUniform(mapping.getRightVariable()); } } @@ -716,8 +743,7 @@ public class ShaderNodeLoaderDelegate { } right.setNameSpace(node.getName()); right.setType(var.getType()); - mapping.setRightVariable(right); - // updateCondition(mapping.getRightVariable(), mapping); + mapping.setRightVariable(right); storeVaryings(node, mapping.getRightVariable()); } @@ -751,7 +777,6 @@ public class ShaderNodeLoaderDelegate { if (left.getNameSpace().equals("Global")) { left.setType("vec4");//Globals are all vec4 for now (maybe forever...) - // updateCondition(left, mapping); storeGlobal(left, statement1); } else { throw new MatParseException("Only Global nameSpace is allowed for outputMapping, got" + left.getNameSpace(), statement1); @@ -1026,6 +1051,11 @@ public class ShaderNodeLoaderDelegate { String rs = mapping.getRightSwizzling().length() == 0 ? "" : "." + mapping.getRightSwizzling(); throw new MatParseException("Type mismatch, cannot convert" + mapping.getLeftVariable().getType() + ls + " to " + mapping.getRightVariable().getType() + rs, statement1); } + if (!ShaderUtils.multiplicityMatch(mapping)) { + String type1 = mapping.getLeftVariable().getType() + "[" + mapping.getLeftVariable().getMultiplicity() + "]"; + String type2 = mapping.getRightVariable().getType() + "[" + mapping.getRightVariable().getMultiplicity() + "]"; + throw new MatParseException("Type mismatch, cannot convert" + type1 + " to " + type2, statement1); + } } private Map getNodeDefinitions() { diff --git a/engine/src/core/com/jme3/shader/Glsl100ShaderGenerator.java b/engine/src/core/com/jme3/shader/Glsl100ShaderGenerator.java index 5340de86a..d7c94c856 100644 --- a/engine/src/core/com/jme3/shader/Glsl100ShaderGenerator.java +++ b/engine/src/core/com/jme3/shader/Glsl100ShaderGenerator.java @@ -49,7 +49,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator { /** * the indentation characters 1à tabulation characters */ - private final static String INDENTCHAR = "\t\t\t\t\t\t\t\t\t\t"; + private final static String INDENTCHAR = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; /** * creates a Glsl100ShaderGenerator @@ -333,6 +333,11 @@ public class Glsl100ShaderGenerator extends ShaderGenerator { source.append("_"); } source.append(var.getName()); + if (var.getMultiplicity() != null) { + source.append("["); + source.append(var.getMultiplicity().toUpperCase()); + source.append("]"); + } if (value != null) { source.append(" = "); source.append(value); diff --git a/engine/src/core/com/jme3/shader/ShaderNodeVariable.java b/engine/src/core/com/jme3/shader/ShaderNodeVariable.java index 5a24473e9..81dba4f52 100644 --- a/engine/src/core/com/jme3/shader/ShaderNodeVariable.java +++ b/engine/src/core/com/jme3/shader/ShaderNodeVariable.java @@ -50,6 +50,7 @@ public class ShaderNodeVariable implements Savable, Cloneable { private String nameSpace; private String condition; private boolean shaderOutput = false; + private String multiplicity; /** * creates a ShaderNodeVariable @@ -61,6 +62,23 @@ public class ShaderNodeVariable implements Savable, Cloneable { this.name = name; this.type = type; } + + + /** + * creates a ShaderNodeVariable + * + * @param type the glsl type of the variable + * @param nameSpace the nameSpace (can be the name of the shaderNode or + * Globel,Attr,MatParam,WorldParam) + * @param name the name of the variable + * @param multiplicity the number of element if this variable is an array. Can be an Int of a declared material parameter + */ + public ShaderNodeVariable(String type, String nameSpace, String name, String multiplicity) { + this.name = name; + this.nameSpace = nameSpace; + this.type = type; + this.multiplicity = multiplicity; + } /** * creates a ShaderNodeVariable @@ -170,6 +188,7 @@ public class ShaderNodeVariable implements Savable, Cloneable { oc.write(nameSpace, "nameSpace", ""); oc.write(condition, "condition", null); oc.write(shaderOutput, "shaderOutput", false); + oc.write(multiplicity, "multiplicity", null); } @@ -184,8 +203,9 @@ public class ShaderNodeVariable implements Savable, Cloneable { name = ic.readString("name", ""); type = ic.readString("type", ""); nameSpace = ic.readString("nameSpace", ""); - condition = ic.readString("condition", null); + condition = ic.readString("condition", null); shaderOutput = ic.readBoolean("shaderOutput", false); + multiplicity = ic.readString("multiplicity", null); } /** @@ -231,4 +251,23 @@ public class ShaderNodeVariable implements Savable, Cloneable { public void setShaderOutput(boolean shaderOutput) { this.shaderOutput = shaderOutput; } + + /** + * + * @return the number of elements if this variable is an array + */ + public String getMultiplicity() { + return multiplicity; + } + + /** + * sets the number of elements of this variable making it an array + * this value can be a number of can be a define + * @param multiplicity + */ + public void setMultiplicity(String multiplicity) { + this.multiplicity = multiplicity; + } + + } diff --git a/engine/src/core/com/jme3/shader/ShaderUtils.java b/engine/src/core/com/jme3/shader/ShaderUtils.java index f7b879d66..5b264f10f 100644 --- a/engine/src/core/com/jme3/shader/ShaderUtils.java +++ b/engine/src/core/com/jme3/shader/ShaderUtils.java @@ -71,6 +71,33 @@ public class ShaderUtils { return false; } + + /** + * Check if a mapping is valid by checking the multiplicity of both of + * the variables if they are arrays + * + * @param mapping the mapping + * @return true if this mapping is valid + */ + public static boolean multiplicityMatch(VariableMapping mapping) { + String leftMult = mapping.getLeftVariable().getMultiplicity(); + String rightMult = mapping.getRightVariable().getMultiplicity(); + + if(leftMult == null){ + if(rightMult != null){ + return false; + } + }else{ + if(rightMult == null){ + return false; + }else{ + if(!leftMult.equalsIgnoreCase(rightMult)){ + return false; + } + } + } + return true; + } /** * return the cardinality of a type and a swizzle example : vec4 cardinality diff --git a/engine/src/core/com/jme3/shader/VarType.java b/engine/src/core/com/jme3/shader/VarType.java index 6a8049d17..b494daf57 100644 --- a/engine/src/core/com/jme3/shader/VarType.java +++ b/engine/src/core/com/jme3/shader/VarType.java @@ -38,19 +38,19 @@ public enum VarType { Vector3("vec3"), Vector4("vec4"), - IntArray(true,false,"int[]"), - FloatArray(true,false,"float[]"), - Vector2Array(true,false,"vec2[]"), - Vector3Array(true,false,"vec3[]"), - Vector4Array(true,false,"vec4[]"), + IntArray(true,false,"int"), + FloatArray(true,false,"float"), + Vector2Array(true,false,"vec2"), + Vector3Array(true,false,"vec3"), + Vector4Array(true,false,"vec4"), Boolean("bool"), Matrix3(true,false,"mat3"), Matrix4(true,false,"mat4"), - Matrix3Array(true,false,"mat3[]"), - Matrix4Array(true,false,"mat4[]"), + Matrix3Array(true,false,"mat3"), + Matrix4Array(true,false,"mat4"), TextureBuffer(false,true,"sampler1D|sampler1DShadow"), Texture2D(false,true,"sampler2D|sampler2DShadow"),