From 9578b0410eedb0c324d9a8570b5be1c5d38f6ea4 Mon Sep 17 00:00:00 2001 From: javasabr Date: Tue, 31 Oct 2017 10:57:39 +0300 Subject: [PATCH] extended some things from shader node system. --- .../java/com/jme3/material/TechniqueDef.java | 21 ++--- .../jme3/shader/Glsl100ShaderGenerator.java | 62 +++++++++++---- .../com/jme3/shader/ShaderNodeVariable.java | 31 ++++++-- .../plugins/ShaderNodeLoaderDelegate.java | 76 +++++++++++++------ .../materialdef/J3mdTechniqueDefWriter.java | 9 +-- 5 files changed, 136 insertions(+), 63 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 882d2b63a..1b0111522 100644 --- a/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java +++ b/jme3-core/src/main/java/com/jme3/material/TechniqueDef.java @@ -188,6 +188,7 @@ public class TechniqueDef implements Savable, Cloneable { defineTypes = new ArrayList(); paramToDefineId = new HashMap(); definesToShaderMap = new HashMap(); + worldBinds = new ArrayList<>(); } /** @@ -513,10 +514,8 @@ public class TechniqueDef implements Savable, Cloneable { } } - if (getWorldBindings() != null) { - for (UniformBinding binding : getWorldBindings()) { - shader.addUniformBinding(binding); - } + for (final UniformBinding binding : getWorldBindings()) { + shader.addUniformBinding(binding); } return shader; @@ -625,14 +624,10 @@ public class TechniqueDef implements Savable, Cloneable { * to the list of world parameters, false otherwise. */ public boolean addWorldParam(String name) { - if (worldBinds == null){ - worldBinds = new ArrayList(); - } - try { - worldBinds.add( UniformBinding.valueOf(name) ); + worldBinds.add(UniformBinding.valueOf(name)); return true; - } catch (IllegalArgumentException ex){ + } catch (IllegalArgumentException ex) { return false; } } @@ -821,10 +816,8 @@ public class TechniqueDef implements Savable, Cloneable { e.printStackTrace(); } - if (worldBinds != null) { - clone.worldBinds = new ArrayList<>(worldBinds.size()); - clone.worldBinds.addAll(worldBinds); - } + clone.worldBinds = new ArrayList<>(worldBinds.size()); + clone.worldBinds.addAll(worldBinds); return clone; } diff --git a/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java b/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java index 602f47f82..a4938c0bb 100644 --- a/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java +++ b/jme3-core/src/main/java/com/jme3/shader/Glsl100ShaderGenerator.java @@ -50,7 +50,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\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t"; - private ShaderNodeVariable inPosTmp; + protected ShaderNodeVariable inPosTmp; /** * creates a Glsl100ShaderGenerator @@ -110,7 +110,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator { protected void generateVaryings(StringBuilder source, ShaderGenerationInfo info, ShaderType type) { source.append("\n"); for (ShaderNodeVariable var : info.getVaryings()) { - declareVarying(source, var, type == ShaderType.Vertex ? false : true); + declareVarying(source, var, type != ShaderType.Vertex); } } @@ -141,7 +141,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator { @Override protected void generateStartOfMainSection(StringBuilder source, ShaderGenerationInfo info, ShaderType type) { source.append("\n"); - source.append("void main(){\n"); + source.append("void main() {\n"); indent(); appendIndent(source); if (type == ShaderType.Vertex) { @@ -237,27 +237,59 @@ public class Glsl100ShaderGenerator extends ShaderGenerator { comment(source, shaderNode, "Begin"); startCondition(shaderNode.getCondition(), source); - List declaredInputs = new ArrayList(); + final List declaredInputs = new ArrayList<>(); + for (VariableMapping mapping : shaderNode.getInputMapping()) { + final ShaderNodeVariable rightVariable = mapping.getRightVariable(); + final ShaderNodeVariable leftVariable = mapping.getLeftVariable(); + //Variables fed with a sampler matparam or world param are replaced by the matparam itself //It avoids issue with samplers that have to be uniforms. - if (isWorldOrMaterialParam(mapping.getRightVariable()) && mapping.getRightVariable().getType().startsWith("sampler")) { - nodeSource = replace(nodeSource, mapping.getLeftVariable(), mapping.getRightVariable().getPrefix() + mapping.getRightVariable().getName()); + if (isWorldOrMaterialParam(rightVariable) && rightVariable.getType().startsWith("sampler")) { + nodeSource = replace(nodeSource, leftVariable, rightVariable.getPrefix() + rightVariable.getName()); } else { - if (mapping.getLeftVariable().getType().startsWith("sampler")) { + + if (leftVariable.getType().startsWith("sampler")) { throw new IllegalArgumentException("a Sampler must be a uniform"); } + map(mapping, source); - String newName = shaderNode.getName() + "_" + mapping.getLeftVariable().getName(); - if (!declaredInputs.contains(newName)) { - nodeSource = replace(nodeSource, mapping.getLeftVariable(), newName); - declaredInputs.add(newName); - } } + + String newName = shaderNode.getName() + "_" + leftVariable.getName(); + if (!declaredInputs.contains(newName)) { + nodeSource = replace(nodeSource, leftVariable, newName); + declaredInputs.add(newName); + } + } + + final ShaderNodeDefinition definition = shaderNode.getDefinition(); + + for (final ShaderNodeVariable var : definition.getInputs()) { + + if (var.getDefaultValue() == null) { + continue; + } + + final String fullName = shaderNode.getName() + "_" + var.getName(); + + if (declaredInputs.contains(fullName)) { + continue; + } + + final ShaderNodeVariable variable = new ShaderNodeVariable(var.getType(), shaderNode.getName(), + var.getName(), var.getMultiplicity()); + + if (!isVarying(info, variable)) { + declareVariable(source, variable, var.getDefaultValue(), true, null); + } + + nodeSource = replaceVariableName(nodeSource, variable); + declaredInputs.add(fullName); } - - for (ShaderNodeVariable var : shaderNode.getDefinition().getOutputs()) { + + for (ShaderNodeVariable var : definition.getOutputs()) { ShaderNodeVariable v = new ShaderNodeVariable(var.getType(), shaderNode.getName(), var.getName(), var.getMultiplicity()); if (!declaredInputs.contains(shaderNode.getName() + "_" + var.getName())) { if (!isVarying(info, v)) { @@ -603,7 +635,7 @@ public class Glsl100ShaderGenerator extends ShaderGenerator { * makes sure inPosition attribute is of type vec3 or vec4 * @param var the inPosition attribute */ - private void fixInPositionType(ShaderNodeVariable var) { + protected void fixInPositionType(ShaderNodeVariable var) { if(!var.getType().equals("vec3") || !var.getType().equals("vec4")){ var.setType("vec3"); } diff --git a/jme3-core/src/main/java/com/jme3/shader/ShaderNodeVariable.java b/jme3-core/src/main/java/com/jme3/shader/ShaderNodeVariable.java index a1363ead1..6b4240d02 100644 --- a/jme3-core/src/main/java/com/jme3/shader/ShaderNodeVariable.java +++ b/jme3-core/src/main/java/com/jme3/shader/ShaderNodeVariable.java @@ -50,8 +50,10 @@ public class ShaderNodeVariable implements Savable, Cloneable { private String type; private String nameSpace; private String condition; - private boolean shaderOutput = false; private String multiplicity; + private String defaultValue; + + private boolean shaderOutput = false; /** * creates a ShaderNodeVariable @@ -180,6 +182,24 @@ public class ShaderNodeVariable implements Savable, Cloneable { this.nameSpace = nameSpace; } + /** + * Gets the default value of this variable. + * + * @return the default value of this variable. + */ + public String getDefaultValue() { + return defaultValue; + } + + /** + * Sets the default value of this variable. + * + * @param defaultValue the default value of this variable. + */ + public void setDefaultValue(final String defaultValue) { + this.defaultValue = defaultValue; + } + @Override public int hashCode() { int hash = 7; @@ -230,7 +250,7 @@ public class ShaderNodeVariable implements Savable, Cloneable { */ @Override public void write(JmeExporter ex) throws IOException { - OutputCapsule oc = (OutputCapsule) ex.getCapsule(this); + OutputCapsule oc = ex.getCapsule(this); oc.write(name, "name", ""); oc.write(type, "type", ""); oc.write(prefix, "prefix", ""); @@ -238,7 +258,7 @@ public class ShaderNodeVariable implements Savable, Cloneable { oc.write(condition, "condition", null); oc.write(shaderOutput, "shaderOutput", false); oc.write(multiplicity, "multiplicity", null); - + oc.write(defaultValue, "defaultValue", null); } /** @@ -249,14 +269,15 @@ public class ShaderNodeVariable implements Savable, Cloneable { */ @Override public void read(JmeImporter im) throws IOException { - InputCapsule ic = (InputCapsule) im.getCapsule(this); + InputCapsule ic = im.getCapsule(this); name = ic.readString("name", ""); type = ic.readString("type", ""); prefix = ic.readString("pefix", ""); nameSpace = ic.readString("nameSpace", ""); - condition = ic.readString("condition", null); + condition = ic.readString("condition", null); shaderOutput = ic.readBoolean("shaderOutput", false); multiplicity = ic.readString("multiplicity", null); + defaultValue = ic.readString("defaultValue", null); } /** diff --git a/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java b/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java index 13f035426..cb75687b0 100644 --- a/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java +++ b/jme3-core/src/plugins/java/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java @@ -217,11 +217,15 @@ public class ShaderNodeLoaderDelegate { * @throws IOException */ protected ShaderNodeVariable readVariable(Statement statement) throws IOException { + String line = statement.getLine().trim().replaceAll("\\s*\\[", "["); String[] splitVar = line.split("\\s"); - if (splitVar.length != 2) { - throw new MatParseException("2 arguments", splitVar.length + "", statement); + + if (splitVar.length > 3) { + throw new MatParseException("More than 3 arguments", splitVar.length + "", statement); } + + String defaultValue = splitVar.length > 2? splitVar[2] : null; String varName = splitVar[1]; String varType = splitVar[0]; String multiplicity = null; @@ -230,13 +234,19 @@ public class ShaderNodeLoaderDelegate { //we have an array String[] arr = splitVar[1].split("\\["); varName = arr[0].trim(); - multiplicity = arr[1].replaceAll("\\]", "").trim(); + multiplicity = arr[1].replaceAll("\\]", "").trim(); } + if (varNames.contains(varName + ";")) { throw new MatParseException("Duplicate variable name " + varName, statement); } + varNames += varName + ";"; - return new ShaderNodeVariable(varType, "", varName, multiplicity); + + final ShaderNodeVariable variable = new ShaderNodeVariable(varType, "", varName, multiplicity); + variable.setDefaultValue(defaultValue); + + return variable; } /** @@ -262,7 +272,7 @@ public class ShaderNodeLoaderDelegate { String[] split = statement.getLine().split("[ \\{]"); if (line.startsWith("Definition")) { ShaderNodeDefinition def = findDefinition(statement); - shaderNode.setDefinition(def); + shaderNode.setDefinition(def); if(def.isNoOutput()){ techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(shaderNode.getName()); } @@ -276,12 +286,12 @@ public class ShaderNodeLoaderDelegate { techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(mapping.getRightVariable().getNameSpace()); shaderNode.getInputMapping().add(mapping); } - } else if (line.startsWith("OutputMapping")) { + } else if (line.startsWith("OutputMapping")) { for (Statement statement1 : statement.getContents()) { VariableMapping mapping = readOutputMapping(statement1); techniqueDef.getShaderGenerationInfo().getUnusedNodes().remove(shaderNode.getName()); shaderNode.getOutputMapping().add(mapping); - } + } } else { throw new MatParseException("ShaderNodeDefinition", split[0], statement); } @@ -298,7 +308,7 @@ public class ShaderNodeLoaderDelegate { * Format : .[.] = * .[.][:Condition] * - * + * * @param statement the statement to read * @return the read mapping */ @@ -660,19 +670,13 @@ 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, statement1)) { + if (updateRightFromUniforms(param, mapping, vertexDeclaredUniforms, statement1)) { + updateMaterialTextureType(statement1, mapping, left, param); storeVertexUniform(mapping.getRightVariable()); } } else { if (updateRightFromUniforms(param, mapping, fragmentDeclaredUniforms, statement1)) { - if (mapping.getRightVariable().getType().contains("|")) { - String type = fixSamplerType(left.getType(), mapping.getRightVariable().getType()); - if (type != null) { - mapping.getRightVariable().setType(type); - } else { - throw new MatParseException(param.getVarType().toString() + " can only be matched to one of " + param.getVarType().getGlslType().replaceAll("\\|", ",") + " found " + left.getType(), statement1); - } - } + updateMaterialTextureType(statement1, mapping, left, param); storeFragmentUniform(mapping.getRightVariable()); } } @@ -683,11 +687,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)) { + if (updateRightFromUniforms(worldParam, mapping, vertexDeclaredUniforms)) { storeVertexUniform(mapping.getRightVariable()); } } else { - if (updateRightFromUniforms(worldParam, mapping, fragmentDeclaredUniforms)) { + if (updateRightFromUniforms(worldParam, mapping, fragmentDeclaredUniforms)) { storeFragmentUniform(mapping.getRightVariable()); } } @@ -704,7 +708,7 @@ public class ShaderNodeLoaderDelegate { right.setNameSpace(node.getName()); right.setType(var.getType()); right.setMultiplicity(var.getMultiplicity()); - mapping.setRightVariable(right); + mapping.setRightVariable(right); storeVaryings(node, mapping.getRightVariable()); } @@ -714,6 +718,32 @@ public class ShaderNodeLoaderDelegate { return mapping; } + /** + * Updated the material texture type of the variable mapping. + * + * @param statement the statement. + * @param mapping the variable mapping. + * @param left the left variable. + * @param param the material parameter. + * @throws MatParseException + */ + private void updateMaterialTextureType(final Statement statement, final VariableMapping mapping, + final ShaderNodeVariable left, final MatParam param) throws MatParseException { + + if (!mapping.getRightVariable().getType().contains("|")) { + return; + } + + final String type = fixSamplerType(left.getType(), mapping.getRightVariable().getType()); + + if (type != null) { + mapping.getRightVariable().setType(type); + } else { + throw new MatParseException(param.getVarType().toString() + " can only be matched to one of " + + param.getVarType().getGlslType().replaceAll("\\|", ",") + " found " + left.getType(), statement); + } + } + /** * reads an output mapping * @@ -924,12 +954,12 @@ public class ShaderNodeLoaderDelegate { dv.addNode(shaderNode); //if a variable is declared with the same name as an input and an output and is a varying, set it as a shader output so it's declared as a varying only once. for (VariableMapping variableMapping : node.getInputMapping()) { - if (variableMapping.getLeftVariable().getName().equals(variable.getName())) { - variableMapping.getLeftVariable().setShaderOutput(true); + final ShaderNodeVariable leftVariable = variableMapping.getLeftVariable(); + if (leftVariable.getName().equals(variable.getName())) { + leftVariable.setShaderOutput(true); } } } - } /** diff --git a/jme3-plugins/src/main/java/com/jme3/material/plugin/export/materialdef/J3mdTechniqueDefWriter.java b/jme3-plugins/src/main/java/com/jme3/material/plugin/export/materialdef/J3mdTechniqueDefWriter.java index 23e30953a..e2e3098cc 100644 --- a/jme3-plugins/src/main/java/com/jme3/material/plugin/export/materialdef/J3mdTechniqueDefWriter.java +++ b/jme3-plugins/src/main/java/com/jme3/material/plugin/export/materialdef/J3mdTechniqueDefWriter.java @@ -168,13 +168,13 @@ public class J3mdTechniqueDefWriter { out.write(shaderNode.getDefinition().getPath()); out.write("\n"); - out.write(" InputMappings{\n"); + out.write(" InputMappings {\n"); for (VariableMapping mapping : shaderNode.getInputMapping()) { writeVariableMapping(out, shaderNode, mapping, matParams); } out.write(" }\n"); - out.write(" OutputMappings{\n"); + out.write(" OutputMappings {\n"); for (VariableMapping mapping : shaderNode.getOutputMapping()) { writeVariableMapping(out, shaderNode, mapping, matParams); } @@ -288,7 +288,4 @@ public class J3mdTechniqueDefWriter { } return null; } - -} - - +} \ No newline at end of file