ShaderNodesLoader : Better way to compute define conditions

git-svn-id: https://jmonkeyengine.googlecode.com/svn/trunk@10479 75d07b2b-3a1a-0410-a2c5-0572b91ccdca
3.0
rem..om 12 years ago
parent 75569f4c04
commit 6ab93d4007
  1. 4
      engine/src/core-plugins/com/jme3/material/plugins/J3MLoader.java
  2. 211
      engine/src/core-plugins/com/jme3/material/plugins/ShaderNodeLoaderDelegate.java

@ -446,6 +446,10 @@ public class J3MLoader implements AssetLoader {
readTechniqueStatement(statement); readTechniqueStatement(statement);
} }
if(isUseNodes){
nodesLoaderDelegate.computeConditions();
}
if (vertName != null && fragName != null){ if (vertName != null && fragName != null){
technique.setShaderFile(vertName, fragName, vertLanguage, fragLanguage); technique.setShaderFile(vertName, fragName, vertLanguage, fragLanguage);
} }

@ -51,6 +51,7 @@ import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import jogamp.common.os.elf.Shdr;
/** /**
* This class is here to be able to load shaderNodeDefinition from both the * This class is here to be able to load shaderNodeDefinition from both the
@ -69,17 +70,105 @@ public class ShaderNodeLoaderDelegate {
protected ShaderNodeDefinition shaderNodeDefinition; protected ShaderNodeDefinition shaderNodeDefinition;
protected ShaderNode shaderNode; protected ShaderNode shaderNode;
protected TechniqueDef techniqueDef; protected TechniqueDef techniqueDef;
protected Map<String, ShaderNodeVariable> attributes = new HashMap<String, ShaderNodeVariable>(); protected Map<String, DeclaredVariable> attributes = new HashMap<String, DeclaredVariable>();
protected Map<String, ShaderNodeVariable> vertexDeclaredUniforms = new HashMap<String, ShaderNodeVariable>(); protected Map<String, DeclaredVariable> vertexDeclaredUniforms = new HashMap<String, DeclaredVariable>();
protected Map<String, ShaderNodeVariable> fragmentDeclaredUniforms = new HashMap<String, ShaderNodeVariable>(); protected Map<String, DeclaredVariable> fragmentDeclaredUniforms = new HashMap<String, DeclaredVariable>();
protected Map<String, ShaderNodeVariable> varyings = new HashMap<String, ShaderNodeVariable>(); protected Map<String, DeclaredVariable> varyings = new HashMap<String, DeclaredVariable>();
protected MaterialDef materialDef; protected MaterialDef materialDef;
protected String shaderLanguage; protected String shaderLanguage;
protected String shaderName; protected String shaderName;
protected String varNames = ""; protected String varNames = "";
protected AssetManager assetManager; protected AssetManager assetManager;
protected ConditionParser conditionParser = new ConditionParser(); protected ConditionParser conditionParser = new ConditionParser();
protected List<String> nulledConditions = new ArrayList<String>();
protected class DeclaredVariable {
ShaderNodeVariable var;
List<ShaderNode> nodes = new ArrayList<ShaderNode>();
public DeclaredVariable(ShaderNodeVariable var) {
this.var = var;
}
public void makeCondition() {
var.setCondition(null);
for (ShaderNode node : nodes) {
String condition = null;
for (VariableMapping mapping : node.getInputMapping()) {
if (mapping.getRightVariable().equals(var)) {
if (mapping.getCondition() == null) {
condition = null;
break;
}
if (condition == null) {
condition = "(" + mapping.getCondition() + ")";
} else {
if (!condition.contains(mapping.getCondition())) {
condition = condition + " || (" + mapping.getCondition() + ")";
}
}
}
}
if (node.getCondition() == null && condition == null) {
var.setCondition(null);
return;
}
if (node.getCondition() != null) {
if (condition == null) {
condition = node.getCondition();
} else {
if (!condition.contains(node.getCondition())) {
condition = "(" + node.getCondition() + ") && (" + condition + ")";
}
}
}
if (var.getCondition() == null) {
var.setCondition(condition);
} else {
if (!var.getCondition().contains(condition)) {
var.setCondition("(" + var.getCondition() + ") || (" + condition + ")");
}
}
}
}
public final void addNode(ShaderNode c) {
if (!nodes.contains(c)) {
nodes.add(c);
}
}
}
protected void computeConditions() {
updateConditions(vertexDeclaredUniforms);
updateConditions(fragmentDeclaredUniforms);
updateConditions(varyings);
for (DeclaredVariable v : varyings.values()) {
for (ShaderNode sn : techniqueDef.getShaderNodes()) {
if (sn.getDefinition().getType() == Shader.ShaderType.Vertex) {
for (VariableMapping mapping : sn.getInputMapping()) {
if (mapping.getLeftVariable().equals(v.var)) {
if (mapping.getCondition() == null || v.var.getCondition() == null) {
mapping.setCondition(v.var.getCondition());
} else {
mapping.setCondition("(" + mapping.getCondition() + ") || (" + v.var.getCondition() + ")");
}
}
}
}
}
}
updateConditions(attributes);
// updateConditions(fragmentGlobals);
// vertexGlobal.makeCondition();
}
/** /**
* Read the ShaderNodesDefinitions block and returns a list of * Read the ShaderNodesDefinitions block and returns a list of
@ -429,18 +518,21 @@ public class ShaderNodeLoaderDelegate {
* @param map the map of uniforms to search into * @param map the map of uniforms to search into
* @return true if the param was added to the map * @return true if the param was added to the map
*/ */
protected boolean updateRightFromUniforms(UniformBinding param, VariableMapping mapping, Map<String, ShaderNodeVariable> map) { protected boolean updateRightFromUniforms(UniformBinding param, VariableMapping mapping, Map<String, DeclaredVariable> map) {
ShaderNodeVariable right = mapping.getRightVariable(); ShaderNodeVariable right = mapping.getRightVariable();
String name = "g_" + param.toString(); String name = "g_" + param.toString();
ShaderNodeVariable var = map.get(name); DeclaredVariable dv = map.get(name);
if (var == null) { if (dv == null) {
right.setType(param.getGlslType()); right.setType(param.getGlslType());
right.setName(name); right.setName(name);
map.put(right.getName(), right); dv = new DeclaredVariable(right);
map.put(right.getName(), dv);
dv.addNode(shaderNode);
mapping.setRightVariable(right); mapping.setRightVariable(right);
return true; return true;
} }
mapping.setRightVariable(var); dv.addNode(shaderNode);
mapping.setRightVariable(dv.var);
return false; return false;
} }
@ -454,17 +546,20 @@ public class ShaderNodeLoaderDelegate {
* @param map the map of uniforms to search into * @param map the map of uniforms to search into
* @return true if the param was added to the map * @return true if the param was added to the map
*/ */
public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map<String, ShaderNodeVariable> map) { public boolean updateRightFromUniforms(MatParam param, VariableMapping mapping, Map<String, DeclaredVariable> map) {
ShaderNodeVariable right = mapping.getRightVariable(); ShaderNodeVariable right = mapping.getRightVariable();
ShaderNodeVariable var = map.get(param.getPrefixedName()); DeclaredVariable dv = map.get(param.getPrefixedName());
if (var == null) { if (dv == null) {
right.setType(param.getVarType().getGlslType()); right.setType(param.getVarType().getGlslType());
right.setName(param.getPrefixedName()); right.setName(param.getPrefixedName());
map.put(right.getName(), right); dv = new DeclaredVariable(right);
map.put(right.getName(), dv);
dv.addNode(shaderNode);
mapping.setRightVariable(right); mapping.setRightVariable(right);
return true; return true;
} }
mapping.setRightVariable(var); dv.addNode(shaderNode);
mapping.setRightVariable(dv.var);
return false; return false;
} }
@ -475,13 +570,15 @@ public class ShaderNodeLoaderDelegate {
* @param mapping the mapping * @param mapping the mapping
*/ */
public void updateVarFromAttributes(ShaderNodeVariable right, VariableMapping mapping) { public void updateVarFromAttributes(ShaderNodeVariable right, VariableMapping mapping) {
ShaderNodeVariable var = attributes.get(right.getName()); DeclaredVariable dv = attributes.get(right.getName());
if (var == null) { if (dv == null) {
dv = new DeclaredVariable(right);
attributes.put(right.getName(), dv);
updateRightTypeFromLeftType(mapping); updateRightTypeFromLeftType(mapping);
} else { } else {
mapping.setRightVariable(dv.var);
mapping.setRightVariable(var);
} }
dv.addNode(shaderNode);
} }
/** /**
@ -557,7 +654,7 @@ public class ShaderNodeLoaderDelegate {
if (right.getNameSpace().equals("Global")) { if (right.getNameSpace().equals("Global")) {
right.setType("vec4");//Globals are all vec4 for now (maybe forever...) right.setType("vec4");//Globals are all vec4 for now (maybe forever...)
updateCondition(right, mapping); // updateCondition(right, mapping);
storeGlobal(right, statement1); storeGlobal(right, statement1);
} else if (right.getNameSpace().equals("Attr")) { } else if (right.getNameSpace().equals("Attr")) {
@ -565,7 +662,7 @@ public class ShaderNodeLoaderDelegate {
throw new MatParseException("Cannot have an attribute as input in a fragment shader" + right.getName(), statement1); throw new MatParseException("Cannot have an attribute as input in a fragment shader" + right.getName(), statement1);
} }
updateVarFromAttributes(mapping.getRightVariable(), mapping); updateVarFromAttributes(mapping.getRightVariable(), mapping);
updateCondition(mapping.getRightVariable(), mapping); // updateCondition(mapping.getRightVariable(), mapping);
storeAttribute(mapping.getRightVariable()); storeAttribute(mapping.getRightVariable());
} else if (right.getNameSpace().equals("MatParam")) { } else if (right.getNameSpace().equals("MatParam")) {
MatParam param = findMatParam(right.getName()); MatParam param = findMatParam(right.getName());
@ -574,7 +671,7 @@ public class ShaderNodeLoaderDelegate {
} }
if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) { if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) {
if (updateRightFromUniforms(param, mapping, vertexDeclaredUniforms)) { if (updateRightFromUniforms(param, mapping, vertexDeclaredUniforms)) {
updateCondition(mapping.getRightVariable(), mapping); // updateCondition(mapping.getRightVariable(), mapping);
storeVertexUniform(mapping.getRightVariable()); storeVertexUniform(mapping.getRightVariable());
} }
} else { } else {
@ -587,7 +684,7 @@ public class ShaderNodeLoaderDelegate {
throw new MatParseException(param.getVarType().toString() + " can only be matched to one of " + param.getVarType().getGlslType().replaceAll("\\|", ",") + " found " + left.getType(), statement1); 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); // updateCondition(mapping.getRightVariable(), mapping);
storeFragmentUniform(mapping.getRightVariable()); storeFragmentUniform(mapping.getRightVariable());
} }
} }
@ -599,12 +696,12 @@ public class ShaderNodeLoaderDelegate {
} }
if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) { if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) {
if (updateRightFromUniforms(worldParam, mapping, vertexDeclaredUniforms)) { if (updateRightFromUniforms(worldParam, mapping, vertexDeclaredUniforms)) {
updateCondition(mapping.getRightVariable(), mapping); // updateCondition(mapping.getRightVariable(), mapping);
storeVertexUniform(mapping.getRightVariable()); storeVertexUniform(mapping.getRightVariable());
} }
} else { } else {
if (updateRightFromUniforms(worldParam, mapping, fragmentDeclaredUniforms)) { if (updateRightFromUniforms(worldParam, mapping, fragmentDeclaredUniforms)) {
updateCondition(mapping.getRightVariable(), mapping); // updateCondition(mapping.getRightVariable(), mapping);
storeFragmentUniform(mapping.getRightVariable()); storeFragmentUniform(mapping.getRightVariable());
} }
} }
@ -621,7 +718,7 @@ public class ShaderNodeLoaderDelegate {
right.setNameSpace(node.getName()); right.setNameSpace(node.getName());
right.setType(var.getType()); right.setType(var.getType());
mapping.setRightVariable(right); mapping.setRightVariable(right);
updateCondition(mapping.getRightVariable(), mapping); // updateCondition(mapping.getRightVariable(), mapping);
storeVaryings(node, mapping.getRightVariable()); storeVaryings(node, mapping.getRightVariable());
} }
@ -655,7 +752,7 @@ public class ShaderNodeLoaderDelegate {
if (left.getNameSpace().equals("Global")) { if (left.getNameSpace().equals("Global")) {
left.setType("vec4");//Globals are all vec4 for now (maybe forever...) left.setType("vec4");//Globals are all vec4 for now (maybe forever...)
updateCondition(left, mapping); // updateCondition(left, mapping);
storeGlobal(left, statement1); storeGlobal(left, statement1);
} else { } else {
throw new MatParseException("Only Global nameSpace is allowed for outputMapping, got" + left.getNameSpace(), statement1); throw new MatParseException("Only Global nameSpace is allowed for outputMapping, got" + left.getNameSpace(), statement1);
@ -737,8 +834,8 @@ public class ShaderNodeLoaderDelegate {
if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) { if (shaderNode.getDefinition().getType() == Shader.ShaderType.Vertex) {
ShaderNodeVariable global = techniqueDef.getShaderGenerationInfo().getVertexGlobal(); ShaderNodeVariable global = techniqueDef.getShaderGenerationInfo().getVertexGlobal();
if (global != null) { if (global != null) {
global.setCondition(mergeConditions(global.getCondition(), var.getCondition(), "||")); // global.setCondition(mergeConditions(global.getCondition(), var.getCondition(), "||"));
var.setCondition(global.getCondition()); // var.setCondition(global.getCondition());
if (!global.getName().equals(var.getName())) { if (!global.getName().equals(var.getName())) {
throw new MatParseException("A global output is already defined for the vertex shader: " + global.getName() + ". vertex shader can only have one global output", statement1); throw new MatParseException("A global output is already defined for the vertex shader: " + global.getName() + ". vertex shader can only have one global output", statement1);
} }
@ -746,7 +843,7 @@ public class ShaderNodeLoaderDelegate {
techniqueDef.getShaderGenerationInfo().setVertexGlobal(var); techniqueDef.getShaderGenerationInfo().setVertexGlobal(var);
} }
} else if (shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment) { } else if (shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment) {
mergeConditionsAndStoreVariable(var, techniqueDef.getShaderGenerationInfo().getFragmentGlobals()); storeVariable(var, techniqueDef.getShaderGenerationInfo().getFragmentGlobals());
} }
} }
@ -756,7 +853,7 @@ public class ShaderNodeLoaderDelegate {
* @param var the variable ot store * @param var the variable ot store
*/ */
public void storeAttribute(ShaderNodeVariable var) { public void storeAttribute(ShaderNodeVariable var) {
mergeConditionsAndStoreVariable(var, techniqueDef.getShaderGenerationInfo().getAttributes()); storeVariable(var, techniqueDef.getShaderGenerationInfo().getAttributes());
} }
/** /**
@ -765,7 +862,7 @@ public class ShaderNodeLoaderDelegate {
* @param var the variable ot store * @param var the variable ot store
*/ */
public void storeVertexUniform(ShaderNodeVariable var) { public void storeVertexUniform(ShaderNodeVariable var) {
mergeConditionsAndStoreVariable(var, techniqueDef.getShaderGenerationInfo().getVertexUniforms()); storeVariable(var, techniqueDef.getShaderGenerationInfo().getVertexUniforms());
} }
@ -775,7 +872,7 @@ public class ShaderNodeLoaderDelegate {
* @param var the variable ot store * @param var the variable ot store
*/ */
public void storeFragmentUniform(ShaderNodeVariable var) { public void storeFragmentUniform(ShaderNodeVariable var) {
mergeConditionsAndStoreVariable(var, techniqueDef.getShaderGenerationInfo().getFragmentUniforms()); storeVariable(var, techniqueDef.getShaderGenerationInfo().getFragmentUniforms());
} }
@ -832,17 +929,21 @@ public class ShaderNodeLoaderDelegate {
* @param var the variable * @param var the variable
* @param mapping the mapping * @param mapping the mapping
*/ */
public void updateCondition(ShaderNodeVariable var, VariableMapping mapping) { // public void updateCondition(ShaderNodeVariable var, VariableMapping mapping) {
//
String condition = mergeConditions(shaderNode.getCondition(), mapping.getCondition(), "&&"); // String condition = mergeConditions(shaderNode.getCondition(), mapping.getCondition(), "&&");
//
if (var.getCondition() == null) { // if (var.getCondition() == null) {
var.setCondition(condition); // if (!nulledConditions.contains(var.getNameSpace() + "." + var.getName())) {
} else { // var.setCondition(condition);
var.setCondition(mergeConditions(var.getCondition(), condition, "||")); // }
} // } else {
} // var.setCondition(mergeConditions(var.getCondition(), condition, "||"));
// if (var.getCondition() == null) {
// nulledConditions.add(var.getNameSpace() + "." + var.getName());
// }
// }
// }
/** /**
* store a varying * store a varying
* *
@ -852,14 +953,14 @@ public class ShaderNodeLoaderDelegate {
public void storeVaryings(ShaderNode node, ShaderNodeVariable variable) { public void storeVaryings(ShaderNode node, ShaderNodeVariable variable) {
variable.setShaderOutput(true); variable.setShaderOutput(true);
if (node.getDefinition().getType() == Shader.ShaderType.Vertex && shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment) { if (node.getDefinition().getType() == Shader.ShaderType.Vertex && shaderNode.getDefinition().getType() == Shader.ShaderType.Fragment) {
ShaderNodeVariable var = varyings.get(variable.getName()); DeclaredVariable dv = varyings.get(variable.getName());
if (var == null) { if (dv == null) {
techniqueDef.getShaderGenerationInfo().getVaryings().add(variable); techniqueDef.getShaderGenerationInfo().getVaryings().add(variable);
varyings.put(variable.getName(), variable); dv = new DeclaredVariable(variable);
} else {
var.setCondition(mergeConditions(var.getCondition(), variable.getCondition(), "||")); varyings.put(variable.getName(), dv);
variable.setCondition(var.getCondition());
} }
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. //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()) { for (VariableMapping variableMapping : node.getInputMapping()) {
if (variableMapping.getLeftVariable().getName().equals(variable.getName())) { if (variableMapping.getLeftVariable().getName().equals(variable.getName())) {
@ -901,11 +1002,11 @@ public class ShaderNodeLoaderDelegate {
* @param variable the variable * @param variable the variable
* @param varList the variable list * @param varList the variable list
*/ */
public void mergeConditionsAndStoreVariable(ShaderNodeVariable variable, List<ShaderNodeVariable> varList) { public void storeVariable(ShaderNodeVariable variable, List<ShaderNodeVariable> varList) {
for (ShaderNodeVariable var : varList) { for (ShaderNodeVariable var : varList) {
if (var.getName().equals(variable.getName())) { if (var.getName().equals(variable.getName())) {
var.setCondition(mergeConditions(var.getCondition(), variable.getCondition(), "||")); // var.setCondition(mergeConditions(var.getCondition(), variable.getCondition(), "||"));
variable.setCondition(var.getCondition()); // variable.setCondition(var.getCondition());
return; return;
} }
} }
@ -934,4 +1035,10 @@ public class ShaderNodeLoaderDelegate {
} }
return nodeDefinitions; return nodeDefinitions;
} }
private void updateConditions(Map<String, DeclaredVariable> map) {
for (DeclaredVariable declaredVariable : map.values()) {
declaredVariable.makeCondition();
}
}
} }

Loading…
Cancel
Save