Просмотр исходного кода

ShaderNodes : Array types are now properly supported and array size can be driven by an int constant or an int define

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10571 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
rem..om 12 лет назад
Родитель
Сommit
f8faebb79e

+ 51 - 21
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<String, DeclaredVariable> map) {
+    public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map<String, DeclaredVariable> 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<String, ShaderNodeDefinition> getNodeDefinitions() {

+ 6 - 1
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);

+ 40 - 1
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;
+    }
+    
+    
 }

+ 27 - 0
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

+ 7 - 7
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"),